Example #1
0
    def wrap(self, err: UntypyTypeError) -> UntypyTypeError:
        (original_expected, _ind) = err.next_type_and_indicator()
        err = ArgumentExecutionContext(self.wf, None, self.arg_name).wrap(err)

        responsable = WrappedFunction.find_location(self.wf)

        (decl, ind) = err.next_type_and_indicator()
        err = err.with_frame(
            Frame(decl,
                  ind,
                  declared=self.wf.declared(),
                  responsable=responsable))

        err = err.with_note(
            f"The argument '{self.arg_name}' of method '{WrappedFunction.find_original(self.wf).__name__}' violates the {self.wf.protocol.protocol_type()} '{self.wf.protocol.proto.__name__}'."
        )
        err = err.with_note(
            f"The annotation '{original_expected}' is incompatible with the {self.wf.protocol.protocol_type()}'s annotation '{self.wf.checker_for(self.arg_name).describe()}'\nwhen checking against the following value:"
        )

        previous_chain = UntypyTypeError(
            self.me, f"{self.wf.protocol.protoname()}"
        ).with_note(
            f"Type '{type(self.me).__name__}' does not implement {self.wf.protocol.protocol_type()} '{self.wf.protocol.protoname()}' correctly."
        )

        previous_chain = self.ctx.wrap(previous_chain)
        # err = err.with_inverted_responsibility_type()

        return err.with_previous_chain(previous_chain)
Example #2
0
    def wrap(self, err: UntypyTypeError) -> UntypyTypeError:
        err = ReturnExecutionContext(self.wf).wrap(err)

        if err.responsibility_type is self.invert:
            return err

        responsable = WrappedFunction.find_location(self.wf)
        (decl, ind) = err.next_type_and_indicator()
        err = err.with_inverted_responsibility_type()
        err = err.with_frame(
            Frame(decl,
                  ind,
                  declared=self.wf.declared(),
                  responsable=responsable))

        inner = self.wf.inner
        if isinstance(inner, WrappedFunction):
            err = err.with_note(
                f"The return value of method '{WrappedFunction.find_original(self.wf).__name__}' does violate the {self.wf.protocol.protocol_type()} '{self.wf.protocol.proto.__name__}'."
            )
            err = err.with_note(
                f"The annotation '{inner.checker_for('return').describe()}' is incompatible with the {self.wf.protocol.protocol_type()}'s annotation '{self.wf.checker_for('return').describe()}'\nwhen checking against the following value:"
            )

        previous_chain = UntypyTypeError(
            self.me, f"{self.wf.protocol.protoname()}"
        ).with_note(
            f"Type '{type(self.me).__name__}' does not implement {self.wf.protocol.protocol_type()} '{self.wf.protocol.protoname()}' correctly."
        )

        previous_chain = self.ctx.wrap(previous_chain)
        return err.with_previous_chain(previous_chain)
Example #3
0
    def wrap(self, err: UntypyTypeError) -> UntypyTypeError:
        (original_expected, _ind) = err.next_type_and_indicator()
        err = ArgumentExecutionContext(self.wf, None, self.arg_name).wrap(err)

        responsable = WrappedFunction.find_location(self.wf)

        (decl, ind) = err.next_type_and_indicator()
        err = err.with_frame(
            Frame(decl,
                  ind,
                  declared=self.wf.declared(),
                  responsable=responsable))

        err = err.with_note(
            f"Argument {self.arg_name} of method {WrappedFunction.find_original(self.wf).__name__} violates the type declared by the {self.wf.protocol.protocol_type()} {self.wf.protocol.proto.__name__}."
        )
        err = err.with_note(
            f"Annotation {original_expected} is incompatible with the {self.wf.protocol.protocol_type()}'s annotation {self.wf.checker_for(self.arg_name).describe()}."
        )

        previous_chain = UntypyTypeError(
            self.me, f"{self.wf.protocol.protoname()}"
        ).with_header(
            f"{type(self.me).__name__} does not implement {self.wf.protocol.protocol_type()} {self.wf.protocol.protoname()} correctly."
        )

        previous_chain = self.ctx.wrap(previous_chain)
        # err = err.with_inverted_responsibility_type()

        return err.with_previous_chain(previous_chain)
