PyObject *,
_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 */
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):
return x
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:
# arg defaults, kwarg defaults
# annotations
spam_minimal,
spam_with_builtins,
spam_with_globals_and_builtins,
+ spam_args_attrs_and_builtins,
spam_returns_arg,
spam_with_inner_not_closure,
spam_with_inner_closure,
+ spam_annotated,
spam_full,
spam,
# outer func
spam,
spam_minimal,
spam_with_builtins,
+ spam_args_attrs_and_builtins,
spam_returns_arg,
+ spam_annotated,
spam_with_inner_not_closure,
spam_with_inner_closure,
spam_N,
'checks': 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: {
'x': POSORKW,
},
'x': CO_FAST_CELL,
'eggs': CO_FAST_LOCAL,
},
+ defs.spam_annotated: {
+ 'a': POSORKW,
+ 'b': POSORKW,
+ 'c': POSORKW,
+ },
defs.spam_full: {
'a': POSONLY,
'b': POSONLY,
purelocals=5,
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(
posorkw=1,
),
othercells=1,
purelocals=1,
),
+ defs.spam_annotated: new_var_counts(
+ posorkw=3,
+ ),
defs.spam_full: new_var_counts(
posonly=2,
posorkw=2,
])
+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):
MODE = 'xidata'
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):
for func in defs.FUNCTIONS:
assert type(func) is types.FunctionType, func
self.assert_not_shareable([
types.MappingProxyType({}),
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.FrameType
goto error;
}
}
+ else if (strcmp(mode, "code") == 0) {
+ if (_PyCode_GetXIData(tstate, obj, xidata) != 0) {
+ goto error;
+ }
+ }
else {
PyErr_Format(PyExc_ValueError, "unsupported mode %R", modeobj);
goto error;
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
static void