Skip to content

Commit 1572241

Browse files
committed
Reflow and reformat to stick to PEP 7's line length limit in most places,
and prefer using `//` for comments instead of `/* */`.
1 parent 3a535de commit 1572241

26 files changed

+338
-228
lines changed

Doc/library/sys.rst

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -916,9 +916,11 @@ always available. Unless explicitly noted otherwise, all variables are read-only
916916

917917
Returns the current lazy imports mode as a string.
918918

919-
* ``"normal"``: Only imports explicitly marked with the ``lazy`` keyword are lazy
919+
* ``"normal"``: Only imports explicitly marked with the ``lazy`` keyword
920+
are lazy
920921
* ``"all"``: All top-level imports are potentially lazy
921-
* ``"none"``: All lazy imports are suppressed (even explicitly marked ones)
922+
* ``"none"``: All lazy imports are suppressed (even explicitly marked
923+
ones)
922924

923925
See also :func:`set_lazy_imports` and :pep:`810`.
924926

@@ -927,23 +929,25 @@ always available. Unless explicitly noted otherwise, all variables are read-only
927929

928930
.. function:: get_lazy_imports_filter()
929931

930-
Returns the current lazy imports filter function, or ``None`` if no filter
931-
is set.
932+
Returns the current lazy imports filter function, or ``None`` if no
933+
filter is set.
932934

933-
The filter function is called for every potentially lazy import to determine
934-
whether it should actually be lazy. See :func:`set_lazy_imports_filter` for
935-
details on the filter function signature.
935+
The filter function is called for every potentially lazy import to
936+
determine whether it should actually be lazy. See
937+
:func:`set_lazy_imports_filter` for details on the filter function
938+
signature.
936939

937940
.. versionadded:: next
938941

939942

940943
.. function:: get_lazy_modules()
941944

942-
Returns a set of fully-qualified module names that have been lazily imported.
943-
This is primarily useful for diagnostics and introspection.
945+
Returns a set of fully-qualified module names that have been
946+
lazilyimported. This is primarily useful for diagnostics and
947+
introspection.
944948

945-
Note that modules are removed from this set when they are reified (actually
946-
loaded on first use).
949+
Note that modules are removed from this set when they are reified
950+
(actually loaded on first use).
947951

948952
.. versionadded:: next
949953

@@ -1759,16 +1763,19 @@ always available. Unless explicitly noted otherwise, all variables are read-only
17591763

17601764
.. function:: set_lazy_imports(mode)
17611765

1762-
Sets the global lazy imports mode. The *mode* parameter must be one of the
1763-
following strings:
1766+
Sets the global lazy imports mode. The *mode* parameter must be one of
1767+
the following strings:
17641768

1765-
* ``"normal"``: Only imports explicitly marked with the ``lazy`` keyword are lazy
1769+
* ``"normal"``: Only imports explicitly marked with the ``lazy`` keyword
1770+
are lazy
17661771
* ``"all"``: All top-level imports become potentially lazy
1767-
* ``"none"``: All lazy imports are suppressed (even explicitly marked ones)
1772+
* ``"none"``: All lazy imports are suppressed (even explicitly marked
1773+
ones)
17681774

1769-
This function is intended for advanced users who need to control lazy imports
1770-
across their entire application. Library developers should generally not use
1771-
this function as it affects the runtime execution of applications.
1775+
This function is intended for advanced users who need to control lazy
1776+
imports across their entire application. Library developers should
1777+
generally not use this function as it affects the runtime execution of
1778+
applications.
17721779

17731780
In addition to the mode, lazy imports can be controlled via the filter
17741781
provided by :func:`set_lazy_imports_filter`.
@@ -1783,8 +1790,9 @@ always available. Unless explicitly noted otherwise, all variables are read-only
17831790
Sets the lazy imports filter callback. The *filter* parameter must be a
17841791
callable or ``None`` to clear the filter.
17851792

1786-
The filter function is called for every potentially lazy import to determine
1787-
whether it should actually be lazy. It must have the following signature::
1793+
The filter function is called for every potentially lazy import to
1794+
determine whether it should actually be lazy. It must have the following
1795+
signature::
17881796

17891797
def filter(importing_module: str, imported_module: str,
17901798
fromlist: tuple[str, ...] | None) -> bool

Doc/whatsnew/3.15.rst

Lines changed: 57 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -86,29 +86,31 @@ New features
8686
:pep:`810`: Explicit lazy imports
8787
---------------------------------
8888

