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    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
220def 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
234def 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
258def 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
272def 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
309def 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
317def 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
334def 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
365class _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
426def 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
444class _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
457def sethelper():
458    __builtin__.help = _Helper()
459
460def 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
475def 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
495def 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
509def 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
523def 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
548main()
549
550def _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
599if __name__ == '__main__':
600    _script()
601