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 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 # XXX This should not be part of site.py, since it is needed even when

    118 # using the -S option for Python.  See http://www.python.org/sf/586680

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

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

    223         if os.geteuid() != os.getuid():
    224             return None
    225     if hasattr(os, "getgid") and hasattr(os, "getegid"):
    226         # check process gid == effective gid

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

    254 
    255     if USER_SITE is not None:
    256         return USER_SITE
    257 
    258     from sysconfig import get_path
    259     import os
    260 
    261     if sys.platform == 'darwin':
    262         from sysconfig import get_config_var
    263         if get_config_var('PYTHONFRAMEWORK'):
    264             USER_SITE = get_path('purelib', 'osx_framework_user')
    265             return USER_SITE
    266 
    267     USER_SITE = get_path('purelib', '%s_user' % os.name)
    268     return USER_SITE
    269 
    270 def addusersitepackages(known_paths):
    271     """Add a per user site-package to sys.path
    272 
    273     Each user has its own python directory with site-packages in the
    274     home directory.
    275     """
    276     # get the per user site-package path

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

    278     user_site = getusersitepackages()
    279 
    280     if ENABLE_USER_SITE and os.path.isdir(user_site):
    281         addsitedir(user_site, known_paths)
    282     return known_paths
    283 
    284 def getsitepackages():
    285     """Returns a list containing all global site-packages directories
    286     (and possibly site-python).
    287 
    288     For each directory present in the global ``PREFIXES``, this function
    289     will find its `site-packages` subdirectory depending on the system
    290     environment, and will return a list of full paths.
    291     """
    292     sitepackages = []
    293     seen = set()
    294 
    295     for prefix in PREFIXES:
    296         if not prefix or prefix in seen:
    297             continue
    298         seen.add(prefix)
    299 
    300         if sys.platform in ('os2emx', 'riscos'):
    301             sitepackages.append(os.path.join(prefix, "Lib", "site-packages"))
    302         elif os.sep == '/':
    303             sitepackages.append(os.path.join(prefix, "lib",
    304                                         "python" + sys.version[:3],
    305                                         "site-packages"))
    306             sitepackages.append(os.path.join(prefix, "lib", "site-python"))
    307         else:
    308             sitepackages.append(prefix)
    309             sitepackages.append(os.path.join(prefix, "lib", "site-packages"))
    310         if sys.platform == "darwin":
    311             # for framework builds *only* we add the standard Apple

    312             # locations.

    313             from sysconfig import get_config_var
    314             framework = get_config_var("PYTHONFRAMEWORK")
    315             if framework and "/%s.framework/"%(framework,) in prefix:
    316                 sitepackages.append(
    317                         os.path.join("/Library", framework,
    318                             sys.version[:3], "site-packages"))
    319     return sitepackages
    320 
    321 def addsitepackages(known_paths):
    322     """Add site-packages (and possibly site-python) to sys.path"""
    323     for sitedir in getsitepackages():
    324         if os.path.isdir(sitedir):
    325             addsitedir(sitedir, known_paths)
    326 
    327     return known_paths
    328 
    329 def setBEGINLIBPATH():
    330     """The OS/2 EMX port has optional extension modules that do double duty
    331     as DLLs (and must use the .DLL file extension) for other extensions.
    332     The library search path needs to be amended so these will be found
    333     during module import.  Use BEGINLIBPATH so that these are at the start
    334     of the library search path.
    335 
    336     """
    337     dllpath = os.path.join(sys.prefix, "Lib", "lib-dynload")
    338     libpath = os.environ['BEGINLIBPATH'].split(';')
    339     if libpath[-1]:
    340         libpath.append(dllpath)
    341     else:
    342         libpath[-1] = dllpath
    343     os.environ['BEGINLIBPATH'] = ';'.join(libpath)
    344 
    345 
    346 def setquit():
    347     """Define new builtins 'quit' and 'exit'.
    348 
    349     These are objects which make the interpreter exit when called.
    350     The repr of each object contains a hint at how it works.
    351 
    352     """
    353     if os.sep == ':':
    354         eof = 'Cmd-Q'
    355     elif os.sep == '\\':
    356         eof = 'Ctrl-Z plus Return'
    357     else:
    358         eof = 'Ctrl-D (i.e. EOF)'
    359 
    360     class Quitter(object):
    361         def __init__(self, name):
    362             self.name = name
    363         def __repr__(self):
    364             return 'Use %s() or %s to exit' % (self.name, eof)
    365         def __call__(self, code=None):
    366             # Shells like IDLE catch the SystemExit, but listen when their
    367             # stdin wrapper is closed.
    368             try:
    369                 sys.stdin.close()
    370             except:
    371                 pass
    372             raise SystemExit(code)
    373     __builtin__.quit = Quitter('quit')
    374     __builtin__.exit = Quitter('exit')
    375 
    376 
    377 class _Printer(object):
    378     """interactive prompt objects for printing the license text, a list of
    379     contributors and the copyright notice."""
    380 
    381     MAXLINES = 23
    382 
    383     def __init__(self, name, data, files=(), dirs=()):
    384         self.__name = name
    385         self.__data = data
    386         self.__files = files
    387         self.__dirs = dirs
    388         self.__lines = None
    389 
    390     def __setup(self):
    391         if self.__lines:
    392             return
    393         data = None
    394         for dir in self.__dirs:
    395             for filename in self.__files:
    396                 filename = os.path.join(dir, filename)
    397                 try:
    398                     fp = file(filename, "rU")
    399                     data = fp.read()
    400                     fp.close()
    401                     break
    402                 except IOError:
    403                     pass
    404             if data:
    405                 break
    406         if not data:
    407             data = self.__data
    408         self.__lines = data.split('\n')
    409         self.__linecnt = len(self.__lines)
    410 
    411     def __repr__(self):
    412         self.__setup()
    413         if len(self.__lines) <= self.MAXLINES:
    414             return "\n".join(self.__lines)
    415         else:
    416             return "Type %s() to see the full %s text" % ((self.__name,)*2)
    417 
    418     def __call__(self):
    419         self.__setup()
    420         prompt = 'Hit Return for more, or q (and Return) to quit: '
    421         lineno = 0
    422         while 1:
    423             try:
    424                 for i in range(lineno, lineno + self.MAXLINES):
    425                     print self.__lines[i]
    426             except IndexError:
    427                 break
    428             else:
    429                 lineno += self.MAXLINES
    430                 key = None
    431                 while key is None:
    432                     key = raw_input(prompt)
    433                     if key not in ('', 'q'):
    434                         key = None
    435                 if key == 'q':
    436                     break
    437 
    438 def setcopyright():
    439     """Set 'copyright' and 'credits' in __builtin__"""
    440     __builtin__.copyright = _Printer("copyright", sys.copyright)
    441     if sys.platform[:4] == 'java':
    442         __builtin__.credits = _Printer(
    443             "credits",
    444             "Jython is maintained by the Jython developers (www.jython.org).")
    445     else:
    446         __builtin__.credits = _Printer("credits", """\
    447     Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands
    448     for supporting Python development.  See www.python.org for more information.""")
    449     here = os.path.dirname(os.__file__)
    450     __builtin__.license = _Printer(
    451         "license", "See http://www.python.org/%.3s/license.html" % sys.version,
    452         ["LICENSE.txt", "LICENSE"],
    453         [os.path.join(here, os.pardir), here, os.curdir])
    454 
    455 
    456 class _Helper(object):
    457     """Define the builtin 'help'.
    458     This is a wrapper around pydoc.help (with a twist).
    459 
    460     """
    461 
    462     def __repr__(self):
    463         return "Type help() for interactive help, " \
    464                "or help(object) for help about object."
    465     def __call__(self, *args, **kwds):
    466         import pydoc
    467         return pydoc.help(*args, **kwds)
    468 
    469 def sethelper():
    470     __builtin__.help = _Helper()
    471 
    472 def aliasmbcs():
    473     """On Windows, some default encodings are not provided by Python,
    474     while they are always available as "mbcs" in each locale. Make
    475     them usable by aliasing to "mbcs" in such a case."""
    476     if sys.platform == 'win32':
    477         import locale, codecs
    478         enc = locale.getdefaultlocale()[1]
    479         if enc.startswith('cp'):            # "cp***" ?
    480             try:
    481                 codecs.lookup(enc)
    482             except LookupError:
    483                 import encodings
    484                 encodings._cache[enc] = encodings._unknown
    485                 encodings.aliases.aliases[enc] = 'mbcs'
    486 
    487 def setencoding():
    488     """Set the string encoding used by the Unicode implementation.  The
    489     default is 'ascii', but if you're willing to experiment, you can
    490     change this."""
    491     encoding = "ascii" # Default value set by _PyUnicode_Init()
    492     if 0:
    493         # Enable to support locale aware default string encodings.
    494         import locale
    495         loc = locale.getdefaultlocale()
    496         if loc[1]:
    497             encoding = loc[1]
    498     if 0:
    499         # Enable to switch off string to Unicode coercion and implicit
    500         # Unicode to string conversion.
    501         encoding = "undefined"
    502     if encoding != "ascii":
    503         # On Non-Unicode builds this will raise an AttributeError...
    504         sys.setdefaultencoding(encoding) # Needs Python Unicode build !
    505 
    506 
    507 def execsitecustomize():
    508     """Run custom site specific code, if available."""
    509     try:
    510         import sitecustomize
    511     except ImportError:
    512         pass
    513     except Exception:
    514         if sys.flags.verbose:
    515             sys.excepthook(*sys.exc_info())
    516         else:
    517             print >>sys.stderr, \
    518                 "'import sitecustomize' failed; use -v for traceback"
    519 
    520 
    521 def execusercustomize():
    522     """Run custom user specific code, if available."""
    523     try:
    524         import usercustomize
    525     except ImportError:
    526         pass
    527     except Exception:
    528         if sys.flags.verbose:
    529             sys.excepthook(*sys.exc_info())
    530         else:
    531             print>>sys.stderr, \
    532                 "'import usercustomize' failed; use -v for traceback"
    533 
    534 
    535 def main():
    536     global ENABLE_USER_SITE
    537 
    538     abs__file__()
    539     known_paths = removeduppaths()
    540     if (os.name == "posix" and sys.path and
    541         os.path.basename(sys.path[-1]) == "Modules"):
    542         addbuilddir()
    543     if ENABLE_USER_SITE is None:
    544         ENABLE_USER_SITE = check_enableusersite()
    545     known_paths = addusersitepackages(known_paths)
    546     known_paths = addsitepackages(known_paths)
    547     if sys.platform == 'os2emx':
    548         setBEGINLIBPATH()
    549     setquit()
    550     setcopyright()
    551     sethelper()
    552     aliasmbcs()
    553     setencoding()
    554     execsitecustomize()
    555     if ENABLE_USER_SITE:
    556         execusercustomize()
    557     # Remove sys.setdefaultencoding() so that users cannot change the
    558     # encoding after initialization.  The test for presence is needed when
    559     # this module is run as a script, because this code is executed twice.
    560     if hasattr(sys, "setdefaultencoding"):
    561         del sys.setdefaultencoding
    562 
    563 main()
    564 
    565 def _script():
    566     help = """\
    567     %s [--user-base] [--user-site]
    568 
    569     Without arguments print some useful information
    570     With arguments print the value of USER_BASE and/or USER_SITE separated
    571     by '%s'.
    572 
    573     Exit codes with --user-base or --user-site:
    574       0 - user site directory is enabled
    575       1 - user site directory is disabled by user
    576       2 - uses site directory is disabled by super user
    577           or for security reasons
    578      >2 - unknown error
    579     """
    580     args = sys.argv[1:]
    581     if not args:
    582         print "sys.path = ["
    583         for dir in sys.path:
    584             print "    %r," % (dir,)
    585         print "]"
    586         print "USER_BASE: %r (%s)" % (USER_BASE,
    587             "exists" if os.path.isdir(USER_BASE) else "doesn't exist")
    588         print "USER_SITE: %r (%s)" % (USER_SITE,
    589             "exists" if os.path.isdir(USER_SITE) else "doesn't exist")
    590         print "ENABLE_USER_SITE: %r" %  ENABLE_USER_SITE
    591         sys.exit(0)
    592 
    593     buffer = []
    594     if '--user-base' in args:
    595         buffer.append(USER_BASE)
    596     if '--user-site' in args:
    597         buffer.append(USER_SITE)
    598 
    599     if buffer:
    600         print os.pathsep.join(buffer)
    601         if ENABLE_USER_SITE:
    602             sys.exit(0)
    603         elif ENABLE_USER_SITE is False:
    604             sys.exit(1)
    605         elif ENABLE_USER_SITE is None:
    606             sys.exit(2)
    607         else:
    608             sys.exit(3)
    609     else:
    610         import textwrap
    611         print textwrap.dedent(help % (sys.argv[0], os.pathsep))
    612         sys.exit(10)
    613 
    614 if __name__ == '__main__':
    615     _script()
    616