mirror of
https://github.com/python/cpython.git
synced 2025-08-04 08:59:19 +00:00
bpo-42990: Refactor _PyFrame_New_NoTrack() (GH-24566)
* Refactor _PyFrame_New_NoTrack() and PyFunction_NewWithQualName() code. * PyFrame_New() checks for _PyEval_BuiltinsFromGlobals() failure. * Fix a ref leak in _PyEval_BuiltinsFromGlobals() error path. * Complete PyFunction_GetModule() documentation: it returns a borrowed reference and it can return NULL. * Move _PyEval_BuiltinsFromGlobals() definition to the internal C API. * PyFunction_NewWithQualName() uses _Py_IDENTIFIER() API for the "__name__" string to make it compatible with subinterpreters.
This commit is contained in:
parent
cc96231f0a
commit
44085a3fc9
6 changed files with 117 additions and 115 deletions
|
@ -2,83 +2,90 @@
|
|||
/* Function object implementation */
|
||||
|
||||
#include "Python.h"
|
||||
#include "pycore_object.h"
|
||||
#include "frameobject.h"
|
||||
#include "code.h"
|
||||
#include "pycore_ceval.h" // _PyEval_BuiltinsFromGlobals()
|
||||
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
|
||||
#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;
|
||||
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);
|
||||
|
||||
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 {
|
||||
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()) {
|
||||
goto error;
|
||||
}
|
||||
Py_XINCREF(module);
|
||||
|
||||
builtins = _PyEval_BuiltinsFromGlobals(globals);
|
||||
if (builtins == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* __module__: If module name is in globals, use it.
|
||||
Otherwise, use None. */
|
||||
module = PyDict_GetItemWithError(globals, __name__);
|
||||
if (module) {
|
||||
Py_INCREF(module);
|
||||
}
|
||||
else if (PyErr_Occurred()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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;
|
||||
assert(globals != NULL);
|
||||
Py_INCREF(globals);
|
||||
op->func_globals = globals;
|
||||
PyObject *builtins = _PyEval_BuiltinsFromGlobals(globals);
|
||||
if (builtins == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
op->func_builtins = builtins;
|
||||
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_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 *
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue