From d4be68e361f4258cf0848fc70018dfe37a2acc24 Mon Sep 17 00:00:00 2001 From: shadchin Date: Mon, 18 Apr 2022 12:39:32 +0300 Subject: IGNIETFERRO-1816 Update Python 3 from 3.9.12 to 3.10.4 ref:9f96be6d02ee8044fdd6f124b799b270c20ce641 --- contrib/tools/python3/src/Objects/funcobject.c | 249 ++++++++++++++++++------- 1 file changed, 184 insertions(+), 65 deletions(-) (limited to 'contrib/tools/python3/src/Objects/funcobject.c') diff --git a/contrib/tools/python3/src/Objects/funcobject.c b/contrib/tools/python3/src/Objects/funcobject.c index 2c60275d906..801478ade22 100644 --- a/contrib/tools/python3/src/Objects/funcobject.c +++ b/contrib/tools/python3/src/Objects/funcobject.c @@ -2,77 +2,94 @@ /* Function object implementation */ #include "Python.h" -#include "pycore_object.h" -#include "pycore_tupleobject.h" -#include "code.h" +#include "pycore_ceval.h" // _PyEval_BuiltinsFromGlobals() +#include "pycore_object.h" // _PyObject_GC_UNTRACK() +#include "pycore_pyerrors.h" // _PyErr_Occurred() #include "structmember.h" // PyMemberDef PyObject * PyFunction_NewWithQualName(PyObject *code, PyObject *globals, PyObject *qualname) { - PyFunctionObject *op; - PyObject *doc, *consts, *module; - static PyObject *__name__ = NULL; + assert(globals != NULL); + assert(PyDict_Check(globals)); + Py_INCREF(globals); - if (__name__ == NULL) { - __name__ = PyUnicode_InternFromString("__name__"); - if (__name__ == NULL) - return NULL; + PyThreadState *tstate = _PyThreadState_GET(); + + PyCodeObject *code_obj = (PyCodeObject *)code; + Py_INCREF(code_obj); + + PyObject *name = code_obj->co_name; + assert(name != NULL); + Py_INCREF(name); + if (!qualname) { + qualname = name; } + Py_INCREF(qualname); - /* __module__: If module name is in globals, use it. - Otherwise, use None. */ - module = PyDict_GetItemWithError(globals, __name__); - if (module) { - Py_INCREF(module); + PyObject *consts = code_obj->co_consts; + assert(PyTuple_Check(consts)); + PyObject *doc; + if (PyTuple_Size(consts) >= 1) { + doc = PyTuple_GetItem(consts, 0); + if (!PyUnicode_Check(doc)) { + doc = Py_None; + } } - else if (PyErr_Occurred()) { - return NULL; + else { + doc = Py_None; + } + Py_INCREF(doc); + + // __module__: Use globals['__name__'] if it exists, or NULL. + _Py_IDENTIFIER(__name__); + PyObject *module = _PyDict_GetItemIdWithError(globals, &PyId___name__); + PyObject *builtins = NULL; + if (module == NULL && _PyErr_Occurred(tstate)) { + goto error; + } + Py_XINCREF(module); + + builtins = _PyEval_BuiltinsFromGlobals(tstate, globals); // borrowed ref + if (builtins == NULL) { + goto error; } + Py_INCREF(builtins); - op = PyObject_GC_New(PyFunctionObject, &PyFunction_Type); + PyFunctionObject *op = PyObject_GC_New(PyFunctionObject, &PyFunction_Type); if (op == NULL) { - Py_XDECREF(module); - return NULL; + goto error; } /* Note: No failures from this point on, since func_dealloc() does not expect a partially-created object. */ - op->func_weakreflist = NULL; - Py_INCREF(code); - op->func_code = code; - Py_INCREF(globals); op->func_globals = globals; - op->func_name = ((PyCodeObject *)code)->co_name; - Py_INCREF(op->func_name); - op->func_defaults = NULL; /* No default arguments */ - op->func_kwdefaults = NULL; /* No keyword only defaults */ + op->func_builtins = builtins; + op->func_name = name; + op->func_qualname = qualname; + op->func_code = (PyObject*)code_obj; + op->func_defaults = NULL; // No default positional arguments + op->func_kwdefaults = NULL; // No default keyword arguments op->func_closure = NULL; - op->vectorcall = _PyFunction_Vectorcall; - op->func_module = module; - - consts = ((PyCodeObject *)code)->co_consts; - if (PyTuple_Size(consts) >= 1) { - doc = PyTuple_GetItem(consts, 0); - if (!PyUnicode_Check(doc)) - doc = Py_None; - } - else - doc = Py_None; - Py_INCREF(doc); op->func_doc = doc; - op->func_dict = NULL; + op->func_weakreflist = NULL; + op->func_module = module; op->func_annotations = NULL; - - if (qualname) - op->func_qualname = qualname; - else - op->func_qualname = op->func_name; - Py_INCREF(op->func_qualname); + op->vectorcall = _PyFunction_Vectorcall; _PyObject_GC_TRACK(op); return (PyObject *)op; + +error: + Py_DECREF(globals); + Py_DECREF(code_obj); + Py_DECREF(name); + Py_DECREF(qualname); + Py_DECREF(doc); + Py_XDECREF(module); + Py_XDECREF(builtins); + return NULL; } PyObject * @@ -204,6 +221,37 @@ PyFunction_SetClosure(PyObject *op, PyObject *closure) return 0; } +static PyObject * +func_get_annotation_dict(PyFunctionObject *op) +{ + if (op->func_annotations == NULL) { + return NULL; + } + if (PyTuple_CheckExact(op->func_annotations)) { + PyObject *ann_tuple = op->func_annotations; + PyObject *ann_dict = PyDict_New(); + if (ann_dict == NULL) { + return NULL; + } + + assert(PyTuple_GET_SIZE(ann_tuple) % 2 == 0); + + for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(ann_tuple); i += 2) { + int err = PyDict_SetItem(ann_dict, + PyTuple_GET_ITEM(ann_tuple, i), + PyTuple_GET_ITEM(ann_tuple, i + 1)); + + if (err < 0) { + return NULL; + } + } + Py_SETREF(op->func_annotations, ann_dict); + } + Py_INCREF(op->func_annotations); + assert(PyDict_Check(op->func_annotations)); + return op->func_annotations; +} + PyObject * PyFunction_GetAnnotations(PyObject *op) { @@ -211,7 +259,7 @@ PyFunction_GetAnnotations(PyObject *op) PyErr_BadInternalCall(); return NULL; } - return ((PyFunctionObject *) op) -> func_annotations; + return func_get_annotation_dict((PyFunctionObject *)op); } int @@ -244,6 +292,7 @@ static PyMemberDef func_memberlist[] = { {"__doc__", T_OBJECT, OFF(func_doc), 0}, {"__globals__", T_OBJECT, OFF(func_globals), READONLY}, {"__module__", T_OBJECT, OFF(func_module), 0}, + {"__builtins__", T_OBJECT, OFF(func_builtins), READONLY}, {NULL} /* Sentinel */ }; @@ -425,8 +474,7 @@ func_get_annotations(PyFunctionObject *op, void *Py_UNUSED(ignored)) if (op->func_annotations == NULL) return NULL; } - Py_INCREF(op->func_annotations); - return op->func_annotations; + return func_get_annotation_dict(op); } static int @@ -550,9 +598,9 @@ func_new_impl(PyTypeObject *type, PyCodeObject *code, PyObject *globals, newfunc = (PyFunctionObject *)PyFunction_New((PyObject *)code, globals); - if (newfunc == NULL) + if (newfunc == NULL) { return NULL; - + } if (name != Py_None) { Py_INCREF(name); Py_SETREF(newfunc->func_name, name); @@ -574,15 +622,16 @@ func_clear(PyFunctionObject *op) { Py_CLEAR(op->func_code); Py_CLEAR(op->func_globals); - Py_CLEAR(op->func_module); + Py_CLEAR(op->func_builtins); Py_CLEAR(op->func_name); + Py_CLEAR(op->func_qualname); + Py_CLEAR(op->func_module); Py_CLEAR(op->func_defaults); Py_CLEAR(op->func_kwdefaults); Py_CLEAR(op->func_doc); Py_CLEAR(op->func_dict); Py_CLEAR(op->func_closure); Py_CLEAR(op->func_annotations); - Py_CLEAR(op->func_qualname); return 0; } @@ -601,7 +650,7 @@ static PyObject* func_repr(PyFunctionObject *op) { return PyUnicode_FromFormat("", - op->func_qualname, op); + op->func_qualname, op); } static int @@ -609,6 +658,7 @@ func_traverse(PyFunctionObject *f, visitproc visit, void *arg) { Py_VISIT(f->func_code); Py_VISIT(f->func_globals); + Py_VISIT(f->func_builtins); Py_VISIT(f->func_module); Py_VISIT(f->func_defaults); Py_VISIT(f->func_kwdefaults); @@ -676,6 +726,50 @@ PyTypeObject PyFunction_Type = { }; +static int +functools_copy_attr(PyObject *wrapper, PyObject *wrapped, PyObject *name) +{ + PyObject *value = PyObject_GetAttr(wrapped, name); + if (value == NULL) { + if (PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Clear(); + return 0; + } + return -1; + } + + int res = PyObject_SetAttr(wrapper, name, value); + Py_DECREF(value); + return res; +} + +// Similar to functools.wraps(wrapper, wrapped) +static int +functools_wraps(PyObject *wrapper, PyObject *wrapped) +{ +#define COPY_ATTR(ATTR) \ + do { \ + _Py_IDENTIFIER(ATTR); \ + PyObject *attr = _PyUnicode_FromId(&PyId_ ## ATTR); \ + if (attr == NULL) { \ + return -1; \ + } \ + if (functools_copy_attr(wrapper, wrapped, attr) < 0) { \ + return -1; \ + } \ + } while (0) \ + + COPY_ATTR(__module__); + COPY_ATTR(__name__); + COPY_ATTR(__qualname__); + COPY_ATTR(__doc__); + COPY_ATTR(__annotations__); + return 0; + +#undef COPY_ATTR +} + + /* Class method object */ /* A class method receives the class as implicit first argument, @@ -742,7 +836,7 @@ cm_descr_get(PyObject *self, PyObject *obj, PyObject *type) type = (PyObject *)(Py_TYPE(obj)); if (Py_TYPE(cm->cm_callable)->tp_descr_get != NULL) { return Py_TYPE(cm->cm_callable)->tp_descr_get(cm->cm_callable, type, - NULL); + type); } return PyMethod_New(cm->cm_callable, type); } @@ -759,11 +853,16 @@ cm_init(PyObject *self, PyObject *args, PyObject *kwds) return -1; Py_INCREF(callable); Py_XSETREF(cm->cm_callable, callable); + + if (functools_wraps((PyObject *)cm, cm->cm_callable) < 0) { + return -1; + } return 0; } static PyMemberDef cm_memberlist[] = { {"__func__", T_OBJECT, offsetof(classmethod, cm_callable), READONLY}, + {"__wrapped__", T_OBJECT, offsetof(classmethod, cm_callable), READONLY}, {NULL} /* Sentinel */ }; @@ -782,13 +881,17 @@ cm_get___isabstractmethod__(classmethod *cm, void *closure) static PyGetSetDef cm_getsetlist[] = { {"__isabstractmethod__", - (getter)cm_get___isabstractmethod__, NULL, - NULL, - NULL}, + (getter)cm_get___isabstractmethod__, NULL, NULL, NULL}, {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict, NULL, NULL}, {NULL} /* Sentinel */ }; +static PyObject* +cm_repr(classmethod *cm) +{ + return PyUnicode_FromFormat("", cm->cm_callable); +} + PyDoc_STRVAR(classmethod_doc, "classmethod(function) -> method\n\ \n\ @@ -821,7 +924,7 @@ PyTypeObject PyClassMethod_Type = { 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ - 0, /* tp_repr */ + (reprfunc)cm_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ @@ -941,11 +1044,23 @@ sm_init(PyObject *self, PyObject *args, PyObject *kwds) return -1; Py_INCREF(callable); Py_XSETREF(sm->sm_callable, callable); + + if (functools_wraps((PyObject *)sm, sm->sm_callable) < 0) { + return -1; + } return 0; } +static PyObject* +sm_call(PyObject *callable, PyObject *args, PyObject *kwargs) +{ + staticmethod *sm = (staticmethod *)callable; + return PyObject_Call(sm->sm_callable, args, kwargs); +} + static PyMemberDef sm_memberlist[] = { {"__func__", T_OBJECT, offsetof(staticmethod, sm_callable), READONLY}, + {"__wrapped__", T_OBJECT, offsetof(staticmethod, sm_callable), READONLY}, {NULL} /* Sentinel */ }; @@ -964,13 +1079,17 @@ sm_get___isabstractmethod__(staticmethod *sm, void *closure) static PyGetSetDef sm_getsetlist[] = { {"__isabstractmethod__", - (getter)sm_get___isabstractmethod__, NULL, - NULL, - NULL}, + (getter)sm_get___isabstractmethod__, NULL, NULL, NULL}, {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict, NULL, NULL}, {NULL} /* Sentinel */ }; +static PyObject* +sm_repr(staticmethod *sm) +{ + return PyUnicode_FromFormat("", sm->sm_callable); +} + PyDoc_STRVAR(staticmethod_doc, "staticmethod(function) -> method\n\ \n\ @@ -1001,12 +1120,12 @@ PyTypeObject PyStaticMethod_Type = { 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ - 0, /* tp_repr */ + (reprfunc)sm_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ - 0, /* tp_call */ + sm_call, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ -- cgit v1.3