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