def get_plugins(package_name, paths=None): """Find packages that are plugins of the given package. Args: package_name (str): Name of the package. paths (list of str): Paths to search for packages, defaults to `config.packages_path`. Returns: list of str: The packages that are plugins of the given package. """ pkg = get_latest_package(package_name, paths=paths, error=True) if not pkg.has_plugins: return [] it = iter_package_families(paths) package_names = set(x.name for x in it) bar = ProgressBar("Searching", len(package_names)) plugin_pkgs = [] for package_name_ in package_names: bar.next() if package_name_ == package_name: continue # not a plugin of itself plugin_pkg = get_latest_package(package_name_, paths=paths) if not plugin_pkg.plugin_for: continue for plugin_for in plugin_pkg.plugin_for: if plugin_for == pkg.name: plugin_pkgs.append(package_name_) bar.finish() return plugin_pkgs
def expand_version(version): rank = len(version) wildcard_found = False while version and str(version[-1]) in wildcard_map: token = wildcard_map[str(version[-1])] version = version.trim(len(version) - 1) if token == "**": if wildcard_found: # catches bad syntax '**.*' return None else: wildcard_found = True rank = 0 break wildcard_found = True if not wildcard_found: return None range_ = VersionRange(str(version)) package = get_latest_package(name=req.name, range_=range_, paths=paths) if package is None: return version if rank: return package.version.trim(rank) else: return package.version
def _get_dest_pkg(self, name, version): return get_latest_package( name, range_=VersionRange("==" + version), paths=[self.dest_install_root], error=True )
def create_context(pip_version=None, python_version=None): """Create a context containing the specific pip and python. Args: pip_version (str or `Version`): Version of pip to use, or latest if None. python_version (str or `Version`): Python version to use, or latest if None. Returns: `ResolvedContext`: Context containing pip and python. """ # determine pip pkg to use for install, and python variants to install on if pip_version: pip_req = "pip-%s" % str(pip_version) else: pip_req = "pip" if python_version: ver = Version(str(python_version)) major_minor_ver = ver.trim(2) py_req = "python-%s" % str(major_minor_ver) else: # use latest major.minor package = get_latest_package("python") if package: major_minor_ver = package.version.trim(2) else: # no python package. We're gonna fail, let's just choose current # python version (and fail at context creation time) major_minor_ver = '.'.join(map(str, sys.version_info[:2])) py_req = "python-%s" % str(major_minor_ver) # use pip + latest python to perform pip download operations request = [pip_req, py_req] with convert_errors(from_=(PackageFamilyNotFoundError, PackageNotFoundError), to=BuildError, msg="Cannot run - pip or python rez " "package is not present"): context = ResolvedContext(request) # print pip package used to perform the install pip_variant = context.get_resolved_package("pip") pip_package = pip_variant.parent print_info("Using %s (%s)" % (pip_package.qualified_name, pip_variant.uri)) return context
def create_context(pip_version=None, python_version=None): """Create a context containing the specific pip and python. Args: pip_version (str or `Version`): Version of pip to use, or latest if None. python_version (str or `Version`): Python version to use, or latest if None. Returns: `ResolvedContext`: Context containing pip and python. """ # determine pip pkg to use for install, and python variants to install on if pip_version: pip_req = "pip-%s" % str(pip_version) else: pip_req = "pip" if python_version: ver = Version(str(python_version)) major_minor_ver = ver.trim(2) py_req = "python-%s" % str(major_minor_ver) else: # use latest major.minor package = get_latest_package("python") if package: major_minor_ver = package.version.trim(2) else: # no python package. We're gonna fail, let's just choose current # python version (and fail at context creation time) major_minor_ver = ".".join(map(str, sys.version_info[:2])) py_req = "python-%s" % str(major_minor_ver) # use pip + latest python to perform pip download operations request = [pip_req, py_req] with convert_errors( from_=(PackageFamilyNotFoundError, PackageNotFoundError), to=BuildError, msg="Cannot run - pip or python rez " "package is not present", ): context = ResolvedContext(request) # print pip package used to perform the install pip_variant = context.get_resolved_package("pip") pip_package = pip_variant.parent print_info("Using %s (%s)" % (pip_package.qualified_name, pip_variant.uri)) return context
def find_intersphinx_links(requirements): """Convert a Rez package's list of requirements into API documentation links. Args: requirements (iter[:class:`rez.utils.formatting.PackageRequest`]): The Package + version (if there is a version) information that will be used to query documentation details. Returns: dict[str, tuple[str, None]]: Get every Rez package and its URL help documentation, if found. """ packages = set() for requirement in requirements: package = packages_.get_latest_package(requirement.name, range_=requirement.range_) if package: packages.add(package) continue _LOGGER.warning('No Rez package was found for requirement "%s".', requirement) output = dict() finders = [ url_help.find_package_documentation, url_help.find_api_documentation ] for package in packages: for finder in finders: documentation = finder(package) if documentation: output[package.name] = (documentation, None) break return output
def expand_requirement(request): """Expands a requirement string like 'python-2.*' Only trailing wildcards are supported; they will be replaced with the latest package version found within the range. If none are found, the wildcards will just be stripped. Example: >>> print expand_requirement('python-2.*') python-2.7 Args: request (str): Request to expand, eg 'python-2.*' Returns: str: Expanded request string. """ if '*' not in request: return request from rez.vendor.version.requirement import VersionedObject, Requirement from rez.packages_ import get_latest_package txt = request.replace('*', '_') obj = VersionedObject(txt) rank = len(obj.version) request_ = request while request_.endswith('*'): request_ = request_[:-2] # strip sep + * req = Requirement(request_) package = get_latest_package(name=req.name, range_=req.range_) if package is None: return request_ obj.version_ = package.version.trim(rank) return str(obj)
def iter_latest_packages(paths=None, packages=None): """Get one package from every Rez package family. Args: paths (list[str], optional): The directories to search for Rez package families, Default: :attr:`rez.config.config.packages_path`. packages (set[str], optional): If this parameter is given a value, any Rez package families that are discovered in `paths` will be filtered by the list of Rez package family names in this parameter. Yields: :class:`rez.packages_.Package`: The latest version of every package in the current environment. """ names = sorted( set(family.name for family in packages_.iter_package_families(paths=paths))) if packages: names = [name for name in names if name in packages] for name in names: package = packages_.get_latest_package(name, paths=paths) if not package: _LOGGER.warning( 'Package family "%s" was found but `get_latest_package` returned None.' "The package is probably damaged.", name, ) continue yield package
def pip_install_package(source_name, pip_version=None, python_versions=None, no_deps=False, install_newer_deps=False): """Install a pip-compatible python package as a rez package. Args: source_name (str): Name of package or archive/url containing the pip package source. This is the same as the arg you would pass to the 'pip install' command. pip_version (str or `Version`): Version of pip to use to perform the install, uses latest if None. python_versions (list of str or `Version`): Python version(s) to use to perform the install, and subsequently have the resulting rez package depend on. If multiple values are provided, this will create multiple variants in the package, each based on the python version. Defaults to a single variant for the latest python version. no_deps (bool): If True, don't install dependencies. install_newer_deps (bool): If True, newer package dependencies will be installed, even if existing rez package versions already exist that already satisfy the package's dependencies. """ if pip_version: pip_req = "pip-%s" % str(pip_version) else: pip_req = "pip" py_reqs = [] if python_versions: py_vers = set() for ver in python_versions: ver_ = Version(str(ver)) major_minor_ver = ver_[:2] py_vers.add(major_minor_ver) for py_ver in sorted(py_vers): py_req = "python-%s" % str(py_ver) py_reqs.append(py_req) else: # use latest major.minor package = get_latest_package("python") major_minor_ver = package.version[:2] py_req = "python-%s" % str(major_minor_ver) py_reqs.append(py_req) tmpdir = mkdtemp(suffix="-rez", prefix="pip-") packages = {} # use pip + latest python to perform common operations request = [pip_req, py_reqs[-1]] context = ResolvedContext(request) # download package and dependency archives dl_path = os.path.join(tmpdir, "download") os.mkdir(dl_path) primary_name = _download_packages(source_name, context=context, tmpdir=dl_path, no_deps=no_deps) # build each so we can extract dependencies and determine if they are # platform-specific (ie if they contain .so or similar) tmp_installs_path = os.path.join(tmpdir, "install") os.mkdir(tmp_installs_path) for name in os.listdir(dl_path): filepath = os.path.join(dl_path, name) tmp_install_path = os.path.join(tmp_installs_path, name) os.mkdir(tmp_install_path) metadata = _analyse_package(context, filepath, tmp_install_path) metadata["primary"] = (name == primary_name) packages[metadata["package_name"]] = metadata # sort as reverse dependency tree, we need to install from bottom of tree # up, since a rez-release must have rez package dependencies present package_list = _get_install_list(packages, install_newer_deps) # perform a rez-release on each package tmp_rezbuilds_path = os.path.join(tmpdir, "rez-build") os.mkdir(tmp_rezbuilds_path) for package in package_list: package_name = package["package_name"] tmp_rezbuild_path = os.path.join(tmp_rezbuilds_path, package_name) _rez_release_package(package, pip_requirement=pip_req, python_requirements=py_reqs, tmpdir=tmp_rezbuild_path)
def find_pip_from_context(python_version, pip_version=None): """Find pip from rez context. Args: python_version (str or `Version`): Python version to use pip_version (str or `Version`): Version of pip to use, or latest. Returns: 3-tuple: - str: Python executable or None if we fell back to system pip. - str: Pip version or None if we fell back to system pip. - `ResolvedContext`: Context containing pip, or None if we fell back to system pip. """ target = "python" package_request = [] if python_version: ver = Version(str(python_version)) python_major_minor_ver = ver.trim(2) else: # use latest major.minor package = get_latest_package("python") if package: python_major_minor_ver = package.version.trim(2) else: raise BuildError("Found no python package.") python_package = "python-%s" % str(python_major_minor_ver) package_request.append(python_package) if pip_version: target = "pip" if pip_version == "latest": package_request.append("pip") else: package_request.append("pip-%s" % str(pip_version)) print_info("Trying to use pip from %s package", target) try: context = ResolvedContext(package_request) except (PackageFamilyNotFoundError, PackageNotFoundError): print_debug("No rez package called %s found", target) return None, None, None py_exe_name = "python" if platform_.name != "windows": # Python < 2 on Windows doesn't have versionned executable. py_exe_name += str(python_major_minor_ver.trim(1)) py_exe = context.which(py_exe_name) proc = context.execute_command( # -E and -s are used to isolate the environment as much as possible. # See python --help for more details. We absolutely don't want to get # pip from the user home. [ py_exe, "-E", "-s", "-c", "import pip, sys; sys.stdout.write(pip.__version__)" ], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) out, err = proc.communicate() if proc.returncode: print_debug("Failed to get pip from package %s", target) print_debug(out) print_debug(err) return None, None, None pip_version = out.strip() variant = context.get_resolved_package(target) package = variant.parent print_info("Found pip-%s inside %s. Will use it with %s", pip_version, package.uri, py_exe) return py_exe, pip_version, context
def _is_missing_python_version(version): """Check if the given version / version-range has a valid package.""" return packages.get_latest_package("python", version) is None