blob: fb9e56e3f7dc64c12703f18c93b419a08948d25d [file] [log] [blame]
Guido van Rossuma4deda02002-12-23 16:30:00 +00001"""Utilities to support packages."""
2
Łukasz Langa6f692512013-06-05 12:20:24 +02003from functools import singledispatch as simplegeneric
Łukasz Langa6f692512013-06-05 12:20:24 +02004import importlib
Brett Cannone4f41de2013-06-16 13:13:40 -04005import importlib.util
Nick Coghlan862542e2013-10-27 00:27:39 +10006import importlib.machinery
Łukasz Langa6f692512013-06-05 12:20:24 +02007import os
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00008import os.path
Łukasz Langa6f692512013-06-05 12:20:24 +02009import sys
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000010from types import ModuleType
Brett Cannone4f41de2013-06-16 13:13:40 -040011import warnings
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000012
13__all__ = [
14 'get_importer', 'iter_importers', 'get_loader', 'find_loader',
Éric Araujoa4e2d4f2011-05-02 22:59:15 +020015 'walk_packages', 'iter_modules', 'get_data',
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000016 'ImpImporter', 'ImpLoader', 'read_code', 'extend_path',
17]
18
19def read_code(stream):
20 # This helper is needed in order for the PEP 302 emulation to
21 # correctly handle compiled files
22 import marshal
23
24 magic = stream.read(4)
Brett Cannone4f41de2013-06-16 13:13:40 -040025 if magic != importlib.util.MAGIC_NUMBER:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000026 return None
27
Antoine Pitrou5136ac02012-01-13 18:52:16 +010028 stream.read(8) # Skip timestamp and size
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000029 return marshal.load(stream)
30
31
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000032def walk_packages(path=None, prefix='', onerror=None):
Thomas Wouters0e3f5912006-08-11 14:57:12 +000033 """Yields (module_loader, name, ispkg) for all modules recursively
34 on path, or, if path is None, all accessible modules.
35
36 'path' should be either None or a list of paths to look for
37 modules in.
38
39 'prefix' is a string to output on the front of every module name
40 on output.
41
42 Note that this function must import all *packages* (NOT all
43 modules!) on the given path, in order to access the __path__
44 attribute to find submodules.
45
46 'onerror' is a function which gets called with one argument (the
47 name of the package which was being imported) if any exception
48 occurs while trying to import a package. If no onerror function is
49 supplied, ImportErrors are caught and ignored, while all other
50 exceptions are propagated, terminating the search.
51
52 Examples:
53
54 # list all modules python can access
55 walk_packages()
56
57 # list all submodules of ctypes
58 walk_packages(ctypes.__path__, ctypes.__name__+'.')
59 """
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000060
Thomas Wouters477c8d52006-05-27 19:21:47 +000061 def seen(p, m={}):
62 if p in m:
63 return True
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000064 m[p] = True
65
66 for importer, name, ispkg in iter_modules(path, prefix):
67 yield importer, name, ispkg
68
69 if ispkg:
70 try:
71 __import__(name)
72 except ImportError:
73 if onerror is not None:
Thomas Wouters0e3f5912006-08-11 14:57:12 +000074 onerror(name)
75 except Exception:
76 if onerror is not None:
77 onerror(name)
78 else:
79 raise
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000080 else:
81 path = getattr(sys.modules[name], '__path__', None) or []
82
83 # don't traverse path items we've seen before
84 path = [p for p in path if not seen(p)]
85
Philip Jenvey4993cc02012-10-01 12:53:43 -070086 yield from walk_packages(path, name+'.', onerror)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000087
88
89def iter_modules(path=None, prefix=''):
Thomas Wouters0e3f5912006-08-11 14:57:12 +000090 """Yields (module_loader, name, ispkg) for all submodules on path,
91 or, if path is None, all top-level modules on sys.path.
92
93 'path' should be either None or a list of paths to look for
94 modules in.
95
96 'prefix' is a string to output on the front of every module name
97 on output.
98 """
99
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000100 if path is None:
101 importers = iter_importers()
102 else:
103 importers = map(get_importer, path)
104
105 yielded = {}
106 for i in importers:
107 for name, ispkg in iter_importer_modules(i, prefix):
108 if name not in yielded:
109 yielded[name] = 1
110 yield i, name, ispkg
111
112
Łukasz Langa6f692512013-06-05 12:20:24 +0200113@simplegeneric
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000114def iter_importer_modules(importer, prefix=''):
Thomas Wouters477c8d52006-05-27 19:21:47 +0000115 if not hasattr(importer, 'iter_modules'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000116 return []
117 return importer.iter_modules(prefix)
118
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000119
Nick Coghlan8ecf5042012-07-15 21:19:18 +1000120# Implement a file walker for the normal importlib path hook
121def _iter_file_finder_modules(importer, prefix=''):
122 if importer.path is None or not os.path.isdir(importer.path):
123 return
124
125 yielded = {}
126 import inspect
127 try:
128 filenames = os.listdir(importer.path)
129 except OSError:
130 # ignore unreadable directories like import does
131 filenames = []
132 filenames.sort() # handle packages before same-named modules
133
134 for fn in filenames:
135 modname = inspect.getmodulename(fn)
136 if modname=='__init__' or modname in yielded:
137 continue
138
139 path = os.path.join(importer.path, fn)
140 ispkg = False
141
142 if not modname and os.path.isdir(path) and '.' not in fn:
143 modname = fn
144 try:
145 dircontents = os.listdir(path)
146 except OSError:
147 # ignore unreadable directories like import does
148 dircontents = []
149 for fn in dircontents:
150 subname = inspect.getmodulename(fn)
151 if subname=='__init__':
152 ispkg = True
153 break
154 else:
155 continue # not a package
156
157 if modname and '.' not in modname:
158 yielded[modname] = 1
159 yield prefix + modname, ispkg
160
161iter_importer_modules.register(
162 importlib.machinery.FileFinder, _iter_file_finder_modules)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000163
Brett Cannone4f41de2013-06-16 13:13:40 -0400164
165def _import_imp():
166 global imp
167 with warnings.catch_warnings():
168 warnings.simplefilter('ignore', PendingDeprecationWarning)
169 imp = importlib.import_module('imp')
170
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000171class ImpImporter:
172 """PEP 302 Importer that wraps Python's "classic" import algorithm
173
174 ImpImporter(dirname) produces a PEP 302 importer that searches that
175 directory. ImpImporter(None) produces a PEP 302 importer that searches
176 the current sys.path, plus any modules that are frozen or built-in.
177
178 Note that ImpImporter does not currently support being used by placement
179 on sys.meta_path.
180 """
181
182 def __init__(self, path=None):
Brett Cannone4f41de2013-06-16 13:13:40 -0400183 global imp
184 warnings.warn("This emulation is deprecated, use 'importlib' instead",
Nick Coghlan85e729e2012-07-15 18:09:52 +1000185 DeprecationWarning)
Brett Cannone4f41de2013-06-16 13:13:40 -0400186 _import_imp()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000187 self.path = path
188
189 def find_module(self, fullname, path=None):
190 # Note: we ignore 'path' argument since it is only used via meta_path
191 subname = fullname.split(".")[-1]
192 if subname != fullname and self.path is None:
193 return None
194 if self.path is None:
195 path = None
196 else:
197 path = [os.path.realpath(self.path)]
198 try:
199 file, filename, etc = imp.find_module(subname, path)
200 except ImportError:
201 return None
202 return ImpLoader(fullname, file, filename, etc)
203
204 def iter_modules(self, prefix=''):
205 if self.path is None or not os.path.isdir(self.path):
206 return
207
208 yielded = {}
209 import inspect
Ned Deilyed27df72011-10-06 14:19:08 -0700210 try:
211 filenames = os.listdir(self.path)
212 except OSError:
213 # ignore unreadable directories like import does
214 filenames = []
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000215 filenames.sort() # handle packages before same-named modules
216
217 for fn in filenames:
218 modname = inspect.getmodulename(fn)
219 if modname=='__init__' or modname in yielded:
220 continue
221
222 path = os.path.join(self.path, fn)
223 ispkg = False
224
225 if not modname and os.path.isdir(path) and '.' not in fn:
226 modname = fn
Ned Deilyed27df72011-10-06 14:19:08 -0700227 try:
228 dircontents = os.listdir(path)
229 except OSError:
230 # ignore unreadable directories like import does
231 dircontents = []
232 for fn in dircontents:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000233 subname = inspect.getmodulename(fn)
234 if subname=='__init__':
235 ispkg = True
236 break
237 else:
238 continue # not a package
239
240 if modname and '.' not in modname:
241 yielded[modname] = 1
242 yield prefix + modname, ispkg
243
244
245class ImpLoader:
246 """PEP 302 Loader that wraps Python's "classic" import algorithm
247 """
248 code = source = None
249
250 def __init__(self, fullname, file, filename, etc):
Brett Cannone4f41de2013-06-16 13:13:40 -0400251 warnings.warn("This emulation is deprecated, use 'importlib' instead",
252 DeprecationWarning)
253 _import_imp()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000254 self.file = file
255 self.filename = filename
256 self.fullname = fullname
257 self.etc = etc
258
259 def load_module(self, fullname):
260 self._reopen()
261 try:
262 mod = imp.load_module(fullname, self.file, self.filename, self.etc)
263 finally:
264 if self.file:
265 self.file.close()
266 # Note: we don't set __loader__ because we want the module to look
267 # normal; i.e. this is just a wrapper for standard import machinery
268 return mod
269
270 def get_data(self, pathname):
Brett Cannon1ab58df2010-10-29 22:36:53 +0000271 with open(pathname, "rb") as file:
272 return file.read()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000273
274 def _reopen(self):
275 if self.file and self.file.closed:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000276 mod_type = self.etc[2]
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000277 if mod_type==imp.PY_SOURCE:
Victor Stinner4e86d5b2011-05-04 13:55:36 +0200278 self.file = open(self.filename, 'r')
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000279 elif mod_type in (imp.PY_COMPILED, imp.C_EXTENSION):
280 self.file = open(self.filename, 'rb')
281
282 def _fix_name(self, fullname):
283 if fullname is None:
284 fullname = self.fullname
285 elif fullname != self.fullname:
286 raise ImportError("Loader for module %s cannot handle "
287 "module %s" % (self.fullname, fullname))
288 return fullname
289
290 def is_package(self, fullname):
291 fullname = self._fix_name(fullname)
292 return self.etc[2]==imp.PKG_DIRECTORY
293
294 def get_code(self, fullname=None):
295 fullname = self._fix_name(fullname)
296 if self.code is None:
297 mod_type = self.etc[2]
298 if mod_type==imp.PY_SOURCE:
299 source = self.get_source(fullname)
300 self.code = compile(source, self.filename, 'exec')
301 elif mod_type==imp.PY_COMPILED:
302 self._reopen()
303 try:
304 self.code = read_code(self.file)
305 finally:
306 self.file.close()
307 elif mod_type==imp.PKG_DIRECTORY:
308 self.code = self._get_delegate().get_code()
309 return self.code
310
311 def get_source(self, fullname=None):
312 fullname = self._fix_name(fullname)
313 if self.source is None:
314 mod_type = self.etc[2]
315 if mod_type==imp.PY_SOURCE:
316 self._reopen()
317 try:
318 self.source = self.file.read()
319 finally:
320 self.file.close()
321 elif mod_type==imp.PY_COMPILED:
322 if os.path.exists(self.filename[:-1]):
Giampaolo Rodola'2f50aaf2013-02-12 02:04:27 +0100323 with open(self.filename[:-1], 'r') as f:
324 self.source = f.read()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000325 elif mod_type==imp.PKG_DIRECTORY:
326 self.source = self._get_delegate().get_source()
327 return self.source
328
329
330 def _get_delegate(self):
331 return ImpImporter(self.filename).find_module('__init__')
332
333 def get_filename(self, fullname=None):
334 fullname = self._fix_name(fullname)
335 mod_type = self.etc[2]
Éric Araujo0cfb81d2011-09-17 03:35:57 +0200336 if mod_type==imp.PKG_DIRECTORY:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000337 return self._get_delegate().get_filename()
Éric Araujo0cfb81d2011-09-17 03:35:57 +0200338 elif mod_type in (imp.PY_SOURCE, imp.PY_COMPILED, imp.C_EXTENSION):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000339 return self.filename
340 return None
341
342
343try:
344 import zipimport
345 from zipimport import zipimporter
346
347 def iter_zipimport_modules(importer, prefix=''):
Alexandre Vassalotti515a74f2009-07-05 06:42:44 +0000348 dirlist = sorted(zipimport._zip_directory_cache[importer.archive])
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000349 _prefix = importer.prefix
350 plen = len(_prefix)
351 yielded = {}
352 import inspect
353 for fn in dirlist:
354 if not fn.startswith(_prefix):
355 continue
356
357 fn = fn[plen:].split(os.sep)
358
359 if len(fn)==2 and fn[1].startswith('__init__.py'):
360 if fn[0] not in yielded:
361 yielded[fn[0]] = 1
362 yield fn[0], True
363
364 if len(fn)!=1:
365 continue
366
367 modname = inspect.getmodulename(fn[0])
368 if modname=='__init__':
369 continue
370
371 if modname and '.' not in modname and modname not in yielded:
372 yielded[modname] = 1
373 yield prefix + modname, False
374
375 iter_importer_modules.register(zipimporter, iter_zipimport_modules)
376
377except ImportError:
378 pass
379
380
381def get_importer(path_item):
382 """Retrieve a PEP 302 importer for the given path item
383
384 The returned importer is cached in sys.path_importer_cache
385 if it was newly created by a path hook.
386
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000387 The cache (or part of it) can be cleared manually if a
388 rescan of sys.path_hooks is necessary.
389 """
390 try:
391 importer = sys.path_importer_cache[path_item]
392 except KeyError:
393 for path_hook in sys.path_hooks:
394 try:
395 importer = path_hook(path_item)
Brett Cannone0d88a12012-04-25 20:54:04 -0400396 sys.path_importer_cache.setdefault(path_item, importer)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000397 break
398 except ImportError:
399 pass
400 else:
Nick Coghlan85e729e2012-07-15 18:09:52 +1000401 importer = None
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000402 return importer
403
404
405def iter_importers(fullname=""):
406 """Yield PEP 302 importers for the given module name
407
408 If fullname contains a '.', the importers will be for the package
Nick Coghlan85e729e2012-07-15 18:09:52 +1000409 containing fullname, otherwise they will be all registered top level
410 importers (i.e. those on both sys.meta_path and sys.path_hooks).
411
412 If the named module is in a package, that package is imported as a side
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000413 effect of invoking this function.
414
Nick Coghlan85e729e2012-07-15 18:09:52 +1000415 If no module name is specified, all top level importers are produced.
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000416 """
417 if fullname.startswith('.'):
Nick Coghlan85e729e2012-07-15 18:09:52 +1000418 msg = "Relative module name {!r} not supported".format(fullname)
419 raise ImportError(msg)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000420 if '.' in fullname:
421 # Get the containing package's __path__
Nick Coghlan85e729e2012-07-15 18:09:52 +1000422 pkg_name = fullname.rpartition(".")[0]
Nick Coghlanc4e0d982013-04-14 22:30:42 +1000423 pkg = importlib.import_module(pkg_name)
424 path = getattr(pkg, '__path__', None)
Nick Coghlan85e729e2012-07-15 18:09:52 +1000425 if path is None:
426 return
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000427 else:
Andrew Svetlov2aa5f3c2012-10-07 23:21:15 +0300428 yield from sys.meta_path
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000429 path = sys.path
430 for item in path:
431 yield get_importer(item)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000432
433def get_loader(module_or_name):
434 """Get a PEP 302 "loader" object for module_or_name
435
Nick Coghlan85e729e2012-07-15 18:09:52 +1000436 Returns None if the module cannot be found or imported.
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000437 If the named module is not already imported, its containing package
438 (if any) is imported, in order to establish the package __path__.
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000439 """
440 if module_or_name in sys.modules:
441 module_or_name = sys.modules[module_or_name]
442 if isinstance(module_or_name, ModuleType):
443 module = module_or_name
Thomas Wouters477c8d52006-05-27 19:21:47 +0000444 loader = getattr(module, '__loader__', None)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000445 if loader is not None:
446 return loader
447 fullname = module.__name__
448 else:
449 fullname = module_or_name
450 return find_loader(fullname)
451
Nick Coghlan85e729e2012-07-15 18:09:52 +1000452
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000453def find_loader(fullname):
454 """Find a PEP 302 "loader" object for fullname
455
Nick Coghlan85e729e2012-07-15 18:09:52 +1000456 This is s convenience wrapper around :func:`importlib.find_loader` that
457 sets the *path* argument correctly when searching for submodules, and
458 also ensures parent packages (if any) are imported before searching for
459 submodules.
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000460 """
Nick Coghlan85e729e2012-07-15 18:09:52 +1000461 if fullname.startswith('.'):
462 msg = "Relative module name {!r} not supported".format(fullname)
463 raise ImportError(msg)
464 path = None
465 pkg_name = fullname.rpartition(".")[0]
466 if pkg_name:
467 pkg = importlib.import_module(pkg_name)
468 path = getattr(pkg, "__path__", None)
469 if path is None:
470 return None
471 try:
472 return importlib.find_loader(fullname, path)
473 except (ImportError, AttributeError, TypeError, ValueError) as ex:
474 # This hack fixes an impedance mismatch between pkgutil and
Andrew Svetlov5b898402012-12-18 21:26:36 +0200475 # importlib, where the latter raises other errors for cases where
Andrew Svetlov1f415cf2012-12-19 22:54:47 +0200476 # pkgutil previously raised ImportError
Nick Coghlan85e729e2012-07-15 18:09:52 +1000477 msg = "Error while finding loader for {!r} ({}: {})"
478 raise ImportError(msg.format(fullname, type(ex), ex)) from ex
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000479
Guido van Rossuma4deda02002-12-23 16:30:00 +0000480
481def extend_path(path, name):
482 """Extend a package's path.
483
484 Intended use is to place the following code in a package's __init__.py:
485
486 from pkgutil import extend_path
487 __path__ = extend_path(__path__, __name__)
488
489 This will add to the package's __path__ all subdirectories of
490 directories on sys.path named after the package. This is useful
491 if one wants to distribute different parts of a single logical
492 package as multiple directories.
493
494 It also looks for *.pkg files beginning where * matches the name
495 argument. This feature is similar to *.pth files (see site.py),
496 except that it doesn't special-case lines starting with 'import'.
497 A *.pkg file is trusted at face value: apart from checking for
498 duplicates, all entries found in a *.pkg file are added to the
499 path, regardless of whether they are exist the filesystem. (This
500 is a feature.)
501
502 If the input path is not a list (as is the case for frozen
503 packages) it is returned unchanged. The input path is not
504 modified; an extended copy is returned. Items are only appended
505 to the copy at the end.
506
507 It is assumed that sys.path is a sequence. Items of sys.path that
508 are not (unicode or 8-bit) strings referring to existing
509 directories are ignored. Unicode items of sys.path that cause
510 errors when used as filenames may cause this function to raise an
511 exception (in line with os.path.isdir() behavior).
512 """
513
514 if not isinstance(path, list):
515 # This could happen e.g. when this is called from inside a
516 # frozen package. Return the path unchanged in that case.
517 return path
518
Skip Montanaro7a98be22007-08-16 14:35:24 +0000519 sname_pkg = name + ".pkg"
Guido van Rossuma4deda02002-12-23 16:30:00 +0000520
521 path = path[:] # Start with a copy of the existing path
522
Antoine Pitroub2dd8802012-07-09 21:23:58 +0200523 parent_package, _, final_name = name.rpartition('.')
524 if parent_package:
525 try:
526 search_path = sys.modules[parent_package].__path__
527 except (KeyError, AttributeError):
528 # We can't do anything: find_loader() returns None when
529 # passed a dotted name.
530 return path
531 else:
532 search_path = sys.path
533
534 for dir in search_path:
Eric V. Smith984b11f2012-05-24 20:21:04 -0400535 if not isinstance(dir, str):
Guido van Rossuma4deda02002-12-23 16:30:00 +0000536 continue
Eric V. Smith984b11f2012-05-24 20:21:04 -0400537
538 finder = get_importer(dir)
539 if finder is not None:
540 # Is this finder PEP 420 compliant?
541 if hasattr(finder, 'find_loader'):
Antoine Pitroub2dd8802012-07-09 21:23:58 +0200542 loader, portions = finder.find_loader(final_name)
Eric V. Smith984b11f2012-05-24 20:21:04 -0400543 else:
544 # No, no need to call it
545 loader = None
546 portions = []
547
548 for portion in portions:
549 # XXX This may still add duplicate entries to path on
550 # case-insensitive filesystems
551 if portion not in path:
552 path.append(portion)
553
Guido van Rossuma4deda02002-12-23 16:30:00 +0000554 # XXX Is this the right thing for subpackages like zope.app?
555 # It looks for a file named "zope.app.pkg"
556 pkgfile = os.path.join(dir, sname_pkg)
557 if os.path.isfile(pkgfile):
558 try:
559 f = open(pkgfile)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200560 except OSError as msg:
Guido van Rossuma4deda02002-12-23 16:30:00 +0000561 sys.stderr.write("Can't open %s: %s\n" %
562 (pkgfile, msg))
563 else:
Giampaolo Rodola'2f50aaf2013-02-12 02:04:27 +0100564 with f:
565 for line in f:
566 line = line.rstrip('\n')
567 if not line or line.startswith('#'):
568 continue
569 path.append(line) # Don't check for existence!
Guido van Rossuma4deda02002-12-23 16:30:00 +0000570
571 return path
Christian Heimesdae2a892008-04-19 00:55:37 +0000572
573def get_data(package, resource):
574 """Get a resource from a package.
575
576 This is a wrapper round the PEP 302 loader get_data API. The package
577 argument should be the name of a package, in standard module format
578 (foo.bar). The resource argument should be in the form of a relative
579 filename, using '/' as the path separator. The parent directory name '..'
580 is not allowed, and nor is a rooted name (starting with a '/').
581
582 The function returns a binary string, which is the contents of the
583 specified resource.
584
585 For packages located in the filesystem, which have already been imported,
586 this is the rough equivalent of
587
588 d = os.path.dirname(sys.modules[package].__file__)
589 data = open(os.path.join(d, resource), 'rb').read()
590
591 If the package cannot be located or loaded, or it uses a PEP 302 loader
592 which does not support get_data(), then None is returned.
593 """
594
595 loader = get_loader(package)
596 if loader is None or not hasattr(loader, 'get_data'):
597 return None
598 mod = sys.modules.get(package) or loader.load_module(package)
599 if mod is None or not hasattr(mod, '__file__'):
600 return None
601
602 # Modify the resource name to be compatible with the loader.get_data
603 # signature - an os.path format "filename" starting with the dirname of
604 # the package's __file__
605 parts = resource.split('/')
606 parts.insert(0, os.path.dirname(mod.__file__))
607 resource_name = os.path.join(*parts)
608 return loader.get_data(resource_name)