zopefoundation / persistent

automatic persistence for Python objects
https://pypi.org/project/persistent/
Other
46 stars 28 forks source link

C and Python TimeStamp objects have different `.raw()` and `repr()` values for same input and are not equal #18

Closed jamadden closed 9 years ago

jamadden commented 9 years ago

This cropped up in testing ZODB (see zopefoundation/ZODB#33), which relies on the particular repr of known TimeStamp objects, but it's not hard to imagine this having implications in many other ways.

Here's a doctest-like example:

First, verify we have access to a C implementation:

>>> import sys
>>> sys.version
'2.7.9 (default, Dec 13 2014, 15:13:49) \n[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.56)]'
>>> import persistent.TimeStamp
>>> persistent.TimeStamp.TimeStamp
<built-in function TimeStamp>

Next, set up a constant time (this exact floating point value and timestamp come from ZODB tests):

>>> import time
>>> now = 1229959248.3
>>> val = (time.gmtime(now)[:5] + (now % 60,))
>>> val
(2008, 12, 22, 15, 20, 48.299999952316284)

Create a C and Python TimeStamp:

>>> C_ts = persistent.TimeStamp.TimeStamp(*val)
>>> Py_ts = persistent.TimeStamp.pyTimeStamp(*val)

Not only do they have different reprs and raw values (different in the last character):

>>> print(repr(C_ts))
'\x03z\xbd\xd8\xce\x14z\xdd'
>>> print(repr(Py_ts))
'\x03z\xbd\xd8\xce\x14z\xde'
>>> C_ts.raw()
'\x03z\xbd\xd8\xce\x14z\xdd'
>>> Py_ts.raw()
'\x03z\xbd\xd8\xce\x14z\xde'

They're not even equal to each other, despite having the same input:

>>> C_ts == Py_ts
False

To me this seems like a bug. I can try to put together a PR, but I'm not familiar with the code so it might take me awhile.

jamadden commented 9 years ago

I've got this now, preparing a PR.