Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PersistentSet in ZODB 3

Tags:

python

set

zodb

ZODB provides a PersistentList and a PersistentMapping, but I'd like a PersistentSet. I wrote a quick class that mirrors the ancient PersistentList from ZODB 2. Because there's no UserSet in Python, I had to extend from the C-based built-in set.

class PersistentSet(UserSet, Persistent):
    def __iand__(self, other):
        set.__iand__(other)
        self._p_changed = 1

    ...

    ...

    ...

    def symmetric_difference_update(self, other):
        set.symmetric_difference_update(other)
        self._p_changed = 1

The code produced a "multiple bases have instance lay-out conflict" error. I tried creating a UserSet wrapper around set, but that didn't solve the problem either.

class UserSet(set):
    def __init__(self):
        self.value = set
    def __getattribute__(self, name):
        return self.value.__getattribute__(name

Finally, I imported sets.Set (superseded by the built-in set), but that seems to be implemented in C, too. I didn't find any set implementations on PyPI so I'm at a dead end now.

What are my options? I may have to implement a set from scratch or use UserDict and throw away all the values.

like image 812
Nikhil Avatar asked Dec 12 '25 04:12

Nikhil


2 Answers

Why don't you use the persistent set class provided with the BTree libraries in ZODB. There are 4 such classes available. IITreeSet and IOTreeSet manage sets of integers and OITreeSet and OOTreeSet manage set of arbitrary objects. They correspond to the four BTree classes IIBTree, IOBTree, OIBTree and OOBTree respectively. Their advantages over the set implementation built into Python are their fast lookup mechanism (thanx to the underlying BTree) and their persistence support.

Here is some sample code:

>>> from BTrees.IIBTree import IITreeSet, union, intersection
>>> a = IITreeSet([1,2,3])
>>> a
<BTrees._IIBTree.IITreeSet object at 0x00B3FF18>
>>> b = IITreeSet([4,3,2])
>>> list(a)
[1, 2, 3]
>>> list(b)
[2, 3, 4]
>>> union(a,b)
IISet([1, 2, 3, 4])
>>> intersection(a,b)
IISet([2, 3])
like image 149
Shailesh Kumar Avatar answered Dec 14 '25 18:12

Shailesh Kumar


Forward all attribute requests to the internal set:

class PersistentSet(Persistent):
    def __init__(self):
        self.inner_set = set()

    def __getattribute__(self, name):
        try:
            inner_set = Persistent.__getattribute__(self, "inner_set")
            output = getattr(inner_set, name)
        except AttributeError:
            output = Persistent.__getattribute__(self, name)

        return output
like image 40
Unknown Avatar answered Dec 14 '25 19:12

Unknown



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!