Catch situations where currentframe() returns None. See SF patch #1447410, this is...
[python.git] / Lib / site.py
blob6818e8531f9f00586be3a44032152b3a71097781
1 """Append module search paths for third-party packages to sys.path.
3 ****************************************************************
4 * This module is automatically imported during initialization. *
5 ****************************************************************
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).
13 This will append site-specific paths to the module search path. On
14 Unix, it starts with sys.prefix and sys.exec_prefix (if different) and
15 appends lib/python<version>/site-packages as well as lib/site-python.
16 On other platforms (mainly Mac and Windows), it uses just sys.prefix
17 (and sys.exec_prefix, if different, but this is unlikely). The
18 resulting directories, if they exist, are appended to sys.path, and
19 also inspected for path configuration files.
21 A path configuration file is a file whose name has the form
22 <package>.pth; its contents are additional directories (one per line)
23 to be added to sys.path. Non-existing directories (or
24 non-directories) are never added to sys.path; no directory is added to
25 sys.path more than once. Blank lines and lines beginning with
26 '#' are skipped. Lines starting with 'import' are executed.
28 For example, suppose sys.prefix and sys.exec_prefix are set to
29 /usr/local and there is a directory /usr/local/lib/python1.5/site-packages
30 with three subdirectories, foo, bar and spam, and two path
31 configuration files, foo.pth and bar.pth. Assume foo.pth contains the
32 following:
34 # foo package configuration
35 foo
36 bar
37 bletch
39 and bar.pth contains:
41 # bar package configuration
42 bar
44 Then the following directories are added to sys.path, in this order:
46 /usr/local/lib/python1.5/site-packages/bar
47 /usr/local/lib/python1.5/site-packages/foo
49 Note that bletch is omitted because it doesn't exist; bar precedes foo
50 because bar.pth comes alphabetically before foo.pth; and spam is
51 omitted because it is not mentioned in either path configuration file.
53 After these path manipulations, an attempt is made to import a module
54 named sitecustomize, which can perform arbitrary additional
55 site-specific customizations. If this import fails with an
56 ImportError exception, it is silently ignored.
58 """
60 import sys
61 import os
62 import __builtin__
65 def makepath(*paths):
66 dir = os.path.abspath(os.path.join(*paths))
67 return dir, os.path.normcase(dir)
69 def abs__file__():
70 """Set all module' __file__ attribute to an absolute path"""
71 for m in sys.modules.values():
72 try:
73 m.__file__ = os.path.abspath(m.__file__)
74 except AttributeError:
75 continue
77 def removeduppaths():
78 """ Remove duplicate entries from sys.path along with making them
79 absolute"""
80 # This ensures that the initial path provided by the interpreter contains
81 # only absolute pathnames, even if we're running from the build directory.
82 L = []
83 known_paths = set()
84 for dir in sys.path:
85 # Filter out duplicate paths (on case-insensitive file systems also
86 # if they only differ in case); turn relative paths into absolute
87 # paths.
88 dir, dircase = makepath(dir)
89 if not dircase in known_paths:
90 L.append(dir)
91 known_paths.add(dircase)
92 sys.path[:] = L
93 return known_paths
95 # XXX This should not be part of site.py, since it is needed even when
96 # using the -S option for Python. See http://www.python.org/sf/586680
97 def addbuilddir():
98 """Append ./build/lib.<platform> in case we're running in the build dir
99 (especially for Guido :-)"""
100 from distutils.util import get_platform
101 s = "build/lib.%s-%.3s" % (get_platform(), sys.version)
102 s = os.path.join(os.path.dirname(sys.path[-1]), s)
103 sys.path.append(s)
105 def _init_pathinfo():
106 """Return a set containing all existing directory entries from sys.path"""
107 d = set()
108 for dir in sys.path:
109 try:
110 if os.path.isdir(dir):
111 dir, dircase = makepath(dir)
112 d.add(dircase)
113 except TypeError:
114 continue
115 return d
117 def addpackage(sitedir, name, known_paths):
118 """Add a new path to known_paths by combining sitedir and 'name' or execute
119 sitedir if it starts with 'import'"""
120 if known_paths is None:
121 _init_pathinfo()
122 reset = 1
123 else:
124 reset = 0
125 fullname = os.path.join(sitedir, name)
126 try:
127 f = open(fullname, "rU")
128 except IOError:
129 return
130 try:
131 for line in f:
132 if line.startswith("#"):
133 continue
134 if line.startswith("import"):
135 exec line
136 continue
137 line = line.rstrip()
138 dir, dircase = makepath(sitedir, line)
139 if not dircase in known_paths and os.path.exists(dir):
140 sys.path.append(dir)
141 known_paths.add(dircase)
142 finally:
143 f.close()
144 if reset:
145 known_paths = None
146 return known_paths
148 def addsitedir(sitedir, known_paths=None):
149 """Add 'sitedir' argument to sys.path if missing and handle .pth files in
150 'sitedir'"""
151 if known_paths is None:
152 known_paths = _init_pathinfo()
153 reset = 1
154 else:
155 reset = 0
156 sitedir, sitedircase = makepath(sitedir)
157 if not sitedircase in known_paths:
158 sys.path.append(sitedir) # Add path component
159 try:
160 names = os.listdir(sitedir)
161 except os.error:
162 return
163 names.sort()
164 for name in names:
165 if name.endswith(os.extsep + "pth"):
166 addpackage(sitedir, name, known_paths)
167 if reset:
168 known_paths = None
169 return known_paths
171 def addsitepackages(known_paths):
172 """Add site-packages (and possibly site-python) to sys.path"""
173 prefixes = [sys.prefix]
174 if sys.exec_prefix != sys.prefix:
175 prefixes.append(sys.exec_prefix)
176 for prefix in prefixes:
177 if prefix:
178 if sys.platform in ('os2emx', 'riscos'):
179 sitedirs = [os.path.join(prefix, "Lib", "site-packages")]
180 elif os.sep == '/':
181 sitedirs = [os.path.join(prefix,
182 "lib",
183 "python" + sys.version[:3],
184 "site-packages"),
185 os.path.join(prefix, "lib", "site-python")]
186 else:
187 sitedirs = [prefix, os.path.join(prefix, "lib", "site-packages")]
188 if sys.platform == 'darwin':
189 # for framework builds *only* we add the standard Apple
190 # locations. Currently only per-user, but /Library and
191 # /Network/Library could be added too
192 if 'Python.framework' in prefix:
193 home = os.environ.get('HOME')
194 if home:
195 sitedirs.append(
196 os.path.join(home,
197 'Library',
198 'Python',
199 sys.version[:3],
200 'site-packages'))
201 for sitedir in sitedirs:
202 if os.path.isdir(sitedir):
203 addsitedir(sitedir, known_paths)
204 return None
207 def setBEGINLIBPATH():
208 """The OS/2 EMX port has optional extension modules that do double duty
209 as DLLs (and must use the .DLL file extension) for other extensions.
210 The library search path needs to be amended so these will be found
211 during module import. Use BEGINLIBPATH so that these are at the start
212 of the library search path.
215 dllpath = os.path.join(sys.prefix, "Lib", "lib-dynload")
216 libpath = os.environ['BEGINLIBPATH'].split(';')
217 if libpath[-1]:
218 libpath.append(dllpath)
219 else:
220 libpath[-1] = dllpath
221 os.environ['BEGINLIBPATH'] = ';'.join(libpath)
224 def setquit():
225 """Define new built-ins 'quit' and 'exit'.
226 These are simply strings that display a hint on how to exit.
229 if os.sep == ':':
230 eof = 'Cmd-Q'
231 elif os.sep == '\\':
232 eof = 'Ctrl-Z plus Return'
233 else:
234 eof = 'Ctrl-D (i.e. EOF)'
236 class Quitter(object):
237 def __init__(self, name):
238 self.name = name
239 def __repr__(self):
240 return 'Use %s() or %s to exit' % (self.name, eof)
241 def __call__(self, code=None):
242 raise SystemExit(code)
243 __builtin__.quit = Quitter('quit')
244 __builtin__.exit = Quitter('exit')
247 class _Printer(object):
248 """interactive prompt objects for printing the license text, a list of
249 contributors and the copyright notice."""
251 MAXLINES = 23
253 def __init__(self, name, data, files=(), dirs=()):
254 self.__name = name
255 self.__data = data
256 self.__files = files
257 self.__dirs = dirs
258 self.__lines = None
260 def __setup(self):
261 if self.__lines:
262 return
263 data = None
264 for dir in self.__dirs:
265 for filename in self.__files:
266 filename = os.path.join(dir, filename)
267 try:
268 fp = file(filename, "rU")
269 data = fp.read()
270 fp.close()
271 break
272 except IOError:
273 pass
274 if data:
275 break
276 if not data:
277 data = self.__data
278 self.__lines = data.split('\n')
279 self.__linecnt = len(self.__lines)
281 def __repr__(self):
282 self.__setup()
283 if len(self.__lines) <= self.MAXLINES:
284 return "\n".join(self.__lines)
285 else:
286 return "Type %s() to see the full %s text" % ((self.__name,)*2)
288 def __call__(self):
289 self.__setup()
290 prompt = 'Hit Return for more, or q (and Return) to quit: '
291 lineno = 0
292 while 1:
293 try:
294 for i in range(lineno, lineno + self.MAXLINES):
295 print self.__lines[i]
296 except IndexError:
297 break
298 else:
299 lineno += self.MAXLINES
300 key = None
301 while key is None:
302 key = raw_input(prompt)
303 if key not in ('', 'q'):
304 key = None
305 if key == 'q':
306 break
308 def setcopyright():
309 """Set 'copyright' and 'credits' in __builtin__"""
310 __builtin__.copyright = _Printer("copyright", sys.copyright)
311 if sys.platform[:4] == 'java':
312 __builtin__.credits = _Printer(
313 "credits",
314 "Jython is maintained by the Jython developers (www.jython.org).")
315 else:
316 __builtin__.credits = _Printer("credits", """\
317 Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands
318 for supporting Python development. See www.python.org for more information.""")
319 here = os.path.dirname(os.__file__)
320 __builtin__.license = _Printer(
321 "license", "See http://www.python.org/%.3s/license.html" % sys.version,
322 ["LICENSE.txt", "LICENSE"],
323 [os.path.join(here, os.pardir), here, os.curdir])
326 class _Helper(object):
327 """Define the built-in 'help'.
328 This is a wrapper around pydoc.help (with a twist).
332 def __repr__(self):
333 return "Type help() for interactive help, " \
334 "or help(object) for help about object."
335 def __call__(self, *args, **kwds):
336 import pydoc
337 return pydoc.help(*args, **kwds)
339 def sethelper():
340 __builtin__.help = _Helper()
342 def aliasmbcs():
343 """On Windows, some default encodings are not provided by Python,
344 while they are always available as "mbcs" in each locale. Make
345 them usable by aliasing to "mbcs" in such a case."""
346 if sys.platform == 'win32':
347 import locale, codecs
348 enc = locale.getdefaultlocale()[1]
349 if enc.startswith('cp'): # "cp***" ?
350 try:
351 codecs.lookup(enc)
352 except LookupError:
353 import encodings
354 encodings._cache[enc] = encodings._unknown
355 encodings.aliases.aliases[enc] = 'mbcs'
357 def setencoding():
358 """Set the string encoding used by the Unicode implementation. The
359 default is 'ascii', but if you're willing to experiment, you can
360 change this."""
361 encoding = "ascii" # Default value set by _PyUnicode_Init()
362 if 0:
363 # Enable to support locale aware default string encodings.
364 import locale
365 loc = locale.getdefaultlocale()
366 if loc[1]:
367 encoding = loc[1]
368 if 0:
369 # Enable to switch off string to Unicode coercion and implicit
370 # Unicode to string conversion.
371 encoding = "undefined"
372 if encoding != "ascii":
373 # On Non-Unicode builds this will raise an AttributeError...
374 sys.setdefaultencoding(encoding) # Needs Python Unicode build !
377 def execsitecustomize():
378 """Run custom site specific code, if available."""
379 try:
380 import sitecustomize
381 except ImportError:
382 pass
385 def main():
386 abs__file__()
387 paths_in_sys = removeduppaths()
388 if (os.name == "posix" and sys.path and
389 os.path.basename(sys.path[-1]) == "Modules"):
390 addbuilddir()
391 paths_in_sys = addsitepackages(paths_in_sys)
392 if sys.platform == 'os2emx':
393 setBEGINLIBPATH()
394 setquit()
395 setcopyright()
396 sethelper()
397 aliasmbcs()
398 setencoding()
399 execsitecustomize()
400 # Remove sys.setdefaultencoding() so that users cannot change the
401 # encoding after initialization. The test for presence is needed when
402 # this module is run as a script, because this code is executed twice.
403 if hasattr(sys, "setdefaultencoding"):
404 del sys.setdefaultencoding
406 main()
408 def _test():
409 print "sys.path = ["
410 for dir in sys.path:
411 print " %r," % (dir,)
412 print "]"
414 if __name__ == '__main__':
415 _test()