@@ -917,6 +917,36 @@ If an error occurs during module loading (such as :exc:`ImportError` or
917917:exc: `SyntaxError `), it is raised at the point where the lazy import is first
918918used, not at the import statement itself.
919919
920+ Plain dotted lazy imports resolve the root package before their submodules,
921+ including when a custom :func: `__import__ ` hook is present. For example,
922+ ``lazy import pkg.a `` calls the hook with ``pkg `` on first use of ``pkg ``.
923+ Access to a pending ``pkg.a `` then calls the hook with ``pkg.a ``.
924+ For packages stored under their declared names, other declared submodules
925+ remain unresolved. Existing attributes are accessed normally. Aliased imports,
926+ such as ``lazy import pkg.a as a ``, still request the full module name.
927+
928+ The root uses the declaring namespace's builtins. A pending child uses the
929+ declaration whose builtins match the namespace that accesses it. If no
930+ declaration matches, Python uses the first namespace that declared that child.
931+ Custom hooks control the attributes of objects that they supply outside
932+ :data: `sys.modules `.
933+
934+ .. impl-detail ::
935+
936+ Assigning plain lazy placeholders to the same root name may merge their
937+ declaration metadata. This includes assignments from containers or namespace
938+ dictionaries and need not preserve placeholder identity.
939+
940+ Once a root resolves, its pending children retain their declaring builtins
941+ mappings. Private modules own this metadata and release it when collected.
942+
943+ Custom import hook exceptions propagate through optional attribute access,
944+ including :func: `hasattr ` and :func: `getattr ` with a default value.
945+
946+ Canonical modules under another name and non-packages retain full-path
947+ validation, so an invalid import such as ``lazy import math.pi `` still raises
948+ an exception.
949+
920950See :pep: `810 ` for the full specification of lazy imports.
921951
922952.. versionadded :: 3.15
0 commit comments