[Python-modules-commits] [python-persistent] 02/15: Import python-persistent_4.2.2.orig.tar.gz

Barry Warsaw barry at moszumanska.debian.org
Fri Jan 6 21:13:38 UTC 2017


This is an automated email from the git hooks/post-receive script.

barry pushed a commit to branch master
in repository python-persistent.

commit 3b72c0c67086e25ce401b6cb4f1925a8b6e07e24
Author: Julien Muchembled <jm at jmuchemb.eu>
Date:   Thu Dec 1 22:16:34 2016 +0100

    Import python-persistent_4.2.2.orig.tar.gz
---
 .gitignore                           |  17 ---
 .travis.yml                          |  54 ++++++--
 CHANGES.rst                          |  31 +++++
 PKG-INFO                             |  51 +++++++-
 README.rst                           |  15 +++
 bootstrap.py                         |  51 +++++---
 ez_setup.py                          | 234 -----------------------------------
 persistent.egg-info/PKG-INFO         |  51 +++++++-
 persistent.egg-info/SOURCES.txt      |   3 +-
 persistent/_timestamp.c              |   5 +
 persistent/cPersistence.c            |  56 ++++++++-
 persistent/persistence.py            |  16 ++-
 persistent/tests/test_persistence.py |  51 ++++++++
 persistent/tests/test_timestamp.py   | 120 +++++++++---------
 persistent/tests/test_wref.py        |   2 +
 persistent/timestamp.py              |  16 ++-
 rtd.txt                              |   1 +
 setup.py                             |   5 +-
 tox.ini                              |  18 +--
 19 files changed, 437 insertions(+), 360 deletions(-)

diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index 28c5025..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,17 +0,0 @@
-*.pyc
-*.so
-__pycache__
-build
-docs/_build
-bin
-develop-eggs
-eggs
-parts
-.tox
-.coverage
-nosetests.xml
-coverage.xml
-*.egg-info
-.installed.cfg
-.dir-locals.el
-dist
diff --git a/.travis.yml b/.travis.yml
index 0bb0ce3..24a86f9 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,16 +1,50 @@
 language: python
 sudo: false
-python:
-    - 2.6
-    - 2.7
-    - 3.2
-    - 3.3
-    - 3.4
-    - pypy
-    - pypy3
+matrix:
+    include:
+        - os: linux
+          python: 2.7
+        - os: linux
+          python: 3.3
+        - os: linux
+          python: 3.4
+        - os: linux
+          python: 3.5
+        - os: linux
+          python: pypy
+        - os: linux
+          python: pypy3
+        - os: osx
+          language: generic
+          env: TERRYFY_PYTHON='homebrew 2'
+        - os: osx
+          language: generic
+          env: TERRYFY_PYTHON='macpython 3.4'
+        - os: osx
+          language: generic
+          env: TERRYFY_PYTHON='homebrew 3.5'
+before_install:
+    - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then git clone https://github.com/MacPython/terryfy; fi
+    - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then source terryfy/travis_tools.sh; fi
+    - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then get_python_environment $TERRYFY_PYTHON venv; fi
+    - if [[ "$TERRYFY_PYTHON" == "homebrew 3" ]]; then alias pip=`which pip3` ; fi
 install:
-    - pip install . --use-mirrors
+    - pip install -e .
 script:
-    - python setup.py test -q
+    - python setup.py -q test -q
 notifications:
     email: false
