Index: recipe_engine/third_party/setuptools/depends.py |
diff --git a/recipe_engine/third_party/setuptools/depends.py b/recipe_engine/third_party/setuptools/depends.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..e87ef3f39c703831d1399b64b3b410196625a2ca |
--- /dev/null |
+++ b/recipe_engine/third_party/setuptools/depends.py |
@@ -0,0 +1,215 @@ |
+import sys |
+import imp |
+import marshal |
+from imp import PKG_DIRECTORY, PY_COMPILED, PY_SOURCE, PY_FROZEN |
+from distutils.version import StrictVersion |
+from setuptools import compat |
+ |
+__all__ = [ |
+ 'Require', 'find_module', 'get_module_constant', 'extract_constant' |
+] |
+ |
+class Require: |
+ """A prerequisite to building or installing a distribution""" |
+ |
+ def __init__(self, name, requested_version, module, homepage='', |
+ attribute=None, format=None): |
+ |
+ if format is None and requested_version is not None: |
+ format = StrictVersion |
+ |
+ if format is not None: |
+ requested_version = format(requested_version) |
+ if attribute is None: |
+ attribute = '__version__' |
+ |
+ self.__dict__.update(locals()) |
+ del self.self |
+ |
+ def full_name(self): |
+ """Return full package/distribution name, w/version""" |
+ if self.requested_version is not None: |
+ return '%s-%s' % (self.name,self.requested_version) |
+ return self.name |
+ |
+ def version_ok(self, version): |
+ """Is 'version' sufficiently up-to-date?""" |
+ return self.attribute is None or self.format is None or \ |
+ str(version) != "unknown" and version >= self.requested_version |
+ |
+ def get_version(self, paths=None, default="unknown"): |
+ |
+ """Get version number of installed module, 'None', or 'default' |
+ |
+ Search 'paths' for module. If not found, return 'None'. If found, |
+ return the extracted version attribute, or 'default' if no version |
+ attribute was specified, or the value cannot be determined without |
+ importing the module. The version is formatted according to the |
+ requirement's version format (if any), unless it is 'None' or the |
+ supplied 'default'. |
+ """ |
+ |
+ if self.attribute is None: |
+ try: |
+ f,p,i = find_module(self.module,paths) |
+ if f: f.close() |
+ return default |
+ except ImportError: |
+ return None |
+ |
+ v = get_module_constant(self.module, self.attribute, default, paths) |
+ |
+ if v is not None and v is not default and self.format is not None: |
+ return self.format(v) |
+ |
+ return v |
+ |
+ def is_present(self, paths=None): |
+ """Return true if dependency is present on 'paths'""" |
+ return self.get_version(paths) is not None |
+ |
+ def is_current(self, paths=None): |
+ """Return true if dependency is present and up-to-date on 'paths'""" |
+ version = self.get_version(paths) |
+ if version is None: |
+ return False |
+ return self.version_ok(version) |
+ |
+ |
+def _iter_code(code): |
+ |
+ """Yield '(op,arg)' pair for each operation in code object 'code'""" |
+ |
+ from array import array |
+ from dis import HAVE_ARGUMENT, EXTENDED_ARG |
+ |
+ bytes = array('b',code.co_code) |
+ eof = len(code.co_code) |
+ |
+ ptr = 0 |
+ extended_arg = 0 |
+ |
+ while ptr<eof: |
+ |
+ op = bytes[ptr] |
+ |
+ if op>=HAVE_ARGUMENT: |
+ |
+ arg = bytes[ptr+1] + bytes[ptr+2]*256 + extended_arg |
+ ptr += 3 |
+ |
+ if op==EXTENDED_ARG: |
+ extended_arg = arg * compat.long_type(65536) |
+ continue |
+ |
+ else: |
+ arg = None |
+ ptr += 1 |
+ |
+ yield op,arg |
+ |
+ |
+def find_module(module, paths=None): |
+ """Just like 'imp.find_module()', but with package support""" |
+ |
+ parts = module.split('.') |
+ |
+ while parts: |
+ part = parts.pop(0) |
+ f, path, (suffix,mode,kind) = info = imp.find_module(part, paths) |
+ |
+ if kind==PKG_DIRECTORY: |
+ parts = parts or ['__init__'] |
+ paths = [path] |
+ |
+ elif parts: |
+ raise ImportError("Can't find %r in %s" % (parts,module)) |
+ |
+ return info |
+ |
+ |
+def get_module_constant(module, symbol, default=-1, paths=None): |
+ |
+ """Find 'module' by searching 'paths', and extract 'symbol' |
+ |
+ Return 'None' if 'module' does not exist on 'paths', or it does not define |
+ 'symbol'. If the module defines 'symbol' as a constant, return the |
+ constant. Otherwise, return 'default'.""" |
+ |
+ try: |
+ f, path, (suffix, mode, kind) = find_module(module, paths) |
+ except ImportError: |
+ # Module doesn't exist |
+ return None |
+ |
+ try: |
+ if kind==PY_COMPILED: |
+ f.read(8) # skip magic & date |
+ code = marshal.load(f) |
+ elif kind==PY_FROZEN: |
+ code = imp.get_frozen_object(module) |
+ elif kind==PY_SOURCE: |
+ code = compile(f.read(), path, 'exec') |
+ else: |
+ # Not something we can parse; we'll have to import it. :( |
+ if module not in sys.modules: |
+ imp.load_module(module, f, path, (suffix, mode, kind)) |
+ return getattr(sys.modules[module], symbol, None) |
+ |
+ finally: |
+ if f: |
+ f.close() |
+ |
+ return extract_constant(code, symbol, default) |
+ |
+ |
+def extract_constant(code, symbol, default=-1): |
+ """Extract the constant value of 'symbol' from 'code' |
+ |
+ If the name 'symbol' is bound to a constant value by the Python code |
+ object 'code', return that value. If 'symbol' is bound to an expression, |
+ return 'default'. Otherwise, return 'None'. |
+ |
+ Return value is based on the first assignment to 'symbol'. 'symbol' must |
+ be a global, or at least a non-"fast" local in the code block. That is, |
+ only 'STORE_NAME' and 'STORE_GLOBAL' opcodes are checked, and 'symbol' |
+ must be present in 'code.co_names'. |
+ """ |
+ |
+ if symbol not in code.co_names: |
+ # name's not there, can't possibly be an assigment |
+ return None |
+ |
+ name_idx = list(code.co_names).index(symbol) |
+ |
+ STORE_NAME = 90 |
+ STORE_GLOBAL = 97 |
+ LOAD_CONST = 100 |
+ |
+ const = default |
+ |
+ for op, arg in _iter_code(code): |
+ |
+ if op==LOAD_CONST: |
+ const = code.co_consts[arg] |
+ elif arg==name_idx and (op==STORE_NAME or op==STORE_GLOBAL): |
+ return const |
+ else: |
+ const = default |
+ |
+ |
+def _update_globals(): |
+ """ |
+ Patch the globals to remove the objects not available on some platforms. |
+ |
+ XXX it'd be better to test assertions about bytecode instead. |
+ """ |
+ |
+ if not sys.platform.startswith('java') and sys.platform != 'cli': |
+ return |
+ incompatible = 'extract_constant', 'get_module_constant' |
+ for name in incompatible: |
+ del globals()[name] |
+ __all__.remove(name) |
+ |
+_update_globals() |