89-
Large Python applications often suffer from slow startup times. A significant
90-
contributor to this problem is the import system: when a module is imported,
91-
Python must locate the file, read it from disk, compile it to bytecode, and
92-
execute all top-level code. For applications with deep dependency trees, this
93-
process can take seconds, even when most of the imported code is never actually
94-
used during a particular run.
89+
Large Python applications often suffer from slow startup times. A
90+
significant contributor to this problem is the import system: when a module
91+
is imported, Python must locate the file, read it from disk, compile it to
92+
bytecode, and execute all top-level code. For applications with deep
93+
dependency trees, this process can take seconds, even when most of the
94+
imported code is never actually used during a particular run.
9595

9696
Developers have worked around this by moving imports inside functions, using
9797
:mod:`importlib` to load modules on demand, or restructuring code to avoid
9898
unnecessary dependencies. These approaches work but make code harder to read
9999
and maintain, scatter import statements throughout the codebase, and require
100100
discipline to apply consistently.
101101

102-
Python now provides a cleaner solution through explicit :keyword:`lazy` imports
103-
using the new ``lazy`` soft keyword. When you mark an import as lazy, Python
104-
defers the actual module loading until the imported name is first used. This
105-
gives you the organizational benefits of declaring all imports at the top of
106-
the file while only paying the loading cost for modules you actually use.
102+
Python now provides a cleaner solution through explicit :keyword:`lazy`
103+
imports using the new ``lazy`` soft keyword. When you mark an import as
104+
lazy, Python defers the actual module loading until the imported name is
105+
first used. This gives you the organizational benefits of declaring all
106+
imports at the top of the file while only paying the loading cost for
107+
modules you actually use.
107108

108-
The ``lazy`` keyword works with both ``import`` and ``from ... import`` statements.
109-
When you write ``lazy import heavy_module``, Python does not immediately load the
110-
module. Instead, it creates a lightweight proxy object. The actual module loading
111-
happens transparently when you first access the name:
109+
The ``lazy`` keyword works with both ``import`` and ``from ... import``
110+
statements. When you write ``lazy import heavy_module``, Python does not
111+
immediately load the module. Instead, it creates a lightweight proxy object.
112+
The actual module loading happens transparently when you first access the
113+
name:
112114

113115
.. code-block:: python
114116
@@ -120,54 +122,59 @@ happens transparently when you first access the name:
120122
data = json.loads('{"key": "value"}') # json gets loads here
121123
now = datetime() # datetime loads here
122124
123-
This mechanism is particularly useful for applications that import many modules
124-
at the top level but may only use a subset of them in any given run. The deferred
125-
loading reduces startup latency without requiring code restructuring or conditional
126-
imports scattered throughout the codebase.
127-
128-
In the case where loading a lazily imported module fails (for example, if the
129-
module does not exist), Python raises the exception at the point of first use
130-
rather than at import time. The associated traceback includes both the location
131-
where the name was accessed and the original import statement, making it
132-
straightforward to diagnose & debug the failure.
133-
134-
For cases where you want to enable lazy loading globally without modifying source
135-
code, Python provides the :option:`-X lazy_imports <-X>` command-line option and
136-
the :envvar:`PYTHON_LAZY_IMPORTS` environment variable. Both accept three values:
137-
``all`` makes all imports lazy by default, ``none`` disables lazy imports entirely
138-
(even explicit ``lazy`` statements become eager), and ``normal`` (the default)
139-
respects the ``lazy`` keyword in source code. The :func:`sys.set_lazy_imports` and
140-
:func:`sys.get_lazy_imports` functions allow changing and querying this mode at
141-
runtime.
142-
143-
For more selective control, :func:`sys.set_lazy_imports_filter` accepts a callable
144-
that determines whether a specific module should be loaded lazily. The filter
145-
receives three arguments: the importing module's name (or ``None``), the imported
146-
module's name, and the fromlist (or ``None`` for regular imports). It should
147-
return ``True`` to allow the import to be lazy, or ``False`` to force eager loading.
148-
This allows patterns like making only your own application's modules lazy while
149-
keeping third-party dependencies eager:
125+
This mechanism is particularly useful for applications that import many
126+
modules at the top level but may only use a subset of them in any given run.
127+
The deferred loading reduces startup latency without requiring code
128+
restructuring or conditional imports scattered throughout the codebase.
129+
130+
In the case where loading a lazily imported module fails (for example, if
131+
the module does not exist), Python raises the exception at the point of
132+
first use rather than at import time. The associated traceback includes both
133+
the location where the name was accessed and the original import statement,
134+
making it straightforward to diagnose & debug the failure.
135+
136+
For cases where you want to enable lazy loading globally without modifying
137+
source code, Python provides the :option:`-X lazy_imports <-X>` command-line
138+
option and the :envvar:`PYTHON_LAZY_IMPORTS` environment variable. Both
139+
accept three values: ``all`` makes all imports lazy by default, ``none``
140+
disables lazy imports entirely (even explicit ``lazy`` statements become
141+
eager), and ``normal`` (the default) respects the ``lazy`` keyword in source
142+
code. The :func:`sys.set_lazy_imports` and :func:`sys.get_lazy_imports`
143+
functions allow changing and querying this mode at runtime.
144+
145+
For more selective control, :func:`sys.set_lazy_imports_filter` accepts a
146+
callable that determines whether a specific module should be loaded lazily.
147+
The filter receives three arguments: the importing module's name (or
148+
``None``), the imported module's name, and the fromlist (or ``None`` for
149+
regular imports). It should return ``True`` to allow the import to be lazy,
150+
or ``False`` to force eager loading. This allows patterns like making only
151+
your own application's modules lazy while keeping third-party dependencies
152+
eager:
150153

