Skip to content

Commit c15af5b

Browse files
committed
Some minor improvements
* Add a note that if known_paths is provided to StartupState.__init__(), it will get mutated in place. * Improve some conditional flows. * Improve some comments. * Improve the what's new entry.
1 parent 5405f69 commit c15af5b

2 files changed

Lines changed: 38 additions & 28 deletions

File tree

Lib/site.py

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,10 @@ def __init__(self, known_paths=None):
259259
*known_paths* is a set of case-normalized paths already present
260260
on sys.path, used to avoid duplicate path entries. When None
261261
(the default), it is initialized from the current sys.path.
262+
263+
A caller-supplied set is stored by reference and mutated in place
264+
as new paths are recorded; pass a fresh set per StartupState if
265+
isolation across instances is required.
262266
"""
263267
self._known_paths = (
264268
_init_pathinfo()
@@ -280,7 +284,7 @@ def __init__(self, known_paths=None):
280284
self._importexecs = {}
281285
self._entrypoints = {}
282286

283-
def add_sitedir(self, sitedir, *, process_known_sitedirs=True):
287+
def _add_sitedir(self, sitedir, *, process_known_sitedirs=True):
284288
sitedir, sitedircase = makepath(sitedir)
285289
# Have we already processed this sitedir?
286290
if sitedircase in self._processed_sitedirs:
@@ -391,13 +395,20 @@ def process(self):
391395
self._execute_start_entrypoints()
392396

393397
def _extend_syspath(self):
394-
# Duplicates have already been filtered (in existing sys.path or
395-
# across .pth files via known_paths), and entries are already
396-
# abspath/normpath'd, so all that remains is to confirm that .pth
397-
# file path entries exist before appending them. filename will be
398-
# None for sitedir entries in the ledger, and these have already been
399-
# checked for existence, so no need to do so again.
398+
# Duplicate path-extension specifications have already been filtered
399+
# out upstream across .pth files within this batch (via known_paths),
400+
# and ledger entries are already abspath/normpath'd. .pth-derived
401+
# entries (filename is not None) are existence-checked and skipped
402+
# with an error if missing. Sitedir entries (filename is None) are
403+
# appended unconditionally: legacy addsitedir() added the sitedir to
404+
# sys.path before attempting to list it, so an unreadable or
405+
# non-existent sitedir still landed on sys.path. Deferring the
406+
# append to here preserves that contract.
400407
for filename, dir_ in self._path_entries:
408+
# As a backstop, known_paths may not have been seeded from sys.path
409+
# (callers can pass an empty set), and multiple StartupState
410+
# instances against the same sys.path don't share state, so always
411+
# do a final anti-duplication check.
401412
if dir_ in sys.path:
402413
continue
403414
if filename is None or os.path.exists(dir_):
@@ -485,8 +496,6 @@ def addpackage(sitedir, name, known_paths):
485496
else:
486497
reset = False
487498

488-
# Although never documented, the semantics of addpackage() is to fully
489-
# process a single sitedir.
490499
state = StartupState(known_paths)
491500
state.read_pth_file(sitedir, name)
492501
state.process()
@@ -534,23 +543,26 @@ def addsitedir(sitedir, known_paths=None, *, startup_state=None):
534543
flush_now = True
535544
process_known_sitedirs = False
536545

537-
sitedir = startup_state.add_sitedir(
546+
# Reach into StartupState's non-public API deliberately: sitedir
547+
# bookkeeping is a detail of how addsitedir() drives a batch, not
548+
# something callers should manage themselves. Keeping _add_sitedir()
549+
# private avoids committing it to the public StartupState API.
550+
sitedir = startup_state._add_sitedir(
538551
sitedir,
539552
process_known_sitedirs=process_known_sitedirs,
540553
)
541554
if sitedir is None:
542-
if not flush_now:
543-
return startup_state
544-
return None if reset else known_paths
555+
if flush_now:
556+
return None if reset else known_paths
557+
return startup_state
545558

546559
try:
547560
names = os.listdir(sitedir)
548561
except OSError:
549562
if flush_now:
550563
startup_state.process()
551-
if not flush_now:
552-
return startup_state
553-
return None if reset else known_paths
564+
return None if reset else known_paths
565+
return startup_state
554566

555567
# The following phases are defined by PEP 829.
556568
# Phases 1-3: Read .pth files, accumulating paths and import lines.
@@ -573,11 +585,8 @@ def addsitedir(sitedir, known_paths=None, *, startup_state=None):
573585

574586
if flush_now:
575587
startup_state.process()
576-
577-
if not flush_now:
578-
return startup_state
579-
580-
return None if reset else known_paths
588+
return None if reset else known_paths
589+
return startup_state
581590

582591

583592
def check_enableusersite():
Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
:class:`site.StartupState` is publicly exposed to allow for :pep:`829`
2-
explicit batch processing of startup configuration files. :func:`~site.addsitedir`
3-
now takes an optional instance of this class so callers can control their
4-
own batch processing. The previously added
5-
:data:`!defer_processing_start_files` argument has been removed. The module
6-
global function ``process_startup_files()`` was removed (use
7-
:meth:`site.StartupState.process` instead).
1+
:func:`site.addsitedir` now accepts an optional *startup_state* keyword
2+
argument that lets callers batch-process :pep:`829` startup configuration
3+
files across multiple site directories before any startup code runs. The new
4+
:class:`site.StartupState` class maintains the batch state, and callers can
5+
instantiate one of these to control the batching process. The
6+
:data:`!defer_processing_start_files` argument and the
7+
``process_startup_files()`` function added earlier in the 3.15 cycle have been
8+
removed; use :meth:`site.StartupState.process` instead.

0 commit comments

Comments
 (0)