Skip to content

Latest commit

 

History

History
634 lines (519 loc) · 20.8 KB

File metadata and controls

634 lines (519 loc) · 20.8 KB
 
1
"""Utilities to support packages."""
2
Sep 8, 2016
Sep 8, 2016
3
from collections import namedtuple
Jun 5, 2013
Jun 5, 2013
4
from functools import singledispatch as simplegeneric
5
import importlib
Jun 16, 2013
Jun 16, 2013
6
import importlib.util
Oct 26, 2013
Oct 26, 2013
7
import importlib.machinery
Jun 5, 2013
Jun 5, 2013
8
import os
Apr 21, 2006
Apr 21, 2006
9
import os.path
Jun 5, 2013
Jun 5, 2013
10
import sys
Apr 21, 2006
Apr 21, 2006
11
from types import ModuleType
Jun 16, 2013
Jun 16, 2013
12
import warnings
Apr 21, 2006
Apr 21, 2006
13
14
__all__ = [
15
'get_importer', 'iter_importers', 'get_loader', 'find_loader',
May 2, 2011
May 2, 2011
16
'walk_packages', 'iter_modules', 'get_data',
Apr 21, 2006
Apr 21, 2006
17
'ImpImporter', 'ImpLoader', 'read_code', 'extend_path',
Sep 8, 2016
Sep 8, 2016
18
'ModuleInfo',
Apr 21, 2006
Apr 21, 2006
19
]
20
Jan 4, 2014
Jan 4, 2014
21
Sep 8, 2016
Sep 8, 2016
22
ModuleInfo = namedtuple('ModuleInfo', 'module_finder name ispkg')
23
ModuleInfo.__doc__ = 'A namedtuple with minimal info about a module.'
24
25
Jan 4, 2014
Jan 4, 2014
26
def _get_spec(finder, name):
27
"""Return the finder-specific module spec."""
28
# Works with legacy finders.
29
try:
30
find_spec = finder.find_spec
31
except AttributeError:
32
loader = finder.find_module(name)
33
if loader is None:
34
return None
35
return importlib.util.spec_from_loader(name, loader)
36
else:
37
return find_spec(name)
38
39
Apr 21, 2006
Apr 21, 2006
40
def read_code(stream):
41
# This helper is needed in order for the PEP 302 emulation to
42
# correctly handle compiled files
43
import marshal
44
45
magic = stream.read(4)
Jun 16, 2013
Jun 16, 2013
46
if magic != importlib.util.MAGIC_NUMBER:
Apr 21, 2006
Apr 21, 2006
47
return None
48
Jan 13, 2012
Jan 13, 2012
49
stream.read(8) # Skip timestamp and size
Apr 21, 2006
Apr 21, 2006
50
return marshal.load(stream)
51
52
53
def walk_packages(path=None, prefix='', onerror=None):
Sep 8, 2016
Sep 8, 2016
54
"""Yields ModuleInfo for all modules recursively
Aug 11, 2006
Aug 11, 2006
55
on path, or, if path is None, all accessible modules.
56
57
'path' should be either None or a list of paths to look for
58
modules in.
59
60
'prefix' is a string to output on the front of every module name
61
on output.
62
63
Note that this function must import all *packages* (NOT all
64
modules!) on the given path, in order to access the __path__
65
attribute to find submodules.
66
67
'onerror' is a function which gets called with one argument (the
68
name of the package which was being imported) if any exception
69
occurs while trying to import a package. If no onerror function is
70
supplied, ImportErrors are caught and ignored, while all other
71
exceptions are propagated, terminating the search.
72
73
Examples:
74
75
# list all modules python can access
76
walk_packages()
77
78
# list all submodules of ctypes
79
walk_packages(ctypes.__path__, ctypes.__name__+'.')
80
"""
Apr 21, 2006
Apr 21, 2006
81
May 27, 2006
May 27, 2006
82
def seen(p, m={}):
83
if p in m:
84
return True
Apr 21, 2006
Apr 21, 2006
85
m[p] = True
86
Sep 8, 2016
Sep 8, 2016
87
for info in iter_modules(path, prefix):
88
yield info
Apr 21, 2006
Apr 21, 2006
89
Sep 8, 2016
Sep 8, 2016
90
if info.ispkg:
Apr 21, 2006
Apr 21, 2006
91
try:
Sep 8, 2016
Sep 8, 2016
92
__import__(info.name)
Apr 21, 2006
Apr 21, 2006
93
except ImportError:
94
if onerror is not None:
Sep 8, 2016
Sep 8, 2016
95
onerror(info.name)
Aug 11, 2006
Aug 11, 2006
96
except Exception:
97
if onerror is not None:
Sep 8, 2016
Sep 8, 2016
98
onerror(info.name)
Aug 11, 2006
Aug 11, 2006
99
else:
100
raise
Apr 21, 2006
Apr 21, 2006
101
else:
Sep 8, 2016
Sep 8, 2016
102
path = getattr(sys.modules[info.name], '__path__', None) or []
Apr 21, 2006
Apr 21, 2006
103
104
# don't traverse path items we've seen before
105
path = [p for p in path if not seen(p)]
106
Sep 8, 2016
Sep 8, 2016
107
yield from walk_packages(path, info.name+'.', onerror)
Apr 21, 2006
Apr 21, 2006
108
109
110
def iter_modules(path=None, prefix=''):
Sep 8, 2016
Sep 8, 2016
111
"""Yields ModuleInfo for all submodules on path,
Aug 11, 2006
Aug 11, 2006
112
or, if path is None, all top-level modules on sys.path.
113
114
'path' should be either None or a list of paths to look for
115
modules in.
116
117
'prefix' is a string to output on the front of every module name
118
on output.
119
"""
Apr 21, 2006
Apr 21, 2006
120
if path is None:
121
importers = iter_importers()
122
else:
123
importers = map(get_importer, path)
124
125
yielded = {}
126
for i in importers:
127
for name, ispkg in iter_importer_modules(i, prefix):
128
if name not in yielded:
129
yielded[name] = 1
Sep 8, 2016
Sep 8, 2016
130
yield ModuleInfo(i, name, ispkg)
Apr 21, 2006
Apr 21, 2006
131
132
Jun 5, 2013
Jun 5, 2013
133
@simplegeneric
Apr 21, 2006
Apr 21, 2006
134
def iter_importer_modules(importer, prefix=''):
May 27, 2006
May 27, 2006
135
if not hasattr(importer, 'iter_modules'):
Apr 21, 2006
Apr 21, 2006
136
return []
137
return importer.iter_modules(prefix)
138
139
Jul 15, 2012
Jul 15, 2012
140
# Implement a file walker for the normal importlib path hook
141
def _iter_file_finder_modules(importer, prefix=''):
142
if importer.path is None or not os.path.isdir(importer.path):
143
return
144
145
yielded = {}
146
import inspect
147
try:
148
filenames = os.listdir(importer.path)
149
except OSError:
150
# ignore unreadable directories like import does
151
filenames = []
152
filenames.sort() # handle packages before same-named modules
153
154
for fn in filenames:
155
modname = inspect.getmodulename(fn)
156
if modname=='__init__' or modname in yielded:
157
continue
158
159
path = os.path.join(importer.path, fn)
160
ispkg = False
161
162
if not modname and os.path.isdir(path) and '.' not in fn:
163
modname = fn
164
try:
165
dircontents = os.listdir(path)
166
except OSError:
167
# ignore unreadable directories like import does
168
dircontents = []
169
for fn in dircontents:
170
subname = inspect.getmodulename(fn)
171
if subname=='__init__':
172
ispkg = True
173
break
174
else:
175
continue # not a package
176
177
if modname and '.' not in modname:
178
yielded[modname] = 1
179
yield prefix + modname, ispkg
180
181
iter_importer_modules.register(
182
importlib.machinery.FileFinder, _iter_file_finder_modules)
Apr 21, 2006
Apr 21, 2006
183
Jun 16, 2013
Jun 16, 2013
184
185
def _import_imp():
186
global imp
187
with warnings.catch_warnings():
Oct 16, 2015
Oct 16, 2015
188
warnings.simplefilter('ignore', DeprecationWarning)
Jun 16, 2013
Jun 16, 2013
189
imp = importlib.import_module('imp')
190
Apr 21, 2006
Apr 21, 2006
191
class ImpImporter:
Jul 8, 2016
Jul 8, 2016
192
"""PEP 302 Finder that wraps Python's "classic" import algorithm
Apr 21, 2006
Apr 21, 2006
193
Jul 8, 2016
Jul 8, 2016
194
ImpImporter(dirname) produces a PEP 302 finder that searches that
195
directory. ImpImporter(None) produces a PEP 302 finder that searches
Apr 21, 2006
Apr 21, 2006
196
the current sys.path, plus any modules that are frozen or built-in.
197
198
Note that ImpImporter does not currently support being used by placement
199
on sys.meta_path.
200
"""
201
202
def __init__(self, path=None):
Jun 16, 2013
Jun 16, 2013
203
global imp
204
warnings.warn("This emulation is deprecated, use 'importlib' instead",
Jul 15, 2012
Jul 15, 2012
205
DeprecationWarning)
Jun 16, 2013
Jun 16, 2013
206
_import_imp()
Apr 21, 2006
Apr 21, 2006
207
self.path = path
208
209
def find_module(self, fullname, path=None):
210
# Note: we ignore 'path' argument since it is only used via meta_path
211
subname = fullname.split(".")[-1]
212
if subname != fullname and self.path is None:
213
return None
214
if self.path is None:
215
path = None
216
else:
217
path = [os.path.realpath(self.path)]
218
try:
219
file, filename, etc = imp.find_module(subname, path)
220
except ImportError:
221
return None
222
return ImpLoader(fullname, file, filename, etc)
223
224
def iter_modules(self, prefix=''):
225
if self.path is None or not os.path.isdir(self.path):
226
return
227
228
yielded = {}
229
import inspect
Oct 6, 2011
Oct 6, 2011
230
try:
231
filenames = os.listdir(self.path)
232
except OSError:
233
# ignore unreadable directories like import does
234
filenames = []
Apr 21, 2006
Apr 21, 2006
235
filenames.sort() # handle packages before same-named modules
236
237
for fn in filenames:
238
modname = inspect.getmodulename(fn)
239
if modname=='__init__' or modname in yielded:
240
continue
241
242
path = os.path.join(self.path, fn)
243
ispkg = False
244
245
if not modname and os.path.isdir(path) and '.' not in fn:
246
modname = fn
Oct 6, 2011
Oct 6, 2011
247
try:
248
dircontents = os.listdir(path)
249
except OSError:
250
# ignore unreadable directories like import does
251
dircontents = []
252
for fn in dircontents:
Apr 21, 2006
Apr 21, 2006
253
subname = inspect.getmodulename(fn)
254
if subname=='__init__':
255
ispkg = True
256
break
257
else:
258
continue # not a package
259
260
if modname and '.' not in modname:
261
yielded[modname] = 1
262
yield prefix + modname, ispkg
263
264
265
class ImpLoader:
266
"""PEP 302 Loader that wraps Python's "classic" import algorithm
267
"""
268
code = source = None
269
270
def __init__(self, fullname, file, filename, etc):
Jun 16, 2013
Jun 16, 2013
271
warnings.warn("This emulation is deprecated, use 'importlib' instead",
272
DeprecationWarning)
273
_import_imp()
Apr 21, 2006
Apr 21, 2006
274
self.file = file
275
self.filename = filename
276
self.fullname = fullname
277
self.etc = etc
278
279
def load_module(self, fullname):
280
self._reopen()
281
try:
282
mod = imp.load_module(fullname, self.file, self.filename, self.etc)
283
finally:
284
if self.file:
285
self.file.close()
286
# Note: we don't set __loader__ because we want the module to look
287
# normal; i.e. this is just a wrapper for standard import machinery
288
return mod
289
290
def get_data(self, pathname):
Oct 29, 2010
Oct 29, 2010
291
with open(pathname, "rb") as file:
292
return file.read()
Apr 21, 2006
Apr 21, 2006
293
294
def _reopen(self):
295
if self.file and self.file.closed:
Aug 11, 2006
Aug 11, 2006
296
mod_type = self.etc[2]
Apr 21, 2006
Apr 21, 2006
297
if mod_type==imp.PY_SOURCE:
May 4, 2011
May 4, 2011
298
self.file = open(self.filename, 'r')
Apr 21, 2006
Apr 21, 2006
299
elif mod_type in (imp.PY_COMPILED, imp.C_EXTENSION):
300
self.file = open(self.filename, 'rb')
301
302
def _fix_name(self, fullname):
303
if fullname is None:
304
fullname = self.fullname
305
elif fullname != self.fullname:
306
raise ImportError("Loader for module %s cannot handle "
307
"module %s" % (self.fullname, fullname))
308
return fullname
309
310
def is_package(self, fullname):
311
fullname = self._fix_name(fullname)
312
return self.etc[2]==imp.PKG_DIRECTORY
313
314
def get_code(self, fullname=None):
315
fullname = self._fix_name(fullname)
316
if self.code is None:
317
mod_type = self.etc[2]
318
if mod_type==imp.PY_SOURCE:
319
source = self.get_source(fullname)
320
self.code = compile(source, self.filename, 'exec')
321
elif mod_type==imp.PY_COMPILED:
322
self._reopen()
323
try:
324
self.code = read_code(self.file)
325
finally:
326
self.file.close()
327
elif mod_type==imp.PKG_DIRECTORY:
328
self.code = self._get_delegate().get_code()
329
return self.code
330
331
def get_source(self, fullname=None):
332
fullname = self._fix_name(fullname)
333
if self.source is None:
334
mod_type = self.etc[2]
335
if mod_type==imp.PY_SOURCE:
336
self._reopen()
337
try:
338
self.source = self.file.read()
339
finally:
340
self.file.close()
341
elif mod_type==imp.PY_COMPILED:
342
if os.path.exists(self.filename[:-1]):
Feb 12, 2013
Feb 12, 2013
343
with open(self.filename[:-1], 'r') as f:
344
self.source = f.read()
Apr 21, 2006
Apr 21, 2006
345
elif mod_type==imp.PKG_DIRECTORY:
346
self.source = self._get_delegate().get_source()
347
return self.source
348
349
def _get_delegate(self):
Jan 4, 2014
Jan 4, 2014
350
finder = ImpImporter(self.filename)
351
spec = _get_spec(finder, '__init__')
352
return spec.loader
Apr 21, 2006
Apr 21, 2006
353
354
def get_filename(self, fullname=None):
355
fullname = self._fix_name(fullname)
356
mod_type = self.etc[2]
Sep 17, 2011
Sep 17, 2011
357
if mod_type==imp.PKG_DIRECTORY:
Apr 21, 2006
Apr 21, 2006
358
return self._get_delegate().get_filename()
Sep 17, 2011
Sep 17, 2011
359
elif mod_type in (imp.PY_SOURCE, imp.PY_COMPILED, imp.C_EXTENSION):
Apr 21, 2006
Apr 21, 2006
360
return self.filename
361
return None
362
363
364
try:
365
import zipimport
366
from zipimport import zipimporter
367
368
def iter_zipimport_modules(importer, prefix=''):
Jul 5, 2009
Jul 5, 2009
369
dirlist = sorted(zipimport._zip_directory_cache[importer.archive])
Apr 21, 2006
Apr 21, 2006
370
_prefix = importer.prefix
371
plen = len(_prefix)
372
yielded = {}
373
import inspect
374
for fn in dirlist:
375
if not fn.startswith(_prefix):
376
continue
377
378
fn = fn[plen:].split(os.sep)
379
380
if len(fn)==2 and fn[1].startswith('__init__.py'):
381
if fn[0] not in yielded:
382
yielded[fn[0]] = 1
Jun 12, 2016
Jun 12, 2016
383
yield prefix + fn[0], True
Apr 21, 2006
Apr 21, 2006
384
385
if len(fn)!=1:
386
continue
387
388
modname = inspect.getmodulename(fn[0])
389
if modname=='__init__':
390
continue
391
392
if modname and '.' not in modname and modname not in yielded:
393
yielded[modname] = 1
394
yield prefix + modname, False
395
396
iter_importer_modules.register(zipimporter, iter_zipimport_modules)
397
398
except ImportError:
399
pass
400
401
402
def get_importer(path_item):
Sep 6, 2016
Sep 6, 2016
403
"""Retrieve a finder for the given path item
Apr 21, 2006
Apr 21, 2006
404
Jul 8, 2016
Jul 8, 2016
405
The returned finder is cached in sys.path_importer_cache
Apr 21, 2006
Apr 21, 2006
406
if it was newly created by a path hook.
407
408
The cache (or part of it) can be cleared manually if a
409
rescan of sys.path_hooks is necessary.
410
"""
411
try:
412
importer = sys.path_importer_cache[path_item]
413
except KeyError:
414
for path_hook in sys.path_hooks:
415
try:
416
importer = path_hook(path_item)
Apr 26, 2012
Apr 26, 2012
417
sys.path_importer_cache.setdefault(path_item, importer)
Apr 21, 2006
Apr 21, 2006
418
break
419
except ImportError:
420
pass
421
else:
Jul 15, 2012
Jul 15, 2012
422
importer = None
Apr 21, 2006
Apr 21, 2006
423
return importer
424
425
426
def iter_importers(fullname=""):
Sep 6, 2016
Sep 6, 2016
427
"""Yield finders for the given module name
Apr 21, 2006
Apr 21, 2006
428
Jul 8, 2016
Jul 8, 2016
429
If fullname contains a '.', the finders will be for the package
Jul 15, 2012
Jul 15, 2012
430
containing fullname, otherwise they will be all registered top level
Jul 8, 2016
Jul 8, 2016
431
finders (i.e. those on both sys.meta_path and sys.path_hooks).
Apr 21, 2006
Apr 21, 2006
432
Jul 15, 2012
Jul 15, 2012
433
If the named module is in a package, that package is imported as a side
434
effect of invoking this function.
Apr 21, 2006
Apr 21, 2006
435
Jul 8, 2016
Jul 8, 2016
436
If no module name is specified, all top level finders are produced.
Apr 21, 2006
Apr 21, 2006
437
"""
438
if fullname.startswith('.'):
Jul 15, 2012
Jul 15, 2012
439
msg = "Relative module name {!r} not supported".format(fullname)
440
raise ImportError(msg)
Apr 21, 2006
Apr 21, 2006
441
if '.' in fullname:
442
# Get the containing package's __path__
Jul 15, 2012
Jul 15, 2012
443
pkg_name = fullname.rpartition(".")[0]
Apr 14, 2013
Apr 14, 2013
444
pkg = importlib.import_module(pkg_name)
445
path = getattr(pkg, '__path__', None)
Jul 15, 2012
Jul 15, 2012
446
if path is None:
447
return
Apr 21, 2006
Apr 21, 2006
448
else:
Oct 7, 2012
Oct 7, 2012
449
yield from sys.meta_path
Apr 21, 2006
Apr 21, 2006
450
path = sys.path
451
for item in path:
452
yield get_importer(item)
453
Nov 22, 2013
Nov 22, 2013
454
Apr 21, 2006
Apr 21, 2006
455
def get_loader(module_or_name):
Sep 6, 2016
Sep 6, 2016
456
"""Get a "loader" object for module_or_name
Apr 21, 2006
Apr 21, 2006
457
Jul 15, 2012
Jul 15, 2012
458
Returns None if the module cannot be found or imported.
Apr 21, 2006
Apr 21, 2006
459
If the named module is not already imported, its containing package
460
(if any) is imported, in order to establish the package __path__.
461
"""
462
if module_or_name in sys.modules:
463
module_or_name = sys.modules[module_or_name]
May 23, 2014
May 23, 2014
464
if module_or_name is None:
465
return None
Apr 21, 2006
Apr 21, 2006
466
if isinstance(module_or_name, ModuleType):
467
module = module_or_name
May 27, 2006
May 27, 2006
468
loader = getattr(module, '__loader__', None)
Apr 21, 2006
Apr 21, 2006
469
if loader is not None:
470
return loader
Apr 19, 2014
Apr 19, 2014
471
if getattr(module, '__spec__', None) is None:
472
return None
Apr 21, 2006
Apr 21, 2006
473
fullname = module.__name__
474
else:
475
fullname = module_or_name
476
return find_loader(fullname)
477
Jul 15, 2012
Jul 15, 2012
478
Apr 21, 2006
Apr 21, 2006
479
def find_loader(fullname):
Sep 6, 2016
Sep 6, 2016
480
"""Find a "loader" object for fullname
Apr 21, 2006
Apr 21, 2006
481
Mar 4, 2014
Mar 4, 2014
482
This is a backwards compatibility wrapper around
483
importlib.util.find_spec that converts most failures to ImportError
484
and only returns the loader rather than the full spec
Apr 21, 2006
Apr 21, 2006
485
"""
Jul 15, 2012
Jul 15, 2012
486
if fullname.startswith('.'):
487
msg = "Relative module name {!r} not supported".format(fullname)
488
raise ImportError(msg)
489
try:
Mar 4, 2014
Mar 4, 2014
490
spec = importlib.util.find_spec(fullname)
Jul 15, 2012
Jul 15, 2012
491
except (ImportError, AttributeError, TypeError, ValueError) as ex:
492
# This hack fixes an impedance mismatch between pkgutil and
Dec 18, 2012
Dec 18, 2012
493
# importlib, where the latter raises other errors for cases where
Dec 19, 2012
Dec 19, 2012
494
# pkgutil previously raised ImportError
Jul 15, 2012
Jul 15, 2012
495
msg = "Error while finding loader for {!r} ({}: {})"
496
raise ImportError(msg.format(fullname, type(ex), ex)) from ex
May 23, 2014
May 23, 2014
497
return spec.loader if spec is not None else None
Apr 21, 2006
Apr 21, 2006
498
499
500
def extend_path(path, name):
501
"""Extend a package's path.
502
503
Intended use is to place the following code in a package's __init__.py:
504
505
from pkgutil import extend_path
506
__path__ = extend_path(__path__, __name__)
507
508
This will add to the package's __path__ all subdirectories of
509
directories on sys.path named after the package. This is useful
510
if one wants to distribute different parts of a single logical
511
package as multiple directories.
512
513
It also looks for *.pkg files beginning where * matches the name
514
argument. This feature is similar to *.pth files (see site.py),
515
except that it doesn't special-case lines starting with 'import'.
516
A *.pkg file is trusted at face value: apart from checking for
517
duplicates, all entries found in a *.pkg file are added to the
518
path, regardless of whether they are exist the filesystem. (This
519
is a feature.)
520
521
If the input path is not a list (as is the case for frozen
522
packages) it is returned unchanged. The input path is not
523
modified; an extended copy is returned. Items are only appended
524
to the copy at the end.
525
526
It is assumed that sys.path is a sequence. Items of sys.path that
527
are not (unicode or 8-bit) strings referring to existing
528
directories are ignored. Unicode items of sys.path that cause
529
errors when used as filenames may cause this function to raise an
530
exception (in line with os.path.isdir() behavior).
531
"""
532
533
if not isinstance(path, list):
534
# This could happen e.g. when this is called from inside a
535
# frozen package. Return the path unchanged in that case.
536
return path
537
Aug 16, 2007
Aug 16, 2007
538
sname_pkg = name + ".pkg"
539
540
path = path[:] # Start with a copy of the existing path
541
Jul 9, 2012
Jul 9, 2012
542
parent_package, _, final_name = name.rpartition('.')
543
if parent_package:
544
try:
545
search_path = sys.modules[parent_package].__path__
546
except (KeyError, AttributeError):
547
# We can't do anything: find_loader() returns None when
548
# passed a dotted name.
549
return path
550
else:
551
search_path = sys.path
552
553
for dir in search_path:
May 25, 2012
May 25, 2012
554
if not isinstance(dir, str):
May 25, 2012
May 25, 2012
556
557
finder = get_importer(dir)
558
if finder is not None:
Jan 7, 2014
Jan 7, 2014
559
portions = []
560
if hasattr(finder, 'find_spec'):
561
spec = finder.find_spec(final_name)
562
if spec is not None:
563
portions = spec.submodule_search_locations or []
May 25, 2012
May 25, 2012
564
# Is this finder PEP 420 compliant?
Jan 7, 2014
Jan 7, 2014
565
elif hasattr(finder, 'find_loader'):
566
_, portions = finder.find_loader(final_name)
May 25, 2012
May 25, 2012
567
568
for portion in portions:
569
# XXX This may still add duplicate entries to path on
570
# case-insensitive filesystems
571
if portion not in path:
572
path.append(portion)
573
574
# XXX Is this the right thing for subpackages like zope.app?
575
# It looks for a file named "zope.app.pkg"
576
pkgfile = os.path.join(dir, sname_pkg)
577
if os.path.isfile(pkgfile):
578
try:
579
f = open(pkgfile)
Dec 25, 2012
Dec 25, 2012
580
except OSError as msg:
581
sys.stderr.write("Can't open %s: %s\n" %
582
(pkgfile, msg))
583
else:
Feb 12, 2013
Feb 12, 2013
584
with f:
585
for line in f:
586
line = line.rstrip('\n')
587
if not line or line.startswith('#'):
588
continue
589
path.append(line) # Don't check for existence!
Apr 19, 2008
Apr 19, 2008
592
Nov 22, 2013
Nov 22, 2013
593
Apr 19, 2008
Apr 19, 2008
594
def get_data(package, resource):
595
"""Get a resource from a package.
596
597
This is a wrapper round the PEP 302 loader get_data API. The package
598
argument should be the name of a package, in standard module format
599
(foo.bar). The resource argument should be in the form of a relative
600
filename, using '/' as the path separator. The parent directory name '..'
601
is not allowed, and nor is a rooted name (starting with a '/').
602
603
The function returns a binary string, which is the contents of the
604
specified resource.
605
606
For packages located in the filesystem, which have already been imported,
607
this is the rough equivalent of
608
609
d = os.path.dirname(sys.modules[package].__file__)
610
data = open(os.path.join(d, resource), 'rb').read()
611
612
If the package cannot be located or loaded, or it uses a PEP 302 loader
613
which does not support get_data(), then None is returned.
614
"""
615
Jan 25, 2014
Jan 25, 2014
616
spec = importlib.util.find_spec(package)
Nov 22, 2013
Nov 22, 2013
617
if spec is None:
618
return None
619
loader = spec.loader
Apr 19, 2008
Apr 19, 2008
620
if loader is None or not hasattr(loader, 'get_data'):
621
return None
Nov 22, 2013
Nov 22, 2013
622
# XXX needs test
623
mod = (sys.modules.get(package) or
May 30, 2014
May 30, 2014
624
importlib._bootstrap._load(spec))
Apr 19, 2008
Apr 19, 2008
625
if mod is None or not hasattr(mod, '__file__'):
626
return None
627
628
# Modify the resource name to be compatible with the loader.get_data
629
# signature - an os.path format "filename" starting with the dirname of
630
# the package's __file__
631
parts = resource.split('/')
632
parts.insert(0, os.path.dirname(mod.__file__))
633
resource_name = os.path.join(*parts)
634
return loader.get_data(resource_name)