+after_success:
+    - echo [distutils]                                  > ~/.pypirc
+    - echo index-servers = pypi                        >> ~/.pypirc
+    - echo [pypi]                                      >> ~/.pypirc
+    - echo repository=https://pypi.python.org/pypi     >> ~/.pypirc
+    - echo username=zope.wheelbuilder                  >> ~/.pypirc
+    - echo password=$PYPIPASSWORD                      >> ~/.pypirc
+    - if [[ $TRAVIS_TAG && "$TRAVIS_OS_NAME" == "osx" ]]; then pip install twine; fi
+    - if [[ $TRAVIS_TAG && "$TRAVIS_OS_NAME" == "osx" ]]; then python setup.py bdist_wheel; fi
+    - if [[ $TRAVIS_TAG && "$TRAVIS_OS_NAME" == "osx" ]]; then twine upload dist/*; fi
+
+env:
+    global:
+        secure: "avoDyPgppusNzldim5fq35sk7HAn3B8zs2KgAe+8Yr3MDpFaxNV96rhNkTdHgsNNw4N+PVew1sFUxLY7HzACyywLFPUPT+YMRcPeqiuekkQoQxatYR0dEfHrxPpNyvXRxIV+nrKTEaIxQNyDcJcyRw6K7NSNxuu2NR6Dj+xJmKY="
diff --git a/CHANGES.rst b/CHANGES.rst
index d698a24..eae8c9d 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -1,6 +1,37 @@
 ``persistent`` Changelog
 ========================
 
+4.2.2 (2016-11-29)
+------------------
+
+- Drop use of ``ctypes`` for determining maximum integer size, to increase
+  pure-Python compatibility.
+
+- Ensure that ``__slots__`` attributes are cleared when a persistent
+  object is ghostified.  (This excluses classes that override
+  ``__new__``.  See
+  https://github.com/zopefoundation/persistent/wiki/Notes_on_state_new_and_slots
+  if you're curious.)
+
+4.2.1 (2016-05-26)
+------------------
+
+- Fix the hashcode of C ``TimeStamp`` objects on 64-bit Python 3 on
+  Windows.
+
+4.2.0 (2016-05-05)
+------------------
+
+- Fixed the Python(/PYPY) implementation ``TimeStamp.timeTime`` method
+  to have subsecond precision.
+
+- When testing ``PURE_PYTHON`` environments under ``tox``, avoid poisoning
+  the user's global wheel cache.
+
+- Add support for Python 3.5.
+
+- Drop support for Python 2.6 and 3.2.
+
 4.1.1 (2015-06-02)
 ------------------
 
diff --git a/PKG-INFO b/PKG-INFO
index 3396a8d..f7fa1d0 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: persistent
-Version: 4.1.1
+Version: 4.2.2
 Summary: Translucent persistent objects
 Home-page: http://www.zope.org/Products/ZODB
 Author: Zope Corporation
@@ -9,6 +9,21 @@ License: ZPL 2.1
 Description: ``persistent``:  automatic persistence for Python objects
         =========================================================
         
+        .. image:: https://travis-ci.org/zopefoundation/persistent.png?branch=master
+                :target: https://travis-ci.org/zopefoundation/persistent
+        
+        .. image:: https://readthedocs.org/projects/persistent/badge/?version=latest
+                :target: http://persistent.readthedocs.org/en/latest/
+                :alt: Documentation Status
+        
+        .. image:: https://img.shields.io/pypi/v/persistent.svg
+                :target: https://pypi.python.org/pypi/persistent
+                :alt: PyPI
+        
+        .. image:: https://img.shields.io/pypi/pyversions/persistent.svg
+                :target: https://pypi.python.org/pypi/persistent
+                :alt: Python versions
+        
         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.
@@ -26,6 +41,37 @@ Description: ``persistent``:  automatic persistence for Python objects
         ``persistent`` Changelog
         ========================
         
+        4.2.2 (2016-11-29)
+        ------------------
+        
+        - Drop use of ``ctypes`` for determining maximum integer size, to increase
+          pure-Python compatibility.
+        
+        - Ensure that ``__slots__`` attributes are cleared when a persistent
+          object is ghostified.  (This excluses classes that override
+          ``__new__``.  See
+          https://github.com/zopefoundation/persistent/wiki/Notes_on_state_new_and_slots
+          if you're curious.)
+        
+        4.2.1 (2016-05-26)
+        ------------------
+        
+        - Fix the hashcode of C ``TimeStamp`` objects on 64-bit Python 3 on
+          Windows.
+        
+        4.2.0 (2016-05-05)
+        ------------------
+        
+        - Fixed the Python(/PYPY) implementation ``TimeStamp.timeTime`` method
+          to have subsecond precision.
+        
+        - When testing ``PURE_PYTHON`` environments under ``tox``, avoid poisoning
+          the user's global wheel cache.
+        
+        - Add support for Python 3.5.
+        
+        - Drop support for Python 2.6 and 3.2.
+        
         4.1.1 (2015-06-02)
         ------------------
         
@@ -199,12 +245,11 @@ Classifier: Development Status :: 6 - Mature
 Classifier: License :: OSI Approved :: Zope Public License
 Classifier: Programming Language :: Python
 Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.6
 Classifier: Programming Language :: Python :: 2.7
 Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.2
 Classifier: Programming Language :: Python :: 3.3
 Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
 Classifier: Programming Language :: Python :: Implementation :: CPython
 Classifier: Programming Language :: Python :: Implementation :: PyPy
 Classifier: Framework :: ZODB
diff --git a/README.rst b/README.rst
index 4678d0f..6b34a92 100644
--- a/README.rst
+++ b/README.rst
@@ -1,6 +1,21 @@
 ``persistent``:  automatic persistence for Python objects
 =========================================================
 
+.. image:: https://travis-ci.org/zopefoundation/persistent.png?branch=master
+        :target: https://travis-ci.org/zopefoundation/persistent
+
+.. image:: https://readthedocs.org/projects/persistent/badge/?version=latest
+        :target: http://persistent.readthedocs.org/en/latest/
+        :alt: Documentation Status
+
+.. image:: https://img.shields.io/pypi/v/persistent.svg
+        :target: https://pypi.python.org/pypi/persistent
+        :alt: PyPI
+
+.. image:: https://img.shields.io/pypi/pyversions/persistent.svg
+        :target: https://pypi.python.org/pypi/persistent
+        :alt: Python versions
+
 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.
diff --git a/bootstrap.py b/bootstrap.py
index a629566..a459921 100644
--- a/bootstrap.py
+++ b/bootstrap.py
@@ -25,7 +25,10 @@ import tempfile
 
 from optparse import OptionParser
 
-tmpeggs = tempfile.mkdtemp()
+__version__ = '2015-07-01'
+# See zc.buildout's changelog if this version is up to date.
+
+tmpeggs = tempfile.mkdtemp(prefix='bootstrap-')
 
 usage = '''\
 [DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options]
@@ -40,8 +43,9 @@ this script from going over the network.
 '''
 
 parser = OptionParser(usage=usage)
-parser.add_option("-v", "--version", help="use a specific zc.buildout version")
-
+parser.add_option("--version",
+                  action="store_true", default=False,
+                  help=("Return bootstrap.py version."))
 parser.add_option("-t", "--accept-buildout-test-releases",
                   dest='accept_buildout_test_releases',
                   action="store_true", default=False,
@@ -59,25 +63,33 @@ parser.add_option("-f", "--find-links",
 parser.add_option("--allow-site-packages",
                   action="store_true", default=False,
                   help=("Let bootstrap.py use existing site packages"))
+parser.add_option("--buildout-version",
+                  help="Use a specific zc.buildout version")
 parser.add_option("--setuptools-version",
-                  help="use a specific setuptools version")
-
+                  help="Use a specific setuptools version")
+parser.add_option("--setuptools-to-dir",
+                  help=("Allow for re-use of existing directory of "
+                        "setuptools versions"))
 
 options, args = parser.parse_args()
+if options.version:
+    print("bootstrap.py version %s" % __version__)
+    sys.exit(0)
+
 
 ######################################################################
 # load/install setuptools
 
 try:
-    if options.allow_site_packages:
-        import setuptools
-        import pkg_resources
     from urllib.request import urlopen
 except ImportError:
     from urllib2 import urlopen
 
 ez = {}
-exec(urlopen('https://bootstrap.pypa.io/ez_setup.py').read(), ez)
+if os.path.exists('ez_setup.py'):
+    exec(open('ez_setup.py').read(), ez)
+else:
+    exec(urlopen('https://bootstrap.pypa.io/ez_setup.py').read(), ez)
 
 if not options.allow_site_packages:
     # ez_setup imports site, which adds site packages
@@ -88,12 +100,19 @@ if not options.allow_site_packages:
     # We can't remove these reliably
     if hasattr(site, 'getsitepackages'):
         for sitepackage_path in site.getsitepackages():
-            sys.path[:] = [x for x in sys.path if sitepackage_path not in x]
+            # Strip all site-packages directories from sys.path that
+            # are not sys.prefix; this is because on Windows
+            # sys.prefix is a site-package directory.
+            if sitepackage_path != sys.prefix:
+                sys.path[:] = [x for x in sys.path
+                               if sitepackage_path not in x]
 
 setup_args = dict(to_dir=tmpeggs, download_delay=0)
 
 if options.setuptools_version is not None:
     setup_args['version'] = options.setuptools_version
+if options.setuptools_to_dir is not None:
+    setup_args['to_dir'] = options.setuptools_to_dir
 
 ez['use_setuptools'](**setup_args)
 import setuptools
@@ -110,7 +129,12 @@ for path in sys.path:
 
 ws = pkg_resources.working_set
 
+setuptools_path = ws.find(
+    pkg_resources.Requirement.parse('setuptools')).location
+
+# Fix sys.path here as easy_install.pth added before PYTHONPATH
 cmd = [sys.executable, '-c',
+       'import sys; sys.path[0:0] = [%r]; ' % setuptools_path +
        'from setuptools.command.easy_install import main; main()',
        '-mZqNxd', tmpeggs]
 
@@ -123,11 +147,8 @@ find_links = os.environ.get(
 if find_links:
     cmd.extend(['-f', find_links])
 
-setuptools_path = ws.find(
-    pkg_resources.Requirement.parse('setuptools')).location
-
 requirement = 'zc.buildout'
-version = options.version
+version = options.buildout_version
 if version is None and not options.accept_buildout_test_releases:
     # Figure out the most recent final version of zc.buildout.
     import setuptools.package_index
@@ -167,7 +188,7 @@ if version:
 cmd.append(requirement)
 
 import subprocess
-if subprocess.call(cmd, env=dict(os.environ, PYTHONPATH=setuptools_path)) != 0:
+if subprocess.call(cmd) != 0:
     raise Exception(
         "Failed to execute command:\n%s" % repr(cmd)[1:-1])
 
diff --git a/ez_setup.py b/ez_setup.py
deleted file mode 100644
index 9e9b281..0000000
--- a/ez_setup.py
+++ /dev/null
@@ -1,234 +0,0 @@
-#!python
-"""Bootstrap setuptools installation
-
-If you want to use setuptools in your package's setup.py, just include this
-file in the same directory with it, and add this to the top of your setup.py::
-
-    from ez_setup import use_setuptools
-    use_setuptools()
-
-If you want to require a specific version of setuptools, set a download
-mirror, or use an alternate download directory, you can do so by supplying
-the appropriate options to ``use_setuptools()``.
-
-This file can also be run as a script to install or upgrade setuptools.
-"""
-import sys
-DEFAULT_VERSION = "0.6c7"
-DEFAULT_URL     = "http://pypi.python.org/packages/%s/s/setuptools/" % sys.version[:3]
-
-md5_data = {
-    'setuptools-0.6b1-py2.3.egg': '8822caf901250d848b996b7f25c6e6ca',
-    'setuptools-0.6b1-py2.4.egg': 'b79a8a403e4502fbb85ee3f1941735cb',
-    'setuptools-0.6b2-py2.3.egg': '5657759d8a6d8fc44070a9d07272d99b',
-    'setuptools-0.6b2-py2.4.egg': '4996a8d169d2be661fa32a6e52e4f82a',
-    'setuptools-0.6b3-py2.3.egg': 'bb31c0fc7399a63579975cad9f5a0618',
-    'setuptools-0.6b3-py2.4.egg': '38a8c6b3d6ecd22247f179f7da669fac',
-    'setuptools-0.6b4-py2.3.egg': '62045a24ed4e1ebc77fe039aa4e6f7e5',
-    'setuptools-0.6b4-py2.4.egg': '4cb2a185d228dacffb2d17f103b3b1c4',
-    'setuptools-0.6c1-py2.3.egg': 'b3f2b5539d65cb7f74ad79127f1a908c',
-    'setuptools-0.6c1-py2.4.egg': 'b45adeda0667d2d2ffe14009364f2a4b',
-    'setuptools-0.6c2-py2.3.egg': 'f0064bf6aa2b7d0f3ba0b43f20817c27',
-    'setuptools-0.6c2-py2.4.egg': '616192eec35f47e8ea16cd6a122b7277',
-    'setuptools-0.6c3-py2.3.egg': 'f181fa125dfe85a259c9cd6f1d7b78fa',
-    'setuptools-0.6c3-py2.4.egg': 'e0ed74682c998bfb73bf803a50e7b71e',
-    'setuptools-0.6c3-py2.5.egg': 'abef16fdd61955514841c7c6bd98965e',
-    'setuptools-0.6c4-py2.3.egg': 'b0b9131acab32022bfac7f44c5d7971f',
-    'setuptools-0.6c4-py2.4.egg': '2a1f9656d4fbf3c97bf946c0a124e6e2',
-    'setuptools-0.6c4-py2.5.egg': '8f5a052e32cdb9c72bcf4b5526f28afc',
-    'setuptools-0.6c5-py2.3.egg': 'ee9fd80965da04f2f3e6b3576e9d8167',
-    'setuptools-0.6c5-py2.4.egg': 'afe2adf1c01701ee841761f5bcd8aa64',
-    'setuptools-0.6c5-py2.5.egg': 'a8d3f61494ccaa8714dfed37bccd3d5d',
-    'setuptools-0.6c6-py2.3.egg': '35686b78116a668847237b69d549ec20',
-    'setuptools-0.6c6-py2.4.egg': '3c56af57be3225019260a644430065ab',
-    'setuptools-0.6c6-py2.5.egg': 'b2f8a7520709a5b34f80946de5f02f53',
-    'setuptools-0.6c7-py2.3.egg': '209fdf9adc3a615e5115b725658e13e2',
-    'setuptools-0.6c7-py2.4.egg': '5a8f954807d46a0fb67cf1f26c55a82e',
-    'setuptools-0.6c7-py2.5.egg': '45d2ad28f9750e7434111fde831e8372',
-}
-
-import sys, os
-
-def _validate_md5(egg_name, data):
-    if egg_name in md5_data:
-        from md5 import md5
-        digest = md5(data).hexdigest()
-        if digest != md5_data[egg_name]:
-            print >>sys.stderr, (
-                "md5 validation of %s failed!  (Possible download problem?)"
-                % egg_name
-            )
-            sys.exit(2)
-    return data
-
-
-def use_setuptools(
-    version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
-    download_delay=15
-):
-    """Automatically find/download setuptools and make it available on sys.path
-
-    `version` should be a valid setuptools version number that is available
-    as an egg for download under the `download_base` URL (which should end with
-    a '/').  `to_dir` is the directory where setuptools will be downloaded, if
-    it is not already available.  If `download_delay` is specified, it should
-    be the number of seconds that will be paused before initiating a download,
-    should one be required.  If an older version of setuptools is installed,
-    this routine will print a message to ``sys.stderr`` and raise SystemExit in
-    an attempt to abort the calling script.
-    """
-    try:
-        import setuptools
-        if setuptools.__version__ == '0.0.1':
-            print >>sys.stderr, (
-            "You have an obsolete version of setuptools installed.  Please\n"
-            "remove it from your system entirely before rerunning this script."
-            )
-            sys.exit(2)
-    except ImportError:
-        egg = download_setuptools(version, download_base, to_dir, download_delay)
-        sys.path.insert(0, egg)
-        import setuptools; setuptools.bootstrap_install_from = egg
-
-    import pkg_resources
-    try:
-        pkg_resources.require("setuptools>="+version)
-
-    except pkg_resources.VersionConflict, e:
-        # XXX could we install in a subprocess here?
-        print >>sys.stderr, (
-            "The required version of setuptools (>=%s) is not available, and\n"
-            "can't be installed while this script is running. Please install\n"
-            " a more recent version first.\n\n(Currently using %r)"
-        ) % (version, e.args[0])
-        sys.exit(2)
-
-def download_setuptools(
-    version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
-    delay = 15
-):
-    """Download setuptools from a specified location and return its filename
-
-    `version` should be a valid setuptools version number that is available
-    as an egg for download under the `download_base` URL (which should end
-    with a '/'). `to_dir` is the directory where the egg will be downloaded.
-    `delay` is the number of seconds to pause before an actual download attempt.
-    """
-    import urllib2, shutil
-    egg_name = "setuptools-%s-py%s.egg" % (version,sys.version[:3])
-    url = download_base + egg_name
-    saveto = os.path.join(to_dir, egg_name)
-    src = dst = None
-    if not os.path.exists(saveto):  # Avoid repeated downloads
-        try:
-            from distutils import log
-            if delay:
-                log.warn("""
----------------------------------------------------------------------------
-This script requires setuptools version %s to run (even to display
-help).  I will attempt to download it for you (from
-%s), but
-you may need to enable firewall access for this script first.
-I will start the download in %d seconds.
-
-(Note: if this machine does not have network access, please obtain the file
-
-   %s
-
-and place it in this directory before rerunning this script.)
----------------------------------------------------------------------------""",
-                    version, download_base, delay, url
-                ); from time import sleep; sleep(delay)
-            log.warn("Downloading %s", url)
-            src = urllib2.urlopen(url)
-            # Read/write all in one block, so we don't create a corrupt file
-            # if the download is interrupted.
-            data = _validate_md5(egg_name, src.read())
-            dst = open(saveto,"wb"); dst.write(data)
-        finally:
-            if src: src.close()
-            if dst: dst.close()
-    return os.path.realpath(saveto)
-
-def main(argv, version=DEFAULT_VERSION):
-    """Install or upgrade setuptools and EasyInstall"""
-
-    try:
-        import setuptools
-    except ImportError:
-        egg = None
-        try:
-            egg = download_setuptools(version, delay=0)
-            sys.path.insert(0,egg)
-            from setuptools.command.easy_install import main
-            return main(list(argv)+[egg])   # we're done here
-        finally:
-            if egg and os.path.exists(egg):
-                os.unlink(egg)
-    else:
-        if setuptools.__version__ == '0.0.1':
-            # tell the user to uninstall obsolete version
-            use_setuptools(version)
-
-    req = "setuptools>="+version
-    import pkg_resources
-    try:
-        pkg_resources.require(req)
-    except pkg_resources.VersionConflict:
-        try:
-            from setuptools.command.easy_install import main
-        except ImportError:
-            from easy_install import main
-        main(list(argv)+[download_setuptools(delay=0)])
-        sys.exit(0) # try to force an exit
-    else:
-        if argv:
-            from setuptools.command.easy_install import main
-            main(argv)
-        else:
-            print "Setuptools version",version,"or greater has been installed."
-            print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)'
-
-
-
-def update_md5(filenames):
-    """Update our built-in md5 registry"""
-
-    import re
-    from md5 import md5
-
-    for name in filenames:
-        base = os.path.basename(name)
-        f = open(name,'rb')
-        md5_data[base] = md5(f.read()).hexdigest()
-        f.close()
-
-    data = ["    %r: %r,\n" % it for it in md5_data.items()]
-    data.sort()
-    repl = "".join(data)
-
-    import inspect
-    srcfile = inspect.getsourcefile(sys.modules[__name__])
-    f = open(srcfile, 'rb'); src = f.read(); f.close()
-
-    match = re.search("\nmd5_data = {\n([^}]+)}", src)
-    if not match:
-        print >>sys.stderr, "Internal error!"
-        sys.exit(2)
-
-    src = src[:match.start(1)] + repl + src[match.end(1):]
-    f = open(srcfile,'w')
-    f.write(src)
-    f.close()
-
-
-if __name__=='__main__':
-    if len(sys.argv)>2 and sys.argv[1]=='--md5update':
-        update_md5(sys.argv[2:])
-    else:
-        main(sys.argv[1:])
-
-
-
-
-
diff --git a/persistent.egg-info/PKG-INFO b/persistent.egg-info/PKG-INFO
index 3396a8d..f7fa1d0 100644
--- a/persistent.egg-info/PKG-INFO
+++ b/persistent.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: persistent
-Version: 4.1.1
+Version: 4.2.2
 Summary: Translucent persistent objects
 Home-page: http://www.zope.org/Products/ZODB
 Author: Zope Corporation
@@ -9,6 +9,21 @@ License: ZPL 2.1
 Description: ``persistent``:  automatic persistence for Python objects
         =========================================================
         
+        .. image:: https://travis-ci.org/zopefoundation/persistent.png?branch=master
+                :target: https://travis-ci.org/zopefoundation/persistent
+        
+        .. image:: https://readthedocs.org/projects/persistent/badge/?version=latest
+                :target: http://persistent.readthedocs.org/en/latest/
+                :alt: Documentation Status
+        
+        .. image:: https://img.shields.io/pypi/v/persistent.svg
+                :target: https://pypi.python.org/pypi/persistent
+                :alt: PyPI
+        
+        .. image:: https://img.shields.io/pypi/pyversions/persistent.svg
+                :target: https://pypi.python.org/pypi/persistent
+                :alt: Python versions
+        
         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.
@@ -26,6 +41,37 @@ Description: ``persistent``:  automatic persistence for Python objects
         ``persistent`` Changelog
         ========================
         
+        4.2.2 (2016-11-29)
+        ------------------
+        
+        - Drop use of ``ctypes`` for determining maximum integer size, to increase
+          pure-Python compatibility.
+        
+        - Ensure that ``__slots__`` attributes are cleared when a persistent
+          object is ghostified.  (This excluses classes that override
+          ``__new__``.  See
+          https://github.com/zopefoundation/persistent/wiki/Notes_on_state_new_and_slots
+          if you're curious.)
+        
+        4.2.1 (2016-05-26)
+        ------------------
+        
+        - Fix the hashcode of C ``TimeStamp`` objects on 64-bit Python 3 on
+          Windows.
+        
+        4.2.0 (2016-05-05)
+        ------------------
+        
+        - Fixed the Python(/PYPY) implementation ``TimeStamp.timeTime`` method
+          to have subsecond precision.
+        
+        - When testing ``PURE_PYTHON`` environments under ``tox``, avoid poisoning
+          the user's global wheel cache.
+        
+        - Add support for Python 3.5.
+        
+        - Drop support for Python 2.6 and 3.2.
+        
         4.1.1 (2015-06-02)
         ------------------
         
@@ -199,12 +245,11 @@ Classifier: Development Status :: 6 - Mature
 Classifier: License :: OSI Approved :: Zope Public License
 Classifier: Programming Language :: Python
 Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.6
 Classifier: Programming Language :: Python :: 2.7
 Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.2
 Classifier: Programming Language :: Python :: 3.3
 Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
 Classifier: Programming Language :: Python :: Implementation :: CPython
 Classifier: Programming Language :: Python :: Implementation :: PyPy
 Classifier: Framework :: ZODB
diff --git a/persistent.egg-info/SOURCES.txt b/persistent.egg-info/SOURCES.txt
index d9a2e69..1839aec 100644
--- a/persistent.egg-info/SOURCES.txt
+++ b/persistent.egg-info/SOURCES.txt
@@ -1,5 +1,4 @@
 .coveragerc
-.gitignore
 .travis.yml
 CHANGES.rst
 COPYRIGHT.txt
@@ -8,7 +7,7 @@ MANIFEST.in
 README.rst
 bootstrap.py
 buildout.cfg
-ez_setup.py
+rtd.txt
 setup.cfg
 setup.py
 tox.ini
diff --git a/persistent/_timestamp.c b/persistent/_timestamp.c
index 83bcdf8..63ced30 100644
--- a/persistent/_timestamp.c
+++ b/persistent/_timestamp.c
@@ -152,7 +152,12 @@ TimeStamp_richcompare(TimeStamp *self, TimeStamp *other, int op)
     return result;
 }
 
+
+#ifdef PY3K
+static Py_hash_t
+#else
 static long
+#endif
 TimeStamp_hash(TimeStamp *self)
 {
     register unsigned char *p = (unsigned char *)self->data;
diff --git a/persistent/cPersistence.c b/persistent/cPersistence.c
index 36ce441..67cdbd2 100644
--- a/persistent/cPersistence.c
+++ b/persistent/cPersistence.c
@@ -82,6 +82,7 @@ fatal_1350(cPersistentObject *self, const char *caller, const char *detail)
 #endif
 
 static void ghostify(cPersistentObject*);
+static PyObject * pickle_slotnames(PyTypeObject *cls);
 
 static PyObject * convert_name(PyObject *name);
 
@@ -150,7 +151,7 @@ accessed(cPersistentObject *self)
 static void
 ghostify(cPersistentObject *self)
 {
-    PyObject **dictptr;
+    PyObject **dictptr, *slotnames;
 
     /* are we already a ghost? */
     if (self->state == cPersistent_GHOST_STATE)
