Author: luke
Date: 2007-04-18 11:47:46 -0600 (Wed, 18 Apr 2007)
New Revision: 2564
Modified:
SQLObject/branches/cache-deps-on-views/sqlobject/events.py
SQLObject/branches/cache-deps-on-views/sqlobject/main.py
SQLObject/branches/cache-deps-on-views/sqlobject/tests/test_events.py
Log:
Events model changes
Modified: SQLObject/branches/cache-deps-on-views/sqlobject/events.py
===================================================================
--- SQLObject/branches/cache-deps-on-views/sqlobject/events.py 2007-04-18 07:12:26 UTC (rev 2563)
+++ SQLObject/branches/cache-deps-on-views/sqlobject/events.py 2007-04-18 17:47:46 UTC (rev 2564)
@@ -82,11 +82,7 @@
class RowCreatedSignal(Signal):
"""
Called after an instance is created, with the class as the
- sender. Called with the arguments ``(kwargs, post_funcs)``.
- There may be a ``connection`` argument. ``kwargs``may be usefully
- modified. ``post_funcs`` is a list of callbacks, intended to have
- functions appended to it, and are called with the arguments
- ``(new_instance)``.
+ sender. Called with the arguments ``(new_instance, kwargs)``.
Note: this is not called when an instance is created from an
existing database row.
@@ -97,9 +93,13 @@
class RowDestroySignal(Signal):
"""
Called before an instance is deleted. Sender is the instance's
- class. Arguments are ``(instance)``. You cannot cancel the delete,
+ class. Arguments are ``(instance, post_funcs)``. You cannot cancel the delete,
but you can raise an exception (which will probably cancel the
delete, but also cause an uncaught exception if not expected).
+
+ ``post_funcs`` is a list of callbacks, intended to have
+ functions appended to it, and are called with the arguments
+ ``(deleted_instance)``.
Note: this is not called when an instance is destroyed through
garbage collection.
@@ -108,15 +108,39 @@
row can be deleted without first fetching it?
"""
+class RowDestroyedSignal(Signal):
+ """
+ Called after an instance is deleted. Sender is the instance's
+ class. Arguments are ``(instance)``.
+
+ Note: this is not called when an instance is destroyed through
+ garbage collection.
+
+ @@: Should this allow ``instance`` to be a primary key, so that a
+ row can be deleted without first fetching it?
+ """
+
class RowUpdateSignal(Signal):
"""
Called when an instance is updated through a call to ``.set()``
(or a column attribute assignment). The arguments are
- ``(instance, kwargs)``. ``kwargs`` can be modified. This is run
- *before* the instance is updated; if you want to look at the
- current values, simply look at ``instance``.
+ ``(instance, kwargs, post_funcs)``. ``kwargs`` can be modified.
+ This is run *before* the instance is updated; if you want to look
+ at the current values, simply look at ``instance``.
+
+ ``post_funcs`` is a list of callbacks, intended to have
+ functions appended to it, and are called with the arguments
+ ``(deleted_instance)``.
+
"""
+class RowUpdatedSignal(Signal):
+ """
+ Called when an instance is updated through a call to ``.set()``
+ (or a column attribute assignment). The arguments are
+ ``(instance, kwargs)``. This is run *after* the instance is updated.
+ """
+
class AddColumnSignal(Signal):
"""
Called when a column is added to a class, with arguments ``(cls,
Modified: SQLObject/branches/cache-deps-on-views/sqlobject/main.py
===================================================================
--- SQLObject/branches/cache-deps-on-views/sqlobject/main.py 2007-04-18 07:12:26 UTC (rev 2563)
+++ SQLObject/branches/cache-deps-on-views/sqlobject/main.py 2007-04-18 17:47:46 UTC (rev 2564)
@@ -1049,9 +1049,10 @@
# in the database, and we can't insert it until all
# the parts are set. So we just keep them in a
# dictionary until later:
+ post_funcs = []
d = {name: value}
if not self.sqlmeta._creating:
- self.sqlmeta.send(events.RowUpdateSignal, self, d)
+ self.sqlmeta.send(events.RowUpdateSignal, self, d, post_funcs)
if len(d) != 1 or name not in d:
return self.set(**d)
value = d[name]
@@ -1073,10 +1074,15 @@
if self.sqlmeta.cacheValues:
setattr(self, instanceName(name), value)
+
+ for func in post_funcs:
+ func(self)
+ self.sqlmeta.send(events.RowUpdatedSignal, self, d)
def set(self, **kw):
+ post_funcs = []
if not self.sqlmeta._creating:
- self.sqlmeta.send(events.RowUpdateSignal, self, kw)
+ self.sqlmeta.send(events.RowUpdateSignal, self, kw, post_funcs)
# set() is used to update multiple values at once,
# potentially with one SQL statement if possible.
@@ -1160,6 +1166,10 @@
self._connection._SO_update(self, args)
finally:
self._SO_writeLock.release()
+
+ for func in post_funcs:
+ func(self)
+ self.sqlmeta.send(events.RowUpdatedSignal, self, kw)
def _SO_selectInit(self, row):
for col, colValue in zip(self.sqlmeta.columnList, row):
@@ -1223,6 +1233,10 @@
self._create(id, **kw)
for func in post_funcs:
func(self)
+
+ kw = kw.copy()
+ kw['id'] = self.id
+ self.sqlmeta.send(events.RowCreatedSignal, self, kw)
def _create(self, id, **kw):
@@ -1279,9 +1293,6 @@
cache = self._connection.cache
cache.created(id, self.__class__, self)
self._init(id)
- post_funcs = []
- kw = dict([('class',self.__class__),('id',id)])
- self.sqlmeta.send(events.RowCreatedSignal, kw, post_funcs)
def _SO_getID(self, obj):
@@ -1506,7 +1517,8 @@
clearTable = classmethod(clearTable)
def destroySelf(self):
- self.sqlmeta.send(events.RowDestroySignal, self)
+ post_funcs = []
+ self.sqlmeta.send(events.RowDestroySignal, self, post_funcs)
# Kills this object. Kills it dead!
klass = self.__class__
@@ -1567,6 +1579,10 @@
self.sqlmeta._obsolete = True
self._connection._SO_delete(self)
self._connection.cache.expire(self.id, self.__class__)
+
+ for func in post_funcs:
+ func(self)
+ self.sqlmeta.send(events.RowDestroyedSignal, self)
def delete(cls, id, connection=None):
obj = cls.get(id, connection=connection)
Modified: SQLObject/branches/cache-deps-on-views/sqlobject/tests/test_events.py
===================================================================
--- SQLObject/branches/cache-deps-on-views/sqlobject/tests/test_events.py 2007-04-18 07:12:26 UTC (rev 2563)
+++ SQLObject/branches/cache-deps-on-views/sqlobject/tests/test_events.py 2007-04-18 17:47:46 UTC (rev 2564)
@@ -41,14 +41,31 @@
assert len(watcher.log) == 2
assert watcher.log[0] == ({'name': 'foo'}, [])
-def test_row_destrow():
+def test_row_created():
setupClass(EventTester)
+ watcher = make_listen(events.RowCreatedSignal)
+ a = EventTester(name='foo')
+ b = EventTester(name='bar')
+ assert len(watcher.log) == 2
+ assert watcher.log[0] == (a, {'id': a.id, 'name': 'foo'})
+ assert watcher.log[1] == (b, {'id': b.id, 'name': 'bar'})
+
+def test_row_destroyrow():
+ setupClass(EventTester)
watcher = make_listen(events.RowDestroySignal)
f = EventTester(name='foo')
assert not watcher.log
f.destroySelf()
+ assert watcher.log == [(f,[])]
+
+def test_row_destroyedrow():
+ setupClass(EventTester)
+ watcher = make_listen(events.RowDestroyedSignal)
+ f = EventTester(name='foo')
+ assert not watcher.log
+ f.destroySelf()
assert watcher.log == [(f,)]
-
+
def test_row_update():
setupClass(EventTester)
watcher = make_listen(events.RowUpdateSignal)
@@ -57,9 +74,20 @@
f.name = 'bar2'
f.set(name='bar3')
assert watcher.log == [
+ (f, {'name': 'bar2'}, []),
+ (f, {'name': 'bar3'}, [])]
+
+def test_row_updated():
+ setupClass(EventTester)
+ watcher = make_listen(events.RowUpdatedSignal)
+ f = EventTester(name='bar')
+ assert not watcher.log
+ f.name = 'bar2'
+ f.set(name='bar3')
+ assert watcher.log == [
(f, {'name': 'bar2'}),
(f, {'name': 'bar3'})]
-
+
def test_add_column():
setupClass(EventTester)
watcher = make_listen(events.AddColumnSignal)
|