Beispiel #1
0
def restify(cls: Optional[Type],
            mode: str = 'fully-qualified-except-typing') -> str:
    """Convert python class to a reST reference.

    :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.
    """
    from sphinx.ext.autodoc.mock import ismock, ismockmodule  # lazy loading
    from sphinx.util import inspect  # lazy loading

    if mode == 'smart':
        modprefix = '~'
    else:
        modprefix = ''

    try:
        if cls is None or cls is NoneType:
            return ':py:obj:`None`'
        elif cls is Ellipsis:
            return '...'
        elif isinstance(cls, str):
            return cls
        elif ismockmodule(cls):
            return ':py:class:`%s%s`' % (modprefix, cls.__name__)
        elif ismock(cls):
            return ':py:class:`%s%s.%s`' % (modprefix, cls.__module__,
                                            cls.__name__)
        elif is_invalid_builtin_class(cls):
            return ':py:class:`%s%s`' % (modprefix,
                                         INVALID_BUILTIN_CLASSES[cls])
        elif inspect.isNewType(cls):
            if sys.version_info > (3, 10):
                # newtypes have correct module info since Python 3.10+
                return ':py:class:`%s%s.%s`' % (modprefix, cls.__module__,
                                                cls.__name__)
            else:
                return ':py:class:`%s`' % cls.__name__
        elif UnionType and isinstance(cls, UnionType):
            if len(cls.__args__) > 1 and None in cls.__args__:
                args = ' | '.join(restify(a, mode) for a in cls.__args__ if a)
                return 'Optional[%s]' % args
            else:
                return ' | '.join(restify(a, mode) for a in cls.__args__)
        elif cls.__module__ in ('__builtin__', 'builtins'):
            if hasattr(cls, '__args__'):
                return ':py:class:`%s`\\ [%s]' % (
                    cls.__name__,
                    ', '.join(restify(arg, mode) for arg in cls.__args__),
                )
            else:
                return ':py:class:`%s`' % cls.__name__
        else:
            return _restify_py37(cls, mode)
    except (AttributeError, TypeError):
        return inspect.object_description(cls)
Beispiel #2
0
def stringify(annotation: Any, mode: str = 'fully-qualified-except-typing') -> str:
    """Stringify type annotation object.

    :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.ext.autodoc.mock import ismock, ismockmodule  # lazy loading
    from sphinx.util import inspect  # lazy loading

    if mode == 'smart':
        modprefix = '~'
    else:
        modprefix = ''

    if isinstance(annotation, str):
        if annotation.startswith("'") and annotation.endswith("'"):
            # might be a double Forward-ref'ed type.  Go unquoting.
            return annotation[1:-1]
        else:
            return annotation
    elif isinstance(annotation, TypeVar):
        if (annotation.__module__ == 'typing' and
                mode in ('fully-qualified-except-typing', 'smart')):
            return annotation.__name__
        else:
            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 modprefix + '%s.%s' % (annotation.__module__, annotation.__name__)
        else:
            return annotation.__name__
    elif not annotation:
        return repr(annotation)
    elif annotation is NoneType:
        return 'None'
    elif ismockmodule(annotation):
        return modprefix + annotation.__name__
    elif ismock(annotation):
        return modprefix + '%s.%s' % (annotation.__module__, annotation.__name__)
    elif is_invalid_builtin_class(annotation):
        return modprefix + INVALID_BUILTIN_CLASSES[annotation]
    elif str(annotation).startswith('typing.Annotated'):  # for py310+
        pass
    elif (getattr(annotation, '__module__', None) == 'builtins' and
          getattr(annotation, '__qualname__', None)):
        if hasattr(annotation, '__args__'):  # PEP 585 generic
            return repr(annotation)
        else:
            return annotation.__qualname__
    elif annotation is Ellipsis:
        return '...'

    if sys.version_info >= (3, 7):  # py37+
        return _stringify_py37(annotation, mode)
    else:
        return _stringify_py36(annotation, mode)