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 =

Reply via email to