@@ -180,6 +181,8 @@ ghostify(cPersistentObject *self)
         _estimated_size_in_bytes(self->estimated_size);
     ring_del(&self->ring);
     self->state = cPersistent_GHOST_STATE;
+
+    /* clear __dict__ */
     dictptr = _PyObject_GetDictPtr((PyObject *)self);
     if (dictptr && *dictptr)
     {
@@ -187,6 +190,53 @@ ghostify(cPersistentObject *self)
         *dictptr = NULL;
     }
 
+    /* clear all slots besides _p_*
+     * ( for backward-compatibility reason we do this only if class does not
+     *   override __new__ ) */
+    if (Py_TYPE(self)->tp_new == Pertype.tp_new)
+    {
+        slotnames = pickle_slotnames(Py_TYPE(self));
+        if (slotnames && slotnames != Py_None)
+        {
+            int i;
+
+            for (i = 0; i < PyList_GET_SIZE(slotnames); i++)
+            {
+                PyObject *name;
+                char *cname;
+                int is_special;
+
+                name = PyList_GET_ITEM(slotnames, i);
+#ifdef PY3K
+                if (PyUnicode_Check(name))
+                {
+                    PyObject *converted = convert_name(name);
+                    cname = PyBytes_AS_STRING(converted);
+#else
+                if (PyBytes_Check(name))
+                {
+                    cname = PyBytes_AS_STRING(name);
+#endif
+                    is_special = !strncmp(cname, "_p_", 3);
+#ifdef PY3K
+                    Py_DECREF(converted);
+#endif
+                    if (is_special) /* skip persistent */
+                    {
+                        continue;
+                    }
+                }
+
+                /* NOTE: this skips our delattr hook */
+                if (PyObject_GenericSetAttr((PyObject *)self, name, NULL) < 0)
+                    /* delattr of non-set slot will raise AttributeError - we
+                     * simply ignore. */
+                    PyErr_Clear();
+            }
+        }
+        Py_XDECREF(slotnames);
+    }
+
     /* We remove the reference to the just ghosted object that the ring
     * holds.  Note that the dictionary of oids->objects has an uncounted
     * reference, so if the ring's reference was the only one, this frees
@@ -270,6 +320,8 @@ Per__p_deactivate(cPersistentObject *self)
             called directly. Methods that override this need to
             do the same! */
         ghostify(self);
+        if (PyErr_Occurred())
+            return NULL;
     }
 
     Py_INCREF(Py_None);
