@@ -1735,6 +1735,55 @@ Past decisions that violated this principle of keeping core abstractions clean
17351735have caused significant pain in the CPython ecosystem, making optimization
17361736difficult and introducing subtle bugs.
17371737
1738+ Transforming lazy objects via ``__class__ `` mutation
1739+ ----------------------------------------------------
1740+
1741+ An alternative implementation approach was proposed where lazy import objects
1742+ would be transformed into their final form by mutating their internal state,
1743+ rather than replacing the object entirely. Under this approach, a lazy object
1744+ would be transformed in-place after the actual import completes.
1745+
1746+ This approach was rejected for several reasons:
1747+
1748+ 1. This technique could potentially work for module objects, but breaks down
1749+ completely for arbitrary objects imported via ``from `` statements. When a
1750+ user writes ``lazy from foo import bar ``, the object ``bar `` could be any
1751+ Python object (a function, class, constant, etc.), not just a module. Any
1752+ transformation approach would require that the lazy proxy object have
1753+ compatible memory layout and other considerations with the target object,
1754+ which is impossible to know before loading the module. This creates a
1755+ fundamental asymmetry where ``lazy import x `` and ``lazy from x import y ``
1756+ would require completely different implementation strategies, with the latter
1757+ still needing the proxy replacement mechanism.
1758+
1759+ 2. Even for module objects, the approach has fundamental limitations. Some
1760+ implementations substitute custom classes in ``sys.modules `` that inherit
1761+ from or replace the standard module type. These custom module classes can
1762+ have different memory layouts and sizes than ``PyModuleObject ``. The
1763+ transformation approach cannot work with such generic custom module
1764+ implementations, creating fragility and maintenance burden across the
1765+ ecosystem.
1766+
1767+ 3. While the transformation approach might appear simpler in some respects, this
1768+ is somewhat subjective. It introduces a bifurcated implementation: one path
1769+ for modules and a completely different path for non-module objects. Whether
1770+ this is simpler than a unified proxy mechanism depends on perspective and
1771+ implementation details.
1772+
1773+ 4. Any code holding a reference to the object before transformation will see a
1774+ different type after transformation. This can break code that checks object
1775+ types or relies on type stability, particularly C extensions that cache type
1776+ pointers or use ``PyObject_TypeCheck ``. The transformation also requires
1777+ careful coordination between the lazy import machinery and the type system to
1778+ ensure that the object remains valid throughout the transformation process.
1779+ The current proxy-based design avoids these issues by maintaining clear
1780+ boundaries between the lazy proxy and the actual imported object.
1781+
1782+ The current design, which uses object replacement through the ``LazyImportType ``
1783+ proxy pattern, provides a consistent mechanism that works uniformly for both
1784+ ``import `` and ``from ... import `` statements while maintaining cleaner
1785+ separation between the lazy import machinery and Python's core object model.
1786+
17381787Making ``lazy `` imports find the module without loading it
17391788----------------------------------------------------------
17401789
0 commit comments