• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1"""Append module search paths for third-party packages to sys.path.
2
3****************************************************************
4* This module is automatically imported during initialization. *
5****************************************************************
6
7In earlier versions of Python (up to 1.5a3), scripts or modules that
8needed to use site-specific modules would place ``import site''
9somewhere near the top of their code.  Because of the automatic
10import, this is no longer necessary (but code that does it still
11works).
12
13This will append site-specific paths to the module search path.  On
14Unix (including Mac OSX), it starts with sys.prefix and
15sys.exec_prefix (if different) and appends
16lib/python<version>/site-packages as well as lib/site-python.
17On other platforms (such as Windows), it tries each of the
18prefixes directly, as well as with lib/site-packages appended.  The
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/usr/local and there is a directory /usr/local/lib/python2.5/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  /usr/local/lib/python2.5/site-packages/bar
48  /usr/local/lib/python2.5/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
59"""
60
61import sys
62import os
63import __builtin__
64import traceback
65
66# Prefixes for site-packages; add additional prefixes like /usr/local here
67PREFIXES = [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
70ENABLE_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.
75USER_SITE = None
76USER_BASE = None
77
78
79def 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
88def 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
99def 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
118def _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
131def 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
172def 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
196def 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    # GOOGLE(nanzhang): Don't enable user-site directories,
207    # everything's supposed to be hermetic.
208    return None
209
210    if sys.flags.no_user_site:
211        return False
212
213    if hasattr(os, "getuid") and hasattr(os, "geteuid"):
214        # check process uid == effective uid
215        if os.geteuid() != os.getuid():
216            return None
217    if hasattr(os, "getgid") and hasattr(os, "getegid"):
218        # check process gid == effective gid
219        if os.getegid() != os.getgid():
220            return None
221
222    return True
223
224def getuserbase():
225    """Returns the `user base` directory path.
226
227    The `user base` directory can be used to store data. If the global
228    variable ``USER_BASE`` is not initialized yet, this function will also set
229    it.
230    """
231    global USER_BASE
232    if USER_BASE is not None:
233        return USER_BASE
234    from sysconfig import get_config_var
235    USER_BASE = get_config_var('userbase')
236    return USER_BASE
237
238def getusersitepackages():
239    """Returns the user-specific site-packages directory path.
240
241    If the global variable ``USER_SITE`` is not initialized yet, this
242    function will also set it.
243    """
244    global USER_SITE
245    user_base = getuserbase() # this will also set USER_BASE
246
247    if USER_SITE is not None:
248        return USER_SITE
249
250    from sysconfig import get_path
251    import os
252
253    if sys.platform == 'darwin':
254        from sysconfig import get_config_var
255        if get_config_var('PYTHONFRAMEWORK'):
256            USER_SITE = get_path('purelib', 'osx_framework_user')
257            return USER_SITE
258
259    USER_SITE = get_path('purelib', '%s_user' % os.name)
260    return USER_SITE
261
262def addusersitepackages(known_paths):
263    """Add a per user site-package to sys.path
264
265    Each user has its own python directory with site-packages in the
266    home directory.
267    """
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    if ENABLE_USER_SITE and os.path.isdir(user_site):
273        addsitedir(user_site, known_paths)
274    return known_paths
275
276def getsitepackages():
277    """Returns a list containing all global site-packages directories
278    (and possibly site-python).
279
280    For each directory present in the global ``PREFIXES``, this function
281    will find its `site-packages` subdirectory depending on the system
282    environment, and will return a list of full paths.
283    """
284    sitepackages = []
285    seen = set()
286
287    for prefix in PREFIXES:
288        if not prefix or prefix in seen:
289            continue
290        seen.add(prefix)
291
292        if sys.platform in ('os2emx', 'riscos'):
293            sitepackages.append(os.path.join(prefix, "Lib", "site-packages"))
294        elif os.sep == '/':
295            sitepackages.append(os.path.join(prefix, "lib",
296                                        "python" + sys.version[:3],
297                                        "site-packages"))
298            sitepackages.append(os.path.join(prefix, "lib", "site-python"))
299        else:
300            sitepackages.append(prefix)
301            sitepackages.append(os.path.join(prefix, "lib", "site-packages"))
302    return sitepackages
303
304def addsitepackages(known_paths):
305    """Add site-packages (and possibly site-python) to sys.path"""
306    for sitedir in getsitepackages():
307        if os.path.isdir(sitedir):
308            addsitedir(sitedir, known_paths)
309
310    return known_paths
311
312def setBEGINLIBPATH():
313    """The OS/2 EMX port has optional extension modules that do double duty
314    as DLLs (and must use the .DLL file extension) for other extensions.
315    The library search path needs to be amended so these will be found
316    during module import.  Use BEGINLIBPATH so that these are at the start
317    of the library search path.
318
319    """
320    dllpath = os.path.join(sys.prefix, "Lib", "lib-dynload")
321    libpath = os.environ['BEGINLIBPATH'].split(';')
322    if libpath[-1]:
323        libpath.append(dllpath)
324    else:
325        libpath[-1] = dllpath
326    os.environ['BEGINLIBPATH'] = ';'.join(libpath)
327
328
329def setquit():
330    """Define new builtins 'quit' and 'exit'.
331
332    These are objects which make the interpreter exit when called.
333    The repr of each object contains a hint at how it works.
334
335    """
336    if os.sep == ':':
337        eof = 'Cmd-Q'
338    elif os.sep == '\\':
339        eof = 'Ctrl-Z plus Return'
340    else:
341        eof = 'Ctrl-D (i.e. EOF)'
342
343    class Quitter(object):
344        def __init__(self, name):
345            self.name = name
346        def __repr__(self):
347            return 'Use %s() or %s to exit' % (self.name, eof)
348        def __call__(self, code=None):
349            # Shells like IDLE catch the SystemExit, but listen when their
350            # stdin wrapper is closed.
351            try:
352                sys.stdin.close()
353            except:
354                pass
355            raise SystemExit(code)
356    __builtin__.quit = Quitter('quit')
357    __builtin__.exit = Quitter('exit')
358
359
360class _Printer(object):
361    """interactive prompt objects for printing the license text, a list of
362    contributors and the copyright notice."""
363
364    MAXLINES = 23
365
366    def __init__(self, name, data, files=(), dirs=()):
367        self.__name = name
368        self.__data = data
369        self.__files = files
370        self.__dirs = dirs
371        self.__lines = None
372
373    def __setup(self):
374        if self.__lines:
375            return
376        data = None
377        for dir in self.__dirs:
378            for filename in self.__files:
379                filename = os.path.join(dir, filename)
380                try:
381                    fp = file(filename, "rU")
382                    data = fp.read()
383                    fp.close()
384                    break
385                except IOError:
386                    pass
387            if data:
388                break
389        if not data:
390            data = self.__data
391        self.__lines = data.split('\n')
392        self.__linecnt = len(self.__lines)
393
394    def __repr__(self):
395        self.__setup()
396        if len(self.__lines) <= self.MAXLINES:
397            return "\n".join(self.__lines)
398        else:
399            return "Type %s() to see the full %s text" % ((self.__name,)*2)
400
401    def __call__(self):
402        self.__setup()
403        prompt = 'Hit Return for more, or q (and Return) to quit: '
404        lineno = 0
405        while 1:
406            try:
407                for i in range(lineno, lineno + self.MAXLINES):
408                    print self.__lines[i]
409            except IndexError:
410                break
411            else:
412                lineno += self.MAXLINES
413                key = None
414                while key is None:
415                    key = raw_input(prompt)
416                    if key not in ('', 'q'):
417                        key = None
418                if key == 'q':
419                    break
420
421def setcopyright():
422    """Set 'copyright' and 'credits' in __builtin__"""
423    __builtin__.copyright = _Printer("copyright", sys.copyright)
424    if sys.platform[:4] == 'java':
425        __builtin__.credits = _Printer(
426            "credits",
427            "Jython is maintained by the Jython developers (www.jython.org).")
428    else:
429        __builtin__.credits = _Printer("credits", """\
430    Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands
431    for supporting Python development.  See www.python.org for more information.""")
432    here = os.path.dirname(os.__file__)
433    __builtin__.license = _Printer(
434        "license", "See https://www.python.org/psf/license/",
435        ["LICENSE.txt", "LICENSE"],
436        [os.path.join(here, os.pardir), here, os.curdir])
437
438
439class _Helper(object):
440    """Define the builtin 'help'.
441    This is a wrapper around pydoc.help (with a twist).
442
443    """
444
445    def __repr__(self):
446        return "Type help() for interactive help, " \
447               "or help(object) for help about object."
448    def __call__(self, *args, **kwds):
449        import pydoc
450        return pydoc.help(*args, **kwds)
451
452def sethelper():
453    __builtin__.help = _Helper()
454
455def aliasmbcs():
456    """On Windows, some default encodings are not provided by Python,
457    while they are always available as "mbcs" in each locale. Make
458    them usable by aliasing to "mbcs" in such a case."""
459    if sys.platform == 'win32':
460        import locale, codecs
461        enc = locale.getdefaultlocale()[1]
462        if enc.startswith('cp'):            # "cp***" ?
463            try:
464                codecs.lookup(enc)
465            except LookupError:
466                import encodings
467                encodings._cache[enc] = encodings._unknown
468                encodings.aliases.aliases[enc] = 'mbcs'
469
470def setencoding():
471    """Set the string encoding used by the Unicode implementation.  The
472    default is 'ascii', but if you're willing to experiment, you can
473    change this."""
474    encoding = "ascii" # Default value set by _PyUnicode_Init()
475    if 0:
476        # Enable to support locale aware default string encodings.
477        import locale
478        loc = locale.getdefaultlocale()
479        if loc[1]:
480            encoding = loc[1]
481    if 0:
482        # Enable to switch off string to Unicode coercion and implicit
483        # Unicode to string conversion.
484        encoding = "undefined"
485    if encoding != "ascii":
486        # On Non-Unicode builds this will raise an AttributeError...
487        sys.setdefaultencoding(encoding) # Needs Python Unicode build !
488
489
490def execsitecustomize():
491    """Run custom site specific code, if available."""
492    try:
493        import sitecustomize
494    except ImportError:
495        pass
496    except Exception:
497        if sys.flags.verbose:
498            sys.excepthook(*sys.exc_info())
499        else:
500            print >>sys.stderr, \
501                "'import sitecustomize' failed; use -v for traceback"
502
503
504def execusercustomize():
505    """Run custom user specific code, if available."""
506    try:
507        import usercustomize
508    except ImportError:
509        pass
510    except Exception:
511        if sys.flags.verbose:
512            sys.excepthook(*sys.exc_info())
513        else:
514            print>>sys.stderr, \
515                "'import usercustomize' failed; use -v for traceback"
516
517
518def main():
519    global ENABLE_USER_SITE
520
521    abs__file__()
522    known_paths = removeduppaths()
523    if ENABLE_USER_SITE is None:
524        ENABLE_USER_SITE = check_enableusersite()
525    if ENABLE_USER_SITE:
526        known_paths = addusersitepackages(known_paths)
527
528    known_paths = addsitepackages(known_paths)
529    if sys.platform == 'os2emx':
530        setBEGINLIBPATH()
531    setquit()
532    setcopyright()
533    sethelper()
534    aliasmbcs()
535    setencoding()
536    execsitecustomize()
537    if ENABLE_USER_SITE:
538        execusercustomize()
539    # Remove sys.setdefaultencoding() so that users cannot change the
540    # encoding after initialization.  The test for presence is needed when
541    # this module is run as a script, because this code is executed twice.
542    if hasattr(sys, "setdefaultencoding"):
543        del sys.setdefaultencoding
544
545main()
546
547def _script():
548    help = """\
549    %s [--user-base] [--user-site]
550
551    Without arguments print some useful information
552    With arguments print the value of USER_BASE and/or USER_SITE separated
553    by '%s'.
554
555    Exit codes with --user-base or --user-site:
556      0 - user site directory is enabled
557      1 - user site directory is disabled by user
558      2 - uses site directory is disabled by super user
559          or for security reasons
560     >2 - unknown error
561    """
562    args = sys.argv[1:]
563    if not args:
564        print "sys.path = ["
565        for dir in sys.path:
566            print "    %r," % (dir,)
567        print "]"
568        print "USER_BASE: %r (%s)" % (USER_BASE,
569            "exists" if os.path.isdir(USER_BASE) else "doesn't exist")
570        print "USER_SITE: %r (%s)" % (USER_SITE,
571            "exists" if os.path.isdir(USER_SITE) else "doesn't exist")
572        print "ENABLE_USER_SITE: %r" %  ENABLE_USER_SITE
573        sys.exit(0)
574
575    buffer = []
576    if '--user-base' in args:
577        buffer.append(USER_BASE)
578    if '--user-site' in args:
579        buffer.append(USER_SITE)
580
581    if buffer:
582        print os.pathsep.join(buffer)
583        if ENABLE_USER_SITE:
584            sys.exit(0)
585        elif ENABLE_USER_SITE is False:
586            sys.exit(1)
587        elif ENABLE_USER_SITE is None:
588            sys.exit(2)
589        else:
590            sys.exit(3)
591    else:
592        import textwrap
593        print textwrap.dedent(help % (sys.argv[0], os.pathsep))
594        sys.exit(10)
595
596if __name__ == '__main__':
597    _script()
598