Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitbdd23c0

Browse files
gh-132775: Add _PyMarshal_GetXIData() (gh-133108)
Note that the bulk of this change is tests.
1 parent68a7376 commitbdd23c0

File tree

5 files changed

+337
-10
lines changed

5 files changed

+337
-10
lines changed

‎Include/internal/pycore_crossinterp.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,13 @@ PyAPI_FUNC(_PyBytes_data_t *) _PyBytes_GetXIDataWrapped(
171171
xid_newobjfunc,
172172
_PyXIData_t*);
173173

174+
// _PyObject_GetXIData() for marshal
175+
PyAPI_FUNC(PyObject*)_PyMarshal_ReadObjectFromXIData(_PyXIData_t*);
176+
PyAPI_FUNC(int)_PyMarshal_GetXIData(
177+
PyThreadState*,
178+
PyObject*,
179+
_PyXIData_t*);
180+
174181

175182
/* using cross-interpreter data */
176183

‎Lib/test/_crossinterp_definitions.py

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ def ham_C_closure(z):
100100
ham_C_closure,*_=eggs_closure_C(2)
101101

102102

103-
FUNCTIONS= [
103+
TOP_FUNCTIONS= [
104104
# shallow
105105
spam_minimal,
106106
spam_full,
@@ -112,6 +112,8 @@ def ham_C_closure(z):
112112
spam_NC,
113113
spam_CN,
114114
spam_CC,
115+
]
116+
NESTED_FUNCTIONS= [
115117
# inner func
116118
eggs_nested,
117119
eggs_closure,
@@ -125,6 +127,10 @@ def ham_C_closure(z):
125127
ham_C_nested,
126128
ham_C_closure,
127129
]
130+
FUNCTIONS= [
131+
*TOP_FUNCTIONS,
132+
*NESTED_FUNCTIONS,
133+
]
128134

129135

130136
#######################################
@@ -157,8 +163,10 @@ async def asyncgen_spam(*args):
157163
gen_spam_1,
158164
gen_spam_2,
159165
async_spam,
160-
coro_spam,# actually FunctionType?
161166
asyncgen_spam,
167+
]
168+
FUNCTION_LIKE_APPLIED= [
169+
coro_spam,# actually FunctionType?
162170
asynccoro_spam,# actually FunctionType?
163171
]
164172

@@ -202,6 +210,13 @@ def __init__(self, a, b, c):
202210
# __str__
203211
# ...
204212

213+
def__eq__(self,other):
214+
ifnotisinstance(other,SpamFull):
215+
returnNotImplemented
216+
return (self.a==other.aand
217+
self.b==other.band
218+
self.c==other.c)
219+
205220
@property
206221
defprop(self):
207222
returnTrue
@@ -222,9 +237,47 @@ class EggsNested:
222237
EggsNested=class_eggs_inner()
223238

224239

240+
TOP_CLASSES= {
241+
Spam: (),
242+
SpamOkay: (),
243+
SpamFull: (1,2,3),
244+
SubSpamFull: (1,2,3),
245+
SubTuple: ([1,2,3],),
246+
}
247+
CLASSES_WITHOUT_EQUALITY= [
248+
Spam,
249+
SpamOkay,
250+
]
251+
BUILTIN_SUBCLASSES= [
252+
SubTuple,
253+
]
254+
NESTED_CLASSES= {
255+
EggsNested: (),
256+
}
257+
CLASSES= {
258+
**TOP_CLASSES,
259+
**NESTED_CLASSES,
260+
}
261+
225262

226263
#######################################
227264
# exceptions
228265

229266
classMimimalError(Exception):
230267
pass
268+
269+
270+
classRichError(Exception):
271+
def__init__(self,msg,value=None):
272+
super().__init__(msg,value)
273+
self.msg=msg
274+
self.value=value
275+
276+
def__eq__(self,other):
277+
ifnotisinstance(other,RichError):
278+
returnNotImplemented
279+
ifself.msg!=other.msg:
280+
returnFalse
281+
ifself.value!=other.value:
282+
returnFalse
283+
returnTrue

‎Lib/test/test_crossinterp.py

Lines changed: 227 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
ifisinstance(o,type)]
1818
EXCEPTION_TYPES= [clsforclsinBUILTIN_TYPES
1919
ifissubclass(cls,BaseException)]
20+
OTHER_TYPES= [oforn,oinvars(types).items()
21+
if (isinstance(o,type)and
22+
nnotin ('DynamicClassAttribute','_GeneratorWrapper'))]
2023

2124

