blob: 487c8cd8a983b61f45e9dab747951b00eb6d5007 [file] [log] [blame]
Guido van Rossuma4deda02002-12-23 16:30:00 +00001"""Utilities to support packages."""
2
3import os
4import sys
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005import imp
Nick Coghlan85e729e2012-07-15 18:09:52 +10006import importlib
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00007import os.path
Nick Coghlan85e729e2012-07-15 18:09:52 +10008from warnings import warn
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00009from types import ModuleType
10
11__all__ = [
12 'get_importer', 'iter_importers', 'get_loader', 'find_loader',
Éric Araujoa4e2d4f2011-05-02 22:59:15 +020013 'walk_packages', 'iter_modules', 'get_data',
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000014 'ImpImporter', 'ImpLoader', 'read_code', 'extend_path',
15]
16
17def read_code(stream):
18 # This helper is needed in order for the PEP 302 emulation to
19 # correctly handle compiled files
20 import marshal
21
22 magic = stream.read(4)
23 if magic != imp.get_magic():
24 return None
25
Antoine Pitrou5136ac02012-01-13 18:52:16 +010026 stream.read(8) # Skip timestamp and size
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000027 return marshal.load(stream)
28
29
30def simplegeneric(func):
31 """Make a trivial single-dispatch generic function"""
32 registry = {}
Thomas Wouters477c8d52006-05-27 19:21:47 +000033 def wrapper(*args, **kw):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000034 ob = args[0]
35 try:
36 cls = ob.__class__
37 except AttributeError:
38 cls = type(ob)
39 try:
40 mro = cls.__mro__
41 except AttributeError:
42 try:
Thomas Wouters477c8d52006-05-27 19:21:47 +000043 class cls(cls, object):
44 pass
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000045 mro = cls.__mro__[1:]
46 except TypeError:
47 mro = object, # must be an ExtensionClass or some such :(
48 for t in mro:
49 if t in registry:
Thomas Wouters477c8d52006-05-27 19:21:47 +000050 return registry[t](*args, **kw)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000051 else:
Thomas Wouters477c8d52006-05-27 19:21:47 +000052 return func(*args, **kw)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000053 try:
54 wrapper.__name__ = func.__name__
Thomas Wouters477c8d52006-05-27 19:21:47 +000055 except (TypeError, AttributeError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000056 pass # Python 2.3 doesn't allow functions to be renamed
57
58 def register(typ, func=None):
59 if func is None:
60 return lambda f: register(typ, f)
61 registry[typ] = func
62 return func
63
64 wrapper.__dict__ = func.__dict__
65 wrapper.__doc__ = func.__doc__
66 wrapper.register = register
67 return wrapper
68
69
70def walk_packages(path=None, prefix='', onerror=None):
Thomas Wouters0e3f5912006-08-11 14:57:12 +000071 """Yields (module_loader, name, ispkg) for all modules recursively
72 on path, or, if path is None, all accessible modules.
73
74 'path' should be either None or a list of paths to look for
75 modules in.
76
77 'prefix' is a string to output on the front of every module name
78 on output.
79
80 Note that this function must import all *packages* (NOT all
81 modules!) on the given path, in order to access the __path__
82 attribute to find submodules.
83
84 'onerror' is a function which gets called with one argument (the
85 name of the package which was being imported) if any exception
86 occurs while trying to import a package. If no onerror function is
87 supplied, ImportErrors are caught and ignored, while all other
88 exceptions are propagated, terminating the search.
89
90 Examples:
91
92 # list all modules python can access
93 walk_packages()
94
95 # list all submodules of ctypes
96 walk_packages(ctypes.__path__, ctypes.__name__+'.')
97 """
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000098
Thomas Wouters477c8d52006-05-27 19:21:47 +000099 def seen(p, m={}):
100 if p in m:
101 return True
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000102 m[p] = True
103
104 for importer, name, ispkg in iter_modules(path, prefix):
105 yield importer, name, ispkg
106
107 if ispkg:
108 try:
109 __import__(name)
110 except ImportError:
111 if onerror is not None:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000112 onerror(name)
113 except Exception:
114 if onerror is not None:
115 onerror(name)
116 else:
117 raise
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000118 else:
119 path = getattr(sys.modules[name], '__path__', None) or []
120
121 # don't traverse path items we've seen before
122 path = [p for p in path if not seen(p)]
123
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000124 for item in walk_packages(path, name+'.', onerror):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000125 yield item
126
127
128def iter_modules(path=None, prefix=''):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000129 """Yields (module_loader, name, ispkg) for all submodules on path,
130 or, if path is None, all top-level modules on sys.path.
131
132 'path' should be either None or a list of paths to look for
133 modules in.
134
135 'prefix' is a string to output on the front of every module name
136 on output.
137 """
138
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000139 if path is None:
140 importers = iter_importers()
141 else:
142 importers = map(get_importer, path)
143
144 yielded = {}
145 for i in importers:
146 for name, ispkg in iter_importer_modules(i, prefix):
147 if name not in yielded:
148 yielded[name] = 1
149 yield i, name, ispkg
150
151
152#@simplegeneric
153def iter_importer_modules(importer, prefix=''):
Thomas Wouters477c8d52006-05-27 19:21:47 +0000154 if not hasattr(importer, 'iter_modules'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000155 return []
156 return importer.iter_modules(prefix)
157
158iter_importer_modules = simplegeneric(iter_importer_modules)
159
160
161class ImpImporter:
162 """PEP 302 Importer that wraps Python's "classic" import algorithm
163
164 ImpImporter(dirname) produces a PEP 302 importer that searches that
165 directory. ImpImporter(None) produces a PEP 302 importer that searches
166 the current sys.path, plus any modules that are frozen or built-in.
167
168 Note that ImpImporter does not currently support being used by placement
169 on sys.meta_path.
170 """
171
172 def __init__(self, path=None):
Nick Coghlan85e729e2012-07-15 18:09:52 +1000173 warn("This emulation is deprecated, use 'importlib' instead",
174 DeprecationWarning)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000175 self.path = path
176
177 def find_module(self, fullname, path=None):
178 # Note: we ignore 'path' argument since it is only used via meta_path
179 subname = fullname.split(".")[-1]
180 if subname != fullname and self.path is None:
181 return None
182 if self.path is None:
183 path = None
184 else:
185 path = [os.path.realpath(self.path)]
186 try:
187 file, filename, etc = imp.find_module(subname, path)
188 except ImportError:
189 return None
190 return ImpLoader(fullname, file, filename, etc)
191
192 def iter_modules(self, prefix=''):
193 if self.path is None or not os.path.isdir(self.path):
194 return
195
196 yielded = {}
197 import inspect
Ned Deilyed27df72011-10-06 14:19:08 -0700198 try:
199 filenames = os.listdir(self.path)
200 except OSError:
201 # ignore unreadable directories like import does
202 filenames = []
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000203 filenames.sort() # handle packages before same-named modules
204
205 for fn in filenames:
206 modname = inspect.getmodulename(fn)
207 if modname=='__init__' or modname in yielded:
208 continue
209
210 path = os.path.join(self.path, fn)
211 ispkg = False
212
213 if not modname and os.path.isdir(path) and '.' not in fn:
214 modname = fn
Ned Deilyed27df72011-10-06 14:19:08 -0700215 try:
216 dircontents = os.listdir(path)
217 except OSError:
218 # ignore unreadable directories like import does
219 dircontents = []
220 for fn in dircontents:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000221 subname = inspect.getmodulename(fn)
222 if subname=='__init__':
223 ispkg = True
224 break
225 else:
226 continue # not a package
227
228 if modname and '.' not in modname:
229 yielded[modname] = 1
230 yield prefix + modname, ispkg
231
232
233class ImpLoader:
234 """PEP 302 Loader that wraps Python's "classic" import algorithm
235 """
236 code = source = None
237
238 def __init__(self, fullname, file, filename, etc):
Nick Coghlan85e729e2012-07-15 18:09:52 +1000239 warn("This emulation is deprecated, use 'importlib' instead",
240 DeprecationWarning)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000241 self.file = file
242 self.filename = filename
243 self.fullname = fullname
244 self.etc = etc
245
246 def load_module(self, fullname):
247 self._reopen()
248 try:
249 mod = imp.load_module(fullname, self.file, self.filename, self.etc)
250 finally:
251 if self.file:
252 self.file.close()
253 # Note: we don't set __loader__ because we want the module to look
254 # normal; i.e. this is just a wrapper for standard import machinery
255 return mod
256
257 def get_data(self, pathname):
Brett Cannon1ab58df2010-10-29 22:36:53 +0000258 with open(pathname, "rb") as file:
259 return file.read()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000260
261 def _reopen(self):
262 if self.file and self.file.closed:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000263 mod_type = self.etc[2]
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000264 if mod_type==imp.PY_SOURCE:
Victor Stinner4e86d5b2011-05-04 13:55:36 +0200265 self.file = open(self.filename, 'r')
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000266 elif mod_type in (imp.PY_COMPILED, imp.C_EXTENSION):
267 self.file = open(self.filename, 'rb')
268
269 def _fix_name(self, fullname):
270 if fullname is None:
271 fullname = self.fullname
272 elif fullname != self.fullname:
273 raise ImportError("Loader for module %s cannot handle "
274 "module %s" % (self.fullname, fullname))
275 return fullname
276
277 def is_package(self, fullname):
278 fullname = self._fix_name(fullname)
279 return self.etc[2]==imp.PKG_DIRECTORY
280
281 def get_code(self, fullname=None):
282 fullname = self._fix_name(fullname)
283 if self.code is None:
284 mod_type = self.etc[2]
285 if mod_type==imp.PY_SOURCE:
286 source = self.get_source(fullname)
287 self.code = compile(source, self.filename, 'exec')
288 elif mod_type==imp.PY_COMPILED:
289 self._reopen()
290 try:
291 self.code = read_code(self.file)
292 finally:
293 self.file.close()
294 elif mod_type==imp.PKG_DIRECTORY:
295 self.code = self._get_delegate().get_code()
296 return self.code
297
298 def get_source(self, fullname=None):
299 fullname = self._fix_name(fullname)
300 if self.source is None:
301 mod_type = self.etc[2]
302 if mod_type==imp.PY_SOURCE:
303 self._reopen()
304 try:
305 self.source = self.file.read()
306 finally:
307 self.file.close()
308 elif mod_type==imp.PY_COMPILED:
309 if os.path.exists(self.filename[:-1]):
Victor Stinner4e86d5b2011-05-04 13:55:36 +0200310 f = open(self.filename[:-1], 'r')
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000311 self.source = f.read()
312 f.close()
313 elif mod_type==imp.PKG_DIRECTORY:
314 self.source = self._get_delegate().get_source()
315 return self.source
316
317
318 def _get_delegate(self):
319 return ImpImporter(self.filename).find_module('__init__')
320
321 def get_filename(self, fullname=None):
322 fullname = self._fix_name(fullname)
323 mod_type = self.etc[2]
Éric Araujo0cfb81d2011-09-17 03:35:57 +0200324 if mod_type==imp.PKG_DIRECTORY:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000325 return self._get_delegate().get_filename()
Éric Araujo0cfb81d2011-09-17 03:35:57 +0200326 elif mod_type in (imp.PY_SOURCE, imp.PY_COMPILED, imp.C_EXTENSION):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000327 return self.filename
328 return None
329
330
331try:
332 import zipimport
333 from zipimport import zipimporter
334
335 def iter_zipimport_modules(importer, prefix=''):
Alexandre Vassalotti515a74f2009-07-05 06:42:44 +0000336 dirlist = sorted(zipimport._zip_directory_cache[importer.archive])
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000337 _prefix = importer.prefix
338 plen = len(_prefix)
339 yielded = {}
340 import inspect
341 for fn in dirlist:
342 if not fn.startswith(_prefix):
343 continue
344
345 fn = fn[plen:].split(os.sep)
346
347 if len(fn)==2 and fn[1].startswith('__init__.py'):
348 if fn[0] not in yielded:
349 yielded[fn[0]] = 1
350 yield fn[0], True
351
352 if len(fn)!=1:
353 continue
354
355 modname = inspect.getmodulename(fn[0])
356 if modname=='__init__':
357 continue
358
359 if modname and '.' not in modname and modname not in yielded:
360 yielded[modname] = 1
361 yield prefix + modname, False
362
363 iter_importer_modules.register(zipimporter, iter_zipimport_modules)
364
365except ImportError:
366 pass
367
368
369def get_importer(path_item):
370 """Retrieve a PEP 302 importer for the given path item
371
372 The returned importer is cached in sys.path_importer_cache
373 if it was newly created by a path hook.
374
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000375 The cache (or part of it) can be cleared manually if a
376 rescan of sys.path_hooks is necessary.
377 """
378 try:
379 importer = sys.path_importer_cache[path_item]
380 except KeyError:
381 for path_hook in sys.path_hooks:
382 try:
383 importer = path_hook(path_item)
Brett Cannone0d88a12012-04-25 20:54:04 -0400384 sys.path_importer_cache.setdefault(path_item, importer)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000385 break
386 except ImportError:
387 pass
388 else:
Nick Coghlan85e729e2012-07-15 18:09:52 +1000389 importer = None
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000390 return importer
391
392
393def iter_importers(fullname=""):
394 """Yield PEP 302 importers for the given module name
395
396 If fullname contains a '.', the importers will be for the package
Nick Coghlan85e729e2012-07-15 18:09:52 +1000397 containing fullname, otherwise they will be all registered top level
398 importers (i.e. those on both sys.meta_path and sys.path_hooks).
399
400 If the named module is in a package, that package is imported as a side
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000401 effect of invoking this function.
402
Nick Coghlan85e729e2012-07-15 18:09:52 +1000403 If no module name is specified, all top level importers are produced.
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000404 """
405 if fullname.startswith('.'):
Nick Coghlan85e729e2012-07-15 18:09:52 +1000406 msg = "Relative module name {!r} not supported".format(fullname)
407 raise ImportError(msg)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000408 if '.' in fullname:
409 # Get the containing package's __path__
Nick Coghlan85e729e2012-07-15 18:09:52 +1000410 pkg_name = fullname.rpartition(".")[0]
411 pkg = importlib.import_module(pkg)
412 path = getattr(sys.modules[pkg], '__path__', None)
413 if path is None:
414 return
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000415 else:
416 for importer in sys.meta_path:
417 yield importer
418 path = sys.path
419 for item in path:
420 yield get_importer(item)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000421
422def get_loader(module_or_name):
423 """Get a PEP 302 "loader" object for module_or_name
424
Nick Coghlan85e729e2012-07-15 18:09:52 +1000425 Returns None if the module cannot be found or imported.
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000426 If the named module is not already imported, its containing package
427 (if any) is imported, in order to establish the package __path__.
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000428 """
429 if module_or_name in sys.modules:
430 module_or_name = sys.modules[module_or_name]
431 if isinstance(module_or_name, ModuleType):
432 module = module_or_name
Thomas Wouters477c8d52006-05-27 19:21:47 +0000433 loader = getattr(module, '__loader__', None)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000434 if loader is not None:
435 return loader
436 fullname = module.__name__
437 else:
438 fullname = module_or_name
439 return find_loader(fullname)
440
Nick Coghlan85e729e2012-07-15 18:09:52 +1000441
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000442def find_loader(fullname):
443 """Find a PEP 302 "loader" object for fullname
444
Nick Coghlan85e729e2012-07-15 18:09:52 +1000445 This is s convenience wrapper around :func:`importlib.find_loader` that
446 sets the *path* argument correctly when searching for submodules, and
447 also ensures parent packages (if any) are imported before searching for
448 submodules.
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000449 """
Nick Coghlan85e729e2012-07-15 18:09:52 +1000450 if fullname.startswith('.'):
451 msg = "Relative module name {!r} not supported".format(fullname)
452 raise ImportError(msg)
453 path = None
454 pkg_name = fullname.rpartition(".")[0]
455 if pkg_name:
456 pkg = importlib.import_module(pkg_name)
457 path = getattr(pkg, "__path__", None)
458 if path is None:
459 return None
460 try:
461 return importlib.find_loader(fullname, path)
462 except (ImportError, AttributeError, TypeError, ValueError) as ex:
463 # This hack fixes an impedance mismatch between pkgutil and
464 # importlib, where the latter throws other errors for cases where
465 # pkgutil previously threw ImportError
466 msg = "Error while finding loader for {!r} ({}: {})"
467 raise ImportError(msg.format(fullname, type(ex), ex)) from ex
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000468
Guido van Rossuma4deda02002-12-23 16:30:00 +0000469
470def extend_path(path, name):
471 """Extend a package's path.
472
473 Intended use is to place the following code in a package's __init__.py:
474
475 from pkgutil import extend_path
476 __path__ = extend_path(__path__, __name__)
477
478 This will add to the package's __path__ all subdirectories of
479 directories on sys.path named after the package. This is useful
480 if one wants to distribute different parts of a single logical
481 package as multiple directories.
482
483 It also looks for *.pkg files beginning where * matches the name
484 argument. This feature is similar to *.pth files (see site.py),
485 except that it doesn't special-case lines starting with 'import'.
486 A *.pkg file is trusted at face value: apart from checking for
487 duplicates, all entries found in a *.pkg file are added to the
488 path, regardless of whether they are exist the filesystem. (This
489 is a feature.)
490
491 If the input path is not a list (as is the case for frozen
492 packages) it is returned unchanged. The input path is not
493 modified; an extended copy is returned. Items are only appended
494 to the copy at the end.
495
496 It is assumed that sys.path is a sequence. Items of sys.path that
497 are not (unicode or 8-bit) strings referring to existing
498 directories are ignored. Unicode items of sys.path that cause
499 errors when used as filenames may cause this function to raise an
500 exception (in line with os.path.isdir() behavior).
501 """
502
503 if not isinstance(path, list):
504 # This could happen e.g. when this is called from inside a
505 # frozen package. Return the path unchanged in that case.
506 return path
507
Skip Montanaro7a98be22007-08-16 14:35:24 +0000508 sname_pkg = name + ".pkg"
Guido van Rossuma4deda02002-12-23 16:30:00 +0000509
510 path = path[:] # Start with a copy of the existing path
511
Antoine Pitroub2dd8802012-07-09 21:23:58 +0200512 parent_package, _, final_name = name.rpartition('.')
513 if parent_package:
514 try:
515 search_path = sys.modules[parent_package].__path__
516 except (KeyError, AttributeError):
517 # We can't do anything: find_loader() returns None when
518 # passed a dotted name.
519 return path
520 else:
521 search_path = sys.path
522
523 for dir in search_path:
Eric V. Smith984b11f2012-05-24 20:21:04 -0400524 if not isinstance(dir, str):
Guido van Rossuma4deda02002-12-23 16:30:00 +0000525 continue
Eric V. Smith984b11f2012-05-24 20:21:04 -0400526
527 finder = get_importer(dir)
528 if finder is not None:
529 # Is this finder PEP 420 compliant?
530 if hasattr(finder, 'find_loader'):
Antoine Pitroub2dd8802012-07-09 21:23:58 +0200531 loader, portions = finder.find_loader(final_name)
Eric V. Smith984b11f2012-05-24 20:21:04 -0400532 else:
533 # No, no need to call it
534 loader = None
535 portions = []
536
537 for portion in portions:
538 # XXX This may still add duplicate entries to path on
539 # case-insensitive filesystems
540 if portion not in path:
541 path.append(portion)
542
Guido van Rossuma4deda02002-12-23 16:30:00 +0000543 # XXX Is this the right thing for subpackages like zope.app?
544 # It looks for a file named "zope.app.pkg"
545 pkgfile = os.path.join(dir, sname_pkg)
546 if os.path.isfile(pkgfile):
547 try:
548 f = open(pkgfile)
Guido van Rossumb940e112007-01-10 16:19:56 +0000549 except IOError as msg:
Guido van Rossuma4deda02002-12-23 16:30:00 +0000550 sys.stderr.write("Can't open %s: %s\n" %
551 (pkgfile, msg))
552 else:
553 for line in f:
554 line = line.rstrip('\n')
555 if not line or line.startswith('#'):
556 continue
557 path.append(line) # Don't check for existence!
558 f.close()
559
560 return path
Christian Heimesdae2a892008-04-19 00:55:37 +0000561
562def get_data(package, resource):
563 """Get a resource from a package.
564
565 This is a wrapper round the PEP 302 loader get_data API. The package
566 argument should be the name of a package, in standard module format
567 (foo.bar). The resource argument should be in the form of a relative
568 filename, using '/' as the path separator. The parent directory name '..'
569 is not allowed, and nor is a rooted name (starting with a '/').
570
571 The function returns a binary string, which is the contents of the
572 specified resource.
573
574 For packages located in the filesystem, which have already been imported,
575 this is the rough equivalent of
576
577 d = os.path.dirname(sys.modules[package].__file__)
578 data = open(os.path.join(d, resource), 'rb').read()
579
580 If the package cannot be located or loaded, or it uses a PEP 302 loader
581 which does not support get_data(), then None is returned.
582 """
583
584 loader = get_loader(package)
585 if loader is None or not hasattr(loader, 'get_data'):
586 return None
587 mod = sys.modules.get(package) or loader.load_module(package)
588 if mod is None or not hasattr(mod, '__file__'):
589 return None
590
591 # Modify the resource name to be compatible with the loader.get_data
592 # signature - an os.path format "filename" starting with the dirname of
593 # the package's __file__
594 parts = resource.split('/')
595 parts.insert(0, os.path.dirname(mod.__file__))
596 resource_name = os.path.join(*parts)
597 return loader.get_data(resource_name)