151154
.. code-block:: python
152155
153156
import sys
154157
155-
sys.set_lazy_imports_filter(lambda importing, imported, fromlist: imported.startswith("myapp."))
158+
def myapp_filter(importing, imported, fromlist):
159+
return imported.startswith("myapp.")
160+
sys.set_lazy_imports_filter(myapp_filter)
156161
sys.set_lazy_imports("all")
157162
158163
import myapp.slow_module # lazy (matches filter)
159164
import json # eager (does not match filter)
160165
161166
For debugging and introspection, :func:`sys.get_lazy_modules` returns a set
162-
containing the names of all modules that have been lazily imported but not yet
163-
loaded. The proxy type itself is available as :data:`types.LazyImportType` for
164-
code that needs to detect lazy imports programmatically.
167+
containing the names of all modules that have been lazily imported but not
168+
yet loaded. The proxy type itself is available as
169+
:data:`types.LazyImportType` for code that needs to detect lazy imports
170+
programmatically.
165171

166172
There are some restrictions on where the ``lazy`` keyword can be used. Lazy
167-
imports are only permitted at module scope; using ``lazy`` inside a function,
168-
class body, or ``try``/``except``/``finally`` block raises a :exc:`SyntaxError`.
169-
Neither star imports nor future imports can be lazy (``lazy from module import *``
170-
and ``lazy from __future__ import ...`` both raise :exc:`SyntaxError`).
173+
imports are only permitted at module scope; using ``lazy`` inside a
174+
function, class body, or ``try``/``except``/``finally`` block raises a
175+
:exc:`SyntaxError`. Neither star imports nor future imports can be lazy
176+
(``lazy from module import *`` and ``lazy from __future__ import ...`` both
177+
raise :exc:`SyntaxError`).
171178

172179
.. seealso:: :pep:`810` for the full specification and rationale.
173180

