summaryrefslogtreecommitdiffstats
path: root/Modules/getpath.py
diff options
context:
space:
mode:
Diffstat (limited to 'Modules/getpath.py')
-rw-r--r--Modules/getpath.py727
1 files changed, 727 insertions, 0 deletions
diff --git a/Modules/getpath.py b/Modules/getpath.py
new file mode 100644
index 0000000..2eadfba
--- /dev/null
+++ b/Modules/getpath.py
@@ -0,0 +1,727 @@
+# ******************************************************************************
+# getpath.py
+# ******************************************************************************
+
+# This script is designed to be precompiled to bytecode, frozen into the
+# main binary, and then directly evaluated. It is not an importable module,
+# and does not import any other modules (besides winreg on Windows).
+# Rather, the values listed below must be specified in the globals dict
+# used when evaluating the bytecode.
+
+# See _PyConfig_InitPathConfig in Modules/getpath.c for the execution.
+
+# ******************************************************************************
+# REQUIRED GLOBALS
+# ******************************************************************************
+
+# ** Helper functions **
+# abspath(path) -- make relative paths absolute against CWD
+# basename(path) -- the filename of path
+# dirname(path) -- the directory name of path
+# hassuffix(path, suffix) -- returns True if path has suffix
+# isabs(path) -- path is absolute or not
+# isdir(path) -- path exists and is a directory
+# isfile(path) -- path exists and is a file
+# isxfile(path) -- path exists and is an executable file
+# joinpath(*paths) -- combine the paths
+# readlines(path) -- a list of each line of text in the UTF-8 encoded file
+# realpath(path) -- resolves symlinks in path
+# warn(message) -- print a warning (if enabled)
+
+# ** Values known at compile time **
+# os_name -- [in] one of 'nt', 'posix', 'darwin'
+# PREFIX -- [in] sysconfig.get_config_var(...)
+# EXEC_PREFIX -- [in] sysconfig.get_config_var(...)
+# PYTHONPATH -- [in] sysconfig.get_config_var(...)
+# VPATH -- [in] sysconfig.get_config_var(...)
+# PLATLIBDIR -- [in] sysconfig.get_config_var(...)
+# PYDEBUGEXT -- [in, opt] '_d' on Windows for debug builds
+# EXE_SUFFIX -- [in, opt] '.exe' on Windows/Cygwin/similar
+# VERSION_MAJOR -- [in] sys.version_info.major
+# VERSION_MINOR -- [in] sys.version_info.minor
+# PYWINVER -- [in] the Windows platform-specific version (e.g. 3.8-32)
+
+# ** Values read from the environment **
+# There is no need to check the use_environment flag before reading
+# these, as the flag will be tested in this script.
+# Also note that ENV_PYTHONPATH is read from config['pythonpath_env']
+# to allow for embedders who choose to specify it via that struct.
+# ENV_PATH -- [in] getenv(...)
+# ENV_PYTHONHOME -- [in] getenv(...)
+# ENV_PYTHONEXECUTABLE -- [in] getenv(...)
+# ENV___PYVENV_LAUNCHER__ -- [in] getenv(...)
+
+# ** Values calculated at runtime **
+# config -- [in/out] dict of the PyConfig structure
+# real_executable -- [in, optional] resolved path to main process
+# On Windows and macOS, read directly from the running process
+# Otherwise, leave None and it will be calculated from executable
+# executable_dir -- [in, optional] real directory containing binary
+# If None, will be calculated from real_executable or executable
+# py_setpath -- [in] argument provided to Py_SetPath
+# If None, 'prefix' and 'exec_prefix' may be updated in config
+# library -- [in, optional] path of dylib/DLL/so
+# Only used for locating ._pth files
+# winreg -- [in, optional] the winreg module (only on Windows)
+
+# ******************************************************************************
+# HIGH-LEVEL ALGORITHM
+# ******************************************************************************
+
+# IMPORTANT: The code is the actual specification at time of writing.
+# This prose description is based on the original comment from the old
+# getpath.c to help capture the intent, but should not be considered
+# a specification.
+
+# Search in some common locations for the associated Python libraries.
+
+# Two directories must be found, the platform independent directory
+# (prefix), containing the common .py and .pyc files, and the platform
+# dependent directory (exec_prefix), containing the shared library
+# modules. Note that prefix and exec_prefix can be the same directory,
+# but for some installations, they are different.
+
+# This script carries out separate searches for prefix and exec_prefix.
+# Each search tries a number of different locations until a ``landmark''
+# file or directory is found. If no prefix or exec_prefix is found, a
+# warning message is issued and the preprocessor defined PREFIX and
+# EXEC_PREFIX are used (even though they will not work); python carries on
+# as best as is possible, but most imports will fail.
+
+# Before any searches are done, the location of the executable is
+# determined. If Py_SetPath() was called, or if we are running on
+# Windows, the 'real_executable' path is used (if known). Otherwise,
+# we use the config-specified program name or default to argv[0].
+# If this has one or more slashes in it, it is made absolute against
+# the current working directory. If it only contains a name, it must
+# have been invoked from the shell's path, so we search $PATH for the
+# named executable and use that. If the executable was not found on
+# $PATH (or there was no $PATH environment variable), the original
+# argv[0] string is used.
+
+# At this point, provided Py_SetPath was not used, the
+# __PYVENV_LAUNCHER__ variable may override the executable (on macOS,
+# the PYTHON_EXECUTABLE variable may also override). This allows
+# certain launchers that run Python as a subprocess to properly
+# specify the executable path. They are not intended for users.
+
+# Next, the executable location is examined to see if it is a symbolic
+# link. If so, the link is realpath-ed and the directory of the link
+# target is used for the remaining searches. The same steps are
+# performed for prefix and for exec_prefix, but with different landmarks.
+
+# Step 1. Are we running in a virtual environment? Unless 'home' has
+# been specified another way, check for a pyvenv.cfg and use its 'home'
+# property to override the executable dir used later for prefix searches.
+# We do not activate the venv here - that is performed later by site.py.
+
+# Step 2. Is there a ._pth file? A ._pth file lives adjacent to the
+# runtime library (if any) or the actual executable (not the symlink),
+# and contains precisely the intended contents of sys.path as relative
+# paths (to its own location). Its presence also enables isolated mode
+# and suppresses other environment variable usage. Unless already
+# specified by Py_SetHome(), the directory containing the ._pth file is
+# set as 'home'.
+
+# Step 3. Are we running python out of the build directory? This is
+# checked by looking for the BUILDDIR_TXT file, which contains the
+# relative path to the platlib dir. The executable_dir value is
+# derived from joining the VPATH preprocessor variable to the
+# directory containing pybuilddir.txt. If it is not found, the
+# BUILD_LANDMARK file is found, which is part of the source tree.
+# prefix is then found by searching up for a file that should only
+# exist in the source tree, and the stdlib dir is set to prefix/Lib.
+
+# Step 4. If 'home' is set, either by Py_SetHome(), ENV_PYTHONHOME,
+# a pyvenv.cfg file, ._pth file, or by detecting a build directory, it
+# is assumed to point to prefix and exec_prefix. $PYTHONHOME can be a
+# single directory, which is used for both, or the prefix and exec_prefix
+# directories separated by DELIM (colon on POSIX; semicolon on Windows).
+
+# Step 5. Try to find prefix and exec_prefix relative to executable_dir,
+# backtracking up the path until it is exhausted. This is the most common
+# step to succeed. Note that if prefix and exec_prefix are different,
+# exec_prefix is more likely to be found; however if exec_prefix is a
+# subdirectory of prefix, both will be found.
+
+# Step 6. Search the directories pointed to by the preprocessor variables
+# PREFIX and EXEC_PREFIX. These are supplied by the Makefile but can be
+# passed in as options to the configure script.
+
+# That's it!
+
+# Well, almost. Once we have determined prefix and exec_prefix, the
+# preprocessor variable PYTHONPATH is used to construct a path. Each
+# relative path on PYTHONPATH is prefixed with prefix. Then the directory
+# containing the shared library modules is appended. The environment
+# variable $PYTHONPATH is inserted in front of it all. On POSIX, if we are
+# in a build directory, both prefix and exec_prefix are reset to the
+# corresponding preprocessor variables (so sys.prefix will reflect the
+# installation location, even though sys.path points into the build
+# directory). This seems to make more sense given that currently the only
+# known use of sys.prefix and sys.exec_prefix is for the ILU installation
+# process to find the installed Python tree.
+
+# An embedding application can use Py_SetPath() to override all of
+# these automatic path computations.
+
+
+# ******************************************************************************
+# PLATFORM CONSTANTS
+# ******************************************************************************
+
+platlibdir = config.get('platlibdir') or PLATLIBDIR
+
+if os_name == 'posix' or os_name == 'darwin':
+ BUILDDIR_TXT = 'pybuilddir.txt'
+ BUILD_LANDMARK = 'Modules/Setup.local'
+ DEFAULT_PROGRAM_NAME = f'python{VERSION_MAJOR}'
+ STDLIB_SUBDIR = f'{platlibdir}/python{VERSION_MAJOR}.{VERSION_MINOR}'
+ STDLIB_LANDMARKS = [f'{STDLIB_SUBDIR}/os.py', f'{STDLIB_SUBDIR}/os.pyc']
+ PLATSTDLIB_LANDMARK = f'{platlibdir}/python{VERSION_MAJOR}.{VERSION_MINOR}/lib-dynload'
+ BUILDSTDLIB_LANDMARKS = ['Lib/os.py']
+ VENV_LANDMARK = 'pyvenv.cfg'
+ ZIP_LANDMARK = f'{platlibdir}/python{VERSION_MAJOR}{VERSION_MINOR}.zip'
+ DELIM = ':'
+ SEP = '/'
+
+elif os_name == 'nt':
+ BUILDDIR_TXT = 'pybuilddir.txt'
+ BUILD_LANDMARK = r'..\..\Modules\Setup.local'
+ DEFAULT_PROGRAM_NAME = f'python'
+ STDLIB_SUBDIR = 'Lib'
+ STDLIB_LANDMARKS = [f'{STDLIB_SUBDIR}\\os.py', f'{STDLIB_SUBDIR}\\os.pyc']
+ PLATSTDLIB_LANDMARK = f'{platlibdir}'
+ BUILDSTDLIB_LANDMARKS = ['Lib\\os.py']
+ VENV_LANDMARK = 'pyvenv.cfg'
+ ZIP_LANDMARK = f'python{VERSION_MAJOR}{VERSION_MINOR}{PYDEBUGEXT or ""}.zip'
+ WINREG_KEY = f'SOFTWARE\\Python\\PythonCore\\{PYWINVER}\\PythonPath'
+ DELIM = ';'
+ SEP = '\\'
+
+
+# ******************************************************************************
+# HELPER FUNCTIONS (note that we prefer C functions for performance)
+# ******************************************************************************
+
+def search_up(prefix, *landmarks, test=isfile):
+ while prefix:
+ if any(test(joinpath(prefix, f)) for f in landmarks):
+ return prefix
+ prefix = dirname(prefix)
+
+
+# ******************************************************************************
+# READ VARIABLES FROM config
+# ******************************************************************************
+
+program_name = config.get('program_name')
+home = config.get('home')
+executable = config.get('executable')
+base_executable = config.get('base_executable')
+prefix = config.get('prefix')
+exec_prefix = config.get('exec_prefix')
+base_prefix = config.get('base_prefix')
+base_exec_prefix = config.get('base_exec_prefix')
+ENV_PYTHONPATH = config['pythonpath_env']
+use_environment = config.get('use_environment', 1)
+
+pythonpath = config.get('module_search_paths')
+
+real_executable_dir = None
+stdlib_dir = None
+platstdlib_dir = None
+
+# ******************************************************************************
+# CALCULATE program_name
+# ******************************************************************************
+
+program_name_was_set = bool(program_name)
+
+if not program_name:
+ try:
+ program_name = config.get('orig_argv', [])[0]
+ except IndexError:
+ pass
+
+if not program_name:
+ program_name = DEFAULT_PROGRAM_NAME
+
+if EXE_SUFFIX and not hassuffix(program_name, EXE_SUFFIX) and isxfile(program_name + EXE_SUFFIX):
+ program_name = program_name + EXE_SUFFIX
+
+
+# ******************************************************************************
+# CALCULATE executable
+# ******************************************************************************
+
+if py_setpath:
+ # When Py_SetPath has been called, executable defaults to
+ # the real executable path.
+ if not executable:
+ executable = real_executable
+
+if not executable and SEP in program_name:
+ # Resolve partial path program_name against current directory
+ executable = abspath(program_name)
+
+if not executable:
+ # All platforms default to real_executable if known at this
+ # stage. POSIX does not set this value.
+ executable = real_executable
+elif os_name == 'darwin':
+ # QUIRK: On macOS we may know the real executable path, but
+ # if our caller has lied to us about it (e.g. most of
+ # test_embed), we need to use their path in order to detect
+ # whether we are in a build tree. This is true even if the
+ # executable path was provided in the config.
+ real_executable = executable
+
+if not executable and program_name:
+ # Resolve names against PATH.
+ # NOTE: The use_environment value is ignored for this lookup.
+ # To properly isolate, launch Python with a full path.
+ for p in ENV_PATH.split(DELIM):
+ p = joinpath(p, program_name)
+ if isxfile(p):
+ executable = p
+ break
+
+if not executable:
+ executable = ''
+ # When we cannot calculate the executable, subsequent searches
+ # look in the current working directory. Here, we emulate that
+ # (the former getpath.c would do it apparently by accident).
+ executable_dir = abspath('.')
+ # Also need to set this fallback in case we are running from a
+ # build directory with an invalid argv0 (i.e. test_sys.test_executable)
+ real_executable_dir = executable_dir
+
+if ENV_PYTHONEXECUTABLE or ENV___PYVENV_LAUNCHER__:
+ # If set, these variables imply that we should be using them as
+ # sys.executable and when searching for venvs. However, we should
+ # use the argv0 path for prefix calculation
+ base_executable = executable
+ if not real_executable:
+ real_executable = executable
+ executable = ENV_PYTHONEXECUTABLE or ENV___PYVENV_LAUNCHER__
+ executable_dir = dirname(executable)
+
+
+# ******************************************************************************
+# CALCULATE (default) home
+# ******************************************************************************
+
+# Used later to distinguish between Py_SetPythonHome and other
+# ways that it may have been set
+home_was_set = False
+
+if home:
+ home_was_set = True
+elif use_environment and ENV_PYTHONHOME and not py_setpath:
+ home = ENV_PYTHONHOME
+
+
+# ******************************************************************************
+# READ pyvenv.cfg
+# ******************************************************************************
+
+venv_prefix = None
+
+# Calling Py_SetPythonHome(), Py_SetPath() or
+# setting $PYTHONHOME will override venv detection.
+if not home and not py_setpath:
+ try:
+ # prefix2 is just to avoid calculating dirname again later,
+ # as the path in venv_prefix is the more common case.
+ venv_prefix2 = executable_dir or dirname(executable)
+ venv_prefix = dirname(venv_prefix2)
+ try:
+ # Read pyvenv.cfg from one level above executable
+ pyvenvcfg = readlines(joinpath(venv_prefix, VENV_LANDMARK))
+ except FileNotFoundError:
+ # Try the same directory as executable
+ pyvenvcfg = readlines(joinpath(venv_prefix2, VENV_LANDMARK))
+ venv_prefix = venv_prefix2
+ except FileNotFoundError:
+ venv_prefix = None
+ pyvenvcfg = []
+
+ for line in pyvenvcfg:
+ key, had_equ, value = line.partition('=')
+ if had_equ and key.strip().lower() == 'home':
+ executable_dir = real_executable_dir = value.strip()
+ base_executable = joinpath(executable_dir, basename(executable))
+ break
+ else:
+ venv_prefix = None
+
+
+# ******************************************************************************
+# CALCULATE base_executable, real_executable AND executable_dir
+# ******************************************************************************
+
+if not base_executable:
+ base_executable = executable or real_executable or ''
+
+if not real_executable:
+ real_executable = base_executable
+
+try:
+ real_executable = realpath(real_executable)
+except OSError as ex:
+ # Only warn if the file actually exists and was unresolvable
+ # Otherwise users who specify a fake executable may get spurious warnings.
+ if isfile(real_executable):
+ warn(f'Failed to find real location of {base_executable}')
+
+if not executable_dir and os_name == 'darwin' and library:
+ # QUIRK: macOS checks adjacent to its library early
+ library_dir = dirname(library)
+ if any(isfile(joinpath(library_dir, p)) for p in STDLIB_LANDMARKS):
+ # Exceptions here should abort the whole process (to match
+ # previous behavior)
+ executable_dir = realpath(library_dir)
+ real_executable_dir = executable_dir
+
+# If we do not have the executable's directory, we can calculate it.
+# This is the directory used to find prefix/exec_prefix if necessary.
+if not executable_dir:
+ executable_dir = real_executable_dir = dirname(real_executable)
+
+# If we do not have the real executable's directory, we calculate it.
+# This is the directory used to detect build layouts.
+if not real_executable_dir:
+ real_executable_dir = dirname(real_executable)
+
+# ******************************************************************************
+# DETECT _pth FILE
+# ******************************************************************************
+
+# The contents of an optional ._pth file are used to totally override
+# sys.path calcualation. Its presence also implies isolated mode and
+# no-site (unless explicitly requested)
+pth = None
+pth_dir = None
+
+# Calling Py_SetPythonHome() or Py_SetPath() will override ._pth search,
+# but environment variables and command-line options cannot.
+if not py_setpath and not home_was_set:
+ # Check adjacent to the main DLL/dylib/so
+ if library:
+ try:
+ pth = readlines(library.rpartition('.')[0] + '._pth')
+ pth_dir = dirname(library)
+ except FileNotFoundError:
+ pass
+
+ # Check adjacent to the original executable, even if we
+ # redirected to actually launch Python. This may allow a
+ # venv to override the base_executable's ._pth file, but
+ # it cannot override the library's one.
+ if not pth_dir:
+ try:
+ pth = readlines(executable.rpartition('.')[0] + '._pth')
+ pth_dir = dirname(executable)
+ except FileNotFoundError:
+ pass
+
+ # If we found a ._pth file, disable environment and home
+ # detection now. Later, we will do the rest.
+ if pth_dir:
+ use_environment = 0
+ home = pth_dir
+ pythonpath = []
+
+
+# ******************************************************************************
+# CHECK FOR BUILD DIRECTORY
+# ******************************************************************************
+
+build_prefix = None
+
+if not home_was_set and real_executable_dir and not py_setpath:
+ # Detect a build marker and use it to infer prefix, exec_prefix,
+ # stdlib_dir and the platstdlib_dir directories.
+ try:
+ platstdlib_dir = joinpath(
+ real_executable_dir,
+ readlines(joinpath(real_executable_dir, BUILDDIR_TXT))[0],
+ )
+ build_prefix = joinpath(real_executable_dir, VPATH)
+ except FileNotFoundError:
+ if isfile(joinpath(real_executable_dir, BUILD_LANDMARK)):
+ build_prefix = joinpath(real_executable_dir, VPATH)
+ if os_name == 'nt':
+ # QUIRK: Windows builds need platstdlib_dir to be the executable
+ # dir. Normally the builddir marker handles this, but in this
+ # case we need to correct manually.
+ platstdlib_dir = real_executable_dir
+
+ if build_prefix:
+ if os_name == 'nt':
+ # QUIRK: No searching for more landmarks on Windows
+ build_stdlib_prefix = build_prefix
+ else:
+ build_stdlib_prefix = search_up(build_prefix, *BUILDSTDLIB_LANDMARKS)
+ # Always use the build prefix for stdlib
+ if build_stdlib_prefix:
+ stdlib_dir = joinpath(build_stdlib_prefix, 'Lib')
+ else:
+ stdlib_dir = joinpath(build_prefix, 'Lib')
+ # Only use the build prefix for prefix if it hasn't already been set
+ if not prefix:
+ prefix = build_stdlib_prefix
+ # Do not warn, because 'prefix' never equals 'build_prefix' on POSIX
+ #elif not venv_prefix and prefix != build_prefix:
+ # warn('Detected development environment but prefix is already set')
+ if not exec_prefix:
+ exec_prefix = build_prefix
+ # Do not warn, because 'exec_prefix' never equals 'build_prefix' on POSIX
+ #elif not venv_prefix and exec_prefix != build_prefix:
+ # warn('Detected development environment but exec_prefix is already set')
+ config['_is_python_build'] = 1
+
+
+# ******************************************************************************
+# CALCULATE prefix AND exec_prefix
+# ******************************************************************************
+
+if py_setpath:
+ # As documented, calling Py_SetPath will force both prefix
+ # and exec_prefix to the empty string.
+ prefix = exec_prefix = ''
+
+else:
+ # Read prefix and exec_prefix from explicitly set home
+ if home:
+ # When multiple paths are listed with ':' or ';' delimiters,
+ # split into prefix:exec_prefix
+ prefix, had_delim, exec_prefix = home.partition(DELIM)
+ if not had_delim:
+ exec_prefix = prefix
+
+
+ # First try to detect prefix by looking alongside our runtime library, if known
+ if library and not prefix:
+ library_dir = dirname(library)
+ if ZIP_LANDMARK:
+ if os_name == 'nt':
+ # QUIRK: Windows does not search up for ZIP file
+ if isfile(joinpath(library_dir, ZIP_LANDMARK)):
+ prefix = library_dir
+ else:
+ prefix = search_up(library_dir, ZIP_LANDMARK)
+ if STDLIB_SUBDIR and STDLIB_LANDMARKS and not prefix:
+ if any(isfile(joinpath(library_dir, f)) for f in STDLIB_LANDMARKS):
+ prefix = library_dir
+ stdlib_dir = joinpath(prefix, STDLIB_SUBDIR)
+
+
+ # Detect prefix by looking for zip file
+ if ZIP_LANDMARK and executable_dir and not prefix:
+ if os_name == 'nt':
+ # QUIRK: Windows does not search up for ZIP file
+ if isfile(joinpath(executable_dir, ZIP_LANDMARK)):
+ prefix = executable_dir
+ else:
+ prefix = search_up(executable_dir, ZIP_LANDMARK)
+ if prefix:
+ stdlib_dir = joinpath(prefix, STDLIB_SUBDIR)
+ if not isdir(stdlib_dir):
+ stdlib_dir = None
+
+
+ # Detect prefix by searching from our executable location for the stdlib_dir
+ if STDLIB_SUBDIR and STDLIB_LANDMARKS and executable_dir and not prefix:
+ prefix = search_up(executable_dir, *STDLIB_LANDMARKS)
+ if prefix:
+ stdlib_dir = joinpath(prefix, STDLIB_SUBDIR)
+
+ if PREFIX and not prefix:
+ prefix = PREFIX
+ if not any(isfile(joinpath(prefix, f)) for f in STDLIB_LANDMARKS):
+ warn('Could not find platform independent libraries <prefix>')
+
+ if not prefix:
+ prefix = abspath('')
+ warn('Could not find platform independent libraries <prefix>')
+
+
+ # Detect exec_prefix by searching from executable for the platstdlib_dir
+ if PLATSTDLIB_LANDMARK and not exec_prefix:
+ if executable_dir:
+ exec_prefix = search_up(executable_dir, PLATSTDLIB_LANDMARK, test=isdir)
+ if not exec_prefix:
+ if EXEC_PREFIX:
+ exec_prefix = EXEC_PREFIX
+ if not isdir(joinpath(exec_prefix, PLATSTDLIB_LANDMARK)):
+ warn('Could not find platform dependent libraries <exec_prefix>')
+ else:
+ warn('Could not find platform dependent libraries <exec_prefix>')
+
+ # Fallback: assume exec_prefix == prefix
+ if not exec_prefix:
+ exec_prefix = prefix
+
+
+ if not prefix or not exec_prefix:
+ warn('Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]')
+
+
+# If we haven't set [plat]stdlib_dir already, set them now
+if not stdlib_dir:
+ if prefix:
+ stdlib_dir = joinpath(prefix, STDLIB_SUBDIR)
+ else:
+ stdlib_dir = ''
+
+if not platstdlib_dir:
+ if exec_prefix:
+ platstdlib_dir = joinpath(exec_prefix, PLATSTDLIB_LANDMARK)
+ else:
+ platstdlib_dir = ''
+
+
+# For a venv, update the main prefix/exec_prefix but leave the base ones unchanged
+# XXX: We currently do not update prefix here, but it happens in site.py
+#if venv_prefix:
+# base_prefix = prefix
+# base_exec_prefix = exec_prefix
+# prefix = exec_prefix = venv_prefix
+
+
+# ******************************************************************************
+# UPDATE pythonpath (sys.path)
+# ******************************************************************************
+
+if py_setpath:
+ # If Py_SetPath was called then it overrides any existing search path
+ config['module_search_paths'] = py_setpath.split(DELIM)
+ config['module_search_paths_set'] = 1
+
+elif not pythonpath:
+ # If pythonpath was already set, we leave it alone.
+ # This won't matter in normal use, but if an embedded host is trying to
+ # recalculate paths while running then we do not want to change it.
+ pythonpath = []
+
+ # First add entries from the process environment
+ if use_environment and ENV_PYTHONPATH:
+ for p in ENV_PYTHONPATH.split(DELIM):
+ pythonpath.append(abspath(p))
+
+ # Then add the default zip file
+ if os_name == 'nt':
+ # QUIRK: Windows uses the library directory rather than the prefix
+ if library:
+ library_dir = dirname(library)
+ else:
+ library_dir = executable_dir
+ pythonpath.append(joinpath(library_dir, ZIP_LANDMARK))
+ elif build_prefix or venv_prefix:
+ # QUIRK: POSIX uses the default prefix when in the build directory
+ # or a venv
+ pythonpath.append(joinpath(PREFIX, ZIP_LANDMARK))
+ else:
+ pythonpath.append(joinpath(prefix, ZIP_LANDMARK))
+
+ if os_name == 'nt' and use_environment and winreg:
+ # QUIRK: Windows also lists paths in the registry. Paths are stored
+ # as the default value of each subkey of
+ # {HKCU,HKLM}\Software\Python\PythonCore\{winver}\PythonPath
+ # where winver is sys.winver (typically '3.x' or '3.x-32')
+ for hk in (winreg.HKEY_CURRENT_USER, winreg.HKEY_LOCAL_MACHINE):
+ try:
+ key = winreg.OpenKeyEx(hk, WINREG_KEY)
+ try:
+ i = 0
+ while True:
+ try:
+ keyname = winreg.EnumKey(key, i)
+ subkey = winreg.OpenKeyEx(key, keyname)
+ if not subkey:
+ continue
+ try:
+ v = winreg.QueryValue(subkey)
+ finally:
+ winreg.CloseKey(subkey)
+ if isinstance(v, str):
+ pythonpath.append(v)
+ i += 1
+ except OSError:
+ break
+ finally:
+ winreg.CloseKey(key)
+ except OSError:
+ pass
+
+ # Then add any entries compiled into the PYTHONPATH macro.
+ if PYTHONPATH:
+ for p in PYTHONPATH.split(DELIM):
+ pythonpath.append(joinpath(prefix, p))
+
+ # Then add stdlib_dir and platstdlib_dir
+ if stdlib_dir:
+ pythonpath.append(stdlib_dir)
+ if platstdlib_dir:
+ if os_name == 'nt' and venv_prefix:
+ # QUIRK: Windows appends executable_dir instead of platstdlib_dir
+ # when in a venv
+ pythonpath.append(executable_dir)
+ else:
+ pythonpath.append(platstdlib_dir)
+
+ config['module_search_paths'] = pythonpath
+ config['module_search_paths_set'] = 1
+
+
+# ******************************************************************************
+# POSIX prefix/exec_prefix QUIRKS
+# ******************************************************************************
+
+# QUIRK: Non-Windows replaces prefix/exec_prefix with defaults when running
+# in build directory. This happens after pythonpath calculation.
+if os_name != 'nt' and build_prefix:
+ prefix = config.get('prefix') or PREFIX
+ exec_prefix = config.get('exec_prefix') or EXEC_PREFIX or prefix
+
+
+# ******************************************************************************
+# SET pythonpath FROM _PTH FILE
+# ******************************************************************************
+
+if pth:
+ config['isolated'] = 1
+ config['use_environment'] = 0
+ config['site_import'] = 0
+ pythonpath = []
+ for line in pth:
+ line = line.partition('#')[0].strip()
+ if not line:
+ pass
+ elif line == 'import site':
+ config['site_import'] = 1
+ elif line.startswith('import '):
+ warn("unsupported 'import' line in ._pth file")
+ else:
+ pythonpath.append(joinpath(pth_dir, line))
+ config['module_search_paths'] = pythonpath
+ config['module_search_paths_set'] = 1
+
+# ******************************************************************************
+# UPDATE config FROM CALCULATED VALUES
+# ******************************************************************************
+
+config['program_name'] = program_name
+config['home'] = home
+config['executable'] = executable
+config['base_executable'] = base_executable
+config['prefix'] = prefix
+config['exec_prefix'] = exec_prefix
+config['base_prefix'] = base_prefix or prefix
+config['base_exec_prefix'] = base_exec_prefix or exec_prefix
+
+config['platlibdir'] = platlibdir
+config['stdlib_dir'] = stdlib_dir
+config['platstdlib_dir'] = platstdlib_dir