1 """Append module search paths for third-party packages to sys.path. 2 3 **************************************************************** 4 * This module is automatically imported during initialization. * 5 **************************************************************** 6 7 This will append site-specific paths to the module search path. On 8 Unix (including Mac OSX), it starts with sys.prefix and 9 sys.exec_prefix (if different) and appends 10 lib/python<version>/site-packages. 11 On other platforms (such as Windows), it tries each of the 12 prefixes directly, as well as with lib/site-packages appended. The 13 resulting directories, if they exist, are appended to sys.path, and 14 also inspected for path configuration files. 15 16 If a file named "pyvenv.cfg" exists one directory above sys.executable, 17 sys.prefix and sys.exec_prefix are set to that directory and 18 it is also checked for site-packages (sys.base_prefix and 19 sys.base_exec_prefix will always be the "real" prefixes of the Python 20 installation). If "pyvenv.cfg" (a bootstrap configuration file) contains 21 the key "include-system-site-packages" set to anything other than "false" 22 (case-insensitive), the system-level prefixes will still also be 23 searched for site-packages; otherwise they won't. 24 25 All of the resulting site-specific directories, if they exist, are 26 appended to sys.path, and also inspected for path configuration 27 files. 28 29 A path configuration file is a file whose name has the form 30 <package>.pth; its contents are additional directories (one per line) 31 to be added to sys.path. Non-existing directories (or 32 non-directories) are never added to sys.path; no directory is added to 33 sys.path more than once. Blank lines and lines beginning with 34 '#' are skipped. Lines starting with 'import' are executed. 35 36 For example, suppose sys.prefix and sys.exec_prefix are set to 37 /usr/local and there is a directory /usr/local/lib/python2.5/site-packages 38 with three subdirectories, foo, bar and spam, and two path 39 configuration files, foo.pth and bar.pth. Assume foo.pth contains the 40 following: 41 42 # foo package configuration 43 foo 44 bar 45 bletch 46 47 and bar.pth contains: 48 49 # bar package configuration 50 bar 51 52 Then the following directories are added to sys.path, in this order: 53 54 /usr/local/lib/python2.5/site-packages/bar 55 /usr/local/lib/python2.5/site-packages/foo 56 57 Note that bletch is omitted because it doesn't exist; bar precedes foo 58 because bar.pth comes alphabetically before foo.pth; and spam is 59 omitted because it is not mentioned in either path configuration file. 60 61 The readline module is also automatically configured to enable 62 completion for systems that support it. This can be overridden in 63 sitecustomize, usercustomize or PYTHONSTARTUP. Starting Python in 64 isolated mode (-I) disables automatic readline configuration. 65 66 After these operations, an attempt is made to import a module 67 named sitecustomize, which can perform arbitrary additional 68 site-specific customizations. If this import fails with an 69 ImportError exception, it is silently ignored. 70 """ 71 72 import sys 73 import os 74 import builtins 75 import _sitebuiltins 76 77 # Prefixes for site-packages; add additional prefixes like /usr/local here 78 PREFIXES = [sys.prefix, sys.exec_prefix] 79 # Enable per user site-packages directory 80 # set it to False to disable the feature or True to force the feature 81 ENABLE_USER_SITE = None 82 83 # for distutils.commands.install 84 # These values are initialized by the getuserbase() and getusersitepackages() 85 # functions, through the main() function when Python starts. 86 USER_SITE = None 87 USER_BASE = None 88 89 90 def makepath(*paths): 91 dir = os.path.join(*paths) 92 try: 93 dir = os.path.abspath(dir) 94 except OSError: 95 pass 96 return dir, os.path.normcase(dir) 97 98 99 def abs_paths(): 100 """Set all module __file__ and __cached__ attributes to an absolute path""" 101 for m in set(sys.modules.values()): 102 if (getattr(getattr(m, '__loader__', None), '__module__', None) not in 103 ('_frozen_importlib', '_frozen_importlib_external')): 104 continue # don't mess with a PEP 302-supplied __file__ 105 try: 106 m.__file__ = os.path.abspath(m.__file__) 107 except (AttributeError, OSError): 108 pass 109 try: 110 m.__cached__ = os.path.abspath(m.__cached__) 111 except (AttributeError, OSError): 112 pass 113 114 115 def removeduppaths(): 116 """ Remove duplicate entries from sys.path along with making them 117 absolute""" 118 # This ensures that the initial path provided by the interpreter contains 119 # only absolute pathnames, even if we're running from the build directory. 120 L = [] 121 known_paths = set() 122 for dir in sys.path: 123 # Filter out duplicate paths (on case-insensitive file systems also 124 # if they only differ in case); turn relative paths into absolute 125 # paths. 126 dir, dircase = makepath(dir) 127 if not dircase in known_paths: 128 L.append(dir) 129 known_paths.add(dircase) 130 sys.path[:] = L 131 return known_paths 132 133 134 def _init_pathinfo(): 135 """Return a set containing all existing file system items from sys.path.""" 136 d = set() 137 for item in sys.path: 138 try: 139 if os.path.exists(item): 140 _, itemcase = makepath(item) 141 d.add(itemcase) 142 except TypeError: 143 continue 144 return d 145 146 147 def addpackage(sitedir, name, known_paths): 148 """Process a .pth file within the site-packages directory: 149 For each line in the file, either combine it with sitedir to a path 150 and add that to known_paths, or execute it if it starts with 'import '. 151 """ 152 if known_paths is None: 153 known_paths = _init_pathinfo() 154 reset = True 155 else: 156 reset = False 157 fullname = os.path.join(sitedir, name) 158 try: 159 f = open(fullname, "r") 160 except OSError: 161 return 162 with f: 163 for n, line in enumerate(f): 164 if line.startswith("#"): 165 continue 166 try: 167 if line.startswith(("import ", "import\t")): 168 exec(line) 169 continue 170 line = line.rstrip() 171 dir, dircase = makepath(sitedir, line) 172 if not dircase in known_paths and os.path.exists(dir): 173 sys.path.append(dir) 174 known_paths.add(dircase) 175 except Exception: 176 print("Error processing line {:d} of {}:\n".format(n+1, fullname), 177 file=sys.stderr) 178 import traceback 179 for record in traceback.format_exception(*sys.exc_info()): 180 for line in record.splitlines(): 181 print(' '+line, file=sys.stderr) 182 print("\nRemainder of file ignored", file=sys.stderr) 183 break 184 if reset: 185 known_paths = None 186 return known_paths 187 188 189 def addsitedir(sitedir, known_paths=None): 190 """Add 'sitedir' argument to sys.path if missing and handle .pth files in 191 'sitedir'""" 192 if known_paths is None: 193 known_paths = _init_pathinfo() 194 reset = True 195 else: 196 reset = False 197 sitedir, sitedircase = makepath(sitedir) 198 if not sitedircase in known_paths: 199 sys.path.append(sitedir) # Add path component 200 known_paths.add(sitedircase) 201 try: 202 names = os.listdir(sitedir) 203 except OSError: 204 return 205 names = [name for name in names if name.endswith(".pth")] 206 for name in sorted(names): 207 addpackage(sitedir, name, known_paths) 208 if reset: 209 known_paths = None 210 return known_paths 211 212 213 def check_enableusersite(): 214 """Check if user site directory is safe for inclusion 215 216 The function tests for the command line flag (including environment var), 217 process uid/gid equal to effective uid/gid. 218 219 None: Disabled for security reasons 220 False: Disabled by user (command line option) 221 True: Safe and enabled 222 """ 223 if sys.flags.no_user_site: 224 return False 225 226 if hasattr(os, "getuid") and hasattr(os, "geteuid"): 227 # check process uid == effective uid 228 if os.geteuid() != os.getuid(): 229 return None 230 if hasattr(os, "getgid") and hasattr(os, "getegid"): 231 # check process gid == effective gid 232 if os.getegid() != os.getgid(): 233 return None 234 235 return True 236 237 def getuserbase(): 238 """Returns the `user base` directory path. 239 240 The `user base` directory can be used to store data. If the global 241 variable ``USER_BASE`` is not initialized yet, this function will also set 242 it. 243 """ 244 global USER_BASE 245 if USER_BASE is not None: 246 return USER_BASE 247 from sysconfig import get_config_var 248 USER_BASE = get_config_var('userbase') 249 return USER_BASE 250 251 def getusersitepackages(): 252 """Returns the user-specific site-packages directory path. 253 254 If the global variable ``USER_SITE`` is not initialized yet, this 255 function will also set it. 256 """ 257 global USER_SITE 258 user_base = getuserbase() # this will also set USER_BASE 259 260 if USER_SITE is not None: 261 return USER_SITE 262 263 from sysconfig import get_path 264 265 if sys.platform == 'darwin': 266 from sysconfig import get_config_var 267 if get_config_var('PYTHONFRAMEWORK'): 268 USER_SITE = get_path('purelib', 'osx_framework_user') 269 return USER_SITE 270 271 USER_SITE = get_path('purelib', '%s_user' % os.name) 272 return USER_SITE 273 274 def addusersitepackages(known_paths): 275 """Add a per user site-package to sys.path 276 277 Each user has its own python directory with site-packages in the 278 home directory. 279 """ 280 # get the per user site-package path 281 # this call will also make sure USER_BASE and USER_SITE are set 282 user_site = getusersitepackages() 283 284 if ENABLE_USER_SITE and os.path.isdir(user_site): 285 addsitedir(user_site, known_paths) 286 return known_paths 287 288 def getsitepackages(prefixes=None): 289 """Returns a list containing all global site-packages directories. 290 291 For each directory present in ``prefixes`` (or the global ``PREFIXES``), 292 this function will find its `site-packages` subdirectory depending on the 293 system environment, and will return a list of full paths. 294 """ 295 sitepackages = [] 296 seen = set() 297 298 if prefixes is None: 299 prefixes = PREFIXES 300 301 for prefix in prefixes: 302 if not prefix or prefix in seen: 303 continue 304 seen.add(prefix) 305 306 if os.sep == '/': 307 sitepackages.append(os.path.join(prefix, "lib", 308 "python%d.%d" % sys.version_info[:2], 309 "site-packages")) 310 else: 311 sitepackages.append(prefix) 312 sitepackages.append(os.path.join(prefix, "lib", "site-packages")) 313 if sys.platform == "darwin": 314 # for framework builds *only* we add the standard Apple 315 # locations. 316 from sysconfig import get_config_var 317 framework = get_config_var("PYTHONFRAMEWORK") 318 if framework: 319 sitepackages.append( 320 os.path.join("/Library", framework, 321 '%d.%d' % sys.version_info[:2], "site-packages")) 322 return sitepackages 323 324 def addsitepackages(known_paths, prefixes=None): 325 """Add site-packages to sys.path""" 326 for sitedir in getsitepackages(prefixes): 327 if os.path.isdir(sitedir): 328 addsitedir(sitedir, known_paths) 329 330 return known_paths 331 332 def setquit(): 333 """Define new builtins 'quit' and 'exit'. 334 335 These are objects which make the interpreter exit when called. 336 The repr of each object contains a hint at how it works. 337 338 """ 339 if os.sep == '\\': 340 eof = 'Ctrl-Z plus Return' 341 else: 342 eof = 'Ctrl-D (i.e. EOF)' 343 344 builtins.quit = _sitebuiltins.Quitter('quit', eof) 345 builtins.exit = _sitebuiltins.Quitter('exit', eof) 346 347 348 def setcopyright(): 349 """Set 'copyright' and 'credits' in builtins""" 350 builtins.copyright = _sitebuiltins._Printer("copyright", sys.copyright) 351 if sys.platform[:4] == 'java': 352 builtins.credits = _sitebuiltins._Printer( 353 "credits", 354 "Jython is maintained by the Jython developers (www.jython.org).") 355 else: 356 builtins.credits = _sitebuiltins._Printer("credits", """\ 357 Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands 358 for supporting Python development. See www.python.org for more information.""") 359 files, dirs = [], [] 360 # Not all modules are required to have a __file__ attribute. See 361 # PEP 420 for more details. 362 if hasattr(os, '__file__'): 363 here = os.path.dirname(os.__file__) 364 files.extend(["LICENSE.txt", "LICENSE"]) 365 dirs.extend([os.path.join(here, os.pardir), here, os.curdir]) 366 builtins.license = _sitebuiltins._Printer( 367 "license", 368 "See https://www.python.org/psf/license/", 369 files, dirs) 370 371 372 def sethelper(): 373 builtins.help = _sitebuiltins._Helper() 374 375 def enablerlcompleter(): 376 """Enable default readline configuration on interactive prompts, by 377 registering a sys.__interactivehook__. 378 379 If the readline module can be imported, the hook will set the Tab key 380 as completion key and register ~/.python_history as history file. 381 This can be overridden in the sitecustomize or usercustomize module, 382 or in a PYTHONSTARTUP file. 383 """ 384 def register_readline(): 385 import atexit 386 try: 387 import readline 388 import rlcompleter 389 except ImportError: 390 return 391 392 # Reading the initialization (config) file may not be enough to set a 393 # completion key, so we set one first and then read the file. 394 readline_doc = getattr(readline, '__doc__', '') 395 if readline_doc is not None and 'libedit' in readline_doc: 396 readline.parse_and_bind('bind ^I rl_complete') 397 else: 398 readline.parse_and_bind('tab: complete') 399 400 try: 401 readline.read_init_file() 402 except OSError: 403 # An OSError here could have many causes, but the most likely one 404 # is that there's no .inputrc file (or .editrc file in the case of 405 # Mac OS X + libedit) in the expected location. In that case, we 406 # want to ignore the exception. 407 pass 408 409 if readline.get_current_history_length() == 0: 410 # If no history was loaded, default to .python_history. 411 # The guard is necessary to avoid doubling history size at 412 # each interpreter exit when readline was already configured 413 # through a PYTHONSTARTUP hook, see: 414 # http://bugs.python.org/issue5845#msg198636 415 history = os.path.join(os.path.expanduser('~'), 416 '.python_history') 417 try: 418 readline.read_history_file(history) 419 except IOError: 420 pass 421 atexit.register(readline.write_history_file, history) 422 423 sys.__interactivehook__ = register_readline 424 425 def venv(known_paths): 426 global PREFIXES, ENABLE_USER_SITE 427 428 env = os.environ 429 if sys.platform == 'darwin' and '__PYVENV_LAUNCHER__' in env: 430 executable = os.environ['__PYVENV_LAUNCHER__'] 431 else: 432 executable = sys.executable 433 exe_dir, _ = os.path.split(os.path.abspath(executable)) 434 site_prefix = os.path.dirname(exe_dir) 435 sys._home = None 436 conf_basename = 'pyvenv.cfg' 437 candidate_confs = [ 438 conffile for conffile in ( 439 os.path.join(exe_dir, conf_basename), 440 os.path.join(site_prefix, conf_basename) 441 ) 442 if os.path.isfile(conffile) 443 ] 444 445 if candidate_confs: 446 virtual_conf = candidate_confs[0] 447 system_site = "true" 448 # Issue 25185: Use UTF-8, as that's what the venv module uses when 449 # writing the file. 450 with open(virtual_conf, encoding='utf-8') as f: 451 for line in f: 452 if '=' in line: 453 key, _, value = line.partition('=') 454 key = key.strip().lower() 455 value = value.strip() 456 if key == 'include-system-site-packages': 457 system_site = value.lower() 458 elif key == 'home': 459 sys._home = value 460 461 sys.prefix = sys.exec_prefix = site_prefix 462 463 # Doing this here ensures venv takes precedence over user-site 464 addsitepackages(known_paths, [sys.prefix]) 465 466 # addsitepackages will process site_prefix again if its in PREFIXES, 467 # but that's ok; known_paths will prevent anything being added twice 468 if system_site == "true": 469 PREFIXES.insert(0, sys.prefix) 470 else: 471 PREFIXES = [sys.prefix] 472 ENABLE_USER_SITE = False 473 474 return known_paths 475 476 477 def execsitecustomize(): 478 """Run custom site specific code, if available.""" 479 try: 480 try: 481 import sitecustomize 482 except ImportError as exc: 483 if exc.name == 'sitecustomize': 484 pass 485 else: 486 raise 487 except Exception as err: 488 if sys.flags.verbose: 489 sys.excepthook(*sys.exc_info()) 490 else: 491 sys.stderr.write( 492 "Error in sitecustomize; set PYTHONVERBOSE for traceback:\n" 493 "%s: %s\n" % 494 (err.__class__.__name__, err)) 495 496 497 def execusercustomize(): 498 """Run custom user specific code, if available.""" 499 try: 500 try: 501 import usercustomize 502 except ImportError as exc: 503 if exc.name == 'usercustomize': 504 pass 505 else: 506 raise 507 except Exception as err: 508 if sys.flags.verbose: 509 sys.excepthook(*sys.exc_info()) 510 else: 511 sys.stderr.write( 512 "Error in usercustomize; set PYTHONVERBOSE for traceback:\n" 513 "%s: %s\n" % 514 (err.__class__.__name__, err)) 515 516 517 def main(): 518 """Add standard site-specific directories to the module search path. 519 520 This function is called automatically when this module is imported, 521 unless the python interpreter was started with the -S flag. 522 """ 523 global ENABLE_USER_SITE 524 525 abs_paths() 526 known_paths = removeduppaths() 527 known_paths = venv(known_paths) 528 if ENABLE_USER_SITE is None: 529 ENABLE_USER_SITE = check_enableusersite() 530 known_paths = addusersitepackages(known_paths) 531 known_paths = addsitepackages(known_paths) 532 setquit() 533 setcopyright() 534 sethelper() 535 if not sys.flags.isolated: 536 enablerlcompleter() 537 execsitecustomize() 538 if ENABLE_USER_SITE: 539 execusercustomize() 540 541 # Prevent extending of sys.path when python was started with -S and 542 # site is imported later. 543 if not sys.flags.no_site: 544 main() 545 546 def _script(): 547 help = """\ 548 %s [--user-base] [--user-site] 549 550 Without arguments print some useful information 551 With arguments print the value of USER_BASE and/or USER_SITE separated 552 by '%s'. 553 554 Exit codes with --user-base or --user-site: 555 0 - user site directory is enabled 556 1 - user site directory is disabled by user 557 2 - uses site directory is disabled by super user 558 or for security reasons 559 >2 - unknown error 560 """ 561 args = sys.argv[1:] 562 if not args: 563 user_base = getuserbase() 564 user_site = getusersitepackages() 565 print("sys.path = [") 566 for dir in sys.path: 567 print(" %r," % (dir,)) 568 print("]") 569 print("USER_BASE: %r (%s)" % (user_base, 570 "exists" if os.path.isdir(user_base) else "doesn't exist")) 571 print("USER_SITE: %r (%s)" % (user_site, 572 "exists" if os.path.isdir(user_site) else "doesn't exist")) 573 print("ENABLE_USER_SITE: %r" % ENABLE_USER_SITE) 574 sys.exit(0) 575 576 buffer = [] 577 if '--user-base' in args: 578 buffer.append(USER_BASE) 579 if '--user-site' in args: 580 buffer.append(USER_SITE) 581 582 if buffer: 583 print(os.pathsep.join(buffer)) 584 if ENABLE_USER_SITE: 585 sys.exit(0) 586 elif ENABLE_USER_SITE is False: 587 sys.exit(1) 588 elif ENABLE_USER_SITE is None: 589 sys.exit(2) 590 else: 591 sys.exit(3) 592 else: 593 import textwrap 594 print(textwrap.dedent(help % (sys.argv[0], os.pathsep))) 595 sys.exit(10) 596 597 if __name__ == '__main__': 598 _script() 599