def _bind_package(name, path=None, version_range=None, bind_args=None, quiet=False): bindfile = find_bind_module(name, verbose=(not quiet)) if not bindfile: raise RezBindError("Bind module not found for '%s'" % name) # load the bind module namespace = {} with open(bindfile) as stream: exec(compile(stream.read(), stream.name, 'exec'), namespace) # parse bind module params bind_parser = argparse.ArgumentParser(prog="rez bind %s" % name, description="%s bind module" % name) parserfunc = namespace.get("setup_parser") if parserfunc: parserfunc(bind_parser) bind_opts = bind_parser.parse_args(bind_args or []) # make the package install_path = path or config.local_packages_path if not quiet: print("creating package '%s' in %s..." % (name, install_path)) bindfunc = namespace.get("bind") if not bindfunc: raise RezBindError("'bind' function missing in %s" % bindfile) variants = bindfunc(path=install_path, version_range=version_range, opts=bind_opts, parser=bind_parser) return variants
def extract_version(exepath, version_arg, word_index=-1, version_rank=3): """Run an executable and get the program version. Args: exepath: Filepath to executable. version_arg: Arg to pass to program, eg "-V". Can also be a list. word_index: Expect the Nth word of output to be the version. version_rank: Cap the version to this many tokens. Returns: `Version` object. """ if isinstance(version_arg, basestring): version_arg = [version_arg] args = [exepath] + version_arg stdout, stderr, returncode = _run_command(args) if returncode: raise RezBindError("failed to execute %s: %s\n(error code %d)" % (exepath, stderr, returncode)) stdout = stdout.strip().split('\n')[0].strip() log("extracting version from output: '%s'" % stdout) try: strver = stdout.split()[word_index] toks = strver.replace('.', ' ').replace('-', ' ').split() strver = '.'.join(toks[:version_rank]) version = Version(strver) except Exception as e: raise RezBindError("failed to parse version from output '%s': %s" % (stdout, str(e))) log("extracted version: '%s'" % str(version)) return version
def copy_module(name, destpath): success, out, err = run_python_command([ "import %s" % name, "print %s.__path__[0] if hasattr(%s, '__path__') else ''" % (name, name) ]) if out: srcpath = out shutil.copytree(srcpath, os.path.join(destpath, name)) else: success, out, err = run_python_command( ["import %s" % name, "print %s.__file__" % name]) if not success: raise RezBindError("Couldn't locate module %s: %s" % (name, err)) srcfile = out dirpart, ext = os.path.splitext(srcfile) if ext == ".pyc": pyfile = dirpart + ".py" if os.path.exists(pyfile): srcfile = pyfile destfile = os.path.join(destpath, os.path.basename(srcfile)) shutil.copy2(srcfile, destfile)
def get_version_in_python(name, commands): success, out, err = run_python_command(commands) if not success or not out: raise RezBindError("Couldn't determine version of module %s: %s" % (name, err)) version = out return version
def bind(path, version_range=None, opts=None, parser=None): exe_path = getattr(opts, 'exe', None) # gcc gcc_path = find_exe('gcc', filepath=exe_path) gcc_version = extract_version(gcc_path, ['-dumpfullversion', '-dumpversion']) log("binding gcc: %s" % gcc_path) # g++ gpp_path = find_exe('g++', filepath=exe_path) gpp_version = extract_version(gpp_path, ['-dumpfullversion', '-dumpversion']) log("binding g++: %s" % gpp_path) if gcc_version != gpp_version: raise RezBindError("gcc version different than g++ can not continue") # create directories and symlink gcc and g++ def make_root(variant, root): bin_path = make_dirs(root, 'bin') gcc_link_path = os.path.join(bin_path, 'gcc') platform_.symlink(gcc_path, gcc_link_path) gpp_link_path = os.path.join(bin_path, 'g++') platform_.symlink(gpp_path, gpp_link_path) with make_package('gcc', path, make_root=make_root) as pkg: pkg.version = gcc_version pkg.tools = ['gcc', 'g++'] pkg.commands = commands pkg.variants = [system.variant] return pkg.installed_variants
def check_version(version, range_=None): """Check that the found software version is within supplied range. Args: version: Version of the package as a Version object. range_: Allowable version range as a VersionRange object. """ if range_ and version not in range_: raise RezBindError("found version %s is not within range %s" % (str(version), str(range_)))
def find_exe(name, filepath=None): """Find an executable. Args: name: Name of the program, eg 'python'. filepath: Path to executable, a search is performed if None. Returns: Path to the executable if found, otherwise an error is raised. """ if filepath: if not os.path.exists(filepath): open(filepath) # raise IOError elif not os.path.isfile(filepath): raise RezBindError("not a file: %s" % filepath) else: filepath = which(name) if not filepath: raise RezBindError("could not find executable: %s" % name) return filepath
def command(opts, parser, extra_arg_groups=None): from rez.config import config from rez.exceptions import RezBindError from rez import module_root_path from rez.util import get_close_pkgs from rez.utils.formatting import columnise, PackageRequest from rez.vendor.version.requirement import VersionedObject import os.path import os import sys # gather the params install_path = (config.local_packages_path if opts.install_path is None else opts.install_path) req = PackageRequest(opts.PKG) name = req.name version_range = None if req.range.is_any() else req.range if req.conflict: parser.error("PKG cannot be a conflict requirement") # find the bind module builtin_path = os.path.join(module_root_path, "bind") searchpaths = config.bind_module_path + [builtin_path] bindfile = None bindnames = {} for path in searchpaths: if opts.verbose: print "searching %s..." % path if not os.path.isdir(path): continue filename = os.path.join(path, name + ".py") if os.path.isfile(filename): if opts.search: print filename sys.exit(0) else: bindfile = filename break else: for filename in os.listdir(path): fpath = os.path.join(path, filename) fname, ext = os.path.splitext(filename) if os.path.isfile(fpath) and ext == ".py" \ and not fname.startswith('_'): bindnames[fname] = fpath if not bindfile: fuzzy_matches = get_close_pkgs(name, bindnames.keys()) if opts.search: if fuzzy_matches: rows = [(x[0], bindnames[x[0]]) for x in fuzzy_matches] print "'%s' not found. Close matches:" % name print '\n'.join(columnise(rows)) else: print "No matches." sys.exit(0) else: msg = "bind module not found for '%s'" % name if fuzzy_matches: matches_s = ', '.join(x[0] for x in fuzzy_matches) msg += "\ndid you mean one of: %s" % matches_s raise RezBindError(msg) # load the bind module stream = open(bindfile) namespace = {} exec stream in namespace # parse bind module params bind_parser = argparse.ArgumentParser(prog="rez bind %s" % name, description="%s bind module" % name) parserfunc = namespace.get("setup_parser") if parserfunc: parserfunc(bind_parser) bind_opts = bind_parser.parse_args(opts.BIND_ARG) # make the package if opts.verbose: print "creating package '%s' in %s..." % (name, install_path) bindfunc = namespace.get("bind") if not bindfunc: raise RezBindError("'bind' function missing in %s" % bindfile) name, version = bindfunc(path=install_path, version_range=version_range, opts=bind_opts, parser=bind_parser) o = VersionedObject.construct(name, version) print "created package '%s' in %s" % (str(o), install_path)