summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/sqlalchemy/orm/attributes.py12
-rw-r--r--test/orm/test_attributes.py33
2 files changed, 45 insertions, 0 deletions
diff --git a/lib/sqlalchemy/orm/attributes.py b/lib/sqlalchemy/orm/attributes.py
index 7f722aa44..40a69d96a 100644
--- a/lib/sqlalchemy/orm/attributes.py
+++ b/lib/sqlalchemy/orm/attributes.py
@@ -1247,3 +1247,15 @@ def del_attribute(instance, key):
state, dict_ = instance_state(instance), instance_dict(instance)
state.manager[key].impl.delete(state, dict_)
+def flag_modified(instance, key):
+ """Mark an attribute on an instance as 'modified'.
+
+ This sets the 'modified' flag on the instance and
+ establishes an unconditional change event for the given attribute.
+
+ """
+ state, dict_ = instance_state(instance), instance_dict(instance)
+ impl = state.manager[key].impl
+ state.modified_event(dict_, impl, NO_VALUE)
+
+ \ No newline at end of file
diff --git a/test/orm/test_attributes.py b/test/orm/test_attributes.py
index 9bbfa98eb..30156bbb7 100644
--- a/test/orm/test_attributes.py
+++ b/test/orm/test_attributes.py
@@ -1123,7 +1123,40 @@ class HistoryTest(_base.ORMTest):
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)
+
+ 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'},], (), ()))
+ attributes.instance_state(f).commit_all(attributes.instance_dict(f))
+ 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'},], ()))
+ attributes.flag_modified(f, 'someattr')
+ 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']], (), ()))
+ attributes.instance_state(f).commit_all(attributes.instance_dict(f))
+
+ 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']], ()))
+ attributes.flag_modified(f, 'someattr')
+
+ eq_(attributes.get_state_history(attributes.instance_state(f), 'someattr'), ([['b', 'c']], (), ()))
+
def test_use_object(self):
class Foo(_base.BasicEntity):
pass