Commit 1b1025ca authored by Jason Madden's avatar Jason Madden

p64 and p64 are faster and create more informative exceptions.

Fixes #216.
parent 6abde06a
......@@ -17,6 +17,11 @@
- Add support for Python 3.7.
- Make the internal support functions for dealing with OIDs (``p64``
and ``u64``) somewhat faster and raise more informative
exceptions on certain types of bad input. See `issue 216
<https://github.com/zopefoundation/ZODB/issues/216>`_.
5.4.0 (2018-03-26)
==================
......@@ -57,10 +62,10 @@
cost of being very slightly less efficient for old-style classes.
.. note:: On Python 2, this will now allow open ``file`` objects
(but **not** open blobs or sockets) to be pickled (loading
the object will result in a closed file); previously this
would result in a ``TypeError``. Doing so is not
recommended as they cannot be loaded in Python 3.
(but **not** open blobs or sockets) to be pickled (loading
the object will result in a closed file); previously this
would result in a ``TypeError``. Doing so is not
recommended as they cannot be loaded in Python 3.
See `issue 179 <https://github.com/zopefoundation/ZODB/pull/179>`_.
......
......@@ -128,12 +128,34 @@ class TestUtils(unittest.TestCase):
self.assertEqual(get_pickle_metadata(pickle),
(__name__, ExampleClass.__name__))
def test_p64_bad_object(self):
with self.assertRaises(ValueError) as exc:
p64(2 ** 65)
e = exc.exception
# The args will be whatever the struct.error args were,
# which vary from version to version and across implementations,
# followed by the bad value
self.assertEqual(e.args[-1], 2 ** 65)
def test_u64_bad_object(self):
with self.assertRaises(ValueError) as exc:
u64(b'123456789')
e = exc.exception
# The args will be whatever the struct.error args were,
# which vary from version to version and across implementations,
# followed by the bad value
self.assertEqual(e.args[-1], b'123456789')
class ExampleClass(object):
pass
def test_suite():
return unittest.TestSuite((
unittest.makeSuite(TestUtils),
doctest.DocFileSuite('../utils.txt', checker=checker),
))
suite = unittest.defaultTestLoader.loadTestsFromName(__name__)
suite.addTest(
doctest.DocFileSuite('../utils.txt', checker=checker)
)
return suite
......@@ -18,10 +18,10 @@ import sys
import time
import threading
from binascii import hexlify, unhexlify
from struct import pack, unpack
from tempfile import mkstemp
from persistent.TimeStamp import TimeStamp
from persistent.timestamp import TimeStamp
from ZODB._compat import Unpickler
from ZODB._compat import BytesIO
......@@ -84,13 +84,24 @@ assert sys.hexversion >= 0x02030000
# The distinction between ints and longs is blurred in Python 2.2,
# so u64() are U64() really the same.
_OID_STRUCT = struct.Struct('>Q')
_OID_PACK = _OID_STRUCT.pack
_OID_UNPACK = _OID_STRUCT.unpack
def p64(v):
"""Pack an integer or long into a 8-byte string"""
return pack(">Q", v)
"""Pack an integer or long into a 8-byte string."""
try:
return _OID_PACK(v)
except struct.error as e:
raise ValueError(*(e.args + (v,)))
def u64(v):
"""Unpack an 8-byte string into a 64-bit long integer."""
return unpack(">Q", v)[0]
try:
return _OID_UNPACK(v)[0]
except struct.error as e:
raise ValueError(*(e.args + (v,)))
U64 = u64
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment