blob: 4678bb8b33e1f42df1d60f833c4d0cda6ee04810 [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
Łukasz Langa6f692512013-06-05 12:20:24 +02006import os
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00007import os.path
Łukasz Langa6f692512013-06-05 12:20:24 +02008import sys
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00009from types import ModuleType
Brett Cannone4f41de2013-06-16 13:13:40 -040010import warnings
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000011
12__all__ = [
13 'get_importer', 'iter_importers', 'get_loader', 'find_loader',
Éric Araujoa4e2d4f2011-05-02 22:59:15 +020014 'walk_packages', 'iter_modules', 'get_data',
Thomas Wouters49fd7fa2006-04-21 10:40:58 +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)
Brett Cannone4f41de2013-06-16 13:13:40 -040024 if magic != importlib.util.MAGIC_NUMBER:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000025 return None
26
Antoine Pitrou5136ac02012-01-13 18:52:16 +010027 stream.read(8) # Skip timestamp and size
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000028 return marshal.load(stream)
29
30
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000031def walk_packages(path=None, prefix='', onerror=None):
Thomas Wouters0e3f5912006-08-11 14:57:12 +000032 """Yields (module_loader, name, ispkg) for all modules recursively
33 on path, or, if path is None, all accessible modules.
34
35 'path' should be either None or a list of paths to look for
36 modules in.
37
38 'prefix' is a string to output on the front of every module name
39 on output.
40
41 Note that this function must import all *packages* (NOT all
42 modules!) on the given path, in order to access the __path__
43 attribute to find submodules.
44
45 'onerror' is a function which gets called with one argument (the
46 name of the package which was being imported) if any exception
47 occurs while trying to import a package. If no onerror function is
48 supplied, ImportErrors are caught and ignored, while all other
49 exceptions are propagated, terminating the search.
50
51 Examples:
52
53 # list all modules python can access
54 walk_packages()
55
56 # list all submodules of ctypes
57 walk_packages(ctypes.__path__, ctypes.__name__+'.')
58 """
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000059
Thomas Wouters477c8d52006-05-27 19:21:47 +000060 def seen(p, m={}):
61 if p in m:
62 return True
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000063 m[p] = True
64
65 for importer, name, ispkg in iter_modules(path, prefix):
66 yield importer, name, ispkg
67
68 if ispkg:
69 try:
70 __import__(name)
71 except ImportError:
72 if onerror is not None:
Thomas Wouters0e3f5912006-08-11 14:57:12 +000073 onerror(name)
74 except Exception:
75 if onerror is not None:
76 onerror(name)
77 else:
78 raise
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000079 else:
80 path = getattr(sys.modules[name], '__path__', None) or []
81
82 # don't traverse path items we've seen before
83 path = [p for p in path if not seen(p)]
84
Philip Jenvey4993cc02012-10-01 12:53:43 -070085 yield from walk_packages(path, name+'.', onerror)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000086
87
88def iter_modules(path=None, prefix=''):
Thomas Wouters0e3f5912006-08-11 14:57:12 +000089 """Yields (module_loader, name, ispkg) for all submodules on path,
90 or, if path is None, all top-level modules on sys.path.
91
92 'path' should be either None or a list of paths to look for
93 modules in.
94
95 'prefix' is a string to output on the front of every module name
96 on output.
97 """
98
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000099 if path is None:
100 importers = iter_importers()
101 else:
102 importers = map(get_importer, path)
103
104 yielded = {}
105 for i in importers:
106 for name, ispkg in iter_importer_modules(i, prefix):
107 if name not in yielded:
108 yielded[name] = 1
109 yield i, name, ispkg
110
111
Łukasz Langa6f692512013-06-05 12:20:24 +0200112@simplegeneric
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000113def iter_importer_modules(importer, prefix=''):
Thomas Wouters477c8d52006-05-27 19:21:47 +0000114 if not hasattr(importer, 'iter_modules'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000115 return []
116 return importer.iter_modules(prefix)
117
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000118
Nick Coghlan8ecf5042012-07-15 21:19:18 +1000119# Implement a file walker for the normal importlib path hook
120def _iter_file_finder_modules(importer, prefix=''):
121 if importer.path is None or not os.path.isdir(importer.path):
122 return
123
124 yielded = {}
125 import inspect
126 try:
127 filenames = os.listdir(importer.path)
128 except OSError:
129 # ignore unreadable directories like import does
130 filenames = []
131 filenames.sort() # handle packages before same-named modules
132
133 for fn in filenames:
134 modname = inspect.getmodulename(fn)
135 if modname=='__init__' or modname in yielded:
136 continue
137
138 path = os.path.join(importer.path, fn)
139 ispkg = False
140
141 if not modname and os.path.isdir(path) and '.' not in fn:
142 modname = fn
143 try:
144 dircontents = os.listdir(path)
145 except OSError:
146 # ignore unreadable directories like import does
147 dircontents = []
148 for fn in dircontents:
149 subname = inspect.getmodulename(fn)
150 if subname=='__init__':
151 ispkg = True
152 break
153 else:
154 continue # not a package
155
156 if modname and '.' not in modname:
157 yielded[modname] = 1
158 yield prefix + modname, ispkg
159
160iter_importer_modules.register(
161 importlib.machinery.FileFinder, _iter_file_finder_modules)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000162
Brett Cannone4f41de2013-06-16 13:13:40 -0400163
164def _import_imp():
165 global imp
166 with warnings.catch_warnings():
167 warnings.simplefilter('ignore', PendingDeprecationWarning)
168 imp = importlib.import_module('imp')
169
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000170class ImpImporter:
171 """PEP 302 Importer that wraps Python's "classic" import algorithm
172
173 ImpImporter(dirname) produces a PEP 302 importer that searches that
174 directory. ImpImporter(None) produces a PEP 302 importer that searches
175 the current sys.path, plus any modules that are frozen or built-in.
176
177 Note that ImpImporter does not currently support being used by placement
178 on sys.meta_path.
179 """
180
181 def __init__(self, path=None):
Brett Cannone4f41de2013-06-16 13:13:40 -0400182 global imp
183 warnings.warn("This emulation is deprecated, use 'importlib' instead",
Nick Coghlan85e729e2012-07-15 18:09:52 +1000184 DeprecationWarning)
Brett Cannone4f41de2013-06-16 13:13:40 -0400185 _import_imp()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000186 self.path = path
187
188 def find_module(self, fullname, path=None):
189 # Note: we ignore 'path' argument since it is only used via meta_path
190 subname = fullname.split(".")[-1]
191 if subname != fullname and self.path is None:
192 return None
193 if self.path is None:
194 path = None
195 else:
196 path = [os.path.realpath(self.path)]
197 try:
198 file, filename, etc = imp.find_module(subname, path)
199 except ImportError:
200 return None
201 return ImpLoader(fullname, file, filename, etc)
202
203 def iter_modules(self, prefix=''):
204 if self.path is None or not os.path.isdir(self.path):
205 return
206
207 yielded = {}
208 import inspect
Ned Deilyed27df72011-10-06 14:19:08 -0700209 try:
210 filenames = os.listdir(self.path)
211 except OSError:
212 # ignore unreadable directories like import does
213 filenames = []
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000214 filenames.sort() # handle packages before same-named modules
215
216 for fn in filenames:
217 modname = inspect.getmodulename(fn)
218 if modname=='__init__' or modname in yielded:
219 continue
220
221 path = os.path.join(self.path, fn)
222 ispkg = False
223
224 if not modname and os.path.isdir(path) and '.' not in fn:
225 modname = fn
Ned Deilyed27df72011-10-06 14:19:08 -0700226 try:
227 dircontents = os.listdir(path)
228 except OSError:
229 # ignore unreadable directories like import does
230 dircontents = []
231 for fn in dircontents:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000232 subname = inspect.getmodulename(fn)
233 if subname=='__init__':
234 ispkg = True
235 break
236 else:
237 continue # not a package
238
239 if modname and '.' not in modname:
240 yielded[modname] = 1
241 yield prefix + modname, ispkg
242
243
244class ImpLoader:
245 """PEP 302 Loader that wraps Python's "classic" import algorithm
246 """
247 code = source = None
248
249 def __init__(self, fullname, file, filename, etc):
Brett Cannone4f41de2013-06-16 13:13:40 -0400250 warnings.warn("This emulation is deprecated, use 'importlib' instead",
251 DeprecationWarning)
252 _import_imp()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000253 self.file = file
254 self.filename = filename
255 self.fullname = fullname
256 self.etc = etc
257
258 def load_module(self, fullname):
259 self._reopen()
260 try:
261 mod = imp.load_module(fullname, self.file, self.filename, self.etc)
262 finally:
263 if self.file:
264 self.file.close()
265 # Note: we don't set __loader__ because we want the module to look
266 # normal; i.e. this is just a wrapper for standard import machinery
267 return mod
268
269 def get_data(self, pathname):
Brett Cannon1ab58df2010-10-29 22:36:53 +0000270 with open(pathname, "rb") as file:
271 return file.read()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000272
273 def _reopen(self):
274 if self.file and self.file.closed:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000275 mod_type = self.etc[2]
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000276 if mod_type==imp.PY_SOURCE:
Victor Stinner4e86d5b2011-05-04 13:55:36 +0200277 self.file = open(self.filename, 'r')
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000278 elif mod_type in (imp.PY_COMPILED, imp.C_EXTENSION):
279 self.file = open(self.filename, 'rb')
280
281 def _fix_name(self, fullname):
282 if fullname is None:
283 fullname = self.fullname
284 elif fullname != self.fullname:
285 raise ImportError("Loader for module %s cannot handle "
286 "module %s" % (self.fullname, fullname))
287 return fullname
288
289 def is_package(self, fullname):
290 fullname = self._fix_name(fullname)
291 return self.etc[2]==imp.PKG_DIRECTORY
292
293 def get_code(self, fullname=None):
294 fullname = self._fix_name(fullname)
295 if self.code is None:
296 mod_type = self.etc[2]
297 if mod_type==imp.PY_SOURCE:
298 source = self.get_source(fullname)
299 self.code = compile(source, self.filename, 'exec')
300 elif mod_type==imp.PY_COMPILED:
301 self._reopen()
302 try:
303 self.code = read_code(self.file)
304 finally:
305 self.file.close()
306 elif mod_type==imp.PKG_DIRECTORY:
307 self.code = self._get_delegate().get_code()
308 return self.code
309
310 def get_source(self, fullname=None):
311 fullname = self._fix_name(fullname)
312 if self.source is None:
313 mod_type = self.etc[2]
314 if mod_type==imp.PY_SOURCE:
315 self._reopen()
316 try:
317 self.source = self.file.read()
318 finally:
319 self.file.close()
320 elif mod_type==imp.PY_COMPILED:
321 if os.path.exists(self.filename[:-1]):
Giampaolo Rodola'2f50aaf2013-02-12 02:04:27 +0100322 with open(self.filename[:-1], 'r') as f:
323 self.source = f.read()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000324 elif mod_type==imp.PKG_DIRECTORY:
325 self.source = self._get_delegate().get_source()
326 return self.source
327
328
329 def _get_delegate(self):
330 return ImpImporter(self.filename).find_module('__init__')
331
332 def get_filename(self, fullname=None):
333 fullname = self._fix_name(fullname)
334 mod_type = self.etc[2]
Éric Araujo0cfb81d2011-09-17 03:35:57 +0200335 if mod_type==imp.PKG_DIRECTORY:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000336 return self._get_delegate().get_filename()
Éric Araujo0cfb81d2011-09-17 03:35:57 +0200337 elif mod_type in (imp.PY_SOURCE, imp.PY_COMPILED, imp.C_EXTENSION):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000338 return self.filename
339 return None
340
341
342try:
343 import zipimport
344 from zipimport import zipimporter
345
346 def iter_zipimport_modules(importer, prefix=''):
Alexandre Vassalotti515a74f2009-07-05 06:42:44 +0000347 dirlist = sorted(zipimport._zip_directory_cache[importer.archive])
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000348 _prefix = importer.prefix
349 plen = len(_prefix)
350 yielded = {}
351 import inspect
352 for fn in dirlist:
353 if not fn.startswith(_prefix):
354 continue
355
356 fn = fn[plen:].split(os.sep)
357
358 if len(fn)==2 and fn[1].startswith('__init__.py'):
359 if fn[0] not in yielded:
360 yielded[fn[0]] = 1
361 yield fn[0], True
362
363 if len(fn)!=1:
364 continue
365
366 modname = inspect.getmodulename(fn[0])
367 if modname=='__init__':
368 continue
369
370 if modname and '.' not in modname and modname not in yielded:
371 yielded[modname] = 1
372 yield prefix + modname, False
373
374 iter_importer_modules.register(zipimporter, iter_zipimport_modules)
375
376except ImportError:
377 pass
378
379
380def get_importer(path_item):
381 """Retrieve a PEP 302 importer for the given path item
382
383 The returned importer is cached in sys.path_importer_cache
384 if it was newly created by a path hook.
385
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000386 The cache (or part of it) can be cleared manually if a
387 rescan of sys.path_hooks is necessary.
388 """
389 try:
390 importer = sys.path_importer_cache[path_item]
391 except KeyError:
392 for path_hook in sys.path_hooks:
393 try:
394 importer = path_hook(path_item)
Brett Cannone0d88a12012-04-25 20:54:04 -0400395 sys.path_importer_cache.setdefault(path_item, importer)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000396 break
397 except ImportError:
398 pass
399 else:
Nick Coghlan85e729e2012-07-15 18:09:52 +1000400 importer = None
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000401 return importer
402
403
404def iter_importers(fullname=""):
405 """Yield PEP 302 importers for the given module name
406
407 If fullname contains a '.', the importers will be for the package
Nick Coghlan85e729e2012-07-15 18:09:52 +1000408 containing fullname, otherwise they will be all registered top level
409 importers (i.e. those on both sys.meta_path and sys.path_hooks).
410
411 If the named module is in a package, that package is imported as a side
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000412 effect of invoking this function.
413
Nick Coghlan85e729e2012-07-15 18:09:52 +1000414 If no module name is specified, all top level importers are produced.
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000415 """
416 if fullname.startswith('.'):
Nick Coghlan85e729e2012-07-15 18:09:52 +1000417 msg = "Relative module name {!r} not supported".format(fullname)
418 raise ImportError(msg)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000419 if '.' in fullname:
420 # Get the containing package's __path__
Nick Coghlan85e729e2012-07-15 18:09:52 +1000421 pkg_name = fullname.rpartition(".")[0]
Nick Coghlanc4e0d982013-04-14 22:30:42 +1000422 pkg = importlib.import_module(pkg_name)
423 path = getattr(pkg, '__path__', None)
Nick Coghlan85e729e2012-07-15 18:09:52 +1000424 if path is None:
425 return
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000426 else:
Andrew Svetlov2aa5f3c2012-10-07 23:21:15 +0300427 yield from sys.meta_path
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000428 path = sys.path
429 for item in path:
430 yield get_importer(item)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000431
432def get_loader(module_or_name):
433 """Get a PEP 302 "loader" object for module_or_name
434
Nick Coghlan85e729e2012-07-15 18:09:52 +1000435 Returns None if the module cannot be found or imported.
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000436 If the named module is not already imported, its containing package
437 (if any) is imported, in order to establish the package __path__.
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000438 """
439 if module_or_name in sys.modules:
440 module_or_name = sys.modules[module_or_name]
441 if isinstance(module_or_name, ModuleType):
442 module = module_or_name
Thomas Wouters477c8d52006-05-27 19:21:47 +0000443 loader = getattr(module, '__loader__', None)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000444 if loader is not None:
445 return loader
446 fullname = module.__name__
447 else:
448 fullname = module_or_name
449 return find_loader(fullname)
450
Nick Coghlan85e729e2012-07-15 18:09:52 +1000451
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000452def find_loader(fullname):
453 """Find a PEP 302 "loader" object for fullname
454
Nick Coghlan85e729e2012-07-15 18:09:52 +1000455 This is s convenience wrapper around :func:`importlib.find_loader` that
456 sets the *path* argument correctly when searching for submodules, and
457 also ensures parent packages (if any) are imported before searching for
458 submodules.
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000459 """
Nick Coghlan85e729e2012-07-15 18:09:52 +1000460 if fullname.startswith('.'):
461 msg = "Relative module name {!r} not supported".format(fullname)
462 raise ImportError(msg)
463 path = None
464 pkg_name = fullname.rpartition(".")[0]
465 if pkg_name:
466 pkg = importlib.import_module(pkg_name)
467 path = getattr(pkg, "__path__", None)
468 if path is None:
469 return None
470 try:
471 return importlib.find_loader(fullname, path)
472 except (ImportError, AttributeError, TypeError, ValueError) as ex:
473 # This hack fixes an impedance mismatch between pkgutil and
Andrew Svetlov5b898402012-12-18 21:26:36 +0200474 # importlib, where the latter raises other errors for cases where
Andrew Svetlov1f415cf2012-12-19 22:54:47 +0200475 # pkgutil previously raised ImportError
Nick Coghlan85e729e2012-07-15 18:09:52 +1000476 msg = "Error while finding loader for {!r} ({}: {})"
477 raise ImportError(msg.format(fullname, type(ex), ex)) from ex
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000478
Guido van Rossuma4deda02002-12-23 16:30:00 +0000479
480def extend_path(path, name):
481 """Extend a package's path.
482
483 Intended use is to place the following code in a package's __init__.py:
484
485 from pkgutil import extend_path
486 __path__ = extend_path(__path__, __name__)
487
488 This will add to the package's __path__ all subdirectories of
489 directories on sys.path named after the package. This is useful
490 if one wants to distribute different parts of a single logical
491 package as multiple directories.
492
493 It also looks for *.pkg files beginning where * matches the name
494 argument. This feature is similar to *.pth files (see site.py),
495 except that it doesn't special-case lines starting with 'import'.
496 A *.pkg file is trusted at face value: apart from checking for
497 duplicates, all entries found in a *.pkg file are added to the
498 path, regardless of whether they are exist the filesystem. (This
499 is a feature.)
500
501 If the input path is not a list (as is the case for frozen
502 packages) it is returned unchanged. The input path is not
503 modified; an extended copy is returned. Items are only appended
504 to the copy at the end.
505
506 It is assumed that sys.path is a sequence. Items of sys.path that
507 are not (unicode or 8-bit) strings referring to existing
508 directories are ignored. Unicode items of sys.path that cause
509 errors when used as filenames may cause this function to raise an
510 exception (in line with os.path.isdir() behavior).
511 """
512
513 if not isinstance(path, list):
514 # This could happen e.g. when this is called from inside a
515 # frozen package. Return the path unchanged in that case.
516 return path
517
Skip Montanaro7a98be22007-08-16 14:35:24 +0000518 sname_pkg = name + ".pkg"
Guido van Rossuma4deda02002-12-23 16:30:00 +0000519
520 path = path[:] # Start with a copy of the existing path
521
Antoine Pitroub2dd8802012-07-09 21:23:58 +0200522 parent_package, _, final_name = name.rpartition('.')
523 if parent_package:
524 try:
525 search_path = sys.modules[parent_package].__path__
526 except (KeyError, AttributeError):
527 # We can't do anything: find_loader() returns None when
528 # passed a dotted name.
529 return path
530 else:
531 search_path = sys.path
532
533 for dir in search_path:
Eric V. Smith984b11f2012-05-24 20:21:04 -0400534 if not isinstance(dir, str):
Guido van Rossuma4deda02002-12-23 16:30:00 +0000535 continue
Eric V. Smith984b11f2012-05-24 20:21:04 -0400536
537 finder = get_importer(dir)
538 if finder is not None:
539 # Is this finder PEP 420 compliant?
540 if hasattr(finder, 'find_loader'):
Antoine Pitroub2dd8802012-07-09 21:23:58 +0200541 loader, portions = finder.find_loader(final_name)
Eric V. Smith984b11f2012-05-24 20:21:04 -0400542 else:
543 # No, no need to call it
544 loader = None
545 portions = []
546
547 for portion in portions:
548 # XXX This may still add duplicate entries to path on
549 # case-insensitive filesystems
550 if portion not in path:
551 path.append(portion)
552
Guido van Rossuma4deda02002-12-23 16:30:00 +0000553 # XXX Is this the right thing for subpackages like zope.app?
554 # It looks for a file named "zope.app.pkg"
555 pkgfile = os.path.join(dir, sname_pkg)
556 if os.path.isfile(pkgfile):
557 try:
558 f = open(pkgfile)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200559 except OSError as msg:
Guido van Rossuma4deda02002-12-23 16:30:00 +0000560 sys.stderr.write("Can't open %s: %s\n" %
561 (pkgfile, msg))
562 else:
Giampaolo Rodola'2f50aaf2013-02-12 02:04:27 +0100563 with f:
564 for line in f:
565 line = line.rstrip('\n')
566 if not line or line.startswith('#'):
567 continue
568 path.append(line) # Don't check for existence!
Guido van Rossuma4deda02002-12-23 16:30:00 +0000569
570 return path
Christian Heimesdae2a892008-04-19 00:55:37 +0000571
572def get_data(package, resource):
573 """Get a resource from a package.
574
575 This is a wrapper round the PEP 302 loader get_data API. The package
576 argument should be the name of a package, in standard module format
577 (foo.bar). The resource argument should be in the form of a relative
578 filename, using '/' as the path separator. The parent directory name '..'
579 is not allowed, and nor is a rooted name (starting with a '/').
580
581 The function returns a binary string, which is the contents of the
582 specified resource.
583
584 For packages located in the filesystem, which have already been imported,
585 this is the rough equivalent of
586
587 d = os.path.dirname(sys.modules[package].__file__)
588 data = open(os.path.join(d, resource), 'rb').read()
589
590 If the package cannot be located or loaded, or it uses a PEP 302 loader
591 which does not support get_data(), then None is returned.
592 """
593
594 loader = get_loader(package)
595 if loader is None or not hasattr(loader, 'get_data'):
596 return None
597 mod = sys.modules.get(package) or loader.load_module(package)
598 if mod is None or not hasattr(mod, '__file__'):
599 return None
600
601 # Modify the resource name to be compatible with the loader.get_data
602 # signature - an os.path format "filename" starting with the dirname of
603 # the package's __file__
604 parts = resource.split('/')
605 parts.insert(0, os.path.dirname(mod.__file__))
606 resource_name = os.path.join(*parts)
607 return loader.get_data(resource_name)