def test_collection_with_backref(self): for base in (object, MyBaseClass, MyClass): class Post(base):pass class Blog(base):pass attributes.register_class(Post) attributes.register_class(Blog) attributes.register_attribute(Post, 'blog', uselist=False, extension=attributes.GenericBackrefExtension('posts'), trackparent=True, useobject=True) attributes.register_attribute(Blog, 'posts', uselist=True, extension=attributes.GenericBackrefExtension('blog'), trackparent=True, useobject=True) b = Blog() (p1, p2, p3) = (Post(), Post(), Post()) b.posts.append(p1) b.posts.append(p2) b.posts.append(p3) self.assert_(b.posts == [p1, p2, p3]) self.assert_(p2.blog is b) p3.blog = None self.assert_(b.posts == [p1, p2]) p4 = Post() p4.blog = b self.assert_(b.posts == [p1, p2, p4]) p4.blog = b p4.blog = b self.assert_(b.posts == [p1, p2, p4]) # assert no failure removing None p5 = Post() p5.blog = None del p5.blog
def test_collections_via_backref(self): class Foo(_base.BasicEntity): pass class Bar(_base.BasicEntity): pass attributes.register_class(Foo) attributes.register_class(Bar) attributes.register_attribute(Foo, 'bars', uselist=True, extension=attributes.GenericBackrefExtension('foo'), trackparent=True, useobject=True) attributes.register_attribute(Bar, 'foo', uselist=False, extension=attributes.GenericBackrefExtension('bars'), trackparent=True, useobject=True) f1 = Foo() b1 = Bar() eq_(attributes.get_history(attributes.instance_state(f1), 'bars'), ((), [], ())) eq_(attributes.get_history(attributes.instance_state(b1), 'foo'), ((), [None], ())) #b1.foo = f1 f1.bars.append(b1) eq_(attributes.get_history(attributes.instance_state(f1), 'bars'), ([b1], [], [])) eq_(attributes.get_history(attributes.instance_state(b1), 'foo'), ([f1], (), ())) b2 = Bar() f1.bars.append(b2) eq_(attributes.get_history(attributes.instance_state(f1), 'bars'), ([b1, b2], [], [])) eq_(attributes.get_history(attributes.instance_state(b1), 'foo'), ([f1], (), ())) eq_(attributes.get_history(attributes.instance_state(b2), 'foo'), ([f1], (), ()))
def test_parenttrack(self): class Foo(object):pass class Bar(object):pass attributes.register_class(Foo) attributes.register_class(Bar) attributes.register_attribute(Foo, 'element', uselist=False, trackparent=True, useobject=True) attributes.register_attribute(Bar, 'element', uselist=False, trackparent=True, useobject=True) f1 = Foo() f2 = Foo() b1 = Bar() b2 = Bar() f1.element = b1 b2.element = f2 assert attributes.has_parent(Foo, b1, 'element') assert not attributes.has_parent(Foo, b2, 'element') assert not attributes.has_parent(Foo, f2, 'element') assert attributes.has_parent(Bar, f2, 'element') b2.element = None assert not attributes.has_parent(Bar, f2, 'element') # test that double assignment doesn't accidentally reset the 'parent' flag. b3 = Bar() f4 = Foo() b3.element = f4 assert attributes.has_parent(Bar, f4, 'element') b3.element = f4 assert attributes.has_parent(Bar, f4, 'element')
def test_dict_collections(self): class Foo(fixtures.Base): pass class Bar(fixtures.Base): pass from sqlalchemy.orm.collections import attribute_mapped_collection attributes.register_class(Foo) attributes.register_attribute(Foo, 'someattr', uselist=True, useobject=True, typecallable=attribute_mapped_collection('name')) hi = Bar(name='hi') there = Bar(name='there') old = Bar(name='old') new = Bar(name='new') f = Foo() self.assertEquals(attributes.get_history(f._state, 'someattr'), ([], [], [])) f.someattr['hi'] = hi self.assertEquals(attributes.get_history(f._state, 'someattr'), ([hi], [], [])) f.someattr['there'] = there self.assertEquals(tuple([set(x) for x in attributes.get_history(f._state, 'someattr')]), (set([hi, there]), set([]), set([]))) f._state.commit(['someattr']) self.assertEquals(tuple([set(x) for x in attributes.get_history(f._state, 'someattr')]), (set([]), set([hi, there]), set([])))
def test_collections_via_backref(self): class Foo(fixtures.Base): pass class Bar(fixtures.Base): pass attributes.register_class(Foo) attributes.register_class(Bar) attributes.register_attribute(Foo, 'bars', uselist=True, extension=attributes.GenericBackrefExtension('foo'), trackparent=True, useobject=True) attributes.register_attribute(Bar, 'foo', uselist=False, extension=attributes.GenericBackrefExtension('bars'), trackparent=True, useobject=True) f1 = Foo() b1 = Bar() self.assertEquals(attributes.get_history(f1._state, 'bars'), ([], [], [])) self.assertEquals(attributes.get_history(b1._state, 'foo'), ([], [None], [])) #b1.foo = f1 f1.bars.append(b1) self.assertEquals(attributes.get_history(f1._state, 'bars'), ([b1], [], [])) self.assertEquals(attributes.get_history(b1._state, 'foo'), ([f1], [], [])) b2 = Bar() f1.bars.append(b2) self.assertEquals(attributes.get_history(f1._state, 'bars'), ([b1, b2], [], [])) self.assertEquals(attributes.get_history(b1._state, 'foo'), ([f1], [], [])) self.assertEquals(attributes.get_history(b2._state, 'foo'), ([f1], [], []))
def test_list(self): class User(object):pass class Address(object):pass attributes.register_class(User) attributes.register_class(Address) attributes.register_attribute(User, 'user_id', uselist=False, useobject=False) attributes.register_attribute(User, 'user_name', uselist=False, useobject=False) attributes.register_attribute(User, 'addresses', uselist = True, useobject=True) attributes.register_attribute(Address, 'address_id', uselist=False, useobject=False) attributes.register_attribute(Address, 'email_address', uselist=False, useobject=False) u = User() u.user_id = 7 u.user_name = 'john' u.addresses = [] a = Address() a.address_id = 10 a.email_address = '*****@*****.**' u.addresses.append(a) self.assert_(u.user_id == 7 and u.user_name == 'john' and u.addresses[0].email_address == '*****@*****.**') u, attributes.instance_state(a).commit_all() self.assert_(u.user_id == 7 and u.user_name == 'john' and u.addresses[0].email_address == '*****@*****.**') u.user_name = 'heythere' a = Address() a.address_id = 11 a.email_address = '*****@*****.**' u.addresses.append(a) self.assert_(u.user_id == 7 and u.user_name == 'heythere' and u.addresses[0].email_address == '*****@*****.**' and u.addresses[1].email_address == '*****@*****.**')
def test_lazy_backref_collections(self): class Foo(_base.BasicEntity): pass class Bar(_base.BasicEntity): pass lazy_load = [] def lazyload(instance): def load(): return lazy_load return load attributes.register_class(Foo) attributes.register_class(Bar) attributes.register_attribute(Foo, 'bars', uselist=True, extension=attributes.GenericBackrefExtension('foo'), trackparent=True, callable_=lazyload, useobject=True) attributes.register_attribute(Bar, 'foo', uselist=False, extension=attributes.GenericBackrefExtension('bars'), trackparent=True, useobject=True) bar1, bar2, bar3, bar4 = [Bar(id=1), Bar(id=2), Bar(id=3), Bar(id=4)] lazy_load = [bar1, bar2, bar3] f = Foo() bar4 = Bar() bar4.foo = f eq_(attributes.get_history(attributes.instance_state(f), 'bars'), ([bar4], [bar1, bar2, bar3], [])) lazy_load = None f = Foo() bar4 = Bar() bar4.foo = f eq_(attributes.get_history(attributes.instance_state(f), 'bars'), ([bar4], [], [])) lazy_load = [bar1, bar2, bar3] attributes.instance_state(f).expire_attributes(['bars']) eq_(attributes.get_history(attributes.instance_state(f), 'bars'), ((), [bar1, bar2, bar3], ()))
def setUp(self): global Post, Blog, called, lazy_load class Post(object): def __init__(self, name): self.name = name __hash__ = None def __eq__(self, other): return other.name == self.name class Blog(object): def __init__(self, name): self.name = name __hash__ = None def __eq__(self, other): return other.name == self.name called = [0] lazy_load = [] def lazy_posts(instance): def load(): called[0] += 1 return lazy_load return load attributes.register_class(Post) attributes.register_class(Blog) attributes.register_attribute(Post, 'blog', uselist=False, extension=attributes.GenericBackrefExtension('posts'), trackparent=True, useobject=True) attributes.register_attribute(Blog, 'posts', uselist=True, extension=attributes.GenericBackrefExtension('blog'), callable_=lazy_posts, trackparent=True, useobject=True)
def test_lazytrackparent(self): """test that the "hasparent" flag works properly when lazy loaders and backrefs are used""" class Post(object):pass class Blog(object):pass attributes.register_class(Post) attributes.register_class(Blog) # set up instrumented attributes with backrefs attributes.register_attribute(Post, 'blog', uselist=False, extension=attributes.GenericBackrefExtension('posts'), trackparent=True, useobject=True) attributes.register_attribute(Blog, 'posts', uselist=True, extension=attributes.GenericBackrefExtension('blog'), trackparent=True, useobject=True) # create objects as if they'd been freshly loaded from the database (without history) b = Blog() p1 = Post() attributes.instance_state(b).set_callable('posts', lambda:[p1]) attributes.instance_state(p1).set_callable('blog', lambda:b) p1, attributes.instance_state(b).commit_all() # no orphans (called before the lazy loaders fire off) assert attributes.has_parent(Blog, p1, 'posts', optimistic=True) assert attributes.has_parent(Post, b, 'blog', optimistic=True) # assert connections assert p1.blog is b assert p1 in b.posts # manual connections b2 = Blog() p2 = Post() b2.posts.append(p2) assert attributes.has_parent(Blog, p2, 'posts') assert attributes.has_parent(Post, b2, 'blog')
def test_dict_collections(self): class Foo(_base.BasicEntity): pass class Bar(_base.BasicEntity): pass from sqlalchemy.orm.collections import attribute_mapped_collection attributes.register_class(Foo) attributes.register_attribute(Foo, 'someattr', uselist=True, useobject=True, typecallable=attribute_mapped_collection('name')) hi = Bar(name='hi') there = Bar(name='there') old = Bar(name='old') new = Bar(name='new') f = Foo() eq_(attributes.get_history(attributes.instance_state(f), 'someattr'), ((), [], ())) f.someattr['hi'] = hi eq_(attributes.get_history(attributes.instance_state(f), 'someattr'), ([hi], [], [])) f.someattr['there'] = there eq_(tuple([set(x) for x in attributes.get_history(attributes.instance_state(f), 'someattr')]), (set([hi, there]), set(), set())) attributes.instance_state(f).commit(['someattr']) eq_(tuple([set(x) for x in attributes.get_history(attributes.instance_state(f), 'someattr')]), (set(), set([hi, there]), set()))
def test_deferred(self): for base in (object, MyBaseClass, MyClass): class Foo(base): pass data = {'a': 'this is a', 'b': 12} def loader(state, keys): for k in keys: state.dict[k] = data[k] return attributes.ATTR_WAS_SET manager = register_class(Foo) manager.deferred_scalar_loader = loader attributes.register_attribute(Foo, 'a', uselist=False, useobject=False) attributes.register_attribute(Foo, 'b', uselist=False, useobject=False) if base is object: assert Foo not in instrumentation._instrumentation_factory._state_finders else: assert Foo in instrumentation._instrumentation_factory._state_finders f = Foo() attributes.instance_state(f)._expire(attributes.instance_dict(f), set()) eq_(f.a, "this is a") eq_(f.b, 12) f.a = "this is some new a" attributes.instance_state(f)._expire(attributes.instance_dict(f), set()) eq_(f.a, "this is a") eq_(f.b, 12) attributes.instance_state(f)._expire(attributes.instance_dict(f), set()) f.a = "this is another new a" eq_(f.a, "this is another new a") eq_(f.b, 12) attributes.instance_state(f)._expire(attributes.instance_dict(f), set()) eq_(f.a, "this is a") eq_(f.b, 12) del f.a eq_(f.a, None) eq_(f.b, 12) attributes.instance_state(f)._commit_all( attributes.instance_dict(f)) eq_(f.a, None) eq_(f.b, 12)
def test_uninstrument(self): class A: pass manager = instrumentation.register_class(A) attributes.register_attribute( A, "x", comparator=object(), parententity=object(), uselist=False, useobject=False, ) assert instrumentation.manager_of_class(A) is manager instrumentation.unregister_class(A) assert instrumentation.opt_manager_of_class(A) is None assert not hasattr(A, "x") with expect_raises_message( sa.orm.exc.UnmappedClassError, r"Can't locate an instrumentation manager for class .*A", ): instrumentation.manager_of_class(A) assert A.__init__ == object.__init__
def instrument_class(self, mapper): attributes.register_attribute(mapper.class_, self.key, comparator=self.Comparator(self, mapper), parententity=mapper, doc=self.doc, impl_class=GenericAttributeImpl, parent_token=self)
def test_scalar(self): class Foo(_base.BasicEntity): pass attributes.register_class(Foo) attributes.register_attribute(Foo, 'someattr', uselist=False, useobject=False) # case 1. new object f = Foo() eq_(attributes.get_history(attributes.instance_state(f), 'someattr'), ((), (), ())) f.someattr = "hi" eq_(attributes.get_history(attributes.instance_state(f), 'someattr'), (['hi'], (), ())) attributes.instance_state(f).commit(['someattr']) eq_(attributes.get_history(attributes.instance_state(f), 'someattr'), ((), ['hi'], ())) f.someattr = 'there' eq_(attributes.get_history(attributes.instance_state(f), 'someattr'), (['there'], (), ['hi'])) attributes.instance_state(f).commit(['someattr']) eq_(attributes.get_history(attributes.instance_state(f), 'someattr'), ((), ['there'], ())) del f.someattr eq_(attributes.get_history(attributes.instance_state(f), 'someattr'), ((), (), ['there'])) # case 2. object with direct dictionary settings (similar to a load operation) f = Foo() f.__dict__['someattr'] = 'new' eq_(attributes.get_history(attributes.instance_state(f), 'someattr'), ((), ['new'], ())) f.someattr = 'old' eq_(attributes.get_history(attributes.instance_state(f), 'someattr'), (['old'], (), ['new'])) attributes.instance_state(f).commit(['someattr']) eq_(attributes.get_history(attributes.instance_state(f), 'someattr'), ((), ['old'], ())) # setting None on uninitialized is currently a change for a scalar attribute # no lazyload occurs so this allows overwrite operation to proceed f = Foo() eq_(attributes.get_history(attributes.instance_state(f), 'someattr'), ((), (), ())) f.someattr = None eq_(attributes.get_history(attributes.instance_state(f), 'someattr'), ([None], (), ())) f = Foo() f.__dict__['someattr'] = 'new' eq_(attributes.get_history(attributes.instance_state(f), 'someattr'), ((), ['new'], ())) f.someattr = None eq_(attributes.get_history(attributes.instance_state(f), 'someattr'), ([None], (), ['new'])) # set same value twice f = Foo() attributes.instance_state(f).commit(['someattr']) f.someattr = 'one' eq_(attributes.get_history(attributes.instance_state(f), 'someattr'), (['one'], (), ())) f.someattr = 'two' eq_(attributes.get_history(attributes.instance_state(f), 'someattr'), (['two'], (), ()))
def test_null_instrumentation(self): class Foo(MyBaseClass): pass attributes.register_class(Foo) attributes.register_attribute(Foo, "name", uselist=False, useobject=False) attributes.register_attribute(Foo, "bars", uselist=True, trackparent=True, useobject=True) assert Foo.name == attributes.manager_of_class(Foo)['name'] assert Foo.bars == attributes.manager_of_class(Foo)['bars']
def test_deferred(self): for base in (object, MyBaseClass, MyClass): class Foo(base): pass data = {'a': 'this is a', 'b': 12} def loader(state, keys): for k in keys: state.dict[k] = data[k] return attributes.ATTR_WAS_SET manager = register_class(Foo) manager.deferred_scalar_loader = loader attributes.register_attribute( Foo, 'a', uselist=False, useobject=False) attributes.register_attribute( Foo, 'b', uselist=False, useobject=False) if base is object: assert Foo not in \ instrumentation._instrumentation_factory._state_finders else: assert Foo in \ instrumentation._instrumentation_factory._state_finders f = Foo() attributes.instance_state(f)._expire( attributes.instance_dict(f), set()) eq_(f.a, "this is a") eq_(f.b, 12) f.a = "this is some new a" attributes.instance_state(f)._expire( attributes.instance_dict(f), set()) eq_(f.a, "this is a") eq_(f.b, 12) attributes.instance_state(f)._expire( attributes.instance_dict(f), set()) f.a = "this is another new a" eq_(f.a, "this is another new a") eq_(f.b, 12) attributes.instance_state(f)._expire( attributes.instance_dict(f), set()) eq_(f.a, "this is a") eq_(f.b, 12) del f.a eq_(f.a, None) eq_(f.b, 12) attributes.instance_state(f)._commit_all( attributes.instance_dict(f)) eq_(f.a, None) eq_(f.b, 12)
def instrument_class(self, mapper): attributes.register_attribute( mapper.class_, self.key, comparator=self.Comparator(self, mapper), parententity=mapper, doc=self.doc, impl_class=GenericAttributeImpl, parent_token=self )
def test_deferred(self): for base in (object, MyBaseClass, MyClass): class Foo(base): pass data = {'a': 'this is a', 'b': 12} def loader(state, keys): for k in keys: state.dict[k] = data[k] return attributes.ATTR_WAS_SET attributes.register_class(Foo) manager = attributes.manager_of_class(Foo) manager.deferred_scalar_loader = loader attributes.register_attribute(Foo, 'a', uselist=False, useobject=False) attributes.register_attribute(Foo, 'b', uselist=False, useobject=False) assert Foo in attributes.instrumentation_registry.state_finders f = Foo() attributes.instance_state(f).expire_attributes(None) self.assertEquals(f.a, "this is a") self.assertEquals(f.b, 12) f.a = "this is some new a" attributes.instance_state(f).expire_attributes(None) self.assertEquals(f.a, "this is a") self.assertEquals(f.b, 12) attributes.instance_state(f).expire_attributes(None) f.a = "this is another new a" self.assertEquals(f.a, "this is another new a") self.assertEquals(f.b, 12) attributes.instance_state(f).expire_attributes(None) self.assertEquals(f.a, "this is a") self.assertEquals(f.b, 12) del f.a self.assertEquals(f.a, None) self.assertEquals(f.b, 12) attributes.instance_state(f).commit_all() self.assertEquals(f.a, None) self.assertEquals(f.b, 12)
def test_uninstrument(self): class A(object): pass manager = instrumentation.register_class(A) attributes.register_attribute(A, "x", uselist=False, useobject=False) assert instrumentation.manager_of_class(A) is manager instrumentation.unregister_class(A) assert instrumentation.manager_of_class(A) is None assert not hasattr(A, "x") assert A.__init__ == object.__init__
def test_object_collections_set(self): class Foo(_base.BasicEntity): pass class Bar(_base.BasicEntity): def __nonzero__(self): assert False attributes.register_class(Foo) attributes.register_attribute(Foo, 'someattr', uselist=True, useobject=True) hi = Bar(name='hi') there = Bar(name='there') old = Bar(name='old') new = Bar(name='new') # case 1. new object f = Foo() eq_(attributes.get_history(attributes.instance_state(f), 'someattr'), ((), [], ())) f.someattr = [hi] eq_(attributes.get_history(attributes.instance_state(f), 'someattr'), ([hi], [], [])) attributes.instance_state(f).commit(['someattr']) eq_(attributes.get_history(attributes.instance_state(f), 'someattr'), ((), [hi], ())) f.someattr = [there] eq_(attributes.get_history(attributes.instance_state(f), 'someattr'), ([there], [], [hi])) attributes.instance_state(f).commit(['someattr']) eq_(attributes.get_history(attributes.instance_state(f), 'someattr'), ((), [there], ())) f.someattr = [hi] eq_(attributes.get_history(attributes.instance_state(f), 'someattr'), ([hi], [], [there])) f.someattr = [old, new] eq_(attributes.get_history(attributes.instance_state(f), 'someattr'), ([old, new], [], [there])) # case 2. object with direct settings (similar to a load operation) f = Foo() collection = attributes.init_collection(attributes.instance_state(f), 'someattr') collection.append_without_event(new) attributes.instance_state(f).commit_all() eq_(attributes.get_history(attributes.instance_state(f), 'someattr'), ((), [new], ())) f.someattr = [old] eq_(attributes.get_history(attributes.instance_state(f), 'someattr'), ([old], [], [new])) attributes.instance_state(f).commit(['someattr']) eq_(attributes.get_history(attributes.instance_state(f), 'someattr'), ((), [old], ()))
def test_object_collections_set(self): class Foo(fixtures.Base): pass class Bar(fixtures.Base): def __nonzero__(self): assert False attributes.register_class(Foo) attributes.register_attribute(Foo, 'someattr', uselist=True, useobject=True) hi = Bar(name='hi') there = Bar(name='there') old = Bar(name='old') new = Bar(name='new') # case 1. new object f = Foo() self.assertEquals(attributes.get_history(f._state, 'someattr'), ([], [], [])) f.someattr = [hi] self.assertEquals(attributes.get_history(f._state, 'someattr'), ([hi], [], [])) f._state.commit(['someattr']) self.assertEquals(attributes.get_history(f._state, 'someattr'), ([], [hi], [])) f.someattr = [there] self.assertEquals(attributes.get_history(f._state, 'someattr'), ([there], [], [hi])) f._state.commit(['someattr']) self.assertEquals(attributes.get_history(f._state, 'someattr'), ([], [there], [])) f.someattr = [hi] self.assertEquals(attributes.get_history(f._state, 'someattr'), ([hi], [], [there])) f.someattr = [old, new] self.assertEquals(attributes.get_history(f._state, 'someattr'), ([old, new], [], [there])) # case 2. object with direct settings (similar to a load operation) f = Foo() collection = attributes.init_collection(f, 'someattr') collection.append_without_event(new) f._state.commit_all() self.assertEquals(attributes.get_history(f._state, 'someattr'), ([], [new], [])) f.someattr = [old] self.assertEquals(attributes.get_history(f._state, 'someattr'), ([old], [], [new])) f._state.commit(['someattr']) self.assertEquals(attributes.get_history(f._state, 'someattr'), ([], [old], []))
def test_scalar(self): class Foo(fixtures.Base): pass attributes.register_class(Foo) attributes.register_attribute(Foo, 'someattr', uselist=False, useobject=False) # case 1. new object f = Foo() self.assertEquals(attributes.get_history(f._state, 'someattr'), ([], [], [])) f.someattr = "hi" self.assertEquals(attributes.get_history(f._state, 'someattr'), (['hi'], [], [])) f._state.commit(['someattr']) self.assertEquals(attributes.get_history(f._state, 'someattr'), ([], ['hi'], [])) f.someattr = 'there' self.assertEquals(attributes.get_history(f._state, 'someattr'), (['there'], [], ['hi'])) f._state.commit(['someattr']) self.assertEquals(attributes.get_history(f._state, 'someattr'), ([], ['there'], [])) del f.someattr self.assertEquals(attributes.get_history(f._state, 'someattr'), ([], [], ['there'])) # case 2. object with direct dictionary settings (similar to a load operation) f = Foo() f.__dict__['someattr'] = 'new' self.assertEquals(attributes.get_history(f._state, 'someattr'), ([], ['new'], [])) f.someattr = 'old' self.assertEquals(attributes.get_history(f._state, 'someattr'), (['old'], [], ['new'])) f._state.commit(['someattr']) self.assertEquals(attributes.get_history(f._state, 'someattr'), ([], ['old'], [])) # setting None on uninitialized is currently a change for a scalar attribute # no lazyload occurs so this allows overwrite operation to proceed f = Foo() self.assertEquals(attributes.get_history(f._state, 'someattr'), ([], [], [])) f.someattr = None self.assertEquals(attributes.get_history(f._state, 'someattr'), ([None], [], [])) f = Foo() f.__dict__['someattr'] = 'new' self.assertEquals(attributes.get_history(f._state, 'someattr'), ([], ['new'], [])) f.someattr = None self.assertEquals(attributes.get_history(f._state, 'someattr'), ([None], [], ['new']))
def test_uninstrument(self): class A(object):pass manager = instrumentation.register_class(A) attributes.register_attribute(A, 'x', uselist=False, useobject=False) assert instrumentation.manager_of_class(A) is manager instrumentation.unregister_class(A) assert instrumentation.manager_of_class(A) is None assert not hasattr(A, 'x') # I prefer 'is' here but on pypy # it seems only == works assert A.__init__ == object.__init__
def test_collectionclasses(self): class Foo(object):pass attributes.register_class(Foo) attributes.register_attribute(Foo, "collection", uselist=True, typecallable=set, useobject=True) assert isinstance(Foo().collection, set) attributes.unregister_attribute(Foo, "collection") try: attributes.register_attribute(Foo, "collection", uselist=True, typecallable=dict, useobject=True) assert False except exceptions.ArgumentError, e: assert str(e) == "Type InstrumentedDict must elect an appender method to be a collection class"
def test_collection_with_backref(self): for base in (object, MyBaseClass, MyClass): class Post(base): pass class Blog(base): pass register_class(Post) register_class(Blog) attributes.register_attribute( Post, "blog", uselist=False, backref="posts", trackparent=True, useobject=True, ) attributes.register_attribute( Blog, "posts", uselist=True, backref="blog", trackparent=True, useobject=True, ) b = Blog() (p1, p2, p3) = (Post(), Post(), Post()) b.posts.append(p1) b.posts.append(p2) b.posts.append(p3) self.assert_(b.posts == [p1, p2, p3]) self.assert_(p2.blog is b) p3.blog = None self.assert_(b.posts == [p1, p2]) p4 = Post() p4.blog = b self.assert_(b.posts == [p1, p2, p4]) p4.blog = b p4.blog = b self.assert_(b.posts == [p1, p2, p4]) # assert no failure removing None p5 = Post() p5.blog = None del p5.blog
def test_onetoone(self): class Port(object):pass class Jack(object):pass attributes.register_class(Port) attributes.register_class(Jack) attributes.register_attribute(Port, 'jack', uselist=False, extension=attributes.GenericBackrefExtension('port'), useobject=True) attributes.register_attribute(Jack, 'port', uselist=False, extension=attributes.GenericBackrefExtension('jack'), useobject=True) p = Port() j = Jack() p.jack = j self.assert_(j.port is p) self.assert_(p.jack is not None) j.port = None self.assert_(p.jack is None)
def test_uninstrument(self): class A(object): pass manager = instrumentation.register_class(A) attributes.register_attribute(A, 'x', uselist=False, useobject=False) assert instrumentation.manager_of_class(A) is manager instrumentation.unregister_class(A) assert instrumentation.manager_of_class(A) is None assert not hasattr(A, 'x') # I prefer 'is' here but on pypy # it seems only == works assert A.__init__ == object.__init__
def test_deferred_pickleable(self): data = {'a':'this is a', 'b':12} def loader(instance, keys): for k in keys: instance.__dict__[k] = data[k] return attributes.ATTR_WAS_SET attributes.register_class(MyTest, deferred_scalar_loader=loader) attributes.register_attribute(MyTest, 'a', uselist=False, useobject=False) attributes.register_attribute(MyTest, 'b', uselist=False, useobject=False) m = MyTest() m._state.expire_attributes(None) assert 'a' not in m.__dict__ m2 = pickle.loads(pickle.dumps(m)) assert 'a' not in m2.__dict__ self.assertEquals(m2.a, "this is a") self.assertEquals(m2.b, 12)
def test_get_committed_value(self): class Foo(fixtures.Base): pass attributes.register_class(Foo) attributes.register_attribute(Foo, 'someattr', uselist=False, useobject=False) f = Foo() self.assertEquals(Foo.someattr.impl.get_committed_value(f._state), None) f.someattr = 3 self.assertEquals(Foo.someattr.impl.get_committed_value(f._state), None) f = Foo() f.someattr = 3 self.assertEquals(Foo.someattr.impl.get_committed_value(f._state), None) f._state.commit(['someattr']) self.assertEquals(Foo.someattr.impl.get_committed_value(f._state), 3)
def test_deferred(self): for base in (object, MyBaseClass, MyClass): class Foo(base):pass data = {'a':'this is a', 'b':12} def loader(state, keys): for k in keys: state.dict[k] = data[k] return attributes.ATTR_WAS_SET attributes.register_class(Foo) manager = attributes.manager_of_class(Foo) manager.deferred_scalar_loader = loader attributes.register_attribute(Foo, 'a', uselist=False, useobject=False) attributes.register_attribute(Foo, 'b', uselist=False, useobject=False) assert Foo in attributes.instrumentation_registry._state_finders f = Foo() attributes.instance_state(f).expire_attributes(None) self.assertEquals(f.a, "this is a") self.assertEquals(f.b, 12) f.a = "this is some new a" attributes.instance_state(f).expire_attributes(None) self.assertEquals(f.a, "this is a") self.assertEquals(f.b, 12) attributes.instance_state(f).expire_attributes(None) f.a = "this is another new a" self.assertEquals(f.a, "this is another new a") self.assertEquals(f.b, 12) attributes.instance_state(f).expire_attributes(None) self.assertEquals(f.a, "this is a") self.assertEquals(f.b, 12) del f.a self.assertEquals(f.a, None) self.assertEquals(f.b, 12) attributes.instance_state(f).commit_all() self.assertEquals(f.a, None) self.assertEquals(f.b, 12)
def test_get_committed_value(self): class Foo(_base.BasicEntity): pass attributes.register_class(Foo) attributes.register_attribute(Foo, 'someattr', uselist=False, useobject=False) f = Foo() eq_(Foo.someattr.impl.get_committed_value(attributes.instance_state(f)), None) f.someattr = 3 eq_(Foo.someattr.impl.get_committed_value(attributes.instance_state(f)), None) f = Foo() f.someattr = 3 eq_(Foo.someattr.impl.get_committed_value(attributes.instance_state(f)), None) attributes.instance_state(f).commit(['someattr']) eq_(Foo.someattr.impl.get_committed_value(attributes.instance_state(f)), 3)
def test_deferred_pickleable(self): data = {'a':'this is a', 'b':12} def loader(state, keys): for k in keys: state.dict[k] = data[k] return attributes.ATTR_WAS_SET attributes.register_class(MyTest) manager = attributes.manager_of_class(MyTest) manager.deferred_scalar_loader=loader attributes.register_attribute(MyTest, 'a', uselist=False, useobject=False) attributes.register_attribute(MyTest, 'b', uselist=False, useobject=False) m = MyTest() attributes.instance_state(m).expire_attributes(None) assert 'a' not in m.__dict__ m2 = pickle.loads(pickle.dumps(m)) assert 'a' not in m2.__dict__ eq_(m2.a, "this is a") eq_(m2.b, 12)
def test_collections_via_lazyload(self): class Foo(_base.BasicEntity): pass class Bar(_base.BasicEntity): pass lazy_load = [] def lazyload(instance): def load(): return lazy_load return load attributes.register_class(Foo) attributes.register_class(Bar) attributes.register_attribute(Foo, 'bars', uselist=True, callable_=lazyload, trackparent=True, useobject=True) bar1, bar2, bar3, bar4 = [Bar(id=1), Bar(id=2), Bar(id=3), Bar(id=4)] lazy_load = [bar1, bar2, bar3] f = Foo() f.bars = [] eq_(attributes.get_history(attributes.instance_state(f), 'bars'), ([], [], [bar1, bar2, bar3])) f = Foo() f.bars.append(bar4) eq_(attributes.get_history(attributes.instance_state(f), 'bars'), ([bar4], [bar1, bar2, bar3], []) ) f = Foo() f.bars.remove(bar2) eq_(attributes.get_history(attributes.instance_state(f), 'bars'), ([], [bar1, bar3], [bar2])) f.bars.append(bar4) eq_(attributes.get_history(attributes.instance_state(f), 'bars'), ([bar4], [bar1, bar3], [bar2])) f = Foo() del f.bars[1] eq_(attributes.get_history(attributes.instance_state(f), 'bars'), ([], [bar1, bar3], [bar2])) lazy_load = None f = Foo() f.bars.append(bar2) eq_(attributes.get_history(attributes.instance_state(f), 'bars'), ([bar2], [], []))
def test_deferred(self): class Foo(object):pass data = {'a':'this is a', 'b':12} def loader(state, keys): for k in keys: state.dict[k] = data[k] return attributes.ATTR_WAS_SET attributes.register_class(Foo) manager = attributes.manager_of_class(Foo) manager.deferred_scalar_loader = loader attributes.register_attribute(Foo, 'a', uselist=False, useobject=False) attributes.register_attribute(Foo, 'b', uselist=False, useobject=False) f = Foo() attributes.instance_state(f).expire_attributes(None) eq_(f.a, "this is a") eq_(f.b, 12) f.a = "this is some new a" attributes.instance_state(f).expire_attributes(None) eq_(f.a, "this is a") eq_(f.b, 12) attributes.instance_state(f).expire_attributes(None) f.a = "this is another new a" eq_(f.a, "this is another new a") eq_(f.b, 12) attributes.instance_state(f).expire_attributes(None) eq_(f.a, "this is a") eq_(f.b, 12) del f.a eq_(f.a, None) eq_(f.b, 12) attributes.instance_state(f).commit_all() eq_(f.a, None) eq_(f.b, 12)
def test_inheritance2(self): """test that the attribute manager can properly traverse the managed attributes of an object, if the object is of a descendant class with managed attributes in the parent class""" class Foo(object):pass class Bar(Foo):pass class Element(object): _state = True attributes.register_class(Foo) attributes.register_class(Bar) attributes.register_attribute(Foo, 'element', uselist=False, useobject=True) el = Element() x = Bar() x.element = el eq_(attributes.get_history(attributes.instance_state(x), 'element'), ([el], (), ())) attributes.instance_state(x).commit_all() (added, unchanged, deleted) = attributes.get_history(attributes.instance_state(x), 'element') assert added == () assert unchanged == [el]
def test_mutablescalars(self): """test detection of changes on mutable scalar items""" class Foo(object):pass attributes.register_class(Foo) attributes.register_attribute(Foo, 'element', uselist=False, copy_function=lambda x:[y for y in x], mutable_scalars=True, useobject=False) x = Foo() x.element = ['one', 'two', 'three'] attributes.instance_state(x).commit_all() x.element[1] = 'five' assert attributes.instance_state(x).check_modified() attributes.unregister_class(Foo) attributes.register_class(Foo) attributes.register_attribute(Foo, 'element', uselist=False, useobject=False) x = Foo() x.element = ['one', 'two', 'three'] attributes.instance_state(x).commit_all() x.element[1] = 'five' assert not attributes.instance_state(x).check_modified()
def test_instance_dict(self): class User(MyClass): pass register_class(User) attributes.register_attribute(User, 'user_id', uselist=False, useobject=False) attributes.register_attribute(User, 'user_name', uselist=False, useobject=False) attributes.register_attribute(User, 'email_address', uselist=False, useobject=False) u = User() u.user_id = 7 u.user_name = 'john' u.email_address = '*****@*****.**' eq_( u.__dict__, { '_my_state': u._my_state, '_goofy_dict': { 'user_id': 7, 'user_name': 'john', 'email_address': '*****@*****.**' } })
def test_inheritance(self): """tests that attributes are polymorphic""" for base in (object, MyBaseClass, MyClass): class Foo(base):pass class Bar(Foo):pass attributes.register_class(Foo) attributes.register_class(Bar) def func1(): print "func1" return "this is the foo attr" def func2(): print "func2" return "this is the bar attr" def func3(): print "func3" return "this is the shared attr" attributes.register_attribute(Foo, 'element', uselist=False, callable_=lambda o:func1, useobject=True) attributes.register_attribute(Foo, 'element2', uselist=False, callable_=lambda o:func3, useobject=True) attributes.register_attribute(Bar, 'element', uselist=False, callable_=lambda o:func2, useobject=True) x = Foo() y = Bar() assert x.element == 'this is the foo attr' assert y.element == 'this is the bar attr', y.element assert x.element2 == 'this is the shared attr' assert y.element2 == 'this is the shared attr'
def test_basic(self): for base in (object, MyBaseClass, MyClass): class User(base): pass attributes.register_class(User) attributes.register_attribute(User, 'user_id', uselist=False, useobject=False) attributes.register_attribute(User, 'user_name', uselist=False, useobject=False) attributes.register_attribute(User, 'email_address', uselist=False, useobject=False) u = User() u.user_id = 7 u.user_name = 'john' u.email_address = '*****@*****.**' self.assert_(u.user_id == 7 and u.user_name == 'john' and u.email_address == '*****@*****.**') attributes.instance_state(u).commit_all() self.assert_(u.user_id == 7 and u.user_name == 'john' and u.email_address == '*****@*****.**') u.user_name = 'heythere' u.email_address = '*****@*****.**' self.assert_(u.user_id == 7 and u.user_name == 'heythere' and u.email_address == '*****@*****.**')
def test_instance_dict(self): class User(MyClass): pass register_class(User) attributes.register_attribute(User, "user_id", uselist=False, useobject=False) attributes.register_attribute(User, "user_name", uselist=False, useobject=False) attributes.register_attribute(User, "email_address", uselist=False, useobject=False) u = User() u.user_id = 7 u.user_name = "john" u.email_address = "*****@*****.**" eq_( u.__dict__, { "_my_state": u._my_state, "_goofy_dict": { "user_id": 7, "user_name": "john", "email_address": "*****@*****.**", }, }, )
def register_attribute(class_, key, *args, **kwargs): """overrides attributes.register_attribute() to add UOW event handlers to new InstrumentedAttributes. """ cascade = kwargs.pop('cascade', None) useobject = kwargs.get('useobject', False) if useobject: # for object-holding attributes, instrument UOWEventHandler # to process per-attribute cascades extension = util.to_list(kwargs.pop('extension', None) or []) extension.insert(0, UOWEventHandler(key, class_, cascade=cascade)) kwargs['extension'] = extension return attributes.register_attribute(class_, key, *args, **kwargs)
def register_attribute(class_, key, *args, **kwargs): """Register an attribute with the attributes module. Overrides attributes.register_attribute() to add unitofwork-specific event handlers. """ useobject = kwargs.get('useobject', False) if useobject: # for object-holding attributes, instrument UOWEventHandler # to process per-attribute cascades extension = util.to_list(kwargs.pop('extension', None) or []) extension.append(UOWEventHandler(key)) kwargs['extension'] = extension return attributes.register_attribute(class_, key, *args, **kwargs)
def test_inheritance(self): """tests that attributes are polymorphic""" for base in (object, MyBaseClass, MyClass): class Foo(base): pass class Bar(Foo): pass register_class(Foo) register_class(Bar) def func1(state, passive): return "this is the foo attr" def func2(state, passive): return "this is the bar attr" def func3(state, passive): return "this is the shared attr" attributes.register_attribute(Foo, "element", uselist=False, callable_=func1, useobject=True) attributes.register_attribute(Foo, "element2", uselist=False, callable_=func3, useobject=True) attributes.register_attribute(Bar, "element", uselist=False, callable_=func2, useobject=True) x = Foo() y = Bar() assert x.element == "this is the foo attr" assert y.element == "this is the bar attr", y.element assert x.element2 == "this is the shared attr" assert y.element2 == "this is the shared attr"
def test_basic(self): for base in (object, MyBaseClass, MyClass): class User(base): pass register_class(User) attributes.register_attribute(User, "user_id", uselist=False, useobject=False) attributes.register_attribute(User, "user_name", uselist=False, useobject=False) attributes.register_attribute(User, "email_address", uselist=False, useobject=False) u = User() u.user_id = 7 u.user_name = "john" u.email_address = "*****@*****.**" eq_(u.user_id, 7) eq_(u.user_name, "john") eq_(u.email_address, "*****@*****.**") attributes.instance_state(u)._commit_all( attributes.instance_dict(u)) eq_(u.user_id, 7) eq_(u.user_name, "john") eq_(u.email_address, "*****@*****.**") u.user_name = "heythere" u.email_address = "*****@*****.**" eq_(u.user_id, 7) eq_(u.user_name, "heythere") eq_(u.email_address, "*****@*****.**")
def test_history(self): for base in (object, MyBaseClass, MyClass): class Foo(base): pass class Bar(base): pass attributes.register_class(Foo) attributes.register_class(Bar) attributes.register_attribute(Foo, "name", uselist=False, useobject=False) attributes.register_attribute(Foo, "bars", uselist=True, trackparent=True, useobject=True) attributes.register_attribute(Bar, "name", uselist=False, useobject=False) f1 = Foo() f1.name = 'f1' eq_(attributes.get_history(attributes.instance_state(f1), 'name'), (['f1'], (), ())) b1 = Bar() b1.name = 'b1' f1.bars.append(b1) eq_(attributes.get_history(attributes.instance_state(f1), 'bars'), ([b1], [], [])) attributes.instance_state(f1).commit_all(attributes.instance_dict(f1)) attributes.instance_state(b1).commit_all(attributes.instance_dict(b1)) eq_(attributes.get_history(attributes.instance_state(f1), 'name'), ((), ['f1'], ())) eq_(attributes.get_history(attributes.instance_state(f1), 'bars'), ((), [b1], ())) f1.name = 'f1mod' b2 = Bar() b2.name = 'b2' f1.bars.append(b2) eq_(attributes.get_history(attributes.instance_state(f1), 'name'), (['f1mod'], (), ['f1'])) eq_(attributes.get_history(attributes.instance_state(f1), 'bars'), ([b2], [b1], [])) f1.bars.remove(b1) eq_(attributes.get_history(attributes.instance_state(f1), 'bars'), ([b2], [], [b1]))
def test_history(self): for base in (object, MyBaseClass, MyClass): class Foo(base): pass class Bar(base): pass register_class(Foo) register_class(Bar) attributes.register_attribute(Foo, "name", uselist=False, useobject=False) attributes.register_attribute(Foo, "bars", uselist=True, trackparent=True, useobject=True) attributes.register_attribute(Bar, "name", uselist=False, useobject=False) f1 = Foo() f1.name = "f1" eq_( attributes.get_state_history(attributes.instance_state(f1), "name"), (["f1"], (), ()), ) b1 = Bar() b1.name = "b1" f1.bars.append(b1) eq_( attributes.get_state_history(attributes.instance_state(f1), "bars"), ([b1], [], []), ) attributes.instance_state(f1)._commit_all( attributes.instance_dict(f1)) attributes.instance_state(b1)._commit_all( attributes.instance_dict(b1)) eq_( attributes.get_state_history(attributes.instance_state(f1), "name"), ((), ["f1"], ()), ) eq_( attributes.get_state_history(attributes.instance_state(f1), "bars"), ((), [b1], ()), ) f1.name = "f1mod" b2 = Bar() b2.name = "b2" f1.bars.append(b2) eq_( attributes.get_state_history(attributes.instance_state(f1), "name"), (["f1mod"], (), ["f1"]), ) eq_( attributes.get_state_history(attributes.instance_state(f1), "bars"), ([b2], [b1], []), ) f1.bars.remove(b1) eq_( attributes.get_state_history(attributes.instance_state(f1), "bars"), ([b2], [], [b1]), )
import time manage_attributes = True init_attributes = manage_attributes and True class User(object): pass class Address(object): pass if manage_attributes: attributes.register_attribute(User, 'id', False, False) attributes.register_attribute(User, 'name', False, False) attributes.register_attribute(User, 'addresses', True, False, trackparent=True) attributes.register_attribute(Address, 'email', False, False) now = time.time() for i in range(0, 130): u = User() if init_attributes: attributes.manage(u) u.id = i u.name = "user " + str(i)
import testenv; testenv.simple_setup() import random, string from sqlalchemy.orm import attributes from sqlalchemy.test.util import gc_collect # with this test, run top. make sure the Python process doenst grow in size arbitrarily. class User(object): pass class Address(object): pass attributes.register_attribute(User, 'id', False, False) attributes.register_attribute(User, 'name', False, False) attributes.register_attribute(User, 'addresses', True, False) attributes.register_attribute(Address, 'email', False, False) attributes.register_attribute(Address, 'user', False, False) for i in xrange(1000): for j in xrange(1000): u = User() attributes.manage(u) u.name = str(random.randint(0, 100000000)) for k in xrange(10): a = Address() a.email_address = str(random.randint(0, 100000000)) attributes.manage(a)
def _register_attribute(class_, key, **kw): kw.setdefault("comparator", object()) kw.setdefault("parententity", object()) attributes.register_attribute(class_, key, **kw)