mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 10:26:02 +00:00 
			
		
		
		
	 e8c91d90ba
			
		
	
	
		e8c91d90ba
		
			
		
	
	
	
	
		
			
			On POSIX systems, excluding macOS framework installs, the lib directory for the free-threaded build now includes a "t" suffix to avoid conflicts with a co-located default build installation.
		
			
				
	
	
		
			797 lines
		
	
	
	
		
			34 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			797 lines
		
	
	
	
		
			34 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # ******************************************************************************
 | |
| # 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(...)
 | |
| # WITH_NEXT_FRAMEWORK   -- [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
 | |
| # ABI_THREAD        -- [in] either 't' for free-threaded builds or ''
 | |
| # 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
 | |
| ABI_THREAD = ABI_THREAD or ''
 | |
| 
 | |
| 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}{ABI_THREAD}'
 | |
|     STDLIB_LANDMARKS = [f'{STDLIB_SUBDIR}/os.py', f'{STDLIB_SUBDIR}/os.pyc']
 | |
|     PLATSTDLIB_LANDMARK = f'{platlibdir}/python{VERSION_MAJOR}.{VERSION_MINOR}{ABI_THREAD}/lib-dynload'
 | |
|     BUILDSTDLIB_LANDMARKS = ['Lib/os.py']
 | |
|     VENV_LANDMARK = 'pyvenv.cfg'
 | |
|     ZIP_LANDMARK = f'{platlibdir}/python{VERSION_MAJOR}{VERSION_MINOR}{ABI_THREAD}.zip'
 | |
|     DELIM = ':'
 | |
|     SEP = '/'
 | |
| 
 | |
| elif os_name == 'nt':
 | |
|     BUILDDIR_TXT = 'pybuilddir.txt'
 | |
|     BUILD_LANDMARK = f'{VPATH}\\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')
 | |
| pythonpath_was_set = config.get('module_search_paths_set')
 | |
| stdlib_dir = config.get('stdlib_dir')
 | |
| stdlib_dir_was_set_in_config = bool(stdlib_dir)
 | |
| 
 | |
| real_executable_dir = None
 | |
| platstdlib_dir = None
 | |
| 
 | |
| # ******************************************************************************
 | |
| # CALCULATE 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 and ENV_PATH:
 | |
|     # 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
 | |
| 
 | |
|     if os_name == 'darwin' and WITH_NEXT_FRAMEWORK:
 | |
|         # In a framework build the binary in {sys.exec_prefix}/bin is
 | |
|         # a stub executable that execs the real interpreter in an
 | |
|         # embedded app bundle. That bundle is an implementation detail
 | |
|         # and should not affect base_executable.
 | |
|         base_executable = f"{dirname(library)}/bin/python{VERSION_MAJOR}.{VERSION_MINOR}"
 | |
|     else:
 | |
|         # Use the real executable as our base, or argv[0] otherwise
 | |
|         # (on Windows, argv[0] is likely to be ENV___PYVENV_LAUNCHER__; on
 | |
|         # other platforms, real_executable is likely to be empty)
 | |
|         base_executable = real_executable or executable
 | |
| 
 | |
|     if not real_executable:
 | |
|         real_executable = base_executable
 | |
|         #real_executable_dir = dirname(real_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, PermissionError):
 | |
|             # Try the same directory as executable
 | |
|             pyvenvcfg = readlines(joinpath(venv_prefix2, VENV_LANDMARK))
 | |
|             venv_prefix = venv_prefix2
 | |
|     except (FileNotFoundError, PermissionError):
 | |
|         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()
 | |
|             if not base_executable:
 | |
|                 # First try to resolve symlinked executables, since that may be
 | |
|                 # more accurate than assuming the executable in 'home'.
 | |
|                 try:
 | |
|                     base_executable = realpath(executable)
 | |
|                     if base_executable == executable:
 | |
|                         # No change, so probably not a link. Clear it and fall back
 | |
|                         base_executable = ''
 | |
|                 except OSError:
 | |
|                     pass
 | |
|                 if not base_executable:
 | |
|                     base_executable = joinpath(executable_dir, basename(executable))
 | |
|                     # It's possible "python" is executed from within a posix venv but that
 | |
|                     # "python" is not available in the "home" directory as the standard
 | |
|                     # `make install` does not create it and distros often do not provide it.
 | |
|                     #
 | |
|                     # In this case, try to fall back to known alternatives
 | |
|                     if os_name != 'nt' and not isfile(base_executable):
 | |
|                         base_exe = basename(executable)
 | |
|                         for candidate in (DEFAULT_PROGRAM_NAME, f'python{VERSION_MAJOR}.{VERSION_MINOR}'):
 | |
|                             candidate += EXE_SUFFIX if EXE_SUFFIX else ''
 | |
|                             if base_exe == candidate:
 | |
|                                 continue
 | |
|                             candidate = joinpath(executable_dir, candidate)
 | |
|                             # Only set base_executable if the candidate exists.
 | |
|                             # If no candidate succeeds, subsequent errors related to
 | |
|                             # base_executable (like FileNotFoundError) remain in the
 | |
|                             # context of the original executable name
 | |
|                             if isfile(candidate):
 | |
|                                 base_executable = candidate
 | |
|                                 break
 | |
|             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
 | |
| 
 | |
| if real_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 and real_executable:
 | |
|     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 and real_executable:
 | |
|     real_executable_dir = dirname(real_executable)
 | |
| 
 | |
| # ******************************************************************************
 | |
| # DETECT _pth FILE
 | |
| # ******************************************************************************
 | |
| 
 | |