Include/internal/pycore_ceval.h

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -311,14 +311,19 @@ PyAPI_FUNC(void) _PyEval_FormatExcCheckArg(PyThreadState *tstate, PyObject *exc,
311311
PyAPI_FUNC(void) _PyEval_FormatExcUnbound(PyThreadState *tstate, PyCodeObject *co, int oparg);
312312
PyAPI_FUNC(void) _PyEval_FormatKwargsError(PyThreadState *tstate, PyObject *func, PyObject *kwargs);
313313
PyAPI_FUNC(PyObject *) _PyEval_ImportFrom(PyThreadState *, PyObject *, PyObject *);
314-
PyAPI_FUNC(PyObject *) _PyEval_LazyImportName(PyThreadState *tstate, PyObject *builtins, PyObject *globals,
315-
PyObject *locals, PyObject *name, PyObject *fromlist, PyObject *level, int lazy);
316-
PyAPI_FUNC(PyObject *) _PyEval_LazyImportFrom(PyThreadState *tstate, PyObject *v, PyObject *name);
317-
PyAPI_FUNC(PyObject *) _PyEval_ImportName(PyThreadState *tstate, PyObject *builtins, PyObject *globals, PyObject *locals,
318-
PyObject *name, PyObject *fromlist, PyObject *level);
319-
PyObject *
320-
_PyEval_ImportNameWithImport(PyThreadState *tstate, PyObject *import_func, PyObject *globals, PyObject *locals,
321-
PyObject *name, PyObject *fromlist, PyObject *level);
314+
315+
PyAPI_FUNC(PyObject *) _PyEval_LazyImportName(
316+
PyThreadState *tstate, PyObject *builtins, PyObject *globals,
317+
PyObject *locals, PyObject *name, PyObject *fromlist, PyObject *level,
318+
int lazy);
319+
PyAPI_FUNC(PyObject *) _PyEval_LazyImportFrom(
320+
PyThreadState *tstate, PyObject *v, PyObject *name);
321+
PyAPI_FUNC(PyObject *) _PyEval_ImportName(
322+
PyThreadState *tstate, PyObject *builtins, PyObject *globals,
323+
PyObject *locals, PyObject *name, PyObject *fromlist, PyObject *level);
324+
PyObject * _PyEval_ImportNameWithImport(
325+
PyThreadState *tstate, PyObject *import_func, PyObject *globals,
326+
PyObject *locals, PyObject *name, PyObject *fromlist, PyObject *level);
322327
PyAPI_FUNC(PyObject *)_PyEval_MatchClass(PyThreadState *tstate, PyObject *subject, PyObject *type, Py_ssize_t nargs, PyObject *kwargs);
323328
PyAPI_FUNC(PyObject *)_PyEval_MatchKeys(PyThreadState *tstate, PyObject *map, PyObject *keys);
324329
PyAPI_FUNC(void) _PyEval_MonitorRaise(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr);

Include/internal/pycore_dict.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ extern int _PyDict_Contains_KnownHash(PyObject *, PyObject *, Py_hash_t);
4040
extern PyObject* _PyDict_GetItemIdWithError(PyObject *dp,
4141
_Py_Identifier *key);
4242
extern int _PyDict_ContainsId(PyObject *, _Py_Identifier *);
43-
extern int _PyDict_SetItemId(PyObject *dp, _Py_Identifier *key, PyObject *item);
43+
extern int _PyDict_SetItemId(PyObject *dp, _Py_Identifier *key,
44+
PyObject *item);
4445
extern int _PyDict_DelItemId(PyObject *mp, _Py_Identifier *key);
4546
extern void _PyDict_ClearKeysVersion(PyObject *mp);
4647

Include/internal/pycore_import.h

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,16 @@ extern int _PyImport_FixupBuiltin(
3232
PyObject *modules
3333
);
3434

35-
extern PyObject *
36-
_PyImport_ResolveName(PyThreadState *tstate, PyObject *name, PyObject *globals, int level);
37-
extern PyObject *
38-
_PyImport_GetAbsName(PyThreadState *tstate, PyObject *name, PyObject *globals, int level);
35+
extern PyObject * _PyImport_ResolveName(
36+
PyThreadState *tstate, PyObject *name, PyObject *globals, int level);
37+
extern PyObject * _PyImport_GetAbsName(
38+
PyThreadState *tstate, PyObject *name, PyObject *globals, int level);
3939
// Symbol is exported for the JIT on Windows builds.
40-
PyAPI_FUNC(PyObject *)
41-
_PyImport_LoadLazyImportTstate(PyThreadState *tstate, PyObject *lazy_import);
42-
extern PyObject *
43-
_PyImport_LazyImportModuleLevelObject(PyThreadState *tstate, PyObject *name, PyObject *builtins, PyObject *globals,
44-
PyObject *locals, PyObject *fromlist,
45-
int level);
40+
PyAPI_FUNC(PyObject *) _PyImport_LoadLazyImportTstate(
41+
PyThreadState *tstate, PyObject *lazy_import);
42+
extern PyObject * _PyImport_LazyImportModuleLevelObject(
43+
PyThreadState *tstate, PyObject *name, PyObject *builtins,
44+
PyObject *globals, PyObject *locals, PyObject *fromlist, int level);
4645

4746

4847
#ifdef HAVE_DLOPEN
@@ -82,7 +81,8 @@ extern void _PyImport_ClearModules(PyInterpreterState *interp);
8281

8382
extern void _PyImport_ClearModulesByIndex(PyInterpreterState *interp);
8483

85-
extern PyObject * _PyImport_InitLazyModules(PyInterpreterState *interp);
84+
extern PyObject * _PyImport_InitLazyModules(
85+
PyInterpreterState *interp);
8686
extern void _PyImport_ClearLazyModules(PyInterpreterState *interp);
8787

8888
extern int _PyImport_InitDefaultImportFunc(PyInterpreterState *interp);

Include/internal/pycore_lazyimportobject.h

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
/* File added for Lazy Imports */
2-
3-
/* Lazy object interface */
1+
// Lazy object interface.
42

53
#ifndef Py_INTERNAL_LAZYIMPORTOBJECT_H
64
#define Py_INTERNAL_LAZYIMPORTOBJECT_H
@@ -21,16 +19,17 @@ typedef struct {
2119
PyObject *lz_builtins;
2220
PyObject *lz_from;
2321
PyObject *lz_attr;
24-
/* Frame information for the original import location */
25-
PyCodeObject *lz_code; /* code object where the lazy import was created */
26-
int lz_instr_offset; /* instruction offset where the lazy import was created */
22+
// Frame information for the original import location.
23+
PyCodeObject *lz_code; // Code object where the lazy import was created.
24+
int lz_instr_offset; // Instruction offset where the lazy import was created.
2725
} PyLazyImportObject;
2826

2927

3028
PyAPI_FUNC(PyObject *) _PyLazyImport_GetName(PyObject *lazy_import);
31-
PyAPI_FUNC(PyObject *) _PyLazyImport_New(PyObject *import_func, PyObject *from, PyObject *attr);
29+
PyAPI_FUNC(PyObject *) _PyLazyImport_New(
30+
PyObject *import_func, PyObject *from, PyObject *attr);
3231

3332
#ifdef __cplusplus
3433
}
3534
#endif
36-
#endif /* !Py_INTERNAL_LAZYIMPORTOBJECT_H */
35+
#endif // !Py_INTERNAL_LAZYIMPORTOBJECT_H

