source: python/trunk/Lib/site.py@ 1381

Last change on this file since 1381 was 1381, checked in by dmik, 7 years ago

python: Expect missing BEGINLIBPATH in environment on OS/2.

  • Property svn:eol-style set to native
File size: 19.3 KB
Line 
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 ('riscos'):
289 sitepackages.append(os.path.join(prefix, "Lib", "site-packages"))
290 elif os.sep == '/' or os.name == 'os2':
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 if os.name == 'os2':
296 sitepackages.append(os.path.join(prefix, "lib", "site-packages"))
297 else:
298 sitepackages.append(prefix)
299 sitepackages.append(os.path.join(prefix, "lib", "site-packages"))
300 if sys.platform == "darwin":
301 # for framework builds *only* we add the standard Apple
302 # locations.
303 from sysconfig import get_config_var
304 framework = get_config_var("PYTHONFRAMEWORK")
305 if framework:
306 sitepackages.append(
307 os.path.join("/Library", framework,
308 sys.version[:3], "site-packages"))
309 return sitepackages
310
311def addsitepackages(known_paths):
312 """Add site-packages (and possibly site-python) to sys.path"""
313 for sitedir in getsitepackages():
314 if os.path.isdir(sitedir):
315 addsitedir(sitedir, known_paths)
316
317 return known_paths
318
319def setBEGINLIBPATH():
320 """The OS/2 EMX port has optional extension modules that do double duty
321 as DLLs (and must use the .DLL file extension) for other extensions.
322 The library search path needs to be amended so these will be found
323 during module import. Use BEGINLIBPATH so that these are at the start
324 of the library search path.
325
326 """
327 dllpath = os.path.join(sys.prefix, "Lib", "lib-dynload")
328 libpath = os.environ.get('BEGINLIBPATH', '').split(';')
329 if libpath[-1]:
330 libpath.append(dllpath)
331 else:
332 libpath[-1] = dllpath
333 os.environ['BEGINLIBPATH'] = ';'.join(libpath)
334
335
336def setquit():
337 """Define new builtins 'quit' and 'exit'.
338
339 These are objects which make the interpreter exit when called.
340 The repr of each object contains a hint at how it works.
341
342 """
343 if os.sep == ':':
344 eof = 'Cmd-Q'
345 elif os.sep == '\\':
346 eof = 'Ctrl-Z plus Return'
347 else:
348 eof = 'Ctrl-D (i.e. EOF)'
349
350 class Quitter(object):
351 def __init__(self, name):
352 self.name = name
353 def __repr__(self):
354 return 'Use %s() or %s to exit' % (self.name, eof)
355 def __call__(self, code=None):
356 # Shells like IDLE catch the SystemExit, but listen when their
357 # stdin wrapper is closed.
358 try:
359 sys.stdin.close()
360 except:
361 pass
362 raise SystemExit(code)
363 __builtin__.quit = Quitter('quit')
364 __builtin__.exit = Quitter('exit')
365
366
367class _Printer(object):
368 """interactive prompt objects for printing the license text, a list of
369 contributors and the copyright notice."""
370
371 MAXLINES = 23
372
373 def __init__(self, name, data, files=(), dirs=()):
374 self.__name = name
375 self.__data = data
376 self.__files = files
377 self.__dirs = dirs
378 self.__lines = None
379
380 def __setup(self):
381 if self.__lines:
382 return
383 data = None
384 for dir in self.__dirs:
385 for filename in self.__files:
386 filename = os.path.join(dir, filename)
387 try:
388 fp = file(filename, "rU")
389 data = fp.read()
390 fp.close()
391 break
392 except IOError:
393 pass
394 if data:
395 break
396 if not data:
397 data = self.__data
398 self.__lines = data.split('\n')
399 self.__linecnt = len(self.__lines)
400
401 def __repr__(self):
402 self.__setup()
403 if len(self.__lines) <= self.MAXLINES:
404 return "\n".join(self.__lines)
405 else:
406 return "Type %s() to see the full %s text" % ((self.__name,)*2)
407
408 def __call__(self):
409 self.__setup()
410 prompt = 'Hit Return for more, or q (and Return) to quit: '
411 lineno = 0
412 while 1:
413 try:
414 for i in range(lineno, lineno + self.MAXLINES):
415 print self.__lines[i]
416 except IndexError:
417 break
418 else:
419 lineno += self.MAXLINES
420 key = None
421 while key is None:
422 key = raw_input(prompt)
423 if key not in ('', 'q'):
424 key = None
425 if key == 'q':
426 break
427
428def setcopyright():
429 """Set 'copyright' and 'credits' in __builtin__"""
430 __builtin__.copyright = _Printer("copyright", sys.copyright)
431 if sys.platform[:4] == 'java':
432 __builtin__.credits = _Printer(
433 "credits",
434 "Jython is maintained by the Jython developers (www.jython.org).")
435 else:
436 __builtin__.credits = _Printer("credits", """\
437 Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands
438 for supporting Python development. See www.python.org for more information.""")
439 here = os.path.dirname(os.__file__)
440 __builtin__.license = _Printer(
441 "license", "See http://www.python.org/%.3s/license.html" % sys.version,
442 ["LICENSE.txt", "LICENSE"],
443 [os.path.join(here, os.pardir), here, os.curdir])
444
445
446class _Helper(object):
447 """Define the builtin 'help'.
448 This is a wrapper around pydoc.help (with a twist).
449
450 """
451
452 def __repr__(self):
453 return "Type help() for interactive help, " \
454 "or help(object) for help about object."
455 def __call__(self, *args, **kwds):
456 import pydoc
457 return pydoc.help(*args, **kwds)
458
459def sethelper():
460 __builtin__.help = _Helper()
461
462def aliasmbcs():
463 """On Windows, some default encodings are not provided by Python,
464 while they are always available as "mbcs" in each locale. Make
465 them usable by aliasing to "mbcs" in such a case."""
466 if sys.platform == 'win32':
467 import locale, codecs
468 enc = locale.getdefaultlocale()[1]
469 if enc.startswith('cp'): # "cp***" ?
470 try:
471 codecs.lookup(enc)
472 except LookupError:
473 import encodings
474 encodings._cache[enc] = encodings._unknown
475 encodings.aliases.aliases[enc] = 'mbcs'
476
477def setencoding():
478 """Set the string encoding used by the Unicode implementation. The
479 default is 'ascii', but if you're willing to experiment, you can
480 change this."""
481 encoding = "ascii" # Default value set by _PyUnicode_Init()
482 if 1:
483 # Enable to support locale aware default string encodings.
484 import locale
485 loc = locale.getdefaultlocale()
486 if loc[1]:
487 encoding = loc[1]
488 if 0:
489 # Enable to switch off string to Unicode coercion and implicit
490 # Unicode to string conversion.
491 encoding = "undefined"
492 if encoding != "ascii":
493 # On Non-Unicode builds this will raise an AttributeError...
494 sys.setdefaultencoding(encoding) # Needs Python Unicode build !
495
496
497def execsitecustomize():
498 """Run custom site specific code, if available."""
499 try:
500 import sitecustomize
501 except ImportError:
502 pass
503 except Exception:
504 if sys.flags.verbose:
505 sys.excepthook(*sys.exc_info())
506 else:
507 print >>sys.stderr, \
508 "'import sitecustomize' failed; use -v for traceback"
509
510
511def execusercustomize():
512 """Run custom user specific code, if available."""
513 try:
514 import usercustomize
515 except ImportError:
516 pass
517 except Exception:
518 if sys.flags.verbose:
519 sys.excepthook(*sys.exc_info())
520 else:
521 print>>sys.stderr, \
522 "'import usercustomize' failed; use -v for traceback"
523
524
525def main():
526 global ENABLE_USER_SITE
527
528 abs__file__()
529 known_paths = removeduppaths()
530 if ENABLE_USER_SITE is None:
531 ENABLE_USER_SITE = check_enableusersite()
532 known_paths = addusersitepackages(known_paths)
533 known_paths = addsitepackages(known_paths)
534 if os.name == "os2":
535 setBEGINLIBPATH()
536 setquit()
537 setcopyright()
538 sethelper()
539 aliasmbcs()
540 setencoding()
541 execsitecustomize()
542 if ENABLE_USER_SITE:
543 execusercustomize()
544 # Remove sys.setdefaultencoding() so that users cannot change the
545 # encoding after initialization. The test for presence is needed when
546 # this module is run as a script, because this code is executed twice.
547 if hasattr(sys, "setdefaultencoding"):
548 del sys.setdefaultencoding
549
550main()
551
552def _script():
553 help = """\
554 %s [--user-base] [--user-site]
555
556 Without arguments print some useful information
557 With arguments print the value of USER_BASE and/or USER_SITE separated
558 by '%s'.
559
560 Exit codes with --user-base or --user-site:
561 0 - user site directory is enabled
562 1 - user site directory is disabled by user
563 2 - uses site directory is disabled by super user
564 or for security reasons
565 >2 - unknown error
566 """
567 args = sys.argv[1:]
568 if not args:
569 print "sys.path = ["
570 for dir in sys.path:
571 print " %r," % (dir,)
572 print "]"
573 print "USER_BASE: %r (%s)" % (USER_BASE,
574 "exists" if os.path.isdir(USER_BASE) else "doesn't exist")
575 print "USER_SITE: %r (%s)" % (USER_SITE,
576 "exists" if os.path.isdir(USER_SITE) else "doesn't exist")
577 print "ENABLE_USER_SITE: %r" % ENABLE_USER_SITE
578 sys.exit(0)
579
580 buffer = []
581 if '--user-base' in args:
582 buffer.append(USER_BASE)
583 if '--user-site' in args:
584 buffer.append(USER_SITE)
585
586 if buffer:
587 print os.pathsep.join(buffer)
588 if ENABLE_USER_SITE:
589 sys.exit(0)
590 elif ENABLE_USER_SITE is False:
591 sys.exit(1)
592 elif ENABLE_USER_SITE is None:
593 sys.exit(2)
594 else:
595 sys.exit(3)
596 else:
597 import textwrap
598 print textwrap.dedent(help % (sys.argv[0], os.pathsep))
599 sys.exit(10)
600
601if __name__ == '__main__':
602 _script()
Note: See TracBrowser for help on using the repository browser.