def prehook(self, boundargs, ctx: WrappedFunctionContextProvider):
        for p in self.precondition:
            bindings = {}
            for name in inspect.signature(p).parameters:
                if name in boundargs.arguments:
                    bindings[name] = boundargs.arguments[name]
                else:
                    raise UntypyAttributeError(
                        f"Did not find argument {name} of precondition in function.",
                        locations=[
                            WrappedFunction.find_location(p),
                            WrappedFunction.find_location(self.func),
                        ]
                    )
            if not p(**bindings):
                lsource = find_lambdasource(p)
                if lsource is not None:
                    expected = f"passing: {lsource}"
                else:
                    expected = "passing precondition"

                err = UntypyTypeError(
                    bindings,
                    expected
                )
                err = err.with_note("Failed precondition.")
                err = err.with_frame(Frame(
                    expected,
                    "",
                    declared=WrappedFunction.find_location(p),
                    responsable=None,
                ))
                raise ctx(0).wrap(err)
Пример #2
0
    def wrap(self, err: UntypyTypeError) -> UntypyTypeError:
        declared = []
        if isinstance(self.declared, Location):
            declared.append(self.declared)
        if isinstance(self.declared, list):
            declared.extend(self.declared)

        responsable = []
        if isinstance(self.responsable, Location):
            responsable.append(self.responsable)
        if isinstance(self.responsable, list):
            responsable.extend(self.responsable)

        while len(declared) < len(responsable):
            declared.append(None)
        while len(declared) > len(responsable):
            responsable.append(None)

        for (d, r) in zip(declared, responsable):
            (t, i) = err.next_type_and_indicator()
            err = err.with_frame(Frame(t, i, d, r))

        if self.upper_ctx is not None:
            return self.upper_ctx.wrap(err)
        else:
            return err
Пример #3
0
    def wrap(self, err: UntypyTypeError) -> UntypyTypeError:
        next_type, indicator = err.next_type_and_indicator()

        err = err.with_frame(
            Frame(f"list[{next_type}]", (" " * len("list[") + indicator), None,
                  None))
        return self.upper.wrap(err)
Пример #4
0
    def wrap(self, err: UntypyTypeError) -> UntypyTypeError:
        (next_ty, indicator) = err.next_type_and_indicator()
        return_id = IndicatorStr(next_ty, indicator)

        original = WrappedFunction.find_original(self.fn)

        try:
            signature = inspect.signature(original)  # TODO:!!! FIX BUILTINS
            front_sig = []
            for name in signature.parameters:
                front_sig.append(
                    f"{name}: {self.fn.checker_for(name).describe()}")
            front_sig = f"{original.__name__}(" + (
                ", ".join(front_sig)) + ") -> "
            return_id = IndicatorStr(front_sig) + return_id
        except:
            return_id = IndicatorStr("???")

        declared = WrappedFunction.find_location(self.fn)
        return err.with_frame(
            Frame(
                return_id.ty,
                return_id.indicator,
                declared=declared,
                responsable=declared,
            ))
Пример #5
0
    def wrap(self, err: UntypyTypeError) -> UntypyTypeError:
        type_declared = self.name() + "["
        indicator = " " * len(type_declared)

        for i, checker in enumerate(self.checkers):
            if i == self.idx:
                next_type, next_indicator = err.next_type_and_indicator()
                type_declared += next_type
                indicator += next_indicator
            else:
                type_declared += checker.describe()
                indicator += " " * len(checker.describe())

            if i != len(self.checkers) - 1:  # not last element
                type_declared += ", "
                indicator += "  "

        type_declared += "]"

        err = err.with_frame(
            Frame(
                type_declared,
                indicator,
                declared=self.declared(),
                responsable=self.responsable(),
            ))

        return self.upper.wrap(err)
Пример #6
0
 def wrap(self, err: UntypyTypeError) -> UntypyTypeError:
     t, i = err.next_type_and_indicator()
     return err.with_frame(
         Frame(t,
               i,
               responsable=Location.from_stack(self.caller),
               declared=Location.from_code(self.declared)))
Пример #7
0
def ProtocolWrapper(protocolchecker: ProtocolChecker, original: type,
                    members: Dict[str, Tuple[inspect.Signature,
                                             dict[str, TypeChecker],
                                             FunctionCondition]],
                    ctx: ExecutionContext):
    list_of_attr = dict()
    for fnname in members:
        if not hasattr(original, fnname):
            raise ctx.wrap(
                UntypyTypeError(expected=protocolchecker.describe(),
                                given=original.__name__)
            ).with_note(
                f"Type {original.__name__} does not meet the requirements of protocol {protocolchecker.proto.__name__}. It is missing the function '{fnname}'"
            )

        original_fn = getattr(original, fnname)
        try:
            # fails on built ins - YEAH
            original_fn_signature = inspect.signature(original_fn)
        except:
            original_fn_signature = None

        if hasattr(original_fn, '__wf'):
            original_fn = getattr(original_fn, '__wf')
        (sig, argdict, fc) = members[fnname]

        for param in sig.parameters:
            if original_fn_signature is not None and param not in original_fn_signature.parameters:
                raise ctx.wrap(
                    UntypyTypeError(expected=protocolchecker.describe(),
                                    given=original.__name__)
                ).with_note(
                    f"Type {original.__name__} does not meet the requirements of protocol {protocolchecker.proto.__name__}. The signature of '{fnname}' does not match. Missing required parameter {param}"
                )

        list_of_attr[fnname] = ProtocolWrappedFunction(original_fn, sig,
                                                       argdict,
                                                       protocolchecker,
                                                       fc).build()

    def constructor(me, inner, ctx):
        me._ProtocolWrappedFunction__inner = inner
        me._ProtocolWrappedFunction__ctx = ctx

    def __getattr__(me, name):
        return getattr(me._ProtocolWrappedFunction__inner, name)

    def __setattr__(me, name, value):
        if name == '_ProtocolWrappedFunction__inner':
            super(type(me), me).__setattr__('_ProtocolWrappedFunction__inner',
                                            value)
        else:
            return setattr(me._ProtocolWrappedFunction__inner, name, value)

    list_of_attr['__init__'] = constructor
    list_of_attr['__getattr__'] = __getattr__  # allow access of attributes
    list_of_attr['__setattr__'] = __setattr__  # allow access of attributes
    name = f"{protocolchecker.proto.__name__}For{original.__name__}"
    return type(name, (), list_of_attr)
Пример #8
0
    def wrap(self, err: UntypyTypeError) -> UntypyTypeError:
        (nt, ni) = err.next_type_and_indicator()

        if nt == err.expected and nt == self.bv.inner.describe():
            err.expected = self.bv.describe()
            err.expected_indicator = "^" * len(self.bv.describe())

        return self.upper.wrap(err)
Пример #9
0
    def wrap(self, err: UntypyTypeError) -> UntypyTypeError:
        (t, i) = err.next_type_and_indicator()

        return err.with_frame(
            Frame(t,
                  i,
                  declared=None,
                  responsable=Location(file="dummy", line_no=0, line_span=1)))
Пример #10
0
    def wrap(self, err: UntypyTypeError) -> UntypyTypeError:
        (original_expected, _ind) = err.next_type_and_indicator()
        err = ArgumentExecutionContext(self.tc.inner, None,
                                       self.arg_name).wrap(err)

        func_decl = WrappedFunction.find_location(self.tc.inner)

        name = WrappedFunction.find_original(self.tc.inner).__name__

        (decl, ind) = err.next_type_and_indicator()
        err = err.with_frame(
            Frame(decl, ind, declared=None, responsable=func_decl))

        previous_chain = UntypyTypeError(
            f"def {name}{self.tc.inner.describe()}", f"{self.tc.describe()}")
        (decl, ind) = previous_chain.next_type_and_indicator()
        previous_chain = previous_chain.with_frame(
            Frame(decl, ind, declared=func_decl, responsable=None))

        err = err.with_note(
            f"The argument '{self.arg_name}' of method '{name}' violates the signature of {self.tc.describe()}."
        )

        previous_chain = self.upper.wrap(previous_chain)

        return err.with_previous_chain(previous_chain)
Пример #11
0
    def check(self, arg: Any, ctx: ExecutionContext) -> None:
        if arg not in self.cont:
            # raise error on falsy value
            err = UntypyTypeError(
                given=arg, expected=self.annotated.describe()).with_note(
                    f"\n\nNote: {repr(arg)} is not in {repr(self.cont)}.")

            for info in self.annotated.info:
                err = err.with_note("    - " + info)

            raise ctx.wrap(err)
