summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJason Madden <jason+github@nextthought.com>2016-08-31 07:41:51 -0500
committerMichael Howitz <mh@gocept.com>2016-08-31 14:41:51 +0200
commit14c8b2966011bc0dcab7e908cd80cb61dfd413cb (patch)
tree45731b513adb6d72bb19642db6b4f45cb569f826 /src
parent21b7a985afd3ad0b0ff89b4ae25015daf63324d1 (diff)
downloadzope-interface-14c8b2966011bc0dcab7e908cd80cb61dfd413cb.tar.gz
Support Components subclasses that are not hashable. (#54)
* Support Components subclasses that are not hashable. Fixes #53.
Diffstat (limited to 'src')
-rw-r--r--src/zope/interface/registry.py20
-rw-r--r--src/zope/interface/tests/test_registry.py22
2 files changed, 31 insertions, 11 deletions
diff --git a/src/zope/interface/registry.py b/src/zope/interface/registry.py
index 2e1b085..c2b588c 100644
--- a/src/zope/interface/registry.py
+++ b/src/zope/interface/registry.py
@@ -14,7 +14,7 @@
"""Basic components support
"""
from collections import defaultdict
-from weakref import WeakKeyDictionary
+import weakref
try:
from zope.event import notify
@@ -71,15 +71,18 @@ class _UnhashableComponentCounter(object):
class _UtilityRegistrations(object):
- _regs_for_components = WeakKeyDictionary()
+ _regs_for_components = {}
+ _weakrefs_for_components = {}
@classmethod
def for_components(cls, components):
# We manage these utility/subscription registrations as associated
# objects with a weakref to avoid making any changes to
- # the pickle format
+ # the pickle format. They are keyed off the id of the component because
+ # Components subclasses are not guaranteed to be hashable.
+ key = id(components)
try:
- regs = cls._regs_for_components[components]
+ regs = cls._regs_for_components[key]
except KeyError:
regs = None
else:
@@ -91,7 +94,14 @@ class _UtilityRegistrations(object):
if regs is None:
regs = cls(components.utilities, components._utility_registrations)
- cls._regs_for_components[components] = regs
+ cls._regs_for_components[key] = regs
+
+ if key not in cls._weakrefs_for_components:
+ def _cleanup(r):
+ cls._weakrefs_for_components.pop(key)
+ cls._regs_for_components.pop(key)
+
+ cls._weakrefs_for_components[key] = weakref.ref(components, _cleanup)
return regs
diff --git a/src/zope/interface/tests/test_registry.py b/src/zope/interface/tests/test_registry.py
index c2a940a..852034e 100644
--- a/src/zope/interface/tests/test_registry.py
+++ b/src/zope/interface/tests/test_registry.py
@@ -2133,6 +2133,15 @@ class ComponentsTests(unittest.TestCase):
self.assertEqual(_called_2, [bar])
+class UnhashableComponentsTests(ComponentsTests):
+
+ def _getTargetClass(self):
+ # Mimic what pyramid does to create an unhashable
+ # registry
+ class Components(super(UnhashableComponentsTests, self)._getTargetClass(), dict):
+ pass
+ return Components
+
# Test _getUtilityProvided, _getAdapterProvided, _getAdapterRequired via their
# callers (Component.registerUtility, Component.registerAdapter).
@@ -2646,9 +2655,10 @@ class _Monkey(object):
def test_suite():
return unittest.TestSuite((
- unittest.makeSuite(ComponentsTests),
- unittest.makeSuite(UtilityRegistrationTests),
- unittest.makeSuite(AdapterRegistrationTests),
- unittest.makeSuite(SubscriptionRegistrationTests),
- unittest.makeSuite(AdapterRegistrationTests),
- ))
+ unittest.makeSuite(ComponentsTests),
+ unittest.makeSuite(UnhashableComponentsTests),
+ unittest.makeSuite(UtilityRegistrationTests),
+ unittest.makeSuite(AdapterRegistrationTests),
+ unittest.makeSuite(SubscriptionRegistrationTests),
+ unittest.makeSuite(AdapterRegistrationTests),
+ ))