def test_tuple_passing(self): T = Tuple(float, int, str) @Compiled def f(x: T) -> T: y = x return y t = T((0.0, 1, "hi")) self.assertEqual(f(t), t)
def test_recursives_held_infinitely_throws(self): X = Forward("X") with self.assertRaisesRegex(Exception, "type-containment cycle"): X = X.define(NamedTuple(x=X)) with self.assertRaisesRegex(Exception, "type-containment cycle"): X = X.define(OneOf(None, X)) with self.assertRaisesRegex(Exception, "type-containment cycle"): X = X.define(Tuple(X))
def test_one_of_in_tuple(self): t = Tuple(OneOf(None, str), str) self.assertEqual(t(("hi","hi2"))[0], "hi") self.assertEqual(t(("hi","hi2"))[1], "hi2") self.assertEqual(t((None,"hi2"))[1], "hi2") self.assertEqual(t((None,"hi2"))[0], None) with self.assertRaises(TypeError): t((None,None)) with self.assertRaises(IndexError): t((None,"hi2"))[2]
def test_bytecount(self): def testfun(x): return _types.bytecount(type(x)) self.assertEqual(testfun(0), 8) def check(x): self.assertEqual( testfun(x), Runtime.singleton().compile(testfun, {'x': type(x)})(x) ) check(0) check(0.0) check(ListOf(int)([10])) check(Tuple(int, int, int)((10, 10, 10)))
def define(self, cls): assert not cls.__name__.startswith("_"), "Illegal to use _ for first character in database classnames." assert not self._frozen, "Schema is already frozen" # get a type stub t = getattr(self, cls.__name__) self._types_to_original[t] = cls # compute baseClasses in order to collect the type's attributes baseClasses = list(cls.__mro__) for i in range(len(baseClasses)): if baseClasses[i] is DatabaseObject: baseClasses = baseClasses[:i] break properBaseClasses = [self._types_to_original.get(b, b) for b in baseClasses] # Collect the type's attributes and populate (_define) the type object # Map: name -> type types = {} for base in reversed(properBaseClasses): for name, val in base.__dict__.items(): if not name.startswith('__'): if isinstance(val, type): types[name] = val elif isinstance(val, Indexed) and isinstance(val.obj, type): types[name] = val.obj t._define(**types) for base in reversed(properBaseClasses): for name, val in base.__dict__.items(): if isinstance(val, Index): self._addTupleIndex(t, name, val.names, Tuple(*tuple(types[k] for k in val.names))) if not name.startswith('__') and isinstance(val, Indexed): self._addIndex(t, name) elif (not name.startswith("__") or name in ["__str__", "__repr__"]): if isinstance(val, (FunctionType, staticmethod, property)): setattr(t, name, val) if hasattr(cls, '__object_database_lazy_subscription__'): t.__object_database_lazy_subscription__ = cls.__object_database_lazy_subscription__ return t
def test_serialize_classes(self): class AClass(Class): x = Member(int) y = Member(float) T = Tuple(AClass, AClass) a = AClass(x=10, y=20.0) a2, a2_copy = deserialize(T, serialize(T, (a, a))) self.assertEqual(a2.x, 10) a2.x = 300 self.assertEqual(a2_copy.x, 300) a2_copy = None self.assertEqual(refcount(a2), 1)
def test_serialize_primitive_compound_types(self): class A: pass B = Alternative("B", X={'a': A}) ts = SerializationContext({'A': A, 'B': B}) for t in [ ConstDict(int, float), NamedTuple(x=int, y=str), TupleOf(bool), Tuple(int, int, bool), OneOf(int, float), OneOf(1, 2, 3, "hi", b"goodbye"), TupleOf(NamedTuple(x=int)), TupleOf(object), TupleOf(A), TupleOf(B) ]: self.assertIs(ping_pong(t, ts), t)
import research_app.Displayable as Displayable from typed_python import python_ast, OneOf, Alternative, TupleOf,\ NamedTuple, Tuple, Class, ConstDict, Member, ListOf import datetime import ast from object_database import Schema, Indexed, current_transaction schema = Schema("research_app.ResearchBackend") @schema.define class ServiceConfig: pass Error = NamedTuple(error=str, line=int, trace = str) CodeBlock = NamedTuple(code=str, line_range=Tuple(int,int)) class ResearchBackend(ServiceBase): def initialize(self, chunkStoreOverride=None): self._logger = logging.getLogger(__file__) self.db.subscribeToSchema(schema) self.db.subscribeToSchema(ContentSchema.schema) self.db.subscribeToSchema(EvaluationSchema.schema) @staticmethod def configureService(database, serviceObject): pass def doWork(self, shouldStop): while not shouldStop.is_set():
def define(self, cls): typename = cls.__name__ assert not typename.startswith("_"), "Illegal to use _ for first character in database classnames." assert not self._frozen, "Schema is already frozen" # get a type stub t = getattr(self, typename) # add the canonical ' exists' property, which we use under the hood to indicate # existence/deletion of an object. self._field_types[typename][' exists'] = bool self._indices[typename][' exists'] = (' exists',) self._index_types[typename][' exists'] = bool t.addField(' exists', bool) t.addIndex(' exists', (' exists',)) # make sure it's not defined yet assert typename in self._undefinedTypes, f"Type {typename} is not undefined." self._undefinedTypes.discard(typename) self._types_to_original[t] = cls # compute baseClasses in order to collect the type's attributes but filter out # object and the DatabaseObjectBase baseClasses = [x for x in cls.__mro__ if x not in (object, DatabaseObjectBase)] properBaseClasses = [self._types_to_original.get(b, b) for b in baseClasses] # Collect the type's attributes and populate the actual type object # Map: name -> type classMembers = {} for base in reversed(properBaseClasses): for name, val in base.__dict__.items(): classMembers[name] = val for name, val in classMembers.items(): isMagic = name[:2] == "__" if isinstance(val, type) and not isMagic: t.addField(name, val) self._field_types[typename][name] = val elif isinstance(val, Indexed): t.addField(name, val.obj) t.addIndex(name, (name,)) self._field_types[typename][name] = val.obj self._indices[typename][name] = (name,) self._index_types[typename][name] = val.obj elif isinstance(val, Index): # do this in a second pass pass elif isinstance(val, property): t.addProperty(name, val.fget, val.fset) elif isinstance(val, staticmethod): t.addStaticMethod(name, val.__func__) elif isinstance(val, FunctionType): t.addMethod(name, val) for name, val in classMembers.items(): if isinstance(val, Index): t.addIndex(name, tuple(val.names)) assert len(val.names) self._indices[typename][name] = tuple(val.names) if len(val.names) > 1: self._index_types[typename][name] = Tuple(*[self._field_types[typename][fieldname] for fieldname in val.names]) else: self._index_types[typename][name] = self._field_types[typename][val.names[0]] t.finalize() if hasattr(cls, '__object_database_lazy_subscription__'): t.markLazyByDefault() return t
def raising(e): raise e Type = Forward("Type") Type = Type.define( Alternative( "Type", Void={}, Float={'bits': int}, Int={ 'bits': int, 'signed': bool }, Struct={ 'element_types': TupleOf(Tuple(str, Type)), 'name': str }, Array={ 'element_type': Type, 'count': int }, Function={ 'output': Type, 'args': TupleOf(Type), 'varargs': bool, 'can_throw': bool }, Pointer={'value_type': Type}, attr_ix=type_attr_ix, __str__=type_str,
"set_removes": ConstDict(IndexId, TupleOf(ObjectId)), "key_versions": TupleOf(ObjectFieldId), "index_versions": TupleOf(IndexId), "transaction_guid": int }, CompleteTransaction={ "as_of_version": int, "transaction_guid": int }, Heartbeat={}, DefineSchema={ 'name': str, 'definition': SchemaDefinition }, LoadLazyObject={ 'schema': str, 'typename': str, 'identity': ObjectId }, Subscribe={ 'schema': str, 'typename': OneOf(None, str), 'fieldname_and_value': OneOf(None, Tuple(str, IndexValue)), 'isLazy': bool # load values when we first request them, instead of blocking on all the data. }, Flush={'guid': int}, Authenticate={'token': str} ) ServerToClient = Alternative( "ServerToClient", Initialize={'transaction_num': int, 'connIdentity': ObjectId, 'identity_root': int}, TransactionResult={'transaction_guid': int, 'success': bool, 'badKey': OneOf(None, ObjectFieldId, IndexId, str) }, SchemaMapping={ 'schema': str, 'mapping': ConstDict(FieldDefinition, int) }, FlushResponse={'guid': int}, SubscriptionData={ 'schema': str,
def test_tuple(self): self.assertEqual( Tuple(int, int, OneOf(10, 20)).ElementTypes, (Int64(), Int64(), OneOf(10, 20)))
def instancesOf(T): """Produce some instances of type T""" if T is type(None): # noqa return [None] if T is bool: return [True, False] if T in (int, float, Int8, Int16, Int32, Float32): return [T(x) for x in [-2, -1, 0, 1, 2]] if T in (UInt8, UInt16, UInt32, UInt64): return [T(x) for x in [0, 1, 2]] if T is str: return ['', 'a', 'b', 'ab', 'ba'] if T is bytes: return [b'', b'a', b'b', b'ab', b'ba'] if T is ListOf(int): return [ ListOf(int)(), ListOf(int)([1]), ListOf(int)([2]), ListOf(int)([1, 2]), ListOf(int)([2, 1]) ] if T is ListOf(str): return [ ListOf(str)(), ListOf(str)(['a']), ListOf(str)(['b']), ListOf(str)(['a', 'b']), ListOf(str)(['b', 'a']) ] if T is TupleOf(int): return [ TupleOf(int)(), TupleOf(int)([1]), TupleOf(int)([2]), TupleOf(int)([1, 2]), TupleOf(int)([2, 1]) ] if T is TupleOf(str): return [ TupleOf(str)(), TupleOf(str)(['a']), TupleOf(str)(['b']), TupleOf(str)(['a', 'b']), TupleOf(str)(['b', 'a']) ] if T is Tuple(int, int, int): return [T((1, 2, 3)), T((2, 2, 3)), T((3, 2, 1))] if T is Tuple(str, int, str): return [T(('1', 2, '3')), T(('2', 2, '3')), T(('3', 2, '1'))] if T is Dict(int, int): return [T({1: 2}), T({3: 4}), T({1: 2, 3: 4})] if T is Dict(str, str): return [T({'1': '2'}), T({'3': '4'}), T({'1': '2', '3': '4'})] assert False, f"Can't make instances of {T}"
return dict assert False, f"No pyType for {T}" # the types we will test. types = [ type(None), bool, int, float, str, bytes, UInt8, UInt16, UInt32, UInt64, Int8, Int16, Int32, Float32, ListOf(int), ListOf(str), TupleOf(int), TupleOf(str), Dict(int, int), Dict(str, str), Tuple(int, int, int), Tuple(str, int, str) ] def instancesOf(T): """Produce some instances of type T""" if T is type(None): # noqa return [None] if T is bool: return [True, False] if T in (int, float, Int8, Int16, Int32, Float32): return [T(x) for x in [-2, -1, 0, 1, 2]]
def makeTuple(*args): if not args: return Tuple()() return Tuple(*[typeFor(v) for v in args])(args)