• Home
  • History
  • Annotate
  • 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 
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 
118 def _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 
131 def 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 
172 def 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 
196 def 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 
224 def 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 
238 def 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 
262 def 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 
276 def 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 
304 def 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 
312 def 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 
329 def 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 
360 class _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 
421 def 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 
439 class _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 
452 def sethelper():
453     __builtin__.help = _Helper()
454 
455 def 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 
470 def 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 
490 def 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 
504 def 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 
518 def 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 
545 main()
546 
547 def _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 
596 if __name__ == '__main__':
597     _script()
598