1"""Append module search paths for third-party packages to sys.path. 2 3**************************************************************** 4* This module is automatically imported during initialization. * 5**************************************************************** 6 7This is a UEFI-specific version of site.py. 8 9In earlier versions of Python (up to 1.5a3), scripts or modules that 10needed to use site-specific modules would place ``import site'' 11somewhere near the top of their code. Because of the automatic 12import, this is no longer necessary (but code that does it still 13works). 14 15This will append site-specific paths to the module search path. It starts with sys.prefix and 16sys.exec_prefix (if different) and appends 17lib/python<version>/site-packages as well as lib/site-python. 18The 19resulting directories, if they exist, are appended to sys.path, and 20also inspected for path configuration files. 21 22A path configuration file is a file whose name has the form 23<package>.pth; its contents are additional directories (one per line) 24to be added to sys.path. Non-existing directories (or 25non-directories) are never added to sys.path; no directory is added to 26sys.path more than once. Blank lines and lines beginning with 27'#' are skipped. Lines starting with 'import' are executed. 28 29For example, suppose sys.prefix and sys.exec_prefix are set to 30/Efi/StdLib and there is a directory /Efi/StdLib/lib/python27.10/site-packages 31with three subdirectories, foo, bar and spam, and two path 32configuration files, foo.pth and bar.pth. Assume foo.pth contains the 33following: 34 35 # foo package configuration 36 foo 37 bar 38 bletch 39 40and bar.pth contains: 41 42 # bar package configuration 43 bar 44 45Then the following directories are added to sys.path, in this order: 46 47 /Efi/StdLib/lib/python27.10/site-packages/bar 48 /Efi/StdLib/lib/python27.10/site-packages/foo 49 50Note that bletch is omitted because it doesn't exist; bar precedes foo 51because bar.pth comes alphabetically before foo.pth; and spam is 52omitted because it is not mentioned in either path configuration file. 53 54After these path manipulations, an attempt is made to import a module 55named sitecustomize, which can perform arbitrary additional 56site-specific customizations. If this import fails with an 57ImportError exception, it is silently ignored. 58 59Copyright (c) 2015, Daryl McDaniel. All rights reserved.<BR> 60Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR> 61This program and the accompanying materials are licensed and made available under 62the terms and conditions of the BSD License that accompanies this distribution. 63The full text of the license may be found at 64http://opensource.org/licenses/bsd-license. 65 66THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 67WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 68""" 69 70import sys 71import os 72import __builtin__ 73import traceback 74 75# Prefixes for site-packages; add additional prefixes like /usr/local here 76PREFIXES = [sys.prefix, sys.exec_prefix] 77# Enable per user site-packages directory 78# set it to False to disable the feature or True to force the feature 79ENABLE_USER_SITE = False 80 81# for distutils.commands.install 82# These values are initialized by the getuserbase() and getusersitepackages() 83# functions, through the main() function when Python starts. 84USER_SITE = None 85USER_BASE = None 86 87 88def makepath(*paths): 89 dir = os.path.join(*paths) 90 try: 91 dir = os.path.abspath(dir) 92 except OSError: 93 pass 94 return dir, os.path.normcase(dir) 95 96 97def abs__file__(): 98 """Set all module' __file__ attribute to an absolute path""" 99 for m in sys.modules.values(): 100 if hasattr(m, '__loader__'): 101 continue # don't mess with a PEP 302-supplied __file__ 102 try: 103 m.__file__ = os.path.abspath(m.__file__) 104 except (AttributeError, OSError): 105 pass 106 107 108def removeduppaths(): 109 """ Remove duplicate entries from sys.path along with making them 110 absolute""" 111 # This ensures that the initial path provided by the interpreter contains 112 # only absolute pathnames, even if we're running from the build directory. 113 L = [] 114 known_paths = set() 115 for dir in sys.path: 116 # Filter out duplicate paths (on case-insensitive file systems also 117 # if they only differ in case); turn relative paths into absolute 118 # paths. 119 dir, dircase = makepath(dir) 120 if not dircase in known_paths: 121 L.append(dir) 122 known_paths.add(dircase) 123 sys.path[:] = L 124 return known_paths 125 126 127def _init_pathinfo(): 128 """Return a set containing all existing directory entries from sys.path""" 129 d = set() 130 for dir in sys.path: 131 try: 132 if os.path.isdir(dir): 133 dir, dircase = makepath(dir) 134 d.add(dircase) 135 except TypeError: 136 continue 137 return d 138 139 140def addpackage(sitedir, name, known_paths): 141 """Process a .pth file within the site-packages directory: 142 For each line in the file, either combine it with sitedir to a path 143 and add that to known_paths, or execute it if it starts with 'import '. 144 """ 145 if known_paths is None: 146 _init_pathinfo() 147 reset = 1 148 else: 149 reset = 0 150 fullname = os.path.join(sitedir, name) 151 try: 152 f = open(fullname, "rU") 153 except IOError: 154 return 155 with f: 156 for n, line in enumerate(f): 157 if line.startswith("#"): 158 continue 159 try: 160 if line.startswith(("import ", "import\t")): 161 exec line 162 continue 163 line = line.rstrip() 164 dir, dircase = makepath(sitedir, line) 165 if not dircase in known_paths and os.path.exists(dir): 166 sys.path.append(dir) 167 known_paths.add(dircase) 168 except Exception as err: 169 print >>sys.stderr, "Error processing line {:d} of {}:\n".format( 170 n+1, fullname) 171 for record in traceback.format_exception(*sys.exc_info()): 172 for line in record.splitlines(): 173 print >>sys.stderr, ' '+line 174 print >>sys.stderr, "\nRemainder of file ignored" 175 break 176 if reset: 177 known_paths = None 178 return known_paths 179 180 181def addsitedir(sitedir, known_paths=None): 182 """Add 'sitedir' argument to sys.path if missing and handle .pth files in 183 'sitedir'""" 184 if known_paths is None: 185 known_paths = _init_pathinfo() 186 reset = 1 187 else: 188 reset = 0 189 sitedir, sitedircase = makepath(sitedir) 190 if not sitedircase in known_paths: 191 sys.path.append(sitedir) # Add path component 192 try: 193 names = os.listdir(sitedir) 194 except os.error: 195 return 196 dotpth = os.extsep + "pth" 197 names = [name for name in names if name.endswith(dotpth)] 198 for name in sorted(names): 199 addpackage(sitedir, name, known_paths) 200 if reset: 201 known_paths = None 202 return known_paths 203 204 205def check_enableusersite(): 206 """Check if user site directory is safe for inclusion 207 208 The function tests for the command line flag (including environment var), 209 process uid/gid equal to effective uid/gid. 210 211 None: Disabled for security reasons 212 False: Disabled by user (command line option) 213 True: Safe and enabled 214 """ 215 if sys.flags.no_user_site: 216 return False 217 218 if hasattr(os, "getuid") and hasattr(os, "geteuid"): 219 # check process uid == effective uid 220 if os.geteuid() != os.getuid(): 221 return None 222 if hasattr(os, "getgid") and hasattr(os, "getegid"): 223 # check process gid == effective gid 224 if os.getegid() != os.getgid(): 225 return None 226 227 return True 228 229def getuserbase(): 230 """Returns the `user base` directory path. 231 232 The `user base` directory can be used to store data. If the global 233 variable ``USER_BASE`` is not initialized yet, this function will also set 234 it. 235 """ 236 global USER_BASE 237 if USER_BASE is not None: 238 return USER_BASE 239 from sysconfig import get_config_var 240 USER_BASE = get_config_var('userbase') 241 return USER_BASE 242 243def getusersitepackages(): 244 """Returns the user-specific site-packages directory path. 245 246 If the global variable ``USER_SITE`` is not initialized yet, this 247 function will also set it. 248 """ 249 global USER_SITE 250 user_base = getuserbase() # this will also set USER_BASE 251 252 if USER_SITE is not None: 253 return USER_SITE 254 255 from sysconfig import get_path 256 import os 257 258 USER_SITE = get_path('purelib', '%s_user' % os.name) 259 return USER_SITE 260 261def addusersitepackages(known_paths): 262 """Add a per user site-package to sys.path 263 264 Each user has its own python directory with site-packages in the 265 home directory. 266 """ 267 if ENABLE_USER_SITE and os.path.isdir(user_site): 268 # get the per user site-package path 269 # this call will also make sure USER_BASE and USER_SITE are set 270 user_site = getusersitepackages() 271 272 addsitedir(user_site, known_paths) 273 return known_paths 274 275def getsitepackages(): 276 """Returns a list containing all global site-packages directories 277 (and possibly site-python). 278 279 For each directory present in the global ``PREFIXES``, this function 280 will find its `site-packages` subdirectory depending on the system 281 environment, and will return a list of full paths. 282 """ 283 sitepackages = [] 284 seen = set() 285 286 for prefix in PREFIXES: 287 if not prefix or prefix in seen: 288 continue 289 seen.add(prefix) 290 291 ix = sys.version.find(' ') 292 if ix != -1: 293 micro = sys.version[4:ix] 294 else: 295 micro = '0' 296 297 sitepackages.append(os.path.join(prefix, "lib", 298 "python" + sys.version[0] + sys.version[2] + '.' + micro, 299 "site-packages")) 300 sitepackages.append(os.path.join(prefix, "lib", "site-python")) 301 return sitepackages 302 303def addsitepackages(known_paths): 304 """Add site-packages (and possibly site-python) to sys.path""" 305 for sitedir in getsitepackages(): 306 if os.path.isdir(sitedir): 307 addsitedir(sitedir, known_paths) 308 309 return known_paths 310 311def setBEGINLIBPATH(): 312 """The UEFI port has optional extension modules that do double duty 313 as DLLs (even though they have .efi file extensions) for other extensions. 314 The library search path needs to be amended so these will be found 315 during module import. Use BEGINLIBPATH so that these are at the start 316 of the library search path. 317 318 """ 319 dllpath = os.path.join(sys.prefix, "Lib", "lib-dynload") 320 libpath = os.environ['BEGINLIBPATH'].split(os.path.pathsep) 321 if libpath[-1]: 322 libpath.append(dllpath) 323 else: 324 libpath[-1] = dllpath 325 os.environ['BEGINLIBPATH'] = os.path.pathsep.join(libpath) 326 327 328def setquit(): 329 """Define new builtins 'quit' and 'exit'. 330 331 These are objects which make the interpreter exit when called. 332 The repr of each object contains a hint at how it works. 333 334 """ 335 eof = 'Ctrl-D (i.e. EOF)' 336 337 class Quitter(object): 338 def __init__(self, name): 339 self.name = name 340 def __repr__(self): 341 return 'Use %s() or %s to exit' % (self.name, eof) 342 def __call__(self, code=None): 343 # Shells like IDLE catch the SystemExit, but listen when their 344 # stdin wrapper is closed. 345 try: 346 sys.stdin.close() 347 except: 348 pass 349 raise SystemExit(code) 350 __builtin__.quit = Quitter('quit') 351 __builtin__.exit = Quitter('exit') 352 353 354class _Printer(object): 355 """interactive prompt objects for printing the license text, a list of 356 contributors and the copyright notice.""" 357 358 MAXLINES = 23 359 360 def __init__(self, name, data, files=(), dirs=()): 361 self.__name = name 362 self.__data = data 363 self.__files = files 364 self.__dirs = dirs 365 self.__lines = None 366 367 def __setup(self): 368 if self.__lines: 369 return 370 data = None 371 for dir in self.__dirs: 372 for filename in self.__files: 373 filename = os.path.join(dir, filename) 374 try: 375 fp = file(filename, "rU") 376 data = fp.read() 377 fp.close() 378 break 379 except IOError: 380 pass 381 if data: 382 break 383 if not data: 384 data = self.__data 385 self.__lines = data.split('\n') 386 self.__linecnt = len(self.__lines) 387 388 def __repr__(self): 389 self.__setup() 390 if len(self.__lines) <= self.MAXLINES: 391 return "\n".join(self.__lines) 392 else: 393 return "Type %s() to see the full %s text" % ((self.__name,)*2) 394 395 def __call__(self): 396 self.__setup() 397 prompt = 'Hit Return for more, or q (and Return) to quit: ' 398 lineno = 0 399 while 1: 400 try: 401 for i in range(lineno, lineno + self.MAXLINES): 402 print self.__lines[i] 403 except IndexError: 404 break 405 else: 406 lineno += self.MAXLINES 407 key = None 408 while key is None: 409 key = raw_input(prompt) 410 if key not in ('', 'q'): 411 key = None 412 if key == 'q': 413 break 414 415def setcopyright(): 416 """Set 'copyright' and 'credits' in __builtin__""" 417 __builtin__.copyright = _Printer("copyright", sys.copyright) 418 __builtin__.credits = _Printer("credits", """\ 419 Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands 420 for supporting Python development. See www.python.org for more information.""") 421 here = os.path.dirname(os.__file__) 422 __builtin__.license = _Printer( 423 "license", "See https://www.python.org/psf/license/", 424 ["LICENSE.txt", "LICENSE"], 425 [os.path.join(here, os.pardir), here, os.curdir]) 426 427 428class _Helper(object): 429 """Define the builtin 'help'. 430 This is a wrapper around pydoc.help (with a twist). 431 432 """ 433 434 def __repr__(self): 435 return "Type help() for interactive help, " \ 436 "or help(object) for help about object." 437 def __call__(self, *args, **kwds): 438 import pydoc 439 return pydoc.help(*args, **kwds) 440 441def sethelper(): 442 __builtin__.help = _Helper() 443 444def setencoding(): 445 """Set the string encoding used by the Unicode implementation. The 446 default is 'ascii', but if you're willing to experiment, you can 447 change this.""" 448 encoding = "ascii" # Default value set by _PyUnicode_Init() 449 if 0: 450 # Enable to support locale aware default string encodings. 451 import locale 452 loc = locale.getdefaultlocale() 453 if loc[1]: 454 encoding = loc[1] 455 if 0: 456 # Enable to switch off string to Unicode coercion and implicit 457 # Unicode to string conversion. 458 encoding = "undefined" 459 if encoding != "ascii": 460 # On Non-Unicode builds this will raise an AttributeError... 461 sys.setdefaultencoding(encoding) # Needs Python Unicode build ! 462 463 464def execsitecustomize(): 465 """Run custom site specific code, if available.""" 466 try: 467 import sitecustomize 468 except ImportError: 469 pass 470 except Exception: 471 if sys.flags.verbose: 472 sys.excepthook(*sys.exc_info()) 473 else: 474 print >>sys.stderr, \ 475 "'import sitecustomize' failed; use -v for traceback" 476 477 478def execusercustomize(): 479 """Run custom user specific code, if available.""" 480 try: 481 import usercustomize 482 except ImportError: 483 pass 484 except Exception: 485 if sys.flags.verbose: 486 sys.excepthook(*sys.exc_info()) 487 else: 488 print>>sys.stderr, \ 489 "'import usercustomize' failed; use -v for traceback" 490 491 492def main(): 493 global ENABLE_USER_SITE 494 495 abs__file__() 496 known_paths = removeduppaths() 497 if ENABLE_USER_SITE is None: 498 ENABLE_USER_SITE = check_enableusersite() 499 known_paths = addusersitepackages(known_paths) 500 known_paths = addsitepackages(known_paths) 501 setquit() 502 setcopyright() 503 sethelper() 504 setencoding() 505 execsitecustomize() 506 # Remove sys.setdefaultencoding() so that users cannot change the 507 # encoding after initialization. The test for presence is needed when 508 # this module is run as a script, because this code is executed twice. 509 if hasattr(sys, "setdefaultencoding"): 510 del sys.setdefaultencoding 511 512main() 513 514def _script(): 515 help = """\ 516 %s 517 518 Path elements are normally separated by '%s'. 519 """ 520 521 print "sys.path = [" 522 for dir in sys.path: 523 print " %r," % (dir,) 524 print "]" 525 526 import textwrap 527 print textwrap.dedent(help % (sys.argv[0], os.pathsep)) 528 sys.exit(0) 529 530if __name__ == '__main__': 531 _script() 532