summaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/src/Objects/funcobject.c
diff options
context:
space:
mode:
authorshadchin <[email protected]>2022-04-18 12:39:32 +0300
committershadchin <[email protected]>2022-04-18 12:39:32 +0300
commitd4be68e361f4258cf0848fc70018dfe37a2acc24 (patch)
tree153e294cd97ac8b5d7a989612704a0c1f58e8ad4 /contrib/tools/python3/src/Objects/funcobject.c
parent260c02f5ccf242d9d9b8a873afaf6588c00237d6 (diff)
IGNIETFERRO-1816 Update Python 3 from 3.9.12 to 3.10.4
ref:9f96be6d02ee8044fdd6f124b799b270c20ce641
Diffstat (limited to 'contrib/tools/python3/src/Objects/funcobject.c')
-rw-r--r--contrib/tools/python3/src/Objects/funcobject.c249
1 files changed, 184 insertions, 65 deletions
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("<function %U at %p>",
- 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("<classmethod(%R)>", 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("<staticmethod(%R)>", 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 */