Skip to content

Commit ad578bc

Browse files
committed
gh-152298: Fix LazyImportType resolve reification
1 parent 6713576 commit ad578bc

13 files changed

Lines changed: 1226 additions & 86 deletions

File tree

Doc/library/types.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,16 @@ Standard names are defined for the following types:
350350
actually accessed. This type can be used to detect lazy imports
351351
programmatically.
352352

353+
.. method:: resolve()
354+
355+
Resolve the lazy import and return the imported object. Successful
356+
resolutions are cached.
357+
358+
For a module-level lazy import, ``resolve()`` also updates the original
359+
module global if that name still refers to this proxy. If the name was
360+
deleted or rebound, it is left unchanged; later ``resolve()`` calls return
361+
the cached object without updating that name.
362+
353363
.. versionadded:: 3.15
354364

355365
.. seealso:: :pep:`810`

Include/internal/pycore_lazyimportobject.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,44 @@ typedef struct {
1919
PyObject *lz_builtins;
2020
PyObject *lz_from;
2121
PyObject *lz_attr;
22+
// Protected by the import lock. lz_owner_* records the first module
23+
// global that resolve() may replace. Pending owners are being stored;
24+
// finalized owners cannot be claimed again.
25+
PyObject *lz_owner_globals;
26+
PyObject *lz_owner_key;
27+
PyObject *lz_resolved;
2228
// Frame information for the original import location.
2329
PyCodeObject *lz_code; // Code object where the lazy import was created.
30+
int lz_owner_pending;
31+
int lz_owner_finalized;
2432
int lz_instr_offset; // Instruction offset where the lazy import was created.
2533
} PyLazyImportObject;
2634

2735

2836
PyAPI_FUNC(PyObject *) _PyLazyImport_GetName(PyObject *lazy_import);
2937
PyAPI_FUNC(PyObject *) _PyLazyImport_New(
3038
struct _PyInterpreterFrame *frame, PyObject *import_func, PyObject *from, PyObject *attr);
39+
PyAPI_FUNC(int) _PyLazyImport_BindGlobal(
40+
PyThreadState *tstate,
41+
PyObject *lazy_import,
42+
PyObject *globals,
43+
PyObject *name);
44+
PyAPI_FUNC(void) _PyLazyImport_FinishGlobalBinding(
45+
PyThreadState *tstate,
46+
PyObject *lazy_import,
47+
PyObject *globals,
48+
PyObject *name,
49+
int stored);
50+
PyAPI_FUNC(int) _PyLazyImport_CommitIfCurrent(
51+
PyThreadState *tstate,
52+
PyObject *lazy_import,
53+
PyObject *globals,
54+
PyObject *name,
55+
PyObject *resolved);
56+
PyAPI_FUNC(int) _PyLazyImport_CommitStoredIfCurrent(
57+
PyThreadState *tstate,
58+
PyObject *lazy_import,
59+
PyObject *resolved);
3160

3261
#ifdef __cplusplus
3362
}

0 commit comments

Comments
 (0)