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)
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)
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)
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
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
def declared(self) -> Location: fn = WrappedFunction.find_original(self.inner) return WrappedFunction.find_location( getattr(self.protocol.proto, fn.__name__))
def describe(self) -> str: fn = WrappedFunction.find_original(self.inner) return f"{fn.__name__}" + str(self.signature)