@@ -298,6 +350,8 @@ Per__p_invalidate(cPersistentObject *self)
         if (Per_set_changed(self, NULL) < 0)
             return NULL;
         ghostify(self);
+        if (PyErr_Occurred())
+            return NULL;
     }
     Py_INCREF(Py_None);
     return Py_None;
diff --git a/persistent/persistence.py b/persistent/persistence.py
index 25c1520..1388da4 100644
--- a/persistent/persistence.py
+++ b/persistent/persistence.py
@@ -303,11 +303,11 @@ class Persistent(object):
                     _OGA(self, '_p_register')()
         object.__delattr__(self, name)
 
-    def _slotnames(self):
+    def _slotnames(self, _v_exclude=True):
         slotnames = copy_reg._slotnames(type(self))
         return [x for x in slotnames
                    if not x.startswith('_p_') and
-                      not x.startswith('_v_') and
+                      not (x.startswith('_v_') and _v_exclude) and
                       not x.startswith('_Persistent__') and
                       x not in Persistent.__slots__]
 
@@ -423,6 +423,18 @@ class Persistent(object):
         idict = getattr(self, '__dict__', None)
         if idict is not None:
             idict.clear()
+        type_ = type(self)
+        # ( for backward-compatibility reason we release __slots__ only if
+        #   class does not override __new__ )
+        if type_.__new__ is Persistent.__new__:
+            for slotname in Persistent._slotnames(self, _v_exclude=False):
+                try:
+                    getattr(type_, slotname).__delete__(self)
+                except AttributeError:
+                    # AttributeError means slot variable was not initialized at all -
+                    # - we can simply skip its deletion.
+                    pass
+
         # Implementation detail: deactivating/invalidating
         # updates the size of the cache (if we have one)
         # by telling it this object no longer takes any bytes
