Hi,

Julien Cristau <jcris...@debian.org> writes:

> I don't think that's ok.  Can't  you remove the conflicting files from
> python-zodb, and make it depend on python-persistent?

Thanks  for the  suggestion. I  talked  with upstream  authors and  this
should  be fine.   However, python-persistent  in the  archive (4.x)  is
incompatible with ZODB < 4.0.0a4 and  thus with the version available in
the  archive (3.9.7).  Therefore, I  had to  backport some  patches from
upstream so that python-zodb could depend on python-persistent.

With these  patches, all the unit  tests of python-zodb pass  when being
ran with python-persistent and  python-zodb installed (even though, they
only ran with python-zope.testing from stable, due to change in the unit
tests framework only from zope.testing 4.x).

Here are the changelog entries for both packages:

  python-persistent (4.0.8-3) unstable; urgency=medium
  
    * Team upload.
    * Revert change in previous upload in favor of removing persistent
      module from python-zodb and make it depend upon this package (with
      upstream ACK). Closes: #767554.
      + d/control: Add Breaks/Replaces against python-zodb << 1:3.9.7-4~.
  
   -- Arnaud Fontaine <ar...@debian.org>  Wed, 10 Dec 2014 17:33:13 +0900
  
  zodb (1:3.9.7-4) unstable; urgency=medium
  
    * Team upload.
    * Revert change in previous upload in favor of removing persistent
      module from this package and make it depend upon python-persistent
      (with upstream ACK). Closes: #767554.
      + d/control: Add Depends against python-persistent.
      + d/rules: Delete persistent module from final package.
      + d/p/fix_persistent_module_4.x_incompatibilities.patch: persistent 4.x
        uses bytes instead of repr() but ZODB < 4.0.0a4 still uses repr() which
        is incompatible.
      + d/tests/all: Remove persistent from the list of tests being ran.
      + d/tests/control: zope.testing.doctest has been removed in
        python-zope.testing 4.0.0 and tests cannot be ran anymore. So update
        Depends accordingly even though << 4.0.0~ is only in stable instead of
        backporting many patches. Fix this issue properly when packing NUR
        after the release of Jessie.
    * d/p/debian/patches/fix_unit_tests.patch: Fix python2.7 tests failures.
  
   -- Arnaud Fontaine <ar...@debian.org>  Fri, 12 Dec 2014 11:47:47 +0900

I have  attached the  debdiff with the  packages currently  in unstable,
would you consider unblocking these changes  if I upload the packages to
unstable?

Regards,
-- 
Arnaud Fontaine

diff -Nru python-persistent-4.0.8/debian/changelog python-persistent-4.0.8/debian/changelog
--- python-persistent-4.0.8/debian/changelog	2014-11-14 18:30:25.000000000 +0900
+++ python-persistent-4.0.8/debian/changelog	2014-12-10 17:41:09.000000000 +0900
@@ -1,3 +1,13 @@
+python-persistent (4.0.8-3) unstable; urgency=medium
+
+  * Team upload.
+  * Revert change in previous upload in favor of removing persistent
+    module from python-zodb and make it depend upon this package (with
+    upstream ACK). Closes: #767554.
+    + d/control: Add Breaks/Replaces against python-zodb << 1:3.9.7-4~.
+
+ -- Arnaud Fontaine <ar...@debian.org>  Wed, 10 Dec 2014 17:33:13 +0900
+
 python-persistent (4.0.8-2) unstable; urgency=medium
 
   * Team upload.
diff -Nru python-persistent-4.0.8/debian/control python-persistent-4.0.8/debian/control
--- python-persistent-4.0.8/debian/control	2014-11-14 18:31:01.000000000 +0900
+++ python-persistent-4.0.8/debian/control	2014-12-10 17:37:40.000000000 +0900
@@ -22,7 +22,8 @@
 Package: python-persistent
 Architecture: any
 Depends: ${misc:Depends}, ${python:Depends}, ${shlibs:Depends}
-Conflicts: python-zodb (<< 3.11.0~)
+Breaks: python-zodb (<< 1:3.9.7-4~)
+Replaces: python-zodb (<< 1:3.9.7-4~)
 Description: 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
