diff options
author | mike bayer <mike_mp@zzzcomputing.com> | 2018-02-07 20:58:47 -0500 |
---|---|---|
committer | Gerrit Code Review <gerrit@ci.zzzcomputing.com> | 2018-02-07 20:58:47 -0500 |
commit | ba957f84d333918ca34d562b407cc6d65bccbccb (patch) | |
tree | 4ec38c96ba774bdc6b8ef91ed55ae81c954b21fe /lib/sqlalchemy/event/attr.py | |
parent | 9f657fee5ba66820b9cd6b80653332c07eec0451 (diff) | |
parent | 4065352c7e9779cfeae34f01073ef6c43aeae488 (diff) | |
download | sqlalchemy-ba957f84d333918ca34d562b407cc6d65bccbccb.tar.gz |
Merge "Add flag for class-level disallow of events, apply to OptionEngine"
Diffstat (limited to 'lib/sqlalchemy/event/attr.py')
-rw-r--r-- | lib/sqlalchemy/event/attr.py | 35 |
1 files changed, 30 insertions, 5 deletions
diff --git a/lib/sqlalchemy/event/attr.py b/lib/sqlalchemy/event/attr.py index 1068257cb..efa8fab42 100644 --- a/lib/sqlalchemy/event/attr.py +++ b/lib/sqlalchemy/event/attr.py @@ -30,7 +30,7 @@ as well as support for subclass propagation (e.g. events assigned to """ from __future__ import absolute_import, with_statement - +from .. import exc from .. import util from ..util import threading from . import registry @@ -47,6 +47,20 @@ class RefCollection(util.MemoizedSlots): return weakref.ref(self, registry._collection_gced) +class _empty_collection(object): + def append(self, element): + pass + + def extend(self, other): + pass + + def __iter__(self): + return iter([]) + + def clear(self): + pass + + class _ClsLevelDispatch(RefCollection): """Class-level events on :class:`._Dispatch` classes.""" @@ -91,6 +105,9 @@ class _ClsLevelDispatch(RefCollection): target = event_key.dispatch_target assert isinstance(target, type), \ "Class-level Event targets must be classes." + if not getattr(target, '_sa_propagate_class_events', True): + raise exc.InvalidRequestError( + "Can't assign an event directly to the %s class" % target) stack = [target] while stack: cls = stack.pop(0) @@ -99,7 +116,7 @@ class _ClsLevelDispatch(RefCollection): self.update_subclass(cls) else: if cls not in self._clslevel: - self._clslevel[cls] = collections.deque() + self._assign_cls_collection(cls) self._clslevel[cls].appendleft(event_key._listen_fn) registry._stored_in_collection(event_key, self) @@ -107,7 +124,9 @@ class _ClsLevelDispatch(RefCollection): target = event_key.dispatch_target assert isinstance(target, type), \ "Class-level Event targets must be classes." - + if not getattr(target, '_sa_propagate_class_events', True): + raise exc.InvalidRequestError( + "Can't assign an event directly to the %s class" % target) stack = [target] while stack: cls = stack.pop(0) @@ -116,13 +135,19 @@ class _ClsLevelDispatch(RefCollection): self.update_subclass(cls) else: if cls not in self._clslevel: - self._clslevel[cls] = collections.deque() + self._assign_cls_collection(cls) self._clslevel[cls].append(event_key._listen_fn) registry._stored_in_collection(event_key, self) + def _assign_cls_collection(self, target): + if getattr(target, '_sa_propagate_class_events', True): + self._clslevel[target] = collections.deque() + else: + self._clslevel[target] = _empty_collection() + def update_subclass(self, target): if target not in self._clslevel: - self._clslevel[target] = collections.deque() + self._assign_cls_collection(target) clslevel = self._clslevel[target] for cls in target.__mro__[1:]: if cls in self._clslevel: |