Skip to main content

Persistent sets are persistent objects that have the API of standard Python sets

Project description

0.2 (2020-05-14)

  • Make Python-3 compatible

  • Add support for PyPy and PyPy3.

0.1 (2007-05-09)

  • Was never released to PyPI

Persistent sets are persistent objects that have the API of standard Python sets. The persistent set should work the same as normal sets, except that changes to them are persistent.

They have the same limitation as persistent lists and persistent mappings, as found in the persistent package: unlike BTree package data structures, changes copy the entire object in the database. This generally means that persistent sets, like persistent lists and persistent mappings, are inappropriate for very large collections. For those, use BTree data structures.

The rest of this file is tests, not documentation. Find out about the Python set API from standard Python documentation (http://docs.python.org/lib/types-set.html, for instance) and find out about persistence in the ZODB documentation (http://www.zope.org/Wikis/ZODB/FrontPage/guide/index.html, for instance).

The persistent set module contains a simple persistent version of a set, that inherits from persistent.Persistent and marks _p_changed = True for any potentially mutating operation.

>>> from ZODB.tests.util import DB
>>> db = DB()
>>> conn = db.open()
>>> root = conn.root()
>>> import zope.app.folder # import rootFolder
>>> app = root['Application'] = zope.app.folder.rootFolder()
>>> import transaction
>>> transaction.commit()
>>> from zc.set import Set
>>> s = Set()
>>> app['s'] = s
>>> transaction.commit()
>>> import persistent.interfaces
>>> persistent.interfaces.IPersistent.providedBy(s)
True
>>> original = factory() # set in one test run; a persistent set in another
>>> sorted(set(dir(original)) - set(dir(s)))
[]

add sets _p_changed

>>> s._p_changed = False
>>> s.add(1) # add
>>> s._p_changed
True
__repr__ includes module, class, and a contents view like a normal set
>>> s # __repr__
zc.set.Set([1])

update works as normal, but sets _p_changed

>>> s._p_changed = False
>>> s.update((2,3,4,5,6,7)) # update
>>> s._p_changed
True

__iter__ works

>>> sorted(s) # __iter__
[1, 2, 3, 4, 5, 6, 7]

__len__ works

>>> len(s)
7

as does __contains__

>>> 3 in s
True
>>> 'kumquat' in s
False

__gt__, __ge__, __eq__, __ne__, __lt__, and __le__ work normally, equating with normal set, at least if spelled in the right direction.

>>> s > original
True
>>> s >= original
True
>>> s < original
False
>>> s <= original
False
>>> s == original
False
>>> s != original
True
>>> original.update(s)
>>> s > original
False
>>> s >= original
True
>>> s < original
False
>>> s <= original
True
>>> s == original
True
>>> s != original
False
>>> original.add(8)
>>> s > original
False
>>> s >= original
False
>>> s < original
True
>>> s <= original
True
>>> s == original
False
>>> s != original
True

I don’t know what __cmp__ is supposed to do–it doesn’t work with sets–so I won’t test it.

issubset and issuperset work when it is a subset.

>>> s.issubset(original)
True
>>> s.issuperset(original)
False

__ior__ works, including setting _p_changed

>>> s._p_changed = False
>>> s |= original
>>> s._p_changed
True
>>> s == original
True

issubset and issuperset work when sets are equal.

>>> s.issubset(original)
True
>>> s.issuperset(original)
True

issubset and issuperset work when it is a superset.

>>> s.add(9)
>>> s.issubset(original)
False
>>> s.issuperset(original)
True

__hash__ works, insofar as raising an error as it is supposed to.

>>> hash(original)
Traceback (most recent call last):
...
TypeError:...unhashable...

__iand__ works, including setting _p_changed

>>> s._p_changed = False
>>> s &= original
>>> s._p_changed
True
>>> sorted(s)
[1, 2, 3, 4, 5, 6, 7, 8]

__isub__ works, including setting _p_changed

>>> s._p_changed = False
>>> s -= factory((1, 2, 3, 4, 5, 6, 7))
>>> s._p_changed
True
>>> sorted(s)
[8]

__ixor__ works, including setting _p_changed

>>> s._p_changed = False
>>> s ^= original
>>> s._p_changed
True
>>> sorted(s)
[1, 2, 3, 4, 5, 6, 7]

difference_update works, including setting _p_changed

>>> s._p_changed = False
>>> s.difference_update((7, 8))
>>> s._p_changed
True
>>> sorted(s)
[1, 2, 3, 4, 5, 6]

intersection_update works, including setting _p_changed

>>> s._p_changed = False
>>> s.intersection_update((2, 3, 4, 5, 6, 7))
>>> s._p_changed
True
>>> sorted(s)
[2, 3, 4, 5, 6]

symmetric_difference_update works, including setting _p_changed

>>> s._p_changed = False
>>> original.add(9)
>>> s.symmetric_difference_update(original)
>>> s._p_changed
True
>>> sorted(s)
[1, 7, 8, 9]

remove works, including setting _p_changed

>>> s._p_changed = False
>>> s.remove(1)
>>> s._p_changed
True
>>> sorted(s)
[7, 8, 9]

If it raises an error, _p_changed is not set.

>>> s._p_changed = False
>>> s.remove(1)
Traceback (most recent call last):
...
KeyError: 1
>>> s._p_changed
False
>>> sorted(s)
[7, 8, 9]

discard works, including setting _p_changed

>>> s._p_changed = False
>>> s.discard(9)
>>> s._p_changed
True
>>> sorted(s)
[7, 8]

If you discard something that wasn’t in the set, _p_changed will still be set. This is an efficiency decision, rather than our desired behavior, necessarily.

>>> s._p_changed = False
>>> s.discard(9)
>>> s._p_changed
True
>>> sorted(s)
[7, 8]

pop works, including setting _p_changed

>>> s._p_changed = False
>>> s.pop() in (7, 8)
True
>>> s._p_changed
True
>>> len(s)
1

clear works, including setting _p_changed

>>> s._p_changed = False
>>> s.clear()
>>> s._p_changed
True
>>> len(s)
0

The methods that return sets all return persistent sets. They otherwise work identically.

__and__

>>> s.update((0,1,2,3,4))
>>> res = s & original
>>> sorted(res)
[1, 2, 3, 4]
>>> res.__class__ is s.__class__
True

__or__

>>> res = s | original
>>> sorted(res)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> res.__class__ is s.__class__
True

__sub__

>>> res = s - original
>>> sorted(res)
[0]
>>> res.__class__ is s.__class__
True

__xor__

>>> res = s ^ original
>>> sorted(res)
[0, 5, 6, 7, 8, 9]
>>> res.__class__ is s.__class__
True

__rand__

>>> res = set((3,4,5)) & s
>>> sorted(res)
[3, 4]
>>> res.__class__ is s.__class__
True

__ror__

>>> res = set((3,4,5)) | s
>>> sorted(res)
[0, 1, 2, 3, 4, 5]
>>> res.__class__ is s.__class__
True

__rsub__

>>> res = set((3,4,5)) - s
>>> sorted(res)
[5]
>>> res.__class__ is s.__class__
True

__rxor__

>>> res = set((3,4,5)) ^ s
>>> sorted(res)
[0, 1, 2, 5]
>>> res.__class__ is s.__class__
True

difference

>>> res = s.difference((3,4,5))
>>> sorted(res)
[0, 1, 2]
>>> res.__class__ is s.__class__
True

intersection

>>> res = s.intersection((3,4,5))
>>> sorted(res)
[3, 4]
>>> res.__class__ is s.__class__
True

symmetric_difference

>>> res = s.symmetric_difference((3,4,5))
>>> sorted(res)
[0, 1, 2, 5]
>>> res.__class__ is s.__class__
True

union

>>> res = s.union((3,4,5))
>>> sorted(res)
[0, 1, 2, 3, 4, 5]
>>> res.__class__ is s.__class__
True

copy returns…a copy.

>>> res = s.copy()
>>> res == s
True
>>> res.__class__ is s.__class__
True

Project details


Release history Release notifications | RSS feed

This version

0.2

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

zc.set-0.2.tar.gz (10.2 kB view details)

Uploaded Source

Built Distributions

zc.set-0.2-py3-none-any.whl (8.7 kB view details)

Uploaded Python 3

zc.set-0.2-py2.py3-none-any.whl (8.7 kB view details)

Uploaded Python 2 Python 3

File details

Details for the file zc.set-0.2.tar.gz.

File metadata

  • Download URL: zc.set-0.2.tar.gz
  • Upload date:
  • Size: 10.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/46.1.3 requests-toolbelt/0.9.1 tqdm/4.45.0 CPython/3.8.2

File hashes

Hashes for zc.set-0.2.tar.gz
Algorithm Hash digest
SHA256 72a8ab65f1b351effae9324db85008dc36e29ad7704983b01c5948bb7f5b7a9a
MD5 d7dc2bdba991fb894586fc3d33660bf2
BLAKE2b-256 4b9b7f0eaafb5f17c2ded7226df847011c0d5fc2cc37bb0910b4fd712d7e2f4b

See more details on using hashes here.

File details

Details for the file zc.set-0.2-py3-none-any.whl.

File metadata

  • Download URL: zc.set-0.2-py3-none-any.whl
  • Upload date:
  • Size: 8.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/46.1.3 requests-toolbelt/0.9.1 tqdm/4.45.0 CPython/3.8.2

File hashes

Hashes for zc.set-0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 08a7fa1a4abd26ca36cc4739970e8d703a2165c874bacb243229f838a906df70
MD5 03504903665cb541405506749908c59b
BLAKE2b-256 79f76a1e997a4110c9e0f6d6e84effe8a1c72a55f6b704ae3fd342512eb78115

See more details on using hashes here.

File details

Details for the file zc.set-0.2-py2.py3-none-any.whl.

File metadata

  • Download URL: zc.set-0.2-py2.py3-none-any.whl
  • Upload date:
  • Size: 8.7 kB
  • Tags: Python 2, Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/46.1.3 requests-toolbelt/0.9.1 tqdm/4.45.0 CPython/3.8.2

File hashes

Hashes for zc.set-0.2-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 da51bca6ffa3cf4dbe968eff6fbcd0eff1c06154acefd53006a1b366fd45ec51
MD5 6df03eeac7ecca3f969cf1c34de046fe
BLAKE2b-256 851440dbbde2622ff66457a92aa46740c0034edd94c5f2094ff3e4ac19d11aaf

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page