Esempio n. 1
0
def test_signature_annotations_py38(app):
    from target.pep570 import foo, bar, baz, qux

    # case: separator at head
    sig = inspect.signature(foo)
    assert stringify_signature(sig) == '(*, a, b)'

    # case: separator in the middle
    sig = inspect.signature(bar)
    assert stringify_signature(sig) == '(a, b, /, c, d)'

    sig = inspect.signature(baz)
    assert stringify_signature(sig) == '(a, /, *, b)'

    # case: separator at tail
    sig = inspect.signature(qux)
    assert stringify_signature(sig) == '(a, b, /)'
Esempio n. 2
0
def test_signature_partial():
    def fun(a, b, c=1, d=2):
        pass

    p = functools.partial(fun, 10, c=11)

    sig = inspect.signature(p)
    assert stringify_signature(sig) == '(b, *, c=11, d=2)'
Esempio n. 3
0
def process_fnop_signature(app, what, name, obj, options, signature, return_annotation):
    try:
        if isinstance(obj, FnOp):
            fn = obj.fn
            fn_sig = inspect.signature(fn)
            signature = str(fn_sig)
            return_annotation = None
    except Exception as ex:
        log.error("Failed `autodoc-process-signature`: %s", ex, exc_info=1)
    return (signature, return_annotation)
def process_signature(app, what: str, name: str, obj, options, sign,
                      return_annotation):
    if not callable(obj):
        return

    original_obj = obj
    if inspect.isclass(obj):
        obj = getattr(obj, '__init__', getattr(obj, '__new__', None))

    if isinstance(obj, tomate.filegroup.scanner.ScannerCS):
        obj = obj.func

    if not getattr(obj, '__annotations__', None):
        return

    obj = inspect.unwrap(obj)
    sign = signature(obj)
    parameters = [
        param.replace(annotation=inspect.Parameter.empty)
        for param in sign.parameters.values()
    ]

    if '<locals>' in obj.__qualname__:
        logger.warning(
            'Cannot treat a function defined as a local function: "%s"  (use @functools.wraps)',
            name)
        return

    if parameters:
        if inspect.isclass(original_obj):
            del parameters[0]
        elif what == 'method':
            outer = inspect.getmodule(obj)
            for clsname in obj.__qualname__.split('.')[:-1]:
                outer = getattr(outer, clsname)

            method_name = obj.__name__
            if method_name.startswith("__") and not method_name.endswith("__"):
                # If the method starts with double underscore (dunder)
                # Python applies mangling so we need to prepend the class name.
                # This doesn't happen if it always ends with double underscore.
                class_name = obj.__qualname__.split('.')[-2]
                method_name = "_{c}{m}".format(c=class_name, m=method_name)

            method_object = outer.__dict__[method_name] if outer else obj
            if not isinstance(method_object, (classmethod, staticmethod)):
                del parameters[0]

    sign = sign.replace(parameters=parameters,
                        return_annotation=inspect.Signature.empty)

    return stringify_signature(sign).replace('\\', '\\\\'), None
Esempio n. 5
0
def test_signature_partialmethod():
    from functools import partialmethod

    class Foo:
        def meth1(self, arg1, arg2, arg3=None, arg4=None):
            pass

        def meth2(self, arg1, arg2):
            pass

        foo = partialmethod(meth1, 1, 2)
        bar = partialmethod(meth1, 1, arg3=3)
        baz = partialmethod(meth2, 1, 2)

    subject = Foo()
    sig = inspect.signature(subject.foo)
    assert stringify_signature(sig) == '(arg3=None, arg4=None)'

    sig = inspect.signature(subject.bar)
    assert stringify_signature(sig) == '(arg2, *, arg3=3, arg4=None)'

    sig = inspect.signature(subject.baz)
    assert stringify_signature(sig) == '()'
Esempio n. 6
0
def record_typehints(app: Sphinx, objtype: str, name: str, obj: Any,
                     options: Dict, args: str, retann: str) -> None:
    """Record type hints to env object."""
    try:
        if callable(obj):
            annotations = app.env.temp_data.setdefault('annotations', {})
            annotation = annotations.setdefault(name, OrderedDict())
            sig = inspect.signature(obj)
            for param in sig.parameters.values():
                if param.annotation is not param.empty:
                    annotation[param.name] = typing.stringify(param.annotation)
            if sig.return_annotation is not sig.empty:
                annotation['return'] = typing.stringify(sig.return_annotation)
    except TypeError:
        pass