diff -Nru zodb-3.9.7/debian/changelog zodb-3.9.7/debian/changelog
--- zodb-3.9.7/debian/changelog	2014-11-17 12:10:50.000000000 +0900
+++ zodb-3.9.7/debian/changelog	2014-12-12 12:00:34.000000000 +0900
@@ -1,3 +1,24 @@
+zodb (1:3.9.7-4) unstable; urgency=medium
+
+  * Team upload.
+  * Revert change in previous upload in favor of removing persistent
+    module from this package and make it depend upon python-persistent
+    (with upstream ACK). Closes: #767554.
+    + d/control: Add Depends against python-persistent.
+    + d/rules: Delete persistent module from final package.
+    + d/p/fix_persistent_module_4.x_incompatibilities.patch: persistent 4.x
+      uses bytes instead of repr() but ZODB < 4.0.0a4 still uses repr() which
+      is incompatible.
+    + d/tests/all: Remove persistent from the list of tests being ran.
+    + d/tests/control: zope.testing.doctest has been removed in
+      python-zope.testing 4.0.0 and tests cannot be ran anymore. So update
+      Depends accordingly even though << 4.0.0~ is only in stable instead of
+      backporting many patches. Fix this issue properly when packing NUR
+      after the release of Jessie.
+  * d/p/debian/patches/fix_unit_tests.patch: Fix python2.7 tests failures.
+
+ -- Arnaud Fontaine <ar...@debian.org>  Fri, 12 Dec 2014 11:47:47 +0900
+
 zodb (1:3.9.7-3) unstable; urgency=medium
 
   * Team upload.
diff -Nru zodb-3.9.7/debian/control zodb-3.9.7/debian/control
--- zodb-3.9.7/debian/control	2014-11-17 12:09:52.000000000 +0900
+++ zodb-3.9.7/debian/control	2014-12-10 19:46:09.000000000 +0900
@@ -19,13 +19,12 @@
 Depends: ${pydeb:Depends},
          ${python:Depends},
          ${misc:Depends},
-         ${shlibs:Depends}
+         ${shlibs:Depends},
+         python-persistent
 Provides: ${pydeb:Provides},
           ${python:Provides},
-          python-persistent
 Suggests: ${pydeb:Suggests}
-Conflicts: zope3,
-           python-persistent
+Conflicts: zope3
 Description: Zope Object Database (ZODB)
  The Zope Object Database is an object-oriented database for Python that
  provides a high-degree of transparency. Applications can take advantage of
