OSDN Git Service

45e7052d8d8561a946f782a67dc6f83b6ad6ab99
[stux/ultron.git] / venv / Lib / site-packages / setuptools / depends.py
1 import sys
2 import imp
3 import marshal
4 from distutils.version import StrictVersion
5 from imp import PKG_DIRECTORY, PY_COMPILED, PY_SOURCE, PY_FROZEN
6
7 from .py33compat import Bytecode
8
9
10 __all__ = [
11     'Require', 'find_module', 'get_module_constant', 'extract_constant'
12 ]
13
14
15 class Require:
16     """A prerequisite to building or installing a distribution"""
17
18     def __init__(self, name, requested_version, module, homepage='',
19             attribute=None, format=None):
20
21         if format is None and requested_version is not None:
22             format = StrictVersion
23
24         if format is not None:
25             requested_version = format(requested_version)
26             if attribute is None:
27                 attribute = '__version__'
28
29         self.__dict__.update(locals())
30         del self.self
31
32     def full_name(self):
33         """Return full package/distribution name, w/version"""
34         if self.requested_version is not None:
35             return '%s-%s' % (self.name, self.requested_version)
36         return self.name
37
38     def version_ok(self, version):
39         """Is 'version' sufficiently up-to-date?"""
40         return self.attribute is None or self.format is None or \
41             str(version) != "unknown" and version >= self.requested_version
42
43     def get_version(self, paths=None, default="unknown"):
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:
58                     f.close()
59                 return default
60             except ImportError:
61                 return None
62
63         v = get_module_constant(self.module, self.attribute, default, paths)
64
65         if v is not None and v is not default and self.format is not None:
66             return self.format(v)
67
68         return v
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     def is_current(self, paths=None):
75         """Return true if dependency is present and up-to-date on 'paths'"""
76         version = self.get_version(paths)
77         if version is None:
78             return False
79         return self.version_ok(version)
80
81
82 def find_module(module, paths=None):
83     """Just like 'imp.find_module()', but with package support"""
84
85     parts = module.split('.')
86
87     while parts:
88         part = parts.pop(0)
89         f, path, (suffix, mode, kind) = info = imp.find_module(part, paths)
90
91         if kind == PKG_DIRECTORY:
92             parts = parts or ['__init__']
93             paths = [path]
94
95         elif parts:
96             raise ImportError("Can't find %r in %s" % (parts, module))
97
98     return info
99
100
101 def get_module_constant(module, symbol, default=-1, paths=None):
102     """Find 'module' by searching 'paths', and extract 'symbol'
103
104     Return 'None' if 'module' does not exist on 'paths', or it does not define
105     'symbol'.  If the module defines 'symbol' as a constant, return the
106     constant.  Otherwise, return 'default'."""
107
108     try:
109         f, path, (suffix, mode, kind) = find_module(module, paths)
110     except ImportError:
111         # Module doesn't exist
112         return None
113
114     try:
115         if kind == PY_COMPILED:
116             f.read(8)  # skip magic & date
117             code = marshal.load(f)
118         elif kind == PY_FROZEN:
119             code = imp.get_frozen_object(module)
120         elif kind == PY_SOURCE:
121             code = compile(f.read(), path, 'exec')
122         else:
123             # Not something we can parse; we'll have to import it.  :(
124             if module not in sys.modules:
125                 imp.load_module(module, f, path, (suffix, mode, kind))
126             return getattr(sys.modules[module], symbol, None)
127
128     finally:
129         if f:
130             f.close()
131
132     return extract_constant(code, symbol, default)
133
134
135 def extract_constant(code, symbol, default=-1):
136     """Extract the constant value of 'symbol' from 'code'
137
138     If the name 'symbol' is bound to a constant value by the Python code
139     object 'code', return that value.  If 'symbol' is bound to an expression,
140     return 'default'.  Otherwise, return 'None'.
141
142     Return value is based on the first assignment to 'symbol'.  'symbol' must
143     be a global, or at least a non-"fast" local in the code block.  That is,
144     only 'STORE_NAME' and 'STORE_GLOBAL' opcodes are checked, and 'symbol'
145     must be present in 'code.co_names'.
146     """
147     if symbol not in code.co_names:
148         # name's not there, can't possibly be an assignment
149         return None
150
151     name_idx = list(code.co_names).index(symbol)
152
153     STORE_NAME = 90
154     STORE_GLOBAL = 97
155     LOAD_CONST = 100
156
157     const = default
158
159     for byte_code in Bytecode(code):
160         op = byte_code.opcode
161         arg = byte_code.arg
162
163         if op == LOAD_CONST:
164             const = code.co_consts[arg]
165         elif arg == name_idx and (op == STORE_NAME or op == STORE_GLOBAL):
166             return const
167         else:
168             const = default
169
170
171 def _update_globals():
172     """
173     Patch the globals to remove the objects not available on some platforms.
174
175     XXX it'd be better to test assertions about bytecode instead.
176     """
177
178     if not sys.platform.startswith('java') and sys.platform != 'cli':
179         return
180     incompatible = 'extract_constant', 'get_module_constant'
181     for name in incompatible:
182         del globals()[name]
183         __all__.remove(name)
184
185
186 _update_globals()