def package_preprocess_function(this, data): from rez.utils.formatting import PackageRequest from rez.exceptions import InvalidPackageError # Ozark profile # Must be built with ozark profile build tool # ozark_profile = getattr(this, "ozark_profile", False) if ozark_profile and not bool(os.getenv("REZ_OZARK_BUILD")): raise InvalidPackageError("This package is an Ozark profile, please " "use Ozark profile build tool instead.") # Must have variant # Unless explicitly set `no_variant=True` # Or it's the 'default' one # if this.name != "default": no_variants = getattr(this, "no_variants", False) if not no_variants and not this.variants: # Add "default" if no variant data["variants"] = [["default"]] # Replacing package requirements # REQUIREMENT_MAP = { # Example "installing_package_name": { "required_request_string": "replacement_request_string", }, } if this.name in REQUIREMENT_MAP: remapped_requires = list() map_ = REQUIREMENT_MAP[this.name] for package in this.requires: if str(package) in map_: package = PackageRequest(map_[str(package)]) elif package.name in map_: package = PackageRequest(map_[package.name]) remapped_requires.append(package) data["requires"] = remapped_requires
def test_developer(self): """test developer package.""" path = os.path.join(self.packages_base_path, "developer") package = get_developer_package(path) expected_data = dict(name="foo", version=Version("3.0.1"), description="a foo type thing.", authors=["joe.bloggs"], requires=[PackageRequest('bah-1.2+<2')], variants=[[PackageRequest('floob-4.1')], [PackageRequest('floob-2.0')]], uuid="28d94bcd1a934bb4999bcf70a21106cc") data = package.validated_data() self.assertDictEqual(data, expected_data)
def __init__(self, failure_description, package_requests=None): self.failure_description = failure_description self.timestamp = int(time.time()) self.load_path = None self._package_requests = [] for req in package_requests or []: if isinstance(req, str): req = PackageRequest(req) self._package_requests.append(req)
def _print_package_info(self, value, buf=sys.stdout, b=False): word = "is also" if b else "is" _pr = Printer(buf) request_str = os.path.basename(value) if request_str != value: return False def _print_package(package): if isinstance(package, Package): name = package.qualified_name else: name = package.qualified_package_name # Variant _pr("Package: %s" % name) path_str = "URI: %s" % package.uri if package.is_local: path_str += " (local)" _pr(path_str) try: req = PackageRequest(request_str) except: return False if req.conflict: return False package_name = req.name version_range = req.range # check for the package in the active context if self.context: variant = self.context.get_resolved_package(package_name) if variant and variant.version in version_range: _pr("'%s' %s a package in the active context:" % (package_name, word)) _print_package(variant) if self.context.load_path: _pr("Context: %s" % self.context.load_path) return True # find the package it = iter_packages(package_name, version_range) packages = sorted(it, key=lambda x: x.version) if packages: txt = "'%s' %s a package. The latest version" % (package_name, word) if not version_range.is_any(): txt += " in the range '%s'" % str(version_range) txt += " is:" _pr(txt) _print_package(packages[-1]) return True return False
def test_6(self): """test variant iteration.""" expected_data_ = dict( name="variants_py", version=Version("2.0"), description="package with variants", base=os.path.join(self.py_packages_path, "variants_py", "2.0"), commands=SourceCode('env.PATH.append("{root}/bin")')) requires_ = ["platform-linux", "platform-osx"] package = get_package("variants_py", "2.0") for i, variant in enumerate(package.iter_variants()): expected_data = expected_data_.copy() expected_data["requires"] = [PackageRequest('python-2.7'), PackageRequest(requires_[i])] data = variant.validated_data() self.assertDictEqual(data, expected_data) self.assertEqual(variant.index, i) self.assertEqual(variant.parent, package)
def test_5(self): """test developer package.""" path = os.path.join(self.packages_base_path, "developer") package = get_developer_package(path) expected_data = dict(name="foo", version=Version("3.0.1"), description="a foo type thing.", authors=["joe.bloggs"], requires=[PackageRequest('bah-1.2+<2')], variants=[[PackageRequest('floob-4.1')], [PackageRequest('floob-2.0')]], uuid="28d94bcd1a934bb4999bcf70a21106cc") data = package.validated_data() self.assertDictEqual(data, expected_data) # a developer package with features such as expanding requirements, # early-binding attribute functions, and preprocessing path = os.path.join(self.packages_base_path, "developer_dynamic") package = get_developer_package(path) self.assertEqual(package.description, "This.") self.assertEqual(package.requires, [PackageRequest('versioned-3')]) self.assertEqual(package.authors, ["tweedle-dee", "tweedle-dum"])
def prune_graph(graph_str, package_name): """Prune a package graph so it only contains nodes accessible from the given package. Args: graph_str (str): Dot-language graph string. package_name (str): Name of package of interest. Returns: Pruned graph, as a string. """ # find nodes of interest g = read_dot(graph_str) nodes = set() for node, attrs in g.node_attr.iteritems(): attr = [x for x in attrs if x[0] == "label"] if attr: label = attr[0][1] try: req_str = _request_from_label(label) request = PackageRequest(req_str) except PackageRequestError: continue if request.name == package_name: nodes.add(node) if not nodes: raise ValueError("The package %r does not appear in the graph." % package_name) # find nodes upstream from these nodes g_rev = g.reverse() accessible_nodes = set() access = accessibility(g_rev) for node in nodes: nodes_ = access.get(node, []) accessible_nodes |= set(nodes_) # remove inaccessible nodes inaccessible_nodes = set(g.nodes()) - accessible_nodes for node in inaccessible_nodes: g.del_node(node) return write_dot(g)
def test_4(self): """test package creation.""" package_data = { "name": "foo", "version": "1.0.0", "description": "something foo-like", "requires": ["python-2.6+"]} package = create_package("foo", package_data) self.assertEqual(package.version, Version("1.0.0")) self.assertEqual(package.description, "something foo-like") self.assertEqual(package.requires, [PackageRequest("python-2.6+")]) family = package.parent self.assertEqual(family.name, package.name) packages = list(family.iter_packages()) self.assertEqual(len(packages), 1) self.assertEqual(package, packages[0])
def test_variant_iteration(self): """test variant iteration.""" base = canonical_path( os.path.join(self.py_packages_path, "variants_py", "2.0")) expected_data = dict( name="variants_py", version=Version("2.0"), description="package with variants", base=base, requires=[PackageRequest("python-2.7")], commands=SourceCode('env.PATH.append("{root}/bin")')) package = get_package("variants_py", "2.0") for i, variant in enumerate(package.iter_variants()): data = variant.validated_data() self.assertDictEqual(data, expected_data) self.assertEqual(variant.index, i) self.assertEqual(variant.parent, package)
def command(opts, parser, extra_arg_groups=None): from rez.utils.formatting import PackageRequest from rez.serialise import FileFormat from rez.packages import iter_packages from rez.status import status import sys req = PackageRequest(opts.PKG) if opts.current: context = status.context if context is None: print("not in a resolved environment context.", file=sys.stderr) sys.exit(1) variant = context.get_resolved_package(req.name) if variant is None: print("Package %r is not in the current context" % req.name, file=sys.stderr) sys.exit(1) package = variant.parent else: it = iter_packages(req.name, req.range) packages = sorted(it, key=lambda x: x.version) if not packages: print("no matches found") sys.exit(1) package = packages[-1] if not opts.brief: print("URI:") print(package.uri) print() print("CONTENTS:") if opts.format == "py": format_ = FileFormat.py else: format_ = FileFormat.yaml package.print_info(format_=format_, include_release=opts.all)
def test_developer_dynamic_local_preprocess(self): """test developer package with a local preprocess function""" # a developer package with features such as expanding requirements, # early-binding attribute functions, and preprocessing # Here we will also verifies that the local preprocess function wins over # the global one. self.update_settings( {"package_preprocess_function": "global_preprocess.inject_data"}) path = os.path.join(self.packages_base_path, "developer_dynamic_local_preprocess") package = get_developer_package(path) self.assertEqual(package.description, "This.") self.assertEqual(package.requires, [PackageRequest('versioned-3')]) self.assertEqual(package.authors, ["tweedle-dee", "tweedle-dum"]) self.assertFalse(hasattr(package, "added_by_global_preprocess")) self.assertEqual(package.added_by_local_preprocess, True)
def get_latest_package_from_string(txt, paths=None, error=False): """Get the latest package found within the given request string. Args: txt (str): Request, eg 'foo-1.2+' paths (list of str, optional): paths to search for packages, defaults to `config.packages_path`. error (bool): If True, raise an error if no package is found. Returns: `Package` object, or None if no package is found. """ from rez.utils.formatting import PackageRequest req = PackageRequest(txt) return get_latest_package(name=req.name, range_=req.range_, paths=paths, error=error)
def find_contexts(self, in_request=None, in_resolve=None): """Find contexts in the suite based on search criteria. Args: in_request (str): Match contexts that contain the given package in their request. in_resolve (str or `Requirement`): Match contexts that contain the given package in their resolve. You can also supply a conflict requirement - '!foo' will match any contexts whos resolve does not contain any version of package 'foo'. Returns: List of context names that match the search criteria. """ names = self.context_names if in_request: def _in_request(name): context = self.context(name) packages = set(x.name for x in context.requested_packages(True)) return (in_request in packages) names = [x for x in names if _in_request(x)] if in_resolve: if isinstance(in_resolve, six.string_types): in_resolve = PackageRequest(in_resolve) def _in_resolve(name): context = self.context(name) variant = context.get_resolved_package(in_resolve.name) if variant: overlap = (variant.version in in_resolve.range) return ((in_resolve.conflict and not overlap) or (overlap and not in_resolve.conflict)) else: return in_resolve.conflict names = [x for x in names if _in_resolve(x)] return names
def command(opts, parser=None, extra_arg_groups=None): from rez.utils.formatting import PackageRequest from rez.package_help import PackageHelp import sys if opts.manual or not opts.PKG: PackageHelp.open_rez_manual() sys.exit(0) request = PackageRequest(opts.PKG) if request.conflict: raise ValueError("Expected a non-conflicting package") help_ = PackageHelp(request.name, request.range, verbose=opts.verbose) if not help_.success: msg = "Could not find a package with help for %r." % request print >> sys.stderr, msg sys.exit(1) package = help_.package print "Help found for:" print package.uri if package.description: print print "Description:" print package.description.strip() print if opts.entries: help_.print_info() else: try: help_.open(opts.SECTION - 1) except IndexError: print >> sys.stderr, "No such help section." sys.exit(2)
def command(opts, parser, extra_arg_groups=None): from rez.status import status from rez.utils.formatting import columnise, PackageRequest from rez.resolved_context import ResolvedContext from rez.utils.graph_utils import save_graph, view_graph, prune_graph from pprint import pformat rxt_file = opts.RXT if opts.RXT else status.context_file if not rxt_file: print >> sys.stderr, "not in a resolved environment context." sys.exit(1) if rxt_file == '-': # read from stdin rc = ResolvedContext.read_from_buffer(sys.stdin, 'STDIN') else: rc = ResolvedContext.load(rxt_file) def _graph(): if rc.has_graph: return rc.graph(as_dot=True) else: print >> sys.stderr, "The context does not contain a graph." sys.exit(1) parent_env = {} if opts.no_env else None if not opts.interpret: if opts.print_request: print " ".join(str(x) for x in rc.requested_packages(False)) elif opts.print_resolve: print ' '.join(x.qualified_package_name for x in rc.resolved_packages) elif opts.tools: rc.print_tools() elif opts.diff: rc_other = ResolvedContext.load(opts.diff) rc.print_resolve_diff(rc_other, True) elif opts.fetch: rc_new = ResolvedContext(rc.requested_packages(), package_paths=rc.package_paths, verbosity=opts.verbose) rc.print_resolve_diff(rc_new, heading=("current", "updated")) elif opts.which: cmd = opts.which path = rc.which(cmd, parent_environ=parent_env) if path: print path else: print >> sys.stderr, "'%s' not found in the context" % cmd elif opts.print_graph: gstr = _graph() print gstr elif opts.graph or opts.write_graph: gstr = _graph() if opts.prune_pkg: req = PackageRequest(opts.prune_pkg) gstr = prune_graph(gstr, req.name) func = view_graph if opts.graph else save_graph func(gstr, dest_file=opts.write_graph) else: rc.print_info(verbosity=opts.verbose, source_order=opts.source_order, show_resolved_uris=opts.show_uris) return if opts.format in ("dict", "table", "json"): env = rc.get_environ(parent_environ=parent_env) if opts.format == 'table': rows = [x for x in sorted(env.iteritems())] print '\n'.join(columnise(rows)) elif opts.format == 'dict': print pformat(env) else: # json print json.dumps(env, sort_keys=True, indent=4) else: code = rc.get_shell_code(shell=opts.format, parent_environ=parent_env, style=OutputStyle[opts.style]) print code
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)
def command(opts, parser, extra_arg_groups=None): from rez.config import config from rez.package_bind import bind_package, find_bind_module, \ get_bind_modules, _print_package_list from rez.utils.formatting import PackageRequest, columnise if opts.release: install_path = config.release_packages_path elif opts.install_path: install_path = opts.install_path else: install_path = config.local_packages_path if opts.list: d = get_bind_modules() rows = [["PACKAGE", "BIND MODULE"], ["-------", "-----------"]] rows += sorted(d.items()) print('\n'.join(columnise(rows))) return if opts.quickstart: # note: in dependency order, do not change names = [ "platform", "arch", "os", "python", "rez", "rezgui", "setuptools", "pip" ] variants = [] for name in names: print("Binding %s into %s..." % (name, install_path)) variants_ = bind_package(name, path=install_path, no_deps=True, quiet=True) variants.extend(variants_) if variants: print("\nSuccessfully converted the following software found on " "the current system into Rez packages:") print() _print_package_list(variants) print("\nTo bind other software, see what's available using the " "command 'rez-bind --list', then run 'rez-bind <name>'.\n") return if not opts.PKG: parser.error("PKG required.") req = PackageRequest(opts.PKG) name = req.name version_range = None if req.range.is_any() else req.range if opts.search: find_bind_module(name, verbose=True) else: bind_package(name, path=install_path, version_range=version_range, no_deps=opts.no_deps, bind_args=opts.BIND_ARGS)
def command(opts, parser, extra_arg_groups=None): import os import sys from rez.config import config from rez.package_repository import package_repository_manager from rez.package_copy import copy_package from rez.utils.formatting import PackageRequest from rez.packages_ import iter_packages if (not opts.dest_path) and not (opts.rename or opts.reversion): parser.error("--dest-path must be specified unless --rename or " "--reversion are used.") # Load the source package. # if opts.paths: paths = opts.paths.split(os.pathsep) paths = [x for x in paths if x] elif opts.no_local: paths = config.nonlocal_packages_path else: paths = None req = PackageRequest(opts.PKG) it = iter_packages(name=req.name, range_=req.range_, paths=paths) src_pkgs = list(it) if not src_pkgs: print >> sys.stderr, "No matching packages found." sys.exit(1) if len(src_pkgs) > 1: print >> sys.stderr, "More than one package matches, please choose:" for pkg in sorted(src_pkgs, key=lambda x: x.version): print >> sys.stderr, pkg.qualified_name sys.exit(1) src_pkg = src_pkgs[0] # Determine repo and perform checks. # # A common mistake may be to specify a dest package path, rather than the # _repo_ path. This would cause a mess, since a package would be installed # into a nested location within an existing package. # if opts.dest_path: dest_pkg_repo = package_repository_manager.get_repository( opts.dest_path) if (not opts.allow_empty) and dest_pkg_repo.is_empty(): print >> sys.stderr, ( "Attempting to copy a package into an EMPTY repository. Are you " "sure that --dest-path is the correct path? This should not " "include package name and/or version." "\n\n" "If this is a valid new package repository, use the " "--allow-empty flag to continue.") sys.exit(1) else: dest_pkg_repo = src_pkg.repository # Perform the copy. # variants = opts.variants or None result = copy_package(package=src_pkg, dest_repository=dest_pkg_repo, dest_name=opts.rename, dest_version=opts.reversion, variants=variants, overwrite=opts.overwrite, shallow=opts.shallow, keep_timestamp=opts.keep_timestamp, force=opts.force, verbose=opts.verbose, dry_run=opts.dry_run) # Print info about the result. # copied = result["copied"] skipped = result["skipped"] if opts.dry_run: # show a good indication of target variant when it doesn't get created path = dest_pkg_repo.get_package_payload_path( package_name=opts.rename or src_pkg.name, package_version=opts.reversion or src_pkg.version) dry_run_uri = path + "/?" verb = "would be" else: verb = "were" # specific output for non-varianted packages if src_pkg.num_variants == 0: if copied: dest_pkg = copied[0][1].parent print("Copied %s to %s" % (src_pkg.uri, dest_pkg.uri)) else: assert skipped dest_pkg = skipped[0][1].parent print( "Target package already exists: %s. Use 'overwrite' to replace it." % dest_pkg.uri) # varianted package else: if copied: print("%d variants %s copied:" % (len(copied), verb)) for src_variant, dest_variant in copied: # None possible if dry_run if dest_variant is None: dest_uri = dry_run_uri else: dest_uri = dest_variant.uri print(" %s -> %s" % (src_variant.uri, dest_uri)) if skipped: print("%d variants %s skipped (target exists):" % (len(skipped), verb)) for src_variant, dest_variant in skipped: print(" %s !-> %s" % (src_variant.uri, dest_variant.uri))