blob: 0641c72bf9c6eefecbe15aa60b43df721b8307c0 [file] [log] [blame]
Tor Norbye3a2425a2013-11-04 10:16:08 -08001"""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__
64ModuleType = type(os)
65
66
67def makepath(*paths):
68 dir = os.path.join(*paths)
69 if dir == '__classpath__' or dir.startswith('__pyclasspath__'):
70 return dir, dir
71 dir = os.path.abspath(dir)
72 return dir, os.path.normcase(dir)
73
74def abs__file__():
75 """Set all module' __file__ attribute to an absolute path"""
76 for m in sys.modules.values():
77 if not isinstance(m, ModuleType) or hasattr(m, '__loader__'):
78 # only modules need the abspath in Jython. and don't mess
79 # with a PEP 302-supplied __file__
80 continue
81 f = getattr(m, '__file__', None)
82 if f is None:
83 continue
84 m.__file__ = os.path.abspath(f)
85
86def removeduppaths():
87 """ Remove duplicate entries from sys.path along with making them
88 absolute"""
89 # This ensures that the initial path provided by the interpreter contains
90 # only absolute pathnames, even if we're running from the build directory.
91 L = []
92 known_paths = set()
93 for dir in sys.path:
94 # Filter out duplicate paths (on case-insensitive file systems also
95 # if they only differ in case); turn relative paths into absolute
96 # paths.
97 dir, dircase = makepath(dir)
98 if not dircase in known_paths:
99 L.append(dir)
100 known_paths.add(dircase)
101 sys.path[:] = L
102 return known_paths
103
104# XXX This should not be part of site.py, since it is needed even when
105# using the -S option for Python. See http://www.python.org/sf/586680
106def addbuilddir():
107 """Append ./build/lib.<platform> in case we're running in the build dir
108 (especially for Guido :-)"""
109 from distutils.util import get_platform
110 s = "build/lib.%s-%.3s" % (get_platform(), sys.version)
111 s = os.path.join(os.path.dirname(sys.path[-1]), s)
112 sys.path.append(s)
113
114def _init_pathinfo():
115 """Return a set containing all existing directory entries from sys.path"""
116 d = set()
117 for dir in sys.path:
118 try:
119 if os.path.isdir(dir):
120 dir, dircase = makepath(dir)
121 d.add(dircase)
122 except TypeError:
123 continue
124 return d
125
126def addpackage(sitedir, name, known_paths):
127 """Add a new path to known_paths by combining sitedir and 'name' or execute
128 sitedir if it starts with 'import'"""
129 if known_paths is None:
130 _init_pathinfo()
131 reset = 1
132 else:
133 reset = 0
134 fullname = os.path.join(sitedir, name)
135 try:
136 f = open(fullname, "rU")
137 except IOError:
138 return
139 try:
140 for line in f:
141 if line.startswith("#"):
142 continue
143 if line.startswith("import"):
144 exec line
145 continue
146 line = line.rstrip()
147 dir, dircase = makepath(sitedir, line)
148 if not dircase in known_paths and os.path.exists(dir):
149 sys.path.append(dir)
150 known_paths.add(dircase)
151 finally:
152 f.close()
153 if reset:
154 known_paths = None
155 return known_paths
156
157def addsitedir(sitedir, known_paths=None):
158 """Add 'sitedir' argument to sys.path if missing and handle .pth files in
159 'sitedir'"""
160 if known_paths is None:
161 known_paths = _init_pathinfo()
162 reset = 1
163 else:
164 reset = 0
165 sitedir, sitedircase = makepath(sitedir)
166 if not sitedircase in known_paths:
167 sys.path.append(sitedir) # Add path component
168 try:
169 names = os.listdir(sitedir)
170 except os.error:
171 return
172 names.sort()
173 for name in names:
174 if name.endswith(os.extsep + "pth"):
175 addpackage(sitedir, name, known_paths)
176 if reset:
177 known_paths = None
178 return known_paths
179
180def addsitepackages(known_paths):
181 """Add site-packages (and possibly site-python) to sys.path"""
182 prefixes = [sys.prefix]
183 if sys.exec_prefix != sys.prefix:
184 prefixes.append(sys.exec_prefix)
185 for prefix in prefixes:
186 if prefix:
187 if sys.platform in ('os2emx', 'riscos') or sys.platform[:4] == 'java':
188 sitedirs = [os.path.join(prefix, "Lib", "site-packages")]
189 elif os.sep == '/':
190 sitedirs = [os.path.join(prefix,
191 "lib",
192 "python" + sys.version[:3],
193 "site-packages"),
194 os.path.join(prefix, "lib", "site-python")]
195 else:
196 sitedirs = [prefix, os.path.join(prefix, "lib", "site-packages")]
197 if sys.platform == 'darwin':
198 # for framework builds *only* we add the standard Apple
199 # locations. Currently only per-user, but /Library and
200 # /Network/Library could be added too
201 if 'Python.framework' in prefix:
202 home = os.environ.get('HOME')
203 if home:
204 sitedirs.append(
205 os.path.join(home,
206 'Library',
207 'Python',
208 sys.version[:3],
209 'site-packages'))
210 for sitedir in sitedirs:
211 if os.path.isdir(sitedir):
212 addsitedir(sitedir, known_paths)
213 return None
214
215
216def setBEGINLIBPATH():
217 """The OS/2 EMX port has optional extension modules that do double duty
218 as DLLs (and must use the .DLL file extension) for other extensions.
219 The library search path needs to be amended so these will be found
220 during module import. Use BEGINLIBPATH so that these are at the start
221 of the library search path.
222
223 """
224 dllpath = os.path.join(sys.prefix, "Lib", "lib-dynload")
225 libpath = os.environ['BEGINLIBPATH'].split(';')
226 if libpath[-1]:
227 libpath.append(dllpath)
228 else:
229 libpath[-1] = dllpath
230 os.environ['BEGINLIBPATH'] = ';'.join(libpath)
231
232
233def setquit():
234 """Define new built-ins 'quit' and 'exit'.
235 These are simply strings that display a hint on how to exit.
236
237 """
238 if os.sep == ':':
239 eof = 'Cmd-Q'
240 elif os.sep == '\\':
241 eof = 'Ctrl-Z plus Return'
242 else:
243 eof = 'Ctrl-D (i.e. EOF)'
244
245 class Quitter(object):
246 def __init__(self, name):
247 self.name = name
248 def __repr__(self):
249 return 'Use %s() or %s to exit' % (self.name, eof)
250 def __call__(self, code=None):
251 # Shells like IDLE catch the SystemExit, but listen when their
252 # stdin wrapper is closed.
253 try:
254 sys.stdin.close()
255 except:
256 pass
257 raise SystemExit(code)
258 __builtin__.quit = Quitter('quit')
259 __builtin__.exit = Quitter('exit')
260
261
262class _Printer(object):
263 """interactive prompt objects for printing the license text, a list of
264 contributors and the copyright notice."""
265
266 MAXLINES = 23
267
268 def __init__(self, name, data, files=(), dirs=()):
269 self.__name = name
270 self.__data = data
271 self.__files = files
272 self.__dirs = dirs
273 self.__lines = None
274
275 def __setup(self):
276 if self.__lines:
277 return
278 data = None
279 for dir in self.__dirs:
280 for filename in self.__files:
281 filename = os.path.join(dir, filename)
282 try:
283 fp = file(filename, "rU")
284 data = fp.read()
285 fp.close()
286 break
287 except IOError:
288 pass
289 if data:
290 break
291 if not data:
292 data = self.__data
293 self.__lines = data.split('\n')
294 self.__linecnt = len(self.__lines)
295
296 def __repr__(self):
297 self.__setup()
298 if len(self.__lines) <= self.MAXLINES:
299 return "\n".join(self.__lines)
300 else:
301 return "Type %s() to see the full %s text" % ((self.__name,)*2)
302
303 def __call__(self):
304 self.__setup()
305 prompt = 'Hit Return for more, or q (and Return) to quit: '
306 lineno = 0
307 while 1:
308 try:
309 for i in range(lineno, lineno + self.MAXLINES):
310 print self.__lines[i]
311 except IndexError:
312 break
313 else:
314 lineno += self.MAXLINES
315 key = None
316 while key is None:
317 key = raw_input(prompt)
318 if key not in ('', 'q'):
319 key = None
320 if key == 'q':
321 break
322
323def setcopyright():
324 """Set 'copyright' and 'credits' in __builtin__"""
325 __builtin__.copyright = _Printer("copyright", sys.copyright)
326 if sys.platform[:4] == 'java':
327 __builtin__.credits = _Printer(
328 "credits",
329 "Jython is maintained by the Jython developers (www.jython.org).")
330 else:
331 __builtin__.credits = _Printer("credits", """\
332 Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands
333 for supporting Python development. See www.python.org for more information.""")
334 here = os.path.dirname(os.__file__)
335 __builtin__.license = _Printer(
336 "license", "See http://www.python.org/%.3s/license.html" % sys.version,
337 ["LICENSE.txt", "LICENSE"],
338 [os.path.join(here, os.pardir), here, os.curdir])
339
340
341class _Helper(object):
342 """Define the built-in 'help'.
343 This is a wrapper around pydoc.help (with a twist).
344
345 """
346
347 def __repr__(self):
348 return "Type help() for interactive help, " \
349 "or help(object) for help about object."
350 def __call__(self, *args, **kwds):
351 import pydoc
352 return pydoc.help(*args, **kwds)
353
354def sethelper():
355 __builtin__.help = _Helper()
356
357def aliasmbcs():
358 """On Windows, some default encodings are not provided by Python,
359 while they are always available as "mbcs" in each locale. Make
360 them usable by aliasing to "mbcs" in such a case."""
361 if sys.platform == 'win32':
362 import locale, codecs
363 enc = locale.getdefaultlocale()[1]
364 if enc.startswith('cp'): # "cp***" ?
365 try:
366 codecs.lookup(enc)
367 except LookupError:
368 import encodings
369 encodings._cache[enc] = encodings._unknown
370 encodings.aliases.aliases[enc] = 'mbcs'
371
372def setencoding():
373 """Set the string encoding used by the Unicode implementation. The
374 default is 'ascii', but if you're willing to experiment, you can
375 change this."""
376 encoding = "ascii" # Default value set by _PyUnicode_Init()
377 if 0:
378 # Enable to support locale aware default string encodings.
379 import locale
380 loc = locale.getdefaultlocale()
381 if loc[1]:
382 encoding = loc[1]
383 if 0:
384 # Enable to switch off string to Unicode coercion and implicit
385 # Unicode to string conversion.
386 encoding = "undefined"
387 if encoding != "ascii":
388 # On Non-Unicode builds this will raise an AttributeError...
389 sys.setdefaultencoding(encoding) # Needs Python Unicode build !
390
391
392def execsitecustomize():
393 """Run custom site specific code, if available."""
394 try:
395 import sitecustomize
396 except ImportError:
397 pass
398
399
400def main():
401 abs__file__()
402 paths_in_sys = removeduppaths()
403 if (os.name == "posix" and sys.path and
404 os.path.basename(sys.path[-1]) == "Modules"):
405 addbuilddir()
406 paths_in_sys = addsitepackages(paths_in_sys)
407 if sys.platform == 'os2emx':
408 setBEGINLIBPATH()
409 setquit()
410 setcopyright()
411 sethelper()
412 aliasmbcs()
413 setencoding()
414 execsitecustomize()
415 # Remove sys.setdefaultencoding() so that users cannot change the
416 # encoding after initialization. The test for presence is needed when
417 # this module is run as a script, because this code is executed twice.
418 if hasattr(sys, "setdefaultencoding"):
419 del sys.setdefaultencoding
420
421main()
422
423def _test():
424 print "sys.path = ["
425 for dir in sys.path:
426 print " %r," % (dir,)
427 print "]"
428
429if __name__ == '__main__':
430 _test()