def test_adding_and_removing(self): A = PythonObject({ "foo": 5 }) B = PythonObject({ "bar": A }) At = UniversalObjectType({ "foo": IntegerType() }) Bt = UniversalObjectType({ "bar": At }) get_manager(A).add_composite_type(At) self.assertEquals(len(get_manager(A).attached_types), 1) self.assertEquals(get_manager(A).attached_type_counts[id(At)], 1) get_manager(B).add_composite_type(Bt) self.assertEquals(len(get_manager(A).attached_types), 1) self.assertEquals(get_manager(A).attached_type_counts[id(At)], 2) get_manager(B).remove_composite_type(Bt) self.assertEquals(len(get_manager(A).attached_types), 1) self.assertEquals(get_manager(A).attached_type_counts[id(At)], 1)
def test_modifying(self): At = UniversalObjectType({ "foo": IntegerType() }) Bt = UniversalObjectType({ "bar": At }) A = PythonObject({ "foo": 5 }) B = PythonObject({ "bar": A }, bind=Bt) self.assertEquals(len(get_manager(A).attached_types), 1) self.assertEquals(get_manager(A).attached_type_counts[id(At)], 1) B.bar = PythonObject({ "foo": 42 }, bind=At) self.assertEquals(len(get_manager(A).attached_types), 0) self.assertEquals(get_manager(A).attached_type_counts[id(At)], 0)
def test_that_python_constraints_dont_spread_to_constrained_children(self): bar = PythonObject({ "baz": 42 }) foo = PythonObject({ "bar": bar }) # The first, stronger, type prevents the NO_SETTER_ERROR_COMPOSITE_TYPE spreading from foo to bar get_manager(bar).add_composite_type(UniversalObjectType({ "baz": IntegerType() })) get_manager(foo).add_composite_type(NO_SETTER_ERROR_COMPOSITE_TYPE) self.assertIs(foo.bar, bar) self.assertEquals(len(get_manager(foo).attached_types), 1) self.assertEquals(len(get_manager(foo.bar).attached_types), 1) # ... but when bar is replaced with a new object without constraints, the PythonObjectType # spreads to the new object foo.bar = PythonObject({ "baz": 123 }) self.assertIsNot(foo.bar, bar) self.assertEquals(len(get_manager(foo.bar).attached_types), 1) # Now that the new object has the PythonObjectType constraint, we can't bind a stronger # constraint with self.assertRaises(CompositeTypeIncompatibleWithTarget): get_manager(foo.bar).add_composite_type(UniversalObjectType({ "baz": IntegerType() }))
def test_double_deep_assignment(self): foo = PythonObject({ "bar": PythonObject({ "baz": PythonObject({ "bam": 10 }) }) }) Baz = UniversalObjectType({ "bam": IntegerType() }) Bar = UniversalObjectType({ "baz": Baz }) get_manager(foo).add_composite_type( UniversalObjectType({ "bar": Bar }) ) self.assertEquals(foo.bar.baz.bam, 10) foo.bar = PythonObject({ "baz": PythonObject({ "bam": 42 }) }, bind=Bar) self.assertEquals(foo.bar.baz.bam, 42)
def test_basic_ignored(self): foo = UniversalObjectType({ "bar": StringType() }) foo = prepare_lhs_type(foo, UniversalObjectType({ "bar": IntegerType() })) self.assertIsInstance(foo.get_micro_op_type(("get", "bar")).value_type, StringType)
def test_dangling_error(self): foo = UniversalObjectType({ "bar": InferredType() }) with self.assertRaises(DanglingInferredType): foo = prepare_lhs_type(foo, UniversalObjectType({ "bam": StringType() })) check_dangling_inferred_types(foo, {})
def test_composite_types_inferred(self): foo = UniversalObjectType({ "bar": InferredType() }) foo = prepare_lhs_type(foo, UniversalObjectType({ "bar": UniversalObjectType({ "bam": IntegerType() }) })) self.assertIsInstance(foo.get_micro_op_type(("get", "bar")).value_type.get_micro_op_type(("get", "bam")).value_type, IntegerType)
def test_narrowing_blocked(self): foo = PythonObject({ "bar": 42 }) get_manager(foo).add_composite_type(UniversalObjectType({ "bar": IntegerType() })) with self.assertRaises(CompositeTypeIncompatibleWithTarget): get_manager(foo).add_composite_type(UniversalObjectType({ "bar": UnitType(42) }))
def test_broadening_with_const_is_ok(self): foo = PythonObject({ "bar": 42 }) get_manager(foo).add_composite_type(UniversalObjectType({ "bar": UnitType(42) })) get_manager(foo).add_composite_type(UniversalObjectType({ "bar": Const(IntegerType()) }))
def test_double_nested(self): Initial_Foo = UniversalObjectType({ "bar": UniversalObjectType({ "bam": InferredType() }) }) RHS_Foo = UniversalObjectType({ "bar": UniversalObjectType({ "bam": IntegerType() }) }) resolved_Foo = prepare_lhs_type(Initial_Foo, RHS_Foo) self.assertIsInstance(resolved_Foo.get_micro_op_type(("get", "bar")).value_type.get_micro_op_type(("get", "bam")).value_type, IntegerType)
def test_interesting(self): func = function_lit( any_type(), infer_all(), match_op(dereference("argument"), [ prepared_function( object_type({"foo": int_type()}), return_op( addition_op(dereference("argument.foo"), literal_op(3)))), prepared_function(any_type(), return_op(literal_op("invalid"))) ])) _, result = bootstrap_function(func, argument=PythonObject( {"foo": 39}, bind=UniversalObjectType( {"foo": IntegerType()}))) self.assertEquals(result.caught_break_mode, "return") self.assertEquals(result.value, 42) _, result = bootstrap_function(func, argument=PythonObject({"foo": "hello"})) self.assertEquals(result.caught_break_mode, "return") self.assertEquals(result.value, "invalid")
def test_misc2(self): # Came up writing test_misc1 PythonObject({ "local": PythonList([ 39, 3 ]) }, bind=UniversalObjectType({ "local": UniversalTupleType([ IntegerType(), IntegerType() ]) }, wildcard_type=RICH_READONLY_TYPE))
def test_deletion_blocked(self): foo = PythonObject({ "bar": PythonObject({ "baz": 42 }) }) get_manager(foo).add_composite_type( UniversalObjectType({ "bar": UniversalObjectType({ "baz": IntegerType() }) }) ) with self.assertRaises(Exception): del foo.bar
def test_basics(self): foo = PythonObject({ "bar": 42 }) get_manager(foo).add_composite_type(UniversalObjectType({ "bar": UnitType(42) })) self.assertEquals(foo.bar, 42)
def test_blocked_basic_assignment(self): foo = PythonObject({ "bar": PythonObject({ "baz": 42 }) }) get_manager(foo).add_composite_type( UniversalObjectType({ "bar": UniversalObjectType({ "baz": IntegerType() }) }) ) with self.assertRaises(Exception): foo.bar = PythonObject({ "baz": "hello" })
def __init__(self, data, code, prepare_context, static, argument_type, outer_type, local_type, local_initializer, break_types): self.data = data self.code = code self.prepare_context = prepare_context self.static = static self.argument_type = argument_type self.outer_type = outer_type self.local_type = local_type self.local_initializer = local_initializer self.break_types = break_types self.types_context = Universal( True, initial_wrapped={ "outer": self.outer_type, "argument": self.argument_type }, debug_reason="local-initialization-context") self.local_initialization_context_type = UniversalObjectType( { "outer": self.outer_type, "argument": self.argument_type, # "types": readonly_rich_composite_type }, wildcard_type=AnyType(), name="local-initialization-context-type") self.execution_context_type = UniversalObjectType( { # "prepare": readonly_rich_composite_type, "outer": self.outer_type, "argument": self.argument_type, # "static": readonly_rich_composite_type, "local": self.local_type, # "types": readonly_rich_composite_type }, wildcard_type=AnyType(), name="code-execution-context-type") if not self.execution_context_type.is_self_consistent(DUMMY_REASONER): raise FatalError() self.compiled_ast = None
def test_misc1(self): # Came up testing lockdown local variable binding PythonObject({ "local": PythonList([ 39, 3 ]), "types": PythonObject({}) }, bind=UniversalObjectType({ "local": UniversalTupleType([ IntegerType(), IntegerType() ]), "types": DEFAULT_READONLY_COMPOSITE_TYPE }, wildcard_type=RICH_READONLY_TYPE))
def test_types_on_object_merged(self): foo = PythonObject({ "foo": 5, "bar": "hello" }) get_manager(foo).add_composite_type( UniversalObjectType({ "foo": IntegerType() }) ) get_manager(foo).add_composite_type( UniversalObjectType({ "bar": StringType() }) ) object_type = get_manager(foo).get_effective_composite_type() UniversalObjectType({ "foo": IntegerType(), "bar": StringType() }).is_copyable_from(object_type, DUMMY_REASONER)
def test_runtime(self): obj = PythonObject({ "foo": 5 }) get_manager(obj).add_composite_type( UniversalObjectType({ "foo": OneOfType([ IntegerType(), StringType() ]) }) )
def test_basic_assignment(self): Bar = UniversalObjectType({ "baz": IntegerType() }) foo = PythonObject({ "bar": PythonObject({ "baz": 42 }) }) get_manager(foo).add_composite_type( UniversalObjectType({ "bar": Bar }) ) foo.bar = PythonObject({ "baz": 42 }, bind=Bar) self.assertEquals(foo.bar.baz, 42)
def test_broad_assignment(self): foo = PythonObject({ "bar": PythonObject({ "baz": 42 }) }) Bar = UniversalObjectType({ "baz": AnyType() }) get_manager(foo).add_composite_type( UniversalObjectType({ "bar": Bar }) ) foo.bar = PythonObject({ "baz": "hello" }, bind=Bar) self.assertEquals(foo.bar.baz, "hello")
def test_can_fail_micro_ops_are_enforced(self): foo = PythonObject({ "foo": 5, "bar": "hello" }) get_manager(foo).add_composite_type( UniversalObjectType({ "foo": Const(IntegerType()) }) ) with self.assertRaises(Exception): foo.foo = "hello"
def test_nested(self): self.assertTrue( UniversalObjectType({ "foo": OneOfType([ IntegerType(), StringType() ]) }).is_copyable_from(UniversalObjectType({ "foo": OneOfType([ IntegerType(), StringType() ]) }), DUMMY_REASONER) ) # Blocked because the receiver could set obj.foo = "hello", breaking the sender self.assertFalse( UniversalObjectType({ "foo": OneOfType([ IntegerType(), StringType() ]) }).is_copyable_from(UniversalObjectType({ "foo": IntegerType() }), DUMMY_REASONER) ) self.assertTrue( UniversalObjectType({ "foo": Const(OneOfType([ IntegerType(), StringType() ])) }).is_copyable_from(UniversalObjectType({ "foo": IntegerType() }), DUMMY_REASONER) )
def test_python_object_with_reference_types_are_enforced(self): bar = PythonObject({ "baz": 42 }) foo = PythonObject({ "bar": bar }) get_manager(bar).add_composite_type(UniversalObjectType({ "baz": IntegerType() })) get_manager(foo).add_composite_type(DEFAULT_COMPOSITE_TYPE) with self.assertRaises(Exception): foo.bar.baz = "hello"
def test_very_broad_assignment(self): foo = PythonObject({ "bar": PythonObject({ "baz": 42 }) }) get_manager(foo).add_composite_type( UniversalObjectType({ "bar": AnyType() }) ) foo.bar = "hello" self.assertEquals(foo.bar, "hello")
def test_const_is_enforced(self): return # test doesn't work because the assignment uses the set-wildcard foo = { "foo": 5, "bar": "hello" } get_manager(foo).add_composite_type( UniversalObjectType({ "foo": Const(IntegerType()) }) ) with self.assertRaises(Exception): foo.foo = 42
def test_conflicting_types(self): foo = PythonObject({ "bar": PythonObject({ "baz": 42 }) }) get_manager(foo).add_composite_type( UniversalObjectType({ "bar": UniversalObjectType({ "baz": IntegerType() }) }) ) with self.assertRaises(Exception): get_manager(foo).add_composite_type( UniversalObjectType({ "bar": UniversalObjectType({ "baz": AnyType() }) }) )
def test_python_object_with_reference_can_be_modified(self): bar = PythonObject({ "baz": 42 }) foo = PythonObject({ "bar": bar }) get_manager(bar).add_composite_type(UniversalObjectType({ "baz": IntegerType() })) get_manager(foo).add_composite_type(DEFAULT_COMPOSITE_TYPE) self.assertEqual(foo.bar.baz, 42) foo.bar.baz = 5 self.assertEqual(foo.bar.baz, 5)
def build_object_type(data): properties = {} for name, type in data._get("properties")._items(): properties[name] = enrich_type(type) if type._contains("const") and type._get("const"): properties[name] = Const(properties[name]) wildcard_type = data._contains("wildcard_type") if wildcard_type: wildcard_type = enrich_type(wildcard_type) return UniversalObjectType(properties, wildcard_type=wildcard_type, name="declared-object-type")
def test_simple_fields_are_required(self): T = UniversalObjectType({ }) S = UniversalObjectType({ "foo": IntegerType() }) self.assertTrue(T.is_copyable_from(S, DUMMY_REASONER)) self.assertFalse(S.is_copyable_from(T, DUMMY_REASONER))