From: Mike Bayer Date: Fri, 11 Feb 2011 22:58:49 +0000 (-0500) Subject: - fix long lines in test_attributes X-Git-Tag: rel_0_7b1~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2a289e915e2d2f479300cecbe57b7495646e1ce7;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - fix long lines in test_attributes - add deprecation warning to get_history() when passed True or False, convert - rearrange symbol() so we can get sphinx autodata to work --- diff --git a/CHANGES b/CHANGES index 8dfc8fd01c..f8fc77c372 100644 --- a/CHANGES +++ b/CHANGES @@ -131,6 +131,11 @@ CHANGES retrieving the information the flush needs in order to not miss anything. [ticket:2049] + - the value of "passive" as passed to + attributes.get_history() should be one of the + constants defined in the attributes package. Sending + True or False is deprecated. + - sql - Added over() function, method to FunctionElement classes, produces the _Over() construct which diff --git a/doc/build/orm/examples.rst b/doc/build/orm/examples.rst index 00b18bc7b8..a9bcf56cc7 100644 --- a/doc/build/orm/examples.rst +++ b/doc/build/orm/examples.rst @@ -42,13 +42,6 @@ Location: /examples/beaker_caching/ .. automodule:: beaker_caching -Derived Attributes ------------------- - -Location: /examples/derived_attributes/ - -.. automodule:: derived_attributes - Directed Graphs --------------- diff --git a/doc/build/orm/session.rst b/doc/build/orm/session.rst index 7e0c8bb83b..31157e0f77 100644 --- a/doc/build/orm/session.rst +++ b/doc/build/orm/session.rst @@ -1491,18 +1491,14 @@ those described in :ref:`events_orm_toplevel`. .. autoclass:: History :members: -.. attribute:: sqlalchemy.orm.attributes.PASSIVE_NO_INITIALIZE +.. autodata:: PASSIVE_NO_INITIALIZE - Symbol indicating that loader callables should - not be fired off, and a non-initialized attribute - should remain that way. +.. autodata:: PASSIVE_NO_FETCH -.. attribute:: sqlalchemy.orm.attributes.PASSIVE_NO_FETCH +.. autodata:: PASSIVE_NO_FETCH_RELATED - Symbol indicating that loader callables should not boe fired off. - Non-initialized attributes should be initialized to an empty value. +.. autodata:: PASSIVE_ONLY_PERSISTENT -.. attribute:: sqlalchemy.orm.attributes.PASSIVE_OFF +.. autodata:: PASSIVE_OFF - Symbol indicating that loader callables should be executed. diff --git a/lib/sqlalchemy/orm/attributes.py b/lib/sqlalchemy/orm/attributes.py index 6ee5cbffeb..e7b04c4af6 100644 --- a/lib/sqlalchemy/orm/attributes.py +++ b/lib/sqlalchemy/orm/attributes.py @@ -28,34 +28,48 @@ ATTR_EMPTY = util.symbol('ATTR_EMPTY') NO_VALUE = util.symbol('NO_VALUE') NEVER_SET = util.symbol('NEVER_SET') -PASSIVE_NO_INITIALIZE = util.symbol('PASSIVE_NO_INITIALIZE') + +PASSIVE_NO_INITIALIZE = util.symbol('PASSIVE_NO_INITIALIZE', """Symbol indicating that loader callables should not be fired off, and a non-initialized attribute - should remain that way.""" + should remain that way. +""") -PASSIVE_NO_FETCH = util.symbol('PASSIVE_NO_FETCH') -"""Symbol indicating that loader callables should not emit SQL. - Non-initialized attributes should be initialized to an empty value.""" +PASSIVE_NO_FETCH = util.symbol('PASSIVE_NO_FETCH', +"""Symbol indicating that loader callables should not emit SQL, + but a value can be fetched from the current session. + + Non-initialized attributes should be initialized to an empty value. -PASSIVE_NO_FETCH_RELATED = util.symbol('PASSIVE_NO_FETCH_RELATED') +""") + +PASSIVE_NO_FETCH_RELATED = util.symbol('PASSIVE_NO_FETCH_RELATED', """Symbol indicating that loader callables should not emit SQL for - the related object, but can refresh the attributes of the local - instance. + loading a related object, but can refresh the attributes of the local + instance in order to locate a related object in the current session. + Non-initialized attributes should be initialized to an empty value. The unit of work uses this mode to check if history is present - with minimal SQL emitted. - """ + on many-to-one attributes with minimal SQL emitted. -PASSIVE_ONLY_PERSISTENT = util.symbol('PASSIVE_ONLY_PERSISTENT') +""") + +PASSIVE_ONLY_PERSISTENT = util.symbol('PASSIVE_ONLY_PERSISTENT', """Symbol indicating that loader callables should only fire off for -persistent objects. + parent objects which are persistent (i.e., have a database + identity). -Loads of "previous" values during change events use this flag. -""" + Load operations for the "previous" value of an attribute make + use of this flag during change events. + +""") -PASSIVE_OFF = util.symbol('PASSIVE_OFF') -"""Symbol indicating that loader callables should be executed.""" +PASSIVE_OFF = util.symbol('PASSIVE_OFF', +"""Symbol indicating that loader callables should be executed + normally. + +""") class QueryableAttribute(interfaces.PropComparator): @@ -1107,11 +1121,20 @@ def get_history(obj, key, passive=PASSIVE_OFF): :param key: string attribute name. :param passive: indicates if the attribute should be - loaded from the database if not already present (:attr:`PASSIVE_NO_FETCH`), and + loaded from the database if not already present (:attr:`.PASSIVE_NO_FETCH`), and if the attribute should be not initialized to a blank value otherwise - (:attr:`PASSIVE_NO_INITIALIZE`). Default is :attr:`PASSIVE_OFF`. + (:attr:`.PASSIVE_NO_INITIALIZE`). Default is :attr:`PASSIVE_OFF`. """ + if passive is True: + util.warn_deprecated("Passing True for 'passive' is deprecated. " + "Use attributes.PASSIVE_NO_INITIALIZE") + passive = PASSIVE_NO_INITIALIZE + elif passive is False: + util.warn_deprecated("Passing False for 'passive' is " + "deprecated. Use attributes.PASSIVE_OFF") + passive = PASSIVE_OFF + return get_state_history(instance_state(obj), key, passive) def get_state_history(state, key, passive=PASSIVE_OFF): diff --git a/lib/sqlalchemy/util/langhelpers.py b/lib/sqlalchemy/util/langhelpers.py index d723a18695..4088e85cb4 100644 --- a/lib/sqlalchemy/util/langhelpers.py +++ b/lib/sqlalchemy/util/langhelpers.py @@ -657,10 +657,12 @@ class classproperty(property): class _symbol(object): - def __init__(self, name): + def __init__(self, name, doc=None): """Construct a new named symbol.""" assert isinstance(name, str) self.name = name + if doc: + self.__doc__ = doc def __reduce__(self): return symbol, (self.name,) def __repr__(self): @@ -682,16 +684,23 @@ class symbol(object): Repeated calls of symbol('name') will all return the same instance. + The optional ``doc`` argument assigns to ``__doc__``. This + is strictly so that Sphinx autoattr picks up the docstring we want + (it doesn't appear to pick up the in-module docstring if the datamember + is in a different module - autoattribute also blows up completely). + If Sphinx fixes/improves this then we would no longer need + ``doc`` here. + """ symbols = {} _lock = threading.Lock() - def __new__(cls, name): + def __new__(cls, name, doc=None): cls._lock.acquire() try: sym = cls.symbols.get(name) if sym is None: - cls.symbols[name] = sym = _symbol(name) + cls.symbols[name] = sym = _symbol(name, doc) return sym finally: symbol._lock.release() diff --git a/test/orm/test_attributes.py b/test/orm/test_attributes.py index 52a06d1504..7d3793abda 100644 --- a/test/orm/test_attributes.py +++ b/test/orm/test_attributes.py @@ -4,7 +4,8 @@ from sqlalchemy.orm.collections import collection from sqlalchemy.orm.interfaces import AttributeExtension from sqlalchemy import exc as sa_exc from test.lib import * -from test.lib.testing import eq_, ne_, assert_raises, assert_raises_message +from test.lib.testing import eq_, ne_, assert_raises, \ + assert_raises_message from test.orm import _base from test.lib.util import gc_collect, all_partial_orderings from sqlalchemy.util import cmp, jython, topological @@ -26,25 +27,29 @@ class AttributesTest(_base.ORMTest): MyTest, MyTest2 = None, None def test_basic(self): - class User(object):pass + class User(object): + pass instrumentation.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) - + 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 = 'lala@123.com' - - self.assert_(u.user_id == 7 and u.user_name == 'john' and u.email_address == 'lala@123.com') + self.assert_(u.user_id == 7 and u.user_name == 'john' + and u.email_address == 'lala@123.com') attributes.instance_state(u).commit_all(attributes.instance_dict(u)) - self.assert_(u.user_id == 7 and u.user_name == 'john' and u.email_address == 'lala@123.com') - + self.assert_(u.user_id == 7 and u.user_name == 'john' + and u.email_address == 'lala@123.com') u.user_name = 'heythere' u.email_address = 'foo@bar.com' - self.assert_(u.user_id == 7 and u.user_name == 'heythere' and u.email_address == 'foo@bar.com') + self.assert_(u.user_id == 7 and u.user_name == 'heythere' + and u.email_address == 'foo@bar.com') def test_pickleness(self): instrumentation.register_class(MyTest) @@ -124,7 +129,8 @@ class AttributesTest(_base.ORMTest): self.assert_(o4.mt2[0].b is None) def test_state_gc(self): - """test that InstanceState always has a dict, even after host object gc'ed.""" + """test that InstanceState always has a dict, even after host + object gc'ed.""" class Foo(object): pass @@ -177,29 +183,29 @@ class AttributesTest(_base.ORMTest): attributes.register_attribute(Foo, 'b', uselist=False, useobject=False) f = Foo() - attributes.instance_state(f).expire(attributes.instance_dict(f), set()) - eq_(f.a, "this is a") + 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") + 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") + 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") + 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), set()) + attributes.instance_state(f).commit_all(attributes.instance_dict(f), + set()) eq_(f.a, None) eq_(f.b, 12) @@ -230,11 +236,16 @@ class AttributesTest(_base.ORMTest): instrumentation.register_class(User) instrumentation.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) + 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 @@ -245,16 +256,23 @@ class AttributesTest(_base.ORMTest): a.email_address = 'lala@123.com' u.addresses.append(a) - self.assert_(u.user_id == 7 and u.user_name == 'john' and u.addresses[0].email_address == 'lala@123.com') - u, attributes.instance_state(a).commit_all(attributes.instance_dict(a)) - self.assert_(u.user_id == 7 and u.user_name == 'john' and u.addresses[0].email_address == 'lala@123.com') + self.assert_(u.user_id == 7 and u.user_name == 'john' + and u.addresses[0].email_address == 'lala@123.com') + (u, + attributes.instance_state(a).commit_all(attributes.instance_dict(a))) + self.assert_(u.user_id == 7 and u.user_name == 'john' + and u.addresses[0].email_address == 'lala@123.com') u.user_name = 'heythere' a = Address() a.address_id = 11 a.email_address = 'foo@bar.com' u.addresses.append(a) - self.assert_(u.user_id == 7 and u.user_name == 'heythere' and u.addresses[0].email_address == 'lala@123.com' and u.addresses[1].email_address == 'foo@bar.com') + + eq_(u.user_id, 7) + eq_(u.user_name, 'heythere') + eq_(u.addresses[0].email_address,'lala@123.com') + eq_(u.addresses[1].email_address,'foo@bar.com') def test_extension_commit_attr(self): """test that an extension which commits attribute history @@ -324,7 +342,8 @@ class AttributesTest(_base.ORMTest): def hist(key, shouldmatch, fn, *arg): attributes.instance_state(f1).commit_all(attributes.instance_dict(f1)) fn(*arg) - histories.append((shouldmatch, attributes.get_history(f1, key))) + histories.append((shouldmatch, + attributes.get_history(f1, key))) f1 = Foo() hist('bars', True, f1.bars.append, b3) @@ -393,14 +412,19 @@ class AttributesTest(_base.ORMTest): x.bars b = Bar(id=4) b.foos.append(x) - attributes.instance_state(x).expire_attributes(attributes.instance_dict(x), ['bars']) + attributes.instance_state(x).expire_attributes(attributes.instance_dict(x), + ['bars']) assert_raises(AssertionError, b.foos.remove, x) def test_scalar_listener(self): - # listeners on ScalarAttributeImpl and MutableScalarAttributeImpl aren't used normally. - # test that they work for the benefit of user extensions + + # listeners on ScalarAttributeImpl and + # MutableScalarAttributeImpl aren't used normally. test that + # they work for the benefit of user extensions + class Foo(object): + pass results = [] @@ -416,8 +440,12 @@ class AttributesTest(_base.ORMTest): return child instrumentation.register_class(Foo) - attributes.register_attribute(Foo, 'x', uselist=False, mutable_scalars=False, useobject=False, extension=ReceiveEvents()) - attributes.register_attribute(Foo, 'y', uselist=False, mutable_scalars=True, useobject=False, copy_function=lambda x:x, extension=ReceiveEvents()) + attributes.register_attribute(Foo, 'x', uselist=False, + mutable_scalars=False, useobject=False, + extension=ReceiveEvents()) + attributes.register_attribute(Foo, 'y', uselist=False, + mutable_scalars=True, useobject=False, + copy_function=lambda x: x, extension=ReceiveEvents()) f = Foo() f.x = 5 @@ -529,24 +557,32 @@ class AttributesTest(_base.ORMTest): 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 + """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 instrumentation.register_class(Foo) instrumentation.register_class(Bar) - attributes.register_attribute(Foo, 'element', uselist=False, useobject=True) + attributes.register_attribute(Foo, 'element', uselist=False, + useobject=True) el = Element() x = Bar() x.element = el - eq_(attributes.get_state_history(attributes.instance_state(x), 'element'), ([el], (), ())) + eq_(attributes.get_state_history(attributes.instance_state(x), + 'element'), ([el], (), ())) attributes.instance_state(x).commit_all(attributes.instance_dict(x)) - - (added, unchanged, deleted) = attributes.get_state_history(attributes.instance_state(x), 'element') + added, unchanged, deleted = \ + attributes.get_state_history(attributes.instance_state(x), + 'element') assert added == () assert unchanged == [el] @@ -560,10 +596,12 @@ class AttributesTest(_base.ORMTest): instrumentation.register_class(Foo) instrumentation.register_class(Bar) + bar1, bar2, bar3, bar4 = [Bar(id=1), Bar(id=2), Bar(id=3), + Bar(id=4)] - bar1, bar2, bar3, bar4 = [Bar(id=1), Bar(id=2), Bar(id=3), Bar(id=4)] def func1(state, passive): - return "this is func 1" + return 'this is func 1' + def func2(state, passive): return [bar1, bar2, bar3] @@ -573,39 +611,41 @@ class AttributesTest(_base.ORMTest): callable_=func2, useobject=True) attributes.register_attribute(Bar, 'id', uselist=False, useobject=True) - x = Foo() attributes.instance_state(x).commit_all(attributes.instance_dict(x)) x.col2.append(bar4) - eq_(attributes.get_state_history(attributes.instance_state(x), 'col2'), ([bar4], [bar1, bar2, bar3], [])) + eq_(attributes.get_state_history(attributes.instance_state(x), + 'col2'), ([bar4], [bar1, bar2, bar3], [])) def test_parenttrack(self): - class Foo(object):pass - class Bar(object):pass + class Foo(object): + pass + + class Bar(object): + pass instrumentation.register_class(Foo) instrumentation.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) - + 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. + # test that double assignment doesn't accidentally reset the + # 'parent' flag. + b3 = Bar() f4 = Foo() b3.element = f4 @@ -615,20 +655,23 @@ class AttributesTest(_base.ORMTest): def test_mutablescalars(self): """test detection of changes on mutable scalar items""" - class Foo(object):pass + + class Foo(object): + pass instrumentation.register_class(Foo) - attributes.register_attribute(Foo, 'element', uselist=False, copy_function=lambda x:[y for y in x], mutable_scalars=True, useobject=False) + 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(attributes.instance_dict(x)) x.element[1] = 'five' assert attributes.instance_state(x).modified - instrumentation.unregister_class(Foo) - instrumentation.register_class(Foo) - attributes.register_attribute(Foo, 'element', uselist=False, useobject=False) + attributes.register_attribute(Foo, 'element', uselist=False, + useobject=False) x = Foo() x.element = ['one', 'two', 'three'] attributes.instance_state(x).commit_all(attributes.instance_dict(x)) @@ -636,12 +679,13 @@ class AttributesTest(_base.ORMTest): assert not attributes.instance_state(x).modified def test_descriptorattributes(self): - """changeset: 1633 broke ability to use ORM to map classes with unusual - descriptor attributes (for example, classes that inherit from ones - implementing zope.interface.Interface). - This is a simple regression test to prevent that defect. - """ + """changeset: 1633 broke ability to use ORM to map classes with + unusual descriptor attributes (for example, classes that inherit + from ones implementing zope.interface.Interface). This is a + simple regression test to prevent that defect. """ + class des(object): + def __get__(self, instance, owner): raise AttributeError('fake attribute') @@ -653,52 +697,70 @@ class AttributesTest(_base.ORMTest): def test_collectionclasses(self): - class Foo(object):pass - instrumentation.register_class(Foo) + class Foo(object): + pass - attributes.register_attribute(Foo, "collection", uselist=True, typecallable=set, useobject=True) - assert attributes.manager_of_class(Foo).is_instrumented("collection") + instrumentation.register_class(Foo) + attributes.register_attribute(Foo, 'collection', uselist=True, + typecallable=set, useobject=True) + assert attributes.manager_of_class(Foo).is_instrumented('collection' + ) assert isinstance(Foo().collection, set) - - attributes.unregister_attribute(Foo, "collection") - assert not attributes.manager_of_class(Foo).is_instrumented("collection") - + attributes.unregister_attribute(Foo, 'collection') + assert not attributes.manager_of_class(Foo).is_instrumented('collection' + ) try: - attributes.register_attribute(Foo, "collection", uselist=True, typecallable=dict, useobject=True) + attributes.register_attribute(Foo, 'collection', + uselist=True, typecallable=dict, useobject=True) assert False except sa_exc.ArgumentError, e: - assert str(e) == "Type InstrumentedDict must elect an appender method to be a collection class" + assert str(e) \ + == 'Type InstrumentedDict must elect an appender '\ + 'method to be a collection class' class MyDict(dict): + @collection.appender def append(self, item): self[item.foo] = item + @collection.remover def remove(self, item): del self[item.foo] - attributes.register_attribute(Foo, "collection", uselist=True, typecallable=MyDict, useobject=True) + + attributes.register_attribute(Foo, 'collection', uselist=True, + typecallable=MyDict, useobject=True) assert isinstance(Foo().collection, MyDict) + attributes.unregister_attribute(Foo, 'collection') - attributes.unregister_attribute(Foo, "collection") + class MyColl(object): + pass - class MyColl(object):pass try: - attributes.register_attribute(Foo, "collection", uselist=True, typecallable=MyColl, useobject=True) + attributes.register_attribute(Foo, 'collection', + uselist=True, typecallable=MyColl, useobject=True) assert False except sa_exc.ArgumentError, e: - assert str(e) == "Type MyColl must elect an appender method to be a collection class" + assert str(e) \ + == 'Type MyColl must elect an appender method to be a '\ + 'collection class' class MyColl(object): + @collection.iterator def __iter__(self): return iter([]) + @collection.appender def append(self, item): pass + @collection.remover def remove(self, item): pass - attributes.register_attribute(Foo, "collection", uselist=True, typecallable=MyColl, useobject=True) + + attributes.register_attribute(Foo, 'collection', uselist=True, + typecallable=MyColl, useobject=True) try: Foo().collection assert True @@ -1035,79 +1097,98 @@ class HistoryTest(_base.ORMTest): pass instrumentation.register_class(Foo) - attributes.register_attribute(Foo, 'someattr', uselist=False, useobject=False) - + attributes.register_attribute(Foo, 'someattr', uselist=False, + useobject=False) f = Foo() - eq_(Foo.someattr.impl.get_committed_value(attributes.instance_state(f), attributes.instance_dict(f)), None) - + eq_(Foo.someattr.impl.get_committed_value(attributes.instance_state(f), + attributes.instance_dict(f)), None) f.someattr = 3 - eq_(Foo.someattr.impl.get_committed_value(attributes.instance_state(f), attributes.instance_dict(f)), None) - + eq_(Foo.someattr.impl.get_committed_value(attributes.instance_state(f), + attributes.instance_dict(f)), None) f = Foo() f.someattr = 3 - eq_(Foo.someattr.impl.get_committed_value(attributes.instance_state(f), attributes.instance_dict(f)), None) - - attributes.instance_state(f).commit(attributes.instance_dict(f), ['someattr']) - eq_(Foo.someattr.impl.get_committed_value(attributes.instance_state(f), attributes.instance_dict(f)), 3) + eq_(Foo.someattr.impl.get_committed_value(attributes.instance_state(f), + attributes.instance_dict(f)), None) + attributes.instance_state(f).commit(attributes.instance_dict(f), + ['someattr']) + eq_(Foo.someattr.impl.get_committed_value(attributes.instance_state(f), + attributes.instance_dict(f)), 3) def test_scalar(self): class Foo(_base.BasicEntity): pass instrumentation.register_class(Foo) - attributes.register_attribute(Foo, 'someattr', uselist=False, useobject=False) + attributes.register_attribute(Foo, 'someattr', uselist=False, + useobject=False) # case 1. new object - f = Foo() - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ((), (), ())) - - f.someattr = "hi" - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), (['hi'], (), ())) - - attributes.instance_state(f).commit(attributes.instance_dict(f), ['someattr']) - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ((), ['hi'], ())) + f = Foo() + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), (), ())) + f.someattr = 'hi' + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), (['hi'], (), ())) + attributes.instance_state(f).commit(attributes.instance_dict(f), + ['someattr']) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), ['hi'], ())) f.someattr = 'there' - - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), (['there'], (), ['hi'])) - attributes.instance_state(f).commit(attributes.instance_dict(f), ['someattr']) - - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ((), ['there'], ())) - + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), (['there'], (), ['hi'])) + attributes.instance_state(f).commit(attributes.instance_dict(f), + ['someattr']) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), ['there'], ())) del f.someattr - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ((), (), ['there'])) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), (), ['there'])) + + # case 2. object with direct dictionary settings (similar to a + # load operation) - # case 2. object with direct dictionary settings (similar to a load operation) f = Foo() f.__dict__['someattr'] = 'new' - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ((), ['new'], ())) - + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), ['new'], ())) f.someattr = 'old' - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), (['old'], (), ['new'])) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), (['old'], (), ['new'])) + attributes.instance_state(f).commit(attributes.instance_dict(f), + ['someattr']) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), ['old'], ())) - attributes.instance_state(f).commit(attributes.instance_dict(f), ['someattr']) - eq_(attributes.get_state_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 - # 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_state_history(attributes.instance_state(f), 'someattr'), ((), (), ())) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), (), ())) f.someattr = None - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ([None], (), ())) - + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ([None], (), ())) f = Foo() f.__dict__['someattr'] = 'new' - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ((), ['new'], ())) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), ['new'], ())) f.someattr = None - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ([None], (), ['new'])) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ([None], (), ['new'])) # set same value twice + f = Foo() - attributes.instance_state(f).commit(attributes.instance_dict(f), ['someattr']) + attributes.instance_state(f).commit(attributes.instance_dict(f), + ['someattr']) f.someattr = 'one' - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), (['one'], (), ())) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), (['one'], (), ())) f.someattr = 'two' - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), (['two'], (), ())) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), (['two'], (), ())) def test_mutable_scalar(self): @@ -1115,71 +1196,84 @@ class HistoryTest(_base.ORMTest): pass instrumentation.register_class(Foo) - attributes.register_attribute(Foo, 'someattr', uselist=False, useobject=False, mutable_scalars=True, copy_function=dict) + attributes.register_attribute(Foo, 'someattr', uselist=False, + useobject=False, mutable_scalars=True, + copy_function=dict) # case 1. new object - f = Foo() - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ((), (), ())) - - f.someattr = {'foo':'hi'} - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ([{'foo':'hi'}], (), ())) - - attributes.instance_state(f).commit(attributes.instance_dict(f), ['someattr']) - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ((), [{'foo':'hi'}], ())) - eq_(attributes.instance_state(f).committed_state['someattr'], {'foo':'hi'}) + f = Foo() + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), (), ())) + f.someattr = {'foo': 'hi'} + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ([{'foo': 'hi'}], (), ())) + attributes.instance_state(f).commit(attributes.instance_dict(f), + ['someattr']) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), [{'foo': 'hi'}], ())) + eq_(attributes.instance_state(f).committed_state['someattr'], + {'foo': 'hi'}) f.someattr['foo'] = 'there' - eq_(attributes.instance_state(f).committed_state['someattr'], {'foo':'hi'}) - - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ([{'foo':'there'}], (), [{'foo':'hi'}])) - attributes.instance_state(f).commit(attributes.instance_dict(f), ['someattr']) - - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ((), [{'foo':'there'}], ())) + eq_(attributes.instance_state(f).committed_state['someattr'], + {'foo': 'hi'}) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ([{'foo': 'there'}], (), [{'foo': 'hi'}])) + attributes.instance_state(f).commit(attributes.instance_dict(f), + ['someattr']) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), [{'foo': 'there'}], ())) + + # case 2. object with direct dictionary settings (similar to a + # load operation) - # case 2. object with direct dictionary settings (similar to a load operation) f = Foo() - f.__dict__['someattr'] = {'foo':'new'} - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ((), [{'foo':'new'}], ())) - - f.someattr = {'foo':'old'} - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ([{'foo':'old'}], (), [{'foo':'new'}])) - - attributes.instance_state(f).commit(attributes.instance_dict(f), ['someattr']) - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ((), [{'foo':'old'}], ())) + f.__dict__['someattr'] = {'foo': 'new'} + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), [{'foo': 'new'}], ())) + f.someattr = {'foo': 'old'} + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ([{'foo': 'old'}], (), [{'foo': 'new'}])) + attributes.instance_state(f).commit(attributes.instance_dict(f), + ['someattr']) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), [{'foo': 'old'}], ())) def test_flag_modified(self): class Foo(_base.BasicEntity): pass instrumentation.register_class(Foo) - attributes.register_attribute(Foo, 'someattr', uselist=False, useobject=False) - + attributes.register_attribute(Foo, 'someattr', uselist=False, + useobject=False) f = Foo() - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ((), (), ())) - - f.someattr = {'a':'b'} - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ([{'a':'b'},], (), ())) - + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), (), ())) + f.someattr = {'a': 'b'} + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ([{'a': 'b'}], (), ())) attributes.instance_state(f).commit_all(attributes.instance_dict(f)) - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ((), [{'a':'b'},], ())) - + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), [{'a': 'b'}], ())) f.someattr['a'] = 'c' - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ((), [{'a':'c'},], ())) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), [{'a': 'c'}], ())) attributes.flag_modified(f, 'someattr') - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ([{'a':'c'},], (), ())) - + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ([{'a': 'c'}], (), ())) f.someattr = ['a'] - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ([['a']], (), ())) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ([['a']], (), ())) attributes.instance_state(f).commit_all(attributes.instance_dict(f)) - - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ((), [['a']], ())) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), [['a']], ())) f.someattr[0] = 'b' f.someattr.append('c') - - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ((), [['b', 'c']], ())) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), [['b', 'c']], ())) attributes.flag_modified(f, 'someattr') - - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ([['b', 'c']], (), ())) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ([['b', 'c']], (), ())) def test_use_object(self): class Foo(_base.BasicEntity): @@ -1196,60 +1290,76 @@ class HistoryTest(_base.ORMTest): old = Bar(name='old') instrumentation.register_class(Foo) - attributes.register_attribute(Foo, 'someattr', uselist=False, useobject=True) + attributes.register_attribute(Foo, 'someattr', uselist=False, + useobject=True) # case 1. new object - f = Foo() - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ((), [None], ())) + f = Foo() + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), [None], ())) f.someattr = hi - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ([hi], (), ())) - - attributes.instance_state(f).commit(attributes.instance_dict(f), ['someattr']) - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ((), [hi], ())) - + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ([hi], (), ())) + attributes.instance_state(f).commit(attributes.instance_dict(f), + ['someattr']) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), [hi], ())) f.someattr = there - - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ([there], (), [hi])) - attributes.instance_state(f).commit(attributes.instance_dict(f), ['someattr']) - - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ((), [there], ())) - + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ([there], (), [hi])) + attributes.instance_state(f).commit(attributes.instance_dict(f), + ['someattr']) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), [there], ())) del f.someattr - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ([None], (), [there])) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ([None], (), [there])) + + # case 2. object with direct dictionary settings (similar to a + # load operation) - # case 2. object with direct dictionary settings (similar to a load operation) f = Foo() f.__dict__['someattr'] = 'new' - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ((), ['new'], ())) - + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), ['new'], ())) f.someattr = old - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ([old], (), ['new'])) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ([old], (), ['new'])) + attributes.instance_state(f).commit(attributes.instance_dict(f), + ['someattr']) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), [old], ())) - attributes.instance_state(f).commit(attributes.instance_dict(f), ['someattr']) - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ((), [old], ())) + # setting None on uninitialized is currently not a change for an + # object attribute (this is different than scalar attribute). a + # lazyload has occured so if its None, its really None - # setting None on uninitialized is currently not a change for an object attribute - # (this is different than scalar attribute). a lazyload has occured so if its - # None, its really None f = Foo() - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ((), [None], ())) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), [None], ())) f.someattr = None - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ((), [None], ())) - + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), [None], ())) f = Foo() f.__dict__['someattr'] = 'new' - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ((), ['new'], ())) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), ['new'], ())) f.someattr = None - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ([None], (), ['new'])) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ([None], (), ['new'])) # set same value twice + f = Foo() - attributes.instance_state(f).commit(attributes.instance_dict(f), ['someattr']) + attributes.instance_state(f).commit(attributes.instance_dict(f), + ['someattr']) f.someattr = 'one' - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), (['one'], (), ())) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), (['one'], (), ())) f.someattr = 'two' - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), (['two'], (), ())) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), (['two'], (), ())) def test_object_collections_set(self): class Foo(_base.BasicEntity): @@ -1260,48 +1370,55 @@ class HistoryTest(_base.ORMTest): instrumentation.register_class(Foo) instrumentation.register_class(Bar) - attributes.register_attribute(Foo, 'someattr', uselist=True, useobject=True) - + 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_state_history(attributes.instance_state(f), 'someattr'), ((), [], ())) + f = Foo() + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), [], ())) f.someattr = [hi] - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ([hi], [], [])) - - attributes.instance_state(f).commit(attributes.instance_dict(f), ['someattr']) - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ((), [hi], ())) - + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ([hi], [], [])) + attributes.instance_state(f).commit(attributes.instance_dict(f), + ['someattr']) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), [hi], ())) f.someattr = [there] - - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ([there], [], [hi])) - attributes.instance_state(f).commit(attributes.instance_dict(f), ['someattr']) - - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ((), [there], ())) - + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ([there], [], [hi])) + attributes.instance_state(f).commit(attributes.instance_dict(f), + ['someattr']) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), [there], ())) f.someattr = [hi] - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ([hi], [], [there])) - + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ([hi], [], [there])) f.someattr = [old, new] - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ([old, new], [], [there])) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ([old, new], [], [there])) + + # case 2. object with direct settings (similar to a load + # operation) - # case 2. object with direct settings (similar to a load operation) f = Foo() collection = attributes.init_collection(f, 'someattr') collection.append_without_event(new) attributes.instance_state(f).commit_all(attributes.instance_dict(f)) - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ((), [new], ())) - + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), [new], ())) f.someattr = [old] - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ([old], [], [new])) - - attributes.instance_state(f).commit(attributes.instance_dict(f), ['someattr']) - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ((), [old], ())) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ([old], [], [new])) + attributes.instance_state(f).commit(attributes.instance_dict(f), + ['someattr']) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), [old], ())) def test_dict_collections(self): class Foo(_base.BasicEntity): @@ -1310,27 +1427,30 @@ class HistoryTest(_base.ORMTest): pass from sqlalchemy.orm.collections import attribute_mapped_collection - instrumentation.register_class(Foo) instrumentation.register_class(Bar) - attributes.register_attribute(Foo, 'someattr', uselist=True, useobject=True, typecallable=attribute_mapped_collection('name')) - + 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_state_history(attributes.instance_state(f), 'someattr'), ((), [], ())) - + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), [], ())) f.someattr['hi'] = hi - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ([hi], [], [])) - + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ([hi], [], [])) f.someattr['there'] = there - eq_(tuple([set(x) for x in attributes.get_state_history(attributes.instance_state(f), 'someattr')]), (set([hi, there]), set(), set())) - - attributes.instance_state(f).commit(attributes.instance_dict(f), ['someattr']) - eq_(tuple([set(x) for x in attributes.get_state_history(attributes.instance_state(f), 'someattr')]), (set(), set([hi, there]), set())) + eq_(tuple([set(x) for x in + attributes.get_state_history(attributes.instance_state(f), + 'someattr')]), (set([hi, there]), set(), set())) + attributes.instance_state(f).commit(attributes.instance_dict(f), + ['someattr']) + eq_(tuple([set(x) for x in + attributes.get_state_history(attributes.instance_state(f), + 'someattr')]), (set(), set([hi, there]), set())) def test_object_collections_mutate(self): class Foo(_base.BasicEntity): @@ -1339,89 +1459,105 @@ class HistoryTest(_base.ORMTest): pass instrumentation.register_class(Foo) - attributes.register_attribute(Foo, 'someattr', uselist=True, useobject=True) - attributes.register_attribute(Foo, 'id', uselist=False, useobject=False) + attributes.register_attribute(Foo, 'someattr', uselist=True, + useobject=True) + attributes.register_attribute(Foo, 'id', uselist=False, + useobject=False) instrumentation.register_class(Bar) - hi = Bar(name='hi') there = Bar(name='there') old = Bar(name='old') new = Bar(name='new') # case 1. new object - f = Foo(id=1) - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ((), [], ())) + f = Foo(id=1) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), [], ())) f.someattr.append(hi) - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ([hi], [], [])) - - attributes.instance_state(f).commit(attributes.instance_dict(f), ['someattr']) - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ((), [hi], ())) - + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ([hi], [], [])) + attributes.instance_state(f).commit(attributes.instance_dict(f), + ['someattr']) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), [hi], ())) f.someattr.append(there) - - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ([there], [hi], [])) - attributes.instance_state(f).commit(attributes.instance_dict(f), ['someattr']) - - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ((), [hi, there], ())) - + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ([there], [hi], [])) + attributes.instance_state(f).commit(attributes.instance_dict(f), + ['someattr']) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), [hi, there], ())) f.someattr.remove(there) - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ([], [hi], [there])) - + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ([], [hi], [there])) f.someattr.append(old) f.someattr.append(new) - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ([old, new], [hi], [there])) - attributes.instance_state(f).commit(attributes.instance_dict(f), ['someattr']) - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ((), [hi, old, new], ())) - + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ([old, new], [hi], [there])) + attributes.instance_state(f).commit(attributes.instance_dict(f), + ['someattr']) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), [hi, old, new], ())) f.someattr.pop(0) - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ([], [old, new], [hi])) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ([], [old, new], [hi])) + + # case 2. object with direct settings (similar to a load + # operation) - # case 2. object with direct settings (similar to a load operation) f = Foo() f.__dict__['id'] = 1 collection = attributes.init_collection(f, 'someattr') collection.append_without_event(new) attributes.instance_state(f).commit_all(attributes.instance_dict(f)) - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ((), [new], ())) - + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), [new], ())) f.someattr.append(old) - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ([old], [new], [])) - - attributes.instance_state(f).commit(attributes.instance_dict(f), ['someattr']) - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ((), [new, old], ())) - + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ([old], [new], [])) + attributes.instance_state(f).commit(attributes.instance_dict(f), + ['someattr']) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), [new, old], ())) f = Foo() collection = attributes.init_collection(f, 'someattr') collection.append_without_event(new) attributes.instance_state(f).commit_all(attributes.instance_dict(f)) - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ((), [new], ())) - + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), [new], ())) f.id = 1 f.someattr.remove(new) - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ([], [], [new])) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ([], [], [new])) # case 3. mixing appends with sets + f = Foo() f.someattr.append(hi) - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ([hi], [], [])) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ([hi], [], [])) f.someattr.append(there) - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ([hi, there], [], [])) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ([hi, there], [], [])) f.someattr = [there] - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ([there], [], [])) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ([there], [], [])) # case 4. ensure duplicates show up, order is maintained + f = Foo() f.someattr.append(hi) f.someattr.append(there) f.someattr.append(hi) - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ([hi, there, hi], [], [])) - + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ([hi, there, hi], [], [])) attributes.instance_state(f).commit_all(attributes.instance_dict(f)) - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ((), [hi, there, hi], ())) - + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ((), [hi, there, hi], ())) f.someattr = [] - eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ([], [], [hi, there, hi])) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'someattr'), ([], [], [hi, there, hi])) def test_collections_via_backref(self): class Foo(_base.BasicEntity): @@ -1431,24 +1567,32 @@ class HistoryTest(_base.ORMTest): instrumentation.register_class(Foo) instrumentation.register_class(Bar) - attributes.register_attribute(Foo, 'bars', uselist=True, backref='foo', trackparent=True, useobject=True) - attributes.register_attribute(Bar, 'foo', uselist=False, backref='bars', trackparent=True, useobject=True) - + attributes.register_attribute(Foo, 'bars', uselist=True, + backref='foo', trackparent=True, useobject=True) + attributes.register_attribute(Bar, 'foo', uselist=False, + backref='bars', trackparent=True, useobject=True) f1 = Foo() b1 = Bar() - eq_(attributes.get_state_history(attributes.instance_state(f1), 'bars'), ((), [], ())) - eq_(attributes.get_state_history(attributes.instance_state(b1), 'foo'), ((), [None], ())) + eq_(attributes.get_state_history(attributes.instance_state(f1), + 'bars'), ((), [], ())) + eq_(attributes.get_state_history(attributes.instance_state(b1), + 'foo'), ((), [None], ())) - #b1.foo = f1 - f1.bars.append(b1) - eq_(attributes.get_state_history(attributes.instance_state(f1), 'bars'), ([b1], [], [])) - eq_(attributes.get_state_history(attributes.instance_state(b1), 'foo'), ([f1], (), ())) + # b1.foo = f1 + f1.bars.append(b1) + eq_(attributes.get_state_history(attributes.instance_state(f1), + 'bars'), ([b1], [], [])) + eq_(attributes.get_state_history(attributes.instance_state(b1), + 'foo'), ([f1], (), ())) b2 = Bar() f1.bars.append(b2) - eq_(attributes.get_state_history(attributes.instance_state(f1), 'bars'), ([b1, b2], [], [])) - eq_(attributes.get_state_history(attributes.instance_state(b1), 'foo'), ([f1], (), ())) - eq_(attributes.get_state_history(attributes.instance_state(b2), 'foo'), ([f1], (), ())) + eq_(attributes.get_state_history(attributes.instance_state(f1), + 'bars'), ([b1, b2], [], [])) + eq_(attributes.get_state_history(attributes.instance_state(b1), + 'foo'), ([f1], (), ())) + eq_(attributes.get_state_history(attributes.instance_state(b2), + 'foo'), ([f1], (), ())) def test_lazy_backref_collections(self): class Foo(_base.BasicEntity): @@ -1467,24 +1611,25 @@ class HistoryTest(_base.ORMTest): useobject=True) attributes.register_attribute(Bar, 'foo', uselist=False, backref='bars', trackparent=True, useobject=True) - - bar1, bar2, bar3, bar4 = [Bar(id=1), Bar(id=2), Bar(id=3), Bar(id=4)] + 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_state_history(attributes.instance_state(f), 'bars'), ([bar4], [bar1, bar2, bar3], [])) - + eq_(attributes.get_state_history(attributes.instance_state(f), + 'bars'), ([bar4], [bar1, bar2, bar3], [])) lazy_load = None f = Foo() bar4 = Bar() bar4.foo = f - eq_(attributes.get_state_history(attributes.instance_state(f), 'bars'), ([bar4], [], [])) - + eq_(attributes.get_state_history(attributes.instance_state(f), + 'bars'), ([bar4], [], [])) lazy_load = [bar1, bar2, bar3] - attributes.instance_state(f).expire_attributes(attributes.instance_dict(f), ['bars']) - eq_(attributes.get_state_history(attributes.instance_state(f), 'bars'), ((), [bar1, bar2, bar3], ())) + attributes.instance_state(f).expire_attributes(attributes.instance_dict(f), + ['bars']) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'bars'), ((), [bar1, bar2, bar3], ())) def test_collections_via_lazyload(self): class Foo(_base.BasicEntity): @@ -1500,38 +1645,40 @@ class HistoryTest(_base.ORMTest): instrumentation.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)] + 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_state_history(attributes.instance_state(f), 'bars'), ([], [], [bar1, bar2, bar3])) - + eq_(attributes.get_state_history(attributes.instance_state(f), + 'bars'), ([], [], [bar1, bar2, bar3])) f = Foo() f.bars.append(bar4) - eq_(attributes.get_state_history(attributes.instance_state(f), 'bars'), ([bar4], [bar1, bar2, bar3], []) ) - + eq_(attributes.get_state_history(attributes.instance_state(f), + 'bars'), ([bar4], [bar1, bar2, bar3], [])) f = Foo() f.bars.remove(bar2) - eq_(attributes.get_state_history(attributes.instance_state(f), 'bars'), ([], [bar1, bar3], [bar2])) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'bars'), ([], [bar1, bar3], [bar2])) f.bars.append(bar4) - eq_(attributes.get_state_history(attributes.instance_state(f), 'bars'), ([bar4], [bar1, bar3], [bar2])) - + eq_(attributes.get_state_history(attributes.instance_state(f), + 'bars'), ([bar4], [bar1, bar3], [bar2])) f = Foo() del f.bars[1] - eq_(attributes.get_state_history(attributes.instance_state(f), 'bars'), ([], [bar1, bar3], [bar2])) - + eq_(attributes.get_state_history(attributes.instance_state(f), + 'bars'), ([], [bar1, bar3], [bar2])) lazy_load = None f = Foo() f.bars.append(bar2) - eq_(attributes.get_state_history(attributes.instance_state(f), 'bars'), ([bar2], [], [])) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'bars'), ([bar2], [], [])) def test_scalar_via_lazyload(self): class Foo(_base.BasicEntity): pass lazy_load = None + def lazyload(state, passive): return lazy_load @@ -1540,35 +1687,39 @@ class HistoryTest(_base.ORMTest): callable_=lazyload, useobject=False) lazy_load = 'hi' - # with scalar non-object and active_history=False, the lazy callable is only executed on gets, not history - # operations + # with scalar non-object and active_history=False, the lazy + # callable is only executed on gets, not history operations f = Foo() - eq_(f.bar, "hi") - eq_(attributes.get_state_history(attributes.instance_state(f), 'bar'), ((), ["hi"], ())) - + eq_(f.bar, 'hi') + eq_(attributes.get_state_history(attributes.instance_state(f), + 'bar'), ((), ['hi'], ())) f = Foo() f.bar = None - eq_(attributes.get_state_history(attributes.instance_state(f), 'bar'), ([None], (), ())) - + eq_(attributes.get_state_history(attributes.instance_state(f), + 'bar'), ([None], (), ())) f = Foo() - f.bar = "there" - eq_(attributes.get_state_history(attributes.instance_state(f), 'bar'), (["there"], (), ())) - f.bar = "hi" - eq_(attributes.get_state_history(attributes.instance_state(f), 'bar'), (["hi"], (), ())) - + f.bar = 'there' + eq_(attributes.get_state_history(attributes.instance_state(f), + 'bar'), (['there'], (), ())) + f.bar = 'hi' + eq_(attributes.get_state_history(attributes.instance_state(f), + 'bar'), (['hi'], (), ())) f = Foo() - eq_(f.bar, "hi") + eq_(f.bar, 'hi') del f.bar - eq_(attributes.get_state_history(attributes.instance_state(f), 'bar'), ((), (), ["hi"])) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'bar'), ((), (), ['hi'])) assert f.bar is None - eq_(attributes.get_state_history(attributes.instance_state(f), 'bar'), ([None], (), ["hi"])) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'bar'), ([None], (), ['hi'])) def test_scalar_via_lazyload_with_active(self): class Foo(_base.BasicEntity): pass lazy_load = None + def lazyload(state, passive): return lazy_load @@ -1578,29 +1729,32 @@ class HistoryTest(_base.ORMTest): active_history=True) lazy_load = 'hi' - # active_history=True means the lazy callable is executed on set as well as get, - # causing the old value to appear in the history + # active_history=True means the lazy callable is executed on set + # as well as get, causing the old value to appear in the history f = Foo() - eq_(f.bar, "hi") - eq_(attributes.get_state_history(attributes.instance_state(f), 'bar'), ((), ["hi"], ())) - + eq_(f.bar, 'hi') + eq_(attributes.get_state_history(attributes.instance_state(f), + 'bar'), ((), ['hi'], ())) f = Foo() f.bar = None - eq_(attributes.get_state_history(attributes.instance_state(f), 'bar'), ([None], (), ['hi'])) - + eq_(attributes.get_state_history(attributes.instance_state(f), + 'bar'), ([None], (), ['hi'])) f = Foo() - f.bar = "there" - eq_(attributes.get_state_history(attributes.instance_state(f), 'bar'), (["there"], (), ['hi'])) - f.bar = "hi" - eq_(attributes.get_state_history(attributes.instance_state(f), 'bar'), ((), ["hi"], ())) - + f.bar = 'there' + eq_(attributes.get_state_history(attributes.instance_state(f), + 'bar'), (['there'], (), ['hi'])) + f.bar = 'hi' + eq_(attributes.get_state_history(attributes.instance_state(f), + 'bar'), ((), ['hi'], ())) f = Foo() - eq_(f.bar, "hi") + eq_(f.bar, 'hi') del f.bar - eq_(attributes.get_state_history(attributes.instance_state(f), 'bar'), ((), (), ["hi"])) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'bar'), ((), (), ['hi'])) assert f.bar is None - eq_(attributes.get_state_history(attributes.instance_state(f), 'bar'), ([None], (), ["hi"])) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'bar'), ([None], (), ['hi'])) def test_scalar_object_via_lazyload(self): class Foo(_base.BasicEntity): @@ -1619,28 +1773,46 @@ class HistoryTest(_base.ORMTest): bar1, bar2 = [Bar(id=1), Bar(id=2)] lazy_load = bar1 - # with scalar object, the lazy callable is only executed on gets and history - # operations + # with scalar object, the lazy callable is only executed on gets + # and history operations f = Foo() - eq_(attributes.get_state_history(attributes.instance_state(f), 'bar'), ((), [bar1], ())) - + eq_(attributes.get_state_history(attributes.instance_state(f), + 'bar'), ((), [bar1], ())) f = Foo() f.bar = None - eq_(attributes.get_state_history(attributes.instance_state(f), 'bar'), ([None], (), [bar1])) - + eq_(attributes.get_state_history(attributes.instance_state(f), + 'bar'), ([None], (), [bar1])) f = Foo() f.bar = bar2 - eq_(attributes.get_state_history(attributes.instance_state(f), 'bar'), ([bar2], (), [bar1])) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'bar'), ([bar2], (), [bar1])) f.bar = bar1 - eq_(attributes.get_state_history(attributes.instance_state(f), 'bar'), ((), [bar1], ())) - + eq_(attributes.get_state_history(attributes.instance_state(f), + 'bar'), ((), [bar1], ())) f = Foo() eq_(f.bar, bar1) del f.bar - eq_(attributes.get_state_history(attributes.instance_state(f), 'bar'), ([None], (), [bar1])) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'bar'), ([None], (), [bar1])) assert f.bar is None - eq_(attributes.get_state_history(attributes.instance_state(f), 'bar'), ([None], (), [bar1])) + eq_(attributes.get_state_history(attributes.instance_state(f), + 'bar'), ([None], (), [bar1])) + + def test_deprecated_flags(self): + assert_raises_message( + sa_exc.SADeprecationWarning, + "Passing True for 'passive' is deprecated. " + "Use attributes.PASSIVE_NO_INITIALIZE", + attributes.get_history, object(), 'foo', True + ) + + assert_raises_message( + sa_exc.SADeprecationWarning, + "Passing False for 'passive' is deprecated. " + "Use attributes.PASSIVE_OFF", + attributes.get_history, object(), 'foo', False + ) class ListenerTest(_base.ORMTest): def test_receive_changes(self): @@ -1661,26 +1833,27 @@ class ListenerTest(_base.ORMTest): instrumentation.register_class(Foo) instrumentation.register_class(Bar) - attributes.register_attribute(Foo, 'data', uselist=False, useobject=False) - attributes.register_attribute(Foo, 'barlist', uselist=True, useobject=True) - attributes.register_attribute(Foo, 'barset', typecallable=set, uselist=True, useobject=True) - attributes.register_attribute(Bar, 'data', uselist=False, useobject=False) - + attributes.register_attribute(Foo, 'data', uselist=False, + useobject=False) + attributes.register_attribute(Foo, 'barlist', uselist=True, + useobject=True) + attributes.register_attribute(Foo, 'barset', typecallable=set, + uselist=True, useobject=True) + attributes.register_attribute(Bar, 'data', uselist=False, + useobject=False) event.listen(Foo.data, 'set', on_set, retval=True) event.listen(Foo.barlist, 'append', append, retval=True) event.listen(Foo.barset, 'append', append, retval=True) - f1 = Foo() - f1.data = "some data" - eq_(f1.data, "some data modified") + f1.data = 'some data' + eq_(f1.data, 'some data modified') b1 = Bar() - b1.data = "some bar" + b1.data = 'some bar' f1.barlist.append(b1) - assert b1.data == "some bar" - assert f1.barlist[0].data == "some bar appended" - + assert b1.data == 'some bar' + assert f1.barlist[0].data == 'some bar appended' f1.barset.add(b1) - assert f1.barset.pop().data == "some bar appended" + assert f1.barset.pop().data == 'some bar appended' def test_propagate(self): classes = [None, None, None] @@ -1710,13 +1883,16 @@ class ListenerTest(_base.ORMTest): instrumentation.register_class(classes[2]) def attr_a(): - attributes.register_attribute(classes[0], 'attrib', uselist=False, useobject=False) + attributes.register_attribute(classes[0], 'attrib', + uselist=False, useobject=False) def attr_b(): - attributes.register_attribute(classes[1], 'attrib', uselist=False, useobject=False) + attributes.register_attribute(classes[1], 'attrib', + uselist=False, useobject=False) def attr_c(): - attributes.register_attribute(classes[2], 'attrib', uselist=False, useobject=False) + attributes.register_attribute(classes[2], 'attrib', + uselist=False, useobject=False) def set(state, value, oldvalue, initiator): canary.append(value)