Merge branch '4.0.x' into 9103_imgconverter_unexpected_conversion

This commit is contained in:
Takeshi KOMIYA 2021-04-18 15:08:51 +09:00 committed by GitHub
commit e0ce61d533
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 104 additions and 47 deletions

View File

@ -16,7 +16,9 @@ Deprecated
Features added
--------------
* #8818: autodoc: Super class having ``Any`` arguments causes nit-picky warning
* #9103: LaTeX: imgconverter: conversion runs even if not needed
* #8127: py domain: Ellipsis in info-field-list causes nit-picky warning
* #9023: More CSS classes on domain descriptions, see :ref:`nodes` for details.
Bugs fixed

View File

@ -304,7 +304,7 @@ class PyXrefMixin:
def make_xrefs(self, rolename: str, domain: str, target: str,
innernode: Type[TextlikeNode] = nodes.emphasis,
contnode: Node = None, env: BuildEnvironment = None) -> List[Node]:
delims = r'(\s*[\[\]\(\),](?:\s*or\s)?\s*|\s+or\s+)'
delims = r'(\s*[\[\]\(\),](?:\s*or\s)?\s*|\s+or\s+|\.\.\.)'
delims_re = re.compile(delims)
sub_targets = re.split(delims, target)

View File

@ -138,16 +138,16 @@ def _restify_py37(cls: Optional[Type]) -> str:
if len(cls.__args__) > 1 and cls.__args__[-1] is NoneType:
if len(cls.__args__) > 2:
args = ', '.join(restify(a) for a in cls.__args__[:-1])
return ':obj:`Optional`\\ [:obj:`Union`\\ [%s]]' % args
return ':obj:`~typing.Optional`\\ [:obj:`~typing.Union`\\ [%s]]' % args
else:
return ':obj:`Optional`\\ [%s]' % restify(cls.__args__[0])
return ':obj:`~typing.Optional`\\ [%s]' % restify(cls.__args__[0])
else:
args = ', '.join(restify(a) for a in cls.__args__)
return ':obj:`Union`\\ [%s]' % args
return ':obj:`~typing.Union`\\ [%s]' % args
elif inspect.isgenericalias(cls):
if getattr(cls, '_name', None):
if cls.__module__ == 'typing':
text = ':class:`%s`' % cls._name
text = ':class:`~%s.%s`' % (cls.__module__, cls._name)
else:
text = ':class:`%s.%s`' % (cls.__module__, cls._name)
else:
@ -167,19 +167,22 @@ def _restify_py37(cls: Optional[Type]) -> str:
return text
elif hasattr(cls, '__qualname__'):
if cls.__module__ == 'typing':
return ':class:`%s`' % cls.__qualname__
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`' % cls._name
return ':obj:`~%s.%s`' % (cls.__module__, cls._name)
else:
return ':obj:`%s.%s`' % (cls.__module__, cls._name)
elif isinstance(cls, ForwardRef):
return ':class:`%s`' % cls.__forward_arg__
else:
# not a class (ex. TypeVar)
if cls.__module__ == 'typing':
return ':obj:`~%s.%s`' % (cls.__module__, cls.__name__)
else:
return ':obj:`%s.%s`' % (cls.__module__, cls.__name__)
@ -203,13 +206,23 @@ def _restify_py36(cls: Optional[Type]) -> str:
if (isinstance(cls, typing.TupleMeta) and # type: ignore
not hasattr(cls, '__tuple_params__')):
if module == 'typing':
reftext = ':class:`~typing.%s`' % qualname
else:
reftext = ':class:`%s`' % qualname
params = cls.__args__
if params:
param_str = ', '.join(restify(p) for p in params)
return ':class:`%s`\\ [%s]' % (qualname, param_str)
return reftext + '\\ [%s]' % param_str
else:
return ':class:`%s`' % qualname
return reftext
elif isinstance(cls, typing.GenericMeta):
if module == 'typing':
reftext = ':class:`~typing.%s`' % qualname
else:
reftext = ':class:`%s`' % qualname
if cls.__args__ is None or len(cls.__args__) <= 2: # type: ignore # NOQA
params = cls.__args__ # type: ignore
elif cls.__origin__ == Generator: # type: ignore
@ -217,13 +230,13 @@ def _restify_py36(cls: Optional[Type]) -> str:
else: # typing.Callable
args = ', '.join(restify(arg) for arg in cls.__args__[:-1]) # type: ignore
result = restify(cls.__args__[-1]) # type: ignore
return ':class:`%s`\\ [[%s], %s]' % (qualname, args, result)
return reftext + '\\ [[%s], %s]' % (args, result)
if params:
param_str = ', '.join(restify(p) for p in params)
return ':class:`%s`\\ [%s]' % (qualname, param_str)
return reftext + '\\ [%s]' % (param_str)
else:
return ':class:`%s`' % qualname
return reftext
elif (hasattr(cls, '__origin__') and
cls.__origin__ is typing.Union):
params = cls.__args__
@ -231,32 +244,36 @@ def _restify_py36(cls: Optional[Type]) -> str:
if len(params) > 1 and params[-1] is NoneType:
if len(params) > 2:
param_str = ", ".join(restify(p) for p in params[:-1])
return ':obj:`Optional`\\ [:obj:`Union`\\ [%s]]' % param_str
return (':obj:`~typing.Optional`\\ '
'[:obj:`~typing.Union`\\ [%s]]' % param_str)
else:
return ':obj:`Optional`\\ [%s]' % restify(params[0])
return ':obj:`~typing.Optional`\\ [%s]' % restify(params[0])
else:
param_str = ', '.join(restify(p) for p in params)
return ':obj:`Union`\\ [%s]' % param_str
return ':obj:`~typing.Union`\\ [%s]' % param_str
else:
return ':obj:`Union`'
elif hasattr(cls, '__qualname__'):
if cls.__module__ == 'typing':
return ':class:`%s`' % cls.__qualname__
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`' % cls._name
return ':obj:`~%s.%s`' % (cls.__module__, cls._name)
else:
return ':obj:`%s.%s`' % (cls.__module__, cls._name)
elif hasattr(cls, '__name__'):
# not a class (ex. TypeVar)
if cls.__module__ == 'typing':
return ':obj:`~%s.%s`' % (cls.__module__, cls.__name__)
else:
return ':obj:`%s.%s`' % (cls.__module__, cls.__name__)
else:
# others (ex. Any)
if cls.__module__ == 'typing':
return ':obj:`%s`' % qualname
return ':obj:`~%s.%s`' % (cls.__module__, qualname)
else:
return ':obj:`%s.%s`' % (cls.__module__, qualname)

