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# 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
119def 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
130def _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
143def 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
184def 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
208def 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
232def 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
246def 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
270def 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
284def 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
321def 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
329def 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
346def 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
377class _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
438def 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
456class _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
469def sethelper():
470    __builtin__.help = _Helper()
471
472def 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
487def 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
507def 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
521def 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
535def 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
563main()
564
565def _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
614if __name__ == '__main__':
615    _script()
616