mirror of
https://github.com/python/cpython.git
synced 2025-08-04 08:59:19 +00:00
bpo-22005: Fixed unpickling instances of datetime classes pickled by Python 2. (GH-11017)
encoding='latin1' should be used for successful decoding.
This commit is contained in:
parent
4c49da0cb7
commit
8452ca15f4
5 changed files with 333 additions and 95 deletions
|
@ -38,6 +38,7 @@ import _testcapi
|
|||
import _strptime
|
||||
#
|
||||
|
||||
pickle_loads = {pickle.loads, pickle._loads}
|
||||
|
||||
pickle_choices = [(pickle, pickle, proto)
|
||||
for proto in range(pickle.HIGHEST_PROTOCOL + 1)]
|
||||
|
@ -1434,6 +1435,19 @@ class TestDate(HarmlessMixedComparison, unittest.TestCase):
|
|||
self.assertEqual(orig, derived)
|
||||
self.assertEqual(orig.__reduce__(), orig.__reduce_ex__(2))
|
||||
|
||||
def test_compat_unpickle(self):
|
||||
tests = [
|
||||
b"cdatetime\ndate\n(S'\\x07\\xdf\\x0b\\x1b'\ntR.",
|
||||
b'cdatetime\ndate\n(U\x04\x07\xdf\x0b\x1btR.',
|
||||
b'\x80\x02cdatetime\ndate\nU\x04\x07\xdf\x0b\x1b\x85R.',
|
||||
]
|
||||
args = 2015, 11, 27
|
||||
expected = self.theclass(*args)
|
||||
for data in tests:
|
||||
for loads in pickle_loads:
|
||||
derived = loads(data, encoding='latin1')
|
||||
self.assertEqual(derived, expected)
|
||||
|
||||
def test_compare(self):
|
||||
t1 = self.theclass(2, 3, 4)
|
||||
t2 = self.theclass(2, 3, 4)
|
||||
|
@ -2098,6 +2112,24 @@ class TestDateTime(TestDate):
|
|||
derived = unpickler.loads(green)
|
||||
self.assertEqual(orig, derived)
|
||||
|
||||
def test_compat_unpickle(self):
|
||||
tests = [
|
||||
b'cdatetime\ndatetime\n('
|
||||
b"S'\\x07\\xdf\\x0b\\x1b\\x14;\\x01\\x00\\x10\\x00'\ntR.",
|
||||
|
||||
b'cdatetime\ndatetime\n('
|
||||
b'U\n\x07\xdf\x0b\x1b\x14;\x01\x00\x10\x00tR.',
|
||||
|
||||
b'\x80\x02cdatetime\ndatetime\n'
|
||||
b'U\n\x07\xdf\x0b\x1b\x14;\x01\x00\x10\x00\x85R.',
|
||||
]
|
||||
args = 2015, 11, 27, 20, 59, 1, 64**2
|
||||
expected = self.theclass(*args)
|
||||
for data in tests:
|
||||
for loads in pickle_loads:
|
||||
derived = loads(data, encoding='latin1')
|
||||
self.assertEqual(derived, expected)
|
||||
|
||||
def test_more_compare(self):
|
||||
# The test_compare() inherited from TestDate covers the error cases.
|
||||
# We just want to test lexicographic ordering on the members datetime
|
||||
|
@ -3069,6 +3101,19 @@ class TestTime(HarmlessMixedComparison, unittest.TestCase):
|
|||
derived = unpickler.loads(green)
|
||||
self.assertEqual(orig, derived)
|
||||
|
||||
def test_compat_unpickle(self):
|
||||
tests = [
|
||||
b"cdatetime\ntime\n(S'\\x14;\\x10\\x00\\x10\\x00'\ntR.",
|
||||
b'cdatetime\ntime\n(U\x06\x14;\x10\x00\x10\x00tR.',
|
||||
b'\x80\x02cdatetime\ntime\nU\x06\x14;\x10\x00\x10\x00\x85R.',
|
||||
]
|
||||
args = 20, 59, 16, 64**2
|
||||
expected = self.theclass(*args)
|
||||
for data in tests:
|
||||
for loads in pickle_loads:
|
||||
derived = loads(data, encoding='latin1')
|
||||
self.assertEqual(derived, expected)
|
||||
|
||||
def test_bool(self):
|
||||
# time is always True.
|
||||
cls = self.theclass
|
||||
|
@ -3441,6 +3486,40 @@ class TestTimeTZ(TestTime, TZInfoBase, unittest.TestCase):
|
|||
self.assertEqual(derived.tzname(), 'cookie')
|
||||
self.assertEqual(orig.__reduce__(), orig.__reduce_ex__(2))
|
||||
|
||||
def test_compat_unpickle(self):
|
||||
tests = [
|
||||
b"cdatetime\ntime\n(S'\\x05\\x06\\x07\\x01\\xe2@'\n"
|
||||
b"ctest.datetimetester\nPicklableFixedOffset\n(tR"
|
||||
b"(dS'_FixedOffset__offset'\ncdatetime\ntimedelta\n"
|
||||
b"(I-1\nI68400\nI0\ntRs"
|
||||
b"S'_FixedOffset__dstoffset'\nNs"
|
||||
b"S'_FixedOffset__name'\nS'cookie'\nsbtR.",
|
||||
|
||||
b'cdatetime\ntime\n(U\x06\x05\x06\x07\x01\xe2@'
|
||||
b'ctest.datetimetester\nPicklableFixedOffset\n)R'
|
||||
b'}(U\x14_FixedOffset__offsetcdatetime\ntimedelta\n'
|
||||
b'(J\xff\xff\xff\xffJ0\x0b\x01\x00K\x00tR'
|
||||
b'U\x17_FixedOffset__dstoffsetN'
|
||||
b'U\x12_FixedOffset__nameU\x06cookieubtR.',
|
||||
|
||||
b'\x80\x02cdatetime\ntime\nU\x06\x05\x06\x07\x01\xe2@'
|
||||
b'ctest.datetimetester\nPicklableFixedOffset\n)R'
|
||||
b'}(U\x14_FixedOffset__offsetcdatetime\ntimedelta\n'
|
||||
b'J\xff\xff\xff\xffJ0\x0b\x01\x00K\x00\x87R'
|
||||
b'U\x17_FixedOffset__dstoffsetN'
|
||||
b'U\x12_FixedOffset__nameU\x06cookieub\x86R.',
|
||||
]
|
||||
|
||||
tinfo = PicklableFixedOffset(-300, 'cookie')
|
||||
expected = self.theclass(5, 6, 7, 123456, tzinfo=tinfo)
|
||||
for data in tests:
|
||||
for loads in pickle_loads:
|
||||
derived = loads(data, encoding='latin1')
|
||||
self.assertEqual(derived, expected, repr(data))
|
||||
self.assertIsInstance(derived.tzinfo, PicklableFixedOffset)
|
||||
self.assertEqual(derived.utcoffset(), timedelta(minutes=-300))
|
||||
self.assertEqual(derived.tzname(), 'cookie')
|
||||
|
||||
def test_more_bool(self):
|
||||
# time is always True.
|
||||
cls = self.theclass
|
||||
|
@ -3789,6 +3868,43 @@ class TestDateTimeTZ(TestDateTime, TZInfoBase, unittest.TestCase):
|
|||
self.assertEqual(derived.tzname(), 'cookie')
|
||||
self.assertEqual(orig.__reduce__(), orig.__reduce_ex__(2))
|
||||
|
||||
def test_compat_unpickle(self):
|
||||
tests = [
|
||||
b'cdatetime\ndatetime\n'
|
||||
b"(S'\\x07\\xdf\\x0b\\x1b\\x14;\\x01\\x01\\xe2@'\n"
|
||||
b'ctest.datetimetester\nPicklableFixedOffset\n(tR'
|
||||
b"(dS'_FixedOffset__offset'\ncdatetime\ntimedelta\n"
|
||||
b'(I-1\nI68400\nI0\ntRs'
|
||||
b"S'_FixedOffset__dstoffset'\nNs"
|
||||
b"S'_FixedOffset__name'\nS'cookie'\nsbtR.",
|
||||
|
||||
b'cdatetime\ndatetime\n'
|
||||
b'(U\n\x07\xdf\x0b\x1b\x14;\x01\x01\xe2@'
|
||||
b'ctest.datetimetester\nPicklableFixedOffset\n)R'
|
||||
b'}(U\x14_FixedOffset__offsetcdatetime\ntimedelta\n'
|
||||
b'(J\xff\xff\xff\xffJ0\x0b\x01\x00K\x00tR'
|
||||
b'U\x17_FixedOffset__dstoffsetN'
|
||||
b'U\x12_FixedOffset__nameU\x06cookieubtR.',
|
||||
|
||||
b'\x80\x02cdatetime\ndatetime\n'
|
||||
b'U\n\x07\xdf\x0b\x1b\x14;\x01\x01\xe2@'
|
||||
b'ctest.datetimetester\nPicklableFixedOffset\n)R'
|
||||
b'}(U\x14_FixedOffset__offsetcdatetime\ntimedelta\n'
|
||||
b'J\xff\xff\xff\xffJ0\x0b\x01\x00K\x00\x87R'
|
||||
b'U\x17_FixedOffset__dstoffsetN'
|
||||
b'U\x12_FixedOffset__nameU\x06cookieub\x86R.',
|
||||
]
|
||||
args = 2015, 11, 27, 20, 59, 1, 123456
|
||||
tinfo = PicklableFixedOffset(-300, 'cookie')
|
||||
expected = self.theclass(*args, **{'tzinfo': tinfo})
|
||||
for data in tests:
|
||||
for loads in pickle_loads:
|
||||
derived = loads(data, encoding='latin1')
|
||||
self.assertEqual(derived, expected)
|
||||
self.assertIsInstance(derived.tzinfo, PicklableFixedOffset)
|
||||
self.assertEqual(derived.utcoffset(), timedelta(minutes=-300))
|
||||
self.assertEqual(derived.tzname(), 'cookie')
|
||||
|
||||
def test_extreme_hashes(self):
|
||||
# If an attempt is made to hash these via subtracting the offset
|
||||
# then hashing a datetime object, OverflowError results. The
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue