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

Last change on this file since 10 was 10, checked in by Yuri Dario, 15 years ago

python: merged offline changes.

  • Property svn:eol-style set to native
File size: 18.2 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__
64
65# Prefixes for site-packages; add additional prefixes like /usr/local here
66PREFIXES = [sys.prefix, sys.exec_prefix]
67# Enable per user site-packages directory
68# set it to False to disable the feature or True to force the feature
69ENABLE_USER_SITE = None
70# for distutils.commands.install
71USER_SITE = None
72USER_BASE = None
73
74
75def makepath(*paths):
76 dir = os.path.abspath(os.path.join(*paths))
77 return dir, os.path.normcase(dir)
78
79
80def abs__file__():
81 """Set all module' __file__ attribute to an absolute path"""
82 for m in sys.modules.values():
83 if hasattr(m, '__loader__'):
84 continue # don't mess with a PEP 302-supplied __file__
85 try:
86 m.__file__ = os.path.abspath(m.__file__)
87 except AttributeError:
88 continue
89
90
91def removeduppaths():
92 """ Remove duplicate entries from sys.path along with making them
93 absolute"""
94 # This ensures that the initial path provided by the interpreter contains
95 # only absolute pathnames, even if we're running from the build directory.
96 L = []
97 known_paths = set()
98 for dir in sys.path:
99 # Filter out duplicate paths (on case-insensitive file systems also
100 # if they only differ in case); turn relative paths into absolute
101 # paths.
102 dir, dircase = makepath(dir)
103 if not dircase in known_paths:
104 L.append(dir)
105 known_paths.add(dircase)
106 sys.path[:] = L
107 return known_paths
108
109# XXX This should not be part of site.py, since it is needed even when
110# using the -S option for Python. See http://www.python.org/sf/586680
111def addbuilddir():
112 """Append ./build/lib.<platform> in case we're running in the build dir
113 (especially for Guido :-)"""
114 from distutils.util import get_platform
115 s = "build/lib.%s-%.3s" % (get_platform(), sys.version)
116 if hasattr(sys, 'gettotalrefcount'):
117 s += '-pydebug'
118 s = os.path.join(os.path.dirname(sys.path[-1]), s)
119 sys.path.append(s)
120
121
122def _init_pathinfo():
123 """Return a set containing all existing directory entries from sys.path"""
124 d = set()
125 for dir in sys.path:
126 try:
127 if os.path.isdir(dir):
128 dir, dircase = makepath(dir)
129 d.add(dircase)
130 except TypeError:
131 continue
132 return d
133
134
135def addpackage(sitedir, name, known_paths):
136 """Process a .pth file within the site-packages directory:
137 For each line in the file, either combine it with sitedir to a path
138 and add that to known_paths, or execute it if it starts with 'import '.
139 """
140 if known_paths is None:
141 _init_pathinfo()
142 reset = 1
143 else:
144 reset = 0
145 fullname = os.path.join(sitedir, name)
146 try:
147 f = open(fullname, "rU")
148 except IOError:
149 return
150 with f:
151 for line in f:
152 if line.startswith("#"):
153 continue
154 if line.startswith(("import ", "import\t")):
155 exec line
156 continue
157 line = line.rstrip()
158 dir, dircase = makepath(sitedir, line)
159 if not dircase in known_paths and os.path.exists(dir):
160 sys.path.append(dir)
161 known_paths.add(dircase)
162 if reset:
163 known_paths = None
164 return known_paths
165
166
167def addsitedir(sitedir, known_paths=None):
168 """Add 'sitedir' argument to sys.path if missing and handle .pth files in
169 'sitedir'"""
170 if known_paths is None:
171 known_paths = _init_pathinfo()
172 reset = 1
173 else:
174 reset = 0
175 sitedir, sitedircase = makepath(sitedir)
176 if not sitedircase in known_paths:
177 sys.path.append(sitedir) # Add path component
178 try:
179 names = os.listdir(sitedir)
180 except os.error:
181 return
182 dotpth = os.extsep + "pth"
183 names = [name for name in names if name.endswith(dotpth)]
184 for name in sorted(names):
185 addpackage(sitedir, name, known_paths)
186 if reset:
187 known_paths = None
188 return known_paths
189
190
191def check_enableusersite():
192 """Check if user site directory is safe for inclusion
193
194 The function tests for the command line flag (including environment var),
195 process uid/gid equal to effective uid/gid.
196
197 None: Disabled for security reasons
198 False: Disabled by user (command line option)
199 True: Safe and enabled
200 """
201 if sys.flags.no_user_site:
202 return False
203
204 if hasattr(os, "getuid") and hasattr(os, "geteuid"):
205 # check process uid == effective uid
206 if os.geteuid() != os.getuid():
207 return None
208 if hasattr(os, "getgid") and hasattr(os, "getegid"):
209 # check process gid == effective gid
210 if os.getegid() != os.getgid():
211 return None
212
213 return True
214
215
216def addusersitepackages(known_paths):
217 """Add a per user site-package to sys.path
218
219 Each user has its own python directory with site-packages in the
220 home directory.
221
222 USER_BASE is the root directory for all Python versions
223
224 USER_SITE is the user specific site-packages directory
225
226 USER_SITE/.. can be used for data.
227 """
228 global USER_BASE, USER_SITE, ENABLE_USER_SITE
229 env_base = os.environ.get("PYTHONUSERBASE", None)
230
231 def joinuser(*args):
232 return os.path.expanduser(os.path.join(*args))
233
234 #if sys.platform in ('os2emx', 'os2knix', 'riscos'):
235 # # Don't know what to put here
236 # USER_BASE = ''
237 # USER_SITE = ''
238 if os.name == "nt":
239 base = os.environ.get("APPDATA") or "~"
240 USER_BASE = env_base if env_base else joinuser(base, "Python")
241 USER_SITE = os.path.join(USER_BASE,
242 "Python" + sys.version[0] + sys.version[2],
243 "site-packages")
244 else:
245 USER_BASE = env_base if env_base else joinuser("~", ".local")
246 USER_SITE = os.path.join(USER_BASE, "lib",
247 "python" + sys.version[:3],
248 "site-packages")
249
250 if ENABLE_USER_SITE and os.path.isdir(USER_SITE):
251 addsitedir(USER_SITE, known_paths)
252 return known_paths
253
254
255def addsitepackages(known_paths):
256 """Add site-packages (and possibly site-python) to sys.path"""
257 sitedirs = []
258 seen = []
259
260 for prefix in PREFIXES:
261 if not prefix or prefix in seen:
262 continue
263 seen.append(prefix)
264
265 if sys.platform in ('os2emx', 'os2knix', 'riscos'):
266 sitedirs.append(os.path.join(prefix, "Lib", "site-packages"))
267 elif os.sep == '/':
268 sitedirs.append(os.path.join(prefix, "lib",
269 "python" + sys.version[:3],
270 "site-packages"))
271 sitedirs.append(os.path.join(prefix, "lib", "site-python"))
272 else:
273 sitedirs.append(prefix)
274 sitedirs.append(os.path.join(prefix, "lib", "site-packages"))
275
276 if sys.platform == "darwin":
277 # for framework builds *only* we add the standard Apple
278 # locations. Currently only per-user, but /Library and
279 # /Network/Library could be added too
280 if 'Python.framework' in prefix:
281 sitedirs.append(
282 os.path.expanduser(
283 os.path.join("~", "Library", "Python",
284 sys.version[:3], "site-packages")))
285
286 for sitedir in sitedirs:
287 if os.path.isdir(sitedir):
288 addsitedir(sitedir, known_paths)
289
290 return known_paths
291
292
293def setBEGINLIBPATH():
294 """The OS/2 EMX port has optional extension modules that do double duty
295 as DLLs (and must use the .DLL file extension) for other extensions.
296 The library search path needs to be amended so these will be found
297 during module import. Use BEGINLIBPATH so that these are at the start
298 of the library search path.
299
300 """
301 dllpath = os.path.join(sys.prefix, "Lib", "lib-dynload")
302 libpath = os.environ['BEGINLIBPATH'].split(';')
303 if libpath[-1]:
304 libpath.append(dllpath)
305 else:
306 libpath[-1] = dllpath
307 os.environ['BEGINLIBPATH'] = ';'.join(libpath)
308
309
310def setquit():
311 """Define new built-ins 'quit' and 'exit'.
312 These are simply strings that display a hint on how to exit.
313
314 """
315 if os.sep == ':':
316 eof = 'Cmd-Q'
317 elif os.sep == '\\':
318 eof = 'Ctrl-Z plus Return'
319 else:
320 eof = 'Ctrl-D (i.e. EOF)'
321
322 class Quitter(object):
323 def __init__(self, name):
324 self.name = name
325 def __repr__(self):
326 return 'Use %s() or %s to exit' % (self.name, eof)
327 def __call__(self, code=None):
328 # Shells like IDLE catch the SystemExit, but listen when their
329 # stdin wrapper is closed.
330 try:
331 sys.stdin.close()
332 except:
333 pass
334 raise SystemExit(code)
335 __builtin__.quit = Quitter('quit')
336 __builtin__.exit = Quitter('exit')
337
338
339class _Printer(object):
340 """interactive prompt objects for printing the license text, a list of
341 contributors and the copyright notice."""
342
343 MAXLINES = 23
344
345 def __init__(self, name, data, files=(), dirs=()):
346 self.__name = name
347 self.__data = data
348 self.__files = files
349 self.__dirs = dirs
350 self.__lines = None
351
352 def __setup(self):
353 if self.__lines:
354 return
355 data = None
356 for dir in self.__dirs:
357 for filename in self.__files:
358 filename = os.path.join(dir, filename)
359 try:
360 fp = file(filename, "rU")
361 data = fp.read()
362 fp.close()
363 break
364 except IOError:
365 pass
366 if data:
367 break
368 if not data:
369 data = self.__data
370 self.__lines = data.split('\n')
371 self.__linecnt = len(self.__lines)
372
373 def __repr__(self):
374 self.__setup()
375 if len(self.__lines) <= self.MAXLINES:
376 return "\n".join(self.__lines)
377 else:
378 return "Type %s() to see the full %s text" % ((self.__name,)*2)
379
380 def __call__(self):
381 self.__setup()
382 prompt = 'Hit Return for more, or q (and Return) to quit: '
383 lineno = 0
384 while 1:
385 try:
386 for i in range(lineno, lineno + self.MAXLINES):
387 print self.__lines[i]
388 except IndexError:
389 break
390 else:
391 lineno += self.MAXLINES
392 key = None
393 while key is None:
394 key = raw_input(prompt)
395 if key not in ('', 'q'):
396 key = None
397 if key == 'q':
398 break
399
400def setcopyright():
401 """Set 'copyright' and 'credits' in __builtin__"""
402 __builtin__.copyright = _Printer("copyright", sys.copyright)
403 if sys.platform[:4] == 'java':
404 __builtin__.credits = _Printer(
405 "credits",
406 "Jython is maintained by the Jython developers (www.jython.org).")
407 else:
408 __builtin__.credits = _Printer("credits", """\
409 Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands
410 for supporting Python development. See www.python.org for more information.""")
411 here = os.path.dirname(os.__file__)
412 __builtin__.license = _Printer(
413 "license", "See http://www.python.org/%.3s/license.html" % sys.version,
414 ["LICENSE.txt", "LICENSE"],
415 [os.path.join(here, os.pardir), here, os.curdir])
416
417
418class _Helper(object):
419 """Define the built-in 'help'.
420 This is a wrapper around pydoc.help (with a twist).
421
422 """
423
424 def __repr__(self):
425 return "Type help() for interactive help, " \
426 "or help(object) for help about object."
427 def __call__(self, *args, **kwds):
428 import pydoc
429 return pydoc.help(*args, **kwds)
430
431def sethelper():
432 __builtin__.help = _Helper()
433
434def aliasmbcs():
435 """On Windows, some default encodings are not provided by Python,
436 while they are always available as "mbcs" in each locale. Make
437 them usable by aliasing to "mbcs" in such a case."""
438 if sys.platform == 'win32':
439 import locale, codecs
440 enc = locale.getdefaultlocale()[1]
441 if enc.startswith('cp'): # "cp***" ?
442 try:
443 codecs.lookup(enc)
444 except LookupError:
445 import encodings
446 encodings._cache[enc] = encodings._unknown
447 encodings.aliases.aliases[enc] = 'mbcs'
448
449def setencoding():
450 """Set the string encoding used by the Unicode implementation. The
451 default is 'ascii', but if you're willing to experiment, you can
452 change this."""
453 encoding = "ascii" # Default value set by _PyUnicode_Init()
454 if 0:
455 # Enable to support locale aware default string encodings.
456 import locale
457 loc = locale.getdefaultlocale()
458 if loc[1]:
459 encoding = loc[1]
460 if 0:
461 # Enable to switch off string to Unicode coercion and implicit
462 # Unicode to string conversion.
463 encoding = "undefined"
464 if encoding != "ascii":
465 # On Non-Unicode builds this will raise an AttributeError...
466 sys.setdefaultencoding(encoding) # Needs Python Unicode build !
467
468
469def execsitecustomize():
470 """Run custom site specific code, if available."""
471 try:
472 import sitecustomize
473 except ImportError:
474 pass
475
476
477def execusercustomize():
478 """Run custom user specific code, if available."""
479 try:
480 import usercustomize
481 except ImportError:
482 pass
483
484
485def main():
486 global ENABLE_USER_SITE
487
488 abs__file__()
489 known_paths = removeduppaths()
490 if (os.name == "posix" and sys.path and
491 os.path.basename(sys.path[-1]) == "Modules"):
492 addbuilddir()
493 if ENABLE_USER_SITE is None:
494 ENABLE_USER_SITE = check_enableusersite()
495 known_paths = addusersitepackages(known_paths)
496 known_paths = addsitepackages(known_paths)
497 if sys.platform == 'os2emx' or sys.platform == 'os2knix':
498 if (sys.path and os.path.basename(sys.path[-1]) == "Modules"):
499 addbuilddir()
500 setBEGINLIBPATH()
501 setquit()
502 setcopyright()
503 sethelper()
504 aliasmbcs()
505 setencoding()
506 execsitecustomize()
507 if ENABLE_USER_SITE:
508 execusercustomize()
509 # Remove sys.setdefaultencoding() so that users cannot change the
510 # encoding after initialization. The test for presence is needed when
511 # this module is run as a script, because this code is executed twice.
512 if hasattr(sys, "setdefaultencoding"):
513 del sys.setdefaultencoding
514
515main()
516
517def _script():
518 help = """\
519 %s [--user-base] [--user-site]
520
521 Without arguments print some useful information
522 With arguments print the value of USER_BASE and/or USER_SITE separated
523 by '%s'.
524
525 Exit codes with --user-base or --user-site:
526 0 - user site directory is enabled
527 1 - user site directory is disabled by user
528 2 - uses site directory is disabled by super user
529 or for security reasons
530 >2 - unknown error
531 """
532 args = sys.argv[1:]
533 if not args:
534 print "sys.path = ["
535 for dir in sys.path:
536 print " %r," % (dir,)
537 print "]"
538 print "USER_BASE: %r (%s)" % (USER_BASE,
539 "exists" if os.path.isdir(USER_BASE) else "doesn't exist")
540 print "USER_SITE: %r (%s)" % (USER_SITE,
541 "exists" if os.path.isdir(USER_SITE) else "doesn't exist")
542 print "ENABLE_USER_SITE: %r" % ENABLE_USER_SITE
543 sys.exit(0)
544
545 buffer = []
546 if '--user-base' in args:
547 buffer.append(USER_BASE)
548 if '--user-site' in args:
549 buffer.append(USER_SITE)
550
551 if buffer:
552 print os.pathsep.join(buffer)
553 if ENABLE_USER_SITE:
554 sys.exit(0)
555 elif ENABLE_USER_SITE is False:
556 sys.exit(1)
557 elif ENABLE_USER_SITE is None:
558 sys.exit(2)
559 else:
560 sys.exit(3)
561 else:
562 import textwrap
563 print textwrap.dedent(help % (sys.argv[0], os.pathsep))
564 sys.exit(10)
565
566if __name__ == '__main__':
567 _script()
Note: See TracBrowser for help on using the repository browser.