1616typedef struct {
1717 PyObject_HEAD
1818 PyObject * lz_builtins ; // Roots own the mapping; projections retain the root.
19- // A root stores its absolute name and original fromlist. A projection
20- // stores its source placeholder and the attribute to import from it.
19+ // A root stores its absolute name (PyUnicode) in lz_from, and original
20+ // fromlist in lz_attr.
21+ // A projection stores its source placeholder (a PyLazyImportObject)
22+ // in lz_from, and the attribute to import from (PyUnicode) it in lz_attr.
2123 PyObject * lz_from ;
2224 PyObject * lz_attr ;
2325 // Declaration location.
@@ -45,9 +47,18 @@ _PyLazyImport_New(_PyInterpreterFrame *frame, PyObject *builtins,
4547 "lazy_import: fromlist must be None, a string, or a tuple" );
4648 return NULL ;
4749 }
48- assert (PyLazyImport_CheckExact (name ) ? builtins == NULL : builtins != NULL );
49- assert (!PyLazyImport_CheckExact (name ) ||
50- (fromlist != NULL && PyUnicode_Check (fromlist )));
50+ #ifndef NDEBUG
51+ if (PyLazyImport_CheckExact (name )) {
52+ // projection
53+ assert (builtins == NULL );
54+ assert (fromlist != NULL );
55+ assert (PyUnicode_Check (fromlist ));
56+ }
57+ else {
58+ // root
59+ assert (builtins != NULL );
60+ }
61+ #endif
5162 PyLazyImportObject * m = PyObject_GC_New (
5263 PyLazyImportObject , & PyLazyImport_Type );
5364 if (m == NULL ) {
@@ -71,6 +82,7 @@ _PyLazyImport_New(_PyInterpreterFrame *frame, PyObject *builtins,
7182
7283// Reuse concrete attributes of initialized modules without waiting for imports
7384// or resolving lazy attributes. Failed cache lookups are retried at resolution.
85+ // May return NULL with or without an exception set.
7486static PyObject *
7587lazy_import_get_loaded_attr (PyThreadState * tstate , PyObject * name ,
7688 PyObject * attr_name )
@@ -466,6 +478,7 @@ _PyImport_LoadLazyImportTstate(PyThreadState *tstate, PyObject *lazy_import)
466478
467479// Loading pkg.child can replace a placeholder in pkg.child with the module
468480// before a from-import retrieves the value that belongs in that binding.
481+ // This is an optimization that can be safely skipped.
469482static int
470483lazy_import_replace_child (PyThreadState * tstate , PyObject * placeholder ,
471484 PyObject * name , PyObject * namespace ,
@@ -563,7 +576,7 @@ lazy_import_resolve(PyObject *self, PyObject *args)
563576static PyMethodDef lazy_import_methods [] = {
564577 {
565578 "resolve" , lazy_import_resolve , METH_NOARGS ,
566- PyDoc_STR ("resolves the lazy import and returns the actual object" )
579+ PyDoc_STR ("Resolve the lazy import and return the imported object. " )
567580 },
568581 {NULL , NULL }
569582};
0 commit comments