mirror of
https://github.com/python/cpython.git
synced 2025-12-08 06:10:17 +00:00
Lazy imports grammar / AST changes
This commit is contained in:
parent
fb114cf497
commit
1c691ea756
25 changed files with 1016 additions and 338 deletions
|
|
@ -121,9 +121,9 @@ simple_stmts[asdl_stmt_seq*]:
|
||||||
simple_stmt[stmt_ty] (memo):
|
simple_stmt[stmt_ty] (memo):
|
||||||
| assignment
|
| assignment
|
||||||
| &"type" type_alias
|
| &"type" type_alias
|
||||||
|
| &('import' | 'from' | "lazy" ) import_stmt
|
||||||
| e=star_expressions { _PyAST_Expr(e, EXTRA) }
|
| e=star_expressions { _PyAST_Expr(e, EXTRA) }
|
||||||
| &'return' return_stmt
|
| &'return' return_stmt
|
||||||
| &('import' | 'from') import_stmt
|
|
||||||
| &'raise' raise_stmt
|
| &'raise' raise_stmt
|
||||||
| &'pass' pass_stmt
|
| &'pass' pass_stmt
|
||||||
| &'del' del_stmt
|
| &'del' del_stmt
|
||||||
|
|
@ -216,7 +216,7 @@ assert_stmt[stmt_ty]:
|
||||||
| invalid_assert_stmt
|
| invalid_assert_stmt
|
||||||
| 'assert' a=expression b=[',' z=expression { z }] { _PyAST_Assert(a, b, EXTRA) }
|
| 'assert' a=expression b=[',' z=expression { z }] { _PyAST_Assert(a, b, EXTRA) }
|
||||||
|
|
||||||
import_stmt[stmt_ty]:
|
import_stmt[stmt_ty](memo):
|
||||||
| invalid_import
|
| invalid_import
|
||||||
| import_name
|
| import_name
|
||||||
| import_from
|
| import_from
|
||||||
|
|
@ -224,13 +224,16 @@ import_stmt[stmt_ty]:
|
||||||
# Import statements
|
# Import statements
|
||||||
# -----------------
|
# -----------------
|
||||||
|
|
||||||
import_name[stmt_ty]: 'import' a=dotted_as_names { _PyAST_Import(a, EXTRA) }
|
import_name[stmt_ty]:
|
||||||
|
| 'import' a=dotted_as_names { _PyAST_Import(a, 0, EXTRA) }
|
||||||
|
| "lazy" 'import' a=dotted_as_names { _PyAST_Import(a, 1, EXTRA) }
|
||||||
|
|
||||||
# note below: the ('.' | '...') is necessary because '...' is tokenized as ELLIPSIS
|
# note below: the ('.' | '...') is necessary because '...' is tokenized as ELLIPSIS
|
||||||
import_from[stmt_ty]:
|
import_from[stmt_ty]:
|
||||||
| 'from' a=('.' | '...')* b=dotted_name 'import' c=import_from_targets {
|
| lazy="lazy"? 'from' a=('.' | '...')* b=dotted_name 'import' c=import_from_targets {
|
||||||
_PyPegen_checked_future_import(p, b->v.Name.id, c, _PyPegen_seq_count_dots(a), EXTRA) }
|
_PyPegen_checked_future_import(p, b->v.Name.id, c, _PyPegen_seq_count_dots(a), lazy ? 1 : 0, EXTRA) }
|
||||||
| 'from' a=('.' | '...')+ 'import' b=import_from_targets {
|
| lazy="lazy"? 'from' a=('.' | '...')+ 'import' b=import_from_targets {
|
||||||
_PyAST_ImportFrom(NULL, b, _PyPegen_seq_count_dots(a), EXTRA) }
|
_PyAST_ImportFrom(NULL, b, _PyPegen_seq_count_dots(a), lazy ? 1 : 0, EXTRA) }
|
||||||
import_from_targets[asdl_alias_seq*]:
|
import_from_targets[asdl_alias_seq*]:
|
||||||
| '(' a=import_from_as_names [','] ')' { a }
|
| '(' a=import_from_as_names [','] ')' { a }
|
||||||
| import_from_as_names !','
|
| import_from_as_names !','
|
||||||
|
|
|
||||||
11
Include/internal/pycore_ast.h
generated
11
Include/internal/pycore_ast.h
generated
|
|
@ -329,12 +329,14 @@ struct _stmt {
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
asdl_alias_seq *names;
|
asdl_alias_seq *names;
|
||||||
|
int is_lazy;
|
||||||
} Import;
|
} Import;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
identifier module;
|
identifier module;
|
||||||
asdl_alias_seq *names;
|
asdl_alias_seq *names;
|
||||||
int level;
|
int level;
|
||||||
|
int is_lazy;
|
||||||
} ImportFrom;
|
} ImportFrom;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|
@ -764,11 +766,12 @@ stmt_ty _PyAST_TryStar(asdl_stmt_seq * body, asdl_excepthandler_seq * handlers,
|
||||||
end_col_offset, PyArena *arena);
|
end_col_offset, PyArena *arena);
|
||||||
stmt_ty _PyAST_Assert(expr_ty test, expr_ty msg, int lineno, int col_offset,
|
stmt_ty _PyAST_Assert(expr_ty test, expr_ty msg, int lineno, int col_offset,
|
||||||
int end_lineno, int end_col_offset, PyArena *arena);
|
int end_lineno, int end_col_offset, PyArena *arena);
|
||||||
stmt_ty _PyAST_Import(asdl_alias_seq * names, int lineno, int col_offset, int
|
stmt_ty _PyAST_Import(asdl_alias_seq * names, int is_lazy, int lineno, int
|
||||||
end_lineno, int end_col_offset, PyArena *arena);
|
col_offset, int end_lineno, int end_col_offset, PyArena
|
||||||
|
*arena);
|
||||||
stmt_ty _PyAST_ImportFrom(identifier module, asdl_alias_seq * names, int level,
|
stmt_ty _PyAST_ImportFrom(identifier module, asdl_alias_seq * names, int level,
|
||||||
int lineno, int col_offset, int end_lineno, int
|
int is_lazy, int lineno, int col_offset, int
|
||||||
end_col_offset, PyArena *arena);
|
end_lineno, int end_col_offset, PyArena *arena);
|
||||||
stmt_ty _PyAST_Global(asdl_identifier_seq * names, int lineno, int col_offset,
|
stmt_ty _PyAST_Global(asdl_identifier_seq * names, int lineno, int col_offset,
|
||||||
int end_lineno, int end_col_offset, PyArena *arena);
|
int end_lineno, int end_col_offset, PyArena *arena);
|
||||||
stmt_ty _PyAST_Nonlocal(asdl_identifier_seq * names, int lineno, int
|
stmt_ty _PyAST_Nonlocal(asdl_identifier_seq * names, int lineno, int
|
||||||
|
|
|
||||||
1
Include/internal/pycore_ast_state.h
generated
1
Include/internal/pycore_ast_state.h
generated
|
|
@ -205,6 +205,7 @@ struct ast_state {
|
||||||
PyObject *id;
|
PyObject *id;
|
||||||
PyObject *ifs;
|
PyObject *ifs;
|
||||||
PyObject *is_async;
|
PyObject *is_async;
|
||||||
|
PyObject *is_lazy;
|
||||||
PyObject *items;
|
PyObject *items;
|
||||||
PyObject *iter;
|
PyObject *iter;
|
||||||
PyObject *key;
|
PyObject *key;
|
||||||
|
|
|
||||||
|
|
@ -297,7 +297,11 @@ PyAPI_FUNC(void) _PyEval_FormatExcCheckArg(PyThreadState *tstate, PyObject *exc,
|
||||||
PyAPI_FUNC(void) _PyEval_FormatExcUnbound(PyThreadState *tstate, PyCodeObject *co, int oparg);
|
PyAPI_FUNC(void) _PyEval_FormatExcUnbound(PyThreadState *tstate, PyCodeObject *co, int oparg);
|
||||||
PyAPI_FUNC(void) _PyEval_FormatKwargsError(PyThreadState *tstate, PyObject *func, PyObject *kwargs);
|
PyAPI_FUNC(void) _PyEval_FormatKwargsError(PyThreadState *tstate, PyObject *func, PyObject *kwargs);
|
||||||
PyAPI_FUNC(PyObject *) _PyEval_ImportFrom(PyThreadState *, PyObject *, PyObject *);
|
PyAPI_FUNC(PyObject *) _PyEval_ImportFrom(PyThreadState *, PyObject *, PyObject *);
|
||||||
PyAPI_FUNC(PyObject *) _PyEval_ImportName(PyThreadState *, _PyInterpreterFrame *, PyObject *, PyObject *, PyObject *);
|
PyAPI_FUNC(PyObject *) _PyEval_LazyImportName(PyThreadState *tstate, PyObject *builtins, PyObject *globals,
|
||||||
|
PyObject *name, PyObject *fromlist, PyObject *level);
|
||||||
|
PyAPI_FUNC(PyObject *) _PyEval_LazyImportFrom(PyThreadState *tstate, PyObject *v, PyObject *name);
|
||||||
|
PyAPI_FUNC(PyObject *) _PyEval_ImportName(PyThreadState *tstate, PyObject *builtins, PyObject *globals, PyObject *locals,
|
||||||
|
PyObject *name, PyObject *fromlist, PyObject *level);
|
||||||
PyAPI_FUNC(PyObject *)_PyEval_MatchClass(PyThreadState *tstate, PyObject *subject, PyObject *type, Py_ssize_t nargs, PyObject *kwargs);
|
PyAPI_FUNC(PyObject *)_PyEval_MatchClass(PyThreadState *tstate, PyObject *subject, PyObject *type, Py_ssize_t nargs, PyObject *kwargs);
|
||||||
PyAPI_FUNC(PyObject *)_PyEval_MatchKeys(PyThreadState *tstate, PyObject *map, PyObject *keys);
|
PyAPI_FUNC(PyObject *)_PyEval_MatchKeys(PyThreadState *tstate, PyObject *map, PyObject *keys);
|
||||||
PyAPI_FUNC(void) _PyEval_MonitorRaise(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr);
|
PyAPI_FUNC(void) _PyEval_MonitorRaise(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr);
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,12 @@ extern int _PyImport_FixupBuiltin(
|
||||||
PyObject *modules
|
PyObject *modules
|
||||||
);
|
);
|
||||||
|
|
||||||
|
extern PyObject *
|
||||||
|
_PyImport_ResolveName(PyThreadState *tstate, PyObject *name, PyObject *globals, int level);
|
||||||
|
extern PyObject *
|
||||||
|
_PyImport_LoadLazyImportTstate(PyThreadState *tstate, PyObject *lazy_import);
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_DLOPEN
|
#ifdef HAVE_DLOPEN
|
||||||
# include <dlfcn.h> // RTLD_NOW, RTLD_LAZY
|
# include <dlfcn.h> // RTLD_NOW, RTLD_LAZY
|
||||||
# if HAVE_DECL_RTLD_NOW
|
# if HAVE_DECL_RTLD_NOW
|
||||||
|
|
|
||||||
29
Include/internal/pycore_lazyimportobject.h
Normal file
29
Include/internal/pycore_lazyimportobject.h
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
/* Copyright (c) Meta, Inc. and its affiliates. All Rights Reserved */
|
||||||
|
/* File added for Lazy Imports */
|
||||||
|
|
||||||
|
/* Lazy object interface */
|
||||||
|
|
||||||
|
#ifndef Py_LAZYIMPORTOBJECT_H
|
||||||
|
#define Py_LAZYIMPORTOBJECT_H
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PyAPI_DATA(PyTypeObject) PyLazyImport_Type;
|
||||||
|
#define PyLazyImport_CheckExact(op) Py_IS_TYPE((op), &PyLazyImport_Type)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PyObject_HEAD
|
||||||
|
PyObject *lz_builtins;
|
||||||
|
PyObject *lz_from;
|
||||||
|
PyObject *lz_attr;
|
||||||
|
} PyLazyImportObject;
|
||||||
|
|
||||||
|
|
||||||
|
PyAPI_FUNC(PyObject *) _PyLazyImport_GetName(PyObject *lazy_import);
|
||||||
|
PyAPI_FUNC(PyObject *) _PyLazyImport_New(PyObject *builtins, PyObject *from, PyObject *attr);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif /* !Py_LAZYIMPORTOBJECT_H */
|
||||||
|
|
@ -286,6 +286,7 @@ Known values:
|
||||||
Python 3.15a1 3653 (Fix handling of opcodes that may leave operands on the stack when optimizing LOAD_FAST)
|
Python 3.15a1 3653 (Fix handling of opcodes that may leave operands on the stack when optimizing LOAD_FAST)
|
||||||
Python 3.15a1 3654 (Fix missing exception handlers in logical expression)
|
Python 3.15a1 3654 (Fix missing exception handlers in logical expression)
|
||||||
Python 3.15a1 3655 (Fix miscompilation of some module-level annotations)
|
Python 3.15a1 3655 (Fix miscompilation of some module-level annotations)
|
||||||
|
Python 3.15a1 3656 Lazy imports IMPORT_NAME opcode changes
|
||||||
|
|
||||||
|
|
||||||
Python 3.16 will start with 3700
|
Python 3.16 will start with 3700
|
||||||
|
|
@ -299,7 +300,7 @@ PC/launcher.c must also be updated.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PYC_MAGIC_NUMBER 3655
|
#define PYC_MAGIC_NUMBER 3656
|
||||||
/* This is equivalent to converting PYC_MAGIC_NUMBER to 2 bytes
|
/* This is equivalent to converting PYC_MAGIC_NUMBER to 2 bytes
|
||||||
(little-endian) and then appending b'\r\n'. */
|
(little-endian) and then appending b'\r\n'. */
|
||||||
#define PYC_MAGIC_NUMBER_TOKEN \
|
#define PYC_MAGIC_NUMBER_TOKEN \
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@
|
||||||
FUNCTION_ATTR_FLAGS = ('defaults', 'kwdefaults', 'annotations', 'closure', 'annotate')
|
FUNCTION_ATTR_FLAGS = ('defaults', 'kwdefaults', 'annotations', 'closure', 'annotate')
|
||||||
|
|
||||||
ENTER_EXECUTOR = opmap['ENTER_EXECUTOR']
|
ENTER_EXECUTOR = opmap['ENTER_EXECUTOR']
|
||||||
|
IMPORT_NAME = opmap['IMPORT_NAME']
|
||||||
LOAD_GLOBAL = opmap['LOAD_GLOBAL']
|
LOAD_GLOBAL = opmap['LOAD_GLOBAL']
|
||||||
LOAD_SMALL_INT = opmap['LOAD_SMALL_INT']
|
LOAD_SMALL_INT = opmap['LOAD_SMALL_INT']
|
||||||
BINARY_OP = opmap['BINARY_OP']
|
BINARY_OP = opmap['BINARY_OP']
|
||||||
|
|
@ -601,6 +602,12 @@ def get_argval_argrepr(self, op, arg, offset):
|
||||||
argval, argrepr = _get_name_info(arg//4, get_name)
|
argval, argrepr = _get_name_info(arg//4, get_name)
|
||||||
if (arg & 1) and argrepr:
|
if (arg & 1) and argrepr:
|
||||||
argrepr = f"{argrepr} + NULL|self"
|
argrepr = f"{argrepr} + NULL|self"
|
||||||
|
elif deop == IMPORT_NAME:
|
||||||
|
argval, argrepr = _get_name_info(arg//4, get_name)
|
||||||
|
if (arg & 1) and argrepr:
|
||||||
|
argrepr = f"{argrepr} + lazy"
|
||||||
|
elif (arg & 2) and argrepr:
|
||||||
|
argrepr = f"{argrepr} + eager"
|
||||||
else:
|
else:
|
||||||
argval, argrepr = _get_name_info(arg, get_name)
|
argval, argrepr = _get_name_info(arg, get_name)
|
||||||
elif deop in hasjump or deop in hasexc:
|
elif deop in hasjump or deop in hasexc:
|
||||||
|
|
|
||||||
1
Lib/keyword.py
generated
1
Lib/keyword.py
generated
|
|
@ -56,6 +56,7 @@ kwlist = [
|
||||||
softkwlist = [
|
softkwlist = [
|
||||||
'_',
|
'_',
|
||||||
'case',
|
'case',
|
||||||
|
'lazy',
|
||||||
'match',
|
'match',
|
||||||
'type'
|
'type'
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -69,10 +69,10 @@ Module(body=[Try(body=[Pass()], handlers=[ExceptHandler(type=Name(...), name='ex
|
||||||
Module(body=[TryStar(body=[Pass()], handlers=[ExceptHandler(type=Name(...), name='exc', body=[Pass(...)])], orelse=[Pass()], finalbody=[Pass()])], type_ignores=[])
|
Module(body=[TryStar(body=[Pass()], handlers=[ExceptHandler(type=Name(...), name='exc', body=[Pass(...)])], orelse=[Pass()], finalbody=[Pass()])], type_ignores=[])
|
||||||
Module(body=[Assert(test=Name(id='v', ctx=Load(...)), msg=None)], type_ignores=[])
|
Module(body=[Assert(test=Name(id='v', ctx=Load(...)), msg=None)], type_ignores=[])
|
||||||
Module(body=[Assert(test=Name(id='v', ctx=Load(...)), msg=Constant(value='message', kind=None))], type_ignores=[])
|
Module(body=[Assert(test=Name(id='v', ctx=Load(...)), msg=Constant(value='message', kind=None))], type_ignores=[])
|
||||||
Module(body=[Import(names=[alias(name='sys', asname=None)])], type_ignores=[])
|
Module(body=[Import(names=[alias(name='sys', asname=None)], is_lazy=0)], type_ignores=[])
|
||||||
Module(body=[Import(names=[alias(name='foo', asname='bar')])], type_ignores=[])
|
Module(body=[Import(names=[alias(name='foo', asname='bar')], is_lazy=0)], type_ignores=[])
|
||||||
Module(body=[ImportFrom(module='sys', names=[alias(name='x', asname='y')], level=0)], type_ignores=[])
|
Module(body=[ImportFrom(module='sys', names=[alias(name='x', asname='y')], level=0, is_lazy=0)], type_ignores=[])
|
||||||
Module(body=[ImportFrom(module='sys', names=[alias(name='v', asname=None)], level=0)], type_ignores=[])
|
Module(body=[ImportFrom(module='sys', names=[alias(name='v', asname=None)], level=0, is_lazy=0)], type_ignores=[])
|
||||||
Module(body=[Global(names=['v'])], type_ignores=[])
|
Module(body=[Global(names=['v'])], type_ignores=[])
|
||||||
Module(body=[Expr(value=Constant(value=1, kind=None))], type_ignores=[])
|
Module(body=[Expr(value=Constant(value=1, kind=None))], type_ignores=[])
|
||||||
Module(body=[Pass()], type_ignores=[])
|
Module(body=[Pass()], type_ignores=[])
|
||||||
|
|
|
||||||
|
|
@ -1722,8 +1722,8 @@ def check_text(code, empty, full, **kwargs):
|
||||||
|
|
||||||
check_text(
|
check_text(
|
||||||
"import _ast as ast; from module import sub",
|
"import _ast as ast; from module import sub",
|
||||||
empty="Module(body=[Import(names=[alias(name='_ast', asname='ast')]), ImportFrom(module='module', names=[alias(name='sub')], level=0)])",
|
empty="Module(body=[Import(names=[alias(name='_ast', asname='ast')], is_lazy=0), ImportFrom(module='module', names=[alias(name='sub')], level=0, is_lazy=0)])",
|
||||||
full="Module(body=[Import(names=[alias(name='_ast', asname='ast')]), ImportFrom(module='module', names=[alias(name='sub')], level=0)], type_ignores=[])",
|
full="Module(body=[Import(names=[alias(name='_ast', asname='ast')], is_lazy=0), ImportFrom(module='module', names=[alias(name='sub')], level=0, is_lazy=0)], type_ignores=[])",
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_copy_location(self):
|
def test_copy_location(self):
|
||||||
|
|
|
||||||
|
|
@ -539,6 +539,7 @@ OBJECT_OBJS= \
|
||||||
Objects/funcobject.o \
|
Objects/funcobject.o \
|
||||||
Objects/interpolationobject.o \
|
Objects/interpolationobject.o \
|
||||||
Objects/iterobject.o \
|
Objects/iterobject.o \
|
||||||
|
Objects/lazyimportobject.o \
|
||||||
Objects/listobject.o \
|
Objects/listobject.o \
|
||||||
Objects/longobject.o \
|
Objects/longobject.o \
|
||||||
Objects/dictobject.o \
|
Objects/dictobject.o \
|
||||||
|
|
@ -1368,6 +1369,7 @@ PYTHON_HEADERS= \
|
||||||
$(srcdir)/Include/internal/pycore_interpolation.h \
|
$(srcdir)/Include/internal/pycore_interpolation.h \
|
||||||
$(srcdir)/Include/internal/pycore_intrinsics.h \
|
$(srcdir)/Include/internal/pycore_intrinsics.h \
|
||||||
$(srcdir)/Include/internal/pycore_jit.h \
|
$(srcdir)/Include/internal/pycore_jit.h \
|
||||||
|
$(srcdir)/Include/internal/pycore_lazyimportobject.h \
|
||||||
$(srcdir)/Include/internal/pycore_list.h \
|
$(srcdir)/Include/internal/pycore_list.h \
|
||||||
$(srcdir)/Include/internal/pycore_llist.h \
|
$(srcdir)/Include/internal/pycore_llist.h \
|
||||||
$(srcdir)/Include/internal/pycore_lock.h \
|
$(srcdir)/Include/internal/pycore_lock.h \
|
||||||
|
|
|
||||||
137
Objects/lazyimportobject.c
Normal file
137
Objects/lazyimportobject.c
Normal file
|
|
@ -0,0 +1,137 @@
|
||||||
|
/* Copyright (c) Meta, Inc. and its affiliates. All Rights Reserved */
|
||||||
|
/* File added for Lazy Imports */
|
||||||
|
|
||||||
|
/* Lazy object implementation */
|
||||||
|
|
||||||
|
#include "Python.h"
|
||||||
|
#include "pycore_lazyimportobject.h"
|
||||||
|
|
||||||
|
PyObject *
|
||||||
|
_PyLazyImport_New(PyObject *builtins, PyObject *from, PyObject *attr)
|
||||||
|
{
|
||||||
|
PyLazyImportObject *m;
|
||||||
|
if (!from || !PyUnicode_Check(from)) {
|
||||||
|
PyErr_BadArgument();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (attr == Py_None) {
|
||||||
|
attr = NULL;
|
||||||
|
}
|
||||||
|
assert(!attr || PyObject_IsTrue(attr));
|
||||||
|
m = PyObject_GC_New(PyLazyImportObject, &PyLazyImport_Type);
|
||||||
|
if (m == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
Py_XINCREF(builtins);
|
||||||
|
m->lz_builtins = builtins;
|
||||||
|
Py_INCREF(from);
|
||||||
|
m->lz_from = from;
|
||||||
|
Py_XINCREF(attr);
|
||||||
|
m->lz_attr = attr;
|
||||||
|
PyObject_GC_Track(m);
|
||||||
|
return (PyObject *)m;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
lazy_import_dealloc(PyLazyImportObject *m)
|
||||||
|
{
|
||||||
|
PyObject_GC_UnTrack(m);
|
||||||
|
Py_XDECREF(m->lz_builtins);
|
||||||
|
Py_XDECREF(m->lz_from);
|
||||||
|
Py_XDECREF(m->lz_attr);
|
||||||
|
Py_TYPE(m)->tp_free((PyObject *)m);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
lazy_import_name(PyLazyImportObject *m)
|
||||||
|
{
|
||||||
|
if (m->lz_attr != NULL) {
|
||||||
|
if (PyUnicode_Check(m->lz_attr)) {
|
||||||
|
return PyUnicode_FromFormat("%U.%U", m->lz_from, m->lz_attr);
|
||||||
|
} else {
|
||||||
|
return PyUnicode_FromFormat("%U...", m->lz_from);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Py_INCREF(m->lz_from);
|
||||||
|
return m->lz_from;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
lazy_import_repr(PyLazyImportObject *m)
|
||||||
|
{
|
||||||
|
PyObject *name = lazy_import_name(m);
|
||||||
|
if (name == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
PyObject *res = PyUnicode_FromFormat("<lazy_import '%U'>", name);
|
||||||
|
Py_DECREF(name);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
lazy_import_traverse(PyLazyImportObject *m, visitproc visit, void *arg)
|
||||||
|
{
|
||||||
|
Py_VISIT(m->lz_builtins);
|
||||||
|
Py_VISIT(m->lz_from);
|
||||||
|
Py_VISIT(m->lz_attr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
lazy_import_clear(PyLazyImportObject *m)
|
||||||
|
{
|
||||||
|
Py_CLEAR(m->lz_builtins);
|
||||||
|
Py_CLEAR(m->lz_from);
|
||||||
|
Py_CLEAR(m->lz_attr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *
|
||||||
|
_PyLazyImport_GetName(PyObject *lazy_import)
|
||||||
|
{
|
||||||
|
assert(PyLazyImport_CheckExact(lazy_import));
|
||||||
|
return lazy_import_name((PyLazyImportObject *)lazy_import);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyTypeObject PyLazyImport_Type = {
|
||||||
|
PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
||||||
|
"lazy_import", /* tp_name */
|
||||||
|
sizeof(PyLazyImportObject), /* tp_basicsize */
|
||||||
|
0, /* tp_itemsize */
|
||||||
|
(destructor)lazy_import_dealloc, /* tp_dealloc */
|
||||||
|
0, /* tp_print */
|
||||||
|
0, /* tp_getattr */
|
||||||
|
0, /* tp_setattr */
|
||||||
|
0, /* tp_reserved */
|
||||||
|
(reprfunc)lazy_import_repr, /* tp_repr */
|
||||||
|
0, /* tp_as_number */
|
||||||
|
0, /* tp_as_sequence */
|
||||||
|
0, /* tp_as_mapping */
|
||||||
|
0, /* tp_hash */
|
||||||
|
0, /* tp_call */
|
||||||
|
0, /* tp_str */
|
||||||
|
0, /* tp_getattro */
|
||||||
|
0, /* tp_setattro */
|
||||||
|
0, /* tp_as_buffer */
|
||||||
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
|
||||||
|
Py_TPFLAGS_BASETYPE, /* tp_flags */
|
||||||
|
0, /* tp_doc */
|
||||||
|
(traverseproc)lazy_import_traverse, /* tp_traverse */
|
||||||
|
(inquiry)lazy_import_clear, /* tp_clear */
|
||||||
|
0, /* tp_richcompare */
|
||||||
|
0, /* tp_weaklistoffset */
|
||||||
|
0, /* tp_iter */
|
||||||
|
0, /* tp_iternext */
|
||||||
|
0, /* tp_methods */
|
||||||
|
0, /* tp_members */
|
||||||
|
0, /* tp_getset */
|
||||||
|
0, /* tp_base */
|
||||||
|
0, /* tp_dict */
|
||||||
|
0, /* tp_descr_get */
|
||||||
|
0, /* tp_descr_set */
|
||||||
|
0, /* tp_dictoffset */
|
||||||
|
0, /* tp_init */
|
||||||
|
PyType_GenericAlloc, /* tp_alloc */
|
||||||
|
PyType_GenericNew, /* tp_new */
|
||||||
|
PyObject_GC_Del, /* tp_free */
|
||||||
|
};
|
||||||
|
|
@ -45,8 +45,8 @@ module Python
|
||||||
| TryStar(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)
|
| TryStar(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)
|
||||||
| Assert(expr test, expr? msg)
|
| Assert(expr test, expr? msg)
|
||||||
|
|
||||||
| Import(alias* names)
|
| Import(alias* names, int? is_lazy)
|
||||||
| ImportFrom(identifier? module, alias* names, int? level)
|
| ImportFrom(identifier? module, alias* names, int? level, int? is_lazy)
|
||||||
|
|
||||||
| Global(identifier* names)
|
| Global(identifier* names)
|
||||||
| Nonlocal(identifier* names)
|
| Nonlocal(identifier* names)
|
||||||
|
|
|
||||||
|
|
@ -1916,7 +1916,7 @@ _PyPegen_concatenate_strings(Parser *p, asdl_expr_seq *strings,
|
||||||
|
|
||||||
stmt_ty
|
stmt_ty
|
||||||
_PyPegen_checked_future_import(Parser *p, identifier module, asdl_alias_seq * names, int level,
|
_PyPegen_checked_future_import(Parser *p, identifier module, asdl_alias_seq * names, int level,
|
||||||
int lineno, int col_offset, int end_lineno, int end_col_offset,
|
int is_lazy, int lineno, int col_offset, int end_lineno, int end_col_offset,
|
||||||
PyArena *arena) {
|
PyArena *arena) {
|
||||||
if (level == 0 && PyUnicode_CompareWithASCIIString(module, "__future__") == 0) {
|
if (level == 0 && PyUnicode_CompareWithASCIIString(module, "__future__") == 0) {
|
||||||
for (Py_ssize_t i = 0; i < asdl_seq_LEN(names); i++) {
|
for (Py_ssize_t i = 0; i < asdl_seq_LEN(names); i++) {
|
||||||
|
|
@ -1926,7 +1926,7 @@ _PyPegen_checked_future_import(Parser *p, identifier module, asdl_alias_seq * na
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return _PyAST_ImportFrom(module, names, level, lineno, col_offset, end_lineno, end_col_offset, arena);
|
return _PyAST_ImportFrom(module, names, level, is_lazy, lineno, col_offset, end_lineno, end_col_offset, arena);
|
||||||
}
|
}
|
||||||
|
|
||||||
asdl_stmt_seq*
|
asdl_stmt_seq*
|
||||||
|
|
|
||||||
582
Parser/parser.c
generated
582
Parser/parser.c
generated
File diff suppressed because it is too large
Load diff
|
|
@ -366,7 +366,7 @@ void *_PyPegen_arguments_parsing_error(Parser *, expr_ty);
|
||||||
expr_ty _PyPegen_get_last_comprehension_item(comprehension_ty comprehension);
|
expr_ty _PyPegen_get_last_comprehension_item(comprehension_ty comprehension);
|
||||||
void *_PyPegen_nonparen_genexp_in_call(Parser *p, expr_ty args, asdl_comprehension_seq *comprehensions);
|
void *_PyPegen_nonparen_genexp_in_call(Parser *p, expr_ty args, asdl_comprehension_seq *comprehensions);
|
||||||
stmt_ty _PyPegen_checked_future_import(Parser *p, identifier module, asdl_alias_seq *,
|
stmt_ty _PyPegen_checked_future_import(Parser *p, identifier module, asdl_alias_seq *,
|
||||||
int , int, int , int , int , PyArena *);
|
int , int, int , int , int , int, PyArena *);
|
||||||
asdl_stmt_seq* _PyPegen_register_stmts(Parser *p, asdl_stmt_seq* stmts);
|
asdl_stmt_seq* _PyPegen_register_stmts(Parser *p, asdl_stmt_seq* stmts);
|
||||||
stmt_ty _PyPegen_register_stmt(Parser *p, stmt_ty s);
|
stmt_ty _PyPegen_register_stmt(Parser *p, stmt_ty s);
|
||||||
|
|
||||||
|
|
|
||||||
2
Programs/test_frozenmain.h
generated
2
Programs/test_frozenmain.h
generated
|
|
@ -2,7 +2,7 @@
|
||||||
unsigned char M_test_frozenmain[] = {
|
unsigned char M_test_frozenmain[] = {
|
||||||
227,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,
|
227,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,
|
||||||
0,0,0,0,0,243,184,0,0,0,128,0,94,0,82,1,
|
0,0,0,0,0,243,184,0,0,0,128,0,94,0,82,1,
|
||||||
73,0,116,0,94,0,82,1,73,1,116,1,93,2,33,0,
|
73,0,116,0,94,0,82,1,73,4,116,1,93,2,33,0,
|
||||||
82,2,52,1,0,0,0,0,0,0,31,0,93,2,33,0,
|
82,2,52,1,0,0,0,0,0,0,31,0,93,2,33,0,
|
||||||
82,3,93,0,80,6,0,0,0,0,0,0,0,0,0,0,
|
82,3,93,0,80,6,0,0,0,0,0,0,0,0,0,0,
|
||||||
0,0,0,0,0,0,0,0,52,2,0,0,0,0,0,0,
|
0,0,0,0,0,0,0,0,52,2,0,0,0,0,0,0,
|
||||||
|
|
|
||||||
113
Python/Python-ast.c
generated
113
Python/Python-ast.c
generated
|
|
@ -222,6 +222,7 @@ void _PyAST_Fini(PyInterpreterState *interp)
|
||||||
Py_CLEAR(state->id);
|
Py_CLEAR(state->id);
|
||||||
Py_CLEAR(state->ifs);
|
Py_CLEAR(state->ifs);
|
||||||
Py_CLEAR(state->is_async);
|
Py_CLEAR(state->is_async);
|
||||||
|
Py_CLEAR(state->is_lazy);
|
||||||
Py_CLEAR(state->items);
|
Py_CLEAR(state->items);
|
||||||
Py_CLEAR(state->iter);
|
Py_CLEAR(state->iter);
|
||||||
Py_CLEAR(state->key);
|
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->id = PyUnicode_InternFromString("id")) == NULL) return -1;
|
||||||
if ((state->ifs = PyUnicode_InternFromString("ifs")) == 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_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->items = PyUnicode_InternFromString("items")) == NULL) return -1;
|
||||||
if ((state->iter = PyUnicode_InternFromString("iter")) == NULL) return -1;
|
if ((state->iter = PyUnicode_InternFromString("iter")) == NULL) return -1;
|
||||||
if ((state->key = PyUnicode_InternFromString("key")) == 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[]={
|
static const char * const Import_fields[]={
|
||||||
"names",
|
"names",
|
||||||
|
"is_lazy",
|
||||||
};
|
};
|
||||||
static const char * const ImportFrom_fields[]={
|
static const char * const ImportFrom_fields[]={
|
||||||
"module",
|
"module",
|
||||||
"names",
|
"names",
|
||||||
"level",
|
"level",
|
||||||
|
"is_lazy",
|
||||||
};
|
};
|
||||||
static const char * const Global_fields[]={
|
static const char * const Global_fields[]={
|
||||||
"names",
|
"names",
|
||||||
|
|
@ -2254,6 +2258,21 @@ add_ast_annotations(struct ast_state *state)
|
||||||
return 0;
|
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",
|
cond = PyObject_SetAttrString(state->Import_type, "_field_types",
|
||||||
Import_annotations) == 0;
|
Import_annotations) == 0;
|
||||||
if (!cond) {
|
if (!cond) {
|
||||||
|
|
@ -2315,6 +2334,22 @@ add_ast_annotations(struct ast_state *state)
|
||||||
return 0;
|
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",
|
cond = PyObject_SetAttrString(state->ImportFrom_type, "_field_types",
|
||||||
ImportFrom_annotations) == 0;
|
ImportFrom_annotations) == 0;
|
||||||
if (!cond) {
|
if (!cond) {
|
||||||
|
|
@ -6218,8 +6253,8 @@ init_types(void *arg)
|
||||||
" | Try(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)\n"
|
" | Try(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)\n"
|
||||||
" | TryStar(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"
|
" | Assert(expr test, expr? msg)\n"
|
||||||
" | Import(alias* names)\n"
|
" | Import(alias* names, int? is_lazy)\n"
|
||||||
" | ImportFrom(identifier? module, alias* names, int? level)\n"
|
" | ImportFrom(identifier? module, alias* names, int? level, int? is_lazy)\n"
|
||||||
" | Global(identifier* names)\n"
|
" | Global(identifier* names)\n"
|
||||||
" | Nonlocal(identifier* names)\n"
|
" | Nonlocal(identifier* names)\n"
|
||||||
" | Expr(expr value)\n"
|
" | Expr(expr value)\n"
|
||||||
|
|
@ -6348,17 +6383,21 @@ init_types(void *arg)
|
||||||
if (PyObject_SetAttr(state->Assert_type, state->msg, Py_None) == -1)
|
if (PyObject_SetAttr(state->Assert_type, state->msg, Py_None) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
state->Import_type = make_type(state, "Import", state->stmt_type,
|
state->Import_type = make_type(state, "Import", state->stmt_type,
|
||||||
Import_fields, 1,
|
Import_fields, 2,
|
||||||
"Import(alias* names)");
|
"Import(alias* names, int? is_lazy)");
|
||||||
if (!state->Import_type) return -1;
|
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,
|
state->ImportFrom_type = make_type(state, "ImportFrom", state->stmt_type,
|
||||||
ImportFrom_fields, 3,
|
ImportFrom_fields, 4,
|
||||||
"ImportFrom(identifier? module, alias* names, int? level)");
|
"ImportFrom(identifier? module, alias* names, int? level, int? is_lazy)");
|
||||||
if (!state->ImportFrom_type) return -1;
|
if (!state->ImportFrom_type) return -1;
|
||||||
if (PyObject_SetAttr(state->ImportFrom_type, state->module, Py_None) == -1)
|
if (PyObject_SetAttr(state->ImportFrom_type, state->module, Py_None) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
if (PyObject_SetAttr(state->ImportFrom_type, state->level, Py_None) == -1)
|
if (PyObject_SetAttr(state->ImportFrom_type, state->level, Py_None) == -1)
|
||||||
return -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,
|
state->Global_type = make_type(state, "Global", state->stmt_type,
|
||||||
Global_fields, 1,
|
Global_fields, 1,
|
||||||
"Global(identifier* names)");
|
"Global(identifier* names)");
|
||||||
|
|
@ -7598,8 +7637,8 @@ _PyAST_Assert(expr_ty test, expr_ty msg, int lineno, int col_offset, int
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt_ty
|
stmt_ty
|
||||||
_PyAST_Import(asdl_alias_seq * names, int lineno, int col_offset, int
|
_PyAST_Import(asdl_alias_seq * names, int is_lazy, int lineno, int col_offset,
|
||||||
end_lineno, int end_col_offset, PyArena *arena)
|
int end_lineno, int end_col_offset, PyArena *arena)
|
||||||
{
|
{
|
||||||
stmt_ty p;
|
stmt_ty p;
|
||||||
p = (stmt_ty)_PyArena_Malloc(arena, sizeof(*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;
|
return NULL;
|
||||||
p->kind = Import_kind;
|
p->kind = Import_kind;
|
||||||
p->v.Import.names = names;
|
p->v.Import.names = names;
|
||||||
|
p->v.Import.is_lazy = is_lazy;
|
||||||
p->lineno = lineno;
|
p->lineno = lineno;
|
||||||
p->col_offset = col_offset;
|
p->col_offset = col_offset;
|
||||||
p->end_lineno = end_lineno;
|
p->end_lineno = end_lineno;
|
||||||
|
|
@ -7616,8 +7656,8 @@ _PyAST_Import(asdl_alias_seq * names, int lineno, int col_offset, int
|
||||||
|
|
||||||
stmt_ty
|
stmt_ty
|
||||||
_PyAST_ImportFrom(identifier module, asdl_alias_seq * names, int level, int
|
_PyAST_ImportFrom(identifier module, asdl_alias_seq * names, int level, int
|
||||||
lineno, int col_offset, int end_lineno, int end_col_offset,
|
is_lazy, int lineno, int col_offset, int end_lineno, int
|
||||||
PyArena *arena)
|
end_col_offset, PyArena *arena)
|
||||||
{
|
{
|
||||||
stmt_ty p;
|
stmt_ty p;
|
||||||
p = (stmt_ty)_PyArena_Malloc(arena, sizeof(*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.module = module;
|
||||||
p->v.ImportFrom.names = names;
|
p->v.ImportFrom.names = names;
|
||||||
p->v.ImportFrom.level = level;
|
p->v.ImportFrom.level = level;
|
||||||
|
p->v.ImportFrom.is_lazy = is_lazy;
|
||||||
p->lineno = lineno;
|
p->lineno = lineno;
|
||||||
p->col_offset = col_offset;
|
p->col_offset = col_offset;
|
||||||
p->end_lineno = end_lineno;
|
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)
|
if (PyObject_SetAttr(result, state->names, value) == -1)
|
||||||
goto failed;
|
goto failed;
|
||||||
Py_DECREF(value);
|
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;
|
break;
|
||||||
case ImportFrom_kind:
|
case ImportFrom_kind:
|
||||||
tp = (PyTypeObject *)state->ImportFrom_type;
|
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)
|
if (PyObject_SetAttr(result, state->level, value) == -1)
|
||||||
goto failed;
|
goto failed;
|
||||||
Py_DECREF(value);
|
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;
|
break;
|
||||||
case Global_kind:
|
case Global_kind:
|
||||||
tp = (PyTypeObject *)state->Global_type;
|
tp = (PyTypeObject *)state->Global_type;
|
||||||
|
|
@ -13481,6 +13532,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
|
||||||
}
|
}
|
||||||
if (isinstance) {
|
if (isinstance) {
|
||||||
asdl_alias_seq* names;
|
asdl_alias_seq* names;
|
||||||
|
int is_lazy;
|
||||||
|
|
||||||
if (PyObject_GetOptionalAttr(obj, state->names, &tmp) < 0) {
|
if (PyObject_GetOptionalAttr(obj, state->names, &tmp) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -13520,7 +13572,24 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
|
||||||
}
|
}
|
||||||
Py_CLEAR(tmp);
|
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);
|
end_col_offset, arena);
|
||||||
if (*out == NULL) goto failed;
|
if (*out == NULL) goto failed;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -13534,6 +13603,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
|
||||||
identifier module;
|
identifier module;
|
||||||
asdl_alias_seq* names;
|
asdl_alias_seq* names;
|
||||||
int level;
|
int level;
|
||||||
|
int is_lazy;
|
||||||
|
|
||||||
if (PyObject_GetOptionalAttr(obj, state->module, &tmp) < 0) {
|
if (PyObject_GetOptionalAttr(obj, state->module, &tmp) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -13607,8 +13677,25 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*
|
||||||
if (res != 0) goto failed;
|
if (res != 0) goto failed;
|
||||||
Py_CLEAR(tmp);
|
Py_CLEAR(tmp);
|
||||||
}
|
}
|
||||||
*out = _PyAST_ImportFrom(module, names, level, lineno, col_offset,
|
if (PyObject_GetOptionalAttr(obj, state->is_lazy, &tmp) < 0) {
|
||||||
end_lineno, end_col_offset, arena);
|
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;
|
if (*out == NULL) goto failed;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1758,6 +1758,13 @@ dummy_func(
|
||||||
}
|
}
|
||||||
ERROR_NO_POP();
|
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 {
|
else {
|
||||||
/* Slow-path if globals or builtins is not a dict */
|
/* Slow-path if globals or builtins is not a dict */
|
||||||
|
|
@ -1775,6 +1782,12 @@ dummy_func(
|
||||||
ERROR_IF(true);
|
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);
|
v = PyStackRef_FromPyObjectSteal(v_o);
|
||||||
|
|
@ -1784,6 +1797,13 @@ dummy_func(
|
||||||
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
|
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
|
||||||
PyObject *v_o = _PyEval_LoadName(tstate, frame, name);
|
PyObject *v_o = _PyEval_LoadName(tstate, frame, name);
|
||||||
ERROR_IF(v_o == NULL);
|
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);
|
v = PyStackRef_FromPyObjectSteal(v_o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1809,7 +1829,18 @@ dummy_func(
|
||||||
op(_LOAD_GLOBAL, ( -- res[1])) {
|
op(_LOAD_GLOBAL, ( -- res[1])) {
|
||||||
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
|
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
|
||||||
_PyEval_LoadGlobalStackRef(GLOBALS(), BUILTINS(), name, res);
|
_PyEval_LoadGlobalStackRef(GLOBALS(), BUILTINS(), name, res);
|
||||||
|
|
||||||
ERROR_IF(PyStackRef_IsNull(*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])) {
|
op(_PUSH_NULL_CONDITIONAL, ( -- null[oparg & 1])) {
|
||||||
|
|
@ -2914,10 +2945,18 @@ dummy_func(
|
||||||
}
|
}
|
||||||
|
|
||||||
inst(IMPORT_NAME, (level, fromlist -- res)) {
|
inst(IMPORT_NAME, (level, fromlist -- res)) {
|
||||||
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
|
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2);
|
||||||
PyObject *res_o = _PyEval_ImportName(tstate, frame, name,
|
PyObject *res_o;
|
||||||
PyStackRef_AsPyObjectBorrow(fromlist),
|
if (oparg & 0x01) {
|
||||||
PyStackRef_AsPyObjectBorrow(level));
|
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();
|
DECREF_INPUTS();
|
||||||
ERROR_IF(res_o == NULL);
|
ERROR_IF(res_o == NULL);
|
||||||
res = PyStackRef_FromPyObjectSteal(res_o);
|
res = PyStackRef_FromPyObjectSteal(res_o);
|
||||||
|
|
@ -2925,7 +2964,13 @@ dummy_func(
|
||||||
|
|
||||||
inst(IMPORT_FROM, (from -- from, res)) {
|
inst(IMPORT_FROM, (from -- from, res)) {
|
||||||
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
|
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);
|
ERROR_IF(res_o == NULL);
|
||||||
res = PyStackRef_FromPyObjectSteal(res_o);
|
res = PyStackRef_FromPyObjectSteal(res_o);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
#include "pycore_interpolation.h" // _PyInterpolation_Build()
|
#include "pycore_interpolation.h" // _PyInterpolation_Build()
|
||||||
#include "pycore_intrinsics.h"
|
#include "pycore_intrinsics.h"
|
||||||
#include "pycore_jit.h"
|
#include "pycore_jit.h"
|
||||||
|
#include "pycore_lazyimportobject.h"
|
||||||
#include "pycore_list.h" // _PyList_GetItemRef()
|
#include "pycore_list.h" // _PyList_GetItemRef()
|
||||||
#include "pycore_long.h" // _PyLong_GetZero()
|
#include "pycore_long.h" // _PyLong_GetZero()
|
||||||
#include "pycore_moduleobject.h" // PyModuleObject
|
#include "pycore_moduleobject.h" // PyModuleObject
|
||||||
|
|
@ -2986,11 +2987,11 @@ _PyEval_SliceIndexNotNone(PyObject *v, Py_ssize_t *pi)
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
_PyEval_ImportName(PyThreadState *tstate, _PyInterpreterFrame *frame,
|
_PyEval_ImportName(PyThreadState *tstate, PyObject *builtins, PyObject *globals, PyObject *locals,
|
||||||
PyObject *name, PyObject *fromlist, PyObject *level)
|
PyObject *name, PyObject *fromlist, PyObject *level)
|
||||||
{
|
{
|
||||||
PyObject *import_func;
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (import_func == NULL) {
|
if (import_func == NULL) {
|
||||||
|
|
@ -2998,7 +2999,6 @@ _PyEval_ImportName(PyThreadState *tstate, _PyInterpreterFrame *frame,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *locals = frame->f_locals;
|
|
||||||
if (locals == NULL) {
|
if (locals == NULL) {
|
||||||
locals = Py_None;
|
locals = Py_None;
|
||||||
}
|
}
|
||||||
|
|
@ -3012,18 +3012,50 @@ _PyEval_ImportName(PyThreadState *tstate, _PyInterpreterFrame *frame,
|
||||||
}
|
}
|
||||||
return PyImport_ImportModuleLevelObject(
|
return PyImport_ImportModuleLevelObject(
|
||||||
name,
|
name,
|
||||||
frame->f_globals,
|
globals,
|
||||||
locals,
|
locals,
|
||||||
fromlist,
|
fromlist,
|
||||||
ilevel);
|
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);
|
PyObject *res = PyObject_Vectorcall(import_func, args, 5, NULL);
|
||||||
Py_DECREF(import_func);
|
Py_DECREF(import_func);
|
||||||
return res;
|
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 *
|
PyObject *
|
||||||
_PyEval_ImportFrom(PyThreadState *tstate, PyObject *v, PyObject *name)
|
_PyEval_ImportFrom(PyThreadState *tstate, PyObject *v, PyObject *name)
|
||||||
{
|
{
|
||||||
|
|
@ -3192,6 +3224,33 @@ _PyEval_ImportFrom(PyThreadState *tstate, PyObject *v, PyObject *name)
|
||||||
return NULL;
|
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 "\
|
#define CANNOT_CATCH_MSG "catching classes that do not inherit from "\
|
||||||
"BaseException is not allowed"
|
"BaseException is not allowed"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -351,8 +351,8 @@ codegen_addop_o(compiler *c, location loc,
|
||||||
#define LOAD_ZERO_SUPER_METHOD -4
|
#define LOAD_ZERO_SUPER_METHOD -4
|
||||||
|
|
||||||
static int
|
static int
|
||||||
codegen_addop_name(compiler *c, location loc,
|
codegen_addop_name_custom(compiler *c, location loc,
|
||||||
int opcode, PyObject *dict, PyObject *o)
|
int opcode, PyObject *dict, PyObject *o, int shift, int low)
|
||||||
{
|
{
|
||||||
PyObject *mangled = _PyCompile_MaybeMangle(c, o);
|
PyObject *mangled = _PyCompile_MaybeMangle(c, o);
|
||||||
if (!mangled) {
|
if (!mangled) {
|
||||||
|
|
@ -363,40 +363,51 @@ codegen_addop_name(compiler *c, location loc,
|
||||||
if (arg < 0) {
|
if (arg < 0) {
|
||||||
return ERROR;
|
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) {
|
if (opcode == LOAD_ATTR) {
|
||||||
arg <<= 1;
|
shift = 1;
|
||||||
}
|
}
|
||||||
if (opcode == LOAD_METHOD) {
|
if (opcode == LOAD_METHOD) {
|
||||||
opcode = LOAD_ATTR;
|
opcode = LOAD_ATTR;
|
||||||
arg <<= 1;
|
shift = 1;
|
||||||
arg |= 1;
|
low = 1;
|
||||||
}
|
}
|
||||||
if (opcode == LOAD_SUPER_ATTR) {
|
if (opcode == LOAD_SUPER_ATTR) {
|
||||||
arg <<= 2;
|
shift = 2;
|
||||||
arg |= 2;
|
low = 2;
|
||||||
}
|
}
|
||||||
if (opcode == LOAD_SUPER_METHOD) {
|
if (opcode == LOAD_SUPER_METHOD) {
|
||||||
opcode = LOAD_SUPER_ATTR;
|
opcode = LOAD_SUPER_ATTR;
|
||||||
arg <<= 2;
|
shift = 2;
|
||||||
arg |= 3;
|
low = 3;
|
||||||
}
|
}
|
||||||
if (opcode == LOAD_ZERO_SUPER_ATTR) {
|
if (opcode == LOAD_ZERO_SUPER_ATTR) {
|
||||||
opcode = LOAD_SUPER_ATTR;
|
opcode = LOAD_SUPER_ATTR;
|
||||||
arg <<= 2;
|
shift = 2;
|
||||||
}
|
}
|
||||||
if (opcode == LOAD_ZERO_SUPER_METHOD) {
|
if (opcode == LOAD_ZERO_SUPER_METHOD) {
|
||||||
opcode = LOAD_SUPER_ATTR;
|
opcode = LOAD_SUPER_ATTR;
|
||||||
arg <<= 2;
|
shift = 2;
|
||||||
arg |= 1;
|
low = 1;
|
||||||
}
|
}
|
||||||
ADDOP_I(c, loc, opcode, arg);
|
return codegen_addop_name_custom(c, loc, opcode, dict, o, shift, low);
|
||||||
return SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ADDOP_NAME(C, LOC, OP, O, TYPE) \
|
#define ADDOP_NAME(C, LOC, OP, O, TYPE) \
|
||||||
RETURN_IF_ERROR(codegen_addop_name((C), (LOC), (OP), METADATA(C)->u_ ## TYPE, (O)))
|
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,
|
codegen_addop_j(instr_sequence *seq, location loc,
|
||||||
int opcode, jump_target_label target)
|
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, zero);
|
||||||
ADDOP_LOAD_CONST(c, loc, Py_None);
|
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) {
|
if (alias->asname) {
|
||||||
r = codegen_import_as(c, loc, alias->name, 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);
|
ADDOP_LOAD_CONST_NEW(c, LOC(s), names);
|
||||||
|
|
||||||
|
identifier from = &_Py_STR(empty);
|
||||||
if (s->v.ImportFrom.module) {
|
if (s->v.ImportFrom.module) {
|
||||||
ADDOP_NAME(c, LOC(s), IMPORT_NAME, s->v.ImportFrom.module, names);
|
from = s->v.ImportFrom.module;
|
||||||
}
|
}
|
||||||
else {
|
if (s->v.ImportFrom.is_lazy) {
|
||||||
_Py_DECLARE_STR(empty, "");
|
// TODO: SyntaxError when not in module scope
|
||||||
ADDOP_NAME(c, LOC(s), IMPORT_NAME, &_Py_STR(empty), names);
|
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++) {
|
for (Py_ssize_t i = 0; i < n; i++) {
|
||||||
alias_ty alias = (alias_ty)asdl_seq_GET(s->v.ImportFrom.names, i);
|
alias_ty alias = (alias_ty)asdl_seq_GET(s->v.ImportFrom.names, i);
|
||||||
|
|
|
||||||
57
Python/executor_cases.c.h
generated
57
Python/executor_cases.c.h
generated
|
|
@ -2458,6 +2458,16 @@
|
||||||
if (v_o == NULL) {
|
if (v_o == NULL) {
|
||||||
JUMP_TO_ERROR();
|
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);
|
v = PyStackRef_FromPyObjectSteal(v_o);
|
||||||
stack_pointer[0] = v;
|
stack_pointer[0] = v;
|
||||||
stack_pointer += 1;
|
stack_pointer += 1;
|
||||||
|
|
@ -2476,6 +2486,21 @@
|
||||||
if (PyStackRef_IsNull(*res)) {
|
if (PyStackRef_IsNull(*res)) {
|
||||||
JUMP_TO_ERROR();
|
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;
|
stack_pointer += 1;
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
break;
|
break;
|
||||||
|
|
@ -4120,11 +4145,22 @@
|
||||||
oparg = CURRENT_OPARG();
|
oparg = CURRENT_OPARG();
|
||||||
fromlist = stack_pointer[-1];
|
fromlist = stack_pointer[-1];
|
||||||
level = stack_pointer[-2];
|
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);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
PyObject *res_o = _PyEval_ImportName(tstate, frame, name,
|
|
||||||
PyStackRef_AsPyObjectBorrow(fromlist),
|
|
||||||
PyStackRef_AsPyObjectBorrow(level));
|
|
||||||
_PyStackRef tmp = fromlist;
|
_PyStackRef tmp = fromlist;
|
||||||
fromlist = PyStackRef_NULL;
|
fromlist = PyStackRef_NULL;
|
||||||
stack_pointer[-1] = fromlist;
|
stack_pointer[-1] = fromlist;
|
||||||
|
|
@ -4152,9 +4188,16 @@
|
||||||
oparg = CURRENT_OPARG();
|
oparg = CURRENT_OPARG();
|
||||||
from = stack_pointer[-1];
|
from = stack_pointer[-1];
|
||||||
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
|
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
PyObject *res_o;
|
||||||
PyObject *res_o = _PyEval_ImportFrom(tstate, PyStackRef_AsPyObjectBorrow(from), name);
|
if (PyLazyImport_CheckExact(PyStackRef_AsPyObjectBorrow(from))) {
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
_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) {
|
if (res_o == NULL) {
|
||||||
JUMP_TO_ERROR();
|
JUMP_TO_ERROR();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
77
Python/generated_cases.c.h
generated
77
Python/generated_cases.c.h
generated
|
|
@ -6188,9 +6188,16 @@
|
||||||
_PyStackRef res;
|
_PyStackRef res;
|
||||||
from = stack_pointer[-1];
|
from = stack_pointer[-1];
|
||||||
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
|
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
PyObject *res_o;
|
||||||
PyObject *res_o = _PyEval_ImportFrom(tstate, PyStackRef_AsPyObjectBorrow(from), name);
|
if (PyLazyImport_CheckExact(PyStackRef_AsPyObjectBorrow(from))) {
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
_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) {
|
if (res_o == NULL) {
|
||||||
JUMP_TO_LABEL(error);
|
JUMP_TO_LABEL(error);
|
||||||
}
|
}
|
||||||
|
|
@ -6214,11 +6221,22 @@
|
||||||
_PyStackRef res;
|
_PyStackRef res;
|
||||||
fromlist = stack_pointer[-1];
|
fromlist = stack_pointer[-1];
|
||||||
level = stack_pointer[-2];
|
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);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
PyObject *res_o = _PyEval_ImportName(tstate, frame, name,
|
|
||||||
PyStackRef_AsPyObjectBorrow(fromlist),
|
|
||||||
PyStackRef_AsPyObjectBorrow(level));
|
|
||||||
_PyStackRef tmp = fromlist;
|
_PyStackRef tmp = fromlist;
|
||||||
fromlist = PyStackRef_NULL;
|
fromlist = PyStackRef_NULL;
|
||||||
stack_pointer[-1] = fromlist;
|
stack_pointer[-1] = fromlist;
|
||||||
|
|
@ -9074,6 +9092,16 @@
|
||||||
}
|
}
|
||||||
JUMP_TO_LABEL(error);
|
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 {
|
else {
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
|
|
@ -9098,6 +9126,16 @@
|
||||||
JUMP_TO_LABEL(error);
|
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);
|
v = PyStackRef_FromPyObjectSteal(v_o);
|
||||||
|
|
@ -9150,6 +9188,21 @@
|
||||||
if (PyStackRef_IsNull(*res)) {
|
if (PyStackRef_IsNull(*res)) {
|
||||||
JUMP_TO_LABEL(error);
|
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
|
// _PUSH_NULL_CONDITIONAL
|
||||||
{
|
{
|
||||||
|
|
@ -9350,6 +9403,16 @@
|
||||||
if (v_o == NULL) {
|
if (v_o == NULL) {
|
||||||
JUMP_TO_LABEL(error);
|
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);
|
v = PyStackRef_FromPyObjectSteal(v_o);
|
||||||
stack_pointer[0] = v;
|
stack_pointer[0] = v;
|
||||||
stack_pointer += 1;
|
stack_pointer += 1;
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@
|
||||||
#include "pycore_import.h" // _PyImport_BootstrapImp()
|
#include "pycore_import.h" // _PyImport_BootstrapImp()
|
||||||
#include "pycore_initconfig.h" // _PyStatus_OK()
|
#include "pycore_initconfig.h" // _PyStatus_OK()
|
||||||
#include "pycore_interp.h" // struct _import_runtime_state
|
#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_magic_number.h" // PYC_MAGIC_NUMBER_TOKEN
|
||||||
#include "pycore_moduleobject.h" // _PyModule_GetDef()
|
#include "pycore_moduleobject.h" // _PyModule_GetDef()
|
||||||
#include "pycore_namespace.h" // _PyNamespace_Type
|
#include "pycore_namespace.h" // _PyNamespace_Type
|
||||||
|
|
@ -3670,6 +3672,101 @@ resolve_name(PyThreadState *tstate, PyObject *name, PyObject *globals, int level
|
||||||
return NULL;
|
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 *
|
static PyObject *
|
||||||
import_find_and_load(PyThreadState *tstate, PyObject *abs_name)
|
import_find_and_load(PyThreadState *tstate, PyObject *abs_name)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue