Skip to content

Commit

Permalink
Fix _wraparound on 64-bit windows without using ctypes.
Browse files Browse the repository at this point in the history
  • Loading branch information
jamadden committed Dec 19, 2016
1 parent d4d5967 commit 358cd61
Show file tree
Hide file tree
Showing 3 changed files with 8 additions and 32 deletions.
2 changes: 1 addition & 1 deletion CHANGES.rst
Expand Up @@ -5,7 +5,7 @@
------------------

- Drop use of ``ctypes`` for determining maximum integer size, to increase
pure-Python compatibility.
pure-Python compatibility. See https://github.com/zopefoundation/persistent/pull/31

- Ensure that ``__slots__`` attributes are cleared when a persistent
object is ghostified. (This excluses classes that override
Expand Down
19 changes: 1 addition & 18 deletions persistent/tests/test_timestamp.py
Expand Up @@ -280,26 +280,13 @@ def test_py_hash_32_64_bit(self):

is_32_bit_hash = orig_maxint == MAX_32_BITS

orig_c_long = None
c_int64 = None
c_int32 = None
if hasattr(MUT, 'c_long'):
import ctypes
orig_c_long = MUT.c_long
c_int32 = ctypes.c_int32
c_int64 = ctypes.c_int64
# win32, even on 64-bit long, has funny sizes
is_32_bit_hash = c_int32 == ctypes.c_long

try:
MUT._MAXINT = MAX_32_BITS
MUT.c_long = c_int32

py = self._makePy(*self.now_ts_args)
self.assertEqual(hash(py), bit_32_hash)

MUT._MAXINT = int(2 ** 63 - 1)
MUT.c_long = c_int64
# call __hash__ directly to avoid interpreter truncation
# in hash() on 32-bit platforms
if not self._is_jython:
Expand All @@ -316,10 +303,6 @@ def test_py_hash_32_64_bit(self):
384009219096809580920179179233996861765753210540033)
finally:
MUT._MAXINT = orig_maxint
if orig_c_long is not None:
MUT.c_long = orig_c_long
else:
del MUT.c_long

# These are *usually* aliases, but aren't required
# to be (and aren't under Jython 2.7).
Expand All @@ -334,7 +317,7 @@ def test_hash_equal_constants(self):
import persistent.timestamp as MUT
# We get 32-bit hash values on 32-bit platforms, or on the JVM
# OR on Windows (whether compiled in 64 or 32-bit mode)
is_32_bit = MUT._MAXINT == (2**31 - 1) or self._is_jython or sys.platform == 'win32'
is_32_bit = MUT._MAXINT == (2**31 - 1) or self._is_jython

c, py = self._make_C_and_Py(b'\x00\x00\x00\x00\x00\x00\x00\x00')
self.assertEqual(hash(c), 8)
Expand Down
19 changes: 6 additions & 13 deletions persistent/timestamp.py
Expand Up @@ -19,7 +19,8 @@
import sys

_RAWTYPE = bytes
_MAXINT = sys.maxsize
# On win32, long is 4 bytes even on a 64-bit platform.
_MAXINT = sys.maxsize if not sys.platform == 'win32' else (2 ** 31 - 1)

def _makeOctets(s):
if sys.version_info < (3,):
Expand All @@ -29,19 +30,11 @@ def _makeOctets(s):

_ZERO = _makeOctets('\x00' * 8)

try:
def _wraparound(x):
# Make sure to overflow and wraparound just
# like the C code does.
from ctypes import c_long
except ImportError: # pragma: no cover
# XXX: This is broken on 64-bit windows, where
# sizeof(long) != sizeof(Py_ssize_t)
# sizeof(long) == 4, sizeof(Py_ssize_t) == 8
def _wraparound(x):
return int(((x + (_MAXINT + 1)) & ((_MAXINT << 1) + 1)) - (_MAXINT + 1))
else:
def _wraparound(x):
return c_long(x).value
# like the C code does. This is more compactly expressed
# as ctypes.c_long(x).value
return int(((x + (_MAXINT + 1)) & ((_MAXINT << 1) + 1)) - (_MAXINT + 1))

class _UTC(datetime.tzinfo):
def tzname(self):
Expand Down

0 comments on commit 358cd61

Please sign in to comment.