Skip to content

Commit 0ebf27a

Browse files
committed
function.__code__
1 parent 3d7d16b commit 0ebf27a

File tree

2 files changed

+133
-64
lines changed

2 files changed

+133
-64
lines changed

Objects/clinic/funcobject.c.h

Lines changed: 59 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Objects/funcobject.c

Lines changed: 74 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -636,66 +636,6 @@ static PyMemberDef func_memberlist[] = {
636636
{NULL} /* Sentinel */
637637
};
638638

639-
static PyObject *
640-
func_get_code(PyObject *self, void *Py_UNUSED(ignored))
641-
{
642-
PyFunctionObject *op = _PyFunction_CAST(self);
643-
if (PySys_Audit("object.__getattr__", "Os", op, "__code__") < 0) {
644-
return NULL;
645-
}
646-
647-
return Py_NewRef(op->func_code);
648-
}
649-
650-
static int
651-
func_set_code(PyObject *self, PyObject *value, void *Py_UNUSED(ignored))
652-
{
653-
PyFunctionObject *op = _PyFunction_CAST(self);
654-
655-
/* Not legal to del f.func_code or to set it to anything
656-
* other than a code object. */
657-
if (value == NULL || !PyCode_Check(value)) {
658-
PyErr_SetString(PyExc_TypeError,
659-
"__code__ must be set to a code object");
660-
return -1;
661-
}
662-
663-
if (PySys_Audit("object.__setattr__", "OsO",
664-
op, "__code__", value) < 0) {
665-
return -1;
666-
}
667-
668-
int nfree = ((PyCodeObject *)value)->co_nfreevars;
669-
Py_ssize_t nclosure = (op->func_closure == NULL ? 0 :
670-
PyTuple_GET_SIZE(op->func_closure));
671-
if (nclosure != nfree) {
672-
PyErr_Format(PyExc_ValueError,
673-
"%U() requires a code object with %zd free vars,"
674-
" not %zd",
675-
op->func_name,
676-
nclosure, nfree);
677-
return -1;
678-
}
679-
680-
PyObject *func_code = PyFunction_GET_CODE(op);
681-
int old_flags = ((PyCodeObject *)func_code)->co_flags;
682-
int new_flags = ((PyCodeObject *)value)->co_flags;
683-
int mask = CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR;
684-
if ((old_flags & mask) != (new_flags & mask)) {
685-
if (PyErr_Warn(PyExc_DeprecationWarning,
686-
"Assigning a code object of non-matching type is deprecated "
687-
"(e.g., from a generator to a plain function)") < 0)
688-
{
689-
return -1;
690-
}
691-
}
692-
693-
handle_func_event(PyFunction_EVENT_MODIFY_CODE, op, value);
694-
_PyFunction_ClearVersion(op);
695-
Py_XSETREF(op->func_code, Py_NewRef(value));
696-
return 0;
697-
}
698-
699639
static PyObject *
700640
func_get_name(PyObject *self, void *Py_UNUSED(ignored))
701641
{
@@ -1023,7 +963,7 @@ Dict of annotations in a function object.
1023963

1024964
static PyObject *
1025965
function___annotations___get_impl(PyFunctionObject *self)
1026-
/*[clinic end generated code: output=a4cf4c884c934cbb input=ae1caef917be9bb2]*/
966+
/*[clinic end generated code: output=a4cf4c884c934cbb input=92643d7186c1ad0c]*/
1027967
{
1028968
PyObject *d = NULL;
1029969
if (self->func_annotations == NULL &&
@@ -1061,8 +1001,80 @@ function___annotations___set_impl(PyFunctionObject *self, PyObject *value)
10611001
return 0;
10621002
}
10631003

1004+
/*[clinic input]
1005+
@critical_section
1006+
@getter
1007+
function.__code__
1008+
1009+
Return the code object of a function.
1010+
[clinic start generated code]*/
1011+
1012+
static PyObject *
1013+
function___code___get_impl(PyFunctionObject *self)
1014+
/*[clinic end generated code: output=da514d8da1cae70f input=6a13a98127ff58ed]*/
1015+
{
1016+
if (PySys_Audit("object.__getattr__", "Os", self, "__code__") < 0) {
1017+
return NULL;
1018+
}
1019+
return Py_NewRef(self->func_code);
1020+
}
1021+
1022+
/*[clinic input]
1023+
@critical_section
1024+
@setter
1025+
function.__code__
1026+
[clinic start generated code]*/
1027+
1028+
static int
1029+
function___code___set_impl(PyFunctionObject *self, PyObject *value)
1030+
/*[clinic end generated code: output=3a90ece2bfc881d9 input=19f6eba9ab5d7b28]*/
1031+
{
1032+
/* Not legal to del f.func_code or to set it to anything
1033+
* other than a code object. */
1034+
if (value == NULL || !PyCode_Check(value)) {
1035+
PyErr_SetString(PyExc_TypeError,
1036+
"__code__ must be set to a code object");
1037+
return -1;
1038+
}
1039+
1040+
if (PySys_Audit("object.__setattr__", "OsO",
1041+
self, "__code__", value) < 0) {
1042+
return -1;
1043+
}
1044+
1045+
int nfree = ((PyCodeObject *)value)->co_nfreevars;
1046+
Py_ssize_t nclosure = (self->func_closure == NULL ? 0 :
1047+
PyTuple_GET_SIZE(self->func_closure));
1048+
if (nclosure != nfree) {
1049+
PyErr_Format(PyExc_ValueError,
1050+
"%U() requires a code object with %zd free vars,"
1051+
" not %zd",
1052+
self->func_name,
1053+
nclosure, nfree);
1054+
return -1;
1055+
}
1056+
1057+
PyObject *func_code = PyFunction_GET_CODE(self);
1058+
int old_flags = ((PyCodeObject *)func_code)->co_flags;
1059+
int new_flags = ((PyCodeObject *)value)->co_flags;
1060+
int mask = CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR;
1061+
if ((old_flags & mask) != (new_flags & mask)) {
1062+
if (PyErr_Warn(PyExc_DeprecationWarning,
1063+
"Assigning a code object of non-matching type is deprecated "
1064+
"(e.g., from a generator to a plain function)") < 0)
1065+
{
1066+
return -1;
1067+
}
1068+
}
1069+
1070+
handle_func_event(PyFunction_EVENT_MODIFY_CODE, self, value);
1071+
_PyFunction_ClearVersion(self);
1072+
Py_XSETREF(self->func_code, Py_NewRef(value));
1073+
return 0;
1074+
}
1075+
10641076
static PyGetSetDef func_getsetlist[] = {
1065-
{"__code__", func_get_code, func_set_code},
1077+
FUNCTION___CODE___GETSETDEF
10661078
{"__defaults__", func_get_defaults, func_set_defaults},
10671079
{"__kwdefaults__", func_get_kwdefaults, func_set_kwdefaults},
10681080
FUNCTION___ANNOTATIONS___GETSETDEF

0 commit comments

Comments
 (0)