Example #4
0
    def build(self):
        fn = WrappedFunction.find_original(self.inner)

        fn_of_protocol = getattr(self.protocol.proto, fn.__name__)
        if hasattr(fn_of_protocol, '__wf'):
            fn_of_protocol = getattr(fn_of_protocol, '__wf')

        def wrapper(me, *args, **kwargs):
            inner_object = me.__inner
            inner_ctx = me.__ctx

            caller = sys._getframe(1)
            (args, kwargs, bind1) = self.wrap_arguments(
                lambda n: ArgumentExecutionContext(fn_of_protocol, caller, n),
                (inner_object, *args), kwargs)
            if isinstance(self.inner, WrappedFunction):
                (args, kwargs, bind2) = self.inner.wrap_arguments(
                    lambda n: ProtocolArgumentExecutionContext(
                        self, n, inner_object, inner_ctx), args, kwargs)
            ret = fn(*args, **kwargs)
            if isinstance(self.inner, WrappedFunction):
                ret = self.inner.wrap_return(
                    ret, bind2,
                    ProtocolReturnExecutionContext(self, ResponsibilityType.IN,
                                                   inner_object, inner_ctx))
            return self.wrap_return(
                ret, bind1,
                ProtocolReturnExecutionContext(self, ResponsibilityType.OUT,
                                               inner_object, inner_ctx))

        async def async_wrapper(*args, **kwargs):
            raise AssertionError("Not correctly implemented see wrapper")

        if inspect.iscoroutine(self.inner):
            w = async_wrapper
        else:
            w = wrapper

        setattr(w, '__wrapped__', fn)
        setattr(w, '__name__', fn.__name__)
        setattr(w, '__signature__', self.signature)
        setattr(w, '__wf', self)
        return w
Example #5
0
def get_proto_members(
    proto: type, ctx: CreationContext
) -> Dict[str, Tuple[inspect.Signature, dict[str, TypeChecker],
                     FunctionCondition]]:
    blacklist = [
        '__init__', '__class__', '__delattr__', '__dict__', '__dir__',
        '__doc__', '__getattribute__', '__getattr__', '__init_subclass__',
        '__new__', '__setattr__', '__subclasshook__', '__weakref__',
        '__abstractmethods__', '__class_getitem__'
    ]

    member_dict = {}
    for [name, member] in inspect.getmembers(proto):
        if name in blacklist:
            continue

        if inspect.isfunction(member):
            member = WrappedFunction.find_original(member)
            signature = inspect.signature(member)
            annotations = typing.get_type_hints(member, include_extras=True)
            checkers = {}
            for key in signature.parameters:
                if key == 'self':
                    checkers[key] = SelfChecker()
                else:
                    param = signature.parameters[key]
                    if param.annotation is inspect.Parameter.empty:
                        raise ctx.wrap(
                            UntypyAttributeError(
                                f"Missing annotation for argument '{key}' of function {member.__name__} "
                                f"in protocol {proto.__name__}\n"))

                    checker = ctx.find_checker(annotations[key])
                    if checker is None:
                        raise ctx.wrap(
                            UntypyAttributeError(
                                f"\n\tUnsupported type annotation: {param.annotation}\n"
                                f"for argument '{key}' of function {member.__name__} "
                                f"in protocol {proto.__name__}.\n"))
                    checkers[key] = checker

            if signature.return_annotation is inspect.Parameter.empty:
                raise ctx.wrap(
                    UntypyAttributeError(
                        f"Missing annotation for return value of function {member.__name__} "
                        f"in protocol {proto.__name__}. Use 'None' if there is no return value.\n"
                    ))
            return_annotation = annotations['return']
            if return_annotation is proto:  # Self as Return Type would led to endless recursion
                return_checker = SimpleInstanceOfChecker(proto, None)
            else:
                return_checker = ctx.find_checker(return_annotation)

            if return_checker is None:
                raise ctx.wrap(
                    UntypyAttributeError(
                        f"\n\tUnsupported type annotation: {signature.return_annotation}\n"
                        f"for return value of function {member.__name__} "
                        f"in protocol-like {proto.__name__}.\n"))
            fc = None
            if hasattr(member, '__fc'):
                fc = getattr(member, '__fc')
            checkers['return'] = return_checker
            member_dict[name] = (signature, checkers, fc)
    return member_dict
Example #6
0
 def declared(self) -> Location:
     fn = WrappedFunction.find_original(self.inner)
     return WrappedFunction.find_location(
         getattr(self.protocol.proto, fn.__name__))
Example #7
0
 def describe(self) -> str:
     fn = WrappedFunction.find_original(self.inner)
     return f"{fn.__name__}" + str(self.signature)