Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork34k
[3.13] gh-75572: Forward-port test_xpickle from Python 2 to 3 (GH-22452)#143509
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Merged
serhiy-storchaka merged 1 commit intopython:3.13fromserhiy-storchaka:backport-8735daf-3.13Jan 7, 2026
Uh oh!
There was an error while loading.Please reload this page.
Merged
Changes fromall commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Jump to file
Failed to load files.
Loading
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
4 changes: 4 additions & 0 deletionsLib/test/libregrtest/cmdline.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletionLib/test/libregrtest/utils.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
353 changes: 353 additions & 0 deletionsLib/test/picklecommon.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,353 @@ | ||
| # Classes used for pickle testing. | ||
| # They are moved to separate file, so they can be loaded | ||
| # in other Python version for test_xpickle. | ||
| import sys | ||
| class C: | ||
| def __eq__(self, other): | ||
| return self.__dict__ == other.__dict__ | ||
| # For test_load_classic_instance | ||
| class D(C): | ||
| def __init__(self, arg): | ||
| pass | ||
| class E(C): | ||
| def __getinitargs__(self): | ||
| return () | ||
| import __main__ | ||
| __main__.C = C | ||
| C.__module__ = "__main__" | ||
| __main__.D = D | ||
| D.__module__ = "__main__" | ||
| __main__.E = E | ||
| E.__module__ = "__main__" | ||
| # Simple mutable object. | ||
| class Object: | ||
| pass | ||
| # Hashable immutable key object containing unheshable mutable data. | ||
| class K: | ||
| def __init__(self, value): | ||
| self.value = value | ||
| def __reduce__(self): | ||
| # Shouldn't support the recursion itself | ||
| return K, (self.value,) | ||
| # For test_misc | ||
| class myint(int): | ||
| def __init__(self, x): | ||
| self.str = str(x) | ||
| # For test_misc and test_getinitargs | ||
| class initarg(C): | ||
| def __init__(self, a, b): | ||
| self.a = a | ||
| self.b = b | ||
| def __getinitargs__(self): | ||
| return self.a, self.b | ||
| # For test_metaclass | ||
| class metaclass(type): | ||
| pass | ||
| if sys.version_info >= (3,): | ||
| # Syntax not compatible with Python 2 | ||
| exec(''' | ||
| class use_metaclass(object, metaclass=metaclass): | ||
| pass | ||
| ''') | ||
| else: | ||
| class use_metaclass(object): | ||
| __metaclass__ = metaclass | ||
| # Test classes for reduce_ex | ||
| class R: | ||
| def __init__(self, reduce=None): | ||
| self.reduce = reduce | ||
| def __reduce__(self, proto): | ||
| return self.reduce | ||
| class REX: | ||
| def __init__(self, reduce_ex=None): | ||
| self.reduce_ex = reduce_ex | ||
| def __reduce_ex__(self, proto): | ||
| return self.reduce_ex | ||
| class REX_one(object): | ||
| """No __reduce_ex__ here, but inheriting it from object""" | ||
| _reduce_called = 0 | ||
| def __reduce__(self): | ||
| self._reduce_called = 1 | ||
| return REX_one, () | ||
| class REX_two(object): | ||
| """No __reduce__ here, but inheriting it from object""" | ||
| _proto = None | ||
| def __reduce_ex__(self, proto): | ||
| self._proto = proto | ||
| return REX_two, () | ||
| class REX_three(object): | ||
| _proto = None | ||
| def __reduce_ex__(self, proto): | ||
| self._proto = proto | ||
| return REX_two, () | ||
| def __reduce__(self): | ||
| raise AssertionError("This __reduce__ shouldn't be called") | ||
| class REX_four(object): | ||
| """Calling base class method should succeed""" | ||
| _proto = None | ||
| def __reduce_ex__(self, proto): | ||
| self._proto = proto | ||
| return object.__reduce_ex__(self, proto) | ||
| class REX_five(object): | ||
| """This one used to fail with infinite recursion""" | ||
| _reduce_called = 0 | ||
| def __reduce__(self): | ||
| self._reduce_called = 1 | ||
| return object.__reduce__(self) | ||
| class REX_six(object): | ||
| """This class is used to check the 4th argument (list iterator) of | ||
| the reduce protocol. | ||
| """ | ||
| def __init__(self, items=None): | ||
| self.items = items if items is not None else [] | ||
| def __eq__(self, other): | ||
| return type(self) is type(other) and self.items == other.items | ||
| def append(self, item): | ||
| self.items.append(item) | ||
| def __reduce__(self): | ||
| return type(self), (), None, iter(self.items), None | ||
| class REX_seven(object): | ||
| """This class is used to check the 5th argument (dict iterator) of | ||
| the reduce protocol. | ||
| """ | ||
| def __init__(self, table=None): | ||
| self.table = table if table is not None else {} | ||
| def __eq__(self, other): | ||
| return type(self) is type(other) and self.table == other.table | ||
| def __setitem__(self, key, value): | ||
| self.table[key] = value | ||
| def __reduce__(self): | ||
| return type(self), (), None, None, iter(self.table.items()) | ||
| class REX_state(object): | ||
| """This class is used to check the 3th argument (state) of | ||
| the reduce protocol. | ||
| """ | ||
| def __init__(self, state=None): | ||
| self.state = state | ||
| def __eq__(self, other): | ||
| return type(self) is type(other) and self.state == other.state | ||
| def __setstate__(self, state): | ||
| self.state = state | ||
| def __reduce__(self): | ||
| return type(self), (), self.state | ||
| # For test_reduce_ex_None | ||
| class REX_None: | ||
| """ Setting __reduce_ex__ to None should fail """ | ||
| __reduce_ex__ = None | ||
| # For test_reduce_None | ||
| class R_None: | ||
| """ Setting __reduce__ to None should fail """ | ||
| __reduce__ = None | ||
| # For test_pickle_setstate_None | ||
| class C_None_setstate: | ||
| """ Setting __setstate__ to None should fail """ | ||
| def __getstate__(self): | ||
| return 1 | ||
| __setstate__ = None | ||
| # Test classes for newobj | ||
| # For test_newobj_generic and test_newobj_proxies | ||
| class MyInt(int): | ||
| sample = 1 | ||
| if sys.version_info >= (3,): | ||
| class MyLong(int): | ||
| sample = 1 | ||
| else: | ||
| class MyLong(long): | ||
| sample = long(1) | ||
| class MyFloat(float): | ||
| sample = 1.0 | ||
| class MyComplex(complex): | ||
| sample = 1.0 + 0.0j | ||
| class MyStr(str): | ||
| sample = "hello" | ||
| if sys.version_info >= (3,): | ||
| class MyUnicode(str): | ||
| sample = "hello \u1234" | ||
| else: | ||
| class MyUnicode(unicode): | ||
| sample = unicode(r"hello \u1234", "raw-unicode-escape") | ||
| class MyTuple(tuple): | ||
| sample = (1, 2, 3) | ||
| class MyList(list): | ||
| sample = [1, 2, 3] | ||
| class MyDict(dict): | ||
| sample = {"a": 1, "b": 2} | ||
| class MySet(set): | ||
| sample = {"a", "b"} | ||
| class MyFrozenSet(frozenset): | ||
| sample = frozenset({"a", "b"}) | ||
| myclasses = [MyInt, MyLong, MyFloat, | ||
| MyComplex, | ||
| MyStr, MyUnicode, | ||
| MyTuple, MyList, MyDict, MySet, MyFrozenSet] | ||
| # For test_newobj_overridden_new | ||
| class MyIntWithNew(int): | ||
| def __new__(cls, value): | ||
| raise AssertionError | ||
| class MyIntWithNew2(MyIntWithNew): | ||
| __new__ = int.__new__ | ||
| # For test_newobj_list_slots | ||
| class SlotList(MyList): | ||
| __slots__ = ["foo"] | ||
| # Ruff "redefined while unused" false positive here due to `global` variables | ||
| # being assigned (and then restored) from within test methods earlier in the file | ||
| class SimpleNewObj(int): # noqa: F811 | ||
| def __init__(self, *args, **kwargs): | ||
| # raise an error, to make sure this isn't called | ||
| raise TypeError("SimpleNewObj.__init__() didn't expect to get called") | ||
| def __eq__(self, other): | ||
| return int(self) == int(other) and self.__dict__ == other.__dict__ | ||
| class ComplexNewObj(SimpleNewObj): | ||
| def __getnewargs__(self): | ||
| return ('%X' % self, 16) | ||
| class ComplexNewObjEx(SimpleNewObj): | ||
| def __getnewargs_ex__(self): | ||
| return ('%X' % self,), {'base': 16} | ||
| class ZeroCopyBytes(bytes): | ||
| readonly = True | ||
| c_contiguous = True | ||
| f_contiguous = True | ||
| zero_copy_reconstruct = True | ||
| def __reduce_ex__(self, protocol): | ||
| if protocol >= 5: | ||
| import pickle | ||
| return type(self)._reconstruct, (pickle.PickleBuffer(self),), None | ||
| else: | ||
| return type(self)._reconstruct, (bytes(self),) | ||
| def __repr__(self): | ||
| return "{}({!r})".format(self.__class__.__name__, bytes(self)) | ||
| __str__ = __repr__ | ||
| @classmethod | ||
| def _reconstruct(cls, obj): | ||
| with memoryview(obj) as m: | ||
| obj = m.obj | ||
| if type(obj) is cls: | ||
| # Zero-copy | ||
| return obj | ||
| else: | ||
| return cls(obj) | ||
| class ZeroCopyBytearray(bytearray): | ||
| readonly = False | ||
| c_contiguous = True | ||
| f_contiguous = True | ||
| zero_copy_reconstruct = True | ||
| def __reduce_ex__(self, protocol): | ||
| if protocol >= 5: | ||
| import pickle | ||
| return type(self)._reconstruct, (pickle.PickleBuffer(self),), None | ||
| else: | ||
| return type(self)._reconstruct, (bytes(self),) | ||
| def __repr__(self): | ||
| return "{}({!r})".format(self.__class__.__name__, bytes(self)) | ||
| __str__ = __repr__ | ||
| @classmethod | ||
| def _reconstruct(cls, obj): | ||
| with memoryview(obj) as m: | ||
| obj = m.obj | ||
| if type(obj) is cls: | ||
| # Zero-copy | ||
| return obj | ||
| else: | ||
| return cls(obj) | ||
| # For test_nested_names | ||
| class Nested: | ||
| class A: | ||
| class B: | ||
| class C: | ||
| pass | ||
| # For test_py_methods | ||
| class PyMethodsTest: | ||
| @staticmethod | ||
| def cheese(): | ||
| return "cheese" | ||
| @classmethod | ||
| def wine(cls): | ||
| assert cls is PyMethodsTest | ||
| return "wine" | ||
| def biscuits(self): | ||
| assert isinstance(self, PyMethodsTest) | ||
| return "biscuits" | ||
| class Nested: | ||
| "Nested class" | ||
| @staticmethod | ||
| def ketchup(): | ||
| return "ketchup" | ||
| @classmethod | ||
| def maple(cls): | ||
| assert cls is PyMethodsTest.Nested | ||
| return "maple" | ||
| def pie(self): | ||
| assert isinstance(self, PyMethodsTest.Nested) | ||
| return "pie" | ||
| # For test_c_methods | ||
| class Subclass(tuple): | ||
| class Nested(str): | ||
| pass |
Oops, something went wrong.
Uh oh!
There was an error while loading.Please reload this page.
Oops, something went wrong.
Uh oh!
There was an error while loading.Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.