Пример #12
0
    def wrap(self, err: UntypyTypeError) -> UntypyTypeError:
        offset = self.ch.describe().find("[") + 1

        (t, i) = err.next_type_and_indicator()

        err = err.with_frame(
            Frame(type_declared=self.ch.describe(),
                  indicator_line=(" " * offset) + i,
                  declared=None,
                  responsable=None))

        return self.upper.wrap(err)
 def check(self, arg: Any, ctx: ExecutionContext) -> None:
     res = self.callable(arg)
     if not res:
         exp = self.annotated.describe()
         # raise error on falsy value
         err = UntypyTypeError(given=arg, expected=exp)
         if self.annotated.is_anonymous:
             err = err.with_note(f"condition in {exp} does not hold")
         (t, i) = err.next_type_and_indicator()
         for info in self.annotated.info:
             err = err.with_note("    - " + info)
         raise ctx.wrap(err)
    def wrap(self, err: UntypyTypeError) -> UntypyTypeError:
        (next_ty, indicator) = err.next_type_and_indicator()
        error_id = IndicatorStr(next_ty, indicator)

        original = WrappedFunction.find_original(self.fn)
        try:
            signature = inspect.signature(original)
        except ValueError:
            # fails on some built-ins
            signature = inspect.signature(self.fn)

        wf = None
        if (hasattr(self.fn, '__wf')):
            wf = getattr(self.fn, '__wf')
        elif isinstance(self.fn, WrappedFunction):
            wf = self.fn

        arglist = []
        for name in signature.parameters:
            if name is self.argument_name:
                arglist.append(IndicatorStr(f"{name}: ") + error_id)
            else:
                if wf is not None:
                    arglist.append(
                        IndicatorStr(
                            f"{name}: {wf.checker_for(name).describe()}"))
                else:
                    arglist.append(IndicatorStr(f"{name}"))

        id = IndicatorStr(f"{format_name(original)}(") + IndicatorStr(
            ", ").join(arglist)

        if wf is not None:
            id += IndicatorStr(f") -> {wf.checker_for('return').describe()}")
        else:
            id += IndicatorStr(f")")

        if self.declared is None:
            declared = WrappedFunction.find_location(self.fn)
        else:
            declared = self.declared

        if self.stack is not None:
            responsable = Location.from_stack(self.stack)
        else:
            responsable = None

        frame = Frame(id.ty,
                      id.indicator,
                      declared=declared,
                      responsable=responsable)
        return err.with_frame(frame)
    def posthook(self, ret, boundargs, ctx: ExecutionContext):
        for p in self.postcondition:
            bindings = {}
            for name in inspect.signature(p).parameters:
                if name == "ret":
                    bindings["ret"] = ret
                elif name in boundargs.arguments:
                    bindings[name] = boundargs.arguments[name]
                else:
                    raise UntypyAttributeError(
                        f"Did not find argument {name} of postcondition in function.",
                        locations=[
                            WrappedFunction.find_location(p),
                            WrappedFunction.find_location(self.func),
                        ]
                    )
            if not p(**bindings):
                lsource = find_lambdasource(p)
                if lsource is not None:
                    expected = f"passing: {lsource}"
                else:
                    expected = "passing postcondition"

                given = ret.__repr__()
                err = UntypyTypeError(
                    given,
                    expected,
                ).with_note("Failed postcondition").with_frame(Frame(
                    expected,
                    "",
                    declared=WrappedFunction.find_location(p),
                    responsable=None,
                ))
                raise ctx.wrap(err)
Пример #16
0
 def check_and_wrap(self, arg: Any, ctx: ExecutionContext) -> Any:
     if not type(arg) is tuple:
         raise ctx.wrap(UntypyTypeError(arg, self.describe()))
     out = []
     for elm in arg:
         out.append(self.inner.check_and_wrap(elm, VariadicTupleExecutionContext(ctx)))
     return tuple(out)
Пример #17
0
 def check_and_wrap(self, arg: Any, ctx: ExecutionContext) -> Any:
     if not isinstance(arg, self.proto):
         raise ctx.wrap(UntypyTypeError(
             expected=self.describe(),
             given=arg
         )).with_note(f"Type '{type(arg).__name__}' does not inherit from '{self.proto.__name__}'")
     return super().check_and_wrap(arg, ctx)
Пример #18
0
    def check_and_wrap(self, arg: Any, ctx: ExecutionContext) -> Any:
        if not inspect.isgenerator(arg):
            raise ctx.wrap(UntypyTypeError(arg, self.describe()))

        me = self
        yield_ctx = TypedGeneratorYieldReturnContext(arg, self, True, ctx)
        return_ctx = TypedGeneratorYieldReturnContext(arg, self, False, ctx)

        def wrapped():
            try:
                sent = None
                while True:
                    value_yield = arg.send(sent)
                    # check value_yield (arg is responsable)
                    value_yield = me.yield_checker.check_and_wrap(
                        value_yield, yield_ctx)

                    sent = yield value_yield

                    caller = sys._getframe(1)

                    # check sent value (caller is responsable)
                    sent = me.send_checker.check_and_wrap(
                        sent, TypedGeneratorSendContext(caller, me, ctx))

            except StopIteration as e:
                # check value_returned (arg is responsable)
                ret = me.return_checker.check_and_wrap(e.value, return_ctx)
                return ret

        return wrapped()
