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