diff -Nru zodb-3.9.7/debian/patches/fix_persistent_module_4.x_incompatibilities.patch zodb-3.9.7/debian/patches/fix_persistent_module_4.x_incompatibilities.patch
--- zodb-3.9.7/debian/patches/fix_persistent_module_4.x_incompatibilities.patch	1970-01-01 09:00:00.000000000 +0900
+++ zodb-3.9.7/debian/patches/fix_persistent_module_4.x_incompatibilities.patch	2014-12-12 11:42:03.000000000 +0900
@@ -0,0 +1,533 @@
+commit 0f8da4c9ee4eaa18224a6769f2fa2e0d7c8cdcf1
+Author: Arnaud Fontaine <ar...@debian.org>
+Date:   Fri Dec 12 11:23:30 2014 +0900
+
+    python-zodb now depends on python-persistent (they both used to provide
+    persistent module). However, python-persistent provides version 4.x of
+    persistent module which uses bytes for OID/TID instead of repr() and thus is
+    incompatible with ZODB < 4.
+    
+    Thus, backport the following upstream commits:
+    
+      commit 19e851c2230a20cfcebc68fca37ce2c0bb716b92
+      Author: Tres Seaver <tsea...@palladion.com>
+      Date:   Sat Dec 15 19:28:08 2012 +0000
+    
+          Avoid repr(tid) (use tid.raw()).
+    
+          Ensure that we use bytes literals for tid values.
+    
+          Remove non-comment / docstring use of backticks.
+    
+      commit 994af0c5f9df63d403a0e21d80eec51d69686bc4
+      Author: Tres Seaver <tsea...@palladion.com>
+      Date:   Sat Dec 15 02:02:54 2012 +0000
+    
+          Moar don't use repr(tid) to get a serial.
+    
+          repr() must return text, and we need bytes.
+    
+      commit edc6c452ee68265544d99a0d806fe62099c12308
+      Author: Tres Seaver <tsea...@palladion.com>
+      Date:   Sat Dec 15 01:42:59 2012 +0000
+    
+          Don't test TimeStamp here:  those tests are in persistent.
+    
+      commit 8dfbff499d109b1cf86d1b4b2b98a6cf8d17ce43
+      Author: Tres Seaver <tsea...@palladion.com>
+      Date:   Sat Dec 15 01:29:13 2012 +0000
+    
+          Don't use repr(tid) to get a serial.
+    
+          repr() must return text, and we need bytes.
+
+--- a/src/ZODB/BaseStorage.py
++++ b/src/ZODB/BaseStorage.py
+@@ -94,7 +94,7 @@
+ 
+         t = time.time()
+         t = self._ts = TimeStamp(*(time.gmtime(t)[:5] + (t%60,)))
+-        self._tid = repr(t)
++        self._tid = t.raw()
+ 
+         # ._oid is the highest oid in use (0 is always in use -- it's
+         # a reserved oid for the root object).  Our new_oid() method
+@@ -242,7 +242,7 @@
+                 now = time.time()
+                 t = TimeStamp(*(time.gmtime(now)[:5] + (now % 60,)))
+                 self._ts = t = t.laterThan(self._ts)
+-                self._tid = repr(t)
++                self._tid = t.raw()
+             else:
+                 self._ts = TimeStamp(tid)
+                 self._tid = tid
+@@ -369,7 +369,7 @@
+                 if ok: print ('Time stamps out of order %s, %s' % (_ts, t))
+                 ok = 0
+                 _ts = t.laterThan(_ts)
+-                tid = `_ts`
++                tid = _ts.raw()
+             else:
+                 _ts = t
+                 if not ok:
+--- a/src/ZODB/DB.py
++++ b/src/ZODB/DB.py
+@@ -319,12 +319,12 @@
+             at = toTimeStamp(at)
+         else:
+             at = TimeStamp(at)
+-        before = repr(at.laterThan(at))
++        before = at.laterThan(at).raw()
+     elif before is not None:
+         if isinstance(before, datetime.datetime):
+-            before = repr(toTimeStamp(before))
++            before = toTimeStamp(before).raw()
+         else:
+-            before = repr(TimeStamp(before))
++            before = TimeStamp(before).raw()
+     return before
+ 
+ 
+--- a/src/ZODB/FileStorage/FileStorage.py
++++ b/src/ZODB/FileStorage/FileStorage.py
+@@ -936,7 +936,7 @@
+ 
+     def _txn_undo(self, transaction_id):
+         # Find the right transaction to undo and call _txn_undo_write().
+-        tid = base64.decodestring(transaction_id + '\n')
++        tid = base64.decodestring(transaction_id + b'\n')
+         assert len(tid) == 8
+         tpos = self._txn_find(tid, 1)
+         tindex = self._txn_undo_write(tpos)
+@@ -1093,8 +1093,9 @@
+         if self._is_read_only:
+             raise POSException.ReadOnlyError()
+ 
+-        stop=`TimeStamp(*time.gmtime(t)[:5]+(t%60,))`
+-        if stop==z64: raise FileStorageError('Invalid pack time')
++        stop = TimeStamp(*time.gmtime(t)[:5]+(t%60,)).raw()
++        if stop==z64:
++            raise FileStorageError('Invalid pack time')
+ 
+         # If the storage is empty, there's nothing to do.
+         if not self._index:
+@@ -1229,7 +1230,7 @@
+             handle_dir = ZODB.blob.remove_committed_dir
+ 
+         # Fist step: move or remove oids or revisions
+-        for line in open(os.path.join(self.blob_dir, '.removed')):
++        for line in open(os.path.join(self.blob_dir, '.removed')): #XXX bytes
+             line = line.strip().decode('hex')
+ 
+             if len(line) == 8:
+@@ -1532,7 +1533,7 @@
+ 
+     pos = start
+     seek(start)
+-    tid = '\0' * 7 + '\1'
++    tid = b'\0' * 7 + b'\1'
+ 
+     while 1:
+         # Read the transaction record
+@@ -1725,7 +1726,7 @@
+         # implementation.  So just return 0.
+         return 0
+ 
+-    # This allows us to pass an iterator as the `other' argument to
++    # This allows us to pass an iterator as the `other` argument to
+     # copyTransactionsFrom() in BaseStorage.  The advantage here is that we
+     # can create the iterator manually, e.g. setting start and stop, and then
+     # just let copyTransactionsFrom() do its thing.
+@@ -1742,7 +1743,7 @@
+         file = self._file
+         pos1 = self._pos
+         file.seek(pos1)
+-        tid1 = file.read(8)
++        tid1 = file.read(8) # XXX bytes
+         if len(tid1) < 8:
+             raise CorruptedError("Couldn't read tid.")
+         if start < tid1:
+--- a/src/ZODB/FileStorage/fspack.py
++++ b/src/ZODB/FileStorage/fspack.py
+@@ -54,7 +54,7 @@
+             self._file.seek(pos - 8)
+             pos = pos - u64(self._file.read(8)) - 8
+             self._file.seek(pos)
+-            h = self._file.read(TRANS_HDR_LEN)
++            h = self._file.read(TRANS_HDR_LEN) # XXX bytes
+             _tid = h[:8]
+             if _tid == tid:
+                 return pos
+--- a/src/ZODB/MappingStorage.py
++++ b/src/ZODB/MappingStorage.py
+@@ -190,7 +190,7 @@
+         if not self._data:
+             return
+         
+-        stop = `ZODB.TimeStamp.TimeStamp(*time.gmtime(t)[:5]+(t%60,))`
++        stop = ZODB.TimeStamp.TimeStamp(*time.gmtime(t)[:5]+(t%60,)).raw()
+         if self._last_pack is not None and self._last_pack >= stop:
+             if self._last_pack == stop:
+                 return
+--- a/src/ZODB/blob.py
++++ b/src/ZODB/blob.py
+@@ -438,7 +438,8 @@
+ 
+         """
+         oidpath = self.getPathForOID(oid)
+-        fd, name = tempfile.mkstemp(suffix='.tmp', prefix=utils.tid_repr(tid),
++        fd, name = tempfile.mkstemp(suffix='.tmp',
++                                    prefix=utils.tid_repr(tid),
+                                     dir=oidpath)
+         return fd, name
+ 
+@@ -828,7 +829,7 @@
+ 
+         # The serial_id is assumed to be given to us base-64 encoded
+         # (belying the web UI legacy of the ZODB code :-()
+-        serial_id = base64.decodestring(serial_id+'\n')
++        serial_id = base64.decodestring(serial_id + b'\n')
+ 
+         self._lock_acquire()
+ 
+--- a/src/ZODB/fsrecover.py
++++ b/src/ZODB/fsrecover.py
+@@ -314,7 +314,7 @@
+                     print ("Time stamps out of order %s, %s" % (_ts, t))
+                 ok = 0
+                 _ts = t.laterThan(_ts)
+-                tid = `_ts`
++                tid = _ts.raw()
+             else:
+                 _ts = t
+                 if not ok:
+--- a/src/ZODB/scripts/fstest.py
++++ b/src/ZODB/scripts/fstest.py
+@@ -91,7 +91,7 @@
+         raise FormatError("invalid file header")
+ 
+     pos = 4L
+-    tid = '\000' * 8 # lowest possible tid to start
++    tid = b'\000' * 8 # lowest possible tid to start
+     i = 0
+     while pos:
+         _pos = pos
+@@ -110,7 +110,7 @@
+     used for generating error messages.
+     """
+ 
+-    h = file.read(TREC_HDR_LEN)
++    h = file.read(TREC_HDR_LEN) #XXX must be bytes under Py3k
+     if not h:
+         return None, None
+     if len(h) != TREC_HDR_LEN:
+--- a/src/ZODB/scripts/migrate.py
++++ b/src/ZODB/scripts/migrate.py
+@@ -262,7 +262,7 @@
+                         'Time stamps are out of order %s, %s' % (ts, t))
+                     ok = False
+                     ts = t.laterThan(ts)
+-                    tid = `ts`
++                    tid = ts.raw()
+                 else:
+                     ts = t
+                     if not ok:
+--- a/src/ZODB/scripts/repozo.py
++++ b/src/ZODB/scripts/repozo.py
+@@ -250,7 +250,7 @@
+ 
+ 
+ def concat(files, ofp=None):
+-    # Concatenate a bunch of files from the repository, output to `outfile' if
++    # Concatenate a bunch of files from the repository, output to 'ofp' if
+     # given.  Return the number of bytes written and the md5 checksum of the
+     # bytes.
+     sum = md5()
+--- a/src/ZODB/scripts/zodbload.py
++++ b/src/ZODB/scripts/zodbload.py
+@@ -319,7 +319,7 @@
+         start, tid, wcomp, ccomp, rconflicts, wconflicts, wcommit, ccommit,
+         factory.__name__, r)
+ 
+-def run(jobs, tid=''):
++def run(jobs, tid=b''):
+     import Zope2
+     while 1:
+         factory, job, args, repeatp = jobs.next()
+--- a/src/ZODB/tests/BasicStorage.py
++++ b/src/ZODB/tests/BasicStorage.py
+@@ -28,7 +28,7 @@
+ import zope.interface
+ import zope.interface.verify
+ 
+-ZERO = '\0'*8
++ZERO = b'\0'*8
+ 
+ class BasicStorage:
+     def checkBasics(self):
+--- a/src/ZODB/tests/MVCCMappingStorage.py
++++ b/src/ZODB/tests/MVCCMappingStorage.py
+@@ -34,7 +34,7 @@
+     def __init__(self, name="MVCC Mapping Storage"):
+         MappingStorage.__init__(self, name=name)
+         # _polled_tid contains the transaction ID at the last poll.
+-        self._polled_tid = ''
++        self._polled_tid = b''
+         self._data_snapshot = None  # {oid->(state, tid)}
+         self._main_lock_acquire = self._lock_acquire
+         self._main_lock_release = self._lock_release
+@@ -81,7 +81,7 @@
+             if self._transactions:
+                 new_tid = self._transactions.maxKey()
+             else:
+-                new_tid = ''
++                new_tid = b''
+ 
+             # Copy the current data into a snapshot. This is obviously
+             # very inefficient for large storages, but it's good for
+--- a/src/ZODB/tests/blob_packing.txt
++++ b/src/ZODB/tests/blob_packing.txt
+@@ -65,7 +65,7 @@
+ 
+     >>> oid = root['blob']._p_oid
+     >>> fns = [ blob_storage.fshelper.getBlobFilename(oid, x) for x in tids ]
+-    >>> [ os.path.exists(x) for x in fns ]
++    >>> [ os.path.exists(x) for x in fns ] # no pack
+     [True, True, True, True, True]
+ 
+ Do a pack to the slightly before the first revision was written:
+--- a/src/ZODB/tests/testFileStorage.py
++++ b/src/ZODB/tests/testFileStorage.py
+@@ -274,9 +274,9 @@
+         self.open()
+ 
+         key = None
+-        for x in ('\000', '\001', '\002'):
++        for x in (b'\000', b'\001', b'\002'):
+             oid, tid, data, next_oid = self._storage.record_iternext(key)
+-            self.assertEqual(oid, ('\000' * 7) + x)
++            self.assertEqual(oid, (b'\000' * 7) + x)
+             key = next_oid
+             expected_data, expected_tid = self._storage.load(oid, '')
+             self.assertEqual(expected_data, data)
+@@ -409,7 +409,7 @@
+ # Raise an exception if the tids in FileStorage fs aren't
+ # strictly increasing.
+ def checkIncreasingTids(fs):
+-    lasttid = '\0' * 8
++    lasttid = b'\0' * 8
+     for txn in fs.iterator():
+         if lasttid >= txn.tid:
+             raise ValueError("tids out of order %r >= %r" % (lasttid, txn.tid))
+--- a/src/ZODB/tests/testPersistentList.py
++++ b/src/ZODB/tests/testPersistentList.py
+@@ -50,7 +50,7 @@
+ 
+         eq(str(u0), str(l0), "str(u0) == str(l0)")
+         eq(repr(u1), repr(l1), "repr(u1) == repr(l1)")
+-        eq(`u2`, `l2`, "`u2` == `l2`")
++        eq(repr(u2), repr(l2), "repr(u2) == repr(l2)")
+ 
+         # Test __cmp__ and __len__
+ 
+--- a/src/ZODB/tests/testRecover.py
++++ b/src/ZODB/tests/testRecover.py
+@@ -147,11 +147,11 @@
+ 
+         L = self.storage.undoLog()
+         r = L[3]
+-        tid = base64.decodestring(r["id"] + "\n")
++        tid = base64.decodestring(r["id"] + b"\n")
+         pos1 = self.storage._txn_find(tid, 0)
+ 
+         r = L[8]
+-        tid = base64.decodestring(r["id"] + "\n")
++        tid = base64.decodestring(r["id"] + b"\n")
+         pos2 = self.storage._txn_find(tid, 0)
+ 
+         self.storage.close()
+@@ -185,7 +185,7 @@
+         # Find a transaction near the end.
+         L = self.storage.undoLog()
+         r = L[1]
+-        tid = base64.decodestring(r["id"] + "\n")
++        tid = base64.decodestring(r["id"] + b"\n")
+         pos = self.storage._txn_find(tid, 0)
+ 
+         # Overwrite its status with 'c'.
+--- a/src/ZODB/tests/testTimeStamp.py
++++ /dev/null
+@@ -1,144 +0,0 @@
+-##############################################################################
+-#
+-# Copyright (c) 2001, 2002 Zope Foundation and Contributors.
+-# All Rights Reserved.
+-#
+-# This software is subject to the provisions of the Zope Public License,
+-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+-# FOR A PARTICULAR PURPOSE.
+-#
+-##############################################################################
+-"""Test the TimeStamp utility type"""
+-
+-import time
+-import unittest
+-
+-from persistent.TimeStamp import TimeStamp
+-
+-EPSILON = 0.000001
+-
+-class TimeStampTests(unittest.TestCase):
+-
+-    def checkYMDTimeStamp(self):
+-        self._check_ymd(2001, 6, 3)
+-
+-    def _check_ymd(self, yr, mo, dy):
+-        ts = TimeStamp(yr, mo, dy)
+-        self.assertEqual(ts.year(), yr)
+-        self.assertEqual(ts.month(), mo)
+-        self.assertEqual(ts.day(), dy)
+-
+-        self.assertEquals(ts.hour(), 0)
+-        self.assertEquals(ts.minute(), 0)
+-        self.assertEquals(ts.second(), 0)
+-
+-        t = time.gmtime(ts.timeTime())
+-        self.assertEquals(yr, t[0])
+-        self.assertEquals(mo, t[1])
+-        self.assertEquals(dy, t[2])
+-
+-    def checkFullTimeStamp(self):
+-        native_ts = int(time.time()) # fractional seconds get in the way
+-        t = time.gmtime(native_ts)   # the corresponding GMT struct tm
+-        ts = TimeStamp(*t[:6])
+-
+-        # Seconds are stored internally via (conceptually) multiplying by
+-        # 2**32 then dividing by 60, ending up with a 32-bit integer.
+-        # While this gives a lot of room for cramming many distinct
+-        # TimeStamps into a second, it's not good at roundtrip accuracy.
+-        # For example, 1 second is stored as int(2**32/60) == 71582788.
+-        # Converting back gives 71582788*60.0/2**32 == 0.9999999962747097.
+-        # In general, we can lose up to 0.999... to truncation during
+-        # storing, creating an absolute error up to about 1*60.0/2**32 ==
+-        # 0.000000014 on the seconds value we get back.  This is so even
+-        # when we have an exact integral second value going in (as we
+-        # do in this test), so we can't expect equality in any comparison
+-        # involving seconds.  Minutes (etc) are stored exactly, so we
+-        # can expect equality for those.
+-
+-        self.assert_(abs(ts.timeTime() - native_ts) < EPSILON)
+-        self.assertEqual(ts.year(), t[0])
+-        self.assertEqual(ts.month(), t[1])
+-        self.assertEqual(ts.day(), t[2])
+-        self.assertEquals(ts.hour(), t[3])
+-        self.assertEquals(ts.minute(), t[4])
+-        self.assert_(abs(ts.second() - t[5]) < EPSILON)
+-
+-    def checkRawTimestamp(self):
+-        t = time.gmtime()
+-        ts1 = TimeStamp(*t[:6])
+-        ts2 = TimeStamp(`ts1`)
+-
+-        self.assertEquals(ts1, ts2)
+-        self.assertEquals(ts1.timeTime(), ts2.timeTime())
+-        self.assertEqual(ts1.year(), ts2.year())
+-        self.assertEqual(ts1.month(), ts2.month())
+-        self.assertEqual(ts1.day(), ts2.day())
+-        self.assertEquals(ts1.hour(), ts2.hour())
+-        self.assertEquals(ts1.minute(), ts2.minute())
+-        self.assert_(abs(ts1.second() - ts2.second()) < EPSILON)
+-
+-    def checkDictKey(self):
+-        t = time.gmtime()
+-        ts1 = TimeStamp(*t[:6])
+-        ts2 = TimeStamp(2000, *t[1:6])
+-
+-        d = {}
+-        d[ts1] = 1
+-        d[ts2] = 2
+-
+-        self.assertEquals(len(d), 2)
+-
+-    def checkCompare(self):
+-        ts1 = TimeStamp(1972, 6, 27)
+-        ts2 = TimeStamp(1971, 12, 12)
+-        self.assert_(ts1 > ts2)
+-        self.assert_(ts2 <= ts1)
+-
+-    def checkLaterThan(self):
+-        t = time.gmtime()
+-        ts = TimeStamp(*t[:6])
+-        ts2 = ts.laterThan(ts)
+-        self.assert_(ts2 > ts)
+-
+-    # TODO:  should test for bogus inputs to TimeStamp constructor
+-
+-    def checkTimeStamp(self):
+-        # Alternate test suite
+-        t = TimeStamp(2002, 1, 23, 10, 48, 5) # GMT
+-        self.assertEquals(str(t), '2002-01-23 10:48:05.000000')
+-        self.assertEquals(repr(t), '\x03B9H\x15UUU')
+-        self.assertEquals(TimeStamp('\x03B9H\x15UUU'), t)
+-        self.assertEquals(t.year(), 2002)
+-        self.assertEquals(t.month(), 1)
+-        self.assertEquals(t.day(), 23)
+-        self.assertEquals(t.hour(), 10)
+-        self.assertEquals(t.minute(), 48)
+-        self.assertEquals(round(t.second()), 5)
+-        self.assertEquals(t.timeTime(), 1011782885)
+-        t1 = TimeStamp(2002, 1, 23, 10, 48, 10)
+-        self.assertEquals(str(t1), '2002-01-23 10:48:10.000000')
+-        self.assert_(t == t)
+-        self.assert_(t != t1)
+-        self.assert_(t < t1)
+-        self.assert_(t <= t1)
+-        self.assert_(t1 >= t)
+-        self.assert_(t1 > t)
+-        self.failIf(t == t1)
+-        self.failIf(t != t)
+-        self.failIf(t > t1)
+-        self.failIf(t >= t1)
+-        self.failIf(t1 < t)
+-        self.failIf(t1 <= t)
+-        self.assertEquals(cmp(t, t), 0)
+-        self.assertEquals(cmp(t, t1), -1)
+-        self.assertEquals(cmp(t1, t), 1)
+-        self.assertEquals(t1.laterThan(t), t1)
+-        self.assert_(t.laterThan(t1) > t1)
+-        self.assertEquals(TimeStamp(2002,1,23), TimeStamp(2002,1,23,0,0,0))
+-
+-def test_suite():
+-    return unittest.makeSuite(TimeStampTests, 'check')
+--- a/src/ZODB/utils.py
++++ b/src/ZODB/utils.py
+@@ -67,7 +67,7 @@
+     warnings.warn("This will be removed in ZODB 3.8:\n%s" % msg,
+                   DeprecationWarning, stacklevel=3)
+ 
+-z64 = '\0'*8
++z64 = b'\0' * 8
+ 
+ assert sys.hexversion >= 0x02030000
+ 
+@@ -118,7 +118,7 @@
+     ts = TimeStamp(*time.gmtime(t)[:5]+(t%60,))
+     if old is not None:
+         ts = ts.laterThan(TimeStamp(old))
+-    return `ts`
++    return ts.raw()
+ 
+ 
+ def oid_repr(oid):
+@@ -146,7 +146,7 @@
+ 
+ # For example, produce
+ #     '0x03441422948b4399 2002-04-14 20:50:34.815000'
+-# for 8-byte string tid '\x03D\x14"\x94\x8bC\x99'.
++# for 8-byte string tid b'\x03D\x14"\x94\x8bC\x99'.
+ def readable_tid_repr(tid):
+     result = tid_repr(tid)
+     if isinstance(tid, str) and len(tid) == 8:
diff -Nru zodb-3.9.7/debian/patches/fix_unit_tests.patch zodb-3.9.7/debian/patches/fix_unit_tests.patch
--- zodb-3.9.7/debian/patches/fix_unit_tests.patch	1970-01-01 09:00:00.000000000 +0900
+++ zodb-3.9.7/debian/patches/fix_unit_tests.patch	2014-12-12 11:43:20.000000000 +0900
@@ -0,0 +1,152 @@
+commit 416266eff93c896b3a6751168766c9cdab2a4431
+Author: Arnaud Fontaine <ar...@debian.org>
+Date:   Fri Dec 12 11:28:33 2014 +0900
+
+    Fix unit tests failures relared to py3k porting (repr() => bytes) and Python
+    2.7 by backporting the following upstream commits:
+    
+      commit 7fddccf6d7f3b3f7c4117f13adb16e586262fc85
+      Author: Chris McDonough <chr...@plope.com>
+      Date:   Tue Dec 6 08:52:45 2011 +0000
+    
+          repr fix for transaction>=1.2.0
+    
+      commit 987b67d402dba2b29121892cb8ffb668086dca66
+      Author: Jim Fulton <j...@zope.com>
+      Date:   Sat Jul 10 19:10:52 2010 +0000
+    
+          Fixed spurious failure under Python 2.7
+    
+      commit bd415c7a5f2f1835351b8889a3f74393047c6d4f
+      Author: Jim Fulton <j...@zope.com>
+      Date:   Sat Jul 10 19:10:51 2010 +0000
+    
+          Added a number of helpers.
+    
+      commit 1cdf9a75ba3159b519a5dc8017ca0aac9292be49
+      Author: Gediminas Paulauskas <mene...@pov.lt>
+      Date:   Tue Dec 17 17:46:28 2013 +0200
+    
+          Fix a test broken by a change to randrange in Python 2.7.6
+
+--- a/src/ZODB/tests/testConnectionSavepoint.txt
++++ b/src/ZODB/tests/testConnectionSavepoint.txt
+@@ -182,15 +182,15 @@
+     >>> root['bob-balance']
+     100.0
+ 
+-    >>> savepoint2.rollback()
++    >>> savepoint2.rollback() # doctest: +IGNORE_EXCEPTION_DETAIL
+     Traceback (most recent call last):
+     ...
+-    InvalidSavepointRollbackError
++    InvalidSavepointRollbackError: invalidated by a later savepoint
+ 
+-    >>> savepoint1.rollback()
++    >>> savepoint1.rollback() # doctest: +IGNORE_EXCEPTION_DETAIL
+     Traceback (most recent call last):
+     ...
+-    InvalidSavepointRollbackError
++    InvalidSavepointRollbackError: invalidated by a later savepoint
+ 
+     >>> transaction.abort()
+ 
+--- a/src/ZODB/tests/testDB.py
++++ b/src/ZODB/tests/testDB.py
+@@ -242,16 +242,10 @@
+ 
+ def connection_allows_empty_version_for_idiots():
+     r"""
+-    >>> import sys, StringIO
+-    >>> stderr = sys.stderr
+-    >>> sys.stderr = StringIO.StringIO()
+     >>> db = ZODB.DB('t.fs')
+-    >>> c = db.open('')
+-    >>> sys.stderr.getvalue() # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
+-    '...: DeprecationWarning: A version string was passed to
+-    open.\nThe first argument is a transaction manager...
+-
+-    >>> sys.stderr = stderr
++    >>> c = ZODB.tests.util.assert_deprecated(
++    ...       (lambda : db.open('')),
++    ...       'A version string was passed to open')
+     >>> c.root()
+     {}
+     >>> db.close()
+--- a/src/ZODB/tests/testUtils.py
++++ b/src/ZODB/tests/testUtils.py
+@@ -24,9 +24,9 @@
+ 
+ class TestUtils(unittest.TestCase):
+ 
+-    small = [random.randrange(1, 1L<<32, int=long)
++    small = [random.randrange(1, 1L<<32)
+              for i in range(NUM)]
+-    large = [random.randrange(1L<<32, 1L<<64, int=long)
++    large = [random.randrange(1L<<32, 1L<<64)
+              for i in range(NUM)]
+     all = small + large
+ 
+--- a/src/ZODB/tests/util.py
++++ b/src/ZODB/tests/util.py
+@@ -16,6 +16,8 @@
+ $Id: util.py 113733 2010-06-21 15:32:58Z ctheune $
+ """
+ 
++from __future__ import with_statement
++
+ from ZODB.MappingStorage import DB
+ 
+ import atexit
+@@ -24,8 +26,12 @@
+ import time
+ import unittest
+ import persistent
++import sys
++import time
+ import transaction
++import warnings
+ import zope.testing.setupstack
++import ZODB.utils
+ 
+ def setUp(test, name='test'):
+     transaction.abort()
+@@ -99,3 +105,38 @@
+     def testNothing(self):
+         pass
+ 
++def assert_warning(category, func, warning_text=''):
++    if sys.version_info < (2, 6):
++        return func() # Can't use catch_warnings :(
++
++    with warnings.catch_warnings(record=True) as w:
++        warnings.simplefilter('default')
++        result = func()
++        for warning in w:
++            if ((warning.category is category)
++                and (warning_text in str(warning.message))):
++                return result
++        raise AssertionError(w)
++
++def assert_deprecated(func, warning_text=''):
++    return assert_warning(DeprecationWarning, func, warning_text)
++
++def wait(func=None, timeout=30):
++    if func is None:
++        return lambda f: wait(f, timeout)
++    for i in xrange(int(timeout*100)):
++        if func():
++            return
++        time.sleep(.01)
++    raise AssertionError
++
++def store(storage, oid, value='x', serial=ZODB.utils.z64):
++    if not isinstance(oid, str):
++        oid = ZODB.utils.p64(oid)
++    if not isinstance(serial, str):
++        serial = ZODB.utils.p64(serial)
++    t = transaction.get()
++    storage.tpc_begin(t)
++    storage.store(oid, serial, value, '', t)
++    storage.tpc_vote(t)
++    storage.tpc_finish(t)
diff -Nru zodb-3.9.7/debian/patches/series zodb-3.9.7/debian/patches/series
--- zodb-3.9.7/debian/patches/series	2011-10-21 14:24:36.000000000 +0900
+++ zodb-3.9.7/debian/patches/series	2014-12-12 11:41:13.000000000 +0900
@@ -1 +1,3 @@
 lp_135108.patch
