示例#1
0
        def decorator(
            callback: event_manager_.CallbackT[event_manager_.EventT_co],
        ) -> event_manager_.CallbackT[event_manager_.EventT_co]:
            nonlocal event_type

            # Avoid resolving forward references in the function's signature if
            # event_type was explicitly provided as this may lead to errors.
            if event_type is not None:
                _assert_is_listener(
                    iter(inspect.signature(callback).parameters.values()))

            else:
                signature = reflect.resolve_signature(callback)
                params = signature.parameters.values()
                _assert_is_listener(iter(params))
                event_param = next(iter(params))

                if event_param.annotation is event_param.empty:
                    raise TypeError(
                        "Must provide the event type in the @listen decorator or as a type hint!"
                    )

                event_type = event_param.annotation

            self.subscribe(event_type, callback, _nested=1)
            return callback
示例#2
0
        def decorator(
            callback: event_manager.CallbackT[event_manager.EventT_co],
        ) -> event_manager.CallbackT[event_manager.EventT_co]:
            nonlocal event_type

            signature = reflect.resolve_signature(callback)
            params = signature.parameters.values()

            if len(params) != 1:
                raise TypeError(
                    "Event listener must have exactly one parameter, the event object."
                )

            event_param = next(iter(params))

            if event_type is None:
                if event_param.annotation is event_param.empty:
                    raise TypeError(
                        "Must provide the event type in the @listen decorator or as a type hint!"
                    )

                event_type = event_param.annotation

            self.subscribe(event_type, callback, _nested=1)
            return callback
示例#3
0
    def test_handles_NoneType(self):
        def foo(bar: type(None)) -> type(None):
            ...

        signature = reflect.resolve_signature(foo)
        assert signature.parameters["bar"].annotation is None
        assert signature.return_annotation is None
示例#4
0
        def decorator(
            callback: event_manager_.CallbackT[base_events.EventT],
        ) -> event_manager_.CallbackT[base_events.EventT]:
            # Avoid resolving forward references in the function's signature if
            # event_type was explicitly provided as this may lead to errors.
            if event_types:
                _assert_is_listener(iter(inspect.signature(callback).parameters.values()))
                resolved_types = event_types

            else:
                signature = reflect.resolve_signature(callback)
                params = signature.parameters.values()
                _assert_is_listener(iter(params))
                event_param = next(iter(params))
                annotation = event_param.annotation

                if annotation is event_param.empty:
                    raise TypeError("Must provide the event type in the @listen decorator or as a type hint!")

                if typing.get_origin(annotation) in _UNIONS:
                    # Resolve the types inside the union
                    resolved_types = typing.get_args(annotation)
                else:
                    # Just pass back the annotation
                    resolved_types = (annotation,)

            for resolved_type in resolved_types:
                self.subscribe(resolved_type, callback, _nested=1)

            return callback
示例#5
0
    def test_handles_nested_annotations(self):
        def foo(bar: typing.Optional[typing.Iterator[int]]):
            ...

        signature = reflect.resolve_signature(foo)
        assert signature.parameters["bar"].annotation == typing.Optional[
            typing.Iterator[int]]
示例#6
0
    def test_handles_mixed_annotations(self):
        def foo(bar: str, bat: "int"):
            ...

        signature = reflect.resolve_signature(foo)
        assert signature.parameters["bar"].annotation is str
        assert signature.parameters["bat"].annotation is int
        assert signature.return_annotation is reflect.EMPTY
示例#7
0
    def test_handles_forward_annotations(self):
        def foo(bar: "str", bat: "int") -> "str":
            ...

        signature = reflect.resolve_signature(foo)
        assert signature.parameters["bar"].annotation is str
        assert signature.parameters["bat"].annotation is int
        assert signature.return_annotation is str
示例#8
0
    def test_handles_normal_no_annotations(self):
        def foo(bar, bat):
            ...

        signature = reflect.resolve_signature(foo)
        assert signature.parameters["bar"].annotation is reflect.EMPTY
        assert signature.parameters["bat"].annotation is reflect.EMPTY
        assert signature.return_annotation is reflect.EMPTY
示例#9
0
    def test_handles_normal_references(self):
        def foo(bar: str, bat: int) -> str:
            ...

        signature = reflect.resolve_signature(foo)
        assert signature.parameters["bar"].annotation is str
        assert signature.parameters["bat"].annotation is int
        assert signature.return_annotation is str
示例#10
0
def test_resolve_signature():
    foo = object()

    with mock.patch.object(inspect, "signature") as signature:
        sig = reflect.resolve_signature(foo)

    assert sig is signature.return_value
    signature.assert_called_once_with(foo, eval_str=True)
示例#11
0
    def test_handles_only_return_annotated(self):
        def foo(bar, bat) -> str:
            ...

        signature = reflect.resolve_signature(foo)
        assert signature.parameters["bar"].annotation is reflect.EMPTY
        assert signature.parameters["bat"].annotation is reflect.EMPTY
        assert signature.return_annotation is str