blob: e138849de6eba9154ee2e51b3cc3f5f452b1c500 [file] [log] [blame]
Guido van Rossuma4deda02002-12-23 16:30:00 +00001"""Utilities to support packages."""
2
Phillip J. Ebyab1d2452006-04-17 20:17:25 +00003# NOTE: This module must remain compatible with Python 2.3, as it is shared
4# by setuptools for distribution with Python 2.3 and up.
5
Guido van Rossuma4deda02002-12-23 16:30:00 +00006import os
7import sys
Phillip J. Ebyab1d2452006-04-17 20:17:25 +00008import imp
9import os.path
10from types import ModuleType
11
12__all__ = [
13 'get_importer', 'iter_importers', 'get_loader', 'find_loader',
Phillip J. Ebyceb30872006-04-18 00:59:55 +000014 'walk_packages', 'iter_modules',
Phillip J. Ebyab1d2452006-04-17 20:17:25 +000015 'ImpImporter', 'ImpLoader', 'read_code', 'extend_path',
16]
17
18def read_code(stream):
19 # This helper is needed in order for the PEP 302 emulation to
20 # correctly handle compiled files
21 import marshal
22
23 magic = stream.read(4)
24 if magic != imp.get_magic():
25 return None
26
27 stream.read(4) # Skip timestamp
28 return marshal.load(stream)
29
30
Phillip J. Ebyceb30872006-04-18 00:59:55 +000031def simplegeneric(func):
32 """Make a trivial single-dispatch generic function"""
33 registry = {}
Neal Norwitz0bbbb002006-04-28 04:32:20 +000034 def wrapper(*args, **kw):
Phillip J. Ebyceb30872006-04-18 00:59:55 +000035 ob = args[0]
36 try:
37 cls = ob.__class__
38 except AttributeError:
39 cls = type(ob)
40 try:
41 mro = cls.__mro__
42 except AttributeError:
43 try:
Neal Norwitz0bbbb002006-04-28 04:32:20 +000044 class cls(cls, object):
45 pass
Phillip J. Ebyceb30872006-04-18 00:59:55 +000046 mro = cls.__mro__[1:]
47 except TypeError:
Tim Peters584b0e02006-04-18 17:32:12 +000048 mro = object, # must be an ExtensionClass or some such :(
Phillip J. Ebyceb30872006-04-18 00:59:55 +000049 for t in mro:
50 if t in registry:
Neal Norwitz0bbbb002006-04-28 04:32:20 +000051 return registry[t](*args, **kw)
Phillip J. Ebyceb30872006-04-18 00:59:55 +000052 else:
Neal Norwitz0bbbb002006-04-28 04:32:20 +000053 return func(*args, **kw)
Phillip J. Ebyceb30872006-04-18 00:59:55 +000054 try:
55 wrapper.__name__ = func.__name__
Neal Norwitz0bbbb002006-04-28 04:32:20 +000056 except (TypeError, AttributeError):
Phillip J. Ebyceb30872006-04-18 00:59:55 +000057 pass # Python 2.3 doesn't allow functions to be renamed
58
59 def register(typ, func=None):
60 if func is None:
61 return lambda f: register(typ, f)
62 registry[typ] = func
63 return func
64
65 wrapper.__dict__ = func.__dict__
66 wrapper.__doc__ = func.__doc__
67 wrapper.register = register
Tim Peters584b0e02006-04-18 17:32:12 +000068 return wrapper
Phillip J. Ebyceb30872006-04-18 00:59:55 +000069
70
71def walk_packages(path=None, prefix='', onerror=None):
Georg Brandl69b9b672006-07-25 10:22:34 +000072 """Yields (module_loader, name, ispkg) for all modules recursively
73 on path, or, if path is None, all accessible modules.
Tim Peters91343072006-07-25 22:30:24 +000074
Georg Brandl69b9b672006-07-25 10:22:34 +000075 'path' should be either None or a list of paths to look for
76 modules in.
77
78 'prefix' is a string to output on the front of every module name
79 on output.
80
81 Note that this function must import all *packages* (NOT all
82 modules!) on the given path, in order to access the __path__
83 attribute to find submodules.
Tim Peters91343072006-07-25 22:30:24 +000084
Georg Brandl69b9b672006-07-25 10:22:34 +000085 'onerror' is a function which gets called with one argument (the
86 name of the package which was being imported) if an ImportError
87 occurs trying to import a package. By default the ImportError is
88 caught and ignored.
89
90 Examples:
91 walk_packages() : list all modules python can access
92 walk_packages(ctypes.__path__, ctypes.__name__+'.') : list all submodules of ctypes
93 """
Phillip J. Ebyceb30872006-04-18 00:59:55 +000094
Neal Norwitz0bbbb002006-04-28 04:32:20 +000095 def seen(p, m={}):
96 if p in m:
97 return True
Phillip J. Ebyceb30872006-04-18 00:59:55 +000098 m[p] = True
99
100 for importer, name, ispkg in iter_modules(path, prefix):
101 yield importer, name, ispkg
102
103 if ispkg:
104 try:
105 __import__(name)
106 except ImportError:
107 if onerror is not None:
Georg Brandl69b9b672006-07-25 10:22:34 +0000108 onerror(name)
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000109 else:
110 path = getattr(sys.modules[name], '__path__', None) or []
111
112 # don't traverse path items we've seen before
113 path = [p for p in path if not seen(p)]
114
Georg Brandl69b9b672006-07-25 10:22:34 +0000115 for item in walk_packages(path, name+'.', onerror):
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000116 yield item
117
118
119def iter_modules(path=None, prefix=''):
Georg Brandl69b9b672006-07-25 10:22:34 +0000120 """Yields (module_loader, name, ispkg) for all submodules on path,
121 or, if path is None, all top-level modules on sys.path.
122
123 'path' should be either None or a list of paths to look for
124 modules in.
125
126 'prefix' is a string to output on the front of every module name
127 on output.
128 """
Tim Peters91343072006-07-25 22:30:24 +0000129
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000130 if path is None:
131 importers = iter_importers()
132 else:
133 importers = map(get_importer, path)
134
135 yielded = {}
136 for i in importers:
137 for name, ispkg in iter_importer_modules(i, prefix):
138 if name not in yielded:
139 yielded[name] = 1
140 yield i, name, ispkg
141
142
143#@simplegeneric
144def iter_importer_modules(importer, prefix=''):
Neal Norwitz0bbbb002006-04-28 04:32:20 +0000145 if not hasattr(importer, 'iter_modules'):
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000146 return []
147 return importer.iter_modules(prefix)
148
149iter_importer_modules = simplegeneric(iter_importer_modules)
150
151
Phillip J. Ebyab1d2452006-04-17 20:17:25 +0000152class ImpImporter:
153 """PEP 302 Importer that wraps Python's "classic" import algorithm
154
155 ImpImporter(dirname) produces a PEP 302 importer that searches that
156 directory. ImpImporter(None) produces a PEP 302 importer that searches
157 the current sys.path, plus any modules that are frozen or built-in.
158
159 Note that ImpImporter does not currently support being used by placement
160 on sys.meta_path.
161 """
162
163 def __init__(self, path=None):
164 self.path = path
165
166 def find_module(self, fullname, path=None):
167 # Note: we ignore 'path' argument since it is only used via meta_path
168 subname = fullname.split(".")[-1]
169 if subname != fullname and self.path is None:
170 return None
171 if self.path is None:
172 path = None
173 else:
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000174 path = [os.path.realpath(self.path)]
Phillip J. Ebyab1d2452006-04-17 20:17:25 +0000175 try:
176 file, filename, etc = imp.find_module(subname, path)
177 except ImportError:
178 return None
179 return ImpLoader(fullname, file, filename, etc)
180
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000181 def iter_modules(self, prefix=''):
182 if self.path is None or not os.path.isdir(self.path):
183 return
184
185 yielded = {}
186 import inspect
187
188 filenames = os.listdir(self.path)
189 filenames.sort() # handle packages before same-named modules
190
191 for fn in filenames:
192 modname = inspect.getmodulename(fn)
193 if modname=='__init__' or modname in yielded:
194 continue
Tim Peters584b0e02006-04-18 17:32:12 +0000195
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000196 path = os.path.join(self.path, fn)
197 ispkg = False
198
199 if not modname and os.path.isdir(path) and '.' not in fn:
200 modname = fn
201 for fn in os.listdir(path):
202 subname = inspect.getmodulename(fn)
203 if subname=='__init__':
204 ispkg = True
205 break
206 else:
207 continue # not a package
208
209 if modname and '.' not in modname:
210 yielded[modname] = 1
211 yield prefix + modname, ispkg
212
Phillip J. Ebyab1d2452006-04-17 20:17:25 +0000213
214class ImpLoader:
215 """PEP 302 Loader that wraps Python's "classic" import algorithm
216 """
217 code = source = None
218
219 def __init__(self, fullname, file, filename, etc):
220 self.file = file
221 self.filename = filename
222 self.fullname = fullname
223 self.etc = etc
224
225 def load_module(self, fullname):
226 self._reopen()
227 try:
228 mod = imp.load_module(fullname, self.file, self.filename, self.etc)
229 finally:
230 if self.file:
231 self.file.close()
232 # Note: we don't set __loader__ because we want the module to look
233 # normal; i.e. this is just a wrapper for standard import machinery
234 return mod
235
236 def get_data(self, pathname):
237 return open(pathname, "rb").read()
238
239 def _reopen(self):
240 if self.file and self.file.closed:
Neal Norwitzf992a2b2006-06-11 07:26:27 +0000241 mod_type = self.etc[2]
Phillip J. Ebyab1d2452006-04-17 20:17:25 +0000242 if mod_type==imp.PY_SOURCE:
243 self.file = open(self.filename, 'rU')
244 elif mod_type in (imp.PY_COMPILED, imp.C_EXTENSION):
245 self.file = open(self.filename, 'rb')
246
247 def _fix_name(self, fullname):
248 if fullname is None:
249 fullname = self.fullname
250 elif fullname != self.fullname:
251 raise ImportError("Loader for module %s cannot handle "
252 "module %s" % (self.fullname, fullname))
253 return fullname
254
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000255 def is_package(self, fullname):
256 fullname = self._fix_name(fullname)
Phillip J. Ebyab1d2452006-04-17 20:17:25 +0000257 return self.etc[2]==imp.PKG_DIRECTORY
258
259 def get_code(self, fullname=None):
260 fullname = self._fix_name(fullname)
261 if self.code is None:
262 mod_type = self.etc[2]
263 if mod_type==imp.PY_SOURCE:
264 source = self.get_source(fullname)
265 self.code = compile(source, self.filename, 'exec')
266 elif mod_type==imp.PY_COMPILED:
267 self._reopen()
268 try:
269 self.code = read_code(self.file)
270 finally:
271 self.file.close()
272 elif mod_type==imp.PKG_DIRECTORY:
273 self.code = self._get_delegate().get_code()
274 return self.code
275
276 def get_source(self, fullname=None):
277 fullname = self._fix_name(fullname)
278 if self.source is None:
279 mod_type = self.etc[2]
280 if mod_type==imp.PY_SOURCE:
281 self._reopen()
282 try:
283 self.source = self.file.read()
284 finally:
285 self.file.close()
286 elif mod_type==imp.PY_COMPILED:
287 if os.path.exists(self.filename[:-1]):
288 f = open(self.filename[:-1], 'rU')
289 self.source = f.read()
290 f.close()
291 elif mod_type==imp.PKG_DIRECTORY:
292 self.source = self._get_delegate().get_source()
293 return self.source
294
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000295
Phillip J. Ebyab1d2452006-04-17 20:17:25 +0000296 def _get_delegate(self):
297 return ImpImporter(self.filename).find_module('__init__')
298
299 def get_filename(self, fullname=None):
300 fullname = self._fix_name(fullname)
301 mod_type = self.etc[2]
302 if self.etc[2]==imp.PKG_DIRECTORY:
303 return self._get_delegate().get_filename()
304 elif self.etc[2] in (imp.PY_SOURCE, imp.PY_COMPILED, imp.C_EXTENSION):
305 return self.filename
306 return None
307
308
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000309try:
310 import zipimport
311 from zipimport import zipimporter
Tim Peters584b0e02006-04-18 17:32:12 +0000312
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000313 def iter_zipimport_modules(importer, prefix=''):
314 dirlist = zipimport._zip_directory_cache[importer.archive].keys()
315 dirlist.sort()
316 _prefix = importer.prefix
317 plen = len(_prefix)
318 yielded = {}
319 import inspect
320 for fn in dirlist:
321 if not fn.startswith(_prefix):
322 continue
323
324 fn = fn[plen:].split(os.sep)
325
326 if len(fn)==2 and fn[1].startswith('__init__.py'):
327 if fn[0] not in yielded:
328 yielded[fn[0]] = 1
329 yield fn[0], True
330
331 if len(fn)!=1:
332 continue
333
334 modname = inspect.getmodulename(fn[0])
335 if modname=='__init__':
336 continue
337
338 if modname and '.' not in modname and modname not in yielded:
339 yielded[modname] = 1
340 yield prefix + modname, False
341
342 iter_importer_modules.register(zipimporter, iter_zipimport_modules)
343
344except ImportError:
345 pass
346
347
Phillip J. Ebyab1d2452006-04-17 20:17:25 +0000348def get_importer(path_item):
349 """Retrieve a PEP 302 importer for the given path item
350
351 The returned importer is cached in sys.path_importer_cache
352 if it was newly created by a path hook.
353
354 If there is no importer, a wrapper around the basic import
355 machinery is returned. This wrapper is never inserted into
356 the importer cache (None is inserted instead).
357
358 The cache (or part of it) can be cleared manually if a
359 rescan of sys.path_hooks is necessary.
360 """
361 try:
362 importer = sys.path_importer_cache[path_item]
363 except KeyError:
364 for path_hook in sys.path_hooks:
365 try:
366 importer = path_hook(path_item)
367 break
368 except ImportError:
369 pass
370 else:
371 importer = None
Neal Norwitz0bbbb002006-04-28 04:32:20 +0000372 sys.path_importer_cache.setdefault(path_item, importer)
Phillip J. Ebyab1d2452006-04-17 20:17:25 +0000373
Georg Brandlf4ef1162006-05-26 18:03:31 +0000374 # The boolean values are used for caching valid and invalid
375 # file paths for the built-in import machinery
376 if importer in (None, True, False):
Phillip J. Ebyab1d2452006-04-17 20:17:25 +0000377 try:
378 importer = ImpImporter(path_item)
379 except ImportError:
Georg Brandlf4ef1162006-05-26 18:03:31 +0000380 importer = None
Phillip J. Ebyab1d2452006-04-17 20:17:25 +0000381 return importer
382
383
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000384def iter_importers(fullname=""):
Phillip J. Ebyab1d2452006-04-17 20:17:25 +0000385 """Yield PEP 302 importers for the given module name
386
387 If fullname contains a '.', the importers will be for the package
388 containing fullname, otherwise they will be importers for sys.meta_path,
389 sys.path, and Python's "classic" import machinery, in that order. If
390 the named module is in a package, that package is imported as a side
391 effect of invoking this function.
392
393 Non PEP 302 mechanisms (e.g. the Windows registry) used by the
394 standard import machinery to find files in alternative locations
395 are partially supported, but are searched AFTER sys.path. Normally,
396 these locations are searched BEFORE sys.path, preventing sys.path
397 entries from shadowing them.
398
399 For this to cause a visible difference in behaviour, there must
400 be a module or package name that is accessible via both sys.path
401 and one of the non PEP 302 file system mechanisms. In this case,
402 the emulation will find the former version, while the builtin
403 import mechanism will find the latter.
404
405 Items of the following types can be affected by this discrepancy:
406 imp.C_EXTENSION, imp.PY_SOURCE, imp.PY_COMPILED, imp.PKG_DIRECTORY
407 """
408 if fullname.startswith('.'):
409 raise ImportError("Relative module names not supported")
410 if '.' in fullname:
411 # Get the containing package's __path__
412 pkg = '.'.join(fullname.split('.')[:-1])
413 if pkg not in sys.modules:
414 __import__(pkg)
Neal Norwitz0bbbb002006-04-28 04:32:20 +0000415 path = getattr(sys.modules[pkg], '__path__', None) or []
Phillip J. Ebyab1d2452006-04-17 20:17:25 +0000416 else:
417 for importer in sys.meta_path:
418 yield importer
419 path = sys.path
420 for item in path:
421 yield get_importer(item)
422 if '.' not in fullname:
423 yield ImpImporter()
424
Phillip J. Ebyab1d2452006-04-17 20:17:25 +0000425def get_loader(module_or_name):
426 """Get a PEP 302 "loader" object for module_or_name
427
428 If the module or package is accessible via the normal import
429 mechanism, a wrapper around the relevant part of that machinery
430 is returned. Returns None if the module cannot be found or imported.
431 If the named module is not already imported, its containing package
432 (if any) is imported, in order to establish the package __path__.
433
434 This function uses iter_importers(), and is thus subject to the same
435 limitations regarding platform-specific special import locations such
436 as the Windows registry.
437 """
438 if module_or_name in sys.modules:
439 module_or_name = sys.modules[module_or_name]
440 if isinstance(module_or_name, ModuleType):
441 module = module_or_name
Neal Norwitz0bbbb002006-04-28 04:32:20 +0000442 loader = getattr(module, '__loader__', None)
Phillip J. Ebyab1d2452006-04-17 20:17:25 +0000443 if loader is not None:
444 return loader
445 fullname = module.__name__
446 else:
447 fullname = module_or_name
448 return find_loader(fullname)
449
Phillip J. Ebyab1d2452006-04-17 20:17:25 +0000450def find_loader(fullname):
451 """Find a PEP 302 "loader" object for fullname
452
453 If fullname contains dots, path must be the containing package's __path__.
454 Returns None if the module cannot be found or imported. This function uses
455 iter_importers(), and is thus subject to the same limitations regarding
456 platform-specific special import locations such as the Windows registry.
457 """
458 for importer in iter_importers(fullname):
459 loader = importer.find_module(fullname)
460 if loader is not None:
461 return loader
462
463 return None
464
Guido van Rossuma4deda02002-12-23 16:30:00 +0000465
466def extend_path(path, name):
467 """Extend a package's path.
468
469 Intended use is to place the following code in a package's __init__.py:
470
471 from pkgutil import extend_path
472 __path__ = extend_path(__path__, __name__)
473
474 This will add to the package's __path__ all subdirectories of
475 directories on sys.path named after the package. This is useful
476 if one wants to distribute different parts of a single logical
477 package as multiple directories.
478
479 It also looks for *.pkg files beginning where * matches the name
480 argument. This feature is similar to *.pth files (see site.py),
481 except that it doesn't special-case lines starting with 'import'.
482 A *.pkg file is trusted at face value: apart from checking for
483 duplicates, all entries found in a *.pkg file are added to the
484 path, regardless of whether they are exist the filesystem. (This
485 is a feature.)
486
487 If the input path is not a list (as is the case for frozen
488 packages) it is returned unchanged. The input path is not
489 modified; an extended copy is returned. Items are only appended
490 to the copy at the end.
491
492 It is assumed that sys.path is a sequence. Items of sys.path that
493 are not (unicode or 8-bit) strings referring to existing
494 directories are ignored. Unicode items of sys.path that cause
495 errors when used as filenames may cause this function to raise an
496 exception (in line with os.path.isdir() behavior).
497 """
498
499 if not isinstance(path, list):
500 # This could happen e.g. when this is called from inside a
501 # frozen package. Return the path unchanged in that case.
502 return path
503
504 pname = os.path.join(*name.split('.')) # Reconstitute as relative path
505 # Just in case os.extsep != '.'
506 sname = os.extsep.join(name.split('.'))
507 sname_pkg = sname + os.extsep + "pkg"
508 init_py = "__init__" + os.extsep + "py"
509
510 path = path[:] # Start with a copy of the existing path
511
512 for dir in sys.path:
Raymond Hettinger7a70ea42003-09-17 05:50:59 +0000513 if not isinstance(dir, basestring) or not os.path.isdir(dir):
Guido van Rossuma4deda02002-12-23 16:30:00 +0000514 continue
515 subdir = os.path.join(dir, pname)
516 # XXX This may still add duplicate entries to path on
517 # case-insensitive filesystems
518 initfile = os.path.join(subdir, init_py)
519 if subdir not in path and os.path.isfile(initfile):
520 path.append(subdir)
521 # XXX Is this the right thing for subpackages like zope.app?
522 # It looks for a file named "zope.app.pkg"
523 pkgfile = os.path.join(dir, sname_pkg)
524 if os.path.isfile(pkgfile):
525 try:
526 f = open(pkgfile)
527 except IOError, msg:
528 sys.stderr.write("Can't open %s: %s\n" %
529 (pkgfile, msg))
530 else:
531 for line in f:
532 line = line.rstrip('\n')
533 if not line or line.startswith('#'):
534 continue
535 path.append(line) # Don't check for existence!
536 f.close()
537
538 return path