+fix_persistent_module_4.x_incompatibilities.patch
+fix_unit_tests.patch
diff -Nru zodb-3.9.7/debian/rules zodb-3.9.7/debian/rules
--- zodb-3.9.7/debian/rules	2011-10-21 14:24:36.000000000 +0900
+++ zodb-3.9.7/debian/rules	2014-12-10 18:49:46.000000000 +0900
@@ -14,3 +14,5 @@
 	done
 	# remove C source files
 	find debian/python-zodb -name '*.c' -delete
+	# remove persistent module provided by python-persistent instead
+	find debian/python-zodb -type d -name 'persistent' -prune -exec rm -rf {} \;
diff -Nru zodb-3.9.7/debian/tests/all zodb-3.9.7/debian/tests/all
--- zodb-3.9.7/debian/tests/all	2011-10-21 14:24:36.000000000 +0900
+++ zodb-3.9.7/debian/tests/all	2014-12-12 11:44:17.000000000 +0900
@@ -6,21 +6,21 @@
 TMPFILE=$(mktemp)
 
 cat > $TMPFILE << EOF
-from zope.testing import testrunner
+from zope import testrunner
 from distutils import sysconfig
 
 test_path = sysconfig.get_python_lib()
 
 exitcode = testrunner.run([
                 '-k',
-                '-m', '(persistent|BTrees|ZEO|ZODB)',
+                '-m', '(BTrees|ZEO|ZODB)',
                 '--test-path', test_path
                 ])
 sys.exit(exitcode)
 EOF
 
 for version in ${PYVERS}; do
-    Running tests for python${version}
+    echo "Running tests for python${version}"
     python${version} ${TMPFILE}
 done
 
diff -Nru zodb-3.9.7/debian/tests/control zodb-3.9.7/debian/tests/control
--- zodb-3.9.7/debian/tests/control	2011-10-21 14:24:36.000000000 +0900
+++ zodb-3.9.7/debian/tests/control	2014-12-12 11:55:44.000000000 +0900
@@ -1,3 +1,3 @@
 Tests: all
 Features: no-build-needed
-Depends: @, python-zope.testing
+Depends: @, python-zope.testing (<< 4.0.0~)

Attachment: signature.asc
Description: PGP signature

Reply via email to