]> git.rkrishnan.org Git - tahoe-lafs/zfec.git/blob - zfec/setuptools-0.6c15dev.egg/setuptools/depends.py
5fdf2d7e57f96b96f89a3a5136fbada3a607b416
[tahoe-lafs/zfec.git] / zfec / setuptools-0.6c15dev.egg / setuptools / depends.py
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