diff --git a/persistent/tests/test_persistence.py b/persistent/tests/test_persistence.py
index b883a8a..09c294f 100644
--- a/persistent/tests/test_persistence.py
+++ b/persistent/tests/test_persistence.py
@@ -1319,6 +1319,57 @@ class _Persistent_Base(object):
         self.assertEqual(list(jar._loaded), [])
         self.assertEqual(list(jar._registered), [])
 
+    def test__p_invalidate_from_changed_w_slots(self):
+        class Derived(self._getTargetClass()):
+            __slots__ = ('myattr1', 'myattr2', 'unset')
+            def __init__(self):
+                self.myattr1 = 'value1'
+                self.myattr2 = 'value2'
+        inst, jar, OID = self._makeOneWithJar(Derived)
+        inst._p_activate()
+        inst._p_changed = True
+        jar._loaded = []
+        jar._registered = []
+        self.assertEqual(Derived.myattr1.__get__(inst), 'value1')
+        self.assertEqual(Derived.myattr2.__get__(inst), 'value2')
+        inst._p_invalidate()
+        self.assertEqual(inst._p_status, 'ghost')
+        self.assertEqual(list(jar._loaded), [])
+        self.assertRaises(AttributeError, lambda: Derived.myattr1.__get__(inst))
+        self.assertRaises(AttributeError, lambda: Derived.myattr2.__get__(inst))
+        self.assertEqual(list(jar._loaded), [])
+        self.assertEqual(list(jar._registered), [])
+
+    def test__p_invalidate_from_changed_w_slots_compat(self):
+        # check that (for backward-compatibility reason) slots are not released
+        # for classes where __new__ is overwritten. Attributes in __dict__
+        # should be always released.
+        class Derived(self._getTargetClass()):
+            __slots__ = ('myattr1', 'myattr2', '__dict__')
+            def __new__(cls):
+                obj = cls.__base__.__new__(cls)
+                obj.myattr1 = 'value1'
+                obj.myattr2 = 'value2'
+                obj.foo = 'foo1' # .foo & .bar are in __dict__
+                obj.bar = 'bar2'
+                return obj
+        inst, jar, OID = self._makeOneWithJar(Derived)
+        inst._p_activate()
+        inst._p_changed = True
+        jar._loaded = []
+        jar._registered = []
+        self.assertEqual(Derived.myattr1.__get__(inst), 'value1')
+        self.assertEqual(Derived.myattr2.__get__(inst), 'value2')
+        self.assertEqual(inst.__dict__, {'foo': 'foo1', 'bar': 'bar2'})
+        inst._p_invalidate()
+        self.assertEqual(inst._p_status, 'ghost')
+        self.assertEqual(list(jar._loaded), [])
+        self.assertEqual(Derived.myattr1.__get__(inst), 'value1')
+        self.assertEqual(Derived.myattr2.__get__(inst), 'value2')
+        self.assertEqual(inst.__dict__, {})
+        self.assertEqual(list(jar._loaded), [])
+        self.assertEqual(list(jar._registered), [])
+
     def test__p_invalidate_from_sticky(self):
         inst, jar, OID = self._makeOneWithJar()
         inst._p_activate() # XXX
