comparison venv/lib/python2.7/site-packages/setuptools/depends.py @ 0:d67268158946 draft

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