blob: f4347e5e5446db68db20341242a91f8479105099 [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
Phillip J. Ebyeb26ea32006-07-26 19:48:27 +000086 name of the package which was being imported) if any exception
87 occurs while trying to import a package. If no onerror function is
88 supplied, ImportErrors are caught and ignored, while all other
89 exceptions are propagated, terminating the search.
Georg Brandl69b9b672006-07-25 10:22:34 +000090
91 Examples:
Phillip J. Ebyeb26ea32006-07-26 19:48:27 +000092
93 # list all modules python can access
Tim Peters95621b22006-07-26 23:23:15 +000094 walk_packages()
Phillip J. Ebyeb26ea32006-07-26 19:48:27 +000095
96 # list all submodules of ctypes
97 walk_packages(ctypes.__path__, ctypes.__name__+'.')
Georg Brandl69b9b672006-07-25 10:22:34 +000098 """
Phillip J. Ebyceb30872006-04-18 00:59:55 +000099
Neal Norwitz0bbbb002006-04-28 04:32:20 +0000100 def seen(p, m={}):
101 if p in m:
102 return True
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000103 m[p] = True
104
105 for importer, name, ispkg in iter_modules(path, prefix):
106 yield importer, name, ispkg
107
108 if ispkg:
109 try:
110 __import__(name)
111 except ImportError:
112 if onerror is not None:
Georg Brandl69b9b672006-07-25 10:22:34 +0000113 onerror(name)
Phillip J. Ebyeb26ea32006-07-26 19:48:27 +0000114 except Exception:
115 if onerror is not None:
116 onerror(name)
117 else:
118 raise
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000119 else:
120 path = getattr(sys.modules[name], '__path__', None) or []
121
122 # don't traverse path items we've seen before
123 path = [p for p in path if not seen(p)]
124
Georg Brandl69b9b672006-07-25 10:22:34 +0000125 for item in walk_packages(path, name+'.', onerror):
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000126 yield item
127
128
129def iter_modules(path=None, prefix=''):
Georg Brandl69b9b672006-07-25 10:22:34 +0000130 """Yields (module_loader, name, ispkg) for all submodules on path,
131 or, if path is None, all top-level modules on sys.path.
132
133 'path' should be either None or a list of paths to look for
134 modules in.
135
136 'prefix' is a string to output on the front of every module name
137 on output.
138 """
Tim Peters91343072006-07-25 22:30:24 +0000139
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000140 if path is None:
141 importers = iter_importers()
142 else:
143 importers = map(get_importer, path)
144
145 yielded = {}
146 for i in importers:
147 for name, ispkg in iter_importer_modules(i, prefix):
148 if name not in yielded:
149 yielded[name] = 1
150 yield i, name, ispkg
151
152
153#@simplegeneric
154def iter_importer_modules(importer, prefix=''):
Neal Norwitz0bbbb002006-04-28 04:32:20 +0000155 if not hasattr(importer, 'iter_modules'):
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000156 return []
157 return importer.iter_modules(prefix)
158
159iter_importer_modules = simplegeneric(iter_importer_modules)
160
161
Phillip J. Ebyab1d2452006-04-17 20:17:25 +0000162class ImpImporter:
163 """PEP 302 Importer that wraps Python's "classic" import algorithm
164
165 ImpImporter(dirname) produces a PEP 302 importer that searches that
166 directory. ImpImporter(None) produces a PEP 302 importer that searches
167 the current sys.path, plus any modules that are frozen or built-in.
168
169 Note that ImpImporter does not currently support being used by placement
170 on sys.meta_path.
171 """
172
173 def __init__(self, path=None):
174 self.path = path
175
176 def find_module(self, fullname, path=None):
177 # Note: we ignore 'path' argument since it is only used via meta_path
178 subname = fullname.split(".")[-1]
179 if subname != fullname and self.path is None:
180 return None
181 if self.path is None:
182 path = None
183 else:
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000184 path = [os.path.realpath(self.path)]
Phillip J. Ebyab1d2452006-04-17 20:17:25 +0000185 try:
186 file, filename, etc = imp.find_module(subname, path)
187 except ImportError:
188 return None
189 return ImpLoader(fullname, file, filename, etc)
190
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000191 def iter_modules(self, prefix=''):
192 if self.path is None or not os.path.isdir(self.path):
193 return
194
195 yielded = {}
196 import inspect
197
198 filenames = os.listdir(self.path)
199 filenames.sort() # handle packages before same-named modules
200
201 for fn in filenames:
202 modname = inspect.getmodulename(fn)
203 if modname=='__init__' or modname in yielded:
204 continue
Tim Peters584b0e02006-04-18 17:32:12 +0000205
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000206 path = os.path.join(self.path, fn)
207 ispkg = False
208
209 if not modname and os.path.isdir(path) and '.' not in fn:
210 modname = fn
211 for fn in os.listdir(path):
212 subname = inspect.getmodulename(fn)
213 if subname=='__init__':
214 ispkg = True
215 break
216 else:
217 continue # not a package
218
219 if modname and '.' not in modname:
220 yielded[modname] = 1
221 yield prefix + modname, ispkg
222
Phillip J. Ebyab1d2452006-04-17 20:17:25 +0000223
224class ImpLoader:
225 """PEP 302 Loader that wraps Python's "classic" import algorithm
226 """
227 code = source = None
228
229 def __init__(self, fullname, file, filename, etc):
230 self.file = file
231 self.filename = filename
232 self.fullname = fullname
233 self.etc = etc
234
235 def load_module(self, fullname):
236 self._reopen()
237 try:
238 mod = imp.load_module(fullname, self.file, self.filename, self.etc)
239 finally:
240 if self.file:
241 self.file.close()
242 # Note: we don't set __loader__ because we want the module to look
243 # normal; i.e. this is just a wrapper for standard import machinery
244 return mod
245
246 def get_data(self, pathname):
247 return open(pathname, "rb").read()
248
249 def _reopen(self):
250 if self.file and self.file.closed:
Neal Norwitzf992a2b2006-06-11 07:26:27 +0000251 mod_type = self.etc[2]
Phillip J. Ebyab1d2452006-04-17 20:17:25 +0000252 if mod_type==imp.PY_SOURCE:
253 self.file = open(self.filename, 'rU')
254 elif mod_type in (imp.PY_COMPILED, imp.C_EXTENSION):
255 self.file = open(self.filename, 'rb')
256
257 def _fix_name(self, fullname):
258 if fullname is None:
259 fullname = self.fullname
260 elif fullname != self.fullname:
261 raise ImportError("Loader for module %s cannot handle "
262 "module %s" % (self.fullname, fullname))
263 return fullname
264
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000265 def is_package(self, fullname):
266 fullname = self._fix_name(fullname)
Phillip J. Ebyab1d2452006-04-17 20:17:25 +0000267 return self.etc[2]==imp.PKG_DIRECTORY
268
269 def get_code(self, fullname=None):
270 fullname = self._fix_name(fullname)
271 if self.code is None:
272 mod_type = self.etc[2]
273 if mod_type==imp.PY_SOURCE:
274 source = self.get_source(fullname)
275 self.code = compile(source, self.filename, 'exec')
276 elif mod_type==imp.PY_COMPILED:
277 self._reopen()
278 try:
279 self.code = read_code(self.file)
280 finally:
281 self.file.close()
282 elif mod_type==imp.PKG_DIRECTORY:
283 self.code = self._get_delegate().get_code()
284 return self.code
285
286 def get_source(self, fullname=None):
287 fullname = self._fix_name(fullname)
288 if self.source is None:
289 mod_type = self.etc[2]
290 if mod_type==imp.PY_SOURCE:
291 self._reopen()
292 try:
293 self.source = self.file.read()
294 finally:
295 self.file.close()
296 elif mod_type==imp.PY_COMPILED:
297 if os.path.exists(self.filename[:-1]):
298 f = open(self.filename[:-1], 'rU')
299 self.source = f.read()
300 f.close()
301 elif mod_type==imp.PKG_DIRECTORY:
302 self.source = self._get_delegate().get_source()
303 return self.source
304
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000305
Phillip J. Ebyab1d2452006-04-17 20:17:25 +0000306 def _get_delegate(self):
307 return ImpImporter(self.filename).find_module('__init__')
308
309 def get_filename(self, fullname=None):
310 fullname = self._fix_name(fullname)
311 mod_type = self.etc[2]
312 if self.etc[2]==imp.PKG_DIRECTORY:
313 return self._get_delegate().get_filename()
314 elif self.etc[2] in (imp.PY_SOURCE, imp.PY_COMPILED, imp.C_EXTENSION):
315 return self.filename
316 return None
317
318
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000319try:
320 import zipimport
321 from zipimport import zipimporter
Tim Peters584b0e02006-04-18 17:32:12 +0000322
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000323 def iter_zipimport_modules(importer, prefix=''):
324 dirlist = zipimport._zip_directory_cache[importer.archive].keys()
325 dirlist.sort()
326 _prefix = importer.prefix
327 plen = len(_prefix)
328 yielded = {}
329 import inspect
330 for fn in dirlist:
331 if not fn.startswith(_prefix):
332 continue
333
334 fn = fn[plen:].split(os.sep)
335
336 if len(fn)==2 and fn[1].startswith('__init__.py'):
337 if fn[0] not in yielded:
338 yielded[fn[0]] = 1
339 yield fn[0], True
340
341 if len(fn)!=1:
342 continue
343
344 modname = inspect.getmodulename(fn[0])
345 if modname=='__init__':
346 continue
347
348 if modname and '.' not in modname and modname not in yielded:
349 yielded[modname] = 1
350 yield prefix + modname, False
351
352 iter_importer_modules.register(zipimporter, iter_zipimport_modules)
353
354except ImportError:
355 pass
356
357
Phillip J. Ebyab1d2452006-04-17 20:17:25 +0000358def get_importer(path_item):
359 """Retrieve a PEP 302 importer for the given path item
360
361 The returned importer is cached in sys.path_importer_cache
362 if it was newly created by a path hook.
363
364 If there is no importer, a wrapper around the basic import
365 machinery is returned. This wrapper is never inserted into
366 the importer cache (None is inserted instead).
367
368 The cache (or part of it) can be cleared manually if a
369 rescan of sys.path_hooks is necessary.
370 """
371 try:
372 importer = sys.path_importer_cache[path_item]
373 except KeyError:
374 for path_hook in sys.path_hooks:
375 try:
376 importer = path_hook(path_item)
377 break
378 except ImportError:
379 pass
380 else:
381 importer = None
Neal Norwitz0bbbb002006-04-28 04:32:20 +0000382 sys.path_importer_cache.setdefault(path_item, importer)
Phillip J. Ebyab1d2452006-04-17 20:17:25 +0000383
Georg Brandlf4ef1162006-05-26 18:03:31 +0000384 # The boolean values are used for caching valid and invalid
385 # file paths for the built-in import machinery
386 if importer in (None, True, False):
Phillip J. Ebyab1d2452006-04-17 20:17:25 +0000387 try:
388 importer = ImpImporter(path_item)
389 except ImportError:
Georg Brandlf4ef1162006-05-26 18:03:31 +0000390 importer = None
Phillip J. Ebyab1d2452006-04-17 20:17:25 +0000391 return importer
392
393
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000394def iter_importers(fullname=""):
Phillip J. Ebyab1d2452006-04-17 20:17:25 +0000395 """Yield PEP 302 importers for the given module name
396
397 If fullname contains a '.', the importers will be for the package
398 containing fullname, otherwise they will be importers for sys.meta_path,
399 sys.path, and Python's "classic" import machinery, in that order. If
400 the named module is in a package, that package is imported as a side
401 effect of invoking this function.
402
403 Non PEP 302 mechanisms (e.g. the Windows registry) used by the
404 standard import machinery to find files in alternative locations
405 are partially supported, but are searched AFTER sys.path. Normally,
406 these locations are searched BEFORE sys.path, preventing sys.path
407 entries from shadowing them.
408
409 For this to cause a visible difference in behaviour, there must
410 be a module or package name that is accessible via both sys.path
411 and one of the non PEP 302 file system mechanisms. In this case,
412 the emulation will find the former version, while the builtin
413 import mechanism will find the latter.
414
415 Items of the following types can be affected by this discrepancy:
416 imp.C_EXTENSION, imp.PY_SOURCE, imp.PY_COMPILED, imp.PKG_DIRECTORY
417 """
418 if fullname.startswith('.'):
419 raise ImportError("Relative module names not supported")
420 if '.' in fullname:
421 # Get the containing package's __path__
422 pkg = '.'.join(fullname.split('.')[:-1])
423 if pkg not in sys.modules:
424 __import__(pkg)
Neal Norwitz0bbbb002006-04-28 04:32:20 +0000425 path = getattr(sys.modules[pkg], '__path__', None) or []
Phillip J. Ebyab1d2452006-04-17 20:17:25 +0000426 else:
427 for importer in sys.meta_path:
428 yield importer
429 path = sys.path
430 for item in path:
431 yield get_importer(item)
432 if '.' not in fullname:
433 yield ImpImporter()
434
Phillip J. Ebyab1d2452006-04-17 20:17:25 +0000435def get_loader(module_or_name):
436 """Get a PEP 302 "loader" object for module_or_name
437
438 If the module or package is accessible via the normal import
439 mechanism, a wrapper around the relevant part of that machinery
440 is returned. Returns None if the module cannot be found or imported.
441 If the named module is not already imported, its containing package
442 (if any) is imported, in order to establish the package __path__.
443
444 This function uses iter_importers(), and is thus subject to the same
445 limitations regarding platform-specific special import locations such
446 as the Windows registry.
447 """
448 if module_or_name in sys.modules:
449 module_or_name = sys.modules[module_or_name]
450 if isinstance(module_or_name, ModuleType):
451 module = module_or_name
Neal Norwitz0bbbb002006-04-28 04:32:20 +0000452 loader = getattr(module, '__loader__', None)
Phillip J. Ebyab1d2452006-04-17 20:17:25 +0000453 if loader is not None:
454 return loader
455 fullname = module.__name__
456 else:
457 fullname = module_or_name
458 return find_loader(fullname)
459
Phillip J. Ebyab1d2452006-04-17 20:17:25 +0000460def find_loader(fullname):
461 """Find a PEP 302 "loader" object for fullname
462
463 If fullname contains dots, path must be the containing package's __path__.
464 Returns None if the module cannot be found or imported. This function uses
465 iter_importers(), and is thus subject to the same limitations regarding
466 platform-specific special import locations such as the Windows registry.
467 """
468 for importer in iter_importers(fullname):
469 loader = importer.find_module(fullname)
470 if loader is not None:
471 return loader
472
473 return None
474
Guido van Rossuma4deda02002-12-23 16:30:00 +0000475
476def extend_path(path, name):
477 """Extend a package's path.
478
479 Intended use is to place the following code in a package's __init__.py:
480
481 from pkgutil import extend_path
482 __path__ = extend_path(__path__, __name__)
483
484 This will add to the package's __path__ all subdirectories of
485 directories on sys.path named after the package. This is useful
486 if one wants to distribute different parts of a single logical
487 package as multiple directories.
488
489 It also looks for *.pkg files beginning where * matches the name
490 argument. This feature is similar to *.pth files (see site.py),
491 except that it doesn't special-case lines starting with 'import'.
492 A *.pkg file is trusted at face value: apart from checking for
493 duplicates, all entries found in a *.pkg file are added to the
494 path, regardless of whether they are exist the filesystem. (This
495 is a feature.)
496
497 If the input path is not a list (as is the case for frozen
498 packages) it is returned unchanged. The input path is not
499 modified; an extended copy is returned. Items are only appended
500 to the copy at the end.
501
502 It is assumed that sys.path is a sequence. Items of sys.path that
503 are not (unicode or 8-bit) strings referring to existing
504 directories are ignored. Unicode items of sys.path that cause
505 errors when used as filenames may cause this function to raise an
506 exception (in line with os.path.isdir() behavior).
507 """
508
509 if not isinstance(path, list):
510 # This could happen e.g. when this is called from inside a
511 # frozen package. Return the path unchanged in that case.
512 return path
513
514 pname = os.path.join(*name.split('.')) # Reconstitute as relative path
515 # Just in case os.extsep != '.'
516 sname = os.extsep.join(name.split('.'))
517 sname_pkg = sname + os.extsep + "pkg"
518 init_py = "__init__" + os.extsep + "py"
519
520 path = path[:] # Start with a copy of the existing path
521
522 for dir in sys.path:
Raymond Hettinger7a70ea42003-09-17 05:50:59 +0000523 if not isinstance(dir, basestring) or not os.path.isdir(dir):
Guido van Rossuma4deda02002-12-23 16:30:00 +0000524 continue
525 subdir = os.path.join(dir, pname)
526 # XXX This may still add duplicate entries to path on
527 # case-insensitive filesystems
528 initfile = os.path.join(subdir, init_py)
529 if subdir not in path and os.path.isfile(initfile):
530 path.append(subdir)
531 # XXX Is this the right thing for subpackages like zope.app?
532 # It looks for a file named "zope.app.pkg"
533 pkgfile = os.path.join(dir, sname_pkg)
534 if os.path.isfile(pkgfile):
535 try:
536 f = open(pkgfile)
537 except IOError, msg:
538 sys.stderr.write("Can't open %s: %s\n" %
539 (pkgfile, msg))
540 else:
541 for line in f:
542 line = line.rstrip('\n')
543 if not line or line.startswith('#'):
544 continue
545 path.append(line) # Don't check for existence!
546 f.close()
547
548 return path