Commit 8de39e61 authored by Jason Madden's avatar Jason Madden

Revert "Fix _wraparound on 64-bit windows without using ctypes."

This reverts commit 358cd618.

The _wraparound function is still broken on PyPy3 (both the old version
on Travis and the latest available) if we don't use ctypes.
parent 358cd618
``persistent`` Changelog ``persistent`` Changelog
======================== ========================
4.2.3 (unreleased)
------------------
- Fix the hashcode of Python ``TimeStamp`` objects on 64-bit Python on
Windows. See https://github.com/zopefoundation/persistent/pull/55
4.2.2 (2016-11-29) 4.2.2 (2016-11-29)
------------------ ------------------
......
...@@ -280,13 +280,26 @@ class PyAndCComparisonTests(unittest.TestCase): ...@@ -280,13 +280,26 @@ class PyAndCComparisonTests(unittest.TestCase):
is_32_bit_hash = orig_maxint == MAX_32_BITS 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: try:
MUT._MAXINT = MAX_32_BITS MUT._MAXINT = MAX_32_BITS
MUT.c_long = c_int32
py = self._makePy(*self.now_ts_args) py = self._makePy(*self.now_ts_args)
self.assertEqual(hash(py), bit_32_hash) self.assertEqual(hash(py), bit_32_hash)
MUT._MAXINT = int(2 ** 63 - 1) MUT._MAXINT = int(2 ** 63 - 1)
MUT.c_long = c_int64
# call __hash__ directly to avoid interpreter truncation # call __hash__ directly to avoid interpreter truncation
# in hash() on 32-bit platforms # in hash() on 32-bit platforms
if not self._is_jython: if not self._is_jython:
...@@ -303,6 +316,10 @@ class PyAndCComparisonTests(unittest.TestCase): ...@@ -303,6 +316,10 @@ class PyAndCComparisonTests(unittest.TestCase):
384009219096809580920179179233996861765753210540033) 384009219096809580920179179233996861765753210540033)
finally: finally:
MUT._MAXINT = orig_maxint 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 # These are *usually* aliases, but aren't required
# to be (and aren't under Jython 2.7). # to be (and aren't under Jython 2.7).
...@@ -317,7 +334,7 @@ class PyAndCComparisonTests(unittest.TestCase): ...@@ -317,7 +334,7 @@ class PyAndCComparisonTests(unittest.TestCase):
import persistent.timestamp as MUT import persistent.timestamp as MUT
# We get 32-bit hash values on 32-bit platforms, or on the JVM # 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) # OR on Windows (whether compiled in 64 or 32-bit mode)
is_32_bit = MUT._MAXINT == (2**31 - 1) or self._is_jython is_32_bit = MUT._MAXINT == (2**31 - 1) or self._is_jython or sys.platform == 'win32'
c, py = self._make_C_and_Py(b'\x00\x00\x00\x00\x00\x00\x00\x00') c, py = self._make_C_and_Py(b'\x00\x00\x00\x00\x00\x00\x00\x00')
self.assertEqual(hash(c), 8) self.assertEqual(hash(c), 8)
......
...@@ -19,8 +19,7 @@ import struct ...@@ -19,8 +19,7 @@ import struct
import sys import sys
_RAWTYPE = bytes _RAWTYPE = bytes
# On win32, long is 4 bytes even on a 64-bit platform. _MAXINT = sys.maxsize
_MAXINT = sys.maxsize if not sys.platform == 'win32' else (2 ** 31 - 1)
def _makeOctets(s): def _makeOctets(s):
if sys.version_info < (3,): if sys.version_info < (3,):
...@@ -30,11 +29,22 @@ def _makeOctets(s): ...@@ -30,11 +29,22 @@ def _makeOctets(s):
_ZERO = _makeOctets('\x00' * 8) _ZERO = _makeOctets('\x00' * 8)
def _wraparound(x): try:
# Make sure to overflow and wraparound just # Make sure to overflow and wraparound just
# like the C code does. This is more compactly expressed # like the C code does.
# as ctypes.c_long(x).value from ctypes import c_long
return int(((x + (_MAXINT + 1)) & ((_MAXINT << 1) + 1)) - (_MAXINT + 1)) 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
# It can be fixed by setting _MAXINT = 2 ** 31 - 1 on all
# win32 platforms, but then that breaks PyPy3 64 bit for an unknown
# reason.
def _wraparound(x):
return int(((x + (_MAXINT + 1)) & ((_MAXINT << 1) + 1)) - (_MAXINT + 1))
else:
def _wraparound(x):
return c_long(x).value
class _UTC(datetime.tzinfo): class _UTC(datetime.tzinfo):
def tzname(self): def tzname(self):
......
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