Exemplo n.º 1
0
    def create_from(self, annotation: Any,
                    ctx: CreationContext) -> Optional[TypeChecker]:
        if type(annotation) in [
                GeneratorTypeA, GeneratorTypeB
        ] and annotation.__origin__ == collections.abc.Generator:
            if len(annotation.__args__) != 3:
                raise ctx.wrap(
                    UntypyAttributeError(
                        f"Expected 3 type arguments for Generator."))

            (yield_checker, send_checker, return_checker) = list(
                map(lambda a: ctx.find_checker(a), annotation.__args__))

            if yield_checker is None:
                raise ctx.wrap(
                    UntypyAttributeError(
                        f"The Yield Annotation of the Generator could not be resolved."
                    ))
            if send_checker is None:
                raise ctx.wrap(
                    UntypyAttributeError(
                        f"The Send Annotation of the Generator could not be resolved."
                    ))
            if return_checker is None:
                raise ctx.wrap(
                    UntypyAttributeError(
                        f"The Return Annotation of the Generator could not be resolved."
                    ))

            return GeneratorChecker(yield_checker, send_checker,
                                    return_checker)
        else:
            return None
def analyse(item, ctx: CreationContext, e) -> UntypyAttributeError:
    org = WrappedFunction.find_original(item)
    source = inspect.getsource(item)
    fn_ast = ast.parse(source)

    for node in map_str_to_ast(fn_ast.body[0].args, fn_ast.body[0].returns):
        for rule in RULES:
            rule_result = rule(node)
            if rule_result:
                # Got a Match
                (n, message) = rule_result
                display = DisplayMatrix(source)
                display.write((n.col_offset - 1, n.lineno),
                              " " + "^" * (n.end_col_offset - n.col_offset) +
                              " - " + message)
                return ctx.wrap(
                    UntypyAttributeError(
                        f"Type annotation of function '{qualname(org)}' could not be resolved:\n"
                        f"{e}\n"
                        f"\n{display}"))

    return ctx.wrap(
        UntypyAttributeError(
            f"Type annotation of function '{qualname(org)}' could not be resolved:\n"
            f"{e}\n"))
Exemplo n.º 3
0
    def __init__(self, inner: Callable, ctx: CreationContext):
        self.inner = inner
        self.signature = inspect.signature(inner)

        # SEE: https://www.python.org/dev/peps/pep-0563/#id7
        annotations = typing.get_type_hints(inner, include_extras=True)

        checkers = {}
        checked_keys = list(self.signature.parameters)

        # Remove self and cls from checking
        if len(checked_keys) > 0 and checked_keys[0] in self.special_args:
            checkers[checked_keys[0]] = SelfChecker()
            checked_keys = checked_keys[1:]

        for key in checked_keys:
            if self.signature.parameters[
                    key].annotation is inspect.Parameter.empty:
                raise ctx.wrap(
                    UntypyAttributeError(
                        f"Missing annotation for argument '{key}' of function {inner.__name__}\n"
                        "Partial annotation are not supported."))
            annotation = annotations[key]
            checker = ctx.find_checker(annotation)
            if checker is None:
                raise ctx.wrap(
                    UntypyAttributeError(
                        f"\n\tUnsupported type annotation: {annotation}\n"
                        f"\tin argument '{key}'"))
            else:
                checkers[key] = checker

        if inner.__name__ in self.method_name_ignore_return:
            checkers['return'] = SelfChecker()
        else:
            if not 'return' in annotations:
                raise ctx.wrap(
                    UntypyAttributeError(
                        f"Missing annotation for return value of function {inner.__name__}\n"
                        "Partial annotation are not supported. Use 'None' or 'NoReturn'"
                        "for specifying no return value."))
            annotation = annotations['return']
            return_checker = ctx.find_checker(annotation)
            if return_checker is None:
                raise ctx.wrap(
                    UntypyAttributeError(
                        f"\n\tUnsupported type annotation: {annotation}\n"
                        f"\tin return"))

            checkers['return'] = return_checker

        self.fc = None
        if hasattr(self.inner, "__fc"):
            self.fc = getattr(self.inner, "__fc")
        self.checkers = checkers
    def create_from(self, annotation: Any, ctx: CreationContext) -> Optional[TypeChecker]:
        if type(annotation) in [IteratorTypeA, IteratorTypeB] and annotation.__origin__ == collections.abc.Iterator:
            if len(annotation.__args__) != 1:
                raise ctx.wrap(UntypyAttributeError(f"Expected 1 type arguments for iterator."))

            inner = ctx.find_checker(annotation.__args__[0])
            if inner is None:
                raise ctx.wrap(UntypyAttributeError(f"The inner type of the iterator could not be resolved."))
            return IteratorChecker(inner)
        else:
            return None
