/
util.py
147 lines (118 loc) · 4.01 KB
/
util.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# Filter DeprecationWarnings until the code has been revised
import warnings
warnings.filterwarnings("ignore", "the imp module is deprecated in")
warnings.filterwarnings("ignore", "imp_walk will be removed in a future")
import os
import imp
import sys
import re
import marshal
import warnings
import inspect
try:
unicode
except NameError:
unicode = str
from ._compat import StringIO, BytesIO, get_instructions, _READ_MODE
def imp_find_module(name, path=None):
"""
same as imp.find_module, but handles dotted names
"""
names = name.split('.')
if path is not None:
if isinstance(path, (str, unicode)):
path = [os.path.realpath(path)]
for name in names:
result = imp.find_module(name, path)
if result[0] is not None:
result[0].close()
path = [result[1]]
return result
def _check_importer_for_path(name, path_item):
try:
importer = sys.path_importer_cache[path_item]
except KeyError:
for path_hook in sys.path_hooks:
try:
importer = path_hook(path_item)
break
except ImportError:
pass
else:
importer = None
sys.path_importer_cache.setdefault(path_item, importer)
if importer is None:
try:
return imp.find_module(name, [path_item])
except ImportError:
return None
return importer.find_module(name)
def imp_walk(name):
"""
yields namepart, tuple_or_importer for each path item
raise ImportError if a name can not be found.
"""
warnings.warn(
"imp_walk will be removed in a future version",
DeprecationWarning)
if name in sys.builtin_module_names:
yield name, (None, None, ("", "", imp.C_BUILTIN))
return
paths = sys.path
res = None
for namepart in name.split('.'):
for path_item in paths:
res = _check_importer_for_path(namepart, path_item)
if hasattr(res, 'load_module'):
if res.path.endswith('.py') or res.path.endswith('.pyw'):
fp = StringIO(res.get_source(namepart))
res = (fp, res.path, ('.py', _READ_MODE, imp.PY_SOURCE))
elif res.path.endswith('.pyc') or res.path.endswith('.pyo'):
co = res.get_code(namepart)
fp = BytesIO(
imp.get_magic() + b'\0\0\0\0' + marshal.dumps(co))
res = (fp, res.path, ('.pyc', 'rb', imp.PY_COMPILED))
else:
res = (
None,
res.path,
(
os.path.splitext(res.path)[-1],
'rb',
imp.C_EXTENSION
)
)
break
elif isinstance(res, tuple):
break
else:
break
yield namepart, res
paths = [os.path.join(path_item, namepart)]
else:
return
raise ImportError('No module named %s' % (name,))
cookie_re = re.compile(br"coding[:=]\s*([-\w.]+)")
if sys.version_info[0] == 2:
default_encoding = 'ascii'
else:
default_encoding = 'utf-8'
def guess_encoding(fp):
for i in range(2):
ln = fp.readline()
m = cookie_re.search(ln)
if m is not None:
return m.group(1).decode('ascii')
return default_encoding
def iterate_instructions(code_object):
"""Delivers the byte-code instructions as a continuous stream.
Yields `dis.Instruction`. After each code-block (`co_code`), `None` is
yielded to mark the end of the block and to interrupt the steam.
"""
yield from get_instructions(code_object)
yield None
# For each constant in this code object that is itself a code object,
# parse this constant in the same manner.
for constant in code_object.co_consts:
if inspect.iscode(constant):
yield from iterate_instructions(constant)