diff --git a/persistent/tests/test_timestamp.py b/persistent/tests/test_timestamp.py
index f83c31d..670e46b 100644
--- a/persistent/tests/test_timestamp.py
+++ b/persistent/tests/test_timestamp.py
@@ -11,13 +11,11 @@
 # FOR A PARTICULAR PURPOSE.
 #
 ##############################################################################
-import operator
 import unittest
 
-import platform
-py_impl = getattr(platform, 'python_implementation', lambda: None)
-_is_jython = py_impl() == 'Jython'
 
+MAX_32_BITS = 2 ** 31 - 1
+MAX_64_BITS = 2 ** 63 - 1
 
 class Test__UTC(unittest.TestCase):
 
@@ -100,9 +98,10 @@ class pyTimeStampTests(unittest.TestCase):
         self.assertEqual(ts.timeTime(), DELTA_SECS)
 
     def test_ctor_from_string_non_zero(self):
-        before = self._makeOne(2011, 2, 16, 14, 37, 22.0)
+        before = self._makeOne(2011, 2, 16, 14, 37, 22.80544)
         after = self._makeOne(before.raw())
         self.assertEqual(before.raw(), after.raw())
+        self.assertEqual(before.timeTime(), 1297867042.80544)
 
     def test_ctor_from_elements(self):
         from persistent.timestamp import _makeOctets
@@ -159,35 +158,37 @@ class pyTimeStampTests(unittest.TestCase):
         self.assertEqual(repr(ts), repr(SERIAL))
 
     def test_comparisons_to_non_timestamps(self):
+        import operator
         from persistent._compat import PYTHON2
         # Check the corner cases when comparing non-comparable types
         ts = self._makeOne(2011, 2, 16, 14, 37, 22.0)
 
-        if PYTHON2:
-            def check(op, passes):
-                if passes == 'neither':
... 356 lines suppressed ...

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-persistent.git



More information about the Python-modules-commits mailing list