2225
class_GetXIDataTests(unittest.TestCase):
@@ -40,16 +43,42 @@ def iter_roundtrip_values(self, values, *, mode=None):
4043
got=_testinternalcapi.restore_crossinterp_data(xid)
4144
yieldobj,got
4245

43-
defassert_roundtrip_equal(self,values,*,mode=None):
44-
forobj,gotinself.iter_roundtrip_values(values,mode=mode):
45-
self.assertEqual(got,obj)
46-
self.assertIs(type(got),type(obj))
47-
4846
defassert_roundtrip_identical(self,values,*,mode=None):
4947
forobj,gotinself.iter_roundtrip_values(values,mode=mode):
5048
# XXX What about between interpreters?
5149
self.assertIs(got,obj)
5250

51+
defassert_roundtrip_equal(self,values,*,mode=None,expecttype=None):
52+
forobj,gotinself.iter_roundtrip_values(values,mode=mode):
53+
self.assertEqual(got,obj)
54+
self.assertIs(type(got),
55+
type(obj)ifexpecttypeisNoneelseexpecttype)
56+
57+
# def assert_roundtrip_equal_not_identical(self, values, *,
58+
# mode=None, expecttype=None):
59+
# mode = self._resolve_mode(mode)
60+
# for obj in values:
61+
# cls = type(obj)
62+
# with self.subTest(obj):
63+
# got = self._get_roundtrip(obj, mode)
64+
# self.assertIsNot(got, obj)
65+
# self.assertIs(type(got), type(obj))
66+
# self.assertEqual(got, obj)
67+
# self.assertIs(type(got),
68+
# cls if expecttype is None else expecttype)
69+
#
70+
# def assert_roundtrip_not_equal(self, values, *, mode=None, expecttype=None):
71+
# mode = self._resolve_mode(mode)
72+
# for obj in values:
73+
# cls = type(obj)
74+
# with self.subTest(obj):
75+
# got = self._get_roundtrip(obj, mode)
76+
# self.assertIsNot(got, obj)
77+
# self.assertIs(type(got), type(obj))
78+
# self.assertNotEqual(got, obj)
79+
# self.assertIs(type(got),
80+
# cls if expecttype is None else expecttype)
81+
5382
defassert_not_shareable(self,values,exctype=None,*,mode=None):
5483
mode=self._resolve_mode(mode)
5584
forobjinvalues:
@@ -66,6 +95,197 @@ def _resolve_mode(self, mode):
6695
returnmode
6796

6897

