Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix unregistering utilities on old persistent adapter registries. #63

Merged
merged 1 commit into from Jul 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion CHANGES.rst
Expand Up @@ -5,7 +5,9 @@
5.0.1 (unreleased)
==================

- Nothing changed yet.
- Fix unregistering utilities on old persistent adapter registries.
Previously this could raise ``TypeError``. See `issue 62
<https://github.com/zopefoundation/zope.component/issues/62>`_.


5.0.0 (2021-03-19)
Expand Down
6 changes: 5 additions & 1 deletion src/zope/component/persistentregistry.py
Expand Up @@ -23,7 +23,7 @@ class PersistentAdapterRegistry(VerifyingAdapterRegistry, Persistent):
"""
An adapter registry that is also a persistent object.

.. versionchanged:: 4.7.0
.. versionchanged:: 5.0.0
Internal data structures are now composed of
:class:`persistent.mapping.PersistentMapping` and
:class:`persistent.list.PersistentList`. This helps scale to
Expand Down Expand Up @@ -68,6 +68,10 @@ def _addValueToLeaf(self, existing_leaf_sequence, new_item):
return existing_leaf_sequence

def _removeValueFromLeaf(self, existing_leaf_sequence, to_remove):
if isinstance(existing_leaf_sequence, tuple):
# Converting from old state
existing_leaf_sequence = self._leafSequenceType(existing_leaf_sequence)

without_removed = VerifyingAdapterRegistry._removeValueFromLeaf(
self,
existing_leaf_sequence,
Expand Down
39 changes: 39 additions & 0 deletions src/zope/component/tests/test_persistentregistry.py
Expand Up @@ -136,9 +136,48 @@ def test___setstate___rebuilds__ro(self):
def test__addValueToLeaf_existing_is_tuple_converts(self):
from persistent.list import PersistentList
registry = self._makeOne()
# It converts when the tuple is not empty...
result = registry._addValueToLeaf(('a',), 'b')
self.assertIsInstance(result, PersistentList)
self.assertEqual(result, ['a', 'b'])
# ...and when it is empty...
result = registry._addValueToLeaf((), 'b')
self.assertIsInstance(result, PersistentList)
self.assertEqual(result, ['b'])
# ...and in fact when it is even missing
result = registry._addValueToLeaf(None, 'b')
self.assertIsInstance(result, PersistentList)
self.assertEqual(result, ['b'])

def test__removeValueFromLeaf_existing_is_tuple_converts(self):
from persistent.list import PersistentList
registry = self._makeOne()
# It converts when the item is found...
result = registry._removeValueFromLeaf(('a', 'b'), 'b')
self.assertIsInstance(result, PersistentList)
self.assertEqual(result, ['a'])
# ...and when it is not found
result = registry._removeValueFromLeaf(('a',), 'b')
self.assertIsInstance(result, PersistentList)
self.assertEqual(result, ['a'])

def test__addValueFromLeaf_preserves_identity(self):
registry = self._makeOne()
first = registry._addValueToLeaf(None, 'a')
second = registry._addValueToLeaf(first, 'b')
self.assertIs(first, second)
self.assertEqual(second, ['a', 'b'])

def test__removeValueFromLeaf_preserves_identity(self):
registry = self._makeOne()
first = registry._addValueToLeaf(None, 'a')
second = registry._addValueToLeaf(first, 'b')
third = registry._addValueToLeaf(second, 'c')
fourth = registry._removeValueFromLeaf(third, 'c')
self.assertIs(first, second)
self.assertIs(third, fourth)
self.assertIs(first, fourth)
self.assertEqual(fourth, ['a', 'b'])


@skipIfNoPersistent
Expand Down