Exemplo n.º 5
0
def find_signature(member, ctx: CreationContext):
    signature = inspect.signature(member)

    checkers = {}
    for key in signature.parameters:
        if key == 'self':
            checkers[key] = SelfChecker()
        else:
            param = signature.parameters[key]
            if param.annotation is inspect.Parameter.empty:
                checkers[key] = AnyChecker()
                continue

            checker = ctx.find_checker(param.annotation)
            if checker is None:
                checkers[key] = AnyChecker()
                continue
            checkers[key] = checker

    if signature.return_annotation is inspect.Parameter.empty:
        checkers['return'] = AnyChecker()
    else:
        return_checker = ctx.find_checker(signature.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__}\n"))
        checkers['return'] = return_checker
    return signature, checkers
    def __init__(self, annotated, inner: TypeChecker, metadata: Iterator,
                 ctx: CreationContext):
        self.annotated = annotated
        self.inner = inner

        meta = []
        info = []
        for m in metadata:
            if callable(m):
                meta.append(AnnotatedCheckerCallable(self, m))
            elif isinstance(m, str):
                info.append(m)
            elif hasattr(m, '__contains__'):
                meta.append(AnnotatedCheckerContainer(self, m))
            else:
                raise ctx.wrap(
                    UntypyAttributeError(
                        f"Unsupported metadata '{repr(m)}' in '{repr(self.annotated)}'.\n"
                        f"Only callables or objects providing __contains__ are allowed."
                    ))
        self.meta = meta
        self.info = info
        if len(info) == 1:
            self.name = info[0]
            self.info = []
        else:
            self.name = None
def get_type_hints(item, ctx: CreationContext, resolver=_default_resolver):
    try:
        # SEE: https://www.python.org/dev/peps/pep-0563/#id7
        return resolver(item)
    except NameError as ne:
        org = WrappedFunction.find_original(item)
        if inspect.isclass(org):
            raise ctx.wrap(
                UntypyNameError(
                    f"{ne}.\nType annotation inside of class '{qualname(org)}' could not be resolved."
                ))
        else:
            raise ctx.wrap(
                UntypyNameError(
                    f"{ne}.\nType annotation of function '{qualname(org)}' could not be resolved."
                ))
    except Exception as e:
        # Try to find better cause in analyse
        raise analyse(item, ctx, e)
    def __init__(self, annotation: Union[CallableTypeOne, CallableTypeTwo],
                 ctx: CreationContext):
        arguments_ty = annotation.__args__[:-1]
        return_ty = annotation.__args__[-1]

        return_checker = ctx.find_checker(return_ty)
        if return_checker is None:
            raise ctx.wrap(
                UntypyAttributeError(
                    f"Return Type Annotation not found. {return_ty}"))

        argument_checker = []
        for arg in arguments_ty:
            checker = ctx.find_checker(arg)
            if checker is None:
                raise ctx.wrap(
                    UntypyAttributeError(
                        f"Argument Type Annotation not found. {arg}"))
            argument_checker.append(checker)

        self.return_checker = return_checker
        self.argument_checker = argument_checker
Exemplo n.º 9
0
    def create_from(self, annotation: Any,
                    ctx: CreationContext) -> Optional[TypeChecker]:
        if hasattr(annotation, '__metadata__') and hasattr(
                annotation, '__origin__'):
            inner = ctx.find_checker(annotation.__origin__)
            if inner is None:
                raise ctx.wrap(
                    UntypyAttributeError(f"Could not resolve annotation "
                                         f"'{repr(annotation.__origin__)}' "
                                         f"inside of '{annotation}'."))

            return AnnotatedChecker(annotation, inner, annotation.__metadata__,
                                    ctx)
        else:
            return None
Exemplo n.º 10
0
 def __init__(self, inner: list[TypeChecker], ctx: CreationContext):
     # especially Protocols must be checked in a specific order.
     self.inner = sorted(inner, key=lambda t: -t.base_type_priority())
     dups = dict()
     for checker in inner:
         for base_type in checker.base_type():
             if base_type in dups:
                 raise ctx.wrap(
                     UntypyAttributeError(
                         f"{checker.describe()} is in conflict with "
                         f"{dups[base_type].describe()} "
                         f"in {self.describe()}. "
                         f"Types must be distinguishable inside one Union."
                         f"\nNote: Only one Protocol is allowed inside one Union. "
                         f"Classes could implement multiple Protocols by accident."
                         f"\nNote: Multiple Callables or Generics inside one Union are also unsupported."
                     ))
             else:
                 dups[base_type] = checker
Exemplo n.º 11
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