Esempio n. 1
0
    def test_type_freeze(self):
        class C:
            pass

        cinder.freeze_type(C)

        with self.assertRaisesRegex(
            TypeError, "type 'C' has been frozen and cannot be modified"
        ):
            C.foo = 42

        class D:
            x = 42

        cinder.freeze_type(D)

        with self.assertRaisesRegex(
            TypeError, "type 'D' has been frozen and cannot be modified"
        ):
            D.foo = 42

        with self.assertRaisesRegex(
            TypeError, "type 'D' has been frozen and cannot be modified"
        ):
            del D.foo
Esempio n. 2
0
    def test_cached_class_prop_frozen_type_inst(self):
        class C:
            @cached_classproperty
            def f(cls):
                return 42

        cinder.freeze_type(C)
        self.assertEqual(C().f, 42)
Esempio n. 3
0
    async def test_cached_class_prop_frozen_type(self):
        class C:
            @async_cached_classproperty
            async def f(cls):
                return 42

        cinder.freeze_type(C)
        self.assertEqual(await C.f, 42)
Esempio n. 4
0
def _replace_types(gen_type: Type[object], subs: Tuple[Type[object],
                                                       ...]) -> Type[object]:
    existing_inst = gen_type.__origin__.__insts__.get(subs)

    if existing_inst is not None:
        return existing_inst

    # Check if we have a full instantation, and verify the constraints
    new_dict = dict(gen_type.__dict__)
    has_params = False
    for sub in subs:
        if isinstance(sub, TypeVar) or hasattr(sub, "__parameters__"):
            has_params = True
            continue

    # Remove the existing StaticGeneric base...
    bases = tuple(base for base in gen_type.__orig_bases__
                  if not isinstance(base, StaticGeneric))

    new_dict["__args__"] = subs
    if not has_params:
        # Instantiated types don't have generic parameters anymore.
        del new_dict["__parameters__"]
    else:
        new_vars = _collect_type_vars(subs)
        new_gen = StaticGeneric()
        new_gen.__parameters__ = new_vars
        new_dict["__orig_bases__"] = bases + (new_gen, )
        bases += (StaticGeneric, )
        new_dict["__parameters__"] = new_vars

    # Eventually we'll want to have some processing of the members here to
    # bind the generics through.  That may be an actual process which creates
    # new objects with the generics bound, or a virtual process.  For now
    # we just propagate the members to the new type.
    param_names = ", ".join(param.__name__ for param in subs)

    res = type(f"{gen_type.__origin__.__name__}[{param_names}]", bases,
               new_dict)
    res.__origin__ = gen_type

    if not has_params:
        # specialize the type
        for name, value in new_dict.items():
            if isinstance(value, FunctionType):
                if hasattr(value, "__runtime_impl__"):
                    setattr(
                        res,
                        name,
                        _static.specialize_function(res, value.__qualname__,
                                                    subs),
                    )

    if cinder is not None:
        cinder.freeze_type(res)

    gen_type.__origin__.__insts__[subs] = res
    return res
Esempio n. 5
0
    def test_warn_on_frozen_type(self):
        class C:
            pass

        cinder.freeze_type(C)

        with self.assertRaisesRegex(
                TypeError, "can't call warn_on_inst_dict on a frozen type"):
            cinder.warn_on_inst_dict(C)
Esempio n. 6
0
    def test_init_frozen_type(self):
        codestr = """
            class C:

                def __init__(self, a: int) -> None:
                    self.value = a

            def f(x: int) -> C:
                return C(x)
        """
        with self.in_module(codestr) as mod:
            C = mod.C
            freeze_type(C)
            f = mod.f
            self.assertEqual(f(42).value, 42)
Esempio n. 7
0
    def test_invoke_with_freevars(self):
        codestr = """
            class C:
                def __init__(self) -> None:
                    super().__init__()


            def f() -> C:
                return C()
        """
        code = self.compile(codestr)
        with self.in_module(codestr) as mod:
            f = mod.f
            C = mod.C
            freeze_type(C)
            self.assertInBytecode(f, "INVOKE_FUNCTION")
            self.assertTrue(isinstance(f(), C))
Esempio n. 8
0
    def test_warn_on_type(self):
        class C:
            pass

        msg = type = attr = None

        def cb(*args):
            nonlocal msg, type, attr
            msg = args[0]
            type = args[1]
            attr = args[2]

        cinder.warn_on_inst_dict(C)
        cinder.freeze_type(C)

        cinder.cinder_set_warn_handler(cb)
        C.foo = 42

        self.assertEqual(
            msg, "WARN002: Type modified that was flagged for immutability")
        self.assertEqual(type, C)
        self.assertEqual(attr, "foo")
Esempio n. 9
0
 def test_type_freeze_bad_arg(self):
     with self.assertRaisesRegex(TypeError, "freeze_type requires a type"):
         cinder.freeze_type(42)