1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797
|
# ******************************************************************************
# 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 ''
|