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