Ejemplo n.º 1
0
def patch_class(clas: type, cfg: Config):
    if clas in GlobalPatchedList:
        return clas
    GlobalPatchedList.add(clas)

    try:
        ctx = DefaultCreationContext(
            typevars=dict(),
            declared_location=Location(
                file=inspect.getfile(clas),
                line_no=inspect.getsourcelines(clas)[1],
                line_span=len(inspect.getsourcelines(clas)[0]),
            ),
            checkedpkgprefixes=cfg.checkedprefixes)
    except (TypeError, OSError) as e:  # Built in types
        ctx = DefaultCreationContext(
            typevars=dict(),
            declared_location=Location(file="<not found>",
                                       line_no=0,
                                       line_span=1),
            checkedpkgprefixes=cfg.checkedprefixes,
        )

    setattr(clas, '__patched', True)

    is_protocol = hasattr(clas, 'mro') and Protocol in clas.mro()

    if hasattr(clas, '__class_getitem__') and not is_protocol:
        original = clas.__class_getitem__
        setattr(clas, '__class_getitem__',
                lambda *args: WrappedGenericAlias(original(*args), ctx))
Ejemplo n.º 2
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)))
 def assertBlame(self, cm, blamed):
     ok = cm.exception.last_responsable() in Location.from_code(blamed)
     if not ok:
         print(cm.exception.last_responsable())
         print("not in")
         print(Location.from_code(blamed))
     self.assertTrue(ok)
Ejemplo n.º 4
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)))
Ejemplo n.º 5
0
 def find_location(fn) -> Optional[Location]:
     fn = WrappedFunction.find_original(fn)
     try:
         return Location(
             file=inspect.getfile(fn),
             line_no=inspect.getsourcelines(fn)[1],
             source_line="".join(inspect.getsourcelines(fn)[0]),
         )
     except:  # Failes on builtins
         return None
    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 responsable(self) -> Optional[Location]:
     try:
         if hasattr(self.iter, 'gi_frame'):
             return Location(
                 file=inspect.getfile(self.iter.gi_frame),
                 line_no=inspect.getsourcelines(self.iter.gi_frame)[1],
                 line_span=len(inspect.getsourcelines(self.iter.gi_frame)[0]),
             )
     except OSError:  # this call does not work all the time
         pass
     except TypeError:
         pass
     return None
Ejemplo n.º 8
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)
Ejemplo n.º 9
0
    def test_standalone(self):
        ch = untypy.checker(lambda: int, TestStandaloneChecker.test_standalone)

        self.assertEqual(ch(42), 42)

        def myfunc(x):
            ch(x)

        with self.assertRaises(UntypyTypeError) as cm:
            myfunc("hello")

        self.assertEqual(cm.exception.expected, 'int')
        self.assertEqual(
            cm.exception.last_declared(),
            Location.from_code(TestStandaloneChecker.test_standalone))
        self.assertIn('myfunc("hello")',
                      cm.exception.last_responsable().source_lines)
Ejemplo n.º 10
0
def _find_bound_typevars(clas: type) -> (type, Dict[TypeVar, Any]):
    if not hasattr(clas, '__args__') or not hasattr(clas, '__origin__'):
        return (clas, dict())
    if not hasattr(clas.__origin__, '__parameters__'):
        return (clas, dict())

    keys = clas.__origin__.__parameters__
    values = clas.__args__

    if len(keys) != len(values):
        raise UntypyAttributeError(
            f"Some unbound Parameters in {clas.__name__}. "
            f"keys={keys} do not match values={values}.", [
                Location(file=inspect.getfile(clas),
                         line_no=inspect.getsourcelines(clas)[1],
                         source_line="".join(inspect.getsourcelines(clas)[0]))
            ])
    return (clas.__origin__, dict(zip(keys, values)))
Ejemplo n.º 11
0
    def get_checker(self):
        if self._checker:
            return self._checker

        ctx = DefaultCreationContext(
            typevars=dict(),
            declared_location=Location.from_code(self.declared),
            checkedpkgprefixes=self.cfg.checkedprefixes)
        try:
            annotation = self.annotation()
        except NameError as ne:
            raise ctx.wrap(
                UntypyNameError(
                    f"{ne}.\nType annotation could not be resolved."))

        checker = ctx.find_checker(annotation)
        if checker is None:
            raise ctx.wrap(
                UntypyAttributeError(
                    f"\n\tUnsupported type annotation: {self.annotation}\n"))
        self._checker = checker
        return checker
Ejemplo n.º 12
0
 def __init__(self, typevars: dict[TypeVar, Any] = dict()):
     super().__init__(typevars.copy(),
                      Location(file="dummy", line_no=0, line_span=1),
                      checkedpkgprefixes=["test"])
Ejemplo n.º 13
0
 def wrap(self, err: UntypyTypeError) -> UntypyTypeError:
     next_type, indicator = err.next_type_and_indicator()
     return err.with_frame(
         Frame(f"list[{next_type}]", (" " * len("list[") + indicator),
               declared=self.declared,
               responsable=Location.from_stack(self.stack)))
Ejemplo n.º 14
0
 def responsable(self) -> Optional[Location]:
     return Location.from_stack(self.stack)
Ejemplo n.º 15
0
def wrap_class(a: type, cfg: Config) -> Callable:
    return WrappedType(
        a,
        DefaultCreationContext(typevars=dict(),
                               declared_location=Location.from_code(a),
                               checkedpkgprefixes=cfg.checkedprefixes))