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 @@ ...@@ -17,6 +17,11 @@
- Add support for Python 3.7. - 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) 5.4.0 (2018-03-26)
================== ==================
...@@ -57,10 +62,10 @@ ...@@ -57,10 +62,10 @@
cost of being very slightly less efficient for old-style classes. cost of being very slightly less efficient for old-style classes.
.. note:: On Python 2, this will now allow open ``file`` objects .. note:: On Python 2, this will now allow open ``file`` objects
(but **not** open blobs or sockets) to be pickled (loading (but **not** open blobs or sockets) to be pickled (loading
the object will result in a closed file); previously this the object will result in a closed file); previously this
would result in a ``TypeError``. Doing so is not would result in a ``TypeError``. Doing so is not
recommended as they cannot be loaded in Python 3. recommended as they cannot be loaded in Python 3.
See `issue 179 <https://github.com/zopefoundation/ZODB/pull/179>`_. See `issue 179 <https://github.com/zopefoundation/ZODB/pull/179>`_.
......
...@@ -128,12 +128,34 @@ class TestUtils(unittest.TestCase): ...@@ -128,12 +128,34 @@ class TestUtils(unittest.TestCase):
self.assertEqual(get_pickle_metadata(pickle), self.assertEqual(get_pickle_metadata(pickle),
(__name__, ExampleClass.__name__)) (__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): class ExampleClass(object):
pass pass
def test_suite(): def test_suite():
return unittest.TestSuite(( suite = unittest.defaultTestLoader.loadTestsFromName(__name__)
unittest.makeSuite(TestUtils), suite.addTest(
doctest.DocFileSuite('../utils.txt', checker=checker), doctest.DocFileSuite('../utils.txt', checker=checker)
)) )
return suite
...@@ -18,10 +18,10 @@ import sys ...@@ -18,10 +18,10 @@ import sys
import time import time
import threading import threading
from binascii import hexlify, unhexlify from binascii import hexlify, unhexlify
from struct import pack, unpack
from tempfile import mkstemp from tempfile import mkstemp
from persistent.TimeStamp import TimeStamp from persistent.timestamp import TimeStamp
from ZODB._compat import Unpickler from ZODB._compat import Unpickler
from ZODB._compat import BytesIO from ZODB._compat import BytesIO
...@@ -84,13 +84,24 @@ assert sys.hexversion >= 0x02030000 ...@@ -84,13 +84,24 @@ assert sys.hexversion >= 0x02030000
# The distinction between ints and longs is blurred in Python 2.2, # The distinction between ints and longs is blurred in Python 2.2,
# so u64() are U64() really the same. # 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): def p64(v):
"""Pack an integer or long into a 8-byte string""" """Pack an integer or long into a 8-byte string."""
return pack(">Q", v) try:
return _OID_PACK(v)
except struct.error as e:
raise ValueError(*(e.args + (v,)))
def u64(v): def u64(v):
"""Unpack an 8-byte string into a 64-bit long integer.""" """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 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