Home | History | Annotate | Download | only in Lib
      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 is a UEFI-specific version of site.py.
      8 
      9 In earlier versions of Python (up to 1.5a3), scripts or modules that
     10 needed to use site-specific modules would place ``import site''
     11 somewhere near the top of their code.  Because of the automatic
     12 import, this is no longer necessary (but code that does it still
     13 works).
     14 
     15 This will append site-specific paths to the module search path.  It
     16 starts with sys.prefix and sys.exec_prefix (if different) and appends
     17 lib/python<version>/site-packages as well as lib/site-python.
     18 The resulting directories, if they exist, are appended to sys.path,
     19 and also inspected for path configuration files.
     20 
     21 A path configuration file is a file whose name has the form
     22 <package>.pth; its contents are additional directories (one per line)
     23 to be added to sys.path.  Non-existing directories (or
     24 non-directories) are never added to sys.path; no directory is added to
     25 sys.path more than once.  Blank lines and lines beginning with
     26 '#' are skipped. Lines starting with 'import' are executed.
     27 
     28 For example, suppose sys.prefix and sys.exec_prefix are set to
     29 /Efi/StdLib and there is a directory /Efi/StdLib/lib/python2.7/site-packages
     30 with three subdirectories, foo, bar and spam, and two path
     31 configuration files, foo.pth and bar.pth.  Assume foo.pth contains the
     32 following:
     33 
     34   # foo package configuration
     35   foo
     36   bar
     37   bletch
     38 
     39 and bar.pth contains:
     40 
     41   # bar package configuration
     42   bar
     43 
     44 Then the following directories are added to sys.path, in this order:
     45 
     46   /Efi/StdLib/lib/python2.7/site-packages/bar
     47   /Efi/StdLib/lib/python2.7/site-packages/foo
     48 
     49 Note that bletch is omitted because it doesn't exist; bar precedes foo
     50 because bar.pth comes alphabetically before foo.pth; and spam is
     51 omitted because it is not mentioned in either path configuration file.
     52 
     53 After these path manipulations, an attempt is made to import a module
     54 named sitecustomize, which can perform arbitrary additional
     55 site-specific customizations.  If this import fails with an
     56 ImportError exception, it is silently ignored.
     57 
     58 Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>
     59 This program and the accompanying materials are licensed and made available under
     60 the terms and conditions of the BSD License that accompanies this distribution.
     61 The full text of the license may be found at
     62 http://opensource.org/licenses/bsd-license.
     63 
     64 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     65 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     66 """
     67 
     68 import sys
     69 import os
     70 import __builtin__
     71 import traceback
     72 
     73 # Prefixes for site-packages; add additional prefixes like /usr/local here

     74 PREFIXES = [sys.prefix, sys.exec_prefix]
     75 # Enable per user site-packages directory

     76 # set it to False to disable the feature or True to force the feature

     77 ENABLE_USER_SITE = False
     78 
     79 # for distutils.commands.install

     80 # These values are initialized by the getuserbase() and getusersitepackages()

     81 # functions, through the main() function when Python starts.

     82 USER_SITE = None
     83 USER_BASE = None
     84 
     85 
     86 def makepath(*paths):
     87     dir = os.path.join(*paths)
     88     try:
     89         dir = os.path.abspath(dir)
     90     except OSError:
     91         pass
     92     return dir, os.path.normcase(dir)
     93 
     94 
     95 def abs__file__():
     96     """Set all module' __file__ attribute to an absolute path"""
     97     for m in sys.modules.values():
     98         if hasattr(m, '__loader__'):
     99             continue   # don't mess with a PEP 302-supplied __file__

    100         try:
    101             m.__file__ = os.path.abspath(m.__file__)
    102         except (AttributeError, OSError):
    103             pass
    104 
    105 
    106 def removeduppaths():
    107     """ Remove duplicate entries from sys.path along with making them
    108     absolute"""
    109     # This ensures that the initial path provided by the interpreter contains

    110     # only absolute pathnames, even if we're running from the build directory.

    111     L = []
    112     known_paths = set()
    113     for dir in sys.path:
    114         # Filter out duplicate paths (on case-insensitive file systems also

    115         # if they only differ in case); turn relative paths into absolute

    116         # paths.

    117         dir, dircase = makepath(dir)
    118         if not dircase in known_paths:
    119             L.append(dir)
    120             known_paths.add(dircase)
    121     sys.path[:] = L
    122     return known_paths
    123 
    124 
    125 def _init_pathinfo():
    126     """Return a set containing all existing directory entries from sys.path"""
    127     d = set()
    128     for dir in sys.path:
    129         try:
    130             if os.path.isdir(dir):
    131                 dir, dircase = makepath(dir)
    132                 d.add(dircase)
    133         except TypeError:
    134             continue
    135     return d
    136 
    137 
    138 def addpackage(sitedir, name, known_paths):
    139     """Process a .pth file within the site-packages directory:
    140        For each line in the file, either combine it with sitedir to a path
    141        and add that to known_paths, or execute it if it starts with 'import '.
    142     """
    143     if known_paths is None:
    144         _init_pathinfo()
    145         reset = 1
    146     else:
    147         reset = 0
    148     fullname = os.path.join(sitedir, name)
    149     try:
    150         f = open(fullname, "rU")
    151     except IOError:
    152         return
    153     with f:
    154         for n, line in enumerate(f):
    155             if line.startswith("#"):
    156                 continue
    157             try:
    158                 if line.startswith(("import ", "import\t")):
    159                     exec line
    160                     continue
    161                 line = line.rstrip()
    162                 dir, dircase = makepath(sitedir, line)
    163                 if not dircase in known_paths and os.path.exists(dir):
    164                     sys.path.append(dir)
    165                     known_paths.add(dircase)
    166             except Exception as err:
    167                 print >>sys.stderr, "Error processing line {:d} of {}:\n".format(
    168                     n+1, fullname)
    169                 for record in traceback.format_exception(*sys.exc_info()):
    170                     for line in record.splitlines():
    171                         print >>sys.stderr, '  '+line
    172                 print >>sys.stderr, "\nRemainder of file ignored"
    173                 break
    174     if reset:
    175         known_paths = None
    176     return known_paths
    177 
    178 
    179 def addsitedir(sitedir, known_paths=None):
    180     """Add 'sitedir' argument to sys.path if missing and handle .pth files in
    181     'sitedir'"""
    182     if known_paths is None:
    183         known_paths = _init_pathinfo()
    184         reset = 1
    185     else:
    186         reset = 0
    187     sitedir, sitedircase = makepath(sitedir)
    188     if not sitedircase in known_paths:
    189         sys.path.append(sitedir)        # Add path component

    190     try:
    191         names = os.listdir(sitedir)
    192     except os.error:
    193         return
    194     dotpth = os.extsep + "pth"
    195     names = [name for name in names if name.endswith(dotpth)]
    196     for name in sorted(names):
    197         addpackage(sitedir, name, known_paths)
    198     if reset:
    199         known_paths = None
    200     return known_paths
    201 
    202 
    203 def check_enableusersite():
    204     """Check if user site directory is safe for inclusion
    205 
    206     The function tests for the command line flag (including environment var),
    207     process uid/gid equal to effective uid/gid.
    208 
    209     None: Disabled for security reasons
    210     False: Disabled by user (command line option)
    211     True: Safe and enabled
    212     """
    213     if sys.flags.no_user_site:
    214         return False
    215 
    216     if hasattr(os, "getuid") and hasattr(os, "geteuid"):
    217         # check process uid == effective uid

    218         if os.geteuid() != os.getuid():
    219             return None
    220     if hasattr(os, "getgid") and hasattr(os, "getegid"):
    221         # check process gid == effective gid

    222         if os.getegid() != os.getgid():
    223             return None
    224 
    225     return True
    226 
    227 def getuserbase():
    228     """Returns the `user base` directory path.
    229 
    230     The `user base` directory can be used to store data. If the global
    231     variable ``USER_BASE`` is not initialized yet, this function will also set
    232     it.
    233     """
    234     global USER_BASE
    235     if USER_BASE is not None:
    236         return USER_BASE
    237     from sysconfig import get_config_var
    238     USER_BASE = get_config_var('userbase')
    239     return USER_BASE
    240 
    241 def getusersitepackages():
    242     """Returns the user-specific site-packages directory path.
    243 
    244     If the global variable ``USER_SITE`` is not initialized yet, this
    245     function will also set it.
    246     """
    247     global USER_SITE
    248     user_base = getuserbase() # this will also set USER_BASE

    249 
    250     if USER_SITE is not None:
    251         return USER_SITE
    252 
    253     from sysconfig import get_path
    254     import os
    255 
    256     USER_SITE = get_path('purelib', '%s_user' % os.name)
    257     return USER_SITE
    258 
    259 def addusersitepackages(known_paths):
    260     """Add a per user site-package to sys.path
    261 
    262     Each user has its own python directory with site-packages in the
    263     home directory.
    264     """
    265     # get the per user site-package path

    266     # this call will also make sure USER_BASE and USER_SITE are set

    267     user_site = getusersitepackages()
    268 
    269     if ENABLE_USER_SITE and os.path.isdir(user_site):
    270         addsitedir(user_site, known_paths)
    271     return known_paths
    272 
    273 def getsitepackages():
    274     """Returns a list containing all global site-packages directories
    275     (and possibly site-python).
    276 
    277     For each directory present in the global ``PREFIXES``, this function
    278     will find its `site-packages` subdirectory depending on the system
    279     environment, and will return a list of full paths.
    280     """
    281     sitepackages = []
    282     seen = set()
    283 
    284     for prefix in PREFIXES:
    285         if not prefix or prefix in seen:
    286             continue
    287         seen.add(prefix)
    288 
    289         sitepackages.append(os.path.join(prefix, "lib",
    290                                     "python." + sys.version[0] + sys.version[2],
    291                                     "site-packages"))
    292         sitepackages.append(os.path.join(prefix, "lib", "site-python"))
    293     return sitepackages
    294 
    295 def addsitepackages(known_paths):
    296     """Add site-packages (and possibly site-python) to sys.path"""
    297     for sitedir in getsitepackages():
    298         if os.path.isdir(sitedir):
    299             addsitedir(sitedir, known_paths)
    300 
    301     return known_paths
    302 
    303 def setBEGINLIBPATH():
    304     """The UEFI port has optional extension modules that do double duty
    305     as DLLs (even though they have .efi file extensions) for other extensions.
    306     The library search path needs to be amended so these will be found
    307     during module import.  Use BEGINLIBPATH so that these are at the start
    308     of the library search path.
    309 
    310     """
    311     dllpath = os.path.join(sys.prefix, "Lib", "lib-dynload")
    312     libpath = os.environ['BEGINLIBPATH'].split(os.path.pathsep)
    313     if libpath[-1]:
    314         libpath.append(dllpath)
    315     else:
    316         libpath[-1] = dllpath
    317     os.environ['BEGINLIBPATH'] = os.path.pathsep.join(libpath)
    318 
    319 
    320 def setquit():
    321     """Define new builtins 'quit' and 'exit'.
    322 
    323     These are objects which make the interpreter exit when called.
    324     The repr of each object contains a hint at how it works.
    325 
    326     """
    327     eof = 'Ctrl-D (i.e. EOF)'
    328 
    329     class Quitter(object):
    330         def __init__(self, name):
    331             self.name = name
    332         def __repr__(self):
    333             return 'Use %s() or %s to exit' % (self.name, eof)
    334         def __call__(self, code=None):
    335             # Shells like IDLE catch the SystemExit, but listen when their

    336             # stdin wrapper is closed.

    337             try:
    338                 sys.stdin.close()
    339             except:
    340                 pass
    341             raise SystemExit(code)
    342     __builtin__.quit = Quitter('quit')
    343     __builtin__.exit = Quitter('exit')
    344 
    345 
    346 class _Printer(object):
    347     """interactive prompt objects for printing the license text, a list of
    348     contributors and the copyright notice."""
    349 
    350     MAXLINES = 23
    351 
    352     def __init__(self, name, data, files=(), dirs=()):
    353         self.__name = name
    354         self.__data = data
    355         self.__files = files
    356         self.__dirs = dirs
    357         self.__lines = None
    358 
    359     def __setup(self):
    360         if self.__lines:
    361             return
    362         data = None
    363         for dir in self.__dirs:
    364             for filename in self.__files:
    365                 filename = os.path.join(dir, filename)
    366                 try:
    367                     fp = file(filename, "rU")
    368                     data = fp.read()
    369                     fp.close()
    370                     break
    371                 except IOError:
    372                     pass
    373             if data:
    374                 break
    375         if not data:
    376             data = self.__data
    377         self.__lines = data.split('\n')
    378         self.__linecnt = len(self.__lines)
    379 
    380     def __repr__(self):
    381         self.__setup()
    382         if len(self.__lines) <= self.MAXLINES:
    383             return "\n".join(self.__lines)
    384         else:
    385             return "Type %s() to see the full %s text" % ((self.__name,)*2)
    386 
    387     def __call__(self):
    388         self.__setup()
    389         prompt = 'Hit Return for more, or q (and Return) to quit: '
    390         lineno = 0
    391         while 1:
    392             try:
    393                 for i in range(lineno, lineno + self.MAXLINES):
    394                     print self.__lines[i]
    395             except IndexError:
    396                 break
    397             else:
    398                 lineno += self.MAXLINES
    399                 key = None
    400                 while key is None:
    401                     key = raw_input(prompt)
    402                     if key not in ('', 'q'):
    403                         key = None
    404                 if key == 'q':
    405                     break
    406 
    407 def setcopyright():
    408     """Set 'copyright' and 'credits' in __builtin__"""
    409     __builtin__.copyright = _Printer("copyright", sys.copyright)
    410     __builtin__.credits = _Printer("credits", """\
    411     Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands
    412     for supporting Python development.  See www.python.org for more information.""")
    413     here = os.path.dirname(os.__file__)
    414     __builtin__.license = _Printer(
    415         "license", "See http://www.python.org/%.3s/license.html" % sys.version,
    416         ["LICENSE.txt", "LICENSE"],
    417         [os.path.join(here, os.pardir), here, os.curdir])
    418 
    419 
    420 class _Helper(object):
    421     """Define the builtin 'help'.
    422     This is a wrapper around pydoc.help (with a twist).
    423 
    424     """
    425 
    426     def __repr__(self):
    427         return "Type help() for interactive help, " \
    428                "or help(object) for help about object."
    429 
    430     def __call__(self, *args, **kwds):
    431         import pydoc
    432         return pydoc.help(*args, **kwds)
    433 
    434 def sethelper():
    435     __builtin__.help = _Helper()
    436 
    437 ####

    438 # Keep around for future mbcs support.

    439 ####

    440 #def aliasmbcs():

    441 #    """On Windows, some default encodings are not provided by Python,

    442 #    while they are always available as "mbcs" in each locale. Make

    443 #    them usable by aliasing to "mbcs" in such a case."""

    444 #    if sys.platform == 'win32':

    445 #        import locale, codecs

    446 #        enc = locale.getdefaultlocale()[1]

    447 #        if enc.startswith('cp'):            # "cp***" ?

    448 #            try:

    449 #                codecs.lookup(enc)

    450 #            except LookupError:

    451 #                import encodings

    452 #                encodings._cache[enc] = encodings._unknown

    453 #                encodings.aliases.aliases[enc] = 'mbcs'

    454 
    455 def setencoding():
    456     """Set the string encoding used by the Unicode implementation.  The
    457     default is 'ascii', but if you're willing to experiment, you can
    458     change this."""
    459     encoding = "ascii" # Default value set by _PyUnicode_Init()

    460     if 0:
    461         # Enable to support locale aware default string encodings.

    462         import locale
    463         loc = locale.getdefaultlocale()
    464         if loc[1]:
    465             encoding = loc[1]
    466     if 0:
    467         # Enable to switch off string to Unicode coercion and implicit

    468         # Unicode to string conversion.

    469         encoding = "undefined"
    470     if encoding != "ascii":
    471         # On Non-Unicode builds this will raise an AttributeError...

    472         sys.setdefaultencoding(encoding) # Needs Python Unicode build !

    473 
    474 
    475 def execsitecustomize():
    476     """Run custom site specific code, if available."""
    477     try:
    478         import sitecustomize
    479     except ImportError:
    480         pass
    481     except Exception:
    482         if sys.flags.verbose:
    483             sys.excepthook(*sys.exc_info())
    484         else:
    485             print >>sys.stderr, \
    486                 "'import sitecustomize' failed; use -v for traceback"
    487 
    488 
    489 def execusercustomize():
    490     """Run custom user specific code, if available."""
    491     try:
    492         import usercustomize
    493     except ImportError:
    494         pass
    495     except Exception:
    496         if sys.flags.verbose:
    497             sys.excepthook(*sys.exc_info())
    498         else:
    499             print>>sys.stderr, \
    500                 "'import usercustomize' failed; use -v for traceback"
    501 
    502 
    503 def main():
    504     abs__file__()
    505     known_paths = removeduppaths()
    506     known_paths = addsitepackages(known_paths)
    507     setquit()
    508     setcopyright()
    509     sethelper()
    510 #    aliasmbcs()

    511     setencoding()
    512     execsitecustomize()
    513     # Remove sys.setdefaultencoding() so that users cannot change the

    514     # encoding after initialization.  The test for presence is needed when

    515     # this module is run as a script, because this code is executed twice.

    516     if hasattr(sys, "setdefaultencoding"):
    517         del sys.setdefaultencoding
    518 
    519 main()
    520 
    521 def _script():
    522     help = """\
    523     %s
    524 
    525     Path elements are normally separated by '%s'.
    526     """
    527     print "sys.path = ["
    528     for dir in sys.path:
    529         print "    %r," % (dir,)
    530     print "]"
    531 
    532     import textwrap
    533     print textwrap.dedent(help % (sys.argv[0], os.pathsep))
    534     sys.exit(0)
    535 
    536 if __name__ == '__main__':
    537     _script()
    538