Skip to content

Commit 6f04325

Browse files
gh-132775: Cleanup Related to crossinterp.c Before Further Changes (gh-132974)
This change consists of adding tests and moving code around, with some renaming thrown in.
1 parent b739ec5 commit 6f04325

10 files changed

+838
-348
lines changed

Include/internal/pycore_crossinterp.h

+33-33
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ struct _xidata {
5757
// likely a registered "xidatafunc", is responsible for
5858
// ensuring it owns the reference (i.e. incref).
5959
PyObject *obj;
60-
// interp is the ID of the owning interpreter of the original
60+
// interpid is the ID of the owning interpreter of the original
6161
// object. It corresponds to the active interpreter when
6262
// _PyObject_GetXIData() was called. This should only
6363
// be set by the cross-interpreter machinery.
@@ -93,37 +93,6 @@ PyAPI_FUNC(void) _PyXIData_Free(_PyXIData_t *data);
9393
// Users should not need getters for "new_object" or "free".
9494

9595

96-
/* getting cross-interpreter data */
97-
98-
typedef int (*xidatafunc)(PyThreadState *tstate, PyObject *, _PyXIData_t *);
99-
100-
PyAPI_FUNC(PyObject *) _PyXIData_GetNotShareableErrorType(PyThreadState *);
101-
PyAPI_FUNC(void) _PyXIData_SetNotShareableError(PyThreadState *, const char *);
102-
PyAPI_FUNC(void) _PyXIData_FormatNotShareableError(
103-
PyThreadState *,
104-
const char *,
105-
...);
106-
107-
PyAPI_FUNC(xidatafunc) _PyXIData_Lookup(
108-
PyThreadState *,
109-
PyObject *);
110-
PyAPI_FUNC(int) _PyObject_CheckXIData(
111-
PyThreadState *,
112-
PyObject *);
113-
114-
PyAPI_FUNC(int) _PyObject_GetXIData(
115-
PyThreadState *,
116-
PyObject *,
117-
_PyXIData_t *);
118-
119-
120-
/* using cross-interpreter data */
121-
122-
PyAPI_FUNC(PyObject *) _PyXIData_NewObject(_PyXIData_t *);
123-
PyAPI_FUNC(int) _PyXIData_Release(_PyXIData_t *);
124-
PyAPI_FUNC(int) _PyXIData_ReleaseAndRawFree(_PyXIData_t *);
125-
126-
12796
/* defining cross-interpreter data */
12897

12998
PyAPI_FUNC(void) _PyXIData_Init(
@@ -134,7 +103,7 @@ PyAPI_FUNC(int) _PyXIData_InitWithSize(
134103
_PyXIData_t *,
135104
PyInterpreterState *interp, const size_t, PyObject *,
136105
xid_newobjfunc);
137-
PyAPI_FUNC(void) _PyXIData_Clear( PyInterpreterState *, _PyXIData_t *);
106+
PyAPI_FUNC(void) _PyXIData_Clear(PyInterpreterState *, _PyXIData_t *);
138107

139108
// Normally the Init* functions are sufficient. The only time
140109
// additional initialization might be needed is to set the "free" func,
@@ -156,6 +125,37 @@ PyAPI_FUNC(void) _PyXIData_Clear( PyInterpreterState *, _PyXIData_t *);
156125
} while (0)
157126

158127

128+
/* getting cross-interpreter data */
129+
130+
typedef int (*xidatafunc)(PyThreadState *tstate, PyObject *, _PyXIData_t *);
131+
132+
PyAPI_FUNC(PyObject *) _PyXIData_GetNotShareableErrorType(PyThreadState *);
133+
PyAPI_FUNC(void) _PyXIData_SetNotShareableError(PyThreadState *, const char *);
134+
PyAPI_FUNC(void) _PyXIData_FormatNotShareableError(
135+
PyThreadState *,
136+
const char *,
137+
...);
138+
139+
PyAPI_FUNC(xidatafunc) _PyXIData_Lookup(
140+
PyThreadState *,
141+
PyObject *);
142+
PyAPI_FUNC(int) _PyObject_CheckXIData(
143+
PyThreadState *,
144+
PyObject *);
145+
146+
PyAPI_FUNC(int) _PyObject_GetXIData(
147+
PyThreadState *,
148+
PyObject *,
149+
_PyXIData_t *);
150+
151+
152+
/* using cross-interpreter data */
153+
154+
PyAPI_FUNC(PyObject *) _PyXIData_NewObject(_PyXIData_t *);
155+
PyAPI_FUNC(int) _PyXIData_Release(_PyXIData_t *);
156+
PyAPI_FUNC(int) _PyXIData_ReleaseAndRawFree(_PyXIData_t *);
157+
158+
159159
/* cross-interpreter data registry */
160160

161161
#define Py_CORE_CROSSINTERP_DATA_REGISTRY_H

Lib/test/_crossinterp_definitions.py

+230
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
# This may be loaded as a module, in the current __main__ module,
2+
# or in another __main__ module.
3+
4+
5+
#######################################
6+
# functions
7+
8+
def spam_minimal():
9+
# no arg defaults or kwarg defaults
10+
# no annotations
11+
# no local vars
12+
# no free vars
13+
# no globals
14+
# no builtins
15+
# no attr access (names)
16+
# no code
17+
return
18+
19+
20+
def spam_full(a, b, /, c, d:int=1, *args, e, f:object=None, **kwargs) -> tuple:
21+
# arg defaults, kwarg defaults
22+
# annotations
23+
# all kinds of local vars, except cells
24+
# no free vars
25+
# some globals
26+
# some builtins
27+
# some attr access (names)
28+
x = args
29+
y = kwargs
30+
z = (a, b, c, d)
31+
kwargs['e'] = e
32+
kwargs['f'] = f
33+
extras = list((x, y, z, spam, spam.__name__))
34+
return tuple(a, b, c, d, e, f, args, kwargs), extras
35+
36+
37+
def spam(x):
38+
return x, None
39+
40+
41+
def spam_N(x):
42+
def eggs_nested(y):
43+
return None, y
44+
return eggs_nested, x
45+
46+
47+
def spam_C(x):
48+
a = 1
49+
def eggs_closure(y):
50+
return None, y, a, x
51+
return eggs_closure, a, x
52+
53+
54+
def spam_NN(x):
55+
def eggs_nested_N(y):
56+
def ham_nested(z):
57+
return None, z
58+
return ham_nested, y
59+
return eggs_nested_N, x
60+
61+
62+
def spam_NC(x):
63+
a = 1
64+
def eggs_nested_C(y):
65+
def ham_closure(z):
66+
return None, z, y, a, x
67+
return ham_closure, y
68+
return eggs_nested_C, a, x
69+
70+
71+
def spam_CN(x):
72+
a = 1
73+
def eggs_closure_N(y):
74+
def ham_C_nested(z):
75+
return None, z
76+
return ham_C_nested, y, a, x
77+
return eggs_closure_N, a, x
78+
79+
80+
def spam_CC(x):
81+
a = 1
82+
def eggs_closure_C(y):
83+
b = 2
84+
def ham_C_closure(z):
85+
return None, z, b, y, a, x
86+
return ham_C_closure, b, y, a, x
87+
return eggs_closure_N, a, x
88+
89+
90+
eggs_nested, *_ = spam_N(1)
91+
eggs_closure, *_ = spam_C(1)
92+
eggs_nested_N, *_ = spam_NN(1)
93+
eggs_nested_C, *_ = spam_NC(1)
94+
eggs_closure_N, *_ = spam_CN(1)
95+
eggs_closure_C, *_ = spam_CC(1)
96+
97+
ham_nested, *_ = eggs_nested_N(2)
98+
ham_closure, *_ = eggs_nested_C(2)
99+
ham_C_nested, *_ = eggs_closure_N(2)
100+
ham_C_closure, *_ = eggs_closure_C(2)
101+
102+
103+
FUNCTIONS = [
104+
# shallow
105+
spam_minimal,
106+
spam_full,
107+
spam,
108+
# outer func
109+
spam_N,
110+
spam_C,
111+
spam_NN,
112+
spam_NC,
113+
spam_CN,
114+
spam_CC,
115+
# inner func
116+
eggs_nested,
117+
eggs_closure,
118+
eggs_nested_N,
119+
eggs_nested_C,
120+
eggs_closure_N,
121+
eggs_closure_C,
122+
# inner inner func
123+
ham_nested,
124+
ham_closure,
125+
ham_C_nested,
126+
ham_C_closure,
127+
]
128+
129+
130+
#######################################
131+
# function-like
132+
133+
# generators
134+
135+
def gen_spam_1(*args):
136+
for arg in args:
137+
yield arg
138+
139+
140+
def gen_spam_2(*args):
141+
yield from args
142+
143+
144+
async def async_spam():
145+
pass
146+
coro_spam = async_spam()
147+
coro_spam.close()
148+
149+
150+
async def asyncgen_spam(*args):
151+
for arg in args:
152+
yield arg
153+
asynccoro_spam = asyncgen_spam(1, 2, 3)
154+
155+
156+
FUNCTION_LIKE = [
157+
gen_spam_1,
158+
gen_spam_2,
159+
async_spam,
160+
coro_spam, # actually FunctionType?
161+
asyncgen_spam,
162+
asynccoro_spam, # actually FunctionType?
163+
]
164+
165+
166+
#######################################
167+
# classes
168+
169+
class Spam:
170+
# minimal
171+
pass
172+
173+
174+
class SpamOkay:
175+
def okay(self):
176+
return True
177+
178+
179+
class SpamFull:
180+
181+
a: object
182+
b: object
183+
c: object
184+
185+
@staticmethod
186+
def staticmeth(cls):
187+
return True
188+
189+
@classmethod
190+
def classmeth(cls):
191+
return True
192+
193+
def __new__(cls, *args, **kwargs):
194+
return super().__new__(cls)
195+
196+
def __init__(self, a, b, c):
197+
self.a = a
198+
self.b = b
199+
self.c = c
200+
201+
# __repr__
202+
# __str__
203+
# ...
204+
205+
@property
206+
def prop(self):
207+
return True
208+
209+
210+
class SubSpamFull(SpamFull):
211+
...
212+
213+
214+
class SubTuple(tuple):
215+
...
216+
217+
218+
def class_eggs_inner():
219+
class EggsNested:
220+
...
221+
return EggsNested
222+
EggsNested = class_eggs_inner()
223+
224+
225+
226+
#######################################
227+
# exceptions
228+
229+
class MimimalError(Exception):
230+
pass

0 commit comments

Comments
 (0)