[Checkins] SVN: zope.interface/branches/regebro-python3/ back-merged trunk
Thomas Lotze
tl at gocept.com
Sat Sep 12 06:10:41 EDT 2009
Log message for revision 103857:
back-merged trunk
Changed:
U zope.interface/branches/regebro-python3/CHANGES.txt
U zope.interface/branches/regebro-python3/README.txt
U zope.interface/branches/regebro-python3/setup.py
U zope.interface/branches/regebro-python3/src/zope/interface/adapter.py
U zope.interface/branches/regebro-python3/src/zope/interface/tests/test_adapter.py
-=-
Modified: zope.interface/branches/regebro-python3/CHANGES.txt
===================================================================
--- zope.interface/branches/regebro-python3/CHANGES.txt 2009-09-12 01:51:11 UTC (rev 103856)
+++ zope.interface/branches/regebro-python3/CHANGES.txt 2009-09-12 10:10:41 UTC (rev 103857)
@@ -2,15 +2,26 @@
*******
==================
-3.5.2 (unreleased)
+3.5.3 (unreleased)
==================
-- ...
+...
+
==================
-3.5.1 (2009-10-13)
+3.5.2 (2009-07-01)
==================
+- BaseAdapterRegistry.unregister, unsubscribe: Remove empty portions of
+ the data structures when something is removed. This avoids leaving
+ references to global objects (interfaces) that may be slated for
+ removal from the calling application.
+
+
+==================
+3.5.1 (2009-03-18)
+==================
+
- verifyObject: use getattr instead of hasattr to test for object attributes
in order to let exceptions other than AttributeError raised by properties
propagate to the caller
Modified: zope.interface/branches/regebro-python3/README.txt
===================================================================
--- zope.interface/branches/regebro-python3/README.txt 2009-09-12 01:51:11 UTC (rev 103856)
+++ zope.interface/branches/regebro-python3/README.txt 2009-09-12 10:10:41 UTC (rev 103857)
@@ -1,3 +1,6 @@
+*This package is intended to be independently reusable in any Python
+project. It is maintained by the* `Zope Toolkit project <http://docs.zope.org/zopetoolkit/>`_.
+
This package provides an implementation of `object interfaces` for Python.
Interfaces are a mechanism for labeling objects as conforming to a given
API or contract. So, this package can be considered as implementation of
Modified: zope.interface/branches/regebro-python3/setup.py
===================================================================
--- zope.interface/branches/regebro-python3/setup.py 2009-09-12 01:51:11 UTC (rev 103856)
+++ zope.interface/branches/regebro-python3/setup.py 2009-09-12 10:10:41 UTC (rev 103857)
@@ -11,6 +11,11 @@
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
+# This package is developed by the Zope Toolkit project, documented here:
+# http://docs.zope.org/zopetoolkit
+# When developing and releasing this package, please follow the documented
+# Zope Toolkit policies as described by this documentation.
+##############################################################################
"""Setup for zope.interface package
$Id$
@@ -96,7 +101,7 @@
from build_ext_2 import optional_build_ext
setup(name='zope.interface',
- version = '3.5.2dev',
+ version = '3.5.3dev',
url='http://pypi.python.org/pypi/zope.interface',
license='ZPL 2.1',
description='Interfaces for Python',
Modified: zope.interface/branches/regebro-python3/src/zope/interface/adapter.py
===================================================================
--- zope.interface/branches/regebro-python3/src/zope/interface/adapter.py 2009-09-12 01:51:11 UTC (rev 103856)
+++ zope.interface/branches/regebro-python3/src/zope/interface/adapter.py 2009-09-12 10:10:41 UTC (rev 103857)
@@ -39,6 +39,13 @@
# {provided -> {name -> valie}}
# but for order == 2, we have:
# {r1 -> {r2 -> {provided -> {name -> valie}}}}
+ #
+ # XXX ^^^ what does the above comment have to do with any code
+ # in this method? and.. "interfaces is really a nested key"?
+ # i don't see "interfaces" mentioned. does it mean
+ # "provided"? what are r1 and r2? why is the structure just
+ # below this a list? is this comment 100% bitrotten or just a
+ # little? /XXX
self._adapters = []
# {order -> {required -> {provided -> {name -> [value]}}}}
@@ -64,6 +71,8 @@
# so have to check the generations of base registries to determine
# if their cache data are current
+ # ^^^ XXX what are the above comments describing? /XXX
+
# Base registries:
self.__bases__ = bases
@@ -146,10 +155,13 @@
components = byorder[order]
key = required + (provided,)
+ # Keep track of how we got to `components`:
+ lookups = []
for k in key:
d = components.get(k)
if d is None:
return
+ lookups.append((components, k))
components = d
old = components.get(name)
@@ -159,6 +171,20 @@
return
del components[name]
+ if not components:
+ # Clean out empty containers, since we don't want our keys
+ # to reference global objects (interfaces) unnecessarily.
+ # This is often a problem when an interface is slated for
+ # removal; a hold-over entry in the registry can make it
+ # difficult to remove such interfaces.
+ for comp, k in reversed(lookups):
+ d = comp[k]
+ if d:
+ break
+ else:
+ del comp[k]
+ while byorder and not byorder[-1]:
+ del byorder[-1]
n = self._provided[provided] - 1
if n == 0:
del self._provided[provided]
@@ -168,9 +194,6 @@
self.changed(self)
- return
-
-
def subscribe(self, required, provided, value):
required = tuple(map(_convert_None_to_Interface, required))
name = u''
@@ -207,10 +230,13 @@
components = byorder[order]
key = required + (provided,)
+ # Keep track of how we got to `components`:
+ lookups = []
for k in key:
d = components.get(k)
if d is None:
return
+ lookups.append((components, k))
components = d
old = components.get(u'')
@@ -224,9 +250,27 @@
if new == old:
return
-
- components[u''] = new
+ if new:
+ components[u''] = new
+ else:
+ # Instead of setting components[u''] = new, we clean out
+ # empty containers, since we don't want our keys to
+ # reference global objects (interfaces) unnecessarily. This
+ # is often a problem when an interface is slated for
+ # removal; a hold-over entry in the registry can make it
+ # difficult to remove such interfaces.
+ if u'' in components:
+ del components[u'']
+ for comp, k in reversed(lookups):
+ d = comp[k]
+ if d:
+ break
+ else:
+ del comp[k]
+ while byorder and not byorder[-1]:
+ del byorder[-1]
+
if provided is not None:
n = self._provided[provided] + len(new) - len(old)
if n == 0:
Modified: zope.interface/branches/regebro-python3/src/zope/interface/tests/test_adapter.py
===================================================================
--- zope.interface/branches/regebro-python3/src/zope/interface/tests/test_adapter.py 2009-09-12 01:51:11 UTC (rev 103856)
+++ zope.interface/branches/regebro-python3/src/zope/interface/tests/test_adapter.py 2009-09-12 10:10:41 UTC (rev 103857)
@@ -344,6 +344,63 @@
"""
+def test_unregister_cleans_up_empties():
+ """
+ >>> class I(zope.interface.Interface):
+ ... pass
+ >>> class IP(zope.interface.Interface):
+ ... pass
+ >>> class C(object):
+ ... pass
+
+ >>> registry = AdapterRegistry()
+
+ >>> registry.register([], IP, '', C)
+ >>> registry.register([I], IP, '', C)
+ >>> registry.register([I], IP, 'name', C)
+ >>> registry.register([I, I], IP, '', C)
+ >>> len(registry._adapters)
+ 3
+ >>> map(len, registry._adapters)
+ [1, 1, 1]
+
+ >>> registry.unregister([], IP, '', C)
+ >>> registry.unregister([I], IP, '', C)
+ >>> registry.unregister([I], IP, 'name', C)
+ >>> registry.unregister([I, I], IP, '', C)
+ >>> registry._adapters
+ []
+
+ """
+
+def test_unsubscribe_cleans_up_empties():
+ """
+ >>> class I1(zope.interface.Interface):
+ ... pass
+ >>> class I2(zope.interface.Interface):
+ ... pass
+ >>> class IP(zope.interface.Interface):
+ ... pass
+
+ >>> registry = AdapterRegistry()
+ >>> def handler(event):
+ ... pass
+
+ >>> registry.subscribe([I1], I1, handler)
+ >>> registry.subscribe([I2], I1, handler)
+ >>> len(registry._subscribers)
+ 2
+ >>> map(len, registry._subscribers)
+ [0, 2]
+
+ >>> registry.unsubscribe([I1], I1, handler)
+ >>> registry.unsubscribe([I2], I1, handler)
+ >>> registry._subscribers
+ []
+
+ """
+
+
def test_suite():
import doctest
return unittest.TestSuite((
More information about the checkins
mailing list