• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# ******************************************************************************
2# getpath.py
3# ******************************************************************************
4
5# This script is designed to be precompiled to bytecode, frozen into the
6# main binary, and then directly evaluated. It is not an importable module,
7# and does not import any other modules (besides winreg on Windows).
8# Rather, the values listed below must be specified in the globals dict
9# used when evaluating the bytecode.
10
11# See _PyConfig_InitPathConfig in Modules/getpath.c for the execution.
12
13# ******************************************************************************
14# REQUIRED GLOBALS
15# ******************************************************************************
16
17# ** Helper functions **
18# abspath(path)     -- make relative paths absolute against CWD
19# basename(path)    -- the filename of path
20# dirname(path)     -- the directory name of path
21# hassuffix(path, suffix) -- returns True if path has suffix
22# isabs(path)       -- path is absolute or not
23# isdir(path)       -- path exists and is a directory
24# isfile(path)      -- path exists and is a file
25# isxfile(path)     -- path exists and is an executable file
26# joinpath(*paths)  -- combine the paths
27# readlines(path)   -- a list of each line of text in the UTF-8 encoded file
28# realpath(path)    -- resolves symlinks in path
29# warn(message)     -- print a warning (if enabled)
30
31# ** Values known at compile time **
32# os_name           -- [in] one of 'nt', 'posix', 'darwin'
33# PREFIX            -- [in] sysconfig.get_config_var(...)
34# EXEC_PREFIX       -- [in] sysconfig.get_config_var(...)
35# PYTHONPATH        -- [in] sysconfig.get_config_var(...)
36# WITH_NEXT_FRAMEWORK   -- [in] sysconfig.get_config_var(...)
37# VPATH             -- [in] sysconfig.get_config_var(...)
38# PLATLIBDIR        -- [in] sysconfig.get_config_var(...)
39# PYDEBUGEXT        -- [in, opt] '_d' on Windows for debug builds
40# EXE_SUFFIX        -- [in, opt] '.exe' on Windows/Cygwin/similar
41# VERSION_MAJOR     -- [in] sys.version_info.major
42# VERSION_MINOR     -- [in] sys.version_info.minor
43# ABI_THREAD        -- [in] either 't' for free-threaded builds or ''
44# PYWINVER          -- [in] the Windows platform-specific version (e.g. 3.8-32)
45
46# ** Values read from the environment **
47#   There is no need to check the use_environment flag before reading
48#   these, as the flag will be tested in this script.
49#   Also note that ENV_PYTHONPATH is read from config['pythonpath_env']
50#   to allow for embedders who choose to specify it via that struct.
51# ENV_PATH                -- [in] getenv(...)
52# ENV_PYTHONHOME          -- [in] getenv(...)
53# ENV_PYTHONEXECUTABLE    -- [in] getenv(...)
54# ENV___PYVENV_LAUNCHER__ -- [in] getenv(...)
55
56# ** Values calculated at runtime **
57# config            -- [in/out] dict of the PyConfig structure
58# real_executable   -- [in, optional] resolved path to main process
59#   On Windows and macOS, read directly from the running process
60#   Otherwise, leave None and it will be calculated from executable
61# executable_dir    -- [in, optional] real directory containing binary
62#   If None, will be calculated from real_executable or executable
63# py_setpath        -- [in] argument provided to Py_SetPath
64#   If None, 'prefix' and 'exec_prefix' may be updated in config
65# library           -- [in, optional] path of dylib/DLL/so
66#   Only used for locating ._pth files
67# winreg            -- [in, optional] the winreg module (only on Windows)
68
69# ******************************************************************************
70# HIGH-LEVEL ALGORITHM
71# ******************************************************************************
72
73# IMPORTANT: The code is the actual specification at time of writing.
74# This prose description is based on the original comment from the old
75# getpath.c to help capture the intent, but should not be considered
76# a specification.
77
78# Search in some common locations for the associated Python libraries.
79
80# Two directories must be found, the platform independent directory
81# (prefix), containing the common .py and .pyc files, and the platform
82# dependent directory (exec_prefix), containing the shared library
83# modules.  Note that prefix and exec_prefix can be the same directory,
84# but for some installations, they are different.
85
86# This script carries out separate searches for prefix and exec_prefix.
87# Each search tries a number of different locations until a ``landmark''
88# file or directory is found.  If no prefix or exec_prefix is found, a
89# warning message is issued and the preprocessor defined PREFIX and
90# EXEC_PREFIX are used (even though they will not work); python carries on
91# as best as is possible, but most imports will fail.
92
93# Before any searches are done, the location of the executable is
94# determined.  If Py_SetPath() was called, or if we are running on
95# Windows, the 'real_executable' path is used (if known).  Otherwise,
96# we use the config-specified program name or default to argv[0].
97# If this has one or more slashes in it, it is made absolute against
98# the current working directory.  If it only contains a name, it must
99# have been invoked from the shell's path, so we search $PATH for the
100# named executable and use that.  If the executable was not found on
101# $PATH (or there was no $PATH environment variable), the original
102# argv[0] string is used.
103
104# At this point, provided Py_SetPath was not used, the
105# __PYVENV_LAUNCHER__ variable may override the executable (on macOS,
106# the PYTHON_EXECUTABLE variable may also override). This allows
107# certain launchers that run Python as a subprocess to properly
108# specify the executable path. They are not intended for users.
109
110# Next, the executable location is examined to see if it is a symbolic
111# link.  If so, the link is realpath-ed and the directory of the link
112# target is used for the remaining searches.  The same steps are
113# performed for prefix and for exec_prefix, but with different landmarks.
114
115# Step 1. Are we running in a virtual environment? Unless 'home' has
116# been specified another way, check for a pyvenv.cfg and use its 'home'
117# property to override the executable dir used later for prefix searches.
118# We do not activate the venv here - that is performed later by site.py.
119
120# Step 2. Is there a ._pth file? A ._pth file lives adjacent to the
121# runtime library (if any) or the actual executable (not the symlink),
122# and contains precisely the intended contents of sys.path as relative
123# paths (to its own location). Its presence also enables isolated mode
124# and suppresses other environment variable usage. Unless already
125# specified by Py_SetHome(), the directory containing the ._pth file is
126# set as 'home'.
127
128# Step 3. Are we running python out of the build directory?  This is
129# checked by looking for the BUILDDIR_TXT file, which contains the
130# relative path to the platlib dir. The executable_dir value is
131# derived from joining the VPATH preprocessor variable to the
132# directory containing pybuilddir.txt. If it is not found, the
133# BUILD_LANDMARK file is found, which is part of the source tree.
134# prefix is then found by searching up for a file that should only
135# exist in the source tree, and the stdlib dir is set to prefix/Lib.
136
137# Step 4. If 'home' is set, either by Py_SetHome(), ENV_PYTHONHOME,
138# a pyvenv.cfg file, ._pth file, or by detecting a build directory, it
139# is assumed to point to prefix and exec_prefix. $PYTHONHOME can be a
140# single directory, which is used for both, or the prefix and exec_prefix
141# directories separated by DELIM (colon on POSIX; semicolon on Windows).
142
143# Step 5. Try to find prefix and exec_prefix relative to executable_dir,
144# backtracking up the path until it is exhausted.  This is the most common
145# step to succeed.  Note that if prefix and exec_prefix are different,
146# exec_prefix is more likely to be found; however if exec_prefix is a
147# subdirectory of prefix, both will be found.
148
149# Step 6. Search the directories pointed to by the preprocessor variables
150# PREFIX and EXEC_PREFIX.  These are supplied by the Makefile but can be
151# passed in as options to the configure script.
152
153# That's it!
154
155# Well, almost.  Once we have determined prefix and exec_prefix, the
156# preprocessor variable PYTHONPATH is used to construct a path.  Each
157# relative path on PYTHONPATH is prefixed with prefix.  Then the directory
158# containing the shared library modules is appended.  The environment
159# variable $PYTHONPATH is inserted in front of it all. On POSIX, if we are
160# in a build directory, both prefix and exec_prefix are reset to the
161# corresponding preprocessor variables (so sys.prefix will reflect the
162# installation location, even though sys.path points into the build
163# directory).  This seems to make more sense given that currently the only
164# known use of sys.prefix and sys.exec_prefix is for the ILU installation
165# process to find the installed Python tree.
166
167# An embedding application can use Py_SetPath() to override all of
168# these automatic path computations.
169
170
171# ******************************************************************************
172# PLATFORM CONSTANTS
173# ******************************************************************************
174
175platlibdir = config.get('platlibdir') or PLATLIBDIR
176ABI_THREAD = ABI_THREAD or ''
177
178if os_name == 'posix' or os_name == 'darwin':
179    BUILDDIR_TXT = 'pybuilddir.txt'
180    BUILD_LANDMARK = 'Modules/Setup.local'
181    DEFAULT_PROGRAM_NAME = f'python{VERSION_MAJOR}'
182    STDLIB_SUBDIR = f'{platlibdir}/python{VERSION_MAJOR}.{VERSION_MINOR}{ABI_THREAD}'
183    STDLIB_LANDMARKS = [f'{STDLIB_SUBDIR}/os.py', f'{STDLIB_SUBDIR}/os.pyc']
184    PLATSTDLIB_LANDMARK = f'{platlibdir}/python{VERSION_MAJOR}.{VERSION_MINOR}{ABI_THREAD}/lib-dynload'
185    BUILDSTDLIB_LANDMARKS = ['Lib/os.py']
186    VENV_LANDMARK = 'pyvenv.cfg'
187    ZIP_LANDMARK = f'{platlibdir}/python{VERSION_MAJOR}{VERSION_MINOR}{ABI_THREAD}.zip'
188    DELIM = ':'
189    SEP = '/'
190
191elif os_name == 'nt':
192    BUILDDIR_TXT = 'pybuilddir.txt'
193    BUILD_LANDMARK = f'{VPATH}\\Modules\\Setup.local'
194    DEFAULT_PROGRAM_NAME = f'python'
195    STDLIB_SUBDIR = 'Lib'
196    STDLIB_LANDMARKS = [f'{STDLIB_SUBDIR}\\os.py', f'{STDLIB_SUBDIR}\\os.pyc']
197    PLATSTDLIB_LANDMARK = f'{platlibdir}'
198    BUILDSTDLIB_LANDMARKS = ['Lib\\os.py']
199    VENV_LANDMARK = 'pyvenv.cfg'
200    ZIP_LANDMARK = f'python{VERSION_MAJOR}{VERSION_MINOR}{PYDEBUGEXT or ""}.zip'
201    WINREG_KEY = f'SOFTWARE\\Python\\PythonCore\\{PYWINVER}\\PythonPath'
202    DELIM = ';'
203    SEP = '\\'
204
205
206# ******************************************************************************
207# HELPER FUNCTIONS (note that we prefer C functions for performance)
208# ******************************************************************************
209
210def search_up(prefix, *landmarks, test=isfile):
211    while prefix:
212        if any(test(joinpath(prefix, f)) for f in landmarks):
213            return prefix
214        prefix = dirname(prefix)
215
216
217# ******************************************************************************
218# READ VARIABLES FROM config
219# ******************************************************************************
220
221program_name = config.get('program_name')
222home = config.get('home')
223executable = config.get('executable')
224base_executable = config.get('base_executable')
225prefix = config.get('prefix')
226exec_prefix = config.get('exec_prefix')
227base_prefix = config.get('base_prefix')
228base_exec_prefix = config.get('base_exec_prefix')
229ENV_PYTHONPATH = config['pythonpath_env']
230use_environment = config.get('use_environment', 1)
231
232pythonpath = config.get('module_search_paths')
233pythonpath_was_set = config.get('module_search_paths_set')
234stdlib_dir = config.get('stdlib_dir')
235stdlib_dir_was_set_in_config = bool(stdlib_dir)
236
237real_executable_dir = None
238platstdlib_dir = None
239
240# ******************************************************************************
241# CALCULATE program_name
242# ******************************************************************************
243
244if not program_name:
245    try:
246        program_name = config.get('orig_argv', [])[0]
247    except IndexError:
248        pass
249
250if not program_name:
251    program_name = DEFAULT_PROGRAM_NAME
252
253if EXE_SUFFIX and not hassuffix(program_name, EXE_SUFFIX) and isxfile(program_name + EXE_SUFFIX):
254    program_name = program_name + EXE_SUFFIX
255
256
257# ******************************************************************************
258# CALCULATE executable
259# ******************************************************************************
260
261if py_setpath:
262    # When Py_SetPath has been called, executable defaults to
263    # the real executable path.
264    if not executable:
265        executable = real_executable
266
267if not executable and SEP in program_name:
268    # Resolve partial path program_name against current directory
269    executable = abspath(program_name)
270
271if not executable:
272    # All platforms default to real_executable if known at this
273    # stage. POSIX does not set this value.
274    executable = real_executable
275elif os_name == 'darwin':
276    # QUIRK: On macOS we may know the real executable path, but
277    # if our caller has lied to us about it (e.g. most of
278    # test_embed), we need to use their path in order to detect
279    # whether we are in a build tree. This is true even if the
280    # executable path was provided in the config.
281    real_executable = executable
282
283if not executable and program_name and ENV_PATH:
284    # Resolve names against PATH.
285    # NOTE: The use_environment value is ignored for this lookup.
286    # To properly isolate, launch Python with a full path.
287    for p in ENV_PATH.split(DELIM):
288        p = joinpath(p, program_name)
289        if isxfile(p):
290            executable = p
291            break
292
293if not executable:
294    executable = ''
295    # When we cannot calculate the executable, subsequent searches
296    # look in the current working directory. Here, we emulate that
297    # (the former getpath.c would do it apparently by accident).
298    executable_dir = abspath('.')
299    # Also need to set this fallback in case we are running from a
300    # build directory with an invalid argv0 (i.e. test_sys.test_executable)
301    real_executable_dir = executable_dir
302
303if ENV_PYTHONEXECUTABLE or ENV___PYVENV_LAUNCHER__:
304    # If set, these variables imply that we should be using them as
305    # sys.executable and when searching for venvs. However, we should
306    # use the argv0 path for prefix calculation
307
308    if os_name == 'darwin' and WITH_NEXT_FRAMEWORK:
309        # In a framework build the binary in {sys.exec_prefix}/bin is
310        # a stub executable that execs the real interpreter in an
311        # embedded app bundle. That bundle is an implementation detail
312        # and should not affect base_executable.
313        base_executable = f"{dirname(library)}/bin/python{VERSION_MAJOR}.{VERSION_MINOR}"
314    else:
315        # Use the real executable as our base, or argv[0] otherwise
316        # (on Windows, argv[0] is likely to be ENV___PYVENV_LAUNCHER__; on
317        # other platforms, real_executable is likely to be empty)
318        base_executable = real_executable or executable
319
320    if not real_executable:
321        real_executable = base_executable
322        #real_executable_dir = dirname(real_executable)
323    executable = ENV_PYTHONEXECUTABLE or ENV___PYVENV_LAUNCHER__
324    executable_dir = dirname(executable)
325
326
327# ******************************************************************************
328# CALCULATE (default) home
329# ******************************************************************************
330
331# Used later to distinguish between Py_SetPythonHome and other
332# ways that it may have been set
333home_was_set = False
334
335if home:
336    home_was_set = True
337elif use_environment and ENV_PYTHONHOME and not py_setpath:
338    home = ENV_PYTHONHOME
339
340
341# ******************************************************************************
342# READ pyvenv.cfg
343# ******************************************************************************
344
345venv_prefix = None
346
347# Calling Py_SetPythonHome(), Py_SetPath() or
348# setting $PYTHONHOME will override venv detection.
349if not home and not py_setpath:
350    try:
351        # prefix2 is just to avoid calculating dirname again later,
352        # as the path in venv_prefix is the more common case.
353        venv_prefix2 = executable_dir or dirname(executable)
354        venv_prefix = dirname(venv_prefix2)
355        try:
356            # Read pyvenv.cfg from one level above executable
357            pyvenvcfg = readlines(joinpath(venv_prefix, VENV_LANDMARK))
358        except (FileNotFoundError, PermissionError):
359            # Try the same directory as executable
360            pyvenvcfg = readlines(joinpath(venv_prefix2, VENV_LANDMARK))
361            venv_prefix = venv_prefix2
362    except (FileNotFoundError, PermissionError):
363        venv_prefix = None
364        pyvenvcfg = []
365
366    for line in pyvenvcfg:
367        key, had_equ, value = line.partition('=')
368        if had_equ and key.strip().lower() == 'home':
369            executable_dir = real_executable_dir = value.strip()
370            if not base_executable:
371                # First try to resolve symlinked executables, since that may be
372                # more accurate than assuming the executable in 'home'.
373                try:
374                    base_executable = realpath(executable)
375                    if base_executable == executable:
376                        # No change, so probably not a link. Clear it and fall back
377                        base_executable = ''
378                except OSError:
379                    pass
380                if not base_executable:
381                    base_executable = joinpath(executable_dir, basename(executable))
382                    # It's possible "python" is executed from within a posix venv but that
383                    # "python" is not available in the "home" directory as the standard
384                    # `make install` does not create it and distros often do not provide it.
385                    #
386                    # In this case, try to fall back to known alternatives
387                    if os_name != 'nt' and not isfile(base_executable):
388                        base_exe = basename(executable)
389                        for candidate in (DEFAULT_PROGRAM_NAME, f'python{VERSION_MAJOR}.{VERSION_MINOR}'):
390                            candidate += EXE_SUFFIX if EXE_SUFFIX else ''
391                            if base_exe == candidate:
392                                continue
393                            candidate = joinpath(executable_dir, candidate)
394                            # Only set base_executable if the candidate exists.
395                            # If no candidate succeeds, subsequent errors related to
396                            # base_executable (like FileNotFoundError) remain in the
397                            # context of the original executable name
398                            if isfile(candidate):
399                                base_executable = candidate
400                                break
401            break
402    else:
403        venv_prefix = None
404
405
406# ******************************************************************************
407# CALCULATE base_executable, real_executable AND executable_dir
408# ******************************************************************************
409
410if not base_executable:
411    base_executable = executable or real_executable or ''
412
413if not real_executable:
414    real_executable = base_executable
415
416if real_executable:
417    try:
418        real_executable = realpath(real_executable)
419    except OSError as ex:
420        # Only warn if the file actually exists and was unresolvable
421        # Otherwise users who specify a fake executable may get spurious warnings.
422        if isfile(real_executable):
423            warn(f'Failed to find real location of {base_executable}')
424
425if not executable_dir and os_name == 'darwin' and library:
426    # QUIRK: macOS checks adjacent to its library early
427    library_dir = dirname(library)
428    if any(isfile(joinpath(library_dir, p)) for p in STDLIB_LANDMARKS):
429        # Exceptions here should abort the whole process (to match
430        # previous behavior)
431        executable_dir = realpath(library_dir)
432        real_executable_dir = executable_dir
433
434# If we do not have the executable's directory, we can calculate it.
435# This is the directory used to find prefix/exec_prefix if necessary.
436if not executable_dir and real_executable:
437    executable_dir = real_executable_dir = dirname(real_executable)
438
439# If we do not have the real executable's directory, we calculate it.
440# This is the directory used to detect build layouts.
441if not real_executable_dir and real_executable:
442    real_executable_dir = dirname(real_executable)
443
444# ******************************************************************************
445# DETECT _pth FILE
446# ******************************************************************************
447
448# The contents of an optional ._pth file are used to totally override
449# sys.path calculation. Its presence also implies isolated mode and
450# no-site (unless explicitly requested)
451pth = None
452pth_dir = None
453
454# Calling Py_SetPythonHome() or Py_SetPath() will override ._pth search,
455# but environment variables and command-line options cannot.
456if not py_setpath and not home_was_set:
457    # 1. Check adjacent to the main DLL/dylib/so (if set)
458    # 2. Check adjacent to the original executable
459    # 3. Check adjacent to our actual executable
460    # This may allow a venv to override the base_executable's
461    # ._pth file, but it cannot override the library's one.
462    for p in [library, executable, real_executable]:
463        if p:
464            if os_name == 'nt' and (hassuffix(p, 'exe') or hassuffix(p, 'dll')):
465                p = p.rpartition('.')[0]
466            p += '._pth'
467            try:
468                pth = readlines(p)
469                pth_dir = dirname(p)
470                break
471            except OSError:
472                pass
473
474    # If we found a ._pth file, disable environment and home
475    # detection now. Later, we will do the rest.
476    if pth_dir:
477        use_environment = 0
478        home = pth_dir
479        pythonpath = []
480
481
482# ******************************************************************************
483# CHECK FOR BUILD DIRECTORY
484# ******************************************************************************
485
486build_prefix = None
487
488if ((not home_was_set and real_executable_dir and not py_setpath)
489        or config.get('_is_python_build', 0) > 0):
490    # Detect a build marker and use it to infer prefix, exec_prefix,
491    # stdlib_dir and the platstdlib_dir directories.
492    try:
493        platstdlib_dir = joinpath(
494            real_executable_dir,
495            readlines(joinpath(real_executable_dir, BUILDDIR_TXT))[0],
496        )
497        build_prefix = joinpath(real_executable_dir, VPATH)
498    except IndexError:
499        # File exists but is empty
500        platstdlib_dir = real_executable_dir
501        build_prefix = joinpath(real_executable_dir, VPATH)
502    except (FileNotFoundError, PermissionError):
503        if isfile(joinpath(real_executable_dir, BUILD_LANDMARK)):
504            build_prefix = joinpath(real_executable_dir, VPATH)
505            if os_name == 'nt':
506                # QUIRK: Windows builds need platstdlib_dir to be the executable
507                # dir. Normally the builddir marker handles this, but in this
508                # case we need to correct manually.
509                platstdlib_dir = real_executable_dir
510
511    if build_prefix:
512        if os_name == 'nt':
513            # QUIRK: No searching for more landmarks on Windows
514            build_stdlib_prefix = build_prefix
515        else:
516            build_stdlib_prefix = search_up(build_prefix, *BUILDSTDLIB_LANDMARKS)
517        # Use the build prefix for stdlib when not explicitly set
518        if not stdlib_dir_was_set_in_config:
519            if build_stdlib_prefix:
520                stdlib_dir = joinpath(build_stdlib_prefix, 'Lib')
521            else:
522                stdlib_dir = joinpath(build_prefix, 'Lib')
523        # Only use the build prefix for prefix if it hasn't already been set
524        if not prefix:
525            prefix = build_stdlib_prefix
526        # Do not warn, because 'prefix' never equals 'build_prefix' on POSIX
527        #elif not venv_prefix and prefix != build_prefix:
528        #    warn('Detected development environment but prefix is already set')
529        if not exec_prefix:
530            exec_prefix = build_prefix
531        # Do not warn, because 'exec_prefix' never equals 'build_prefix' on POSIX
532        #elif not venv_prefix and exec_prefix != build_prefix:
533        #    warn('Detected development environment but exec_prefix is already set')
534        config['_is_python_build'] = 1
535
536
537# ******************************************************************************
538# CALCULATE prefix AND exec_prefix
539# ******************************************************************************
540
541if py_setpath:
542    # As documented, calling Py_SetPath will force both prefix
543    # and exec_prefix to the empty string.
544    prefix = exec_prefix = ''
545
546else:
547    # Read prefix and exec_prefix from explicitly set home
548    if home:
549        # When multiple paths are listed with ':' or ';' delimiters,
550        # split into prefix:exec_prefix
551        prefix, had_delim, exec_prefix = home.partition(DELIM)
552        if not had_delim:
553            exec_prefix = prefix
554        # Reset the standard library directory if it was not explicitly set
555        if not stdlib_dir_was_set_in_config:
556            stdlib_dir = None
557
558
559    # First try to detect prefix by looking alongside our runtime library, if known
560    if library and not prefix:
561        library_dir = dirname(library)
562        if ZIP_LANDMARK:
563            if os_name == 'nt':
564                # QUIRK: Windows does not search up for ZIP file
565                if isfile(joinpath(library_dir, ZIP_LANDMARK)):
566                    prefix = library_dir
567            else:
568                prefix = search_up(library_dir, ZIP_LANDMARK)
569        if STDLIB_SUBDIR and STDLIB_LANDMARKS and not prefix:
570            if any(isfile(joinpath(library_dir, f)) for f in STDLIB_LANDMARKS):
571                prefix = library_dir
572                if not stdlib_dir_was_set_in_config:
573                    stdlib_dir = joinpath(prefix, STDLIB_SUBDIR)
574
575
576    # Detect prefix by looking for zip file
577    if ZIP_LANDMARK and executable_dir and not prefix:
578        if os_name == 'nt':
579            # QUIRK: Windows does not search up for ZIP file
580            if isfile(joinpath(executable_dir, ZIP_LANDMARK)):
581                prefix = executable_dir
582        else:
583            prefix = search_up(executable_dir, ZIP_LANDMARK)
584        if prefix and not stdlib_dir_was_set_in_config:
585            stdlib_dir = joinpath(prefix, STDLIB_SUBDIR)
586            if not isdir(stdlib_dir):
587                stdlib_dir = None
588
589
590    # Detect prefix by searching from our executable location for the stdlib_dir
591    if STDLIB_SUBDIR and STDLIB_LANDMARKS and executable_dir and not prefix:
592        prefix = search_up(executable_dir, *STDLIB_LANDMARKS)
593        if prefix and not stdlib_dir:
594            stdlib_dir = joinpath(prefix, STDLIB_SUBDIR)
595
596    if PREFIX and not prefix:
597        prefix = PREFIX
598        if not any(isfile(joinpath(prefix, f)) for f in STDLIB_LANDMARKS):
599            warn('Could not find platform independent libraries <prefix>')
600
601    if not prefix:
602        prefix = abspath('')
603        warn('Could not find platform independent libraries <prefix>')
604
605
606    # Detect exec_prefix by searching from executable for the platstdlib_dir
607    if PLATSTDLIB_LANDMARK and not exec_prefix:
608        if os_name == 'nt':
609            # QUIRK: Windows always assumed these were the same
610            # gh-100320: Our PYDs are assumed to be relative to the Lib directory
611            # (that is, prefix) rather than the executable (that is, executable_dir)
612            exec_prefix = prefix
613        if not exec_prefix and executable_dir:
614            exec_prefix = search_up(executable_dir, PLATSTDLIB_LANDMARK, test=isdir)
615        if not exec_prefix and EXEC_PREFIX:
616            exec_prefix = EXEC_PREFIX
617        if not exec_prefix or not isdir(joinpath(exec_prefix, PLATSTDLIB_LANDMARK)):
618            if os_name == 'nt':
619                # QUIRK: If DLLs is missing on Windows, don't warn, just assume
620                # that they're in exec_prefix
621                if not platstdlib_dir:
622                    # gh-98790: We set platstdlib_dir here to avoid adding "DLLs" into
623                    # sys.path when it doesn't exist in the platstdlib place, which
624                    # would give Lib packages precedence over executable_dir where our
625                    # PYDs *probably* live. Ideally, whoever changes our layout will tell
626                    # us what the layout is, but in the past this worked, so it should
627                    # keep working.
628                    platstdlib_dir = exec_prefix
629            else:
630                warn('Could not find platform dependent libraries <exec_prefix>')
631
632
633    # Fallback: assume exec_prefix == prefix
634    if not exec_prefix:
635        exec_prefix = prefix
636
637
638    if not prefix or not exec_prefix:
639        warn('Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]')
640
641
642# For a venv, update the main prefix/exec_prefix but leave the base ones unchanged
643# XXX: We currently do not update prefix here, but it happens in site.py
644#if venv_prefix:
645#    base_prefix = prefix
646#    base_exec_prefix = exec_prefix
647#    prefix = exec_prefix = venv_prefix
648
649
650# ******************************************************************************
651# UPDATE pythonpath (sys.path)
652# ******************************************************************************
653
654if py_setpath:
655    # If Py_SetPath was called then it overrides any existing search path
656    config['module_search_paths'] = py_setpath.split(DELIM)
657    config['module_search_paths_set'] = 1
658
659elif not pythonpath_was_set:
660    # If pythonpath was already explicitly set or calculated, we leave it alone.
661    # This won't matter in normal use, but if an embedded host is trying to
662    # recalculate paths while running then we do not want to change it.
663    pythonpath = []
664
665    # First add entries from the process environment
666    if use_environment and ENV_PYTHONPATH:
667        for p in ENV_PYTHONPATH.split(DELIM):
668            pythonpath.append(abspath(p))
669
670    # Then add the default zip file
671    if os_name == 'nt':
672        # QUIRK: Windows uses the library directory rather than the prefix
673        if library:
674            library_dir = dirname(library)
675        else:
676            library_dir = executable_dir
677        pythonpath.append(joinpath(library_dir, ZIP_LANDMARK))
678    elif build_prefix:
679        # QUIRK: POSIX uses the default prefix when in the build directory
680        pythonpath.append(joinpath(PREFIX, ZIP_LANDMARK))
681    else:
682        pythonpath.append(joinpath(prefix, ZIP_LANDMARK))
683
684    if os_name == 'nt' and use_environment and winreg:
685        # QUIRK: Windows also lists paths in the registry. Paths are stored
686        # as the default value of each subkey of
687        # {HKCU,HKLM}\Software\Python\PythonCore\{winver}\PythonPath
688        # where winver is sys.winver (typically '3.x' or '3.x-32')
689        for hk in (winreg.HKEY_CURRENT_USER, winreg.HKEY_LOCAL_MACHINE):
690            try:
691                key = winreg.OpenKeyEx(hk, WINREG_KEY)
692                try:
693                    i = 0
694                    while True:
695                        try:
696                            v = winreg.QueryValue(key, winreg.EnumKey(key, i))
697                        except OSError:
698                            break
699                        if isinstance(v, str):
700                            pythonpath.extend(v.split(DELIM))
701                        i += 1
702                    # Paths from the core key get appended last, but only
703                    # when home was not set and we haven't found our stdlib
704                    # some other way.
705                    if not home and not stdlib_dir:
706                        v = winreg.QueryValue(key, None)
707                        if isinstance(v, str):
708                            pythonpath.extend(v.split(DELIM))
709                finally:
710                    winreg.CloseKey(key)
711            except OSError:
712                pass
713
714    # Then add any entries compiled into the PYTHONPATH macro.
715    if PYTHONPATH:
716        for p in PYTHONPATH.split(DELIM):
717            pythonpath.append(joinpath(prefix, p))
718
719    # Then add stdlib_dir and platstdlib_dir
720    if not stdlib_dir and prefix:
721        stdlib_dir = joinpath(prefix, STDLIB_SUBDIR)
722    if not platstdlib_dir and exec_prefix:
723        platstdlib_dir = joinpath(exec_prefix, PLATSTDLIB_LANDMARK)
724
725    if os_name == 'nt':
726        # QUIRK: Windows generates paths differently
727        if platstdlib_dir:
728            pythonpath.append(platstdlib_dir)
729        if stdlib_dir:
730            pythonpath.append(stdlib_dir)
731        if executable_dir and executable_dir not in pythonpath:
732            # QUIRK: the executable directory is on sys.path
733            # We keep it low priority, so that properly installed modules are
734            # found first. It may be earlier in the order if we found some
735            # reason to put it there.
736            pythonpath.append(executable_dir)
737    else:
738        if stdlib_dir:
739            pythonpath.append(stdlib_dir)
740        if platstdlib_dir:
741            pythonpath.append(platstdlib_dir)
742
743    config['module_search_paths'] = pythonpath
744    config['module_search_paths_set'] = 1
745
746
747# ******************************************************************************
748# POSIX prefix/exec_prefix QUIRKS
749# ******************************************************************************
750
751# QUIRK: Non-Windows replaces prefix/exec_prefix with defaults when running
752# in build directory. This happens after pythonpath calculation.
753if os_name != 'nt' and build_prefix:
754    prefix = config.get('prefix') or PREFIX
755    exec_prefix = config.get('exec_prefix') or EXEC_PREFIX or prefix
756
757
758# ******************************************************************************
759# SET pythonpath FROM _PTH FILE
760# ******************************************************************************
761
762if pth:
763    config['isolated'] = 1
764    config['use_environment'] = 0
765    config['site_import'] = 0
766    config['safe_path'] = 1
767    pythonpath = []
768    for line in pth:
769        line = line.partition('#')[0].strip()
770        if not line:
771            pass
772        elif line == 'import site':
773            config['site_import'] = 1
774        elif line.startswith('import '):
775            warn("unsupported 'import' line in ._pth file")
776        else:
777            pythonpath.append(joinpath(pth_dir, line))
778    config['module_search_paths'] = pythonpath
779    config['module_search_paths_set'] = 1
780
781# ******************************************************************************
782# UPDATE config FROM CALCULATED VALUES
783# ******************************************************************************
784
785config['program_name'] = program_name
786config['home'] = home
787config['executable'] = executable
788config['base_executable'] = base_executable
789config['prefix'] = prefix
790config['exec_prefix'] = exec_prefix
791config['base_prefix'] = base_prefix or prefix
792config['base_exec_prefix'] = base_exec_prefix or exec_prefix
793
794config['platlibdir'] = platlibdir
795# test_embed expects empty strings, not None
796config['stdlib_dir'] = stdlib_dir or ''
797config['platstdlib_dir'] = platstdlib_dir or ''
798