mirror of
https://github.com/python/cpython.git
synced 2025-12-08 06:10:17 +00:00
Merge pull request #9 from LazyImportsCabal/cleanup
More PEP-810 compatibility, fix memory leaks and LOAD_ATTR specialization
This commit is contained in:
commit
fe526b4e54
15 changed files with 135 additions and 94 deletions
|
|
@ -38,6 +38,7 @@ extern PyObject* _PyDict_GetItemIdWithError(PyObject *dp,
|
||||||
extern int _PyDict_ContainsId(PyObject *, _Py_Identifier *);
|
extern int _PyDict_ContainsId(PyObject *, _Py_Identifier *);
|
||||||
extern int _PyDict_SetItemId(PyObject *dp, _Py_Identifier *key, PyObject *item);
|
extern int _PyDict_SetItemId(PyObject *dp, _Py_Identifier *key, PyObject *item);
|
||||||
extern int _PyDict_DelItemId(PyObject *mp, _Py_Identifier *key);
|
extern int _PyDict_DelItemId(PyObject *mp, _Py_Identifier *key);
|
||||||
|
extern void _PyDict_ClearKeysVersion(PyObject *mp);
|
||||||
|
|
||||||
extern int _PyDict_Next(
|
extern int _PyDict_Next(
|
||||||
PyObject *mp, Py_ssize_t *pos, PyObject **key, PyObject **value, Py_hash_t *hash);
|
PyObject *mp, Py_ssize_t *pos, PyObject **key, PyObject **value, Py_hash_t *hash);
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ PyAPI_DATA(PyTypeObject) PyLazyImport_Type;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
PyObject *lz_import_func;
|
PyObject *lz_builtins;
|
||||||
PyObject *lz_from;
|
PyObject *lz_from;
|
||||||
PyObject *lz_attr;
|
PyObject *lz_attr;
|
||||||
/* Frame information for the original import location */
|
/* Frame information for the original import location */
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,8 @@ extern Py_ssize_t _PyModule_GetFilenameUTF8(
|
||||||
PyObject* _Py_module_getattro_impl(PyModuleObject *m, PyObject *name, int suppress);
|
PyObject* _Py_module_getattro_impl(PyModuleObject *m, PyObject *name, int suppress);
|
||||||
PyObject* _Py_module_getattro(PyObject *m, PyObject *name);
|
PyObject* _Py_module_getattro(PyObject *m, PyObject *name);
|
||||||
|
|
||||||
|
PyAPI_FUNC(int) _PyModule_ReplaceLazyValue(PyObject *dict, PyObject *name, PyObject *value);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@
|
||||||
|
|
||||||
from ._bootstrap import __import__
|
from ._bootstrap import __import__
|
||||||
|
|
||||||
from _imp import lazy_import, set_lazy_imports
|
from _imp import set_lazy_imports
|
||||||
|
|
||||||
|
|
||||||
def invalidate_caches():
|
def invalidate_caches():
|
||||||
|
|
|
||||||
|
|
@ -2790,7 +2790,7 @@ def test_lazy_import_pkg_cross_import(self):
|
||||||
|
|
||||||
g = test.test_import.data.lazy_imports.pkg.c.get_globals()
|
g = test.test_import.data.lazy_imports.pkg.c.get_globals()
|
||||||
self.assertEqual(type(g["x"]), int)
|
self.assertEqual(type(g["x"]), int)
|
||||||
self.assertEqual(type(g["b"]), importlib.lazy_import)
|
self.assertEqual(type(g["b"]), types.LazyImportType)
|
||||||
|
|
||||||
class TestSinglePhaseSnapshot(ModuleSnapshot):
|
class TestSinglePhaseSnapshot(ModuleSnapshot):
|
||||||
"""A representation of a single-phase init module for testing.
|
"""A representation of a single-phase init module for testing.
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include "pycore_descrobject.h" // _PyMethodWrapper_Type
|
#include "pycore_descrobject.h" // _PyMethodWrapper_Type
|
||||||
|
#include "pycore_lazyimportobject.h" // PyLazyImport_Type
|
||||||
#include "pycore_namespace.h" // _PyNamespace_Type
|
#include "pycore_namespace.h" // _PyNamespace_Type
|
||||||
#include "pycore_object.h" // _PyNone_Type, _PyNotImplemented_Type
|
#include "pycore_object.h" // _PyNone_Type, _PyNotImplemented_Type
|
||||||
#include "pycore_unionobject.h" // _PyUnion_Type
|
#include "pycore_unionobject.h" // _PyUnion_Type
|
||||||
|
|
@ -35,6 +36,7 @@ _types_exec(PyObject *m)
|
||||||
EXPORT_STATIC_TYPE("GetSetDescriptorType", PyGetSetDescr_Type);
|
EXPORT_STATIC_TYPE("GetSetDescriptorType", PyGetSetDescr_Type);
|
||||||
// LambdaType is the same as FunctionType
|
// LambdaType is the same as FunctionType
|
||||||
EXPORT_STATIC_TYPE("LambdaType", PyFunction_Type);
|
EXPORT_STATIC_TYPE("LambdaType", PyFunction_Type);
|
||||||
|
EXPORT_STATIC_TYPE("LazyImportType", PyLazyImport_Type);
|
||||||
EXPORT_STATIC_TYPE("MappingProxyType", PyDictProxy_Type);
|
EXPORT_STATIC_TYPE("MappingProxyType", PyDictProxy_Type);
|
||||||
EXPORT_STATIC_TYPE("MemberDescriptorType", PyMemberDescr_Type);
|
EXPORT_STATIC_TYPE("MemberDescriptorType", PyMemberDescr_Type);
|
||||||
EXPORT_STATIC_TYPE("MethodDescriptorType", PyMethodDescr_Type);
|
EXPORT_STATIC_TYPE("MethodDescriptorType", PyMethodDescr_Type);
|
||||||
|
|
|
||||||
|
|
@ -4719,6 +4719,14 @@ sizeof_lock_held(PyDictObject *mp)
|
||||||
return (Py_ssize_t)res;
|
return (Py_ssize_t)res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_PyDict_ClearKeysVersion(PyObject *mp)
|
||||||
|
{
|
||||||
|
ASSERT_DICT_LOCKED(mp);
|
||||||
|
|
||||||
|
FT_ATOMIC_STORE_UINT32_RELAXED(((PyDictObject *)mp)->ma_keys->dk_version, 0);
|
||||||
|
}
|
||||||
|
|
||||||
Py_ssize_t
|
Py_ssize_t
|
||||||
_PyDict_SizeOf(PyDictObject *mp)
|
_PyDict_SizeOf(PyDictObject *mp)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
#include "pycore_interpframe.h"
|
#include "pycore_interpframe.h"
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
_PyLazyImport_New(PyObject *import_func, PyObject *from, PyObject *attr)
|
_PyLazyImport_New(PyObject *builtins, PyObject *from, PyObject *attr)
|
||||||
{
|
{
|
||||||
PyLazyImportObject *m;
|
PyLazyImportObject *m;
|
||||||
if (!from || !PyUnicode_Check(from)) {
|
if (!from || !PyUnicode_Check(from)) {
|
||||||
|
|
@ -23,8 +23,8 @@ _PyLazyImport_New(PyObject *import_func, PyObject *from, PyObject *attr)
|
||||||
if (m == NULL) {
|
if (m == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
Py_XINCREF(import_func);
|
Py_XINCREF(builtins);
|
||||||
m->lz_import_func = import_func;
|
m->lz_builtins = builtins;
|
||||||
Py_INCREF(from);
|
Py_INCREF(from);
|
||||||
m->lz_from = from;
|
m->lz_from = from;
|
||||||
Py_XINCREF(attr);
|
Py_XINCREF(attr);
|
||||||
|
|
@ -52,7 +52,7 @@ static void
|
||||||
lazy_import_dealloc(PyLazyImportObject *m)
|
lazy_import_dealloc(PyLazyImportObject *m)
|
||||||
{
|
{
|
||||||
PyObject_GC_UnTrack(m);
|
PyObject_GC_UnTrack(m);
|
||||||
Py_XDECREF(m->lz_import_func);
|
Py_XDECREF(m->lz_builtins);
|
||||||
Py_XDECREF(m->lz_from);
|
Py_XDECREF(m->lz_from);
|
||||||
Py_XDECREF(m->lz_attr);
|
Py_XDECREF(m->lz_attr);
|
||||||
Py_XDECREF(m->lz_code);
|
Py_XDECREF(m->lz_code);
|
||||||
|
|
@ -88,7 +88,7 @@ lazy_import_repr(PyLazyImportObject *m)
|
||||||
static int
|
static int
|
||||||
lazy_import_traverse(PyLazyImportObject *m, visitproc visit, void *arg)
|
lazy_import_traverse(PyLazyImportObject *m, visitproc visit, void *arg)
|
||||||
{
|
{
|
||||||
Py_VISIT(m->lz_import_func);
|
Py_VISIT(m->lz_builtins);
|
||||||
Py_VISIT(m->lz_from);
|
Py_VISIT(m->lz_from);
|
||||||
Py_VISIT(m->lz_attr);
|
Py_VISIT(m->lz_attr);
|
||||||
Py_VISIT(m->lz_code);
|
Py_VISIT(m->lz_code);
|
||||||
|
|
@ -98,7 +98,7 @@ lazy_import_traverse(PyLazyImportObject *m, visitproc visit, void *arg)
|
||||||
static int
|
static int
|
||||||
lazy_import_clear(PyLazyImportObject *m)
|
lazy_import_clear(PyLazyImportObject *m)
|
||||||
{
|
{
|
||||||
Py_CLEAR(m->lz_import_func);
|
Py_CLEAR(m->lz_builtins);
|
||||||
Py_CLEAR(m->lz_from);
|
Py_CLEAR(m->lz_from);
|
||||||
Py_CLEAR(m->lz_attr);
|
Py_CLEAR(m->lz_attr);
|
||||||
Py_CLEAR(m->lz_code);
|
Py_CLEAR(m->lz_code);
|
||||||
|
|
@ -144,8 +144,8 @@ static PyMethodDef lazy_methods[] = {
|
||||||
|
|
||||||
PyTypeObject PyLazyImport_Type = {
|
PyTypeObject PyLazyImport_Type = {
|
||||||
PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
||||||
"lazy_import", /* tp_name */
|
"LazyImport", /* tp_name */
|
||||||
sizeof(PyLazyImportObject), /* tp_basicsize */
|
sizeof(PyLazyImportObject), /* tp_basicsize */
|
||||||
0, /* tp_itemsize */
|
0, /* tp_itemsize */
|
||||||
(destructor)lazy_import_dealloc, /* tp_dealloc */
|
(destructor)lazy_import_dealloc, /* tp_dealloc */
|
||||||
0, /* tp_print */
|
0, /* tp_print */
|
||||||
|
|
|
||||||
|
|
@ -1036,6 +1036,23 @@ _PyModule_IsPossiblyShadowing(PyObject *origin)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_PyModule_ReplaceLazyValue(PyObject *dict, PyObject *name, PyObject *value)
|
||||||
|
{
|
||||||
|
// The adaptive interpreter uses the dictionary version to return the slot at
|
||||||
|
// a given index from the module. When replacing a value the version number doesn't
|
||||||
|
// change, so we need to atomically clear the version before replacing so that it
|
||||||
|
// doesn't return a lazy value.
|
||||||
|
int err;
|
||||||
|
Py_BEGIN_CRITICAL_SECTION(dict);
|
||||||
|
|
||||||
|
_PyDict_ClearKeysVersion(dict);
|
||||||
|
err = _PyDict_SetItem_LockHeld((PyDictObject *)dict, name, value);
|
||||||
|
|
||||||
|
Py_END_CRITICAL_SECTION();
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
PyObject*
|
PyObject*
|
||||||
_Py_module_getattro_impl(PyModuleObject *m, PyObject *name, int suppress)
|
_Py_module_getattro_impl(PyModuleObject *m, PyObject *name, int suppress)
|
||||||
{
|
{
|
||||||
|
|
@ -1052,13 +1069,13 @@ _Py_module_getattro_impl(PyModuleObject *m, PyObject *name, int suppress)
|
||||||
// instead treated as if the attribute doesn't exist.
|
// instead treated as if the attribute doesn't exist.
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
|
||||||
} else if (PyDict_SetItem(m->md_dict, name, new_value) < 0) {
|
|
||||||
Py_DECREF(new_value);
|
|
||||||
Py_DECREF(attr);
|
Py_DECREF(attr);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_PyModule_ReplaceLazyValue(m->md_dict, name, new_value) < 0) {
|
||||||
|
Py_CLEAR(new_value);
|
||||||
|
}
|
||||||
Py_DECREF(attr);
|
Py_DECREF(attr);
|
||||||
return new_value;
|
return new_value;
|
||||||
}
|
}
|
||||||
|
|
@ -1490,7 +1507,7 @@ module_get_dict(PyObject *mod, void *Py_UNUSED(ignored))
|
||||||
if (new_value == NULL) {
|
if (new_value == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (PyDict_SetItem(self->md_dict, key, new_value) < 0) {
|
if (_PyModule_ReplaceLazyValue(self->md_dict, key, new_value) < 0) {
|
||||||
Py_DECREF(new_value);
|
Py_DECREF(new_value);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1799,12 +1799,13 @@ dummy_func(
|
||||||
ERROR_IF(v_o == NULL);
|
ERROR_IF(v_o == NULL);
|
||||||
if (PyLazyImport_CheckExact(v_o)) {
|
if (PyLazyImport_CheckExact(v_o)) {
|
||||||
PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, v_o);
|
PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, v_o);
|
||||||
if (l_v != NULL && PyDict_SetItem(GLOBALS(), name, l_v) < 0) {
|
Py_DECREF(v_o);
|
||||||
|
ERROR_IF(l_v == NULL);
|
||||||
|
int err = _PyModule_ReplaceLazyValue(GLOBALS(), name, l_v);
|
||||||
|
if (err < 0) {
|
||||||
JUMP_TO_LABEL(error);
|
JUMP_TO_LABEL(error);
|
||||||
}
|
}
|
||||||
Py_DECREF(v_o);
|
|
||||||
v_o = l_v;
|
v_o = l_v;
|
||||||
ERROR_IF(v_o == NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
v = PyStackRef_FromPyObjectSteal(v_o);
|
v = PyStackRef_FromPyObjectSteal(v_o);
|
||||||
|
|
@ -1838,13 +1839,14 @@ dummy_func(
|
||||||
PyObject *res_o = PyStackRef_AsPyObjectBorrow(*res);
|
PyObject *res_o = PyStackRef_AsPyObjectBorrow(*res);
|
||||||
if (PyLazyImport_CheckExact(res_o)) {
|
if (PyLazyImport_CheckExact(res_o)) {
|
||||||
PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, res_o);
|
PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, res_o);
|
||||||
if (l_v != NULL && PyDict_SetItem(GLOBALS(), name, l_v) < 0) {
|
PyStackRef_CLOSE(res[0]);
|
||||||
|
ERROR_IF(l_v == NULL);
|
||||||
|
int err = _PyModule_ReplaceLazyValue(GLOBALS(), name, l_v);
|
||||||
|
if (err < 0) {
|
||||||
|
Py_DECREF(l_v);
|
||||||
JUMP_TO_LABEL(error);
|
JUMP_TO_LABEL(error);
|
||||||
}
|
}
|
||||||
res_o = l_v;
|
*res = PyStackRef_FromPyObjectSteal(l_v);
|
||||||
PyStackRef_CLOSE(res[0]);
|
|
||||||
ERROR_IF(res_o == NULL);
|
|
||||||
*res = PyStackRef_FromPyObjectSteal(res_o);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3038,6 +3038,9 @@ check_lazy_import_comatibility(PyThreadState *tstate, PyObject *globals,
|
||||||
// Check if this module should be imported lazily due to the compatbility mode support via
|
// Check if this module should be imported lazily due to the compatbility mode support via
|
||||||
// __lazy_modules__.
|
// __lazy_modules__.
|
||||||
PyObject *lazy_modules = NULL;
|
PyObject *lazy_modules = NULL;
|
||||||
|
PyObject *abs_name = NULL;
|
||||||
|
int res = -1;
|
||||||
|
|
||||||
if (globals != NULL &&
|
if (globals != NULL &&
|
||||||
PyMapping_GetOptionalItem(globals, &_Py_ID(__lazy_modules__), &lazy_modules) < 0) {
|
PyMapping_GetOptionalItem(globals, &_Py_ID(__lazy_modules__), &lazy_modules) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -3047,15 +3050,19 @@ check_lazy_import_comatibility(PyThreadState *tstate, PyObject *globals,
|
||||||
|
|
||||||
int ilevel = PyLong_AsInt(level);
|
int ilevel = PyLong_AsInt(level);
|
||||||
if (ilevel == -1 && _PyErr_Occurred(tstate)) {
|
if (ilevel == -1 && _PyErr_Occurred(tstate)) {
|
||||||
return -1;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *abs_name = _PyImport_GetAbsName(tstate, name, globals, ilevel);
|
abs_name = _PyImport_GetAbsName(tstate, name, globals, ilevel);
|
||||||
if (abs_name == NULL) {
|
if (abs_name == NULL) {
|
||||||
return -1;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
return PySequence_Contains(lazy_modules, abs_name);
|
res = PySequence_Contains(lazy_modules, abs_name);
|
||||||
|
error:
|
||||||
|
Py_XDECREF(abs_name);
|
||||||
|
Py_XDECREF(lazy_modules);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
|
|
@ -3089,14 +3096,6 @@ _PyEval_LazyImportName(PyThreadState *tstate, PyObject *builtins, PyObject *glob
|
||||||
return _PyEval_ImportName(tstate, builtins, globals, locals, name, fromlist, level);
|
return _PyEval_ImportName(tstate, builtins, globals, locals, name, fromlist, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *import_func;
|
|
||||||
if (PyMapping_GetOptionalItem(builtins, &_Py_ID(__import__), &import_func) < 0) {
|
|
||||||
goto error;
|
|
||||||
} else if (import_func == NULL) {
|
|
||||||
_PyErr_SetString(tstate, PyExc_ImportError, "__import__ not found");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyObject *lazy_import_func;
|
PyObject *lazy_import_func;
|
||||||
if (PyMapping_GetOptionalItem(builtins, &_Py_ID(__lazy_import__), &lazy_import_func) < 0) {
|
if (PyMapping_GetOptionalItem(builtins, &_Py_ID(__lazy_import__), &lazy_import_func) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
|
|
@ -3116,16 +3115,15 @@ _PyEval_LazyImportName(PyThreadState *tstate, PyObject *builtins, PyObject *glob
|
||||||
}
|
}
|
||||||
|
|
||||||
res = _PyImport_LazyImportModuleLevelObject(
|
res = _PyImport_LazyImportModuleLevelObject(
|
||||||
tstate, name, import_func, globals, locals, fromlist, ilevel
|
tstate, name, builtins, globals, locals, fromlist, ilevel
|
||||||
);
|
);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject* args[6] = {name, globals, locals, fromlist, level, import_func};
|
PyObject* args[6] = {name, globals, locals, fromlist, level, builtins};
|
||||||
res = PyObject_Vectorcall(lazy_import_func, args, 6, NULL);
|
res = PyObject_Vectorcall(lazy_import_func, args, 6, NULL);
|
||||||
error:
|
error:
|
||||||
Py_XDECREF(lazy_import_func);
|
Py_XDECREF(lazy_import_func);
|
||||||
Py_XDECREF(import_func);
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3311,8 +3309,10 @@ _PyEval_LazyImportFrom(PyThreadState *tstate, PyObject *v, PyObject *name)
|
||||||
PyObject *mod_dict = PyModule_GetDict(mod);
|
PyObject *mod_dict = PyModule_GetDict(mod);
|
||||||
if (mod_dict != NULL) {
|
if (mod_dict != NULL) {
|
||||||
if (PyDict_GetItemRef(mod_dict, name, &ret) < 0) {
|
if (PyDict_GetItemRef(mod_dict, name, &ret) < 0) {
|
||||||
|
Py_DECREF(mod);
|
||||||
return NULL;
|
return NULL;
|
||||||
} else if (ret != NULL) {
|
} else if (ret != NULL) {
|
||||||
|
Py_DECREF(mod);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3323,7 +3323,7 @@ _PyEval_LazyImportFrom(PyThreadState *tstate, PyObject *v, PyObject *name)
|
||||||
if (d->lz_attr != NULL) {
|
if (d->lz_attr != NULL) {
|
||||||
if (PyUnicode_Check(d->lz_attr)) {
|
if (PyUnicode_Check(d->lz_attr)) {
|
||||||
PyObject *from = PyUnicode_FromFormat("%U.%U", d->lz_from, d->lz_attr);
|
PyObject *from = PyUnicode_FromFormat("%U.%U", d->lz_from, d->lz_attr);
|
||||||
ret = _PyLazyImport_New(d->lz_import_func, from, name);
|
ret = _PyLazyImport_New(d->lz_builtins, from, name);
|
||||||
Py_DECREF(from);
|
Py_DECREF(from);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
@ -3331,12 +3331,12 @@ _PyEval_LazyImportFrom(PyThreadState *tstate, PyObject *v, PyObject *name)
|
||||||
Py_ssize_t dot = PyUnicode_FindChar(d->lz_from, '.', 0, PyUnicode_GET_LENGTH(d->lz_from), 1);
|
Py_ssize_t dot = PyUnicode_FindChar(d->lz_from, '.', 0, PyUnicode_GET_LENGTH(d->lz_from), 1);
|
||||||
if (dot >= 0) {
|
if (dot >= 0) {
|
||||||
PyObject *from = PyUnicode_Substring(d->lz_from, 0, dot);
|
PyObject *from = PyUnicode_Substring(d->lz_from, 0, dot);
|
||||||
ret = _PyLazyImport_New(d->lz_import_func, from, name);
|
ret = _PyLazyImport_New(d->lz_builtins, from, name);
|
||||||
Py_DECREF(from);
|
Py_DECREF(from);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret = _PyLazyImport_New(d->lz_import_func, d->lz_from, name);
|
ret = _PyLazyImport_New(d->lz_builtins, d->lz_from, name);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
34
Python/executor_cases.c.h
generated
34
Python/executor_cases.c.h
generated
|
|
@ -2461,17 +2461,18 @@
|
||||||
if (PyLazyImport_CheckExact(v_o)) {
|
if (PyLazyImport_CheckExact(v_o)) {
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, v_o);
|
PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, v_o);
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
|
||||||
if (l_v != NULL && PyDict_SetItem(GLOBALS(), name, l_v) < 0) {
|
|
||||||
JUMP_TO_LABEL(error);
|
|
||||||
}
|
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
|
||||||
Py_DECREF(v_o);
|
Py_DECREF(v_o);
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
v_o = l_v;
|
if (l_v == NULL) {
|
||||||
if (v_o == NULL) {
|
|
||||||
JUMP_TO_ERROR();
|
JUMP_TO_ERROR();
|
||||||
}
|
}
|
||||||
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
|
int err = _PyModule_ReplaceLazyValue(GLOBALS(), name, l_v);
|
||||||
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
|
if (err < 0) {
|
||||||
|
JUMP_TO_LABEL(error);
|
||||||
|
}
|
||||||
|
v_o = l_v;
|
||||||
}
|
}
|
||||||
v = PyStackRef_FromPyObjectSteal(v_o);
|
v = PyStackRef_FromPyObjectSteal(v_o);
|
||||||
stack_pointer[0] = v;
|
stack_pointer[0] = v;
|
||||||
|
|
@ -2495,18 +2496,21 @@
|
||||||
if (PyLazyImport_CheckExact(res_o)) {
|
if (PyLazyImport_CheckExact(res_o)) {
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, res_o);
|
PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, res_o);
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
|
||||||
if (l_v != NULL && PyDict_SetItem(GLOBALS(), name, l_v) < 0) {
|
|
||||||
JUMP_TO_LABEL(error);
|
|
||||||
}
|
|
||||||
res_o = l_v;
|
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
|
||||||
PyStackRef_CLOSE(res[0]);
|
PyStackRef_CLOSE(res[0]);
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
if (res_o == NULL) {
|
if (l_v == NULL) {
|
||||||
JUMP_TO_ERROR();
|
JUMP_TO_ERROR();
|
||||||
}
|
}
|
||||||
*res = PyStackRef_FromPyObjectSteal(res_o);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
|
int err = _PyModule_ReplaceLazyValue(GLOBALS(), name, l_v);
|
||||||
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
|
if (err < 0) {
|
||||||
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
|
Py_DECREF(l_v);
|
||||||
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
|
JUMP_TO_LABEL(error);
|
||||||
|
}
|
||||||
|
*res = PyStackRef_FromPyObjectSteal(l_v);
|
||||||
}
|
}
|
||||||
stack_pointer += 1;
|
stack_pointer += 1;
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
|
|
|
||||||
28
Python/generated_cases.c.h
generated
28
Python/generated_cases.c.h
generated
|
|
@ -9193,18 +9193,21 @@
|
||||||
if (PyLazyImport_CheckExact(res_o)) {
|
if (PyLazyImport_CheckExact(res_o)) {
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, res_o);
|
PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, res_o);
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
|
||||||
if (l_v != NULL && PyDict_SetItem(GLOBALS(), name, l_v) < 0) {
|
|
||||||
JUMP_TO_LABEL(error);
|
|
||||||
}
|
|
||||||
res_o = l_v;
|
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
|
||||||
PyStackRef_CLOSE(res[0]);
|
PyStackRef_CLOSE(res[0]);
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
if (res_o == NULL) {
|
if (l_v == NULL) {
|
||||||
JUMP_TO_LABEL(error);
|
JUMP_TO_LABEL(error);
|
||||||
}
|
}
|
||||||
*res = PyStackRef_FromPyObjectSteal(res_o);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
|
int err = _PyModule_ReplaceLazyValue(GLOBALS(), name, l_v);
|
||||||
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
|
if (err < 0) {
|
||||||
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
|
Py_DECREF(l_v);
|
||||||
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
|
JUMP_TO_LABEL(error);
|
||||||
|
}
|
||||||
|
*res = PyStackRef_FromPyObjectSteal(l_v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// _PUSH_NULL_CONDITIONAL
|
// _PUSH_NULL_CONDITIONAL
|
||||||
|
|
@ -9409,17 +9412,18 @@
|
||||||
if (PyLazyImport_CheckExact(v_o)) {
|
if (PyLazyImport_CheckExact(v_o)) {
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, v_o);
|
PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, v_o);
|
||||||
|
Py_DECREF(v_o);
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
if (l_v != NULL && PyDict_SetItem(GLOBALS(), name, l_v) < 0) {
|
if (l_v == NULL) {
|
||||||
JUMP_TO_LABEL(error);
|
JUMP_TO_LABEL(error);
|
||||||
}
|
}
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
Py_DECREF(v_o);
|
int err = _PyModule_ReplaceLazyValue(GLOBALS(), name, l_v);
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
v_o = l_v;
|
if (err < 0) {
|
||||||
if (v_o == NULL) {
|
|
||||||
JUMP_TO_LABEL(error);
|
JUMP_TO_LABEL(error);
|
||||||
}
|
}
|
||||||
|
v_o = l_v;
|
||||||
}
|
}
|
||||||
v = PyStackRef_FromPyObjectSteal(v_o);
|
v = PyStackRef_FromPyObjectSteal(v_o);
|
||||||
stack_pointer[0] = v;
|
stack_pointer[0] = v;
|
||||||
|
|
|
||||||
|
|
@ -3706,6 +3706,7 @@ _PyImport_LoadLazyImportTstate(PyThreadState *tstate, PyObject *lazy_import)
|
||||||
{
|
{
|
||||||
PyObject *obj = NULL;
|
PyObject *obj = NULL;
|
||||||
PyObject *fromlist = NULL;
|
PyObject *fromlist = NULL;
|
||||||
|
PyObject *import_func = NULL;
|
||||||
assert(lazy_import != NULL);
|
assert(lazy_import != NULL);
|
||||||
assert(PyLazyImport_CheckExact(lazy_import));
|
assert(PyLazyImport_CheckExact(lazy_import));
|
||||||
|
|
||||||
|
|
@ -3723,7 +3724,7 @@ _PyImport_LoadLazyImportTstate(PyThreadState *tstate, PyObject *lazy_import)
|
||||||
}
|
}
|
||||||
|
|
||||||
int is_loading = PySet_Contains(importing, lazy_import);
|
int is_loading = PySet_Contains(importing, lazy_import);
|
||||||
if (is_loading < 0 ) {
|
if (is_loading < 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
} else if (is_loading == 1) {
|
} else if (is_loading == 1) {
|
||||||
PyObject *name = _PyLazyImport_GetName(lazy_import);
|
PyObject *name = _PyLazyImport_GetName(lazy_import);
|
||||||
|
|
@ -3766,9 +3767,12 @@ _PyImport_LoadLazyImportTstate(PyThreadState *tstate, PyObject *lazy_import)
|
||||||
|
|
||||||
PyObject *globals = PyEval_GetGlobals();
|
PyObject *globals = PyEval_GetGlobals();
|
||||||
|
|
||||||
|
if (PyMapping_GetOptionalItem(lz->lz_builtins, &_Py_ID(__import__), &import_func) < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
if (full) {
|
if (full) {
|
||||||
obj = _PyEval_ImportNameWithImport(tstate,
|
obj = _PyEval_ImportNameWithImport(tstate,
|
||||||
lz->lz_import_func,
|
import_func,
|
||||||
globals,
|
globals,
|
||||||
globals,
|
globals,
|
||||||
lz->lz_from,
|
lz->lz_from,
|
||||||
|
|
@ -3780,7 +3784,7 @@ _PyImport_LoadLazyImportTstate(PyThreadState *tstate, PyObject *lazy_import)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
obj = _PyEval_ImportNameWithImport(tstate,
|
obj = _PyEval_ImportNameWithImport(tstate,
|
||||||
lz->lz_import_func,
|
import_func,
|
||||||
globals,
|
globals,
|
||||||
globals,
|
globals,
|
||||||
name,
|
name,
|
||||||
|
|
@ -3788,7 +3792,6 @@ _PyImport_LoadLazyImportTstate(PyThreadState *tstate, PyObject *lazy_import)
|
||||||
_PyLong_GetZero());
|
_PyLong_GetZero());
|
||||||
Py_DECREF(name);
|
Py_DECREF(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (obj == NULL) {
|
if (obj == NULL) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
@ -3886,6 +3889,7 @@ _PyImport_LoadLazyImportTstate(PyThreadState *tstate, PyObject *lazy_import)
|
||||||
}
|
}
|
||||||
|
|
||||||
Py_XDECREF(fromlist);
|
Py_XDECREF(fromlist);
|
||||||
|
Py_XDECREF(import_func);
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4113,7 +4117,7 @@ get_mod_dict(PyObject *module)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
register_lazy_on_parent(PyThreadState *tstate, PyObject *name, PyObject *import_func)
|
register_lazy_on_parent(PyThreadState *tstate, PyObject *name, PyObject *builtins)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
PyObject *parent = NULL;
|
PyObject *parent = NULL;
|
||||||
|
|
@ -4183,7 +4187,7 @@ register_lazy_on_parent(PyThreadState *tstate, PyObject *name, PyObject *import_
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (PyDict_CheckExact(parent_dict) && !PyDict_Contains(parent_dict, child)) {
|
if (PyDict_CheckExact(parent_dict) && !PyDict_Contains(parent_dict, child)) {
|
||||||
PyObject *lazy_module_attr = _PyLazyImport_New(import_func, parent, child);
|
PyObject *lazy_module_attr = _PyLazyImport_New(builtins, parent, child);
|
||||||
if (lazy_module_attr == NULL) {
|
if (lazy_module_attr == NULL) {
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
@ -4211,7 +4215,7 @@ register_lazy_on_parent(PyThreadState *tstate, PyObject *name, PyObject *import_
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
_PyImport_LazyImportModuleLevelObject(PyThreadState *tstate,
|
_PyImport_LazyImportModuleLevelObject(PyThreadState *tstate,
|
||||||
PyObject *name, PyObject *import_func,
|
PyObject *name, PyObject *builtins,
|
||||||
PyObject *globals, PyObject *locals,
|
PyObject *globals, PyObject *locals,
|
||||||
PyObject *fromlist, int level)
|
PyObject *fromlist, int level)
|
||||||
{
|
{
|
||||||
|
|
@ -4221,7 +4225,7 @@ _PyImport_LazyImportModuleLevelObject(PyThreadState *tstate,
|
||||||
}
|
}
|
||||||
|
|
||||||
PyInterpreterState *interp = tstate->interp;
|
PyInterpreterState *interp = tstate->interp;
|
||||||
assert(frame->f_globals == frame->f_locals); // should only be called in global scope
|
assert(_PyEval_GetFrame()->f_globals == _PyEval_GetFrame()->f_locals); // should only be called in global scope
|
||||||
|
|
||||||
// Check if the filter disables the lazy import
|
// Check if the filter disables the lazy import
|
||||||
PyObject *filter = LAZY_IMPORTS_FILTER(interp);
|
PyObject *filter = LAZY_IMPORTS_FILTER(interp);
|
||||||
|
|
@ -4253,8 +4257,8 @@ _PyImport_LazyImportModuleLevelObject(PyThreadState *tstate,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *res = _PyLazyImport_New(import_func, abs_name, fromlist);
|
PyObject *res = _PyLazyImport_New(builtins, abs_name, fromlist);
|
||||||
if (register_lazy_on_parent(tstate, abs_name, import_func) < 0) {
|
if (register_lazy_on_parent(tstate, abs_name, builtins) < 0) {
|
||||||
Py_DECREF(res);
|
Py_DECREF(res);
|
||||||
res = NULL;
|
res = NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -5302,20 +5306,12 @@ _imp__set_lazy_attributes_impl(PyObject *module, PyObject *child_module,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
PyObject *builtins = _PyEval_GetBuiltins(tstate);
|
PyObject *builtins = _PyEval_GetBuiltins(tstate);
|
||||||
PyObject *import_func;
|
PyObject *lazy_module_attr = _PyLazyImport_New(builtins, name, attr_name);
|
||||||
if (PyMapping_GetOptionalItem(builtins, &_Py_ID(__import__), &import_func) < 0) {
|
|
||||||
goto error;
|
|
||||||
} else if (import_func == NULL) {
|
|
||||||
_PyErr_SetString(tstate, PyExc_ImportError, "__import__ not found");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyObject *lazy_module_attr = _PyLazyImport_New(import_func, name, attr_name);
|
|
||||||
if (lazy_module_attr == NULL) {
|
if (lazy_module_attr == NULL) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PyDict_SetItem(child_dict, attr_name, lazy_module_attr) < 0) {
|
if (_PyModule_ReplaceLazyValue(child_dict, attr_name, lazy_module_attr) < 0) {
|
||||||
Py_DECREF(lazy_module_attr);
|
Py_DECREF(lazy_module_attr);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
@ -5377,11 +5373,6 @@ imp_module_exec(PyObject *module)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PyModule_AddObjectRef(module, "lazy_import",
|
|
||||||
(PyObject *)&PyLazyImport_Type) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
#include "pycore_dict.h" // DICT_KEYS_UNICODE
|
#include "pycore_dict.h" // DICT_KEYS_UNICODE
|
||||||
#include "pycore_function.h" // _PyFunction_GetVersionForCurrentState()
|
#include "pycore_function.h" // _PyFunction_GetVersionForCurrentState()
|
||||||
#include "pycore_interpframe.h" // FRAME_SPECIALS_SIZE
|
#include "pycore_interpframe.h" // FRAME_SPECIALS_SIZE
|
||||||
|
#include "pycore_lazyimportobject.h" // PyLazyImport_CheckExact
|
||||||
#include "pycore_list.h" // _PyListIterObject
|
#include "pycore_list.h" // _PyListIterObject
|
||||||
#include "pycore_long.h" // _PyLong_IsNonNegativeCompact()
|
#include "pycore_long.h" // _PyLong_IsNonNegativeCompact()
|
||||||
#include "pycore_moduleobject.h"
|
#include "pycore_moduleobject.h"
|
||||||
|
|
@ -541,6 +542,7 @@ _PyCode_Quicken(_Py_CODEUNIT *instructions, Py_ssize_t size, int enable_counters
|
||||||
#define SPEC_FAIL_ATTR_BUILTIN_CLASS_METHOD 22
|
#define SPEC_FAIL_ATTR_BUILTIN_CLASS_METHOD 22
|
||||||
#define SPEC_FAIL_ATTR_CLASS_METHOD_OBJ 23
|
#define SPEC_FAIL_ATTR_CLASS_METHOD_OBJ 23
|
||||||
#define SPEC_FAIL_ATTR_OBJECT_SLOT 24
|
#define SPEC_FAIL_ATTR_OBJECT_SLOT 24
|
||||||
|
#define SPEC_FAIL_ATTR_MODULE_LAZY_VALUE 25
|
||||||
|
|
||||||
#define SPEC_FAIL_ATTR_INSTANCE_ATTRIBUTE 26
|
#define SPEC_FAIL_ATTR_INSTANCE_ATTRIBUTE 26
|
||||||
#define SPEC_FAIL_ATTR_METACLASS_ATTRIBUTE 27
|
#define SPEC_FAIL_ATTR_METACLASS_ATTRIBUTE 27
|
||||||
|
|
@ -797,6 +799,14 @@ specialize_module_load_attr_lock_held(PyDictObject *dict, _Py_CODEUNIT *instr, P
|
||||||
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS);
|
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
PyObject *value = NULL;
|
||||||
|
if (PyDict_GetItemRef((PyObject *)dict, name, &value) < 0 ||
|
||||||
|
(value != NULL && PyLazyImport_CheckExact(value))) {
|
||||||
|
Py_XDECREF(value);
|
||||||
|
SPECIALIZATION_FAIL(SPEC_FAIL_ATTR_MODULE_LAZY_VALUE, SPEC_FAIL_OUT_OF_VERSIONS);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
Py_XDECREF(value);
|
||||||
write_u32(cache->version, keys_version);
|
write_u32(cache->version, keys_version);
|
||||||
cache->index = (uint16_t)index;
|
cache->index = (uint16_t)index;
|
||||||
specialize(instr, LOAD_ATTR_MODULE);
|
specialize(instr, LOAD_ATTR_MODULE);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue