summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/event/attr.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2014-08-14 14:40:28 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2014-08-14 14:40:28 -0400
commit4a4cccfee5a2eb78380e56eb9476e91658656676 (patch)
tree86d8727dfa51538906b57f2872741642b1435b0c /lib/sqlalchemy/event/attr.py
parentc0c6aaa58ad1bf01345189a917029c40edc3c8eb (diff)
downloadsqlalchemy-4a4cccfee5a2eb78380e56eb9476e91658656676.tar.gz
- Removing (or adding) an event listener at the same time that the event
is being run itself, either from inside the listener or from a concurrent thread, now raises a RuntimeError, as the collection used is now an instance of ``colletions.deque()`` and does not support changes while being iterated. Previously, a plain Python list was used where removal from inside the event itself would produce silent failures. fixes #3163
Diffstat (limited to 'lib/sqlalchemy/event/attr.py')
-rw-r--r--lib/sqlalchemy/event/attr.py15
1 files changed, 8 insertions, 7 deletions
diff --git a/lib/sqlalchemy/event/attr.py b/lib/sqlalchemy/event/attr.py
index 7641b595a..dba1063cf 100644
--- a/lib/sqlalchemy/event/attr.py
+++ b/lib/sqlalchemy/event/attr.py
@@ -37,6 +37,7 @@ from . import registry
from . import legacy
from itertools import chain
import weakref
+import collections
class RefCollection(object):
@@ -96,8 +97,8 @@ class _DispatchDescriptor(RefCollection):
self.update_subclass(cls)
else:
if cls not in self._clslevel:
- self._clslevel[cls] = []
- self._clslevel[cls].insert(0, event_key._listen_fn)
+ self._clslevel[cls] = collections.deque()
+ self._clslevel[cls].appendleft(event_key._listen_fn)
registry._stored_in_collection(event_key, self)
def append(self, event_key, propagate):
@@ -113,13 +114,13 @@ class _DispatchDescriptor(RefCollection):
self.update_subclass(cls)
else:
if cls not in self._clslevel:
- self._clslevel[cls] = []
+ self._clslevel[cls] = collections.deque()
self._clslevel[cls].append(event_key._listen_fn)
registry._stored_in_collection(event_key, self)
def update_subclass(self, target):
if target not in self._clslevel:
- self._clslevel[target] = []
+ self._clslevel[target] = collections.deque()
clslevel = self._clslevel[target]
for cls in target.__mro__[1:]:
if cls in self._clslevel:
@@ -145,7 +146,7 @@ class _DispatchDescriptor(RefCollection):
to_clear = set()
for dispatcher in self._clslevel.values():
to_clear.update(dispatcher)
- dispatcher[:] = []
+ dispatcher.clear()
registry._clear(self, to_clear)
def for_modify(self, obj):
@@ -287,7 +288,7 @@ class _ListenerCollection(RefCollection, _CompoundListener):
self.parent_listeners = parent._clslevel[target_cls]
self.parent = parent
self.name = parent.__name__
- self.listeners = []
+ self.listeners = collections.deque()
self.propagate = set()
def for_modify(self, obj):
@@ -337,7 +338,7 @@ class _ListenerCollection(RefCollection, _CompoundListener):
def clear(self):
registry._clear(self, self.listeners)
self.propagate.clear()
- self.listeners[:] = []
+ self.listeners.clear()
class _JoinedDispatchDescriptor(object):