mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge pull request #9997 from tk0miya/9194_Literal_type_not_hyperlinked
Fix #9194: autodoc: types in typing module are not hyperlinked
This commit is contained in:
1
CHANGES
1
CHANGES
@@ -49,6 +49,7 @@ Bugs fixed
|
||||
with Python 3.10
|
||||
* #9968: autodoc: instance variables are not shown if __init__ method has
|
||||
position-only-arguments
|
||||
* #9194: autodoc: types under the "typing" module are not hyperlinked
|
||||
* #9947: i18n: topic directive having a bullet list can't be translatable
|
||||
* #9878: mathjax: MathJax configuration is placed after loading MathJax itself
|
||||
* #9857: Generated RFC links use outdated base url
|
||||
|
||||
@@ -83,7 +83,8 @@ class ModuleEntry(NamedTuple):
|
||||
def type_to_xref(target: str, env: BuildEnvironment = None, suppress_prefix: bool = False
|
||||
) -> addnodes.pending_xref:
|
||||
"""Convert a type string to a cross reference node."""
|
||||
if target == 'None':
|
||||
if target == 'None' or target.startswith('typing.'):
|
||||
# typing module provides non-class types. Obj reference is good to refer them.
|
||||
reftype = 'obj'
|
||||
else:
|
||||
reftype = 'class'
|
||||
@@ -104,6 +105,8 @@ def type_to_xref(target: str, env: BuildEnvironment = None, suppress_prefix: boo
|
||||
text = target.split('.')[-1]
|
||||
elif suppress_prefix:
|
||||
text = target.split('.')[-1]
|
||||
elif target.startswith('typing.'):
|
||||
text = target[7:]
|
||||
else:
|
||||
text = target
|
||||
|
||||
@@ -203,10 +206,16 @@ def _parse_annotation(annotation: str, env: BuildEnvironment = None) -> List[Nod
|
||||
return result
|
||||
else:
|
||||
if sys.version_info < (3, 8):
|
||||
if isinstance(node, ast.Ellipsis):
|
||||
if isinstance(node, ast.Bytes):
|
||||
return [addnodes.desc_sig_literal_string('', repr(node.s))]
|
||||
elif isinstance(node, ast.Ellipsis):
|
||||
return [addnodes.desc_sig_punctuation('', "...")]
|
||||
elif isinstance(node, ast.NameConstant):
|
||||
return [nodes.Text(node.value)]
|
||||
elif isinstance(node, ast.Num):
|
||||
return [addnodes.desc_sig_literal_string('', repr(node.n))]
|
||||
elif isinstance(node, ast.Str):
|
||||
return [addnodes.desc_sig_literal_string('', repr(node.s))]
|
||||
|
||||
raise SyntaxError # unsupported syntax
|
||||
|
||||
@@ -1481,7 +1490,7 @@ def builtin_resolver(app: Sphinx, env: BuildEnvironment,
|
||||
return None
|
||||
elif node.get('reftype') in ('class', 'obj') and node.get('reftarget') == 'None':
|
||||
return contnode
|
||||
elif node.get('reftype') in ('class', 'exc'):
|
||||
elif node.get('reftype') in ('class', 'obj', 'exc'):
|
||||
reftarget = node.get('reftarget')
|
||||
if inspect.isclass(getattr(builtins, reftarget, None)):
|
||||
# built-in class
|
||||
|
||||
@@ -753,6 +753,11 @@ def stringify_signature(sig: inspect.Signature, show_annotation: bool = True,
|
||||
:param unqualified_typehints: If enabled, show annotations as unqualified
|
||||
(ex. io.StringIO -> StringIO)
|
||||
"""
|
||||
if unqualified_typehints:
|
||||
mode = 'smart'
|
||||
else:
|
||||
mode = 'fully-qualified'
|
||||
|
||||
args = []
|
||||
last_kind = None
|
||||
for param in sig.parameters.values():
|
||||
@@ -775,7 +780,7 @@ def stringify_signature(sig: inspect.Signature, show_annotation: bool = True,
|
||||
|
||||
if show_annotation and param.annotation is not param.empty:
|
||||
arg.write(': ')
|
||||
arg.write(stringify_annotation(param.annotation, unqualified_typehints))
|
||||
arg.write(stringify_annotation(param.annotation, mode))
|
||||
if param.default is not param.empty:
|
||||
if show_annotation and param.annotation is not param.empty:
|
||||
arg.write(' = ')
|
||||
@@ -795,7 +800,7 @@ def stringify_signature(sig: inspect.Signature, show_annotation: bool = True,
|
||||
show_return_annotation is False):
|
||||
return '(%s)' % ', '.join(args)
|
||||
else:
|
||||
annotation = stringify_annotation(sig.return_annotation, unqualified_typehints)
|
||||
annotation = stringify_annotation(sig.return_annotation, mode)
|
||||
return '(%s) -> %s' % (', '.join(args), annotation)
|
||||
|
||||
|
||||
|
||||
@@ -299,18 +299,25 @@ def _restify_py36(cls: Optional[Type]) -> str:
|
||||
return ':py:obj:`%s.%s`' % (cls.__module__, qualname)
|
||||
|
||||
|
||||
def stringify(annotation: Any, smartref: bool = False) -> str:
|
||||
def stringify(annotation: Any, mode: str = 'fully-qualified-except-typing') -> str:
|
||||
"""Stringify type annotation object.
|
||||
|
||||
:param smartref: If true, add "~" prefix to the result to remove the leading
|
||||
module and class names from the reference text
|
||||
:param mode: Specify a method how annotations will be stringified.
|
||||
|
||||
'fully-qualified-except-typing'
|
||||
Show the module name and qualified name of the annotation except
|
||||
the "typing" module.
|
||||
'smart'
|
||||
Show the name of the annotation.
|
||||
'fully-qualified'
|
||||
Show the module name and qualified name of the annotation.
|
||||
"""
|
||||
from sphinx.util import inspect # lazy loading
|
||||
|
||||
if smartref:
|
||||
prefix = '~'
|
||||
if mode == 'smart':
|
||||
modprefix = '~'
|
||||
else:
|
||||
prefix = ''
|
||||
modprefix = ''
|
||||
|
||||
if isinstance(annotation, str):
|
||||
if annotation.startswith("'") and annotation.endswith("'"):
|
||||
@@ -319,14 +326,15 @@ def stringify(annotation: Any, smartref: bool = False) -> str:
|
||||
else:
|
||||
return annotation
|
||||
elif isinstance(annotation, TypeVar):
|
||||
if annotation.__module__ == 'typing':
|
||||
if (annotation.__module__ == 'typing' and
|
||||
mode in ('fully-qualified-except-typing', 'smart')):
|
||||
return annotation.__name__
|
||||
else:
|
||||
return prefix + '.'.join([annotation.__module__, annotation.__name__])
|
||||
return modprefix + '.'.join([annotation.__module__, annotation.__name__])
|
||||
elif inspect.isNewType(annotation):
|
||||
if sys.version_info > (3, 10):
|
||||
# newtypes have correct module info since Python 3.10+
|
||||
return prefix + '%s.%s' % (annotation.__module__, annotation.__name__)
|
||||
return modprefix + '%s.%s' % (annotation.__module__, annotation.__name__)
|
||||
else:
|
||||
return annotation.__name__
|
||||
elif not annotation:
|
||||
@@ -334,7 +342,7 @@ def stringify(annotation: Any, smartref: bool = False) -> str:
|
||||
elif annotation is NoneType:
|
||||
return 'None'
|
||||
elif annotation in INVALID_BUILTIN_CLASSES:
|
||||
return prefix + INVALID_BUILTIN_CLASSES[annotation]
|
||||
return modprefix + INVALID_BUILTIN_CLASSES[annotation]
|
||||
elif str(annotation).startswith('typing.Annotated'): # for py310+
|
||||
pass
|
||||
elif (getattr(annotation, '__module__', None) == 'builtins' and
|
||||
@@ -347,12 +355,12 @@ def stringify(annotation: Any, smartref: bool = False) -> str:
|
||||
return '...'
|
||||
|
||||
if sys.version_info >= (3, 7): # py37+
|
||||
return _stringify_py37(annotation, smartref)
|
||||
return _stringify_py37(annotation, mode)
|
||||
else:
|
||||
return _stringify_py36(annotation, smartref)
|
||||
return _stringify_py36(annotation, mode)
|
||||
|
||||
|
||||
def _stringify_py37(annotation: Any, smartref: bool = False) -> str:
|
||||
def _stringify_py37(annotation: Any, mode: str = 'fully-qualified-except-typing') -> str:
|
||||
"""stringify() for py37+."""
|
||||
module = getattr(annotation, '__module__', None)
|
||||
modprefix = ''
|
||||
@@ -364,19 +372,21 @@ def _stringify_py37(annotation: Any, smartref: bool = False) -> str:
|
||||
elif getattr(annotation, '__qualname__', None):
|
||||
qualname = annotation.__qualname__
|
||||
else:
|
||||
qualname = stringify(annotation.__origin__) # ex. Union
|
||||
qualname = stringify(annotation.__origin__).replace('typing.', '') # ex. Union
|
||||
|
||||
if smartref:
|
||||
if mode == 'smart':
|
||||
modprefix = '~%s.' % module
|
||||
elif mode == 'fully-qualified':
|
||||
modprefix = '%s.' % module
|
||||
elif hasattr(annotation, '__qualname__'):
|
||||
if smartref:
|
||||
if mode == 'smart':
|
||||
modprefix = '~%s.' % module
|
||||
else:
|
||||
modprefix = '%s.' % module
|
||||
qualname = annotation.__qualname__
|
||||
elif hasattr(annotation, '__origin__'):
|
||||
# instantiated generic provided by a user
|
||||
qualname = stringify(annotation.__origin__, smartref)
|
||||
qualname = stringify(annotation.__origin__, mode)
|
||||
elif UnionType and isinstance(annotation, UnionType): # types.Union (for py3.10+)
|
||||
qualname = 'types.Union'
|
||||
else:
|
||||
@@ -391,13 +401,13 @@ def _stringify_py37(annotation: Any, smartref: bool = False) -> str:
|
||||
elif qualname in ('Optional', 'Union'):
|
||||
if len(annotation.__args__) > 1 and annotation.__args__[-1] is NoneType:
|
||||
if len(annotation.__args__) > 2:
|
||||
args = ', '.join(stringify(a, smartref) for a in annotation.__args__[:-1])
|
||||
args = ', '.join(stringify(a, mode) for a in annotation.__args__[:-1])
|
||||
return '%sOptional[%sUnion[%s]]' % (modprefix, modprefix, args)
|
||||
else:
|
||||
return '%sOptional[%s]' % (modprefix,
|
||||
stringify(annotation.__args__[0], smartref))
|
||||
stringify(annotation.__args__[0], mode))
|
||||
else:
|
||||
args = ', '.join(stringify(a, smartref) for a in annotation.__args__)
|
||||
args = ', '.join(stringify(a, mode) for a in annotation.__args__)
|
||||
return '%sUnion[%s]' % (modprefix, args)
|
||||
elif qualname == 'types.Union':
|
||||
if len(annotation.__args__) > 1 and None in annotation.__args__:
|
||||
@@ -406,25 +416,25 @@ def _stringify_py37(annotation: Any, smartref: bool = False) -> str:
|
||||
else:
|
||||
return ' | '.join(stringify(a) for a in annotation.__args__)
|
||||
elif qualname == 'Callable':
|
||||
args = ', '.join(stringify(a, smartref) for a in annotation.__args__[:-1])
|
||||
returns = stringify(annotation.__args__[-1], smartref)
|
||||
args = ', '.join(stringify(a, mode) for a in annotation.__args__[:-1])
|
||||
returns = stringify(annotation.__args__[-1], mode)
|
||||
return '%s%s[[%s], %s]' % (modprefix, qualname, args, returns)
|
||||
elif qualname == 'Literal':
|
||||
args = ', '.join(repr(a) for a in annotation.__args__)
|
||||
return '%s%s[%s]' % (modprefix, qualname, args)
|
||||
elif str(annotation).startswith('typing.Annotated'): # for py39+
|
||||
return stringify(annotation.__args__[0], smartref)
|
||||
return stringify(annotation.__args__[0], mode)
|
||||
elif all(is_system_TypeVar(a) for a in annotation.__args__):
|
||||
# Suppress arguments if all system defined TypeVars (ex. Dict[KT, VT])
|
||||
return modprefix + qualname
|
||||
else:
|
||||
args = ', '.join(stringify(a, smartref) for a in annotation.__args__)
|
||||
args = ', '.join(stringify(a, mode) for a in annotation.__args__)
|
||||
return '%s%s[%s]' % (modprefix, qualname, args)
|
||||
|
||||
return modprefix + qualname
|
||||
|
||||
|
||||
def _stringify_py36(annotation: Any, smartref: bool = False) -> str:
|
||||
def _stringify_py36(annotation: Any, mode: str = 'fully-qualified-except-typing') -> str:
|
||||
"""stringify() for py36."""
|
||||
module = getattr(annotation, '__module__', None)
|
||||
modprefix = ''
|
||||
@@ -440,10 +450,12 @@ def _stringify_py36(annotation: Any, smartref: bool = False) -> str:
|
||||
else:
|
||||
qualname = repr(annotation).replace('typing.', '')
|
||||
|
||||
if smartref:
|
||||
if mode == 'smart':
|
||||
modprefix = '~%s.' % module
|
||||
elif mode == 'fully-qualified':
|
||||
modprefix = '%s.' % module
|
||||
elif hasattr(annotation, '__qualname__'):
|
||||
if smartref:
|
||||
if mode == 'smart':
|
||||
modprefix = '~%s.' % module
|
||||
else:
|
||||
modprefix = '%s.' % module
|
||||
@@ -455,7 +467,7 @@ def _stringify_py36(annotation: Any, smartref: bool = False) -> str:
|
||||
not hasattr(annotation, '__tuple_params__')): # for Python 3.6
|
||||
params = annotation.__args__
|
||||
if params:
|
||||
param_str = ', '.join(stringify(p, smartref) for p in params)
|
||||
param_str = ', '.join(stringify(p, mode) for p in params)
|
||||
return '%s%s[%s]' % (modprefix, qualname, param_str)
|
||||
else:
|
||||
return modprefix + qualname
|
||||
@@ -466,12 +478,12 @@ def _stringify_py36(annotation: Any, smartref: bool = False) -> str:
|
||||
elif annotation.__origin__ == Generator: # type: ignore
|
||||
params = annotation.__args__ # type: ignore
|
||||
else: # typing.Callable
|
||||
args = ', '.join(stringify(arg, smartref) for arg
|
||||
args = ', '.join(stringify(arg, mode) for arg
|
||||
in annotation.__args__[:-1]) # type: ignore
|
||||
result = stringify(annotation.__args__[-1]) # type: ignore
|
||||
return '%s%s[[%s], %s]' % (modprefix, qualname, args, result)
|
||||
if params is not None:
|
||||
param_str = ', '.join(stringify(p, smartref) for p in params)
|
||||
param_str = ', '.join(stringify(p, mode) for p in params)
|
||||
return '%s%s[%s]' % (modprefix, qualname, param_str)
|
||||
elif (hasattr(annotation, '__origin__') and
|
||||
annotation.__origin__ is typing.Union):
|
||||
@@ -479,12 +491,12 @@ def _stringify_py36(annotation: Any, smartref: bool = False) -> str:
|
||||
if params is not None:
|
||||
if len(params) > 1 and params[-1] is NoneType:
|
||||
if len(params) > 2:
|
||||
param_str = ", ".join(stringify(p, smartref) for p in params[:-1])
|
||||
param_str = ", ".join(stringify(p, mode) for p in params[:-1])
|
||||
return '%sOptional[%sUnion[%s]]' % (modprefix, modprefix, param_str)
|
||||
else:
|
||||
return '%sOptional[%s]' % (modprefix, stringify(params[0]))
|
||||
return '%sOptional[%s]' % (modprefix, stringify(params[0], mode))
|
||||
else:
|
||||
param_str = ', '.join(stringify(p, smartref) for p in params)
|
||||
param_str = ', '.join(stringify(p, mode) for p in params)
|
||||
return '%sUnion[%s]' % (modprefix, param_str)
|
||||
|
||||
return modprefix + qualname
|
||||
|
||||
@@ -348,6 +348,17 @@ def test_parse_annotation(app):
|
||||
assert_node(doctree, ([pending_xref, "None"],))
|
||||
assert_node(doctree[0], pending_xref, refdomain="py", reftype="obj", reftarget="None")
|
||||
|
||||
# Literal type makes an object-reference (not a class reference)
|
||||
doctree = _parse_annotation("typing.Literal['a', 'b']", app.env)
|
||||
assert_node(doctree, ([pending_xref, "Literal"],
|
||||
[desc_sig_punctuation, "["],
|
||||
[desc_sig_literal_string, "'a'"],
|
||||
[desc_sig_punctuation, ","],
|
||||
desc_sig_space,
|
||||
[desc_sig_literal_string, "'b'"],
|
||||
[desc_sig_punctuation, "]"]))
|
||||
assert_node(doctree[0], pending_xref, refdomain="py", reftype="obj", reftarget="typing.Literal")
|
||||
|
||||
|
||||
def test_parse_annotation_suppress(app):
|
||||
doctree = _parse_annotation("~typing.Dict[str, str]", app.env)
|
||||
@@ -358,7 +369,7 @@ def test_parse_annotation_suppress(app):
|
||||
desc_sig_space,
|
||||
[pending_xref, "str"],
|
||||
[desc_sig_punctuation, "]"]))
|
||||
assert_node(doctree[0], pending_xref, refdomain="py", reftype="class", reftarget="typing.Dict")
|
||||
assert_node(doctree[0], pending_xref, refdomain="py", reftype="obj", reftarget="typing.Dict")
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 8), reason='python 3.8+ is required.')
|
||||
@@ -373,7 +384,7 @@ def test_parse_annotation_Literal(app):
|
||||
[desc_sig_punctuation, "]"]))
|
||||
|
||||
doctree = _parse_annotation("typing.Literal[0, 1, 'abc']", app.env)
|
||||
assert_node(doctree, ([pending_xref, "typing.Literal"],
|
||||
assert_node(doctree, ([pending_xref, "Literal"],
|
||||
[desc_sig_punctuation, "["],
|
||||
[desc_sig_literal_number, "0"],
|
||||
[desc_sig_punctuation, ","],
|
||||
|
||||
@@ -162,7 +162,7 @@ def test_wrapped_function_contextmanager(app):
|
||||
actual = do_autodoc(app, 'function', 'target.wrappedfunction.feeling_good')
|
||||
assert list(actual) == [
|
||||
'',
|
||||
'.. py:function:: feeling_good(x: int, y: int) -> Generator',
|
||||
'.. py:function:: feeling_good(x: int, y: int) -> typing.Generator',
|
||||
' :module: target.wrappedfunction',
|
||||
'',
|
||||
" You'll feel better in this context!",
|
||||
|
||||
@@ -130,4 +130,4 @@ def test_subclass_of_mocked_object(app):
|
||||
|
||||
options = {'members': None}
|
||||
actual = do_autodoc(app, 'module', 'target.need_mocks', options)
|
||||
assert '.. py:class:: Inherited(*args: Any, **kwargs: Any)' in actual
|
||||
assert '.. py:class:: Inherited(*args: typing.Any, **kwargs: typing.Any)' in actual
|
||||
|
||||
@@ -612,7 +612,7 @@ def test_autodoc_typehints_signature(app):
|
||||
' :type: int',
|
||||
'',
|
||||
'',
|
||||
'.. py:class:: Math(s: str, o: Optional[Any] = None)',
|
||||
'.. py:class:: Math(s: str, o: typing.Optional[typing.Any] = None)',
|
||||
' :module: target.typehints',
|
||||
'',
|
||||
'',
|
||||
@@ -677,7 +677,8 @@ def test_autodoc_typehints_signature(app):
|
||||
' :module: target.typehints',
|
||||
'',
|
||||
'',
|
||||
'.. py:function:: tuple_args(x: Tuple[int, Union[int, str]]) -> Tuple[int, int]',
|
||||
'.. py:function:: tuple_args(x: typing.Tuple[int, typing.Union[int, str]]) '
|
||||
'-> typing.Tuple[int, int]',
|
||||
' :module: target.typehints',
|
||||
'',
|
||||
]
|
||||
@@ -1145,11 +1146,6 @@ def test_autodoc_typehints_description_and_type_aliases(app):
|
||||
@pytest.mark.sphinx('html', testroot='ext-autodoc',
|
||||
confoverrides={'autodoc_typehints_format': "short"})
|
||||
def test_autodoc_typehints_format_short(app):
|
||||
if sys.version_info < (3, 7):
|
||||
Any = 'Any'
|
||||
else:
|
||||
Any = '~typing.Any'
|
||||
|
||||
options = {"members": None,
|
||||
"undoc-members": None}
|
||||
actual = do_autodoc(app, 'module', 'target.typehints', options)
|
||||
@@ -1163,7 +1159,7 @@ def test_autodoc_typehints_format_short(app):
|
||||
' :type: int',
|
||||
'',
|
||||
'',
|
||||
'.. py:class:: Math(s: str, o: ~typing.Optional[%s] = None)' % Any,
|
||||
'.. py:class:: Math(s: str, o: ~typing.Optional[~typing.Any] = None)',
|
||||
' :module: target.typehints',
|
||||
'',
|
||||
'',
|
||||
|
||||
@@ -36,15 +36,15 @@ def test_preserve_defaults(app):
|
||||
' docstring',
|
||||
'',
|
||||
'',
|
||||
' .. py:method:: Class.meth(name: str = CONSTANT, sentinel: Any = SENTINEL, '
|
||||
'now: datetime.datetime = datetime.now(), color: int = %s) -> None' % color,
|
||||
' .. py:method:: Class.meth(name: str = CONSTANT, sentinel: typing.Any = '
|
||||
'SENTINEL, now: datetime.datetime = datetime.now(), color: int = %s) -> None' % color,
|
||||
' :module: target.preserve_defaults',
|
||||
'',
|
||||
' docstring',
|
||||
'',
|
||||
'',
|
||||
'.. py:function:: foo(name: str = CONSTANT, sentinel: Any = SENTINEL, now: '
|
||||
'datetime.datetime = datetime.now(), color: int = %s) -> None' % color,
|
||||
'.. py:function:: foo(name: str = CONSTANT, sentinel: typing.Any = SENTINEL, '
|
||||
'now: datetime.datetime = datetime.now(), color: int = %s) -> None' % color,
|
||||
' :module: target.preserve_defaults',
|
||||
'',
|
||||
' docstring',
|
||||
|
||||
@@ -157,21 +157,24 @@ def test_signature_annotations():
|
||||
|
||||
# Generic types with concrete parameters
|
||||
sig = inspect.signature(f1)
|
||||
assert stringify_signature(sig) == '(x: List[int]) -> List[int]'
|
||||
assert stringify_signature(sig) == '(x: typing.List[int]) -> typing.List[int]'
|
||||
|
||||
# TypeVars and generic types with TypeVars
|
||||
sig = inspect.signature(f2)
|
||||
if sys.version_info < (3, 7):
|
||||
assert stringify_signature(sig) == '(x: List[T], y: List[T_co], z: T) -> List[T_contra]'
|
||||
assert stringify_signature(sig) == ('(x: typing.List[typing.T],'
|
||||
' y: typing.List[typing.T_co],'
|
||||
' z: typing.T'
|
||||
') -> typing.List[typing.T_contra]')
|
||||
else:
|
||||
assert stringify_signature(sig) == ('(x: List[tests.typing_test_data.T],'
|
||||
' y: List[tests.typing_test_data.T_co],'
|
||||
assert stringify_signature(sig) == ('(x: typing.List[tests.typing_test_data.T],'
|
||||
' y: typing.List[tests.typing_test_data.T_co],'
|
||||
' z: tests.typing_test_data.T'
|
||||
') -> List[tests.typing_test_data.T_contra]')
|
||||
') -> typing.List[tests.typing_test_data.T_contra]')
|
||||
|
||||
# Union types
|
||||
sig = inspect.signature(f3)
|
||||
assert stringify_signature(sig) == '(x: Union[str, numbers.Integral]) -> None'
|
||||
assert stringify_signature(sig) == '(x: typing.Union[str, numbers.Integral]) -> None'
|
||||
|
||||
# Quoted annotations
|
||||
sig = inspect.signature(f4)
|
||||
@@ -187,18 +190,18 @@ def test_signature_annotations():
|
||||
|
||||
# Space around '=' for defaults
|
||||
sig = inspect.signature(f7)
|
||||
assert stringify_signature(sig) == '(x: Optional[int] = None, y: dict = {}) -> None'
|
||||
assert stringify_signature(sig) == '(x: typing.Optional[int] = None, y: dict = {}) -> None'
|
||||
|
||||
# Callable types
|
||||
sig = inspect.signature(f8)
|
||||
assert stringify_signature(sig) == '(x: Callable[[int, str], int]) -> None'
|
||||
assert stringify_signature(sig) == '(x: typing.Callable[[int, str], int]) -> None'
|
||||
|
||||
sig = inspect.signature(f9)
|
||||
assert stringify_signature(sig) == '(x: Callable) -> None'
|
||||
assert stringify_signature(sig) == '(x: typing.Callable) -> None'
|
||||
|
||||
# Tuple types
|
||||
sig = inspect.signature(f10)
|
||||
assert stringify_signature(sig) == '(x: Tuple[int, str], y: Tuple[int, ...]) -> None'
|
||||
assert stringify_signature(sig) == '(x: typing.Tuple[int, str], y: typing.Tuple[int, ...]) -> None'
|
||||
|
||||
# Instance annotations
|
||||
sig = inspect.signature(f11)
|
||||
@@ -206,24 +209,24 @@ def test_signature_annotations():
|
||||
|
||||
# tuple with more than two items
|
||||
sig = inspect.signature(f12)
|
||||
assert stringify_signature(sig) == '() -> Tuple[int, str, int]'
|
||||
assert stringify_signature(sig) == '() -> typing.Tuple[int, str, int]'
|
||||
|
||||
# optional
|
||||
sig = inspect.signature(f13)
|
||||
assert stringify_signature(sig) == '() -> Optional[str]'
|
||||
assert stringify_signature(sig) == '() -> typing.Optional[str]'
|
||||
|
||||
# optional union
|
||||
sig = inspect.signature(f20)
|
||||
assert stringify_signature(sig) in ('() -> Optional[Union[int, str]]',
|
||||
'() -> Optional[Union[str, int]]')
|
||||
assert stringify_signature(sig) in ('() -> typing.Optional[typing.Union[int, str]]',
|
||||
'() -> typing.Optional[typing.Union[str, int]]')
|
||||
|
||||
# Any
|
||||
sig = inspect.signature(f14)
|
||||
assert stringify_signature(sig) == '() -> Any'
|
||||
assert stringify_signature(sig) == '() -> typing.Any'
|
||||
|
||||
# ForwardRef
|
||||
sig = inspect.signature(f15)
|
||||
assert stringify_signature(sig) == '(x: Unknown, y: int) -> Any'
|
||||
assert stringify_signature(sig) == '(x: Unknown, y: int) -> typing.Any'
|
||||
|
||||
# keyword only arguments (1)
|
||||
sig = inspect.signature(f16)
|
||||
@@ -234,7 +237,8 @@ def test_signature_annotations():
|
||||
assert stringify_signature(sig) == '(*, arg3, arg4)'
|
||||
|
||||
sig = inspect.signature(f18)
|
||||
assert stringify_signature(sig) == '(self, arg1: Union[int, Tuple] = 10) -> List[Dict]'
|
||||
assert stringify_signature(sig) == ('(self, arg1: typing.Union[int, typing.Tuple] = 10) -> '
|
||||
'typing.List[typing.Dict]')
|
||||
|
||||
# annotations for variadic and keyword parameters
|
||||
sig = inspect.signature(f19)
|
||||
@@ -246,10 +250,10 @@ def test_signature_annotations():
|
||||
|
||||
# type hints by string
|
||||
sig = inspect.signature(Node.children)
|
||||
assert stringify_signature(sig) == '(self) -> List[tests.typing_test_data.Node]'
|
||||
assert stringify_signature(sig) == '(self) -> typing.List[tests.typing_test_data.Node]'
|
||||
|
||||
sig = inspect.signature(Node.__init__)
|
||||
assert stringify_signature(sig) == '(self, parent: Optional[tests.typing_test_data.Node]) -> None'
|
||||
assert stringify_signature(sig) == '(self, parent: typing.Optional[tests.typing_test_data.Node]) -> None'
|
||||
|
||||
# show_annotation is False
|
||||
sig = inspect.signature(f7)
|
||||
@@ -257,7 +261,7 @@ def test_signature_annotations():
|
||||
|
||||
# show_return_annotation is False
|
||||
sig = inspect.signature(f7)
|
||||
assert stringify_signature(sig, show_return_annotation=False) == '(x: Optional[int] = None, y: dict = {})'
|
||||
assert stringify_signature(sig, show_return_annotation=False) == '(x: typing.Optional[int] = None, y: dict = {})'
|
||||
|
||||
# unqualified_typehints is True
|
||||
sig = inspect.signature(f7)
|
||||
|
||||
@@ -178,156 +178,181 @@ def test_restify_mock():
|
||||
|
||||
|
||||
def test_stringify():
|
||||
assert stringify(int, False) == "int"
|
||||
assert stringify(int, True) == "int"
|
||||
assert stringify(int) == "int"
|
||||
assert stringify(int, "smart") == "int"
|
||||
|
||||
assert stringify(str, False) == "str"
|
||||
assert stringify(str, True) == "str"
|
||||
assert stringify(str) == "str"
|
||||
assert stringify(str, "smart") == "str"
|
||||
|
||||
assert stringify(None, False) == "None"
|
||||
assert stringify(None, True) == "None"
|
||||
assert stringify(None) == "None"
|
||||
assert stringify(None, "smart") == "None"
|
||||
|
||||
assert stringify(Integral, False) == "numbers.Integral"
|
||||
assert stringify(Integral, True) == "~numbers.Integral"
|
||||
assert stringify(Integral) == "numbers.Integral"
|
||||
assert stringify(Integral, "smart") == "~numbers.Integral"
|
||||
|
||||
assert stringify(Struct, False) == "struct.Struct"
|
||||
assert stringify(Struct, True) == "~struct.Struct"
|
||||
assert stringify(Struct) == "struct.Struct"
|
||||
assert stringify(Struct, "smart") == "~struct.Struct"
|
||||
|
||||
assert stringify(TracebackType, False) == "types.TracebackType"
|
||||
assert stringify(TracebackType, True) == "~types.TracebackType"
|
||||
assert stringify(TracebackType) == "types.TracebackType"
|
||||
assert stringify(TracebackType, "smart") == "~types.TracebackType"
|
||||
|
||||
assert stringify(Any, False) == "Any"
|
||||
assert stringify(Any, True) == "~typing.Any"
|
||||
assert stringify(Any) == "Any"
|
||||
assert stringify(Any, "fully-qualified") == "typing.Any"
|
||||
assert stringify(Any, "smart") == "~typing.Any"
|
||||
|
||||
|
||||
def test_stringify_type_hints_containers():
|
||||
assert stringify(List, False) == "List"
|
||||
assert stringify(List, True) == "~typing.List"
|
||||
assert stringify(List) == "List"
|
||||
assert stringify(List, "fully-qualified") == "typing.List"
|
||||
assert stringify(List, "smart") == "~typing.List"
|
||||
|
||||
assert stringify(Dict, False) == "Dict"
|
||||
assert stringify(Dict, True) == "~typing.Dict"
|
||||
assert stringify(Dict) == "Dict"
|
||||
assert stringify(Dict, "fully-qualified") == "typing.Dict"
|
||||
assert stringify(Dict, "smart") == "~typing.Dict"
|
||||
|
||||
assert stringify(List[int], False) == "List[int]"
|
||||
assert stringify(List[int], True) == "~typing.List[int]"
|
||||
assert stringify(List[int]) == "List[int]"
|
||||
assert stringify(List[int], "fully-qualified") == "typing.List[int]"
|
||||
assert stringify(List[int], "smart") == "~typing.List[int]"
|
||||
|
||||
assert stringify(List[str], False) == "List[str]"
|
||||
assert stringify(List[str], True) == "~typing.List[str]"
|
||||
assert stringify(List[str]) == "List[str]"
|
||||
assert stringify(List[str], "fully-qualified") == "typing.List[str]"
|
||||
assert stringify(List[str], "smart") == "~typing.List[str]"
|
||||
|
||||
assert stringify(Dict[str, float], False) == "Dict[str, float]"
|
||||
assert stringify(Dict[str, float], True) == "~typing.Dict[str, float]"
|
||||
assert stringify(Dict[str, float]) == "Dict[str, float]"
|
||||
assert stringify(Dict[str, float], "fully-qualified") == "typing.Dict[str, float]"
|
||||
assert stringify(Dict[str, float], "smart") == "~typing.Dict[str, float]"
|
||||
|
||||
assert stringify(Tuple[str, str, str], False) == "Tuple[str, str, str]"
|
||||
assert stringify(Tuple[str, str, str], True) == "~typing.Tuple[str, str, str]"
|
||||
assert stringify(Tuple[str, str, str]) == "Tuple[str, str, str]"
|
||||
assert stringify(Tuple[str, str, str], "fully-qualified") == "typing.Tuple[str, str, str]"
|
||||
assert stringify(Tuple[str, str, str], "smart") == "~typing.Tuple[str, str, str]"
|
||||
|
||||
assert stringify(Tuple[str, ...], False) == "Tuple[str, ...]"
|
||||
assert stringify(Tuple[str, ...], True) == "~typing.Tuple[str, ...]"
|
||||
assert stringify(Tuple[str, ...]) == "Tuple[str, ...]"
|
||||
assert stringify(Tuple[str, ...], "fully-qualified") == "typing.Tuple[str, ...]"
|
||||
assert stringify(Tuple[str, ...], "smart") == "~typing.Tuple[str, ...]"
|
||||
|
||||
assert stringify(Tuple[()], False) == "Tuple[()]"
|
||||
assert stringify(Tuple[()], True) == "~typing.Tuple[()]"
|
||||
assert stringify(Tuple[()]) == "Tuple[()]"
|
||||
assert stringify(Tuple[()], "fully-qualified") == "typing.Tuple[()]"
|
||||
assert stringify(Tuple[()], "smart") == "~typing.Tuple[()]"
|
||||
|
||||
assert stringify(List[Dict[str, Tuple]], False) == "List[Dict[str, Tuple]]"
|
||||
assert stringify(List[Dict[str, Tuple]], True) == "~typing.List[~typing.Dict[str, ~typing.Tuple]]"
|
||||
assert stringify(List[Dict[str, Tuple]]) == "List[Dict[str, Tuple]]"
|
||||
assert stringify(List[Dict[str, Tuple]], "fully-qualified") == "typing.List[typing.Dict[str, typing.Tuple]]"
|
||||
assert stringify(List[Dict[str, Tuple]], "smart") == "~typing.List[~typing.Dict[str, ~typing.Tuple]]"
|
||||
|
||||
assert stringify(MyList[Tuple[int, int]], False) == "tests.test_util_typing.MyList[Tuple[int, int]]"
|
||||
assert stringify(MyList[Tuple[int, int]], True) == "~tests.test_util_typing.MyList[~typing.Tuple[int, int]]"
|
||||
assert stringify(MyList[Tuple[int, int]]) == "tests.test_util_typing.MyList[Tuple[int, int]]"
|
||||
assert stringify(MyList[Tuple[int, int]], "fully-qualified") == "tests.test_util_typing.MyList[typing.Tuple[int, int]]"
|
||||
assert stringify(MyList[Tuple[int, int]], "smart") == "~tests.test_util_typing.MyList[~typing.Tuple[int, int]]"
|
||||
|
||||
assert stringify(Generator[None, None, None], False) == "Generator[None, None, None]"
|
||||
assert stringify(Generator[None, None, None], True) == "~typing.Generator[None, None, None]"
|
||||
assert stringify(Generator[None, None, None]) == "Generator[None, None, None]"
|
||||
assert stringify(Generator[None, None, None], "fully-qualified") == "typing.Generator[None, None, None]"
|
||||
assert stringify(Generator[None, None, None], "smart") == "~typing.Generator[None, None, None]"
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 9), reason='python 3.9+ is required.')
|
||||
def test_stringify_type_hints_pep_585():
|
||||
assert stringify(list[int], False) == "list[int]"
|
||||
assert stringify(list[int], True) == "list[int]"
|
||||
assert stringify(list[int]) == "list[int]"
|
||||
assert stringify(list[int], "smart") == "list[int]"
|
||||
|
||||
assert stringify(list[str], False) == "list[str]"
|
||||
assert stringify(list[str], True) == "list[str]"
|
||||
assert stringify(list[str]) == "list[str]"
|
||||
assert stringify(list[str], "smart") == "list[str]"
|
||||
|
||||
assert stringify(dict[str, float], False) == "dict[str, float]"
|
||||
assert stringify(dict[str, float], True) == "dict[str, float]"
|
||||
assert stringify(dict[str, float]) == "dict[str, float]"
|
||||
assert stringify(dict[str, float], "smart") == "dict[str, float]"
|
||||
|
||||
assert stringify(tuple[str, str, str], False) == "tuple[str, str, str]"
|
||||
assert stringify(tuple[str, str, str], True) == "tuple[str, str, str]"
|
||||
assert stringify(tuple[str, str, str]) == "tuple[str, str, str]"
|
||||
assert stringify(tuple[str, str, str], "smart") == "tuple[str, str, str]"
|
||||
|
||||
assert stringify(tuple[str, ...], False) == "tuple[str, ...]"
|
||||
assert stringify(tuple[str, ...], True) == "tuple[str, ...]"
|
||||
assert stringify(tuple[str, ...]) == "tuple[str, ...]"
|
||||
assert stringify(tuple[str, ...], "smart") == "tuple[str, ...]"
|
||||
|
||||
assert stringify(tuple[()], False) == "tuple[()]"
|
||||
assert stringify(tuple[()], True) == "tuple[()]"
|
||||
assert stringify(tuple[()]) == "tuple[()]"
|
||||
assert stringify(tuple[()], "smart") == "tuple[()]"
|
||||
|
||||
assert stringify(list[dict[str, tuple]], False) == "list[dict[str, tuple]]"
|
||||
assert stringify(list[dict[str, tuple]], True) == "list[dict[str, tuple]]"
|
||||
assert stringify(list[dict[str, tuple]]) == "list[dict[str, tuple]]"
|
||||
assert stringify(list[dict[str, tuple]], "smart") == "list[dict[str, tuple]]"
|
||||
|
||||
assert stringify(type[int], False) == "type[int]"
|
||||
assert stringify(type[int], True) == "type[int]"
|
||||
assert stringify(type[int]) == "type[int]"
|
||||
assert stringify(type[int], "smart") == "type[int]"
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 9), reason='python 3.9+ is required.')
|
||||
def test_stringify_Annotated():
|
||||
from typing import Annotated # type: ignore
|
||||
assert stringify(Annotated[str, "foo", "bar"], False) == "str" # NOQA
|
||||
assert stringify(Annotated[str, "foo", "bar"], True) == "str" # NOQA
|
||||
assert stringify(Annotated[str, "foo", "bar"]) == "str" # NOQA
|
||||
assert stringify(Annotated[str, "foo", "bar"], "smart") == "str" # NOQA
|
||||
|
||||
|
||||
def test_stringify_type_hints_string():
|
||||
assert stringify("int", False) == "int"
|
||||
assert stringify("int", True) == "int"
|
||||
assert stringify("int") == "int"
|
||||
assert stringify("int", "smart") == "int"
|
||||
|
||||
assert stringify("str", False) == "str"
|
||||
assert stringify("str", True) == "str"
|
||||
assert stringify("str") == "str"
|
||||
assert stringify("str", "smart") == "str"
|
||||
|
||||
assert stringify(List["int"], False) == "List[int]"
|
||||
assert stringify(List["int"], True) == "~typing.List[int]"
|
||||
assert stringify(List["int"]) == "List[int]"
|
||||
assert stringify(List["int"], "smart") == "~typing.List[int]"
|
||||
|
||||
assert stringify("Tuple[str]", False) == "Tuple[str]"
|
||||
assert stringify("Tuple[str]", True) == "Tuple[str]"
|
||||
assert stringify("Tuple[str]") == "Tuple[str]"
|
||||
assert stringify("Tuple[str]", "smart") == "Tuple[str]"
|
||||
|
||||
assert stringify("unknown", False) == "unknown"
|
||||
assert stringify("unknown", True) == "unknown"
|
||||
assert stringify("unknown") == "unknown"
|
||||
assert stringify("unknown", "smart") == "unknown"
|
||||
|
||||
|
||||
def test_stringify_type_hints_Callable():
|
||||
assert stringify(Callable, False) == "Callable"
|
||||
assert stringify(Callable, True) == "~typing.Callable"
|
||||
assert stringify(Callable) == "Callable"
|
||||
assert stringify(Callable, "fully-qualified") == "typing.Callable"
|
||||
assert stringify(Callable, "smart") == "~typing.Callable"
|
||||
|
||||
if sys.version_info >= (3, 7):
|
||||
assert stringify(Callable[[str], int], False) == "Callable[[str], int]"
|
||||
assert stringify(Callable[[str], int], True) == "~typing.Callable[[str], int]"
|
||||
assert stringify(Callable[[str], int]) == "Callable[[str], int]"
|
||||
assert stringify(Callable[[str], int], "fully-qualified") == "typing.Callable[[str], int]"
|
||||
assert stringify(Callable[[str], int], "smart") == "~typing.Callable[[str], int]"
|
||||
|
||||
assert stringify(Callable[..., int], False) == "Callable[[...], int]"
|
||||
assert stringify(Callable[..., int], True) == "~typing.Callable[[...], int]"
|
||||
assert stringify(Callable[..., int]) == "Callable[[...], int]"
|
||||
assert stringify(Callable[..., int], "fully-qualified") == "typing.Callable[[...], int]"
|
||||
assert stringify(Callable[..., int], "smart") == "~typing.Callable[[...], int]"
|
||||
else:
|
||||
assert stringify(Callable[[str], int], False) == "Callable[str, int]"
|
||||
assert stringify(Callable[[str], int], True) == "~typing.Callable[str, int]"
|
||||
assert stringify(Callable[[str], int]) == "Callable[str, int]"
|
||||
assert stringify(Callable[[str], int], "fully-qualified") == "typing.Callable[str, int]"
|
||||
assert stringify(Callable[[str], int], "smart") == "~typing.Callable[str, int]"
|
||||
|
||||
assert stringify(Callable[..., int], False) == "Callable[..., int]"
|
||||
assert stringify(Callable[..., int], True) == "~typing.Callable[..., int]"
|
||||
assert stringify(Callable[..., int]) == "Callable[..., int]"
|
||||
assert stringify(Callable[..., int], "fully-qualified") == "typing.Callable[..., int]"
|
||||
assert stringify(Callable[..., int], "smart") == "~typing.Callable[..., int]"
|
||||
|
||||
|
||||
def test_stringify_type_hints_Union():
|
||||
assert stringify(Optional[int], False) == "Optional[int]"
|
||||
assert stringify(Optional[int], True) == "~typing.Optional[int]"
|
||||
assert stringify(Optional[int]) == "Optional[int]"
|
||||
assert stringify(Optional[int], "fully-qualified") == "typing.Optional[int]"
|
||||
assert stringify(Optional[int], "smart") == "~typing.Optional[int]"
|
||||
|
||||
assert stringify(Union[str, None], False) == "Optional[str]"
|
||||
assert stringify(Union[str, None], True) == "~typing.Optional[str]"
|
||||
assert stringify(Union[str, None]) == "Optional[str]"
|
||||
assert stringify(Union[str, None], "fully-qualified") == "typing.Optional[str]"
|
||||
assert stringify(Union[str, None], "smart") == "~typing.Optional[str]"
|
||||
|
||||
assert stringify(Union[int, str], False) == "Union[int, str]"
|
||||
assert stringify(Union[int, str], True) == "~typing.Union[int, str]"
|
||||
assert stringify(Union[int, str]) == "Union[int, str]"
|
||||
assert stringify(Union[int, str], "fully-qualified") == "typing.Union[int, str]"
|
||||
assert stringify(Union[int, str], "smart") == "~typing.Union[int, str]"
|
||||
|
||||
if sys.version_info >= (3, 7):
|
||||
assert stringify(Union[int, Integral], False) == "Union[int, numbers.Integral]"
|
||||
assert stringify(Union[int, Integral], True) == "~typing.Union[int, ~numbers.Integral]"
|
||||
assert stringify(Union[int, Integral]) == "Union[int, numbers.Integral]"
|
||||
assert stringify(Union[int, Integral], "fully-qualified") == "typing.Union[int, numbers.Integral]"
|
||||
assert stringify(Union[int, Integral], "smart") == "~typing.Union[int, ~numbers.Integral]"
|
||||
|
||||
assert (stringify(Union[MyClass1, MyClass2], False) ==
|
||||
assert (stringify(Union[MyClass1, MyClass2]) ==
|
||||
"Union[tests.test_util_typing.MyClass1, tests.test_util_typing.<MyClass2>]")
|
||||
assert (stringify(Union[MyClass1, MyClass2], True) ==
|
||||
assert (stringify(Union[MyClass1, MyClass2], "fully-qualified") ==
|
||||
"typing.Union[tests.test_util_typing.MyClass1, tests.test_util_typing.<MyClass2>]")
|
||||
assert (stringify(Union[MyClass1, MyClass2], "smart") ==
|
||||
"~typing.Union[~tests.test_util_typing.MyClass1, ~tests.test_util_typing.<MyClass2>]")
|
||||
else:
|
||||
assert stringify(Union[int, Integral], False) == "numbers.Integral"
|
||||
assert stringify(Union[int, Integral], True) == "~numbers.Integral"
|
||||
assert stringify(Union[int, Integral]) == "numbers.Integral"
|
||||
assert stringify(Union[int, Integral], "fully-qualified") == "numbers.Integral"
|
||||
assert stringify(Union[int, Integral], "smart") == "~numbers.Integral"
|
||||
|
||||
assert stringify(Union[MyClass1, MyClass2], False) == "tests.test_util_typing.MyClass1"
|
||||
assert stringify(Union[MyClass1, MyClass2], True) == "~tests.test_util_typing.MyClass1"
|
||||
assert stringify(Union[MyClass1, MyClass2]) == "tests.test_util_typing.MyClass1"
|
||||
assert stringify(Union[MyClass1, MyClass2], "fully-qualified") == "tests.test_util_typing.MyClass1"
|
||||
assert stringify(Union[MyClass1, MyClass2], "smart") == "~tests.test_util_typing.MyClass1"
|
||||
|
||||
|
||||
def test_stringify_type_hints_typevars():
|
||||
@@ -336,83 +361,84 @@ def test_stringify_type_hints_typevars():
|
||||
T_contra = TypeVar('T_contra', contravariant=True)
|
||||
|
||||
if sys.version_info < (3, 7):
|
||||
assert stringify(T, False) == "T"
|
||||
assert stringify(T, True) == "T"
|
||||
assert stringify(T) == "T"
|
||||
assert stringify(T, "smart") == "T"
|
||||
|
||||
assert stringify(T_co, False) == "T_co"
|
||||
assert stringify(T_co, True) == "T_co"
|
||||
assert stringify(T_co) == "T_co"
|
||||
assert stringify(T_co, "smart") == "T_co"
|
||||
|
||||
assert stringify(T_contra, False) == "T_contra"
|
||||
assert stringify(T_contra, True) == "T_contra"
|
||||
assert stringify(T_contra) == "T_contra"
|
||||
assert stringify(T_contra, "smart") == "T_contra"
|
||||
|
||||
assert stringify(List[T], False) == "List[T]"
|
||||
assert stringify(List[T], True) == "~typing.List[T]"
|
||||
assert stringify(List[T]) == "List[T]"
|
||||
assert stringify(List[T], "smart") == "~typing.List[T]"
|
||||
else:
|
||||
assert stringify(T, False) == "tests.test_util_typing.T"
|
||||
assert stringify(T, True) == "~tests.test_util_typing.T"
|
||||
assert stringify(T) == "tests.test_util_typing.T"
|
||||
assert stringify(T, "smart") == "~tests.test_util_typing.T"
|
||||
|
||||
assert stringify(T_co, False) == "tests.test_util_typing.T_co"
|
||||
assert stringify(T_co, True) == "~tests.test_util_typing.T_co"
|
||||
assert stringify(T_co) == "tests.test_util_typing.T_co"
|
||||
assert stringify(T_co, "smart") == "~tests.test_util_typing.T_co"
|
||||
|
||||
assert stringify(T_contra, False) == "tests.test_util_typing.T_contra"
|
||||
assert stringify(T_contra, True) == "~tests.test_util_typing.T_contra"
|
||||
assert stringify(T_contra) == "tests.test_util_typing.T_contra"
|
||||
assert stringify(T_contra, "smart") == "~tests.test_util_typing.T_contra"
|
||||
|
||||
assert stringify(List[T], False) == "List[tests.test_util_typing.T]"
|
||||
assert stringify(List[T], True) == "~typing.List[~tests.test_util_typing.T]"
|
||||
assert stringify(List[T]) == "List[tests.test_util_typing.T]"
|
||||
assert stringify(List[T], "smart") == "~typing.List[~tests.test_util_typing.T]"
|
||||
|
||||
if sys.version_info >= (3, 10):
|
||||
assert stringify(MyInt, False) == "tests.test_util_typing.MyInt"
|
||||
assert stringify(MyInt, True) == "~tests.test_util_typing.MyInt"
|
||||
assert stringify(MyInt) == "tests.test_util_typing.MyInt"
|
||||
assert stringify(MyInt, "smart") == "~tests.test_util_typing.MyInt"
|
||||
else:
|
||||
assert stringify(MyInt, False) == "MyInt"
|
||||
assert stringify(MyInt, True) == "MyInt"
|
||||
assert stringify(MyInt) == "MyInt"
|
||||
assert stringify(MyInt, "smart") == "MyInt"
|
||||
|
||||
|
||||
def test_stringify_type_hints_custom_class():
|
||||
assert stringify(MyClass1, False) == "tests.test_util_typing.MyClass1"
|
||||
assert stringify(MyClass1, True) == "~tests.test_util_typing.MyClass1"
|
||||
assert stringify(MyClass1) == "tests.test_util_typing.MyClass1"
|
||||
assert stringify(MyClass1, "smart") == "~tests.test_util_typing.MyClass1"
|
||||
|
||||
assert stringify(MyClass2, False) == "tests.test_util_typing.<MyClass2>"
|
||||
assert stringify(MyClass2, True) == "~tests.test_util_typing.<MyClass2>"
|
||||
assert stringify(MyClass2) == "tests.test_util_typing.<MyClass2>"
|
||||
assert stringify(MyClass2, "smart") == "~tests.test_util_typing.<MyClass2>"
|
||||
|
||||
|
||||
def test_stringify_type_hints_alias():
|
||||
MyStr = str
|
||||
MyTuple = Tuple[str, str]
|
||||
|
||||
assert stringify(MyStr, False) == "str"
|
||||
assert stringify(MyStr, True) == "str"
|
||||
assert stringify(MyStr) == "str"
|
||||
assert stringify(MyStr, "smart") == "str"
|
||||
|
||||
assert stringify(MyTuple, False) == "Tuple[str, str]" # type: ignore
|
||||
assert stringify(MyTuple, True) == "~typing.Tuple[str, str]" # type: ignore
|
||||
assert stringify(MyTuple) == "Tuple[str, str]" # type: ignore
|
||||
assert stringify(MyTuple, "smart") == "~typing.Tuple[str, str]" # type: ignore
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 8), reason='python 3.8+ is required.')
|
||||
def test_stringify_type_Literal():
|
||||
from typing import Literal # type: ignore
|
||||
assert stringify(Literal[1, "2", "\r"], False) == "Literal[1, '2', '\\r']"
|
||||
assert stringify(Literal[1, "2", "\r"], True) == "~typing.Literal[1, '2', '\\r']"
|
||||
assert stringify(Literal[1, "2", "\r"]) == "Literal[1, '2', '\\r']"
|
||||
assert stringify(Literal[1, "2", "\r"], "fully-qualified") == "typing.Literal[1, '2', '\\r']"
|
||||
assert stringify(Literal[1, "2", "\r"], "smart") == "~typing.Literal[1, '2', '\\r']"
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 10), reason='python 3.10+ is required.')
|
||||
def test_stringify_type_union_operator():
|
||||
assert stringify(int | None, False) == "int | None" # type: ignore
|
||||
assert stringify(int | None, True) == "int | None" # type: ignore
|
||||
assert stringify(int | None) == "int | None" # type: ignore
|
||||
assert stringify(int | None, "smart") == "int | None" # type: ignore
|
||||
|
||||
assert stringify(int | str, False) == "int | str" # type: ignore
|
||||
assert stringify(int | str, True) == "int | str" # type: ignore
|
||||
assert stringify(int | str) == "int | str" # type: ignore
|
||||
assert stringify(int | str, "smart") == "int | str" # type: ignore
|
||||
|
||||
assert stringify(int | str | None, False) == "int | str | None" # type: ignore
|
||||
assert stringify(int | str | None, True) == "int | str | None" # type: ignore
|
||||
assert stringify(int | str | None) == "int | str | None" # type: ignore
|
||||
assert stringify(int | str | None, "smart") == "int | str | None" # type: ignore
|
||||
|
||||
|
||||
def test_stringify_broken_type_hints():
|
||||
assert stringify(BrokenType, False) == 'tests.test_util_typing.BrokenType'
|
||||
assert stringify(BrokenType, True) == '~tests.test_util_typing.BrokenType'
|
||||
assert stringify(BrokenType) == 'tests.test_util_typing.BrokenType'
|
||||
assert stringify(BrokenType, "smart") == '~tests.test_util_typing.BrokenType'
|
||||
|
||||
|
||||
def test_stringify_mock():
|
||||
with mock(['unknown']):
|
||||
import unknown
|
||||
assert stringify(unknown.secret.Class, False) == 'unknown.secret.Class'
|
||||
assert stringify(unknown.secret.Class, True) == 'unknown.secret.Class'
|
||||
assert stringify(unknown.secret.Class) == 'unknown.secret.Class'
|
||||
assert stringify(unknown.secret.Class, "smart") == 'unknown.secret.Class'
|
||||
|
||||
Reference in New Issue
Block a user