[3.7] bpo-34621: fix uuid.UUID (un)pickling compatbility with older Python versions (<3.7) (GH-9133)
This commit is contained in:
parent
e9119a5de6
commit
d53f1cabe8
|
@ -2,10 +2,13 @@ import unittest.mock
|
|||
from test import support
|
||||
import builtins
|
||||
import contextlib
|
||||
import copy
|
||||
import io
|
||||
import os
|
||||
import pickle
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
py_uuid = support.import_fresh_module('uuid', blocked=['_uuid'])
|
||||
c_uuid = support.import_fresh_module('uuid', fresh=['_uuid'])
|
||||
|
@ -311,6 +314,140 @@ class BaseTestUUID:
|
|||
node2 = self.uuid.getnode()
|
||||
self.assertEqual(node1, node2, '%012x != %012x' % (node1, node2))
|
||||
|
||||
def test_pickle_roundtrip(self):
|
||||
def check(actual, expected):
|
||||
self.assertEqual(actual, expected)
|
||||
self.assertEqual(actual.is_safe, expected.is_safe)
|
||||
|
||||
with support.swap_item(sys.modules, 'uuid', self.uuid):
|
||||
for is_safe in self.uuid.SafeUUID:
|
||||
u = self.uuid.UUID('d82579ce6642a0de7ddf490a7aec7aa5',
|
||||
is_safe=is_safe)
|
||||
check(copy.copy(u), u)
|
||||
check(copy.deepcopy(u), u)
|
||||
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
|
||||
with self.subTest(protocol=proto):
|
||||
check(pickle.loads(pickle.dumps(u, proto)), u)
|
||||
|
||||
def test_unpickle_previous_python_versions(self):
|
||||
def check(actual, expected):
|
||||
self.assertEqual(actual, expected)
|
||||
self.assertEqual(actual.is_safe, expected.is_safe)
|
||||
|
||||
pickled_uuids = [
|
||||
# Python 2.7, protocol 0
|
||||
b'ccopy_reg\n_reconstructor\n(cuuid\nUUID\nc__builtin__\nobject\nN'
|
||||
b'tR(dS\'int\'\nL287307832597519156748809049798316161701L\nsb.',
|
||||
# Python 2.7, protocol 1
|
||||
b'ccopy_reg\n_reconstructor\n(cuuid\nUUID\nc__builtin__\nobject\nN'
|
||||
b'tR}U\x03intL287307832597519156748809049798316161701L\nsb.',
|
||||
# Python 2.7, protocol 2
|
||||
b'\x80\x02cuuid\nUUID\n)\x81}U\x03int\x8a\x11\xa5z\xecz\nI\xdf}'
|
||||
b'\xde\xa0Bf\xcey%\xd8\x00sb.',
|
||||
# Python 3.6, protocol 0
|
||||
b'ccopy_reg\n_reconstructor\n(cuuid\nUUID\nc__builtin__\nobject\nN'
|
||||
b'tR(dVint\nL287307832597519156748809049798316161701L\nsb.',
|
||||
# Python 3.6, protocol 1
|
||||
b'ccopy_reg\n_reconstructor\n(cuuid\nUUID\nc__builtin__\nobject\nN'
|
||||
b'tR}X\x03\x00\x00\x00intL287307832597519156748809049798316161701L'
|
||||
b'\nsb.',
|
||||
# Python 3.6, protocol 2
|
||||
b'\x80\x02cuuid\nUUID\n)\x81}X\x03\x00\x00\x00int\x8a\x11\xa5z\xec'
|
||||
b'z\nI\xdf}\xde\xa0Bf\xcey%\xd8\x00sb.',
|
||||
# Python 3.6, protocol 3
|
||||
b'\x80\x03cuuid\nUUID\n)\x81}X\x03\x00\x00\x00int\x8a\x11\xa5z\xec'
|
||||
b'z\nI\xdf}\xde\xa0Bf\xcey%\xd8\x00sb.',
|
||||
# Python 3.6, protocol 4
|
||||
b'\x80\x04\x95+\x00\x00\x00\x00\x00\x00\x00\x8c\x04uuid\x8c\x04UUI'
|
||||
b'D\x93)\x81}\x8c\x03int\x8a\x11\xa5z\xecz\nI\xdf}\xde\xa0Bf\xcey%'
|
||||
b'\xd8\x00sb.',
|
||||
# Python 3.7, protocol 0
|
||||
b'ccopy_reg\n_reconstructor\n(cuuid\nUUID\nc__builtin__\nobject\nN'
|
||||
b'tR(dVint\nL287307832597519156748809049798316161701L\nsVis_safe\n'
|
||||
b'cuuid\nSafeUUID\n(NtRsb.',
|
||||
# Python 3.7, protocol 1
|
||||
b'ccopy_reg\n_reconstructor\n(cuuid\nUUID\nc__builtin__\nobject\nN'
|
||||
b'tR}(X\x03\x00\x00\x00intL287307832597519156748809049798316161701'
|
||||
b'L\nX\x07\x00\x00\x00is_safecuuid\nSafeUUID\n(NtRub.',
|
||||
# Python 3.7, protocol 2
|
||||
b'\x80\x02cuuid\nUUID\n)\x81}(X\x03\x00\x00\x00int\x8a\x11\xa5z'
|
||||
b'\xecz\nI\xdf}\xde\xa0Bf\xcey%\xd8\x00X\x07\x00\x00\x00is_safecuu'
|
||||
b'id\nSafeUUID\nN\x85Rub.',
|
||||
# Python 3.7, protocol 3
|
||||
b'\x80\x03cuuid\nUUID\n)\x81}(X\x03\x00\x00\x00int\x8a\x11\xa5z'
|
||||
b'\xecz\nI\xdf}\xde\xa0Bf\xcey%\xd8\x00X\x07\x00\x00\x00is_safecuu'
|
||||
b'id\nSafeUUID\nN\x85Rub.',
|
||||
# Python 3.7, protocol 4
|
||||
b'\x80\x04\x95F\x00\x00\x00\x00\x00\x00\x00\x8c\x04uuid\x94\x8c'
|
||||
b'\x04UUID\x93)\x81}(\x8c\x03int\x8a\x11\xa5z\xecz\nI\xdf}\xde\xa0'
|
||||
b'Bf\xcey%\xd8\x00\x8c\x07is_safeh\x00\x8c\x08SafeUUID\x93N\x85Rub'
|
||||
b'.',
|
||||
]
|
||||
pickled_uuids_safe = [
|
||||
# Python 3.7, protocol 0
|
||||
b'ccopy_reg\n_reconstructor\n(cuuid\nUUID\nc__builtin__\nobject\nN'
|
||||
b'tR(dVint\nL287307832597519156748809049798316161701L\nsVis_safe\n'
|
||||
b'cuuid\nSafeUUID\n(I0\ntRsb.',
|
||||
# Python 3.7, protocol 1
|
||||
b'ccopy_reg\n_reconstructor\n(cuuid\nUUID\nc__builtin__\nobject\nN'
|
||||
b'tR}(X\x03\x00\x00\x00intL287307832597519156748809049798316161701'
|
||||
b'L\nX\x07\x00\x00\x00is_safecuuid\nSafeUUID\n(K\x00tRub.',
|
||||
# Python 3.7, protocol 2
|
||||
b'\x80\x02cuuid\nUUID\n)\x81}(X\x03\x00\x00\x00int\x8a\x11\xa5z'
|
||||
b'\xecz\nI\xdf}\xde\xa0Bf\xcey%\xd8\x00X\x07\x00\x00\x00is_safecuu'
|
||||
b'id\nSafeUUID\nK\x00\x85Rub.',
|
||||
# Python 3.7, protocol 3
|
||||
b'\x80\x03cuuid\nUUID\n)\x81}(X\x03\x00\x00\x00int\x8a\x11\xa5z'
|
||||
b'\xecz\nI\xdf}\xde\xa0Bf\xcey%\xd8\x00X\x07\x00\x00\x00is_safecuu'
|
||||
b'id\nSafeUUID\nK\x00\x85Rub.',
|
||||
# Python 3.7, protocol 4
|
||||
b'\x80\x04\x95G\x00\x00\x00\x00\x00\x00\x00\x8c\x04uuid\x94\x8c'
|
||||
b'\x04UUID\x93)\x81}(\x8c\x03int\x8a\x11\xa5z\xecz\nI\xdf}\xde\xa0'
|
||||
b'Bf\xcey%\xd8\x00\x8c\x07is_safeh\x00\x8c\x08SafeUUID\x93K\x00'
|
||||
b'\x85Rub.',
|
||||
]
|
||||
pickled_uuids_unsafe = [
|
||||
# Python 3.7, protocol 0
|
||||
b'ccopy_reg\n_reconstructor\n(cuuid\nUUID\nc__builtin__\nobject\nN'
|
||||
b'tR(dVint\nL287307832597519156748809049798316161701L\nsVis_safe\n'
|
||||
b'cuuid\nSafeUUID\n(I-1\ntRsb.',
|
||||
# Python 3.7, protocol 1
|
||||
b'ccopy_reg\n_reconstructor\n(cuuid\nUUID\nc__builtin__\nobject\nN'
|
||||
b'tR}(X\x03\x00\x00\x00intL287307832597519156748809049798316161701'
|
||||
b'L\nX\x07\x00\x00\x00is_safecuuid\nSafeUUID\n(J\xff\xff\xff\xfftR'
|
||||
b'ub.',
|
||||
# Python 3.7, protocol 2
|
||||
b'\x80\x02cuuid\nUUID\n)\x81}(X\x03\x00\x00\x00int\x8a\x11\xa5z'
|
||||
b'\xecz\nI\xdf}\xde\xa0Bf\xcey%\xd8\x00X\x07\x00\x00\x00is_safecuu'
|
||||
b'id\nSafeUUID\nJ\xff\xff\xff\xff\x85Rub.',
|
||||
# Python 3.7, protocol 3
|
||||
b'\x80\x03cuuid\nUUID\n)\x81}(X\x03\x00\x00\x00int\x8a\x11\xa5z'
|
||||
b'\xecz\nI\xdf}\xde\xa0Bf\xcey%\xd8\x00X\x07\x00\x00\x00is_safecuu'
|
||||
b'id\nSafeUUID\nJ\xff\xff\xff\xff\x85Rub.',
|
||||
# Python 3.7, protocol 4
|
||||
b'\x80\x04\x95J\x00\x00\x00\x00\x00\x00\x00\x8c\x04uuid\x94\x8c'
|
||||
b'\x04UUID\x93)\x81}(\x8c\x03int\x8a\x11\xa5z\xecz\nI\xdf}\xde\xa0'
|
||||
b'Bf\xcey%\xd8\x00\x8c\x07is_safeh\x00\x8c\x08SafeUUID\x93J\xff'
|
||||
b'\xff\xff\xff\x85Rub.',
|
||||
]
|
||||
|
||||
u = self.uuid.UUID('d82579ce6642a0de7ddf490a7aec7aa5')
|
||||
u_safe = self.uuid.UUID('d82579ce6642a0de7ddf490a7aec7aa5',
|
||||
is_safe=self.uuid.SafeUUID.safe)
|
||||
u_unsafe = self.uuid.UUID('d82579ce6642a0de7ddf490a7aec7aa5',
|
||||
is_safe=self.uuid.SafeUUID.unsafe)
|
||||
|
||||
with support.swap_item(sys.modules, 'uuid', self.uuid):
|
||||
for pickled in pickled_uuids:
|
||||
# is_safe was added in 3.7. When unpickling values from older
|
||||
# versions, is_safe will be missing, so it should be set to
|
||||
# SafeUUID.unknown.
|
||||
check(pickle.loads(pickled), u)
|
||||
for pickled in pickled_uuids_safe:
|
||||
check(pickle.loads(pickled), u_safe)
|
||||
for pickled in pickled_uuids_unsafe:
|
||||
check(pickle.loads(pickled), u_unsafe)
|
||||
|
||||
# bpo-32502: UUID1 requires a 48-bit identifier, but hardware identifiers
|
||||
# need not necessarily be 48 bits (e.g., EUI-64).
|
||||
def test_uuid1_eui64(self):
|
||||
|
|
17
Lib/uuid.py
17
Lib/uuid.py
|
@ -204,6 +204,23 @@ class UUID:
|
|||
self.__dict__['int'] = int
|
||||
self.__dict__['is_safe'] = is_safe
|
||||
|
||||
def __getstate__(self):
|
||||
state = self.__dict__
|
||||
if self.is_safe != SafeUUID.unknown:
|
||||
# is_safe is a SafeUUID instance. Return just its value, so that
|
||||
# it can be un-pickled in older Python versions without SafeUUID.
|
||||
state = state.copy()
|
||||
state['is_safe'] = self.is_safe.value
|
||||
return state
|
||||
|
||||
def __setstate__(self, state):
|
||||
self.__dict__.update(state)
|
||||
# is_safe was added in 3.7; it is also omitted when it is "unknown"
|
||||
self.__dict__['is_safe'] = (
|
||||
SafeUUID(state['is_safe'])
|
||||
if 'is_safe' in state else SafeUUID.unknown
|
||||
)
|
||||
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, UUID):
|
||||
return self.int == other.int
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
Fix un/pickling compatbility of uuid.UUID objects with older versions of
|
||||
Python (<3.7).
|
Loading…
Reference in New Issue