|
9 | 9 | from .extern.packaging.version import Version |
10 | 10 |
|
11 | 11 |
|
12 | | -__all__ = ['Require', 'find_module', 'get_module_constant', 'extract_constant'] |
| 12 | +__all__ = ['Require', 'find_module'] |
13 | 13 |
|
14 | 14 |
|
15 | 15 | class Require: |
@@ -95,86 +95,73 @@ def empty(): |
95 | 95 | return contextlib.closing(f) |
96 | 96 |
|
97 | 97 |
|
98 | | -def get_module_constant(module, symbol, default=-1, paths=None): |
99 | | - """Find 'module' by searching 'paths', and extract 'symbol' |
100 | | -
|
101 | | - Return 'None' if 'module' does not exist on 'paths', or it does not define |
102 | | - 'symbol'. If the module defines 'symbol' as a constant, return the |
103 | | - constant. Otherwise, return 'default'.""" |
104 | | - |
105 | | - try: |
106 | | - f, path, (suffix, mode, kind) = info = find_module(module, paths) |
107 | | - except ImportError: |
108 | | - # Module doesn't exist |
109 | | - return None |
110 | | - |
111 | | - with maybe_close(f): |
112 | | - if kind == PY_COMPILED: |
113 | | - f.read(8) # skip magic & date |
114 | | - code = marshal.load(f) |
115 | | - elif kind == PY_FROZEN: |
116 | | - code = _imp.get_frozen_object(module, paths) |
117 | | - elif kind == PY_SOURCE: |
118 | | - code = compile(f.read(), path, 'exec') |
119 | | - else: |
120 | | - # Not something we can parse; we'll have to import it. :( |
121 | | - imported = _imp.get_module(module, paths, info) |
122 | | - return getattr(imported, symbol, None) |
123 | | - |
124 | | - return extract_constant(code, symbol, default) |
125 | | - |
126 | | - |
127 | | -def extract_constant(code, symbol, default=-1): |
128 | | - """Extract the constant value of 'symbol' from 'code' |
129 | | -
|
130 | | - If the name 'symbol' is bound to a constant value by the Python code |
131 | | - object 'code', return that value. If 'symbol' is bound to an expression, |
132 | | - return 'default'. Otherwise, return 'None'. |
133 | | -
|
134 | | - Return value is based on the first assignment to 'symbol'. 'symbol' must |
135 | | - be a global, or at least a non-"fast" local in the code block. That is, |
136 | | - only 'STORE_NAME' and 'STORE_GLOBAL' opcodes are checked, and 'symbol' |
137 | | - must be present in 'code.co_names'. |
138 | | - """ |
139 | | - if symbol not in code.co_names: |
140 | | - # name's not there, can't possibly be an assignment |
141 | | - return None |
142 | | - |
143 | | - name_idx = list(code.co_names).index(symbol) |
144 | | - |
145 | | - STORE_NAME = dis.opmap['STORE_NAME'] |
146 | | - STORE_GLOBAL = dis.opmap['STORE_GLOBAL'] |
147 | | - LOAD_CONST = dis.opmap['LOAD_CONST'] |
148 | | - |
149 | | - const = default |
150 | | - |
151 | | - for byte_code in dis.Bytecode(code): |
152 | | - op = byte_code.opcode |
153 | | - arg = byte_code.arg |
154 | | - |
155 | | - if op == LOAD_CONST: |
156 | | - const = code.co_consts[arg] |
157 | | - elif arg == name_idx and (op == STORE_NAME or op == STORE_GLOBAL): |
158 | | - return const |
159 | | - else: |
160 | | - const = default |
| 98 | +# Some objects are not available on some platforms. |
| 99 | +# XXX it'd be better to test assertions about bytecode instead. |
| 100 | +if not sys.platform.startswith('java') and sys.platform != 'cli': |
| 101 | + |
| 102 | + def get_module_constant(module, symbol, default=-1, paths=None): |
| 103 | + """Find 'module' by searching 'paths', and extract 'symbol' |
| 104 | +
|
| 105 | + Return 'None' if 'module' does not exist on 'paths', or it does not define |
| 106 | + 'symbol'. If the module defines 'symbol' as a constant, return the |
| 107 | + constant. Otherwise, return 'default'.""" |
| 108 | + |
| 109 | + try: |
| 110 | + f, path, (suffix, mode, kind) = info = find_module(module, paths) |
| 111 | + except ImportError: |
| 112 | + # Module doesn't exist |
| 113 | + return None |
| 114 | + |
| 115 | + with maybe_close(f): |
| 116 | + if kind == PY_COMPILED: |
| 117 | + f.read(8) # skip magic & date |
| 118 | + code = marshal.load(f) |
| 119 | + elif kind == PY_FROZEN: |
| 120 | + code = _imp.get_frozen_object(module, paths) |
| 121 | + elif kind == PY_SOURCE: |
| 122 | + code = compile(f.read(), path, 'exec') |
| 123 | + else: |
| 124 | + # Not something we can parse; we'll have to import it. :( |
| 125 | + imported = _imp.get_module(module, paths, info) |
| 126 | + return getattr(imported, symbol, None) |
| 127 | + |
| 128 | + return extract_constant(code, symbol, default) |
| 129 | + |
| 130 | + def extract_constant(code, symbol, default=-1): |
| 131 | + """Extract the constant value of 'symbol' from 'code' |
| 132 | +
|
| 133 | + If the name 'symbol' is bound to a constant value by the Python code |
| 134 | + object 'code', return that value. If 'symbol' is bound to an expression, |
| 135 | + return 'default'. Otherwise, return 'None'. |
| 136 | +
|
| 137 | + Return value is based on the first assignment to 'symbol'. 'symbol' must |
| 138 | + be a global, or at least a non-"fast" local in the code block. That is, |
| 139 | + only 'STORE_NAME' and 'STORE_GLOBAL' opcodes are checked, and 'symbol' |
| 140 | + must be present in 'code.co_names'. |
| 141 | + """ |
| 142 | + if symbol not in code.co_names: |
| 143 | + # name's not there, can't possibly be an assignment |
| 144 | + return None |
161 | 145 |
|
162 | | - return None |
| 146 | + name_idx = list(code.co_names).index(symbol) |
163 | 147 |
|
| 148 | + STORE_NAME = dis.opmap['STORE_NAME'] |
| 149 | + STORE_GLOBAL = dis.opmap['STORE_GLOBAL'] |
| 150 | + LOAD_CONST = dis.opmap['LOAD_CONST'] |
164 | 151 |
|
165 | | -def _update_globals(): |
166 | | - """ |
167 | | - Patch the globals to remove the objects not available on some platforms. |
| 152 | + const = default |
168 | 153 |
|
169 | | - XXX it'd be better to test assertions about bytecode instead. |
170 | | - """ |
| 154 | + for byte_code in dis.Bytecode(code): |
| 155 | + op = byte_code.opcode |
| 156 | + arg = byte_code.arg |
171 | 157 |
|
172 | | - if not sys.platform.startswith('java') and sys.platform != 'cli': |
173 | | - return |
174 | | - incompatible = 'extract_constant', 'get_module_constant' |
175 | | - for name in incompatible: |
176 | | - del globals()[name] |
177 | | - __all__.remove(name) |
| 158 | + if op == LOAD_CONST: |
| 159 | + const = code.co_consts[arg] |
| 160 | + elif arg == name_idx and (op == STORE_NAME or op == STORE_GLOBAL): |
| 161 | + return const |
| 162 | + else: |
| 163 | + const = default |
178 | 164 |
|
| 165 | + return None |
179 | 166 |
|
180 | | -_update_globals() |
| 167 | + __all__ += ['get_module_constant', 'extract_constant'] |
0 commit comments