Пример #19
0
    def check_and_wrap(self, arg: Any, ctx: ExecutionContext) -> Any:
        if not issubclass(type(arg), self.origin):
            raise ctx.wrap(UntypyTypeError(arg, self.describe()))

        instance = self.template.__new__(self.template)
        instance._WrappedClassFunction__inner = arg
        instance._WrappedClassFunction__return_ctx = ReplaceTypeExecutionContext(ctx, self.name)
        return instance
Пример #20
0
    def wrap(self, err: UntypyTypeError) -> UntypyTypeError:
        (type_declared, indicator_line) = self.declared_and_indicator(err)

        declared = WrappedFunction.find_location(self.fn.inner)

        responsable = Location.from_stack(self.stack)

        frame = Frame(
            type_declared,
            indicator_line,
            declared=declared,
            responsable=responsable,
        )

        err = err.with_frame(frame)
        err = err.with_inverted_responsibility_type()
        return self.upper.wrap(err)
Пример #21
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)
Пример #22
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)
Пример #23
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)
Пример #24
0
    def wrap(self, err: UntypyTypeError) -> UntypyTypeError:
        if self.invert:
            err = ReturnExecutionContext(self.fn.inner).wrap(err)
            return err

        (next_ty, indicator) = err.next_type_and_indicator()

        desc = lambda s: s.describe()
        front_str = f"Callable[[{', '.join(map(desc, self.fn.argument_checker))}], "

        responsable = WrappedFunction.find_location(self.fn.inner)

        err = err.with_frame(
            Frame(f"{front_str}{next_ty}]", (" " * len(front_str)) + indicator,
                  declared=None,
                  responsable=responsable))

        return self.upper.wrap(err)
Пример #25
0
 def check_and_wrap(self, arg: Any, ctx: ExecutionContext) -> Any:
     if simpleTypeCompat(arg, self.annotation) and not self.always_wrap:
         return arg
     if isinstance(arg, self.annotation):
         if self.parent_checker is None:
             return arg
         else:
             return self.parent_checker(arg, ctx)
     else:
         raise ctx.wrap(UntypyTypeError(arg, self.describe()))
Пример #26
0
    def check_and_wrap(self, arg: Any, ctx: ExecutionContext) -> Any:
        if not type(arg) is tuple or len(arg) != len(self.inner):
            raise ctx.wrap(UntypyTypeError(arg, self.describe()))

        out = []
        idx = 0
        for elm, checker in zip(arg, self.inner):
            out.append(checker.check_and_wrap(elm, TupleExecutionContext(ctx, self.inner, idx)))
            idx += 1

        return tuple(out)
Пример #27
0
    def check_and_wrap(self, arg: Any, upper: ExecutionContext) -> Any:
        idx = 0
        for checker in self.inner:
            ctx = UnionExecutionContext(upper, self.inner, idx)
            idx += 1
            try:
                return checker.check_and_wrap(arg, ctx)
            except UntypyTypeError as _e:
                pass

        raise upper.wrap(UntypyTypeError(arg, self.describe()))
Пример #28
0
    def wrap(self, err: UntypyTypeError) -> UntypyTypeError:
        full = self.upper.wrap(err)

        # now remove responsability in frames:
        frames_to_add = []
        for frame in full.frames:
            if frame not in err.frames:
                frame.responsable = None
                frames_to_add.append(frame)

        for frame in frames_to_add:
            err = err.with_frame(frame)

        for note in full.notes:
            err = err.with_note(note)

        if full.previous_chain is not None:
            err = err.with_previous_chain(full.previous_chain)

        return err
Пример #29
0
    def wrap_arguments(self, ctxprv: WrappedFunctionContextProvider, args,
                       kwargs):
        try:
            bindings = self.signature.bind(*args, **kwargs)
        except TypeError as e:
            err = UntypyTypeError(header=str(e))
            if "self" not in self.signature.parameters:
                err = err.with_note(
                    "Hint: 'self'-parameter was omitted in declaration.")
            raise ctxprv("").wrap(err)

        bindings.apply_defaults()
        if self.fc is not None:
            self.fc.prehook(bindings, ctxprv)
        for name in bindings.arguments:
            check = self.checker[name]
            ctx = ctxprv(name)
            bindings.arguments[name] = check.check_and_wrap(
                bindings.arguments[name], ctx)
        return bindings.args, bindings.kwargs, bindings
    def check_and_wrap(self, arg: Any, ctx: ExecutionContext) -> Any:
        if not hasattr(arg, '__next__') or not hasattr(arg, '__iter__'):
            raise ctx.wrap(UntypyTypeError(arg, self.describe()))

        me = self
        ctx = TypedIteratorExecutionContext(self.inner, arg, ctx)

        def wrapper():
            for item in arg:
                yield me.inner.check_and_wrap(item, ctx)

        return wrapper()