blob: d2a6f1ec67e03c1fd13c711cf46e1b660aa675c0 [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
Nick Coghlanbe7e49f2012-07-20 23:40:09 +10004import imp
Łukasz Langa6f692512013-06-05 12:20:24 +02005import importlib
6import 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
Łukasz Langa6f692512013-06-05 12:20:24 +020010from warnings import warn
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)
24 if magic != imp.get_magic():
25 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
163class ImpImporter:
164 """PEP 302 Importer that wraps Python's "classic" import algorithm
165
166 ImpImporter(dirname) produces a PEP 302 importer that searches that
167 directory. ImpImporter(None) produces a PEP 302 importer that searches
168 the current sys.path, plus any modules that are frozen or built-in.
169
170 Note that ImpImporter does not currently support being used by placement
171 on sys.meta_path.
172 """
173
174 def __init__(self, path=None):
Nick Coghlan85e729e2012-07-15 18:09:52 +1000175 warn("This emulation is deprecated, use 'importlib' instead",
176 DeprecationWarning)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000177 self.path = path
178
179 def find_module(self, fullname, path=None):
180 # Note: we ignore 'path' argument since it is only used via meta_path
181 subname = fullname.split(".")[-1]
182 if subname != fullname and self.path is None:
183 return None
184 if self.path is None:
185 path = None
186 else:
187 path = [os.path.realpath(self.path)]
188 try:
189 file, filename, etc = imp.find_module(subname, path)
190 except ImportError:
191 return None
192 return ImpLoader(fullname, file, filename, etc)
193
194 def iter_modules(self, prefix=''):
195 if self.path is None or not os.path.isdir(self.path):
196 return
197
198 yielded = {}
199 import inspect
Ned Deilyed27df72011-10-06 14:19:08 -0700200 try:
201 filenames = os.listdir(self.path)
202 except OSError:
203 # ignore unreadable directories like import does
204 filenames = []
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000205 filenames.sort() # handle packages before same-named modules
206
207 for fn in filenames:
208 modname = inspect.getmodulename(fn)
209 if modname=='__init__' or modname in yielded:
210 continue
211
212 path = os.path.join(self.path, fn)
213 ispkg = False
214
215 if not modname and os.path.isdir(path) and '.' not in fn:
216 modname = fn
Ned Deilyed27df72011-10-06 14:19:08 -0700217 try:
218 dircontents = os.listdir(path)
219 except OSError:
220 # ignore unreadable directories like import does
221 dircontents = []
222 for fn in dircontents:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000223 subname = inspect.getmodulename(fn)
224 if subname=='__init__':
225 ispkg = True
226 break
227 else:
228 continue # not a package
229
230 if modname and '.' not in modname:
231 yielded[modname] = 1
232 yield prefix + modname, ispkg
233
234
235class ImpLoader:
236 """PEP 302 Loader that wraps Python's "classic" import algorithm
237 """
238 code = source = None
239
240 def __init__(self, fullname, file, filename, etc):
Nick Coghlan85e729e2012-07-15 18:09:52 +1000241 warn("This emulation is deprecated, use 'importlib' instead",
242 DeprecationWarning)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000243 self.file = file
244 self.filename = filename
245 self.fullname = fullname
246 self.etc = etc
247
248 def load_module(self, fullname):
249 self._reopen()
250 try:
251 mod = imp.load_module(fullname, self.file, self.filename, self.etc)
252 finally:
253 if self.file:
254 self.file.close()
255 # Note: we don't set __loader__ because we want the module to look
256 # normal; i.e. this is just a wrapper for standard import machinery
257 return mod
258
259 def get_data(self, pathname):
Brett Cannon1ab58df2010-10-29 22:36:53 +0000260 with open(pathname, "rb") as file:
261 return file.read()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000262
263 def _reopen(self):
264 if self.file and self.file.closed:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000265 mod_type = self.etc[2]
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000266 if mod_type==imp.PY_SOURCE:
Victor Stinner4e86d5b2011-05-04 13:55:36 +0200267 self.file = open(self.filename, 'r')
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000268 elif mod_type in (imp.PY_COMPILED, imp.C_EXTENSION):
269 self.file = open(self.filename, 'rb')
270
271 def _fix_name(self, fullname):
272 if fullname is None:
273 fullname = self.fullname
274 elif fullname != self.fullname:
275 raise ImportError("Loader for module %s cannot handle "
276 "module %s" % (self.fullname, fullname))
277 return fullname
278
279 def is_package(self, fullname):
280 fullname = self._fix_name(fullname)
281 return self.etc[2]==imp.PKG_DIRECTORY
282
283 def get_code(self, fullname=None):
284 fullname = self._fix_name(fullname)
285 if self.code is None:
286 mod_type = self.etc[2]
287 if mod_type==imp.PY_SOURCE:
288 source = self.get_source(fullname)
289 self.code = compile(source, self.filename, 'exec')
290 elif mod_type==imp.PY_COMPILED:
291 self._reopen()
292 try:
293 self.code = read_code(self.file)
294 finally:
295 self.file.close()
296 elif mod_type==imp.PKG_DIRECTORY:
297 self.code = self._get_delegate().get_code()
298 return self.code
299
300 def get_source(self, fullname=None):
301 fullname = self._fix_name(fullname)
302 if self.source is None:
303 mod_type = self.etc[2]
304 if mod_type==imp.PY_SOURCE:
305 self._reopen()
306 try:
307 self.source = self.file.read()
308 finally:
309 self.file.close()
310 elif mod_type==imp.PY_COMPILED:
311 if os.path.exists(self.filename[:-1]):
Giampaolo Rodola'2f50aaf2013-02-12 02:04:27 +0100312 with open(self.filename[:-1], 'r') as f:
313 self.source = f.read()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000314 elif mod_type==imp.PKG_DIRECTORY:
315 self.source = self._get_delegate().get_source()
316 return self.source
317
318
319 def _get_delegate(self):
320 return ImpImporter(self.filename).find_module('__init__')
321
322 def get_filename(self, fullname=None):
323 fullname = self._fix_name(fullname)
324 mod_type = self.etc[2]
Éric Araujo0cfb81d2011-09-17 03:35:57 +0200325 if mod_type==imp.PKG_DIRECTORY:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000326 return self._get_delegate().get_filename()
Éric Araujo0cfb81d2011-09-17 03:35:57 +0200327 elif mod_type in (imp.PY_SOURCE, imp.PY_COMPILED, imp.C_EXTENSION):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000328 return self.filename
329 return None
330
331
332try:
333 import zipimport
334 from zipimport import zipimporter
335
336 def iter_zipimport_modules(importer, prefix=''):
Alexandre Vassalotti515a74f2009-07-05 06:42:44 +0000337 dirlist = sorted(zipimport._zip_directory_cache[importer.archive])
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000338 _prefix = importer.prefix
339 plen = len(_prefix)
340 yielded = {}
341 import inspect
342 for fn in dirlist:
343 if not fn.startswith(_prefix):
344 continue
345
346 fn = fn[plen:].split(os.sep)
347
348 if len(fn)==2 and fn[1].startswith('__init__.py'):
349 if fn[0] not in yielded:
350 yielded[fn[0]] = 1
351 yield fn[0], True
352
353 if len(fn)!=1:
354 continue
355
356 modname = inspect.getmodulename(fn[0])
357 if modname=='__init__':
358 continue
359
360 if modname and '.' not in modname and modname not in yielded:
361 yielded[modname] = 1
362 yield prefix + modname, False
363
364 iter_importer_modules.register(zipimporter, iter_zipimport_modules)
365
366except ImportError:
367 pass
368
369
370def get_importer(path_item):
371 """Retrieve a PEP 302 importer for the given path item
372
373 The returned importer is cached in sys.path_importer_cache
374 if it was newly created by a path hook.
375
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000376 The cache (or part of it) can be cleared manually if a
377 rescan of sys.path_hooks is necessary.
378 """
379 try:
380 importer = sys.path_importer_cache[path_item]
381 except KeyError:
382 for path_hook in sys.path_hooks:
383 try:
384 importer = path_hook(path_item)
Brett Cannone0d88a12012-04-25 20:54:04 -0400385 sys.path_importer_cache.setdefault(path_item, importer)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000386 break
387 except ImportError:
388 pass
389 else:
Nick Coghlan85e729e2012-07-15 18:09:52 +1000390 importer = None
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000391 return importer
392
393
394def iter_importers(fullname=""):
395 """Yield PEP 302 importers for the given module name
396
397 If fullname contains a '.', the importers will be for the package
Nick Coghlan85e729e2012-07-15 18:09:52 +1000398 containing fullname, otherwise they will be all registered top level
399 importers (i.e. those on both sys.meta_path and sys.path_hooks).
400
401 If the named module is in a package, that package is imported as a side
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000402 effect of invoking this function.
403
Nick Coghlan85e729e2012-07-15 18:09:52 +1000404 If no module name is specified, all top level importers are produced.
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000405 """
406 if fullname.startswith('.'):
Nick Coghlan85e729e2012-07-15 18:09:52 +1000407 msg = "Relative module name {!r} not supported".format(fullname)
408 raise ImportError(msg)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000409 if '.' in fullname:
410 # Get the containing package's __path__
Nick Coghlan85e729e2012-07-15 18:09:52 +1000411 pkg_name = fullname.rpartition(".")[0]
Nick Coghlanc4e0d982013-04-14 22:30:42 +1000412 pkg = importlib.import_module(pkg_name)
413 path = getattr(pkg, '__path__', None)
Nick Coghlan85e729e2012-07-15 18:09:52 +1000414 if path is None:
415 return
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000416 else:
Andrew Svetlov2aa5f3c2012-10-07 23:21:15 +0300417 yield from sys.meta_path
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000418 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
Andrew Svetlov5b898402012-12-18 21:26:36 +0200464 # importlib, where the latter raises other errors for cases where
Andrew Svetlov1f415cf2012-12-19 22:54:47 +0200465 # pkgutil previously raised ImportError
Nick Coghlan85e729e2012-07-15 18:09:52 +1000466 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)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200549 except OSError 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:
Giampaolo Rodola'2f50aaf2013-02-12 02:04:27 +0100553 with f:
554 for line in f:
555 line = line.rstrip('\n')
556 if not line or line.startswith('#'):
557 continue
558 path.append(line) # Don't check for existence!
Guido van Rossuma4deda02002-12-23 16:30:00 +0000559
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)