| 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()
|
|
|