98+
classMarshalTests(_GetXIDataTests):
99+
100+
MODE='marshal'
101+
102+
deftest_simple_builtin_singletons(self):
103+
self.assert_roundtrip_identical([
104+
True,
105+
False,
106+
None,
107+
Ellipsis,
108+
])
109+
self.assert_not_shareable([
110+
NotImplemented,
111+
])
112+
113+
deftest_simple_builtin_objects(self):
114+
self.assert_roundtrip_equal([
115+
# int
116+
*range(-1,258),
117+
sys.maxsize+1,
118+
sys.maxsize,
119+
-sys.maxsize-1,
120+
-sys.maxsize-2,
121+
2**1000,
122+
# complex
123+
1+2j,
124+
# float
125+
0.0,
126+
1.1,
127+
-1.0,
128+
0.12345678,
129+
-0.12345678,
130+
# bytes
131+
*(i.to_bytes(2,'little',signed=True)
132+
foriinrange(-1,258)),
133+
b'hello world',
134+
# str
135+
'hello world',
136+
'你好世界',
137+
'',
138+
])
139+
self.assert_not_shareable([
140+
object(),
141+
types.SimpleNamespace(),
142+
])
143+
144+
deftest_bytearray(self):
145+
# bytearray is special because it unmarshals to bytes, not bytearray.
146+
self.assert_roundtrip_equal([
147+
bytearray(),
148+
bytearray(b'hello world'),
149+
],expecttype=bytes)
150+
151+
deftest_compound_immutable_builtin_objects(self):
152+
self.assert_roundtrip_equal([
153+
# tuple
154+
(),
155+
(1,),
156+
("hello","world"),
157+
(1,True,"hello"),
158+
# frozenset
159+
frozenset([1,2,3]),
160+
])
161+
# nested
162+
self.assert_roundtrip_equal([
163+
# tuple
164+
((1,),),
165+
((1,2), (3,4)),
166+
((1,2), (3,4), (5,6)),
167+
# frozenset
168+
frozenset([frozenset([1]),frozenset([2]),frozenset([3])]),
169+
])
170+
171+
deftest_compound_mutable_builtin_objects(self):
172+
self.assert_roundtrip_equal([
173+
# list
174+
[],
175+
[1,2,3],
176+
# dict
177+
{},
178+
{1:7,2:8,3:9},
179+
# set
180+
set(),
181+
{1,2,3},
182+
])
183+
# nested
184+
self.assert_roundtrip_equal([
185+
[[1], [2], [3]],
186+
{1: {'a':True},2: {'b':False}},
187+
{(1,2,3,)},
188+
])
189+
190+
deftest_compound_builtin_objects_with_bad_items(self):
191+
bogus=object()
192+
self.assert_not_shareable([
193+
(bogus,),
194+
frozenset([bogus]),
195+
[bogus],
196+
{bogus:True},
197+
{True:bogus},
198+
{bogus},
199+
])
200+
201+
deftest_builtin_code(self):
202+
self.assert_roundtrip_equal([
203+
*(f.__code__forfindefs.FUNCTIONS),
204+
*(f.__code__forfindefs.FUNCTION_LIKE),
205+
])
206+
207+
deftest_builtin_type(self):
208+
shareable= [
209+
StopIteration,
210+
]
211+
types= [
212+
*BUILTIN_TYPES,
213+
*OTHER_TYPES,
214+
]
215+
self.assert_not_shareable(clsforclsintypes
216+
ifclsnotinshareable)
217+
self.assert_roundtrip_identical(clsforclsintypes
218+
ifclsinshareable)
219+
220+
deftest_builtin_function(self):
221+
functions= [
222+
len,
223+
sys.is_finalizing,
224+
sys.exit,
225+
_testinternalcapi.get_crossinterp_data,
226+
]
227+
forfuncinfunctions:
228+
asserttype(func)istypes.BuiltinFunctionType,func
229+
230+
self.assert_not_shareable(functions)
231+
232+
deftest_builtin_exception(self):
233+
msg='error!'
234+
try:
235+
raiseException
236+
exceptExceptionasexc:
237+
caught=exc
238+
special= {
239+
BaseExceptionGroup: (msg, [caught]),
240+
ExceptionGroup: (msg, [caught]),
241+
# UnicodeError: (None, msg, None, None, None),
242+
UnicodeEncodeError: ('utf-8','',1,3,msg),
243+
UnicodeDecodeError: ('utf-8',b'',1,3,msg),
244+
UnicodeTranslateError: ('',1,3,msg),
245+
}
246+
exceptions= []
247+
forclsinEXCEPTION_TYPES:
248+
args=special.get(cls)or (msg,)
249+
exceptions.append(cls(*args))
250+
251+
self.assert_not_shareable(exceptions)
252+
# Note that StopIteration (the type) can be marshalled,
253+
# but its instances cannot.
254+
255+
deftest_module(self):
256+
asserttype(sys)istypes.ModuleType,type(sys)
257+
asserttype(defs)istypes.ModuleType,type(defs)
258+
asserttype(unittest)istypes.ModuleType,type(defs)
259+
260+
assert'emptymod'notinsys.modules
261+
withimport_helper.ready_to_import('emptymod',''):
262+
importemptymod
263+
264+
self.assert_not_shareable([
265+
sys,
266+
defs,
267+
unittest,
268+
emptymod,
269+
])
270+
271+
deftest_user_class(self):
272+
self.assert_not_shareable(defs.TOP_CLASSES)
273+
274+
instances= []
275+
forcls,argsindefs.TOP_CLASSES.items():
276+
instances.append(cls(*args))
277+
self.assert_not_shareable(instances)
278+
279+
deftest_user_function(self):
280+
self.assert_not_shareable(defs.TOP_FUNCTIONS)
281+
282+
deftest_user_exception(self):
283+
self.assert_not_shareable([
284+
defs.MimimalError('error!'),
285+
defs.RichError('error!',42),
286+
])
287+
288+
69289
classShareableTypeTests(_GetXIDataTests):
70290

71291
MODE='xidata'
@@ -184,6 +404,7 @@ def test_builtin_function(self):
184404

185405
deftest_function_like(self):
186406
self.assert_not_shareable(defs.FUNCTION_LIKE)
407+
self.assert_not_shareable(defs.FUNCTION_LIKE_APPLIED)
187408

188409
deftest_builtin_wrapper(self):
189410
_wrappers= {
@@ -243,9 +464,7 @@ def test_class(self):
243464
deftest_builtin_type(self):
244465
self.assert_not_shareable([
245466
*BUILTIN_TYPES,
246-
*(oforn,oinvars(types).items()
247-
if (isinstance(o,type)and
248-
nnotin ('DynamicClassAttribute','_GeneratorWrapper'))),
467+
*OTHER_TYPES,
249468
])
250469

251470
deftest_exception(self):

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp