Lazy imports grammar / AST changes

This commit is contained in:
Dino Viehland 2025-09-16 15:10:28 -07:00
parent fb114cf497
commit 1c691ea756
25 changed files with 1016 additions and 338 deletions

113
Python/Python-ast.c generated
View file

@ -222,6 +222,7 @@ void _PyAST_Fini(PyInterpreterState *interp)
Py_CLEAR(state->id);
Py_CLEAR(state->ifs);
Py_CLEAR(state->is_async);
Py_CLEAR(state->is_lazy);
Py_CLEAR(state->items);
Py_CLEAR(state->iter);
Py_CLEAR(state->key);
@ -327,6 +328,7 @@ static int init_identifiers(struct ast_state *state)
if ((state->id = PyUnicode_InternFromString("id")) == NULL) return -1;
if ((state->ifs = PyUnicode_InternFromString("ifs")) == NULL) return -1;
if ((state->is_async = PyUnicode_InternFromString("is_async")) == NULL) return -1;
if ((state->is_lazy = PyUnicode_InternFromString("is_lazy")) == NULL) return -1;
if ((state->items = PyUnicode_InternFromString("items")) == NULL) return -1;
if ((state->iter = PyUnicode_InternFromString("iter")) == NULL) return -1;
if ((state->key = PyUnicode_InternFromString("key")) == NULL) return -1;
@ -527,11 +529,13 @@ static const char * const Assert_fields[]={
};
static const char * const Import_fields[]={
"names",
"is_lazy",
};
static const char * const ImportFrom_fields[]={
"module",
"names",
"level",
"is_lazy",
};
static const char * const Global_fields[]={
"names",
@ -2254,6 +2258,21 @@ add_ast_annotations(struct ast_state *state)
return 0;
}
}
{
PyObject *type = (PyObject *)&PyLong_Type;
type = _Py_union_type_or(type, Py_None);
cond = type != NULL;
if (!cond) {
Py_DECREF(Import_annotations);
return 0;
}
cond = PyDict_SetItemString(Import_annotations, "is_lazy", type) == 0;
Py_DECREF(type);
if (!cond) {
Py_DECREF(Import_annotations);
return 0;
}
}
cond = PyObject_SetAttrString(state->Import_type, "_field_types",
Import_annotations) == 0;
if (!cond) {
@ -2315,6 +2334,22 @@ add_ast_annotations(struct ast_state *state)
return 0;
}
}
{
PyObject *type = (PyObject *)&PyLong_Type;
type = _Py_union_type_or(type, Py_None);
cond = type != NULL;
if (!cond) {
Py_DECREF(ImportFrom_annotations);
return 0;
}
cond = PyDict_SetItemString(ImportFrom_annotations, "is_lazy", type) ==
0;
Py_DECREF(type);
if (!cond) {
Py_DECREF(ImportFrom_annotations);
return 0;
}
}
cond = PyObject_SetAttrString(state->ImportFrom_type, "_field_types",
ImportFrom_annotations) == 0;
if (!cond) {
@ -6218,8 +6253,8 @@ init_types(void *arg)
" | Try(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)\n"
" | TryStar(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)\n"
" | Assert(expr test, expr? msg)\n"
" | Import(alias* names)\n"
" | ImportFrom(identifier? module, alias* names, int? level)\n"
" | Import(alias* names, int? is_lazy)\n"
" | ImportFrom(identifier? module, alias* names, int? level, int? is_lazy)\n"
" | Global(identifier* names)\n"
" | Nonlocal(identifier* names)\n"
" | Expr(expr value)\n"
@ -6348,17 +6383,21 @@ init_types(void *arg)
if (PyObject_SetAttr(state->Assert_type, state->msg, Py_None) == -1)
return -1;
state->Import_type = make_type(state, "Import", state->stmt_type,
Import_fields, 1,
"Import(alias* names)");
Import_fields, 2,
"Import(alias* names, int? is_lazy)");
if (!state->Import_type) return -1;
if (PyObject_SetAttr(state->Import_type, state->is_lazy, Py_None) == -1)
return -1;
state->ImportFrom_type = make_type(state, "ImportFrom", state->stmt_type,
ImportFrom_fields, 3,
"ImportFrom(identifier? module, alias* names, int? level)");
ImportFrom_fields, 4,
"ImportFrom(identifier? module, alias* names, int? level, int? is_lazy)");
if (!state->ImportFrom_type) return -1;
if (PyObject_SetAttr(state->ImportFrom_type, state->module, Py_None) == -1)
return -1;
if (PyObject_SetAttr(state->ImportFrom_type, state->level, Py_None) == -1)
return -1;
if (PyObject_SetAttr(state->ImportFrom_type, state->is_lazy, Py_None) == -1)
return -1;
state->Global_type = make_type(state, "Global", state->stmt_type,
Global_fields, 1,
"Global(identifier* names)");
@ -7598,8 +7637,8 @@ _PyAST_Assert(expr_ty test, expr_ty msg, int lineno, int col_offset, int
}
stmt_ty
_PyAST_Import(asdl_alias_seq * names, int lineno, int col_offset, int
end_lineno, int end_col_offset, PyArena *arena)
_PyAST_Import(asdl_alias_seq * names, int is_lazy, int lineno, int col_offset,
int end_lineno, int end_col_offset, PyArena *arena)
{
stmt_ty p;
p = (stmt_ty)_PyArena_Malloc(arena, sizeof(*p));
@ -7607,6 +7646,7 @@ _PyAST_Import(asdl_alias_seq * names, int lineno, int col_offset, int
return NULL;
p->kind = Import_kind;
p->v.Import.names = names;
p->v.Import.is_lazy = is_lazy;
p->lineno = lineno;
p->col_offset = col_offset;
p->end_lineno = end_lineno;
@ -7616,8 +7656,8 @@ _PyAST_Import(asdl_alias_seq * names, int lineno, int col_offset, int
stmt_ty
_PyAST_ImportFrom(identifier module, asdl_alias_seq * names, int level, int
lineno, int col_offset, int end_lineno, int end_col_offset,
PyArena *arena)
is_lazy, int lineno, int col_offset, int end_lineno, int
end_col_offset, PyArena *arena)
{
stmt_ty p;
p = (stmt_ty)_PyArena_Malloc(arena, sizeof(*p));
@ -7627,6 +7667,7 @@ _PyAST_ImportFrom(identifier module, asdl_alias_seq * names, int level, int
p->v.ImportFrom.module = module;
p->v.ImportFrom.names = names;
p->v.ImportFrom.level = level;
p->v.ImportFrom.is_lazy = is_lazy;
p->lineno = lineno;
p->col_offset = col_offset;
p->end_lineno = end_lineno;
@ -9465,6 +9506,11 @@ ast2obj_stmt(struct ast_state *state, void* _o)
if (PyObject_SetAttr(result, state->names, value) == -1)
goto failed;
Py_DECREF(value);
value = ast2obj_int(state, o->v.Import.is_lazy);
if (!value) goto failed;
if (PyObject_SetAttr(result, state->is_lazy, value) == -1)
goto failed;
Py_DECREF(value);
break;
case ImportFrom_kind:
tp = (PyTypeObject *)state->ImportFrom_type;
@ -9486,6 +9532,11 @@ ast2obj_stmt(struct ast_state *state, void* _o)
if (PyObject_SetAttr(result, state->level, value) == -1)
goto failed;
Py_DECREF(value);
value = ast2obj_int(state, o->v.ImportFrom.is_lazy);
if (!value) goto failed;
if (PyObject_SetAttr(result, state->is_lazy, value) == -1)
goto failed;
Py_DECREF(value);
break;
case Global_kind:
tp = (PyTypeObject *)state->Global_type;
@ -13481,6 +13532,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
}
if (isinstance) {
asdl_alias_seq* names;
int is_lazy;
if (PyObject_GetOptionalAttr(obj, state->names, &tmp) < 0) {
return -1;
@ -13520,7 +13572,24 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
}
Py_CLEAR(tmp);
}
*out = _PyAST_Import(names, lineno, col_offset, end_lineno,
if (PyObject_GetOptionalAttr(obj, state->is_lazy, &tmp) < 0) {
return -1;
}
if (tmp == NULL || tmp == Py_None) {
Py_CLEAR(tmp);
is_lazy = 0;
}
else {
int res;
if (_Py_EnterRecursiveCall(" while traversing 'Import' node")) {
goto failed;
}
res = obj2ast_int(state, tmp, &is_lazy, arena);
_Py_LeaveRecursiveCall();
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
*out = _PyAST_Import(names, is_lazy, lineno, col_offset, end_lineno,
end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
@ -13534,6 +13603,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
identifier module;
asdl_alias_seq* names;
int level;
int is_lazy;
if (PyObject_GetOptionalAttr(obj, state->module, &tmp) < 0) {
return -1;
@ -13607,8 +13677,25 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
*out = _PyAST_ImportFrom(module, names, level, lineno, col_offset,
end_lineno, end_col_offset, arena);
if (PyObject_GetOptionalAttr(obj, state->is_lazy, &tmp) < 0) {
return -1;
}
if (tmp == NULL || tmp == Py_None) {
Py_CLEAR(tmp);
is_lazy = 0;
}
else {
int res;
if (_Py_EnterRecursiveCall(" while traversing 'ImportFrom' node")) {
goto failed;
}
res = obj2ast_int(state, tmp, &is_lazy, arena);
_Py_LeaveRecursiveCall();
if (res != 0) goto failed;
Py_CLEAR(tmp);
}
*out = _PyAST_ImportFrom(module, names, level, is_lazy, lineno,
col_offset, end_lineno, end_col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}

View file

@ -1758,6 +1758,13 @@ dummy_func(
}
ERROR_NO_POP();
}
if (PyLazyImport_CheckExact(v_o)) {
PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, v_o);
Py_DECREF(v_o);
v_o = l_v;
ERROR_IF(v_o == NULL);
}
}
else {
/* Slow-path if globals or builtins is not a dict */
@ -1775,6 +1782,12 @@ dummy_func(
ERROR_IF(true);
}
}
if (PyLazyImport_CheckExact(v_o)) {
PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, v_o);
Py_DECREF(v_o);
v_o = l_v;
ERROR_IF(v_o == NULL);
}
}
}
v = PyStackRef_FromPyObjectSteal(v_o);
@ -1784,6 +1797,13 @@ dummy_func(
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
PyObject *v_o = _PyEval_LoadName(tstate, frame, name);
ERROR_IF(v_o == NULL);
if (PyLazyImport_CheckExact(v_o)) {
PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, v_o);
Py_DECREF(v_o);
v_o = l_v;
ERROR_IF(v_o == NULL);
}
v = PyStackRef_FromPyObjectSteal(v_o);
}
@ -1809,7 +1829,18 @@ dummy_func(
op(_LOAD_GLOBAL, ( -- res[1])) {
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
_PyEval_LoadGlobalStackRef(GLOBALS(), BUILTINS(), name, res);
ERROR_IF(PyStackRef_IsNull(*res));
PyObject *res_o = PyStackRef_AsPyObjectBorrow(*res);
if (PyLazyImport_CheckExact(res_o)) {
PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, res_o);
Py_DECREF(res_o);
res_o = l_v;
PyStackRef_CLOSE(res[0]);
ERROR_IF(res_o == NULL);
*res = PyStackRef_FromPyObjectSteal(res_o);
}
}
op(_PUSH_NULL_CONDITIONAL, ( -- null[oparg & 1])) {
@ -2914,10 +2945,18 @@ dummy_func(
}
inst(IMPORT_NAME, (level, fromlist -- res)) {
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
PyObject *res_o = _PyEval_ImportName(tstate, frame, name,
PyStackRef_AsPyObjectBorrow(fromlist),
PyStackRef_AsPyObjectBorrow(level));
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2);
PyObject *res_o;
if (oparg & 0x01) {
res_o = _PyEval_LazyImportName(tstate, BUILTINS(), GLOBALS(), name,
PyStackRef_AsPyObjectBorrow(fromlist),
PyStackRef_AsPyObjectBorrow(level));
} else {
res_o = _PyEval_ImportName(tstate, BUILTINS(), GLOBALS(), LOCALS(), name,
PyStackRef_AsPyObjectBorrow(fromlist),
PyStackRef_AsPyObjectBorrow(level));
}
DECREF_INPUTS();
ERROR_IF(res_o == NULL);
res = PyStackRef_FromPyObjectSteal(res_o);
@ -2925,7 +2964,13 @@ dummy_func(
inst(IMPORT_FROM, (from -- from, res)) {
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
PyObject *res_o = _PyEval_ImportFrom(tstate, PyStackRef_AsPyObjectBorrow(from), name);
PyObject *res_o;
if (PyLazyImport_CheckExact(PyStackRef_AsPyObjectBorrow(from))) {
res_o = _PyEval_LazyImportFrom(tstate, PyStackRef_AsPyObjectBorrow(from), name);
} else {
res_o = _PyEval_ImportFrom(tstate, PyStackRef_AsPyObjectBorrow(from), name);
}
ERROR_IF(res_o == NULL);
res = PyStackRef_FromPyObjectSteal(res_o);
}

View file

@ -22,6 +22,7 @@
#include "pycore_interpolation.h" // _PyInterpolation_Build()
#include "pycore_intrinsics.h"
#include "pycore_jit.h"
#include "pycore_lazyimportobject.h"
#include "pycore_list.h" // _PyList_GetItemRef()
#include "pycore_long.h" // _PyLong_GetZero()
#include "pycore_moduleobject.h" // PyModuleObject
@ -2986,11 +2987,11 @@ _PyEval_SliceIndexNotNone(PyObject *v, Py_ssize_t *pi)
}
PyObject *
_PyEval_ImportName(PyThreadState *tstate, _PyInterpreterFrame *frame,
_PyEval_ImportName(PyThreadState *tstate, PyObject *builtins, PyObject *globals, PyObject *locals,
PyObject *name, PyObject *fromlist, PyObject *level)
{
PyObject *import_func;
if (PyMapping_GetOptionalItem(frame->f_builtins, &_Py_ID(__import__), &import_func) < 0) {
if (PyMapping_GetOptionalItem(builtins, &_Py_ID(__import__), &import_func) < 0) {
return NULL;
}
if (import_func == NULL) {
@ -2998,7 +2999,6 @@ _PyEval_ImportName(PyThreadState *tstate, _PyInterpreterFrame *frame,
return NULL;
}
PyObject *locals = frame->f_locals;
if (locals == NULL) {
locals = Py_None;
}
@ -3012,18 +3012,50 @@ _PyEval_ImportName(PyThreadState *tstate, _PyInterpreterFrame *frame,
}
return PyImport_ImportModuleLevelObject(
name,
frame->f_globals,
globals,
locals,
fromlist,
ilevel);
}
PyObject* args[5] = {name, frame->f_globals, locals, fromlist, level};
PyObject* args[5] = {name, globals, locals, fromlist, level};
PyObject *res = PyObject_Vectorcall(import_func, args, 5, NULL);
Py_DECREF(import_func);
return res;
}
PyObject *
_PyEval_LazyImportName(PyThreadState *tstate, PyObject *builtins, PyObject *globals,
PyObject *name, PyObject *fromlist, PyObject *level)
{
PyObject *res = NULL;
PyObject *abs_name = NULL;
int ilevel = PyLong_AsInt(level);
if (ilevel == -1 && PyErr_Occurred()) {
goto error;
}
if (ilevel > 0) {
abs_name = _PyImport_ResolveName(tstate, name, globals, ilevel);
if (abs_name == NULL) {
goto error;
}
} else { /* ilevel == 0 */
if (PyUnicode_GET_LENGTH(name) == 0) {
PyErr_SetString(PyExc_ValueError, "Empty module name");
goto error;
}
abs_name = name;
Py_INCREF(abs_name);
}
// TODO: check sys.modules for module
res = _PyLazyImport_New(builtins, abs_name, fromlist);
error:
Py_XDECREF(abs_name);
return res;
}
PyObject *
_PyEval_ImportFrom(PyThreadState *tstate, PyObject *v, PyObject *name)
{
@ -3192,6 +3224,33 @@ _PyEval_ImportFrom(PyThreadState *tstate, PyObject *v, PyObject *name)
return NULL;
}
PyObject *
_PyEval_LazyImportFrom(PyThreadState *tstate, PyObject *v, PyObject *name)
{
assert(PyLazyImport_CheckExact(v));
assert(name && PyUnicode_Check(name));
PyObject *ret;
PyLazyImportObject *d = (PyLazyImportObject *)v;
if (d->lz_attr != NULL) {
if (PyUnicode_Check(d->lz_attr)) {
PyObject *from = PyUnicode_FromFormat("%U.%U", d->lz_from, d->lz_attr);
ret = _PyLazyImport_New(d->lz_builtins, from, name);
Py_DECREF(from);
return ret;
}
} else {
Py_ssize_t dot = PyUnicode_FindChar(d->lz_from, '.', 0, PyUnicode_GET_LENGTH(d->lz_from), 1);
if (dot >= 0) {
PyObject *from = PyUnicode_Substring(d->lz_from, 0, dot);
ret = _PyLazyImport_New(d->lz_builtins, from, name);
Py_DECREF(from);
return ret;
}
}
ret = _PyLazyImport_New(d->lz_builtins, d->lz_from, name);
return ret;
}
#define CANNOT_CATCH_MSG "catching classes that do not inherit from "\
"BaseException is not allowed"

View file

@ -351,8 +351,8 @@ codegen_addop_o(compiler *c, location loc,
#define LOAD_ZERO_SUPER_METHOD -4
static int
codegen_addop_name(compiler *c, location loc,
int opcode, PyObject *dict, PyObject *o)
codegen_addop_name_custom(compiler *c, location loc,
int opcode, PyObject *dict, PyObject *o, int shift, int low)
{
PyObject *mangled = _PyCompile_MaybeMangle(c, o);
if (!mangled) {
@ -363,40 +363,51 @@ codegen_addop_name(compiler *c, location loc,
if (arg < 0) {
return ERROR;
}
ADDOP_I(c, loc, opcode, (arg << shift) | low);
return SUCCESS;
}
static int
codegen_addop_name(compiler *c, location loc,
int opcode, PyObject *dict, PyObject *o)
{
int shift = 0, low = 0;
if (opcode == LOAD_ATTR) {
arg <<= 1;
shift = 1;
}
if (opcode == LOAD_METHOD) {
opcode = LOAD_ATTR;
arg <<= 1;
arg |= 1;
shift = 1;
low = 1;
}
if (opcode == LOAD_SUPER_ATTR) {
arg <<= 2;
arg |= 2;
shift = 2;
low = 2;
}
if (opcode == LOAD_SUPER_METHOD) {
opcode = LOAD_SUPER_ATTR;
arg <<= 2;
arg |= 3;
shift = 2;
low = 3;
}
if (opcode == LOAD_ZERO_SUPER_ATTR) {
opcode = LOAD_SUPER_ATTR;
arg <<= 2;
shift = 2;
}
if (opcode == LOAD_ZERO_SUPER_METHOD) {
opcode = LOAD_SUPER_ATTR;
arg <<= 2;
arg |= 1;
shift = 2;
low = 1;
}
ADDOP_I(c, loc, opcode, arg);
return SUCCESS;
return codegen_addop_name_custom(c, loc, opcode, dict, o, shift, low);
}
#define ADDOP_NAME(C, LOC, OP, O, TYPE) \
RETURN_IF_ERROR(codegen_addop_name((C), (LOC), (OP), METADATA(C)->u_ ## TYPE, (O)))
static int
#define ADDOP_NAME_CUSTOM(C, LOC, OP, O, TYPE, SHIFT, LOW) \
RETURN_IF_ERROR(codegen_addop_name_custom((C), (LOC), (OP), METADATA(C)->u_ ## TYPE, (O), SHIFT, LOW))
static int
codegen_addop_j(instr_sequence *seq, location loc,
int opcode, jump_target_label target)
{
@ -2861,7 +2872,13 @@ codegen_import(compiler *c, stmt_ty s)
ADDOP_LOAD_CONST(c, loc, zero);
ADDOP_LOAD_CONST(c, loc, Py_None);
ADDOP_NAME(c, loc, IMPORT_NAME, alias->name, names);
if (s->v.Import.is_lazy) {
// TODO: SyntaxError when not in module scope
ADDOP_NAME_CUSTOM(c, loc, IMPORT_NAME, alias->name, names, 2, 1);
} else {
// TODO: If in try/except, set 2nd bit
ADDOP_NAME_CUSTOM(c, loc, IMPORT_NAME, alias->name, names, 2, 0);
}
if (alias->asname) {
r = codegen_import_as(c, loc, alias->name, alias->asname);
@ -2907,12 +2924,15 @@ codegen_from_import(compiler *c, stmt_ty s)
ADDOP_LOAD_CONST_NEW(c, LOC(s), names);
identifier from = &_Py_STR(empty);
if (s->v.ImportFrom.module) {
ADDOP_NAME(c, LOC(s), IMPORT_NAME, s->v.ImportFrom.module, names);
from = s->v.ImportFrom.module;
}
else {
_Py_DECLARE_STR(empty, "");
ADDOP_NAME(c, LOC(s), IMPORT_NAME, &_Py_STR(empty), names);
if (s->v.ImportFrom.is_lazy) {
// TODO: SyntaxError when not in module scope
ADDOP_NAME_CUSTOM(c, LOC(s), IMPORT_NAME, from, names, 2, 1);
} else {
ADDOP_NAME_CUSTOM(c, LOC(s), IMPORT_NAME, from, names, 2, 0);
}
for (Py_ssize_t i = 0; i < n; i++) {
alias_ty alias = (alias_ty)asdl_seq_GET(s->v.ImportFrom.names, i);

View file

@ -2458,6 +2458,16 @@
if (v_o == NULL) {
JUMP_TO_ERROR();
}
if (PyLazyImport_CheckExact(v_o)) {
_PyFrame_SetStackPointer(frame, stack_pointer);
PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, v_o);
Py_DECREF(v_o);
stack_pointer = _PyFrame_GetStackPointer(frame);
v_o = l_v;
if (v_o == NULL) {
JUMP_TO_ERROR();
}
}
v = PyStackRef_FromPyObjectSteal(v_o);
stack_pointer[0] = v;
stack_pointer += 1;
@ -2476,6 +2486,21 @@
if (PyStackRef_IsNull(*res)) {
JUMP_TO_ERROR();
}
PyObject *res_o = PyStackRef_AsPyObjectBorrow(*res);
if (PyLazyImport_CheckExact(res_o)) {
_PyFrame_SetStackPointer(frame, stack_pointer);
PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, res_o);
Py_DECREF(res_o);
stack_pointer = _PyFrame_GetStackPointer(frame);
res_o = l_v;
_PyFrame_SetStackPointer(frame, stack_pointer);
PyStackRef_CLOSE(res[0]);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (res_o == NULL) {
JUMP_TO_ERROR();
}
*res = PyStackRef_FromPyObjectSteal(res_o);
}
stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
break;
@ -4120,11 +4145,22 @@
oparg = CURRENT_OPARG();
fromlist = stack_pointer[-1];
level = stack_pointer[-2];
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2);
PyObject *res_o;
if (oparg & 0x01) {
_PyFrame_SetStackPointer(frame, stack_pointer);
res_o = _PyEval_LazyImportName(tstate, BUILTINS(), GLOBALS(), name,
PyStackRef_AsPyObjectBorrow(fromlist),
PyStackRef_AsPyObjectBorrow(level));
stack_pointer = _PyFrame_GetStackPointer(frame);
} else {
_PyFrame_SetStackPointer(frame, stack_pointer);
res_o = _PyEval_ImportName(tstate, BUILTINS(), GLOBALS(), LOCALS(), name,
PyStackRef_AsPyObjectBorrow(fromlist),
PyStackRef_AsPyObjectBorrow(level));
stack_pointer = _PyFrame_GetStackPointer(frame);
}
_PyFrame_SetStackPointer(frame, stack_pointer);
PyObject *res_o = _PyEval_ImportName(tstate, frame, name,
PyStackRef_AsPyObjectBorrow(fromlist),
PyStackRef_AsPyObjectBorrow(level));
_PyStackRef tmp = fromlist;
fromlist = PyStackRef_NULL;
stack_pointer[-1] = fromlist;
@ -4152,9 +4188,16 @@
oparg = CURRENT_OPARG();
from = stack_pointer[-1];
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
_PyFrame_SetStackPointer(frame, stack_pointer);
PyObject *res_o = _PyEval_ImportFrom(tstate, PyStackRef_AsPyObjectBorrow(from), name);
stack_pointer = _PyFrame_GetStackPointer(frame);
PyObject *res_o;
if (PyLazyImport_CheckExact(PyStackRef_AsPyObjectBorrow(from))) {
_PyFrame_SetStackPointer(frame, stack_pointer);
res_o = _PyEval_LazyImportFrom(tstate, PyStackRef_AsPyObjectBorrow(from), name);
stack_pointer = _PyFrame_GetStackPointer(frame);
} else {
_PyFrame_SetStackPointer(frame, stack_pointer);
res_o = _PyEval_ImportFrom(tstate, PyStackRef_AsPyObjectBorrow(from), name);
stack_pointer = _PyFrame_GetStackPointer(frame);
}
if (res_o == NULL) {
JUMP_TO_ERROR();
}

View file

@ -6188,9 +6188,16 @@
_PyStackRef res;
from = stack_pointer[-1];
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
_PyFrame_SetStackPointer(frame, stack_pointer);
PyObject *res_o = _PyEval_ImportFrom(tstate, PyStackRef_AsPyObjectBorrow(from), name);
stack_pointer = _PyFrame_GetStackPointer(frame);
PyObject *res_o;
if (PyLazyImport_CheckExact(PyStackRef_AsPyObjectBorrow(from))) {
_PyFrame_SetStackPointer(frame, stack_pointer);
res_o = _PyEval_LazyImportFrom(tstate, PyStackRef_AsPyObjectBorrow(from), name);
stack_pointer = _PyFrame_GetStackPointer(frame);
} else {
_PyFrame_SetStackPointer(frame, stack_pointer);
res_o = _PyEval_ImportFrom(tstate, PyStackRef_AsPyObjectBorrow(from), name);
stack_pointer = _PyFrame_GetStackPointer(frame);
}
if (res_o == NULL) {
JUMP_TO_LABEL(error);
}
@ -6214,11 +6221,22 @@
_PyStackRef res;
fromlist = stack_pointer[-1];
level = stack_pointer[-2];
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2);
PyObject *res_o;
if (oparg & 0x01) {
_PyFrame_SetStackPointer(frame, stack_pointer);
res_o = _PyEval_LazyImportName(tstate, BUILTINS(), GLOBALS(), name,
PyStackRef_AsPyObjectBorrow(fromlist),
PyStackRef_AsPyObjectBorrow(level));
stack_pointer = _PyFrame_GetStackPointer(frame);
} else {
_PyFrame_SetStackPointer(frame, stack_pointer);
res_o = _PyEval_ImportName(tstate, BUILTINS(), GLOBALS(), LOCALS(), name,
PyStackRef_AsPyObjectBorrow(fromlist),
PyStackRef_AsPyObjectBorrow(level));
stack_pointer = _PyFrame_GetStackPointer(frame);
}
_PyFrame_SetStackPointer(frame, stack_pointer);
PyObject *res_o = _PyEval_ImportName(tstate, frame, name,
PyStackRef_AsPyObjectBorrow(fromlist),
PyStackRef_AsPyObjectBorrow(level));
_PyStackRef tmp = fromlist;
fromlist = PyStackRef_NULL;
stack_pointer[-1] = fromlist;
@ -9074,6 +9092,16 @@
}
JUMP_TO_LABEL(error);
}
if (PyLazyImport_CheckExact(v_o)) {
_PyFrame_SetStackPointer(frame, stack_pointer);
PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, v_o);
Py_DECREF(v_o);
stack_pointer = _PyFrame_GetStackPointer(frame);
v_o = l_v;
if (v_o == NULL) {
JUMP_TO_LABEL(error);
}
}
}
else {
_PyFrame_SetStackPointer(frame, stack_pointer);
@ -9098,6 +9126,16 @@
JUMP_TO_LABEL(error);
}
}
if (PyLazyImport_CheckExact(v_o)) {
_PyFrame_SetStackPointer(frame, stack_pointer);
PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, v_o);
Py_DECREF(v_o);
stack_pointer = _PyFrame_GetStackPointer(frame);
v_o = l_v;
if (v_o == NULL) {
JUMP_TO_LABEL(error);
}
}
}
}
v = PyStackRef_FromPyObjectSteal(v_o);
@ -9150,6 +9188,21 @@
if (PyStackRef_IsNull(*res)) {
JUMP_TO_LABEL(error);
}
PyObject *res_o = PyStackRef_AsPyObjectBorrow(*res);
if (PyLazyImport_CheckExact(res_o)) {
_PyFrame_SetStackPointer(frame, stack_pointer);
PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, res_o);
Py_DECREF(res_o);
stack_pointer = _PyFrame_GetStackPointer(frame);
res_o = l_v;
_PyFrame_SetStackPointer(frame, stack_pointer);
PyStackRef_CLOSE(res[0]);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (res_o == NULL) {
JUMP_TO_LABEL(error);
}
*res = PyStackRef_FromPyObjectSteal(res_o);
}
}
// _PUSH_NULL_CONDITIONAL
{
@ -9350,6 +9403,16 @@
if (v_o == NULL) {
JUMP_TO_LABEL(error);
}
if (PyLazyImport_CheckExact(v_o)) {
_PyFrame_SetStackPointer(frame, stack_pointer);
PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, v_o);
Py_DECREF(v_o);
stack_pointer = _PyFrame_GetStackPointer(frame);
v_o = l_v;
if (v_o == NULL) {
JUMP_TO_LABEL(error);
}
}
v = PyStackRef_FromPyObjectSteal(v_o);
stack_pointer[0] = v;
stack_pointer += 1;

View file

@ -7,6 +7,8 @@
#include "pycore_import.h" // _PyImport_BootstrapImp()
#include "pycore_initconfig.h" // _PyStatus_OK()
#include "pycore_interp.h" // struct _import_runtime_state
#include "pycore_long.h" // _PyLong_GetZero
#include "pycore_lazyimportobject.h"
#include "pycore_magic_number.h" // PYC_MAGIC_NUMBER_TOKEN
#include "pycore_moduleobject.h" // _PyModule_GetDef()
#include "pycore_namespace.h" // _PyNamespace_Type
@ -3670,6 +3672,101 @@ resolve_name(PyThreadState *tstate, PyObject *name, PyObject *globals, int level
return NULL;
}
PyObject *
_PyImport_ResolveName(PyThreadState *tstate, PyObject *name, PyObject *globals, int level)
{
return resolve_name(tstate, name, globals, level);
}
PyObject *
_PyImport_LoadLazyImportTstate(PyThreadState *tstate, PyObject *lazy_import)
{
PyObject *obj = NULL;
PyObject *fromlist = NULL;
assert(lazy_import != NULL);
assert(PyLazyImport_CheckExact(lazy_import));
PyObject *state_dict = _PyThreadState_GetDict(tstate);
assert(state_dict != NULL);
PyLazyImportObject *lz = (PyLazyImportObject *)lazy_import;
Py_ssize_t dot = -1;
int full = 0;
if (lz->lz_attr != NULL) {
full = 1;
}
if (!full) {
dot = PyUnicode_FindChar(lz->lz_from, '.', 0, PyUnicode_GET_LENGTH(lz->lz_from), 1);
}
if (dot < 0) {
full = 1;
}
if (lz->lz_attr != NULL) {
if (PyUnicode_Check(lz->lz_attr)) {
fromlist = PyTuple_New(1);
if (fromlist == NULL) {
goto error;
}
Py_INCREF(lz->lz_attr);
PyTuple_SET_ITEM(fromlist, 0, lz->lz_attr);
} else {
Py_INCREF(lz->lz_attr);
fromlist = lz->lz_attr;
}
}
PyObject *globals = PyEval_GetGlobals();
if (full) {
obj = _PyEval_ImportName(tstate,
lz->lz_builtins,
globals,
globals,
lz->lz_from,
fromlist,
_PyLong_GetZero());
} else {
PyObject *name = PyUnicode_Substring(lz->lz_from, 0, dot);
if (name == NULL) {
goto error;
}
obj = _PyEval_ImportName(tstate,
lz->lz_builtins,
globals,
globals,
name,
fromlist,
_PyLong_GetZero());
Py_DECREF(name);
}
if (obj == NULL) {
goto error;
}
if (lz->lz_attr != NULL && PyUnicode_Check(lz->lz_attr)) {
PyObject *from = obj;
obj = _PyEval_ImportFrom(tstate, from, lz->lz_attr);
Py_DECREF(from);
if (obj == NULL) {
goto error;
}
}
assert(!PyLazyImport_CheckExact(obj));
goto ok;
error:
Py_XDECREF(obj);
obj = NULL;
ok:
Py_XDECREF(fromlist);
return obj;
}
static PyObject *
import_find_and_load(PyThreadState *tstate, PyObject *abs_name)
{