#!/usr/bin/env python """ $URL: svn+ssh://svn/repos/trunk/grouch/lib/test/utest_schema.py $ $Id: utest_schema.py 25104 2004-09-14 12:41:32Z dbinger $ """ import sys from types import LongType, IntType, FileType from sancho.utest import UTest from cStringIO import StringIO from grouch.schema import ObjectSchema, ClassDefinition from grouch.test import fake_module # sets up foo.Foo, foo.SubFoo, # and foo.bar.FooBar modules/classes def make_classdef (name, schema, bases=None, attrs=None): # name : string # bases : [string] # attrs : [(string, ValueType)] classdef = ClassDefinition(name, schema, bases) if attrs: for (name, type) in attrs: classdef.add_attribute(name, type) classdef.finish_definition() schema.add_class(classdef) return classdef class SchemaTest (UTest): def _pre (self): pass def _post (self): pass def check_create (self): "create an object schema" schema = ObjectSchema() assert schema.is_atomic_type_name('int') assert not schema.is_atomic_type_name('function') assert schema.get_atomic_type_name(LongType) == "long" assert schema.get_atomic_type_object('long') == LongType def check_atomic (self): "add/fetch atomic types to/from a schema" schema = ObjectSchema() int_type = schema.get_type(IntType) assert int_type.is_atomic_type() assert str(int_type) == "int" assert schema.get_type('int') == int_type assert schema.get_type(int_type) == int_type schema.add_atomic_type(sys.__stdout__, 'file') assert schema.get_atomic_type_name(FileType) == "file" assert schema.get_atomic_type_object('file') == FileType assert schema.get_type('file').type == FileType assert schema.is_atomic_type_name('file') assert not schema.is_atomic_type_name('thingy') schema = ObjectSchema() schema.add_atomic_type(sys.__stdout__, "thingy") assert schema.get_atomic_type_name(FileType) == "thingy" assert schema.get_atomic_type_object('thingy') == FileType assert schema.get_type('thingy').type == FileType assert schema.is_atomic_type_name('thingy') assert not schema.is_atomic_type_name('file') try: schema.add_atomic_type(sys.__stdout__, 'file') assert 0 except ValueError: pass try: schema.add_atomic_type(self._pre, 'thingy') assert 0 except ValueError: pass def check_alias (self): "adding aliases to a schema" schema = ObjectSchema() schema.add_alias("real", "int|float|long") schema.add_alias("pvalue", "(float,string)") assert schema.has_alias('real') assert schema.get_alias('real').is_union_type() schema.add_alias("range", "(real,real)") assert schema.has_alias('range') assert schema.get_alias('range').container_type == "tuple" def check_classdef (self): "add/fetch class definitions to/from a schema" import foo schema = ObjectSchema() assert schema.get_class_definition('foo.Foo') == None assert schema.get_class_definition(foo.Foo) == None Foo_def = make_classdef("foo.Foo", schema) assert schema.get_class_definition('foo.Foo') == Foo_def assert schema.get_class_definition(foo.Foo) == Foo_def try: schema.add_class(Foo_def) assert 0 except RuntimeError: pass def check_gettype (self): "exercise the wildly overloaded 'get_type()' method" from types import FunctionType # not an atomic type! import foo schema = fake_module.make_schema() # so we have some classes defined schema.add_alias("Foo", "foo.Foo") assert schema.get_type(IntType).type == IntType try: schema.get_type(FunctionType) assert 0 except ValueError: pass assert schema.get_type('int').type == IntType assert schema.get_type('foo.Foo').klass_name == "foo.Foo" assert schema.get_type('Foo').alias_type.klass_name == "foo.Foo" try: schema.get_type('blah') assert 0 except ValueError: pass assert schema.get_type(foo.Foo).klass_name == "foo.Foo" int_type = schema.make_atomic_type('int') assert schema.get_type(int_type) is int_type try: schema.get_type(1) assert 0 except TypeError: pass def check_pickle (self): "pickle an object schema" from cPickle import loads, dumps orig = ObjectSchema() copy = loads(dumps(orig)) # Redo the tests for a just-created schema on the recreated one assert copy.is_atomic_type_name('int') assert not copy.is_atomic_type_name('function') assert copy.get_atomic_type_name(LongType) == "long" assert copy.get_atomic_type_object('long') == LongType inttype = copy.get_type(IntType) longtype = copy.get_type(LongType) assert inttype.schema is longtype.schema # Make sure we can pickle a schema with scanner and parser objects # (SPARK classes don't seem to be pickleable). orig.parse_type("[int]") oparser = orig.parser dumps(orig) assert orig.parser is oparser copy = loads(dumps(orig)) copy.parse_type('[int]') # class SchemaTest class ClassDefTest (UTest): def _pre (self): self.schema = ObjectSchema() self.int_type = self.schema.get_type('int') self.float_type = self.schema.get_type('float') def _post (self): pass def _make_classdef (self, name, bases=None, attrs=None): return make_classdef(name, self.schema, bases, attrs) def check_create (self): "create a class definition" # Hmmm, this'll be in trouble if ClassDefinition ever starts # to enforce that the named class must exist... cdef = ClassDefinition("Foo", self.schema) assert cdef.name == "Foo" assert cdef.bases == [] assert cdef.num_attributes() == 0 cdef = ClassDefinition("SubFoo", self.schema, ["Foo"]) assert cdef.bases == ["Foo"] def check_attrs (self): "add/fetch attribute definitions" Foo_def = self._make_classdef("Foo", attrs=[("a", self.int_type), ("__b", self.float_type)]) assert Foo_def.num_attributes() == 2 assert Foo_def.get_attribute_type('a') == self.int_type assert Foo_def.get_attribute_type('_Foo__b') == self.float_type # Should make this work eventually. try: Foo_def.add_attribute('x', 'int') assert 0 except TypeError: pass # But not this! try: Foo_def.add_attribute('x', 42) assert 0 except TypeError: pass Bar_def = self._make_classdef("Bar", attrs=[("c", self.int_type)]) SubFoo_def = self._make_classdef("SubFoo", bases=["Foo", "Bar"], attrs=[("d", self.float_type), ("e", self.int_type)]) assert SubFoo_def._find_bases() == [Foo_def, Bar_def, SubFoo_def] assert len(SubFoo_def.attrs) == 2 assert len(SubFoo_def.attr_types) == 2 assert SubFoo_def.num_attributes() == 5 assert SubFoo_def.get_attribute_type('a') == self.int_type assert SubFoo_def.get_attribute_type('_Foo__b') == self.float_type assert SubFoo_def.get_attribute_type('c') == self.int_type assert SubFoo_def.get_attribute_type('d') == self.float_type SubSubFoo_def = self._make_classdef("SubSubFoo", bases=["SubFoo"]) assert SubSubFoo_def._find_bases() == [ Foo_def, Bar_def, SubFoo_def, SubSubFoo_def] assert len(SubSubFoo_def.attrs) == 0 assert len(SubSubFoo_def.attr_types) == 0 assert SubSubFoo_def.num_attributes() == 5 assert SubSubFoo_def.get_attribute_type('a') == self.int_type assert SubSubFoo_def.get_attribute_type('c') == self.int_type assert SubSubFoo_def.get_attribute_type('d') == self.float_type def check_write (self): "write class definition" cdef = self._make_classdef("Bar") expect = """\ class Bar: pass """ f = StringIO() ; cdef.write(f) assert f.getvalue() == expect cdef = self._make_classdef("Foo", attrs=[("a", self.int_type), ("b", self.float_type)]) expect = """\ class Foo: a : int b : float """ f = StringIO() ; cdef.write(f) assert f.getvalue() == expect cdef = self._make_classdef("SubFoo", bases=["Foo"]) expect = """\ class SubFoo (Foo): pass """ f = StringIO() ; cdef.write(f) assert f.getvalue() == expect # class ClassDefTest if __name__ == "__main__": SchemaTest() ClassDefTest()