root / env / lib / python2.7 / site-packages / distribute-0.6.19-py2.7.egg / setuptools / depends.py @ 1a305335
History | View | Annotate | Download (6.06 KB)
1 |
from __future__ import generators |
---|---|
2 |
import sys, imp, marshal |
3 |
from imp import PKG_DIRECTORY, PY_COMPILED, PY_SOURCE, PY_FROZEN |
4 |
from distutils.version import StrictVersion, LooseVersion |
5 |
|
6 |
__all__ = [ |
7 |
'Require', 'find_module', 'get_module_constant', 'extract_constant' |
8 |
] |
9 |
|
10 |
class Require: |
11 |
"""A prerequisite to building or installing a distribution"""
|
12 |
|
13 |
def __init__(self,name,requested_version,module,homepage='', |
14 |
attribute=None,format=None |
15 |
): |
16 |
|
17 |
if format is None and requested_version is not None: |
18 |
format = StrictVersion |
19 |
|
20 |
if format is not None: |
21 |
requested_version = format(requested_version) |
22 |
if attribute is None: |
23 |
attribute = '__version__'
|
24 |
|
25 |
self.__dict__.update(locals()) |
26 |
del self.self |
27 |
|
28 |
|
29 |
def full_name(self): |
30 |
"""Return full package/distribution name, w/version"""
|
31 |
if self.requested_version is not None: |
32 |
return '%s-%s' % (self.name,self.requested_version) |
33 |
return self.name |
34 |
|
35 |
|
36 |
def version_ok(self,version): |
37 |
"""Is 'version' sufficiently up-to-date?"""
|
38 |
return self.attribute is None or self.format is None or \ |
39 |
str(version)<>"unknown" and version >= self.requested_version |
40 |
|
41 |
|
42 |
def get_version(self, paths=None, default="unknown"): |
43 |
|
44 |
"""Get version number of installed module, 'None', or 'default'
|
45 |
|
46 |
Search 'paths' for module. If not found, return 'None'. If found,
|
47 |
return the extracted version attribute, or 'default' if no version
|
48 |
attribute was specified, or the value cannot be determined without
|
49 |
importing the module. The version is formatted according to the
|
50 |
requirement's version format (if any), unless it is 'None' or the
|
51 |
supplied 'default'.
|
52 |
"""
|
53 |
|
54 |
if self.attribute is None: |
55 |
try:
|
56 |
f,p,i = find_module(self.module,paths)
|
57 |
if f: f.close()
|
58 |
return default
|
59 |
except ImportError: |
60 |
return None |
61 |
|
62 |
v = get_module_constant(self.module,self.attribute,default,paths) |
63 |
|
64 |
if v is not None and v is not default and self.format is not None: |
65 |
return self.format(v) |
66 |
|
67 |
return v
|
68 |
|
69 |
|
70 |
def is_present(self,paths=None): |
71 |
"""Return true if dependency is present on 'paths'"""
|
72 |
return self.get_version(paths) is not None |
73 |
|
74 |
|
75 |
def is_current(self,paths=None): |
76 |
"""Return true if dependency is present and up-to-date on 'paths'"""
|
77 |
version = self.get_version(paths)
|
78 |
if version is None: |
79 |
return False |
80 |
return self.version_ok(version) |
81 |
|
82 |
|
83 |
def _iter_code(code): |
84 |
|
85 |
"""Yield '(op,arg)' pair for each operation in code object 'code'"""
|
86 |
|
87 |
from array import array |
88 |
from dis import HAVE_ARGUMENT, EXTENDED_ARG |
89 |
|
90 |
bytes = array('b',code.co_code)
|
91 |
eof = len(code.co_code)
|
92 |
|
93 |
ptr = 0
|
94 |
extended_arg = 0
|
95 |
|
96 |
while ptr<eof:
|
97 |
|
98 |
op = bytes[ptr]
|
99 |
|
100 |
if op>=HAVE_ARGUMENT:
|
101 |
|
102 |
arg = bytes[ptr+1] + bytes[ptr+2]*256 + extended_arg |
103 |
ptr += 3
|
104 |
|
105 |
if op==EXTENDED_ARG:
|
106 |
extended_arg = arg * 65536L
|
107 |
continue
|
108 |
|
109 |
else:
|
110 |
arg = None
|
111 |
ptr += 1
|
112 |
|
113 |
yield op,arg
|
114 |
|
115 |
|
116 |
|
117 |
|
118 |
|
119 |
|
120 |
|
121 |
|
122 |
|
123 |
|
124 |
def find_module(module, paths=None): |
125 |
"""Just like 'imp.find_module()', but with package support"""
|
126 |
|
127 |
parts = module.split('.')
|
128 |
|
129 |
while parts:
|
130 |
part = parts.pop(0)
|
131 |
f, path, (suffix,mode,kind) = info = imp.find_module(part, paths) |
132 |
|
133 |
if kind==PKG_DIRECTORY:
|
134 |
parts = parts or ['__init__'] |
135 |
paths = [path] |
136 |
|
137 |
elif parts:
|
138 |
raise ImportError("Can't find %r in %s" % (parts,module)) |
139 |
|
140 |
return info
|
141 |
|
142 |
|
143 |
|
144 |
|
145 |
|
146 |
|
147 |
|
148 |
|
149 |
|
150 |
|
151 |
|
152 |
|
153 |
|
154 |
|
155 |
|
156 |
|
157 |
|
158 |
|
159 |
|
160 |
|
161 |
|
162 |
|
163 |
|
164 |
|
165 |
def get_module_constant(module, symbol, default=-1, paths=None): |
166 |
|
167 |
"""Find 'module' by searching 'paths', and extract 'symbol'
|
168 |
|
169 |
Return 'None' if 'module' does not exist on 'paths', or it does not define
|
170 |
'symbol'. If the module defines 'symbol' as a constant, return the
|
171 |
constant. Otherwise, return 'default'."""
|
172 |
|
173 |
try:
|
174 |
f, path, (suffix,mode,kind) = find_module(module,paths) |
175 |
except ImportError: |
176 |
# Module doesn't exist
|
177 |
return None |
178 |
|
179 |
try:
|
180 |
if kind==PY_COMPILED:
|
181 |
f.read(8) # skip magic & date |
182 |
code = marshal.load(f) |
183 |
elif kind==PY_FROZEN:
|
184 |
code = imp.get_frozen_object(module) |
185 |
elif kind==PY_SOURCE:
|
186 |
code = compile(f.read(), path, 'exec') |
187 |
else:
|
188 |
# Not something we can parse; we'll have to import it. :(
|
189 |
if module not in sys.modules: |
190 |
imp.load_module(module,f,path,(suffix,mode,kind)) |
191 |
return getattr(sys.modules[module],symbol,None) |
192 |
|
193 |
finally:
|
194 |
if f:
|
195 |
f.close() |
196 |
|
197 |
return extract_constant(code,symbol,default)
|
198 |
|
199 |
|
200 |
|
201 |
|
202 |
|
203 |
|
204 |
|
205 |
|
206 |
def extract_constant(code,symbol,default=-1): |
207 |
"""Extract the constant value of 'symbol' from 'code'
|
208 |
|
209 |
If the name 'symbol' is bound to a constant value by the Python code
|
210 |
object 'code', return that value. If 'symbol' is bound to an expression,
|
211 |
return 'default'. Otherwise, return 'None'.
|
212 |
|
213 |
Return value is based on the first assignment to 'symbol'. 'symbol' must
|
214 |
be a global, or at least a non-"fast" local in the code block. That is,
|
215 |
only 'STORE_NAME' and 'STORE_GLOBAL' opcodes are checked, and 'symbol'
|
216 |
must be present in 'code.co_names'.
|
217 |
"""
|
218 |
|
219 |
if symbol not in code.co_names: |
220 |
# name's not there, can't possibly be an assigment
|
221 |
return None |
222 |
|
223 |
name_idx = list(code.co_names).index(symbol)
|
224 |
|
225 |
STORE_NAME = 90
|
226 |
STORE_GLOBAL = 97
|
227 |
LOAD_CONST = 100
|
228 |
|
229 |
const = default |
230 |
|
231 |
for op, arg in _iter_code(code): |
232 |
|
233 |
if op==LOAD_CONST:
|
234 |
const = code.co_consts[arg] |
235 |
elif arg==name_idx and (op==STORE_NAME or op==STORE_GLOBAL): |
236 |
return const
|
237 |
else:
|
238 |
const = default |
239 |
|
240 |
if sys.platform.startswith('java') or sys.platform == 'cli': |
241 |
# XXX it'd be better to test assertions about bytecode instead...
|
242 |
del extract_constant, get_module_constant
|
243 |
__all__.remove('extract_constant')
|
244 |
__all__.remove('get_module_constant')
|
245 |
|
246 |
|