Esempio n. 7
0
def test_signature():
    # literals
    with pytest.raises(TypeError):
        inspect.signature(1)

    with pytest.raises(TypeError):
        inspect.signature('')

    # builitin classes
    with pytest.raises(TypeError):
        inspect.signature(int)

    with pytest.raises(TypeError):
        inspect.signature(str)

    # normal function
    def func(a, b, c=1, d=2, *e, **f):
        pass

    sig = inspect.stringify_signature(inspect.signature(func))
    assert sig == '(a, b, c=1, d=2, *e, **f)'
Esempio n. 8
0
def test_signature_methods():
    class Foo:
        def meth1(self, arg1, **kwargs):
            pass

        @classmethod
        def meth2(cls, arg1, *args, **kwargs):
            pass

        @staticmethod
        def meth3(arg1, *args, **kwargs):
            pass

    @functools.wraps(Foo().meth1)
    def wrapped_bound_method(*args, **kwargs):
        pass

    # unbound method
    sig = inspect.signature(Foo.meth1)
    assert stringify_signature(sig) == '(self, arg1, **kwargs)'

    sig = inspect.signature(Foo.meth1, bound_method=True)
    assert stringify_signature(sig) == '(arg1, **kwargs)'

    # bound method
    sig = inspect.signature(Foo().meth1)
    assert stringify_signature(sig) == '(arg1, **kwargs)'

    # class method
    sig = inspect.signature(Foo.meth2)
    assert stringify_signature(sig) == '(arg1, *args, **kwargs)'

    sig = inspect.signature(Foo().meth2)
    assert stringify_signature(sig) == '(arg1, *args, **kwargs)'

    # static method
    sig = inspect.signature(Foo.meth3)
    assert stringify_signature(sig) == '(arg1, *args, **kwargs)'

    sig = inspect.signature(Foo().meth3)
    assert stringify_signature(sig) == '(arg1, *args, **kwargs)'

    # wrapped bound method
    sig = inspect.signature(wrapped_bound_method)
    assert stringify_signature(sig) == '(arg1, **kwargs)'
Esempio n. 9
0
def update_annotations_using_type_comments(app: Sphinx, obj: Any, bound_method: bool) -> None:
    """Update annotations info of *obj* using type_comments."""
    try:
        function = get_type_comment(obj)
        if function and hasattr(function, 'argtypes'):
            if function.argtypes != [ast.Ellipsis]:  # type: ignore
                sig = inspect.signature(obj, bound_method)
                for i, param in enumerate(sig.parameters.values()):
                    if param.name not in obj.__annotations__:
                        annotation = ast_unparse(function.argtypes[i])  # type: ignore
                        obj.__annotations__[param.name] = annotation

            if 'return' not in obj.__annotations__:
                obj.__annotations__['return'] = ast_unparse(function.returns)  # type: ignore
    except NotImplementedError as exc:  # failed to ast.unparse()
        logger.warning("Failed to parse type_comment for %r: %s", obj, exc)
Esempio n. 10
0
def update_annotations_using_type_comments(app: Sphinx, obj: Any,
                                           bound_method: bool) -> None:
    """Update annotations info of *obj* using type_comments."""
    try:
        type_sig = get_type_comment(obj, bound_method)
        if type_sig:
            sig = inspect.signature(obj, bound_method)
            for param in sig.parameters.values():
                if param.name not in obj.__annotations__:
                    annotation = type_sig.parameters[param.name].annotation
                    if annotation is not Parameter.empty:
                        obj.__annotations__[param.name] = ast_unparse(
                            annotation)

            if 'return' not in obj.__annotations__:
                obj.__annotations__['return'] = type_sig.return_annotation
    except NotImplementedError as exc:  # failed to ast.unparse()
        logger.warning("Failed to parse type_comment for %r: %s", obj, exc)
Esempio n. 11
0
def record_typehints(app: Sphinx, objtype: str, name: str, obj: Any,
                     options: Dict, args: str, retann: str) -> None:
    """Record type hints to env object."""
    if app.config.autodoc_typehints_format == 'short':
        mode = 'smart'
    else:
        mode = 'fully-qualified'

    try:
        if callable(obj):
            annotations = app.env.temp_data.setdefault('annotations', {})
            annotation = annotations.setdefault(name, OrderedDict())
            sig = inspect.signature(obj, type_aliases=app.config.autodoc_type_aliases)
            for param in sig.parameters.values():
                if param.annotation is not param.empty:
                    annotation[param.name] = typing.stringify(param.annotation, mode)
            if sig.return_annotation is not sig.empty:
                annotation['return'] = typing.stringify(sig.return_annotation, mode)
    except (TypeError, ValueError):
        pass
