Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions peps/pep-0810.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1735,6 +1735,55 @@ Past decisions that violated this principle of keeping core abstractions clean
have caused significant pain in the CPython ecosystem, making optimization
difficult and introducing subtle bugs.

Transforming lazy objects via ``__class__`` mutation
----------------------------------------------------

An alternative implementation approach was proposed where lazy import objects
would be transformed into their final form by mutating their internal state,
rather than replacing the object entirely. Under this approach, a lazy object
would be transformed in-place after the actual import completes.

This approach was rejected for several reasons:

1. This technique could potentially work for module objects, but breaks down
completely for arbitrary objects imported via ``from`` statements. When a
user writes ``lazy from foo import bar``, the object ``bar`` could be any
Python object (a function, class, constant, etc.), not just a module. Any
transformation approach would require that the lazy proxy object have
compatible memory layout and other considerations with the target object,
which is impossible to know before loading the module. This creates a
fundamental asymmetry where ``lazy import x`` and ``lazy from x import y``
would require completely different implementation strategies, with the latter
still needing the proxy replacement mechanism.

2. Even for module objects, the approach has fundamental limitations. Some
implementations substitute custom classes in ``sys.modules`` that inherit
from or replace the standard module type. These custom module classes can
have different memory layouts and sizes than ``PyModuleObject``. The
transformation approach cannot work with such generic custom module
implementations, creating fragility and maintenance burden across the
ecosystem.

3. While the transformation approach might appear simpler in some respects, this
is somewhat subjective. It introduces a bifurcated implementation: one path
for modules and a completely different path for non-module objects. Whether
this is simpler than a unified proxy mechanism depends on perspective and
implementation details.

4. Any code holding a reference to the object before transformation will see a
different type after transformation. This can break code that checks object
types or relies on type stability, particularly C extensions that cache type
pointers or use ``PyObject_TypeCheck``. The transformation also requires
careful coordination between the lazy import machinery and the type system to
ensure that the object remains valid throughout the transformation process.
The current proxy-based design avoids these issues by maintaining clear
boundaries between the lazy proxy and the actual imported object.

The current design, which uses object replacement through the ``LazyImportType``
proxy pattern, provides a consistent mechanism that works uniformly for both
``import`` and ``from ... import`` statements while maintaining cleaner
separation between the lazy import machinery and Python's core object model.

Making ``lazy`` imports find the module without loading it
----------------------------------------------------------

Expand Down