Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-persistent for openSUSE:Factory checked in at 2024-01-08 23:44:14 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-persistent (Old) and /work/SRC/openSUSE:Factory/.python-persistent.new.21961 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-persistent" Mon Jan 8 23:44:14 2024 rev:16 rq:1137436 version:5.1 Changes: -------- --- /work/SRC/openSUSE:Factory/python-persistent/python-persistent.changes 2023-08-16 14:16:44.634830808 +0200 +++ /work/SRC/openSUSE:Factory/.python-persistent.new.21961/python-persistent.changes 2024-01-08 23:44:30.096652546 +0100 @@ -1,0 +2,7 @@ +Sun Jan 7 20:15:51 UTC 2024 - Dirk Müller <dmuel...@suse.com> + +- update to 5.1: + * Add support for Python 3.12. +- drop python312.patch (upstream) + +------------------------------------------------------------------- Old: ---- persistent-5.0.tar.gz python312.patch New: ---- persistent-5.1.tar.gz BETA DEBUG BEGIN: Old: * Add support for Python 3.12. - drop python312.patch (upstream) BETA DEBUG END: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-persistent.spec ++++++ --- /var/tmp/diff_new_pack.H2wCEr/_old 2024-01-08 23:44:30.836679452 +0100 +++ /var/tmp/diff_new_pack.H2wCEr/_new 2024-01-08 23:44:30.836679452 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-persistent # -# Copyright (c) 2023 SUSE LLC +# Copyright (c) 2024 SUSE LLC # Copyright (c) 2013-2023 LISA GmbH, Bingen, Germany. # # All modifications and additions to the file contributed by third parties @@ -19,13 +19,12 @@ %{?sle15_python_module_pythons} Name: python-persistent -Version: 5.0 +Version: 5.1 Release: 0 Summary: Translucent persistent objects License: ZPL-2.1 URL: https://github.com/zopefoundation/persistent Source: https://files.pythonhosted.org/packages/source/p/persistent/persistent-%{version}.tar.gz -Patch1: python312.patch BuildRequires: %{python_module cffi} BuildRequires: %{python_module devel} BuildRequires: %{python_module manuel} ++++++ persistent-5.0.tar.gz -> persistent-5.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/persistent-5.0/.manylinux-install.sh new/persistent-5.1/.manylinux-install.sh --- old/persistent-5.0/.manylinux-install.sh 2023-01-09 16:06:42.000000000 +0100 +++ new/persistent-5.1/.manylinux-install.sh 2023-10-05 14:50:50.000000000 +0200 @@ -33,6 +33,7 @@ *"cp39"*) echo 'py39';; *"cp310"*) echo 'py310';; *"cp311"*) echo 'py311';; + *"cp312"*) echo 'py312';; *) echo 'py';; esac } @@ -41,6 +42,7 @@ for PYBIN in /opt/python/*/bin; do if \ [[ "${PYBIN}" == *"cp311"* ]] || \ + [[ "${PYBIN}" == *"cp312"* ]] || \ [[ "${PYBIN}" == *"cp37"* ]] || \ [[ "${PYBIN}" == *"cp38"* ]] || \ [[ "${PYBIN}" == *"cp39"* ]] || \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/persistent-5.0/.readthedocs.yaml new/persistent-5.1/.readthedocs.yaml --- old/persistent-5.0/.readthedocs.yaml 1970-01-01 01:00:00.000000000 +0100 +++ new/persistent-5.1/.readthedocs.yaml 2023-10-05 14:50:50.000000000 +0200 @@ -0,0 +1,25 @@ +# Generated from: +# https://github.com/zopefoundation/meta/tree/master/config/c-code +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +# Set the version of Python and other tools you might need +build: + os: ubuntu-22.04 + tools: + python: "3.11" + +# Build documentation in the docs/ directory with Sphinx +sphinx: + configuration: docs/conf.py + +# We recommend specifying your dependencies to enable reproducible builds: +# https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html +python: + install: + - requirements: docs/requirements.txt + - method: pip + path: . diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/persistent-5.0/CHANGES.rst new/persistent-5.1/CHANGES.rst --- old/persistent-5.0/CHANGES.rst 2023-01-09 16:06:42.000000000 +0100 +++ new/persistent-5.1/CHANGES.rst 2023-10-05 14:50:50.000000000 +0200 @@ -2,6 +2,12 @@ ``persistent`` Changelog ========================== +5.1 (2023-10-05) +================ + +- Add support for Python 3.12. + + 5.0 (2023-01-09) ================ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/persistent-5.0/MANIFEST.in new/persistent-5.1/MANIFEST.in --- old/persistent-5.0/MANIFEST.in 2023-01-09 16:06:42.000000000 +0100 +++ new/persistent-5.1/MANIFEST.in 2023-10-05 14:50:50.000000000 +0200 @@ -14,6 +14,7 @@ recursive-include docs Makefile recursive-include src *.py +include *.yaml include *.sh recursive-include docs *.bat recursive-include src *.h diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/persistent-5.0/PKG-INFO new/persistent-5.1/PKG-INFO --- old/persistent-5.0/PKG-INFO 2023-01-09 16:06:46.202301700 +0100 +++ new/persistent-5.1/PKG-INFO 2023-10-05 15:20:02.909608800 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: persistent -Version: 5.0 +Version: 5.1 Summary: Translucent persistent objects Home-page: https://github.com/zopefoundation/persistent/ Author: Zope Foundation and Contributors @@ -18,6 +18,7 @@ Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Framework :: ZODB @@ -26,10 +27,17 @@ Classifier: Operating System :: Microsoft :: Windows Classifier: Operating System :: Unix Requires-Python: >=3.7 +License-File: LICENSE.txt +Requires-Dist: zope.interface +Requires-Dist: cffi; platform_python_implementation == "CPython" Provides-Extra: test +Requires-Dist: zope.testrunner; extra == "test" +Requires-Dist: manuel; extra == "test" Provides-Extra: testing Provides-Extra: docs -License-File: LICENSE.txt +Requires-Dist: Sphinx; extra == "docs" +Requires-Dist: repoze.sphinx.autointerface; extra == "docs" +Requires-Dist: sphinx_rtd_theme; extra == "docs" =========================================================== ``persistent``: automatic persistence for Python objects @@ -76,6 +84,12 @@ ``persistent`` Changelog ========================== +5.1 (2023-10-05) +================ + +- Add support for Python 3.12. + + 5.0 (2023-01-09) ================ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/persistent-5.0/appveyor.yml new/persistent-5.1/appveyor.yml --- old/persistent-5.0/appveyor.yml 2023-01-09 16:06:42.000000000 +0100 +++ new/persistent-5.1/appveyor.yml 2023-10-05 14:50:50.000000000 +0200 @@ -15,6 +15,7 @@ - python: 39-x64 - python: 310-x64 - python: 311-x64 + - python: 312-x64 install: - "SET PYTHONVERSION=%PYTHON%" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/persistent-5.0/docs/_build/doctest/output.txt new/persistent-5.1/docs/_build/doctest/output.txt --- old/persistent-5.0/docs/_build/doctest/output.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/persistent-5.1/docs/_build/doctest/output.txt 2023-10-05 14:15:37.000000000 +0200 @@ -0,0 +1,41 @@ +Results of doctest builder run on 2023-10-05 14:15:37 +===================================================== + +Document: using +--------------- +1 items passed all tests: + 97 tests in default +97 tests in 1 items. +97 passed and 0 failed. +Test passed. + +Document: api/cache +------------------- +1 items passed all tests: + 11 tests in default +11 tests in 1 items. +11 passed and 0 failed. +Test passed. + +Document: api/attributes +------------------------ +1 items passed all tests: + 80 tests in default +80 tests in 1 items. +80 passed and 0 failed. +Test passed. + +Document: api/pickling +---------------------- +1 items passed all tests: + 68 tests in default +68 tests in 1 items. +68 passed and 0 failed. +Test passed. + +Doctest summary +=============== + 256 tests + 0 failures in tests + 0 failures in setup code + 0 failures in cleanup code diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/persistent-5.0/docs/_build/html/_sources/api/attributes.rst.txt new/persistent-5.1/docs/_build/html/_sources/api/attributes.rst.txt --- old/persistent-5.0/docs/_build/html/_sources/api/attributes.rst.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/persistent-5.1/docs/_build/html/_sources/api/attributes.rst.txt 2022-11-03 14:57:25.000000000 +0100 @@ -0,0 +1,329 @@ +Customizing Attribute Access +============================ + +Hooking :meth:`__getattr__` +--------------------------- +The __getattr__ method works pretty much the same for persistent +classes as it does for other classes. No special handling is +needed. If an object is a ghost, then it will be activated before +__getattr__ is called. + +In this example, our objects returns a tuple with the attribute +name, converted to upper case and the value of _p_changed, for any +attribute that isn't handled by the default machinery. + +.. doctest:: + + >>> from persistent.tests.attrhooks import OverridesGetattr + >>> o = OverridesGetattr() + >>> o._p_changed + False + >>> o._p_oid + >>> o._p_jar + >>> o.spam + ('SPAM', False) + >>> o.spam = 1 + >>> o.spam + 1 + +We'll save the object, so it can be deactivated: + +.. doctest:: + + >>> from persistent.tests.attrhooks import _resettingJar + >>> jar = _resettingJar() + >>> jar.add(o) + >>> o._p_deactivate() + >>> o._p_changed + +And now, if we ask for an attribute it doesn't have, + +.. doctest:: + + >>> o.eggs + ('EGGS', False) + +And we see that the object was activated before calling the +:meth:`__getattr__` method. + +Hooking All Access +------------------ + +In this example, we'll provide an example that shows how to +override the :meth:`__getattribute__`, :meth:`__setattr__`, and +:meth:`__delattr__` methods. We'll create a class that stores it's +attributes in a secret dictionary within the instance dictionary. + +The class will have the policy that variables with names starting +with ``tmp_`` will be volatile. + +Our sample class takes initial values as keyword arguments to the constructor: + +.. doctest:: + + >>> from persistent.tests.attrhooks import VeryPrivate + >>> o = VeryPrivate(x=1) + + +Hooking :meth:`__getattribute__`` +################################# + +The :meth:`__getattribute__` method is called for all attribute +accesses. It overrides the attribute access support inherited +from Persistent. + +.. doctest:: + + >>> o._p_changed + False + >>> o._p_oid + >>> o._p_jar + >>> o.x + 1 + >>> o.y + Traceback (most recent call last): + ... + AttributeError: y + +Next, we'll save the object in a database so that we can deactivate it: + +.. doctest:: + + >>> from persistent.tests.attrhooks import _rememberingJar + >>> jar = _rememberingJar() + >>> jar.add(o) + >>> o._p_deactivate() + >>> o._p_changed + +And we'll get some data: + +.. doctest:: + + >>> o.x + 1 + +which activates the object: + +.. doctest:: + + >>> o._p_changed + False + +It works for missing attributes too: + +.. doctest:: + + >>> o._p_deactivate() + >>> o._p_changed + + >>> o.y + Traceback (most recent call last): + ... + AttributeError: y + + >>> o._p_changed + False + + +Hooking :meth:`__setattr__`` +############################ + +The :meth:`__setattr__` method is called for all attribute +assignments. It overrides the attribute assignment support +inherited from Persistent. + +Implementors of :meth:`__setattr__` methods: + +1. Must call Persistent._p_setattr first to allow it + to handle some attributes and to make sure that the object + is activated if necessary, and + +2. Must set _p_changed to mark objects as changed. + +.. doctest:: + + >>> o = VeryPrivate() + >>> o._p_changed + False + >>> o._p_oid + >>> o._p_jar + >>> o.x + Traceback (most recent call last): + ... + AttributeError: x + + >>> o.x = 1 + >>> o.x + 1 + +Because the implementation doesn't store attributes directly +in the instance dictionary, we don't have a key for the attribute: + +.. doctest:: + + >>> 'x' in o.__dict__ + False + +Next, we'll give the object a "remembering" jar so we can +deactivate it: + +.. doctest:: + + >>> jar = _rememberingJar() + >>> jar.add(o) + >>> o._p_deactivate() + >>> o._p_changed + +We'll modify an attribute + +.. doctest:: + + >>> o.y = 2 + >>> o.y + 2 + +which reactivates it, and marks it as modified, because our +implementation marked it as modified: + +.. doctest:: + + >>> o._p_changed + True + +Now, if fake a commit: + +.. doctest:: + + >>> jar.fake_commit() + >>> o._p_changed + False + +And deactivate the object: + +.. doctest:: + + >>> o._p_deactivate() + >>> o._p_changed + +and then set a variable with a name starting with ``tmp_``, +The object will be activated, but not marked as modified, +because our :meth:`__setattr__` implementation doesn't mark the +object as changed if the name starts with ``tmp_``: + +.. doctest:: + + >>> o.tmp_foo = 3 + >>> o._p_changed + False + >>> o.tmp_foo + 3 + + +Hooking :meth:`__delattr__`` +############################ + +The __delattr__ method is called for all attribute +deletions. It overrides the attribute deletion support +inherited from Persistent. + +Implementors of :meth:`__delattr__` methods: + +1. Must call Persistent._p_delattr first to allow it + to handle some attributes and to make sure that the object + is activated if necessary, and + +2. Must set _p_changed to mark objects as changed. + +.. doctest:: + + >>> o = VeryPrivate(x=1, y=2, tmp_z=3) + >>> o._p_changed + False + >>> o._p_oid + >>> o._p_jar + >>> o.x + 1 + >>> del o.x + >>> o.x + Traceback (most recent call last): + ... + AttributeError: x + +Next, we'll save the object in a jar so that we can +deactivate it: + +.. doctest:: + + >>> jar = _rememberingJar() + >>> jar.add(o) + >>> o._p_deactivate() + >>> o._p_changed + +If we delete an attribute: + +.. doctest:: + + >>> del o.y + +The object is activated. It is also marked as changed because +our implementation marked it as changed. + +.. doctest:: + + >>> o._p_changed + True + >>> o.y + Traceback (most recent call last): + ... + AttributeError: y + + >>> o.tmp_z + 3 + +Now, if fake a commit: + +.. doctest:: + + >>> jar.fake_commit() + >>> o._p_changed + False + +And deactivate the object: + +.. doctest:: + + >>> o._p_deactivate() + >>> o._p_changed + +and then delete a variable with a name starting with ``tmp_``, +The object will be activated, but not marked as modified, +because our :meth:`__delattr__` implementation doesn't mark the +object as changed if the name starts with ``tmp_``: + +.. doctest:: + + >>> del o.tmp_z + >>> o._p_changed + False + >>> o.tmp_z + Traceback (most recent call last): + ... + AttributeError: tmp_z + +If we attempt to delete ``_p_oid``, we find that we can't, and the +object is also not activated or changed: + +.. doctest:: + + >>> del o._p_oid + Traceback (most recent call last): + ... + ValueError: can't delete _p_oid of cached object + >>> o._p_changed + False + +We are allowed to delete ``_p_changed``, which sets it to ``None``: + + >>> del o._p_changed + >>> o._p_changed is None + True diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/persistent-5.0/docs/_build/html/_sources/api/cache.rst.txt new/persistent-5.1/docs/_build/html/_sources/api/cache.rst.txt --- old/persistent-5.0/docs/_build/html/_sources/api/cache.rst.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/persistent-5.1/docs/_build/html/_sources/api/cache.rst.txt 2022-11-03 14:57:25.000000000 +0100 @@ -0,0 +1,59 @@ +Caching Persistent Objects +========================== + +Creating Objects ``de novo`` +---------------------------- + +Creating ghosts from scratch, as opposed to ghostifying a non-ghost +is rather tricky. :class:`~persistent.interfaces.IPeristent` doesn't +really provide the right interface given that: + +- :meth:`_p_deactivate` and :meth:`_p_invalidate` are overridable, and + could assume that the object's state is properly initialized. + +- Assigning :attr:`_p_changed` to None just calls :meth:`_p_deactivate`. + +- Deleting :attr:`_p_changed` just calls :meth:`_p_invalidate`. + +.. note:: + + The current cache implementation is intimately tied up with the + persistence implementation and has internal access to the persistence + state. The cache implementation can update the persistence state for + newly created and uninitialized objects directly. + + The future persistence and cache implementations will be far more + decoupled. The persistence implementation will only manage object + state and generate object-usage events. The cache implementation(s) + will be responsible for managing persistence-related (meta-)state, + such as _p_state, _p_changed, _p_oid, etc. So in that future + implementation, the cache will be more central to managing object + persistence information. + +Caches have a :meth:`new_ghost` method that: + +- adds an object to the cache, and + +- initializes its persistence data. + +.. doctest:: + + >>> import persistent + >>> from persistent.tests.utils import ResettingJar + + >>> class C(persistent.Persistent): + ... pass + + >>> jar = ResettingJar() + >>> cache = persistent.PickleCache(jar, 10, 100) + >>> ob = C.__new__(C) + >>> cache.new_ghost(b'1', ob) + + >>> ob._p_changed + >>> ob._p_jar is jar + True + >>> ob._p_oid == b'1' + True + + >>> cache.cache_non_ghost_count + 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/persistent-5.0/docs/_build/html/_sources/api/collections.rst.txt new/persistent-5.1/docs/_build/html/_sources/api/collections.rst.txt --- old/persistent-5.0/docs/_build/html/_sources/api/collections.rst.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/persistent-5.1/docs/_build/html/_sources/api/collections.rst.txt 2022-11-03 14:57:25.000000000 +0100 @@ -0,0 +1,14 @@ +======================== + Persistent Collections +======================== + +The ``persistent`` package provides two simple collections that are +persistent and keep track of when they are mutated in place. + +.. autoclass:: persistent.mapping.PersistentMapping + :members: + :show-inheritance: + +.. autoclass:: persistent.list.PersistentList + :members: + :show-inheritance: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/persistent-5.0/docs/_build/html/_sources/api/interfaces.rst.txt new/persistent-5.1/docs/_build/html/_sources/api/interfaces.rst.txt --- old/persistent-5.0/docs/_build/html/_sources/api/interfaces.rst.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/persistent-5.1/docs/_build/html/_sources/api/interfaces.rst.txt 2022-11-03 14:57:25.000000000 +0100 @@ -0,0 +1,26 @@ +:mod:`persistent.interfaces` +=================================== + +.. automodule:: persistent.interfaces + + .. autointerface:: IPersistent + :members: + :member-order: bysource + + .. autointerface:: IPersistentDataManager + :members: + :member-order: bysource + + .. autointerface:: IPickleCache + :members: + :member-order: bysource + +Implementations +=============== + +This package provides one implementation of :class:`IPersistent` that +should be extended. + + .. autoclass:: persistent.Persistent + :members: + :show-inheritance: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/persistent-5.0/docs/_build/html/_sources/api/pickling.rst.txt new/persistent-5.1/docs/_build/html/_sources/api/pickling.rst.txt --- old/persistent-5.0/docs/_build/html/_sources/api/pickling.rst.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/persistent-5.1/docs/_build/html/_sources/api/pickling.rst.txt 2022-11-03 14:57:25.000000000 +0100 @@ -0,0 +1,167 @@ +Pickling Persistent Objects +=========================== + +Persistent objects are designed to make the standard Python pickling +machinery happy: + +.. doctest:: + + >>> import pickle + >>> from persistent.tests.cucumbers import Simple + >>> from persistent.tests.cucumbers import print_dict + + >>> x = Simple('x', aaa=1, bbb='foo') + + >>> print_dict(x.__getstate__()) + {'__name__': 'x', 'aaa': 1, 'bbb': 'foo'} + + >>> f, (c,), state = x.__reduce__() + >>> f.__name__ + '__newobj__' + >>> f.__module__.replace('_', '') # Normalize Python2/3 + 'copyreg' + >>> c.__name__ + 'Simple' + + >>> print_dict(state) + {'__name__': 'x', 'aaa': 1, 'bbb': 'foo'} + + >>> import pickle + >>> pickle.loads(pickle.dumps(x)) == x + True + >>> pickle.loads(pickle.dumps(x, 0)) == x + True + >>> pickle.loads(pickle.dumps(x, 1)) == x + True + + >>> pickle.loads(pickle.dumps(x, 2)) == x + True + + >>> x.__setstate__({'z': 1}) + >>> x.__dict__ + {'z': 1} + +This support even works well for derived classes which customize pickling +by overriding :meth:`__getnewargs__`, :meth:`__getstate__` and +:meth:`__setstate__`. + +.. doctest:: + + >>> from persistent.tests.cucumbers import Custom + + >>> x = Custom('x', 'y') + >>> x.__getnewargs__() + ('x', 'y') + >>> x.a = 99 + + >>> (f, (c, ax, ay), a) = x.__reduce__() + >>> f.__name__ + '__newobj__' + >>> f.__module__.replace('_', '') # Normalize Python2/3 + 'copyreg' + >>> c.__name__ + 'Custom' + >>> ax, ay, a + ('x', 'y', 99) + + >>> pickle.loads(pickle.dumps(x)) == x + True + >>> pickle.loads(pickle.dumps(x, 0)) == x + True + >>> pickle.loads(pickle.dumps(x, 1)) == x + True + >>> pickle.loads(pickle.dumps(x, 2)) == x + True + +The support works for derived classes which define :attr:`__slots__`. It +ignores any slots which map onto the "persistent" namespace (prefixed with +``_p_``) or the "volatile" namespace (prefixed with ``_v_``): + +.. doctest:: + + >>> from persistent.tests.cucumbers import SubSlotted + >>> x = SubSlotted('x', 'y', 'z') + +Note that we haven't yet assigned a value to the ``s4`` attribute: + +.. doctest:: + + >>> d, s = x.__getstate__() + >>> d + >>> print_dict(s) + {'s1': 'x', 's2': 'y', 's3': 'z'} + + >>> import pickle + >>> pickle.loads(pickle.dumps(x)) == x + True + >>> pickle.loads(pickle.dumps(x, 0)) == x + True + >>> pickle.loads(pickle.dumps(x, 1)) == x + True + >>> pickle.loads(pickle.dumps(x, 2)) == x + True + + +After assigning it: + +.. doctest:: + + >>> x.s4 = 'spam' + + >>> d, s = x.__getstate__() + >>> d + >>> print_dict(s) + {'s1': 'x', 's2': 'y', 's3': 'z', 's4': 'spam'} + + >>> pickle.loads(pickle.dumps(x)) == x + True + >>> pickle.loads(pickle.dumps(x, 0)) == x + True + >>> pickle.loads(pickle.dumps(x, 1)) == x + True + >>> pickle.loads(pickle.dumps(x, 2)) == x + True + +:class:`persistent.Persistent` supports derived classes which have base +classes defining :attr:`__slots`, but which do not define attr:`__slots__` +themselves: + +.. doctest:: + + >>> from persistent.tests.cucumbers import SubSubSlotted + >>> x = SubSubSlotted('x', 'y', 'z') + + >>> d, s = x.__getstate__() + >>> print_dict(d) + {} + >>> print_dict(s) + {'s1': 'x', 's2': 'y', 's3': 'z'} + + >>> import pickle + >>> pickle.loads(pickle.dumps(x)) == x + True + >>> pickle.loads(pickle.dumps(x, 0)) == x + True + >>> pickle.loads(pickle.dumps(x, 1)) == x + True + >>> pickle.loads(pickle.dumps(x, 2)) == x + True + + >>> x.s4 = 'spam' + >>> x.foo = 'bar' + >>> x.baz = 'bam' + + >>> d, s = x.__getstate__() + >>> print_dict(d) + {'baz': 'bam', 'foo': 'bar'} + >>> print_dict(s) + {'s1': 'x', 's2': 'y', 's3': 'z', 's4': 'spam'} + + >>> pickle.loads(pickle.dumps(x)) == x + True + >>> pickle.loads(pickle.dumps(x, 0)) == x + True + >>> pickle.loads(pickle.dumps(x, 1)) == x + True + >>> pickle.loads(pickle.dumps(x, 2)) == x + True diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/persistent-5.0/docs/_build/html/_sources/api.rst.txt new/persistent-5.1/docs/_build/html/_sources/api.rst.txt --- old/persistent-5.0/docs/_build/html/_sources/api.rst.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/persistent-5.1/docs/_build/html/_sources/api.rst.txt 2022-11-03 14:57:25.000000000 +0100 @@ -0,0 +1,11 @@ +:mod:`persistent` API documentation +=================================== + +.. toctree:: + :maxdepth: 2 + + api/interfaces + api/collections + api/attributes + api/pickling + api/cache diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/persistent-5.0/docs/_build/html/_sources/changes.rst.txt new/persistent-5.1/docs/_build/html/_sources/changes.rst.txt --- old/persistent-5.0/docs/_build/html/_sources/changes.rst.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/persistent-5.1/docs/_build/html/_sources/changes.rst.txt 2022-11-03 14:57:25.000000000 +0100 @@ -0,0 +1 @@ +.. include:: ../CHANGES.rst diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/persistent-5.0/docs/_build/html/_sources/glossary.rst.txt new/persistent-5.1/docs/_build/html/_sources/glossary.rst.txt --- old/persistent-5.0/docs/_build/html/_sources/glossary.rst.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/persistent-5.1/docs/_build/html/_sources/glossary.rst.txt 2022-11-03 14:57:25.000000000 +0100 @@ -0,0 +1,50 @@ +.. _glossary: + +Glossary +======== + +.. glossary:: + :sorted: + + data manager + The object responsible for storing and loading an object's + :term:`pickled data` in a backing store. Also called a :term:`jar`. + + jar + Alias for :term:`data manager`: short for "pickle jar", because + it traditionally holds the :term:`pickled data` of persistent objects. + + object cache + An MRU cache for objects associated with a given :term:`data manager`. + + ghost + An object whose :term:`pickled data` has not yet been loaded from its + :term:`jar`. Accessing or mutating any of its attributes causes + that data to be loaded, which is referred to as :term:`activation`. + + volatile attribute + Attributes of a persistent object which are *not* captured as part + of its :term:`pickled data`. These attributes thus disappear during + :term:`deactivation` or :term:`invalidation`. + + pickled data + The serialized data of a persistent object, stored in and retrieved + from a backing store by a :term:`data manager`. + + activation + Moving an object from the ``GHOST`` state to the ``UPTODATE`` state, + load its :term:`pickled data` from its :term:`jar`. + + deactivation + Moving an object from the ``UPTODATE`` state to the ``GHOST`` state, + discarding its :term:`pickled data`. + + invalidation + Moving an object from either the ``UPTODATE`` state or the ``CHANGED`` + state to the ``GHOST`` state, discarding its :term:`pickled data`. + + object id + The stable identifier that uniquely names a particular object. + This is analogous to Python's `id`, but unlike `id`, object + ids remain the same for a given object across different + processes. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/persistent-5.0/docs/_build/html/_sources/index.rst.txt new/persistent-5.1/docs/_build/html/_sources/index.rst.txt --- old/persistent-5.0/docs/_build/html/_sources/index.rst.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/persistent-5.1/docs/_build/html/_sources/index.rst.txt 2022-11-03 14:57:25.000000000 +0100 @@ -0,0 +1,23 @@ +:mod:`persistent`: automatic persistence for Python objects +============================================================ + +This package contains a generic persistence implementation for Python. It +forms the core protocol for making objects interact "transparently" with +a database such as the ZODB. + +Contents: + +.. toctree:: + :maxdepth: 2 + + using + api + changes + glossary + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/persistent-5.0/docs/_build/html/_sources/using.rst.txt new/persistent-5.1/docs/_build/html/_sources/using.rst.txt --- old/persistent-5.0/docs/_build/html/_sources/using.rst.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/persistent-5.1/docs/_build/html/_sources/using.rst.txt 2022-11-03 14:57:25.000000000 +0100 @@ -0,0 +1,466 @@ +============================================= + Using :mod:`persistent` in your application +============================================= + + +Inheriting from :class:`persistent.Persistent` +============================================== + +The basic mechanism for making your application's objects persistent +is mix-in inheritance. Instances whose classes derive from +:class:`persistent.Persistent` are automatically capable of being +created as :term:`ghost` instances, being associated with a database +connection (called the :term:`jar`), and notifying the connection when +they have been changed. + + +Relationship to a Data Manager and its Cache +============================================ + +Except immediately after their creation, persistent objects are normally +associated with a :term:`data manager` (also referred to as a :term:`jar`). +An object's data manager is stored in its ``_p_jar`` attribute. +The data manager is responsible for loading and saving the state of the +persistent object to some sort of backing store, including managing any +interactions with transaction machinery. + +Each data manager maintains an :term:`object cache`, which keeps track of +the currently loaded objects, as well as any objects they reference which +have not yet been loaded: such an object is called a :term:`ghost`. +The cache is stored on the data manager in its ``_cache`` attribute. + +A persistent object remains in the ghost state until the application +attempts to access or mutate one of its attributes: at that point, the +object requests that its data manager load its state. The persistent +object also notifies the cache that it has been loaded, as well as on +each subsequent attribute access. The cache keeps a "most-recently-used" +list of its objects, and removes objects in least-recently-used order +when it is asked to reduce its working set. + +The examples below use a stub data manager class: + +.. doctest:: + + >>> from zope.interface import implementer + >>> from persistent.interfaces import IPersistentDataManager + >>> @implementer(IPersistentDataManager) + ... class DM(object): + ... def __init__(self): + ... self.registered = 0 + ... def register(self, ob): + ... self.registered += 1 + ... def setstate(self, ob): + ... ob.__setstate__({'x': 42}) + +.. note:: + Notice that the ``DM`` class always sets the ``x`` attribute to the value + ``42`` when activating an object. + + +Persistent objects without a Data Manager +========================================= + +Before persistent instance has been associated with a a data manager ( +i.e., its ``_p_jar`` is still ``None``). + +The examples below use a class, ``P``, defined as: + +.. doctest:: + + >>> from persistent import Persistent + >>> from persistent.interfaces import GHOST, UPTODATE, CHANGED + >>> class P(Persistent): + ... def __init__(self): + ... self.x = 0 + ... def inc(self): + ... self.x += 1 + +Instances of the derived ``P`` class which are not (yet) assigned to +a :term:`data manager` behave as other Python instances, except that +they have some extra attributes: + +.. doctest:: + + >>> p = P() + >>> p.x + 0 + +The :attr:`_p_changed` attribute is a three-state flag: it can be +one of ``None`` (the object is not loaded), ``False`` (the object has +not been changed since it was loaded) or ``True`` (the object has been +changed). Until the object is assigned a :term:`jar`, this attribute +will always be ``False``. + +.. doctest:: + + >>> p._p_changed + False + +The :attr:`_p_state` attribute is an integer, representing which of the +"persistent lifecycle" states the object is in. Until the object is assigned +a :term:`jar`, this attribute will always be ``0`` (the ``UPTODATE`` +constant): + +.. doctest:: + + >>> p._p_state == UPTODATE + True + +The :attr:`_p_jar` attribute is the object's :term:`data manager`. Since +it has not yet been assigned, its value is ``None``: + +.. doctest:: + + >>> print(p._p_jar) + None + +The :attr:`_p_oid` attribute is the :term:`object id`, a unique value +normally assigned by the object's :term:`data manager`. Since the object +has not yet been associated with its :term:`jar`, its value is ``None``: + +.. doctest:: + + >>> print(p._p_oid) + None + +Without a data manager, modifying a persistent object has no effect on +its ``_p_state`` or ``_p_changed``. + +.. doctest:: + + >>> p.inc() + >>> p.inc() + >>> p.x + 2 + >>> p._p_changed + False + >>> p._p_state + 0 + +Try all sorts of different ways to change the object's state: + +.. doctest:: + + >>> p._p_deactivate() + >>> p._p_state + 0 + >>> p._p_changed + False + >>> p._p_changed = True + >>> p._p_changed + False + >>> p._p_state + 0 + >>> del p._p_changed + >>> p._p_changed + False + >>> p._p_state + 0 + >>> p.x + 2 + + +Associating an Object with a Data Manager +========================================= + +Once associated with a data manager, a persistent object's behavior changes: + +.. doctest:: + + >>> p = P() + >>> dm = DM() + >>> p._p_oid = "00000012" + >>> p._p_jar = dm + >>> p._p_changed + False + >>> p._p_state + 0 + >>> p.__dict__ + {'x': 0} + >>> dm.registered + 0 + +Modifying the object marks it as changed and registers it with the data +manager. Subsequent modifications don't have additional side-effects. + +.. doctest:: + + >>> p.inc() + >>> p.x + 1 + >>> p.__dict__ + {'x': 1} + >>> p._p_changed + True + >>> p._p_state + 1 + >>> dm.registered + 1 + >>> p.inc() + >>> p._p_changed + True + >>> p._p_state + 1 + >>> dm.registered + 1 + +Object which register themselves with the data manager are candidates +for storage to the backing store at a later point in time. + +Note that mutating a non-persistent attribute of a persistent object +such as a :class:`dict` or :class:`list` will *not* cause the +containing object to be changed. Instead you can either explicitly +control the state as described below, or use a +:class:`~.PersistentList` or :class:`~.PersistentMapping`. + +Explicitly controlling ``_p_state`` +=================================== + +Persistent objects expose three methods for moving an object into and out +of the "ghost" state:: :meth:`persistent.Persistent._p_activate`, +:meth:`persistent.Persistent._p_deactivate`, and +:meth:`persistent.Persistent._p_invalidate`: + +.. doctest:: + + >>> p = P() + >>> p._p_oid = '00000012' + >>> p._p_jar = DM() + +After being assigned a jar, the object is initially in the ``UPTODATE`` +state: + +.. doctest:: + + >>> p._p_state + 0 + +From that state, ``_p_deactivate`` rests the object to the ``GHOST`` state: + +.. doctest:: + + >>> p._p_deactivate() + >>> p._p_state + -1 + +From the ``GHOST`` state, ``_p_activate`` reloads the object's data and +moves it to the ``UPTODATE`` state: + +.. doctest:: + + >>> p._p_activate() + >>> p._p_state + 0 + >>> p.x + 42 + +Changing the object puts it in the ``CHANGED`` state: + +.. doctest:: + + >>> p.inc() + >>> p.x + 43 + >>> p._p_state + 1 + +Attempting to deactivate in the ``CHANGED`` state is a no-op: + +.. doctest:: + + >>> p._p_deactivate() + >>> p.__dict__ + {'x': 43} + >>> p._p_changed + True + >>> p._p_state + 1 + +``_p_invalidate`` forces objects into the ``GHOST`` state; it works even on +objects in the ``CHANGED`` state, which is the key difference between +deactivation and invalidation: + +.. doctest:: + + >>> p._p_invalidate() + >>> p.__dict__ + {} + >>> p._p_state + -1 + +You can manually reset the ``_p_changed`` field to ``False``: in this case, +the object changes to the ``UPTODATE`` state but retains its modifications: + +.. doctest:: + + >>> p.inc() + >>> p.x + 43 + >>> p._p_changed = False + >>> p._p_state + 0 + >>> p._p_changed + False + >>> p.x + 43 + +For an object in the "ghost" state, assigning ``True`` (or any value which is +coercible to ``True``) to its ``_p_changed`` attributes activates the object, +which is exactly the same as calling ``_p_activate``: + +.. doctest:: + + >>> p._p_invalidate() + >>> p._p_state + -1 + >>> p._p_changed = True + >>> p._p_changed + True + >>> p._p_state + 1 + >>> p.x + 42 + + +The pickling protocol +===================== + +Because persistent objects need to control how they are pickled and +unpickled, the :class:`persistent.Persistent` base class overrides +the implementations of ``__getstate__()`` and ``__setstate__()``: + +.. doctest:: + + >>> p = P() + >>> dm = DM() + >>> p._p_oid = "00000012" + >>> p._p_jar = dm + >>> p.__getstate__() + {'x': 0} + >>> p._p_state + 0 + +Calling ``__setstate__`` always leaves the object in the uptodate state. + +.. doctest:: + + >>> p.__setstate__({'x': 5}) + >>> p._p_state + 0 + +A :term:`volatile attribute` is an attribute those whose name begins with a +special prefix (``_v__``). Unlike normal attributes, volatile attributes do +not get stored in the object's :term:`pickled data`. + +.. doctest:: + + >>> p._v_foo = 2 + >>> p.__getstate__() + {'x': 5} + +Assigning to volatile attributes doesn't cause the object to be marked as +changed: + +.. doctest:: + + >>> p._p_state + 0 + +The ``_p_serial`` attribute is not affected by calling setstate. + +.. doctest:: + + >>> p._p_serial = b"00000012" + >>> p.__setstate__(p.__getstate__()) + >>> p._p_serial + b'00000012' + + +Estimated Object Size +===================== + +We can store a size estimation in ``_p_estimated_size``. Its default is 0. +The size estimation can be used by a cache associated with the data manager +to help in the implementation of its replacement strategy or its size bounds. + +.. doctest:: + + >>> p._p_estimated_size + 0 + >>> p._p_estimated_size = 1000 + >>> p._p_estimated_size + 1024 + +Huh? Why is the estimated size coming out different than what we put +in? The reason is that the size isn't stored exactly. For backward +compatibility reasons, the size needs to fit in 24 bits, so, +internally, it is adjusted somewhat. + +Of course, the estimated size must not be negative. + +.. doctest:: + + >>> p._p_estimated_size = -1 + Traceback (most recent call last): + ... + ValueError: _p_estimated_size must not be negative + + +Overriding the attribute protocol +================================= + +Subclasses which override the attribute-management methods provided by +:class:`persistent.Persistent`, but must obey some constraints: + + +:meth:`__getattribute__` + When overriding ``__getattribute__``, the derived class implementation + **must** first call :meth:`persistent.IPersistent._p_getattr`, passing the + name being accessed. This method ensures that the object is activated, + if needed, and handles the "special" attributes which do not require + activation (e.g., ``_p_oid``, ``__class__``, ``__dict__``, etc.) + If ``_p_getattr`` returns ``True``, the derived class implementation + **must** delegate to the base class implementation for the attribute. + +:meth:`__setattr__` + When overriding ``__setattr__``, the derived class implementation + **must** first call :meth:`persistent.IPersistent._p_setattr`, passing the + name being accessed and the value. This method ensures that the object is + activated, if needed, and handles the "special" attributes which do not + require activation (``_p_*``). If ``_p_setattr`` returns ``True``, the + derived implementation must assume that the attribute value has been set by + the base class. + +:meth:`__delattr__` + When overriding ``__delattr__``, the derived class implementation + **must** first call :meth:`persistent.IPersistent._p_delattr`, passing the + name being accessed. This method ensures that the object is + activated, if needed, and handles the "special" attributes which do not + require activation (``_p_*``). If ``_p_delattr`` returns ``True``, the + derived implementation must assume that the attribute has been deleted + base class. + +:meth:`__getattr__` + For the ``__getattr__`` method, the behavior is like that for regular Python + classes and for earlier versions of ZODB 3. + + +Implementing ``_p_repr`` +======================== + +Subclasses can implement ``_p_repr`` to provide a custom +representation. If this method raises an exception, the default +representation will be used. The benefit of implementing ``_p_repr`` +instead of overriding ``__repr__`` is that it provides safer handling +for objects that can't be activated because their persistent data is +missing or their jar is closed. + +.. doctest:: + + >>> class P(Persistent): + ... def _p_repr(self): + ... return "Custom repr" + + >>> p = P() + >>> print(repr(p)) + Custom repr diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/persistent-5.0/docs/conf.py new/persistent-5.1/docs/conf.py --- old/persistent-5.0/docs/conf.py 2023-01-09 16:06:42.000000000 +0100 +++ new/persistent-5.1/docs/conf.py 2023-10-05 14:50:50.000000000 +0200 @@ -100,7 +100,7 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = 'default' +html_theme = 'sphinx_rtd_theme' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/persistent-5.0/docs/requirements.txt new/persistent-5.1/docs/requirements.txt --- old/persistent-5.0/docs/requirements.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/persistent-5.1/docs/requirements.txt 2023-10-05 14:50:50.000000000 +0200 @@ -0,0 +1,4 @@ +Sphinx +repoze.sphinx.autointerface +sphinx_rtd_theme>1 +docutils<0.19 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/persistent-5.0/setup.cfg new/persistent-5.1/setup.cfg --- old/persistent-5.0/setup.cfg 2023-01-09 16:06:46.210622000 +0100 +++ new/persistent-5.1/setup.cfg 2023-10-05 15:20:02.909935200 +0200 @@ -19,7 +19,7 @@ force_single_line = True combine_as_imports = True sections = FUTURE,STDLIB,THIRDPARTY,ZOPE,FIRSTPARTY,LOCALFOLDER -known_third_party = six, docutils, pkg_resources +known_third_party = docutils, pkg_resources, pytz known_zope = known_first_party = default_section = ZOPE diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/persistent-5.0/setup.py new/persistent-5.1/setup.py --- old/persistent-5.0/setup.py 2023-01-09 16:06:42.000000000 +0100 +++ new/persistent-5.1/setup.py 2023-10-05 14:50:50.000000000 +0200 @@ -19,7 +19,7 @@ from setuptools import find_packages from setuptools import setup -version = '5.0' +version = '5.1' here = os.path.abspath(os.path.dirname(__file__)) @@ -99,6 +99,7 @@ "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Framework :: ZODB", @@ -132,6 +133,7 @@ 'docs': [ 'Sphinx', 'repoze.sphinx.autointerface', + 'sphinx_rtd_theme', ], }, python_requires='>=3.7', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/persistent-5.0/src/persistent/tests/test_persistence.py new/persistent-5.1/src/persistent/tests/test_persistence.py --- old/persistent-5.0/src/persistent/tests/test_persistence.py 2023-01-09 16:06:42.000000000 +0100 +++ new/persistent-5.1/src/persistent/tests/test_persistence.py 2023-04-20 10:26:28.000000000 +0200 @@ -29,11 +29,6 @@ class _Persistent_Base: - # py2/3 compat - assertRaisesRegex = getattr(unittest.TestCase, - 'assertRaisesRegex', - unittest.TestCase.assertRaisesRegexp) - def _getTargetClass(self): # concrete testcase classes must override raise NotImplementedError() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/persistent-5.0/src/persistent/tests/test_picklecache.py new/persistent-5.1/src/persistent/tests/test_picklecache.py --- old/persistent-5.0/src/persistent/tests/test_picklecache.py 2023-01-09 16:06:42.000000000 +0100 +++ new/persistent-5.1/src/persistent/tests/test_picklecache.py 2023-04-20 10:26:28.000000000 +0200 @@ -60,11 +60,6 @@ class PickleCacheTestMixin: - # py2/3 compat - assertRaisesRegex = getattr(unittest.TestCase, - 'assertRaisesRegex', - unittest.TestCase.assertRaisesRegexp) - def _getTargetClass(self): from persistent.picklecache import PickleCachePy as BasePickleCache class PickleCache(BasePickleCache): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/persistent-5.0/src/persistent.egg-info/PKG-INFO new/persistent-5.1/src/persistent.egg-info/PKG-INFO --- old/persistent-5.0/src/persistent.egg-info/PKG-INFO 2023-01-09 16:06:46.000000000 +0100 +++ new/persistent-5.1/src/persistent.egg-info/PKG-INFO 2023-10-05 15:20:02.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: persistent -Version: 5.0 +Version: 5.1 Summary: Translucent persistent objects Home-page: https://github.com/zopefoundation/persistent/ Author: Zope Foundation and Contributors @@ -18,6 +18,7 @@ Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Framework :: ZODB @@ -26,10 +27,17 @@ Classifier: Operating System :: Microsoft :: Windows Classifier: Operating System :: Unix Requires-Python: >=3.7 +License-File: LICENSE.txt +Requires-Dist: zope.interface +Requires-Dist: cffi; platform_python_implementation == "CPython" Provides-Extra: test +Requires-Dist: zope.testrunner; extra == "test" +Requires-Dist: manuel; extra == "test" Provides-Extra: testing Provides-Extra: docs -License-File: LICENSE.txt +Requires-Dist: Sphinx; extra == "docs" +Requires-Dist: repoze.sphinx.autointerface; extra == "docs" +Requires-Dist: sphinx_rtd_theme; extra == "docs" =========================================================== ``persistent``: automatic persistence for Python objects @@ -76,6 +84,12 @@ ``persistent`` Changelog ========================== +5.1 (2023-10-05) +================ + +- Add support for Python 3.12. + + 5.0 (2023-01-09) ================ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/persistent-5.0/src/persistent.egg-info/SOURCES.txt new/persistent-5.1/src/persistent.egg-info/SOURCES.txt --- old/persistent-5.0/src/persistent.egg-info/SOURCES.txt 2023-01-09 16:06:46.000000000 +0100 +++ new/persistent-5.1/src/persistent.egg-info/SOURCES.txt 2023-10-05 15:20:02.000000000 +0200 @@ -1,6 +1,7 @@ .coveragerc .manylinux-install.sh .manylinux.sh +.readthedocs.yaml CHANGES.rst CONTRIBUTING.md COPYRIGHT.txt @@ -20,7 +21,19 @@ docs/glossary.rst docs/index.rst docs/make.bat +docs/requirements.txt docs/using.rst +docs/_build/doctest/output.txt +docs/_build/html/_sources/api.rst.txt +docs/_build/html/_sources/changes.rst.txt +docs/_build/html/_sources/glossary.rst.txt +docs/_build/html/_sources/index.rst.txt +docs/_build/html/_sources/using.rst.txt +docs/_build/html/_sources/api/attributes.rst.txt +docs/_build/html/_sources/api/cache.rst.txt +docs/_build/html/_sources/api/collections.rst.txt +docs/_build/html/_sources/api/interfaces.rst.txt +docs/_build/html/_sources/api/pickling.rst.txt docs/api/attributes.rst docs/api/cache.rst docs/api/collections.rst diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/persistent-5.0/src/persistent.egg-info/requires.txt new/persistent-5.1/src/persistent.egg-info/requires.txt --- old/persistent-5.0/src/persistent.egg-info/requires.txt 2023-01-09 16:06:46.000000000 +0100 +++ new/persistent-5.1/src/persistent.egg-info/requires.txt 2023-10-05 15:20:02.000000000 +0200 @@ -6,6 +6,7 @@ [docs] Sphinx repoze.sphinx.autointerface +sphinx_rtd_theme [test] zope.testrunner diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/persistent-5.0/tox.ini new/persistent-5.1/tox.ini --- old/persistent-5.0/tox.ini 2023-01-09 16:06:42.000000000 +0100 +++ new/persistent-5.1/tox.ini 2023-10-05 14:50:50.000000000 +0200 @@ -1,7 +1,7 @@ # Generated from: # https://github.com/zopefoundation/meta/tree/master/config/c-code [tox] -minversion = 3.18 +minversion = 4.0 envlist = lint py37,py37-pure @@ -9,6 +9,7 @@ py39,py39-pure py310,py310-pure py311,py311-pure + py312,py312-pure pypy3 docs coverage @@ -16,9 +17,12 @@ [testenv] usedevelop = true deps = + py37: urllib3 < 2 setenv = pure: PURE_PYTHON=1 !pure-!pypy3: PURE_PYTHON=0 + py312: VIRTUALENV_PIP=23.1.2 + py312: PIP_REQUIRE_VIRTUALENV=0 commands = zope-testrunner --test-path=src {posargs:-vc} sphinx-build -b doctest -d {envdir}/.cache/doctrees docs {envdir}/.cache/doctest @@ -32,6 +36,7 @@ mkdir deps = coverage + py37: urllib3 < 2 setenv = PURE_PYTHON=1 commands =