Esempio n. 12
0
def test_signature():
    # literals
    with pytest.raises(TypeError):
        inspect.signature(1)

    with pytest.raises(TypeError):
        inspect.signature('')

    # builtins are supported on a case-by-case basis, depending on whether
    # they define __text_signature__
    if getattr(list, '__text_signature__', None):
        sig = inspect.stringify_signature(inspect.signature(list))
        assert sig == '(iterable=(), /)'
    else:
        with pytest.raises(ValueError):
            inspect.signature(list)

    # normal function
    def func(a, b, c=1, d=2, *e, **f):
        pass

    sig = inspect.stringify_signature(inspect.signature(func))
    assert sig == '(a, b, c=1, d=2, *e, **f)'
Esempio n. 13
0
def test_signature_annotations():
    from .typing_test_data import (Node, f0, f1, f2, f3, f4, f5, f6, f7, f8,
                                   f9, f10, f11, f12, f13, f14, f15, f16, f17,
                                   f18, f19, f20, f21)

    # Class annotations
    sig = inspect.signature(f0)
    assert stringify_signature(sig) == '(x: int, y: numbers.Integral) -> None'

    # Generic types with concrete parameters
    sig = inspect.signature(f1)
    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: typing.List[typing.T],'
            ' y: typing.List[typing.T_co],'
            ' z: typing.T'
            ') -> typing.List[typing.T_contra]')
    else:
        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'
            ') -> typing.List[tests.typing_test_data.T_contra]')

    # Union types
    sig = inspect.signature(f3)
    assert stringify_signature(
        sig) == '(x: typing.Union[str, numbers.Integral]) -> None'

    # Quoted annotations
    sig = inspect.signature(f4)
    assert stringify_signature(sig) == '(x: str, y: str) -> None'

    # Keyword-only arguments
    sig = inspect.signature(f5)
    assert stringify_signature(sig) == '(x: int, *, y: str, z: str) -> None'

    # Keyword-only arguments with varargs
    sig = inspect.signature(f6)
    assert stringify_signature(
        sig) == '(x: int, *args, y: str, z: str) -> None'

    # Space around '=' for defaults
    sig = inspect.signature(f7)
    if sys.version_info < (3, 11):
        assert stringify_signature(
            sig) == '(x: typing.Optional[int] = None, y: dict = {}) -> None'
    else:
        assert stringify_signature(
            sig) == '(x: int = None, y: dict = {}) -> None'

    # Callable types
    sig = inspect.signature(f8)
    assert stringify_signature(
        sig) == '(x: typing.Callable[[int, str], int]) -> None'

    sig = inspect.signature(f9)
    assert stringify_signature(sig) == '(x: typing.Callable) -> None'

    # Tuple types
    sig = inspect.signature(f10)
    assert stringify_signature(
        sig
    ) == '(x: typing.Tuple[int, str], y: typing.Tuple[int, ...]) -> None'

    # Instance annotations
    sig = inspect.signature(f11)
    assert stringify_signature(sig) == '(x: CustomAnnotation, y: 123) -> None'

    # tuple with more than two items
    sig = inspect.signature(f12)
    assert stringify_signature(sig) == '() -> typing.Tuple[int, str, int]'

    # optional
    sig = inspect.signature(f13)
    assert stringify_signature(sig) == '() -> typing.Optional[str]'

    # optional union
    sig = inspect.signature(f20)
    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) == '() -> typing.Any'

    # ForwardRef
    sig = inspect.signature(f15)
    assert stringify_signature(sig) == '(x: Unknown, y: int) -> typing.Any'

    # keyword only arguments (1)
    sig = inspect.signature(f16)
    assert stringify_signature(sig) == '(arg1, arg2, *, arg3=None, arg4=None)'

    # keyword only arguments (2)
    sig = inspect.signature(f17)
    assert stringify_signature(sig) == '(*, arg3, arg4)'

    sig = inspect.signature(f18)
    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)
    assert stringify_signature(sig) == '(*args: int, **kwargs: str)'

    # default value is inspect.Signature.empty
    sig = inspect.signature(f21)
    assert stringify_signature(sig) == "(arg1='whatever', arg2)"

    # type hints by string
    sig = inspect.signature(Node.children)
    assert stringify_signature(
        sig) == '(self) -> typing.List[tests.typing_test_data.Node]'

    sig = inspect.signature(Node.__init__)
    assert stringify_signature(
        sig
    ) == '(self, parent: typing.Optional[tests.typing_test_data.Node]) -> None'

    # show_annotation is False
    sig = inspect.signature(f7)
    assert stringify_signature(sig, show_annotation=False) == '(x=None, y={})'

    # show_return_annotation is False
    sig = inspect.signature(f7)
    if sys.version_info < (3, 11):
        assert stringify_signature(
            sig, show_return_annotation=False
        ) == '(x: typing.Optional[int] = None, y: dict = {})'
    else:
        assert stringify_signature(
            sig,
            show_return_annotation=False) == '(x: int = None, y: dict = {})'

    # unqualified_typehints is True
    sig = inspect.signature(f7)
    if sys.version_info < (3, 11):
        assert stringify_signature(
            sig, unqualified_typehints=True
        ) == '(x: ~typing.Optional[int] = None, y: dict = {}) -> None'
    else:
        assert stringify_signature(sig, unqualified_typehints=True
                                   ) == '(x: int = None, y: dict = {}) -> None'