View File

@ -876,7 +876,9 @@ def test_info_field_list(app):
"\n"
" :param str name: blah blah\n"
" :param age: blah blah\n"
" :type age: int\n")
" :type age: int\n"
" :param items: blah blah\n"
" :type items: Tuple[str, ...]\n")
doctree = restructuredtext.parse(app, text)
print(doctree)
@ -890,6 +892,7 @@ def test_info_field_list(app):
assert_node(doctree[3][1][0][0],
([nodes.field_name, "Parameters"],
[nodes.field_body, nodes.bullet_list, ([nodes.list_item, nodes.paragraph],
[nodes.list_item, nodes.paragraph],
[nodes.list_item, nodes.paragraph])]))
# :param str name:
@ -916,6 +919,26 @@ def test_info_field_list(app):
refdomain="py", reftype="class", reftarget="int",
**{"py:module": "example", "py:class": "Class"})
# :param items: + :type items:
assert_node(doctree[3][1][0][0][1][0][2][0],
([addnodes.literal_strong, "items"],
" (",
[pending_xref, addnodes.literal_emphasis, "Tuple"],
[addnodes.literal_emphasis, "["],
[pending_xref, addnodes.literal_emphasis, "str"],
[addnodes.literal_emphasis, ", "],
[addnodes.literal_emphasis, "..."],
[addnodes.literal_emphasis, "]"],
")",
" -- ",
"blah blah"))
assert_node(doctree[3][1][0][0][1][0][2][0][2], pending_xref,
refdomain="py", reftype="class", reftarget="Tuple",
**{"py:module": "example", "py:class": "Class"})
assert_node(doctree[3][1][0][0][1][0][2][0][4], pending_xref,
refdomain="py", reftype="class", reftarget="str",
**{"py:module": "example", "py:class": "Class"})
def test_info_field_list_var(app):
text = (".. py:class:: Class\n"

View File

@ -1893,12 +1893,12 @@ def test_autodoc_GenericAlias(app):
' .. py:attribute:: Class.T',
' :module: target.genericalias',
'',
' alias of :class:`List`\\ [:class:`int`]',
' alias of :class:`~typing.List`\\ [:class:`int`]',
'',
'.. py:attribute:: T',
' :module: target.genericalias',
'',
' alias of :class:`List`\\ [:class:`int`]',
' alias of :class:`~typing.List`\\ [:class:`int`]',
]
else:
assert list(actual) == [

View File

@ -256,7 +256,8 @@ def test_show_inheritance_for_subclass_of_generic_type(app):
'.. py:class:: Quux(iterable=(), /)',
' :module: target.classes',
'',
' Bases: :class:`List`\\ [:obj:`Union`\\ [:class:`int`, :class:`float`]]',
' Bases: :class:`~typing.List`\\ '
'[:obj:`~typing.Union`\\ [:class:`int`, :class:`float`]]',
'',
' A subclass of List[Union[int, float]]',
'',

View File

@ -47,42 +47,56 @@ def test_restify():
assert restify(Integral) == ":class:`numbers.Integral`"
assert restify(Struct) == ":class:`struct.Struct`"
assert restify(TracebackType) == ":class:`types.TracebackType`"
assert restify(Any) == ":obj:`Any`"
assert restify(Any) == ":obj:`~typing.Any`"
def test_restify_type_hints_containers():
assert restify(List) == ":class:`List`"
assert restify(Dict) == ":class:`Dict`"
assert restify(List[int]) == ":class:`List`\\ [:class:`int`]"
assert restify(List[str]) == ":class:`List`\\ [:class:`str`]"
assert restify(Dict[str, float]) == ":class:`Dict`\\ [:class:`str`, :class:`float`]"
assert restify(Tuple[str, str, str]) == ":class:`Tuple`\\ [:class:`str`, :class:`str`, :class:`str`]"
assert restify(Tuple[str, ...]) == ":class:`Tuple`\\ [:class:`str`, ...]"
assert restify(List[Dict[str, Tuple]]) == ":class:`List`\\ [:class:`Dict`\\ [:class:`str`, :class:`Tuple`]]"
assert restify(MyList[Tuple[int, int]]) == ":class:`tests.test_util_typing.MyList`\\ [:class:`Tuple`\\ [:class:`int`, :class:`int`]]"
assert restify(Generator[None, None, None]) == ":class:`Generator`\\ [:obj:`None`, :obj:`None`, :obj:`None`]"
assert restify(List) == ":class:`~typing.List`"
assert restify(Dict) == ":class:`~typing.Dict`"
assert restify(List[int]) == ":class:`~typing.List`\\ [:class:`int`]"
assert restify(List[str]) == ":class:`~typing.List`\\ [:class:`str`]"
assert restify(Dict[str, float]) == (":class:`~typing.Dict`\\ "
"[:class:`str`, :class:`float`]")
assert restify(Tuple[str, str, str]) == (":class:`~typing.Tuple`\\ "
"[:class:`str`, :class:`str`, :class:`str`]")
assert restify(Tuple[str, ...]) == ":class:`~typing.Tuple`\\ [:class:`str`, ...]"
assert restify(List[Dict[str, Tuple]]) == (":class:`~typing.List`\\ "
"[:class:`~typing.Dict`\\ "
"[:class:`str`, :class:`~typing.Tuple`]]")
assert restify(MyList[Tuple[int, int]]) == (":class:`tests.test_util_typing.MyList`\\ "
"[:class:`~typing.Tuple`\\ "
"[:class:`int`, :class:`int`]]")
assert restify(Generator[None, None, None]) == (":class:`~typing.Generator`\\ "
"[:obj:`None`, :obj:`None`, :obj:`None`]")
def test_restify_type_hints_Callable():
assert restify(Callable) == ":class:`Callable`"
assert restify(Callable) == ":class:`~typing.Callable`"
if sys.version_info >= (3, 7):
assert restify(Callable[[str], int]) == ":class:`Callable`\\ [[:class:`str`], :class:`int`]"
assert restify(Callable[..., int]) == ":class:`Callable`\\ [[...], :class:`int`]"
assert restify(Callable[[str], int]) == (":class:`~typing.Callable`\\ "
"[[:class:`str`], :class:`int`]")
assert restify(Callable[..., int]) == (":class:`~typing.Callable`\\ "
"[[...], :class:`int`]")
else:
assert restify(Callable[[str], int]) == ":class:`Callable`\\ [:class:`str`, :class:`int`]"
assert restify(Callable[..., int]) == ":class:`Callable`\\ [..., :class:`int`]"
assert restify(Callable[[str], int]) == (":class:`~typing.Callable`\\ "
"[:class:`str`, :class:`int`]")
assert restify(Callable[..., int]) == (":class:`~typing.Callable`\\ "
"[..., :class:`int`]")
def test_restify_type_hints_Union():
assert restify(Optional[int]) == ":obj:`Optional`\\ [:class:`int`]"
assert restify(Union[str, None]) == ":obj:`Optional`\\ [:class:`str`]"
assert restify(Union[int, str]) == ":obj:`Union`\\ [:class:`int`, :class:`str`]"
assert restify(Optional[int]) == ":obj:`~typing.Optional`\\ [:class:`int`]"
assert restify(Union[str, None]) == ":obj:`~typing.Optional`\\ [:class:`str`]"
assert restify(Union[int, str]) == ":obj:`~typing.Union`\\ [:class:`int`, :class:`str`]"
if sys.version_info >= (3, 7):
assert restify(Union[int, Integral]) == ":obj:`Union`\\ [:class:`int`, :class:`numbers.Integral`]"
assert restify(Union[int, Integral]) == (":obj:`~typing.Union`\\ "
"[:class:`int`, :class:`numbers.Integral`]")
assert (restify(Union[MyClass1, MyClass2]) ==
":obj:`Union`\\ [:class:`tests.test_util_typing.MyClass1`, :class:`tests.test_util_typing.<MyClass2>`]")
(":obj:`~typing.Union`\\ "
"[:class:`tests.test_util_typing.MyClass1`, "
":class:`tests.test_util_typing.<MyClass2>`]"))
else:
assert restify(Union[int, Integral]) == ":class:`numbers.Integral`"
assert restify(Union[MyClass1, MyClass2]) == ":class:`tests.test_util_typing.MyClass1`"
@ -97,7 +111,7 @@ def test_restify_type_hints_typevars():
assert restify(T) == ":obj:`tests.test_util_typing.T`"
assert restify(T_co) == ":obj:`tests.test_util_typing.T_co`"
assert restify(T_contra) == ":obj:`tests.test_util_typing.T_contra`"
assert restify(List[T]) == ":class:`List`\\ [:obj:`tests.test_util_typing.T`]"
assert restify(List[T]) == ":class:`~typing.List`\\ [:obj:`tests.test_util_typing.T`]"
assert restify(MyInt) == ":class:`MyInt`"
@ -110,7 +124,7 @@ def test_restify_type_hints_alias():
MyStr = str
MyTuple = Tuple[str, str]
assert restify(MyStr) == ":class:`str`"
assert restify(MyTuple) == ":class:`Tuple`\\ [:class:`str`, :class:`str`]" # type: ignore
assert restify(MyTuple) == ":class:`~typing.Tuple`\\ [:class:`str`, :class:`str`]"
@pytest.mark.skipif(sys.version_info < (3, 7), reason='python 3.7+ is required.')