Skip to content

Commit 385e132

Browse files
committed
gh-150228: Improve the PEP 829 batch processing APIs
As previously discussed with @ncoghlan and approved for 3.15b2 by @hugovk, this exposes the batch processing APIs for addsitedir() and friends. We remove the `defer_processing_start_files` flag which required some implicit module global state, and promote StartupState to the public documented API. This removes the need for module global implicit state and allows callers to control when accumulated .start and .pth file state is processed if they want. This also fixes the interleaving regression identified by @ncoghlan in the same issue. Now, .pth file sys.path extensions are added to sys.path after the sitedir that the .pth file is found in, restoring the legacy behavior. Along the way, I've made a lot of improvements to function docstrings, site.rst documentation, and comments in the code explaining what's going on.
1 parent a679366 commit 385e132

5 files changed

Lines changed: 415 additions & 305 deletions

File tree

Doc/library/site.rst

Lines changed: 51 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,27 @@ Module contents
356356
This function used to be called unconditionally.
357357

358358

359-
.. function:: addsitedir(sitedir, known_paths=None, *, defer_processing_start_files=False)
359+
.. class:: StartupState(known_paths=None)
360+
361+
Instances of this class are used as an accumulator for interpreter startup
362+
configuration data, such as ``.pth`` and ``.start`` files, from one or more
363+
site directories. These are used to batch the processing of these startup
364+
files. The optional *known_paths* argument is a set of case-normalized
365+
paths used to prevent duplicate :data:`sys.path` entries. With ``None``
366+
(the default), this set is built from the current :data:`sys.path`.
367+
:func:`main` implicitly uses an instance of this class.
368+
369+
.. method:: process()
370+
371+
Apply the accumulated state by first adding the path extensions to
372+
:data:`sys.path`, then executing the :file:`.start` file entry points
373+
and :file:`.pth` file ``import`` lines (:ref:`deprecated
374+
<site-pth-files>`).
375+
376+
.. versionadded:: 3.15
377+
378+
379+
.. function:: addsitedir(sitedir, known_paths=None, *, startup_state=None)
360380

361381
Add a directory to sys.path and parse the :file:`.pth` and :file:`.start`
362382
files found in that directory. Typically used in :mod:`sitecustomize` or
@@ -366,17 +386,39 @@ Module contents
366386
used to prevent duplicate :data:`sys.path` entries. When ``None`` (the
367387
default), the set is built from the current :data:`sys.path`.
368388

369-
While :file:`.pth` and :file:`.start` files are always parsed, set
370-
*defer_processing_start_files* to ``True`` to prevent processing the
371-
startup data found in those files, so that you can process them explicitly
372-
(this is typically used by the :func:`main` function).
389+
Pass an instance of :class:`StartupState` as *startup_state* to accumulate
390+
startup data from multiple site directories before explicitly processing
391+
with :meth:`StartupState.process`. The *known_paths* and *startup_state*
392+
arguments cannot both be given.
393+
394+
For example:
395+
396+
.. code-block:: python
397+
398+
state = site.StartupState()
399+
for sitedir in site_dirs:
400+
site.addsitedir(sitedir, startup_state=state)
401+
state.process()
402+
403+
Semantics and return values:
404+
405+
* When only *sitedir* is given, startup configuration is processed before
406+
the function returns, and ``None`` is returned.
407+
* When *known_paths* is given, startup configuration is process before the
408+
function returns, and the updated *known_paths* is returned.
409+
* When *startup_state* is given, startup configuration is **not**
410+
processed, and the state instance is returned. It is up to the caller to
411+
call :meth:`StartupState.process` on this instance.
412+
* It is a :exc:`TypeError` to pass both *known_paths* and *startup_state*.
373413

374414
.. versionchanged:: 3.15
375415

376-
Also processes :file:`.start` files. See :ref:`site-start-files`.
377-
All :file:`.pth` and :file:`.start` files are now read and
378-
accumulated before any path extensions, ``import`` line execution,
379-
or entry point invocations take place.
416+
Also processes :file:`.start` files. See :ref:`site-start-files`. All
417+
:file:`.pth` and :file:`.start` files are now read and accumulated
418+
before any path extensions, entry point invocations, or``import`` line
419+
execution take place.
420+
421+
The *startup_state* keyword-only argument was added.
380422

381423

382424
.. function:: getsitepackages()
@@ -447,4 +489,3 @@ value greater than 2 if there is an error.
447489
* :pep:`370` -- Per user site-packages directory
448490
* :pep:`829` -- Startup entry points and the deprecation of import lines in ``.pth`` files
449491
* :ref:`sys-path-init` -- The initialization of :data:`sys.path`.
450-

Doc/whatsnew/3.15.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,14 @@ matching :file:`.start` file is found, ``import`` lines in :file:`.pth` files
478478
are ignored. There is no change to :data:`sys.path` extension lines in
479479
:file:`.pth` files.
480480

481+
The :mod:`site` module also provides :class:`site.StartupState` to batch
482+
startup processing for multiple site directories, ensuring all static path
483+
extensions are applied before any startup code is executed. :func:`site.main`
484+
uses an instance of this class implicitly to batch process all startup
485+
configuration files during normal interpreter startup. Callers of
486+
:func:`site.addsitedir` can pass one of these explicitly to control startup
487+
configuration file batch processing.
488+
481489
(Contributed by Barry Warsaw in :gh:`148641`.)
482490

483491

0 commit comments

Comments
 (0)