summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/event.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2012-03-07 22:36:22 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2012-03-07 22:36:22 -0500
commit8696a45b096dd7fedb6e9683bef4de99220c976d (patch)
tree0318e9d345a24039bc7cf28daae80f58546768b8 /lib/sqlalchemy/event.py
parentbe71c73f614f9c316c0c02a98505a8c03d5ef788 (diff)
downloadsqlalchemy-8696a45b096dd7fedb6e9683bef4de99220c976d.tar.gz
- [bug] Fixed event registration bug
which would primarily show up as events not being registered with sessionmaker() instances created after the event was associated with the Session class. [ticket:2424]
Diffstat (limited to 'lib/sqlalchemy/event.py')
-rw-r--r--lib/sqlalchemy/event.py35
1 files changed, 26 insertions, 9 deletions
diff --git a/lib/sqlalchemy/event.py b/lib/sqlalchemy/event.py
index 9cc3139af..cd70b3a7c 100644
--- a/lib/sqlalchemy/event.py
+++ b/lib/sqlalchemy/event.py
@@ -13,12 +13,12 @@ NO_RETVAL = util.symbol('NO_RETVAL')
def listen(target, identifier, fn, *args, **kw):
"""Register a listener function for the given target.
-
+
e.g.::
-
+
from sqlalchemy import event
from sqlalchemy.schema import UniqueConstraint
-
+
def unique_constraint_name(const, table):
const.name = "uq_%s_%s" % (
table.name,
@@ -41,12 +41,12 @@ def listen(target, identifier, fn, *args, **kw):
def listens_for(target, identifier, *args, **kw):
"""Decorate a function as a listener for the given target + identifier.
-
+
e.g.::
-
+
from sqlalchemy import event
from sqlalchemy.schema import UniqueConstraint
-
+
@event.listens_for(UniqueConstraint, "after_parent_attach")
def unique_constraint_name(const, table):
const.name = "uq_%s_%s" % (
@@ -205,12 +205,14 @@ class _DispatchDescriptor(object):
def insert(self, obj, target, propagate):
assert isinstance(target, type), \
"Class-level Event targets must be classes."
-
stack = [target]
while stack:
cls = stack.pop(0)
stack.extend(cls.__subclasses__())
- self._clslevel[cls].insert(0, obj)
+ if cls is not target and cls not in self._clslevel:
+ self.update_subclass(cls)
+ else:
+ self._clslevel[cls].insert(0, obj)
def append(self, obj, target, propagate):
assert isinstance(target, type), \
@@ -220,7 +222,20 @@ class _DispatchDescriptor(object):
while stack:
cls = stack.pop(0)
stack.extend(cls.__subclasses__())
- self._clslevel[cls].append(obj)
+ if cls is not target and cls not in self._clslevel:
+ self.update_subclass(cls)
+ else:
+ self._clslevel[cls].append(obj)
+
+ def update_subclass(self, target):
+ clslevel = self._clslevel[target]
+ for cls in target.__mro__[1:]:
+ if cls in self._clslevel:
+ clslevel.extend([
+ fn for fn
+ in self._clslevel[cls]
+ if fn not in clslevel
+ ])
def remove(self, obj, target):
stack = [target]
@@ -252,6 +267,8 @@ class _ListenerCollection(object):
_exec_once = False
def __init__(self, parent, target_cls):
+ if target_cls not in parent._clslevel:
+ parent.update_subclass(target_cls)
self.parent_listeners = parent._clslevel[target_cls]
self.name = parent.__name__
self.listeners = []