| # The contents of an optional ._pth file are used to totally override
 | |
| # sys.path calculation. 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:
 | |
|     # 1. Check adjacent to the main DLL/dylib/so (if set)
 | |
|     # 2. Check adjacent to the original executable
 | |
|     # 3. Check adjacent to our actual executable
 | |
|     # This may allow a venv to override the base_executable's
 | |
|     # ._pth file, but it cannot override the library's one.
 | |
|     for p in [library, executable, real_executable]:
 | |
|         if p:
 | |
|             if os_name == 'nt' and (hassuffix(p, 'exe') or hassuffix(p, 'dll')):
 | |
|                 p = p.rpartition('.')[0]
 | |
|             p += '._pth'
 | |
|             try:
 | |
|                 pth = readlines(p)
 | |
|                 pth_dir = dirname(p)
 | |
|                 break
 | |
|             except OSError:
 | |
|                 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)
 | |
|         or config.get('_is_python_build', 0) > 0):
 | |
|     # 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 IndexError:
 | |
|         # File exists but is empty
 | |
|         platstdlib_dir = real_executable_dir
 | |
|         build_prefix = joinpath(real_executable_dir, VPATH)
 | |
|     except (FileNotFoundError, PermissionError):
 | |
|         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)
 | |
|         # Use the build prefix for stdlib when not explicitly set
 | |
|         if not stdlib_dir_was_set_in_config:
 | |
|             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
 | |
|         # Reset the standard library directory if it was not explicitly set
 | |
|         if not stdlib_dir_was_set_in_config:
 | |
|             stdlib_dir = None
 | |
| 
 | |
| 
 | |
|     # 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
 | |
|                 if not stdlib_dir_was_set_in_config:
 | |
|                     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 and not stdlib_dir_was_set_in_config:
 | |
|             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 and not stdlib_dir:
 | |
|             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 os_name == 'nt':
 | |
|             # QUIRK: Windows always assumed these were the same
 | |
|             # gh-100320: Our PYDs are assumed to be relative to the Lib directory
 | |
|             # (that is, prefix) rather than the executable (that is, executable_dir)
 | |
|             exec_prefix = prefix
 | |
|         if not exec_prefix and executable_dir:
 | |
|             exec_prefix = search_up(executable_dir, PLATSTDLIB_LANDMARK, test=isdir)
 | |
|         if not exec_prefix and EXEC_PREFIX:
 | |
|             exec_prefix = EXEC_PREFIX
 | |
|         if not exec_prefix or not isdir(joinpath(exec_prefix, PLATSTDLIB_LANDMARK)):
 | |
|             if os_name == 'nt':
 | |
|                 # QUIRK: If DLLs is missing on Windows, don't warn, just assume
 | |
|                 # that they're in exec_prefix
 | |
|                 if not platstdlib_dir:
 | |
|                     # gh-98790: We set platstdlib_dir here to avoid adding "DLLs" into
 | |
|                     # sys.path when it doesn't exist in the platstdlib place, which
 | |
|                     # would give Lib packages precedence over executable_dir where our
 | |
|                     # PYDs *probably* live. Ideally, whoever changes our layout will tell
 | |
|                     # us what the layout is, but in the past this worked, so it should
 | |
|                     # keep working.
 | |
|                     platstdlib_dir = 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>]')
 | |
| 
 | |
| 
 | |
| # 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_was_set:
 | |
|     # If pythonpath was already explicitly set or calculated, 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:
 | |
|         # QUIRK: POSIX uses the default prefix when in the build directory
 | |
|         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:
 | |
|                             v = winreg.QueryValue(key, winreg.EnumKey(key, i))
 | |
|                         except OSError:
 | |
|                             break
 | |
|                         if isinstance(v, str):
 | |
|                             pythonpath.extend(v.split(DELIM))
 | |
|                         i += 1
 | |
|                     # Paths from the core key get appended last, but only
 | |
|                     # when home was not set and we haven't found our stdlib
 | |
|                     # some other way.
 | |
|                     if not home and not stdlib_dir:
 | |
|                         v = winreg.QueryValue(key, None)
 | |
|                         if isinstance(v, str):
 | |
|                             pythonpath.extend(v.split(DELIM))
 | |
|                 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 not stdlib_dir and prefix:
 | |
|         stdlib_dir = joinpath(prefix, STDLIB_SUBDIR)
 | |
|     if not platstdlib_dir and exec_prefix:
 | |
|         platstdlib_dir = joinpath(exec_prefix, PLATSTDLIB_LANDMARK)
 | |
| 
 | |
|     if os_name == 'nt':
 | |
|         # QUIRK: Windows generates paths differently
 | |
|         if platstdlib_dir:
 | |
|             pythonpath.append(platstdlib_dir)
 | |
|         if stdlib_dir:
 | |
|             pythonpath.append(stdlib_dir)
 | |
|         if executable_dir and executable_dir not in pythonpath:
 | |
|             # QUIRK: the executable directory is on sys.path
 | |
|             # We keep it low priority, so that properly installed modules are
 | |
|             # found first. It may be earlier in the order if we found some
 | |
|             # reason to put it there.
 | |
|             pythonpath.append(executable_dir)
 | |
|     else:
 | |
|         if stdlib_dir:
 | |
|             pythonpath.append(stdlib_dir)
 | |
|         if platstdlib_dir:
 | |
|             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
 | |
|     config['safe_path'] = 1
 | |
|     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
 | |
| # test_embed expects empty strings, not None
 | |
| config['stdlib_dir'] = stdlib_dir or ''
 | |
| config['platstdlib_dir'] = platstdlib_dir or ''
 |