Esempio n. 14
0
def test_signature_annotations():
    from typing_test_data import (f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10,
                                  f11, f12, f13, f14, f15, f16, f17, f18, f19, Node)

    # Class annotations
    sig = inspect.signature(f0)
    assert stringify_signature(sig) == '(x: int, y: numbers.Integral) -> None'

    # Generic types with concrete parameters
    sig = inspect.signature(f1)
    assert stringify_signature(sig) == '(x: List[int]) -> List[int]'

    # TypeVars and generic types with TypeVars
    sig = inspect.signature(f2)
    assert stringify_signature(sig) == '(x: List[T], y: List[T_co], z: T) -> List[T_contra]'

    # Union types
    sig = inspect.signature(f3)
    assert stringify_signature(sig) == '(x: Union[str, numbers.Integral]) -> None'

    # Quoted annotations
    sig = inspect.signature(f4)
    assert stringify_signature(sig) == '(x: str, y: str) -> None'

    # Keyword-only arguments
    sig = inspect.signature(f5)
    assert stringify_signature(sig) == '(x: int, *, y: str, z: str) -> None'

    # Keyword-only arguments with varargs
    sig = inspect.signature(f6)
    assert stringify_signature(sig) == '(x: int, *args, y: str, z: str) -> None'

    # Space around '=' for defaults
    sig = inspect.signature(f7)
    assert stringify_signature(sig) == '(x: int = None, y: dict = {}) -> None'

    # Callable types
    sig = inspect.signature(f8)
    assert stringify_signature(sig) == '(x: Callable[[int, str], int]) -> None'

    sig = inspect.signature(f9)
    assert stringify_signature(sig) == '(x: Callable) -> None'

    # Tuple types
    sig = inspect.signature(f10)
    assert stringify_signature(sig) == '(x: Tuple[int, str], y: Tuple[int, ...]) -> None'

    # Instance annotations
    sig = inspect.signature(f11)
    assert stringify_signature(sig) == '(x: CustomAnnotation, y: 123) -> None'

    # tuple with more than two items
    sig = inspect.signature(f12)
    assert stringify_signature(sig) == '() -> Tuple[int, str, int]'

    # optional
    sig = inspect.signature(f13)
    assert stringify_signature(sig) == '() -> Optional[str]'

    # Any
    sig = inspect.signature(f14)
    assert stringify_signature(sig) == '() -> Any'

    # ForwardRef
    sig = inspect.signature(f15)
    assert stringify_signature(sig) == '(x: Unknown, y: int) -> Any'

    # keyword only arguments (1)
    sig = inspect.signature(f16)
    assert stringify_signature(sig) == '(arg1, arg2, *, arg3=None, arg4=None)'

    # keyword only arguments (2)
    sig = inspect.signature(f17)
    assert stringify_signature(sig) == '(*, arg3, arg4)'

    sig = inspect.signature(f18)
    assert stringify_signature(sig) == '(self, arg1: Union[int, Tuple] = 10) -> List[Dict]'

    # annotations for variadic and keyword parameters
    sig = inspect.signature(f19)
    assert stringify_signature(sig) == '(*args: int, **kwargs: str)'

    # type hints by string
    sig = inspect.signature(Node.children)
    if (3, 5, 0) <= sys.version_info < (3, 5, 3):
        assert stringify_signature(sig) == '(self) -> List[Node]'
    else:
        assert stringify_signature(sig) == '(self) -> List[typing_test_data.Node]'

    sig = inspect.signature(Node.__init__)
    assert stringify_signature(sig) == '(self, parent: Optional[Node]) -> None'

    # show_annotation is False
    sig = inspect.signature(f7)
    assert stringify_signature(sig, show_annotation=False) == '(x=None, y={})'

    # show_return_annotation is False
    sig = inspect.signature(f7)
    assert stringify_signature(sig, show_return_annotation=False) == '(x: int = None, y: dict = {})'
Esempio n. 15
0
 def process_signature(obj):
     sig = signature(obj)
     return stringify_signature(sig)