gh-132775: Add _PyCode_GetXIData() (gh-133475)
This commit is contained in:
parent
e9616110aa
commit
ea598730ef
@ -185,6 +185,13 @@ PyAPI_FUNC(int) _PyMarshal_GetXIData(
|
|||||||
PyObject *,
|
PyObject *,
|
||||||
_PyXIData_t *);
|
_PyXIData_t *);
|
||||||
|
|
||||||
|
// _PyObject_GetXIData() for code objects
|
||||||
|
PyAPI_FUNC(PyObject *) _PyCode_FromXIData(_PyXIData_t *);
|
||||||
|
PyAPI_FUNC(int) _PyCode_GetXIData(
|
||||||
|
PyThreadState *,
|
||||||
|
PyObject *,
|
||||||
|
_PyXIData_t *);
|
||||||
|
|
||||||
|
|
||||||
/* using cross-interpreter data */
|
/* using cross-interpreter data */
|
||||||
|
|
||||||
|
@ -29,6 +29,12 @@ def spam_with_globals_and_builtins():
|
|||||||
print(res)
|
print(res)
|
||||||
|
|
||||||
|
|
||||||
|
def spam_args_attrs_and_builtins(a, b, /, c, d, *args, e, f, **kwargs):
|
||||||
|
if args.__len__() > 2:
|
||||||
|
return None
|
||||||
|
return a, b, c, d, e, f, args, kwargs
|
||||||
|
|
||||||
|
|
||||||
def spam_returns_arg(x):
|
def spam_returns_arg(x):
|
||||||
return x
|
return x
|
||||||
|
|
||||||
@ -46,6 +52,10 @@ def spam_with_inner_closure():
|
|||||||
eggs()
|
eggs()
|
||||||
|
|
||||||
|
|
||||||
|
def spam_annotated(a: int, b: str, c: object) -> tuple:
|
||||||
|
return a, b, c
|
||||||
|
|
||||||
|
|
||||||
def spam_full(a, b, /, c, d:int=1, *args, e, f:object=None, **kwargs) -> tuple:
|
def spam_full(a, b, /, c, d:int=1, *args, e, f:object=None, **kwargs) -> tuple:
|
||||||
# arg defaults, kwarg defaults
|
# arg defaults, kwarg defaults
|
||||||
# annotations
|
# annotations
|
||||||
@ -134,9 +144,11 @@ TOP_FUNCTIONS = [
|
|||||||
spam_minimal,
|
spam_minimal,
|
||||||
spam_with_builtins,
|
spam_with_builtins,
|
||||||
spam_with_globals_and_builtins,
|
spam_with_globals_and_builtins,
|
||||||
|
spam_args_attrs_and_builtins,
|
||||||
spam_returns_arg,
|
spam_returns_arg,
|
||||||
spam_with_inner_not_closure,
|
spam_with_inner_not_closure,
|
||||||
spam_with_inner_closure,
|
spam_with_inner_closure,
|
||||||
|
spam_annotated,
|
||||||
spam_full,
|
spam_full,
|
||||||
spam,
|
spam,
|
||||||
# outer func
|
# outer func
|
||||||
@ -170,7 +182,9 @@ STATELESS_FUNCTIONS = [
|
|||||||
spam,
|
spam,
|
||||||
spam_minimal,
|
spam_minimal,
|
||||||
spam_with_builtins,
|
spam_with_builtins,
|
||||||
|
spam_args_attrs_and_builtins,
|
||||||
spam_returns_arg,
|
spam_returns_arg,
|
||||||
|
spam_annotated,
|
||||||
spam_with_inner_not_closure,
|
spam_with_inner_not_closure,
|
||||||
spam_with_inner_closure,
|
spam_with_inner_closure,
|
||||||
spam_N,
|
spam_N,
|
||||||
|
@ -687,6 +687,16 @@ class CodeTest(unittest.TestCase):
|
|||||||
'checks': CO_FAST_LOCAL,
|
'checks': CO_FAST_LOCAL,
|
||||||
'res': CO_FAST_LOCAL,
|
'res': CO_FAST_LOCAL,
|
||||||
},
|
},
|
||||||
|
defs.spam_args_attrs_and_builtins: {
|
||||||
|
'a': POSONLY,
|
||||||
|
'b': POSONLY,
|
||||||
|
'c': POSORKW,
|
||||||
|
'd': POSORKW,
|
||||||
|
'e': KWONLY,
|
||||||
|
'f': KWONLY,
|
||||||
|
'args': VARARGS,
|
||||||
|
'kwargs': VARKWARGS,
|
||||||
|
},
|
||||||
defs.spam_returns_arg: {
|
defs.spam_returns_arg: {
|
||||||
'x': POSORKW,
|
'x': POSORKW,
|
||||||
},
|
},
|
||||||
@ -697,6 +707,11 @@ class CodeTest(unittest.TestCase):
|
|||||||
'x': CO_FAST_CELL,
|
'x': CO_FAST_CELL,
|
||||||
'eggs': CO_FAST_LOCAL,
|
'eggs': CO_FAST_LOCAL,
|
||||||
},
|
},
|
||||||
|
defs.spam_annotated: {
|
||||||
|
'a': POSORKW,
|
||||||
|
'b': POSORKW,
|
||||||
|
'c': POSORKW,
|
||||||
|
},
|
||||||
defs.spam_full: {
|
defs.spam_full: {
|
||||||
'a': POSONLY,
|
'a': POSONLY,
|
||||||
'b': POSONLY,
|
'b': POSONLY,
|
||||||
@ -892,6 +907,14 @@ class CodeTest(unittest.TestCase):
|
|||||||
purelocals=5,
|
purelocals=5,
|
||||||
globalvars=6,
|
globalvars=6,
|
||||||
),
|
),
|
||||||
|
defs.spam_args_attrs_and_builtins: new_var_counts(
|
||||||
|
posonly=2,
|
||||||
|
posorkw=2,
|
||||||
|
kwonly=2,
|
||||||
|
varargs=1,
|
||||||
|
varkwargs=1,
|
||||||
|
attrs=1,
|
||||||
|
),
|
||||||
defs.spam_returns_arg: new_var_counts(
|
defs.spam_returns_arg: new_var_counts(
|
||||||
posorkw=1,
|
posorkw=1,
|
||||||
),
|
),
|
||||||
@ -902,6 +925,9 @@ class CodeTest(unittest.TestCase):
|
|||||||
othercells=1,
|
othercells=1,
|
||||||
purelocals=1,
|
purelocals=1,
|
||||||
),
|
),
|
||||||
|
defs.spam_annotated: new_var_counts(
|
||||||
|
posorkw=3,
|
||||||
|
),
|
||||||
defs.spam_full: new_var_counts(
|
defs.spam_full: new_var_counts(
|
||||||
posonly=2,
|
posonly=2,
|
||||||
posorkw=2,
|
posorkw=2,
|
||||||
|
@ -725,6 +725,39 @@ class MarshalTests(_GetXIDataTests):
|
|||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
|
class CodeTests(_GetXIDataTests):
|
||||||
|
|
||||||
|
MODE = 'code'
|
||||||
|
|
||||||
|
def test_function_code(self):
|
||||||
|
self.assert_roundtrip_equal_not_identical([
|
||||||
|
*(f.__code__ for f in defs.FUNCTIONS),
|
||||||
|
*(f.__code__ for f in defs.FUNCTION_LIKE),
|
||||||
|
])
|
||||||
|
|
||||||
|
def test_functions(self):
|
||||||
|
self.assert_not_shareable([
|
||||||
|
*defs.FUNCTIONS,
|
||||||
|
*defs.FUNCTION_LIKE,
|
||||||
|
])
|
||||||
|
|
||||||
|
def test_other_objects(self):
|
||||||
|
self.assert_not_shareable([
|
||||||
|
None,
|
||||||
|
True,
|
||||||
|
False,
|
||||||
|
Ellipsis,
|
||||||
|
NotImplemented,
|
||||||
|
9999,
|
||||||
|
'spam',
|
||||||
|
b'spam',
|
||||||
|
(),
|
||||||
|
[],
|
||||||
|
{},
|
||||||
|
object(),
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
class ShareableTypeTests(_GetXIDataTests):
|
class ShareableTypeTests(_GetXIDataTests):
|
||||||
|
|
||||||
MODE = 'xidata'
|
MODE = 'xidata'
|
||||||
@ -817,6 +850,13 @@ class ShareableTypeTests(_GetXIDataTests):
|
|||||||
object(),
|
object(),
|
||||||
])
|
])
|
||||||
|
|
||||||
|
def test_code(self):
|
||||||
|
# types.CodeType
|
||||||
|
self.assert_not_shareable([
|
||||||
|
*(f.__code__ for f in defs.FUNCTIONS),
|
||||||
|
*(f.__code__ for f in defs.FUNCTION_LIKE),
|
||||||
|
])
|
||||||
|
|
||||||
def test_function_object(self):
|
def test_function_object(self):
|
||||||
for func in defs.FUNCTIONS:
|
for func in defs.FUNCTIONS:
|
||||||
assert type(func) is types.FunctionType, func
|
assert type(func) is types.FunctionType, func
|
||||||
@ -935,12 +975,6 @@ class ShareableTypeTests(_GetXIDataTests):
|
|||||||
self.assert_not_shareable([
|
self.assert_not_shareable([
|
||||||
types.MappingProxyType({}),
|
types.MappingProxyType({}),
|
||||||
types.SimpleNamespace(),
|
types.SimpleNamespace(),
|
||||||
# types.CodeType
|
|
||||||
defs.spam_minimal.__code__,
|
|
||||||
defs.spam_full.__code__,
|
|
||||||
defs.spam_CC.__code__,
|
|
||||||
defs.eggs_closure_C.__code__,
|
|
||||||
defs.ham_C_closure.__code__,
|
|
||||||
# types.CellType
|
# types.CellType
|
||||||
types.CellType(),
|
types.CellType(),
|
||||||
# types.FrameType
|
# types.FrameType
|
||||||
|
@ -1984,6 +1984,11 @@ get_crossinterp_data(PyObject *self, PyObject *args, PyObject *kwargs)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (strcmp(mode, "code") == 0) {
|
||||||
|
if (_PyCode_GetXIData(tstate, obj, xidata) != 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
PyErr_Format(PyExc_ValueError, "unsupported mode %R", modeobj);
|
PyErr_Format(PyExc_ValueError, "unsupported mode %R", modeobj);
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -654,6 +654,30 @@ error:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// code
|
||||||
|
|
||||||
|
PyObject *
|
||||||
|
_PyCode_FromXIData(_PyXIData_t *xidata)
|
||||||
|
{
|
||||||
|
return _PyMarshal_ReadObjectFromXIData(xidata);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_PyCode_GetXIData(PyThreadState *tstate, PyObject *obj, _PyXIData_t *xidata)
|
||||||
|
{
|
||||||
|
if (!PyCode_Check(obj)) {
|
||||||
|
_PyXIData_FormatNotShareableError(tstate, "expected code, got %R", obj);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (_PyMarshal_GetXIData(tstate, obj, xidata) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
assert(_PyXIData_CHECK_NEW_OBJECT(xidata, _PyMarshal_ReadObjectFromXIData));
|
||||||
|
_PyXIData_SET_NEW_OBJECT(xidata, _PyCode_FromXIData);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// registration
|
// registration
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
Loading…
x
Reference in New Issue
Block a user