blob: 8fa840595d304f1776a058cebbb2c85015c8a391 [file] [log] [blame]
Guido van Rossuma4deda02002-12-23 16:30:00 +00001"""Utilities to support packages."""
2
3import os
4import sys
Nick Coghlan85e729e2012-07-15 18:09:52 +10005import importlib
Nick Coghlanbe7e49f2012-07-20 23:40:09 +10006import imp
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
Philip Jenvey4993cc02012-10-01 12:53:43 -0700124 yield from walk_packages(path, name+'.', onerror)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000125
126
127def iter_modules(path=None, prefix=''):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000128 """Yields (module_loader, name, ispkg) for all submodules on path,
129 or, if path is None, all top-level modules on sys.path.
130
131 'path' should be either None or a list of paths to look for
132 modules in.
133
134 'prefix' is a string to output on the front of every module name
135 on output.
136 """
137
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000138 if path is None:
139 importers = iter_importers()
140 else:
141 importers = map(get_importer, path)
142
143 yielded = {}
144 for i in importers:
145 for name, ispkg in iter_importer_modules(i, prefix):
146 if name not in yielded:
147 yielded[name] = 1
148 yield i, name, ispkg
149
150
151#@simplegeneric
152def iter_importer_modules(importer, prefix=''):
Thomas Wouters477c8d52006-05-27 19:21:47 +0000153 if not hasattr(importer, 'iter_modules'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000154 return []
155 return importer.iter_modules(prefix)
156
157iter_importer_modules = simplegeneric(iter_importer_modules)
158
Nick Coghlan8ecf5042012-07-15 21:19:18 +1000159# Implement a file walker for the normal importlib path hook
160def _iter_file_finder_modules(importer, prefix=''):
161 if importer.path is None or not os.path.isdir(importer.path):
162 return
163
164 yielded = {}
165 import inspect
166 try:
167 filenames = os.listdir(importer.path)
168 except OSError:
169 # ignore unreadable directories like import does
170 filenames = []
171 filenames.sort() # handle packages before same-named modules
172
173 for fn in filenames:
174 modname = inspect.getmodulename(fn)
175 if modname=='__init__' or modname in yielded:
176 continue
177
178 path = os.path.join(importer.path, fn)
179 ispkg = False
180
181 if not modname and os.path.isdir(path) and '.' not in fn:
182 modname = fn
183 try:
184 dircontents = os.listdir(path)
185 except OSError:
186 # ignore unreadable directories like import does
187 dircontents = []
188 for fn in dircontents:
189 subname = inspect.getmodulename(fn)
190 if subname=='__init__':
191 ispkg = True
192 break
193 else:
194 continue # not a package
195
196 if modname and '.' not in modname:
197 yielded[modname] = 1
198 yield prefix + modname, ispkg
199
200iter_importer_modules.register(
201 importlib.machinery.FileFinder, _iter_file_finder_modules)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000202
203class ImpImporter:
204 """PEP 302 Importer that wraps Python's "classic" import algorithm
205
206 ImpImporter(dirname) produces a PEP 302 importer that searches that
207 directory. ImpImporter(None) produces a PEP 302 importer that searches
208 the current sys.path, plus any modules that are frozen or built-in.
209
210 Note that ImpImporter does not currently support being used by placement
211 on sys.meta_path.
212 """
213
214 def __init__(self, path=None):
Nick Coghlan85e729e2012-07-15 18:09:52 +1000215 warn("This emulation is deprecated, use 'importlib' instead",
216 DeprecationWarning)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000217 self.path = path
218
219 def find_module(self, fullname, path=None):
220 # Note: we ignore 'path' argument since it is only used via meta_path
221 subname = fullname.split(".")[-1]
222 if subname != fullname and self.path is None:
223 return None
224 if self.path is None:
225 path = None
226 else:
227 path = [os.path.realpath(self.path)]
228 try:
229 file, filename, etc = imp.find_module(subname, path)
230 except ImportError:
231 return None
232 return ImpLoader(fullname, file, filename, etc)
233
234 def iter_modules(self, prefix=''):
235 if self.path is None or not os.path.isdir(self.path):
236 return
237
238 yielded = {}
239 import inspect
Ned Deilyed27df72011-10-06 14:19:08 -0700240 try:
241 filenames = os.listdir(self.path)
242 except OSError:
243 # ignore unreadable directories like import does
244 filenames = []
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000245 filenames.sort() # handle packages before same-named modules
246
247 for fn in filenames:
248 modname = inspect.getmodulename(fn)
249 if modname=='__init__' or modname in yielded:
250 continue
251
252 path = os.path.join(self.path, fn)
253 ispkg = False
254
255 if not modname and os.path.isdir(path) and '.' not in fn:
256 modname = fn
Ned Deilyed27df72011-10-06 14:19:08 -0700257 try:
258 dircontents = os.listdir(path)
259 except OSError:
260 # ignore unreadable directories like import does
261 dircontents = []
262 for fn in dircontents:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000263 subname = inspect.getmodulename(fn)
264 if subname=='__init__':
265 ispkg = True
266 break
267 else:
268 continue # not a package
269
270 if modname and '.' not in modname:
271 yielded[modname] = 1
272 yield prefix + modname, ispkg
273
274
275class ImpLoader:
276 """PEP 302 Loader that wraps Python's "classic" import algorithm
277 """
278 code = source = None
279
280 def __init__(self, fullname, file, filename, etc):
Nick Coghlan85e729e2012-07-15 18:09:52 +1000281 warn("This emulation is deprecated, use 'importlib' instead",
282 DeprecationWarning)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000283 self.file = file
284 self.filename = filename
285 self.fullname = fullname
286 self.etc = etc
287
288 def load_module(self, fullname):
289 self._reopen()
290 try:
291 mod = imp.load_module(fullname, self.file, self.filename, self.etc)
292 finally:
293 if self.file:
294 self.file.close()
295 # Note: we don't set __loader__ because we want the module to look
296 # normal; i.e. this is just a wrapper for standard import machinery
297 return mod
298
299 def get_data(self, pathname):
Brett Cannon1ab58df2010-10-29 22:36:53 +0000300 with open(pathname, "rb") as file:
301 return file.read()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000302
303 def _reopen(self):
304 if self.file and self.file.closed:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000305 mod_type = self.etc[2]
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000306 if mod_type==imp.PY_SOURCE:
Victor Stinner4e86d5b2011-05-04 13:55:36 +0200307 self.file = open(self.filename, 'r')
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000308 elif mod_type in (imp.PY_COMPILED, imp.C_EXTENSION):
309 self.file = open(self.filename, 'rb')
310
311 def _fix_name(self, fullname):
312 if fullname is None:
313 fullname = self.fullname
314 elif fullname != self.fullname:
315 raise ImportError("Loader for module %s cannot handle "
316 "module %s" % (self.fullname, fullname))
317 return fullname
318
319 def is_package(self, fullname):
320 fullname = self._fix_name(fullname)
321 return self.etc[2]==imp.PKG_DIRECTORY
322
323 def get_code(self, fullname=None):
324 fullname = self._fix_name(fullname)
325 if self.code is None:
326 mod_type = self.etc[2]
327 if mod_type==imp.PY_SOURCE:
328 source = self.get_source(fullname)
329 self.code = compile(source, self.filename, 'exec')
330 elif mod_type==imp.PY_COMPILED:
331 self._reopen()
332 try:
333 self.code = read_code(self.file)
334 finally:
335 self.file.close()
336 elif mod_type==imp.PKG_DIRECTORY:
337 self.code = self._get_delegate().get_code()
338 return self.code
339
340 def get_source(self, fullname=None):
341 fullname = self._fix_name(fullname)
342 if self.source is None:
343 mod_type = self.etc[2]
344 if mod_type==imp.PY_SOURCE:
345 self._reopen()
346 try:
347 self.source = self.file.read()
348 finally:
349 self.file.close()
350 elif mod_type==imp.PY_COMPILED:
351 if os.path.exists(self.filename[:-1]):
Giampaolo Rodola'2f50aaf2013-02-12 02:04:27 +0100352 with open(self.filename[:-1], 'r') as f:
353 self.source = f.read()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000354 elif mod_type==imp.PKG_DIRECTORY:
355 self.source = self._get_delegate().get_source()
356 return self.source
357
358
359 def _get_delegate(self):
360 return ImpImporter(self.filename).find_module('__init__')
361
362 def get_filename(self, fullname=None):
363 fullname = self._fix_name(fullname)
364 mod_type = self.etc[2]
Éric Araujo0cfb81d2011-09-17 03:35:57 +0200365 if mod_type==imp.PKG_DIRECTORY:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000366 return self._get_delegate().get_filename()
Éric Araujo0cfb81d2011-09-17 03:35:57 +0200367 elif mod_type in (imp.PY_SOURCE, imp.PY_COMPILED, imp.C_EXTENSION):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000368 return self.filename
369 return None
370
371
372try:
373 import zipimport
374 from zipimport import zipimporter
375
376 def iter_zipimport_modules(importer, prefix=''):
Alexandre Vassalotti515a74f2009-07-05 06:42:44 +0000377 dirlist = sorted(zipimport._zip_directory_cache[importer.archive])
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000378 _prefix = importer.prefix
379 plen = len(_prefix)
380 yielded = {}
381 import inspect
382 for fn in dirlist:
383 if not fn.startswith(_prefix):
384 continue
385
386 fn = fn[plen:].split(os.sep)
387
388 if len(fn)==2 and fn[1].startswith('__init__.py'):
389 if fn[0] not in yielded:
390 yielded[fn[0]] = 1
391 yield fn[0], True
392
393 if len(fn)!=1:
394 continue
395
396 modname = inspect.getmodulename(fn[0])
397 if modname=='__init__':
398 continue
399
400 if modname and '.' not in modname and modname not in yielded:
401 yielded[modname] = 1
402 yield prefix + modname, False
403
404 iter_importer_modules.register(zipimporter, iter_zipimport_modules)
405
406except ImportError:
407 pass
408
409
410def get_importer(path_item):
411 """Retrieve a PEP 302 importer for the given path item
412
413 The returned importer is cached in sys.path_importer_cache
414 if it was newly created by a path hook.
415
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000416 The cache (or part of it) can be cleared manually if a
417 rescan of sys.path_hooks is necessary.
418 """
419 try:
420 importer = sys.path_importer_cache[path_item]
421 except KeyError:
422 for path_hook in sys.path_hooks:
423 try:
424 importer = path_hook(path_item)
Brett Cannone0d88a12012-04-25 20:54:04 -0400425 sys.path_importer_cache.setdefault(path_item, importer)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000426 break
427 except ImportError:
428 pass
429 else:
Nick Coghlan85e729e2012-07-15 18:09:52 +1000430 importer = None
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000431 return importer
432
433
434def iter_importers(fullname=""):
435 """Yield PEP 302 importers for the given module name
436
437 If fullname contains a '.', the importers will be for the package
Nick Coghlan85e729e2012-07-15 18:09:52 +1000438 containing fullname, otherwise they will be all registered top level
439 importers (i.e. those on both sys.meta_path and sys.path_hooks).
440
441 If the named module is in a package, that package is imported as a side
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000442 effect of invoking this function.
443
Nick Coghlan85e729e2012-07-15 18:09:52 +1000444 If no module name is specified, all top level importers are produced.
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000445 """
446 if fullname.startswith('.'):
Nick Coghlan85e729e2012-07-15 18:09:52 +1000447 msg = "Relative module name {!r} not supported".format(fullname)
448 raise ImportError(msg)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000449 if '.' in fullname:
450 # Get the containing package's __path__
Nick Coghlan85e729e2012-07-15 18:09:52 +1000451 pkg_name = fullname.rpartition(".")[0]
452 pkg = importlib.import_module(pkg)
453 path = getattr(sys.modules[pkg], '__path__', None)
454 if path is None:
455 return
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000456 else:
Andrew Svetlov2aa5f3c2012-10-07 23:21:15 +0300457 yield from sys.meta_path
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000458 path = sys.path
459 for item in path:
460 yield get_importer(item)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000461
462def get_loader(module_or_name):
463 """Get a PEP 302 "loader" object for module_or_name
464
Nick Coghlan85e729e2012-07-15 18:09:52 +1000465 Returns None if the module cannot be found or imported.
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000466 If the named module is not already imported, its containing package
467 (if any) is imported, in order to establish the package __path__.
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000468 """
469 if module_or_name in sys.modules:
470 module_or_name = sys.modules[module_or_name]
471 if isinstance(module_or_name, ModuleType):
472 module = module_or_name
Thomas Wouters477c8d52006-05-27 19:21:47 +0000473 loader = getattr(module, '__loader__', None)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000474 if loader is not None:
475 return loader
476 fullname = module.__name__
477 else:
478 fullname = module_or_name
479 return find_loader(fullname)
480
Nick Coghlan85e729e2012-07-15 18:09:52 +1000481
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000482def find_loader(fullname):
483 """Find a PEP 302 "loader" object for fullname
484
Nick Coghlan85e729e2012-07-15 18:09:52 +1000485 This is s convenience wrapper around :func:`importlib.find_loader` that
486 sets the *path* argument correctly when searching for submodules, and
487 also ensures parent packages (if any) are imported before searching for
488 submodules.
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000489 """
Nick Coghlan85e729e2012-07-15 18:09:52 +1000490 if fullname.startswith('.'):
491 msg = "Relative module name {!r} not supported".format(fullname)
492 raise ImportError(msg)
493 path = None
494 pkg_name = fullname.rpartition(".")[0]
495 if pkg_name:
496 pkg = importlib.import_module(pkg_name)
497 path = getattr(pkg, "__path__", None)
498 if path is None:
499 return None
500 try:
501 return importlib.find_loader(fullname, path)
502 except (ImportError, AttributeError, TypeError, ValueError) as ex:
503 # This hack fixes an impedance mismatch between pkgutil and
Andrew Svetlov5b898402012-12-18 21:26:36 +0200504 # importlib, where the latter raises other errors for cases where
Andrew Svetlov1f415cf2012-12-19 22:54:47 +0200505 # pkgutil previously raised ImportError
Nick Coghlan85e729e2012-07-15 18:09:52 +1000506 msg = "Error while finding loader for {!r} ({}: {})"
507 raise ImportError(msg.format(fullname, type(ex), ex)) from ex
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000508
Guido van Rossuma4deda02002-12-23 16:30:00 +0000509
510def extend_path(path, name):
511 """Extend a package's path.
512
513 Intended use is to place the following code in a package's __init__.py:
514
515 from pkgutil import extend_path
516 __path__ = extend_path(__path__, __name__)
517
518 This will add to the package's __path__ all subdirectories of
519 directories on sys.path named after the package. This is useful
520 if one wants to distribute different parts of a single logical
521 package as multiple directories.
522
523 It also looks for *.pkg files beginning where * matches the name
524 argument. This feature is similar to *.pth files (see site.py),
525 except that it doesn't special-case lines starting with 'import'.
526 A *.pkg file is trusted at face value: apart from checking for
527 duplicates, all entries found in a *.pkg file are added to the
528 path, regardless of whether they are exist the filesystem. (This
529 is a feature.)
530
531 If the input path is not a list (as is the case for frozen
532 packages) it is returned unchanged. The input path is not
533 modified; an extended copy is returned. Items are only appended
534 to the copy at the end.
535
536 It is assumed that sys.path is a sequence. Items of sys.path that
537 are not (unicode or 8-bit) strings referring to existing
538 directories are ignored. Unicode items of sys.path that cause
539 errors when used as filenames may cause this function to raise an
540 exception (in line with os.path.isdir() behavior).
541 """
542
543 if not isinstance(path, list):
544 # This could happen e.g. when this is called from inside a
545 # frozen package. Return the path unchanged in that case.
546 return path
547
Skip Montanaro7a98be22007-08-16 14:35:24 +0000548 sname_pkg = name + ".pkg"
Guido van Rossuma4deda02002-12-23 16:30:00 +0000549
550 path = path[:] # Start with a copy of the existing path
551
Antoine Pitroub2dd8802012-07-09 21:23:58 +0200552 parent_package, _, final_name = name.rpartition('.')
553 if parent_package:
554 try:
555 search_path = sys.modules[parent_package].__path__
556 except (KeyError, AttributeError):
557 # We can't do anything: find_loader() returns None when
558 # passed a dotted name.
559 return path
560 else:
561 search_path = sys.path
562
563 for dir in search_path:
Eric V. Smith984b11f2012-05-24 20:21:04 -0400564 if not isinstance(dir, str):
Guido van Rossuma4deda02002-12-23 16:30:00 +0000565 continue
Eric V. Smith984b11f2012-05-24 20:21:04 -0400566
567 finder = get_importer(dir)
568 if finder is not None:
569 # Is this finder PEP 420 compliant?
570 if hasattr(finder, 'find_loader'):
Antoine Pitroub2dd8802012-07-09 21:23:58 +0200571 loader, portions = finder.find_loader(final_name)
Eric V. Smith984b11f2012-05-24 20:21:04 -0400572 else:
573 # No, no need to call it
574 loader = None
575 portions = []
576
577 for portion in portions:
578 # XXX This may still add duplicate entries to path on
579 # case-insensitive filesystems
580 if portion not in path:
581 path.append(portion)
582
Guido van Rossuma4deda02002-12-23 16:30:00 +0000583 # XXX Is this the right thing for subpackages like zope.app?
584 # It looks for a file named "zope.app.pkg"
585 pkgfile = os.path.join(dir, sname_pkg)
586 if os.path.isfile(pkgfile):
587 try:
588 f = open(pkgfile)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200589 except OSError as msg:
Guido van Rossuma4deda02002-12-23 16:30:00 +0000590 sys.stderr.write("Can't open %s: %s\n" %
591 (pkgfile, msg))
592 else:
Giampaolo Rodola'2f50aaf2013-02-12 02:04:27 +0100593 with f:
594 for line in f:
595 line = line.rstrip('\n')
596 if not line or line.startswith('#'):
597 continue
598 path.append(line) # Don't check for existence!
Guido van Rossuma4deda02002-12-23 16:30:00 +0000599
600 return path
Christian Heimesdae2a892008-04-19 00:55:37 +0000601
602def get_data(package, resource):
603 """Get a resource from a package.
604
605 This is a wrapper round the PEP 302 loader get_data API. The package
606 argument should be the name of a package, in standard module format
607 (foo.bar). The resource argument should be in the form of a relative
608 filename, using '/' as the path separator. The parent directory name '..'
609 is not allowed, and nor is a rooted name (starting with a '/').
610
611 The function returns a binary string, which is the contents of the
612 specified resource.
613
614 For packages located in the filesystem, which have already been imported,
615 this is the rough equivalent of
616
617 d = os.path.dirname(sys.modules[package].__file__)
618 data = open(os.path.join(d, resource), 'rb').read()
619
620 If the package cannot be located or loaded, or it uses a PEP 302 loader
621 which does not support get_data(), then None is returned.
622 """
623
624 loader = get_loader(package)
625 if loader is None or not hasattr(loader, 'get_data'):
626 return None
627 mod = sys.modules.get(package) or loader.load_module(package)
628 if mod is None or not hasattr(mod, '__file__'):
629 return None
630
631 # Modify the resource name to be compatible with the loader.get_data
632 # signature - an os.path format "filename" starting with the dirname of
633 # the package's __file__
634 parts = resource.split('/')
635 parts.insert(0, os.path.dirname(mod.__file__))
636 resource_name = os.path.join(*parts)
637 return loader.get_data(resource_name)