Include/internal/pycore_moduleobject.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ extern Py_ssize_t _PyModule_GetFilenameUTF8(
7878
PyObject* _Py_module_getattro_impl(PyModuleObject *m, PyObject *name, int suppress);
7979
PyObject* _Py_module_getattro(PyObject *m, PyObject *name);
8080

81-
PyAPI_FUNC(int) _PyModule_ReplaceLazyValue(PyObject *dict, PyObject *name, PyObject *value);
81+
PyAPI_FUNC(int) _PyModule_ReplaceLazyValue(
82+
PyObject *dict, PyObject *name, PyObject *value);
8283

8384
#ifdef __cplusplus
8485
}

Lib/dis.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1019,7 +1019,8 @@ def _find_imports(co):
10191019
(level_op[0] in hasconst or level_op[0] == LOAD_SMALL_INT)):
10201020
level = _get_const_value(level_op[0], level_op[1], consts)
10211021
fromlist = _get_const_value(from_op[0], from_op[1], consts)
1022-
# IMPORT_NAME encodes lazy/eager flags in bits 0-1, name index in bits 2+
1022+
# IMPORT_NAME encodes lazy/eager flags in bits 0-1,
1023+
# name index in bits 2+.
10231024
yield (names[oparg >> 2], level, fromlist)
10241025

10251026
def _find_store_names(co):

Lib/idlelib/idle_test/test_colorizer.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -545,9 +545,11 @@ def test_case_soft_keyword(self):
545545
def test_lazy_soft_keyword(self):
546546
# lazy followed by import
547547
self._assert_highlighting('lazy import foo',
548-
{'KEYWORD': [('1.0', '1.4'), ('1.5', '1.11')]})
548+
{'KEYWORD': [('1.0', '1.4'),
549+
('1.5', '1.11')]})
549550
self._assert_highlighting(' lazy import foo',
550-
{'KEYWORD': [('1.4', '1.8'), ('1.9', '1.15')]})
551+
{'KEYWORD': [('1.4', '1.8'),
552+
('1.9', '1.15')]})
551553

552554
# lazy followed by from
553555
self._assert_highlighting('lazy from foo import bar',

Lib/rlcompleter.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,8 @@ def attr_matches(self, text):
192192

193193
if (isinstance(thisobject, types.ModuleType)
194194
and
195-
isinstance(thisobject.__dict__.get(word), types.LazyImportType)
195+
isinstance(thisobject.__dict__.get(word),
196+
types.LazyImportType)
196197
):
197198
value = thisobject.__dict__.get(word)
198199
else:

0 commit comments

Comments
 (0)