Skip to content

Commit

Permalink
Add surgery to remove rid from UUIDIndex.
Browse files Browse the repository at this point in the history
  • Loading branch information
deiferni committed Jun 4, 2019
1 parent 9333ea9 commit 20af22b
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 4 deletions.
16 changes: 15 additions & 1 deletion ftw/catalogdoctor/surgery.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,19 @@ def perform(self):
pass


class RemoveFromUUIDIndex(IndexSurgery):
"""Remove rid from a `UUIDIndex`."""

def _remove_keys_pointing_to_rid(self, index):
for key in find_keys_pointing_to_rid(index, self.rid):
del index[key]
self._decrease_length()

def perform(self):
self._remove_keys_pointing_to_rid(self.index._index)
self._remove_rid_from_unindex(self.index._unindex)


class RemoveFromUnIndex(IndexSurgery):
"""Remove a rid from a simple forward and reverse index."""

Expand Down Expand Up @@ -126,6 +139,7 @@ class Surgery(object):
FieldIndex: RemoveFromUnIndex,
GopipIndex: NullSurgery, # not a real index
KeywordIndex: RemoveFromUnIndex,
UUIDIndex: RemoveFromUUIDIndex,
ZCTextIndex: UnindexObject,
}

Expand All @@ -144,7 +158,7 @@ def unindex_rid_from_all_catalog_indexes(self, rid):
surgery(idx, rid).perform()
continue

if not isinstance(idx, (ExtendedPathIndex, UUIDIndex)):
if not isinstance(idx, (ExtendedPathIndex,)):
raise CantPerformSurgery(
'Unhandled index type: {0!r}'.format(idx))

Expand Down
68 changes: 68 additions & 0 deletions ftw/catalogdoctor/tests/test_surgery_remove_from_uuidindex.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
from ftw.builder import Builder
from ftw.builder import create
from ftw.catalogdoctor.surgery import RemoveFromUUIDIndex
from ftw.catalogdoctor.tests import FunctionalTestCase
from ftw.catalogdoctor.utils import find_keys_pointing_to_rid


class TestRemoveFromUUIDIndex(FunctionalTestCase):

def setUp(self):
super(TestRemoveFromUUIDIndex, self).setUp()

self.grant('Contributor')
self.folder = create(Builder('folder').titled(u'Foo'))

def test_remove_healthy_object(self):
rid = self.get_rid(self.folder)
index = self.catalog.indexes['UID']

entries_pointing_to_rid = find_keys_pointing_to_rid(index._index, rid)
self.assertEqual(1, len(entries_pointing_to_rid))
self.assertIn(rid, index._unindex)
self.assertEqual(1, len(index))

surgery = RemoveFromUUIDIndex(index, rid)
surgery.perform()

entries_pointing_to_rid = find_keys_pointing_to_rid(index._index, rid)
self.assertEqual(0, len(entries_pointing_to_rid))
self.assertNotIn(rid, index._unindex)
self.assertEqual(0, len(index))

def test_remove_from_reverse_index_only(self):
rid = self.get_rid(self.folder)
index = self.catalog.indexes['UID']

entries_pointing_to_rid = find_keys_pointing_to_rid(index._index, rid)
del index._index[entries_pointing_to_rid[0]]
index._length.change(-1)

self.assertIn(rid, index._unindex)
self.assertEqual(1, len(index._unindex))

surgery = RemoveFromUUIDIndex(index, rid)
surgery.perform()

entries_pointing_to_rid = find_keys_pointing_to_rid(index._index, rid)
self.assertEqual(0, len(entries_pointing_to_rid))
self.assertNotIn(rid, index._unindex)
self.assertEqual(0, len(index))

def test_remove_from_forward_index_only(self):
rid = self.get_rid(self.folder)
index = self.catalog.indexes['UID']

del index._unindex[rid]

entries_pointing_to_rid = find_keys_pointing_to_rid(index._index, rid)
self.assertEqual(1, len(entries_pointing_to_rid))
self.assertEqual(1, len(index._index))

surgery = RemoveFromUUIDIndex(index, rid)
surgery.perform()

entries_pointing_to_rid = find_keys_pointing_to_rid(index._index, rid)
self.assertEqual(0, len(entries_pointing_to_rid))
self.assertNotIn(rid, index._unindex)
self.assertEqual(0, len(index))
7 changes: 7 additions & 0 deletions ftw/catalogdoctor/tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ def test_find_keys_pointing_to_rid(self):
self.assertItemsEqual(
['foo', 'bar'], find_keys_pointing_to_rid(dictish, 77))

def test_find_keys_pointing_to_rid_single_value(self):
dictish = {'foo': 1,
'bar': -23}

self.assertItemsEqual(
['bar'], find_keys_pointing_to_rid(dictish, -23))

def test_find_keys_pointing_to_rid_emtpy_result(self):
dictish = {'foo': [1, 77],
'qux': []}
Expand Down
19 changes: 16 additions & 3 deletions ftw/catalogdoctor/utils.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
def find_keys_pointing_to_rid(dictish, rid):
"""Return all entries in dictish item pointing to rid."""
"""Return all entries in dictish item pointing to rid.
The values in dictish can be either the rid as a single value or a
collection containing the rid.
"""
return [
key for key, rids_for_key in dictish.items()
if rid in rids_for_key
key for key, rids_or_rid in dictish.items()
if contains_or_equals_rid(rid, rids_or_rid)
]


def contains_or_equals_rid(rid, rids_or_rid):
"""Return whether rids_or_rid contains or equals a rid."""

try:
return rid in rids_or_rid
except TypeError:
return rid == rids_or_rid

0 comments on commit 20af22b

Please sign in to comment.