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:
authorTakeshi KOMIYA <i.tkomiya@gmail.com>2021-12-01 19:42:57 +0300
committerTakeshi KOMIYA <i.tkomiya@gmail.com>2021-12-03 12:05:49 +0300
commit80f79aef919d54fec1fcf6edcda7f5de26e70873 (patch)
treec4af4b6cc7eb2df0524d73920d00c7ef08fc3839 /sphinx/util
parent5eaed2bed753c8f58e702419d997053ddec05d9c (diff)
Add `smartref` parameter to sphinx.util.typing:stringify()
To make the generated function signatures simple, this adds a new parameter `smartref` to sphinx.util.typing:stringify() to suppress the leading module name from typehints.
Diffstat (limited to 'sphinx/util')
-rw-r--r--sphinx/util/typing.py118
1 files changed, 72 insertions, 46 deletions
diff --git a/sphinx/util/typing.py b/sphinx/util/typing.py
index e1972d86d..259384ec7 100644
--- a/sphinx/util/typing.py
+++ b/sphinx/util/typing.py
@@ -299,10 +299,19 @@ def _restify_py36(cls: Optional[Type]) -> str:
return ':py:obj:`%s.%s`' % (cls.__module__, qualname)
-def stringify(annotation: Any) -> str:
- """Stringify type annotation object."""
+def stringify(annotation: Any, smartref: bool = False) -> 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
+ """
from sphinx.util import inspect # lazy loading
+ if smartref:
+ prefix = '~'
+ else:
+ prefix = ''
+
if isinstance(annotation, str):
if annotation.startswith("'") and annotation.endswith("'"):
# might be a double Forward-ref'ed type. Go unquoting.
@@ -313,11 +322,11 @@ def stringify(annotation: Any) -> str:
if annotation.__module__ == 'typing':
return annotation.__name__
else:
- return '.'.join([annotation.__module__, annotation.__name__])
+ return prefix + '.'.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 '%s.%s' % (annotation.__module__, annotation.__name__)
+ return prefix + '%s.%s' % (annotation.__module__, annotation.__name__)
else:
return annotation.__name__
elif not annotation:
@@ -325,7 +334,7 @@ def stringify(annotation: Any) -> str:
elif annotation is NoneType:
return 'None'
elif annotation in INVALID_BUILTIN_CLASSES:
- return INVALID_BUILTIN_CLASSES[annotation]
+ return prefix + INVALID_BUILTIN_CLASSES[annotation]
elif str(annotation).startswith('typing.Annotated'): # for py310+
pass
elif (getattr(annotation, '__module__', None) == 'builtins' and
@@ -338,28 +347,36 @@ def stringify(annotation: Any) -> str:
return '...'
if sys.version_info >= (3, 7): # py37+
- return _stringify_py37(annotation)
+ return _stringify_py37(annotation, smartref)
else:
- return _stringify_py36(annotation)
+ return _stringify_py36(annotation, smartref)
-def _stringify_py37(annotation: Any) -> str:
+def _stringify_py37(annotation: Any, smartref: bool = False) -> str:
"""stringify() for py37+."""
module = getattr(annotation, '__module__', None)
- if module == 'typing':
+ modprefix = ''
+ if module == 'typing' and getattr(annotation, '__forward_arg__', None):
+ qualname = annotation.__forward_arg__
+ elif module == 'typing':
if getattr(annotation, '_name', None):
qualname = annotation._name
elif getattr(annotation, '__qualname__', None):
qualname = annotation.__qualname__
- elif getattr(annotation, '__forward_arg__', None):
- qualname = annotation.__forward_arg__
else:
qualname = stringify(annotation.__origin__) # ex. Union
+
+ if smartref:
+ modprefix = '~%s.' % module
elif hasattr(annotation, '__qualname__'):
- qualname = '%s.%s' % (module, annotation.__qualname__)
+ if smartref:
+ modprefix = '~%s.' % module
+ else:
+ modprefix = '%s.' % module
+ qualname = annotation.__qualname__
elif hasattr(annotation, '__origin__'):
# instantiated generic provided by a user
- qualname = stringify(annotation.__origin__)
+ qualname = stringify(annotation.__origin__, smartref)
elif UnionType and isinstance(annotation, UnionType): # types.Union (for py3.10+)
qualname = 'types.Union'
else:
@@ -374,54 +391,63 @@ def _stringify_py37(annotation: Any) -> 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) for a in annotation.__args__[:-1])
- return 'Optional[Union[%s]]' % args
+ args = ', '.join(stringify(a, smartref) for a in annotation.__args__[:-1])
+ return '%sOptional[%sUnion[%s]]' % (modprefix, modprefix, args)
else:
- return 'Optional[%s]' % stringify(annotation.__args__[0])
+ return '%sOptional[%s]' % (modprefix,
+ stringify(annotation.__args__[0], smartref))
else:
- args = ', '.join(stringify(a) for a in annotation.__args__)
- return 'Union[%s]' % args
+ args = ', '.join(stringify(a, smartref) for a in annotation.__args__)
+ return '%sUnion[%s]' % (modprefix, args)
elif qualname == 'types.Union':
if len(annotation.__args__) > 1 and None in annotation.__args__:
args = ' | '.join(stringify(a) for a in annotation.__args__ if a)
- return 'Optional[%s]' % args
+ return '%sOptional[%s]' % (modprefix, args)
else:
return ' | '.join(stringify(a) for a in annotation.__args__)
elif qualname == 'Callable':
- args = ', '.join(stringify(a) for a in annotation.__args__[:-1])
- returns = stringify(annotation.__args__[-1])
- return '%s[[%s], %s]' % (qualname, args, returns)
+ args = ', '.join(stringify(a, smartref) for a in annotation.__args__[:-1])
+ returns = stringify(annotation.__args__[-1], smartref)
+ return '%s%s[[%s], %s]' % (modprefix, qualname, args, returns)
elif qualname == 'Literal':
args = ', '.join(repr(a) for a in annotation.__args__)
- return '%s[%s]' % (qualname, args)
+ return '%s%s[%s]' % (modprefix, qualname, args)
elif str(annotation).startswith('typing.Annotated'): # for py39+
- return stringify(annotation.__args__[0])
+ return stringify(annotation.__args__[0], smartref)
elif all(is_system_TypeVar(a) for a in annotation.__args__):
# Suppress arguments if all system defined TypeVars (ex. Dict[KT, VT])
- return qualname
+ return modprefix + qualname
else:
- args = ', '.join(stringify(a) for a in annotation.__args__)
- return '%s[%s]' % (qualname, args)
+ args = ', '.join(stringify(a, smartref) for a in annotation.__args__)
+ return '%s%s[%s]' % (modprefix, qualname, args)
- return qualname
+ return modprefix + qualname
-def _stringify_py36(annotation: Any) -> str:
+def _stringify_py36(annotation: Any, smartref: bool = False) -> str:
"""stringify() for py36."""
module = getattr(annotation, '__module__', None)
- if module == 'typing':
+ modprefix = ''
+ if module == 'typing' and getattr(annotation, '__forward_arg__', None):
+ qualname = annotation.__forward_arg__
+ elif module == 'typing':
if getattr(annotation, '_name', None):
qualname = annotation._name
elif getattr(annotation, '__qualname__', None):
qualname = annotation.__qualname__
- elif getattr(annotation, '__forward_arg__', None):
- qualname = annotation.__forward_arg__
elif getattr(annotation, '__origin__', None):
qualname = stringify(annotation.__origin__) # ex. Union
else:
qualname = repr(annotation).replace('typing.', '')
+
+ if smartref:
+ modprefix = '~%s.' % module
elif hasattr(annotation, '__qualname__'):
- qualname = '%s.%s' % (module, annotation.__qualname__)
+ if smartref:
+ modprefix = '~%s.' % module
+ else:
+ modprefix = '%s.' % module
+ qualname = annotation.__qualname__
else:
qualname = repr(annotation)
@@ -429,10 +455,10 @@ def _stringify_py36(annotation: Any) -> str:
not hasattr(annotation, '__tuple_params__')): # for Python 3.6
params = annotation.__args__
if params:
- param_str = ', '.join(stringify(p) for p in params)
- return '%s[%s]' % (qualname, param_str)
+ param_str = ', '.join(stringify(p, smartref) for p in params)
+ return '%s%s[%s]' % (modprefix, qualname, param_str)
else:
- return qualname
+ return modprefix + qualname
elif isinstance(annotation, typing.GenericMeta):
params = None
if annotation.__args__ is None or len(annotation.__args__) <= 2: # type: ignore # NOQA
@@ -440,28 +466,28 @@ def _stringify_py36(annotation: Any) -> str:
elif annotation.__origin__ == Generator: # type: ignore
params = annotation.__args__ # type: ignore
else: # typing.Callable
- args = ', '.join(stringify(arg) for arg
+ args = ', '.join(stringify(arg, smartref) for arg
in annotation.__args__[:-1]) # type: ignore
result = stringify(annotation.__args__[-1]) # type: ignore
- return '%s[[%s], %s]' % (qualname, args, result)
+ return '%s%s[[%s], %s]' % (modprefix, qualname, args, result)
if params is not None:
- param_str = ', '.join(stringify(p) for p in params)
- return '%s[%s]' % (qualname, param_str)
+ param_str = ', '.join(stringify(p, smartref) for p in params)
+ return '%s%s[%s]' % (modprefix, qualname, param_str)
elif (hasattr(annotation, '__origin__') and
annotation.__origin__ is typing.Union):
params = annotation.__args__
if params is not None:
if len(params) > 1 and params[-1] is NoneType:
if len(params) > 2:
- param_str = ", ".join(stringify(p) for p in params[:-1])
- return 'Optional[Union[%s]]' % param_str
+ param_str = ", ".join(stringify(p, smartref) for p in params[:-1])
+ return '%sOptional[%sUnion[%s]]' % (modprefix, modprefix, param_str)
else:
- return 'Optional[%s]' % stringify(params[0])
+ return '%sOptional[%s]' % (modprefix, stringify(params[0]))
else:
- param_str = ', '.join(stringify(p) for p in params)
- return 'Union[%s]' % param_str
+ param_str = ', '.join(stringify(p, smartref) for p in params)
+ return '%sUnion[%s]' % (modprefix, param_str)
- return qualname
+ return modprefix + qualname
deprecated_alias('sphinx.util.typing',