def _iter_variant_extracted_paths(root, path, variants):
    """Convert a Rez package path that contains a variant back into its "non-variant" form.

    Args:
        root (str):
            The directory that contains the Rez package's package.py,
            package.txt, or package.yaml.
        path (str):
            A path that is a sub-folder inside of the Rez package. This
            path also has a variant somewhere in it.
        variants (iter[list[:class:`rez.utils.formatting.PackageRequest`]]):
            A Rez package's different build configurations. Usually,
            this will just be different Python versions such as
            [[PackageRequest("python-2.7")]] but it can be more complex.

    Yields:
        str: The original `path` but without a variant.

    """
    for variant in sorted(variants, key=len, reverse=True):
        inner_path = os.path.join(*[str(request) for request in variant])
        resolved_path = os.path.join(root, inner_path)

        if filer.in_directory(path, resolved_path, follow=False):
            yield path.replace(inner_path + os.sep, "")
def get_all_packages(directory):
    """Find every Rez package in the given directory.

    Args:
        directory (str):
            An absolute path to a folder on-disk. y package on or below
            this path will be returned.

    Returns:
        list[:class:`rez.packages_.DeveloperPackage`]: The found packages.

    """
    paths = set()
    packages = []

    for root, _, _ in os.walk(directory):
        if any(filer.in_directory(root, directory_) for directory_ in paths):
            continue

        package = finder.get_nearest_rez_package(root)

        if package:
            packages.append(package)

    return packages
Ejemplo n.º 3
0
def _get_first_external_path(excludes=frozenset()):
    """Find the path of the Python file which calls this function.

    This function excludes paths within this same Rez package, for simplicity's sake.

    Args:
        excludes (set[str]):
            The absolute path to any directory which should be ignored
            while running this function. Default default, even if no
            paths are given, this module's current Rez package is always excluded.

    Returns:
        str: The found caller path, if any.

    """
    package = finder.get_nearest_rez_package(_CURRENT_DIRECTORY)
    root = os.path.dirname(package.filepath)

    excludes = set(excludes)
    excludes.add(root)

    for source_path, _, _, _ in reversed(traceback.extract_stack()):
        # If `source_path` isn't within any of the excluded paths,
        # return it. Otherwise if `source_path` does match at least one
        # of the excluded paths, keep searching.
        #
        for path in excludes:
            if filer.in_directory(source_path, path):
                break
        else:
            return source_path

    return ""
 def test_no_006(self):
     """Check that `in_directory` returns True."""
     self.assertFalse(
         filer.in_directory("/some/path/here",
                            "/some/path/here",
                            follow=True))
 def test_no_005(self):
     """Check that `in_directory` returns True even with trailing slashes."""
     self.assertFalse(
         filer.in_directory("/some/path/here/",
                            "/some/path/here/",
                            follow=True))
 def test_no_001(self):
     """Check that `in_directory` returns False for normal paths."""
     self.assertFalse(
         filer.in_directory("some/path/here", "/some/path", follow=True))
 def test_empty_003(self):
     """Check that `in_directory` is False if one of the paths is empty."""
     self.assertFalse(
         filer.in_directory("", tempfile.gettempdir(), follow=True))
     self.assertFalse(
         filer.in_directory("", tempfile.gettempdir(), follow=False))
 def test_no_006(self):
     """Check that `in_directory` returns True."""
     self.assertFalse(
         filer.in_directory(self._source[1:] + os.sep,
                            self._source[1:] + os.sep,
                            follow=True))
 def test_no_005(self):
     """Check that `in_directory` returns True even with trailing slashes."""
     self.assertFalse(
         filer.in_directory(self._source[1:], self._source[1:],
                            follow=True))
 def test_no_004(self):
     """Check that `in_directory` returns False even with trailing slashes."""
     self.assertFalse(
         filer.in_directory(self._source[1:] + os.sep,
                            self._destination + os.sep,
                            follow=True))
 def test_empty_001(self):
     """Check that `in_directory` is False if both paths are empty."""
     self.assertFalse(filer.in_directory("", "", follow=True))
     self.assertFalse(filer.in_directory("", "", follow=False))
 def test_no_001(self):
     """Check that `in_directory` returns False for normal paths."""
     self.assertFalse(
         filer.in_directory(self._source[1:],
                            self._destination,
                            follow=True))
 def test_yes_003(self):
     """Check that `in_directory` returns True even with trailing slashes."""
     self.assertTrue(
         filer.in_directory(self._source,
                            self._destination + os.sep,
                            follow=True))
 def test_yes_001(self):
     """Check that `in_directory` returns True for normal paths."""
     self.assertTrue(
         filer.in_directory(self._source, self._destination, follow=True))
def get_package_python_paths(package, paths):
    """Get the Python files that a Rez package adds to the user's PYTHONPATH.

    If the Rez package is an installed Rez package and it contains
    variants, each variant will have its paths returned.

    Note:
        This function is a bit sub-optimal. Basically, Rez's API should
        have a way to just query an individual package's contribution
        to PYTHONPATH. But currently doesn't. So we have to hack around
        the problem by using a Rez context.

    Reference:
        https://github.com/nerdvegas/rez/issues/737
        https://github.com/nerdvegas/rez/pull/739
        https://rez-talk.slack.com/archives/CHELFCTFB/p1578604659006100

    Args:
        package (:class:`rez.packages_.Package`):
            The built or source Rez package to get a valid path from.
        paths (iter[str]):
            The PYTHONPATH paths within the Rez package.

    Returns:
        set[str]: The found Python files (excluding __init__.py files).

    """
    # Note: Here we're trying to get `package`'s specific changes to PYTHONPATH (if any)
    #
    # Unfortunately, the Rez API doesn't really support this yet.
    # There's 2 GitHub links that may one-day implement it though:
    #     - https://github.com/nerdvegas/rez/issues/737
    #     - https://github.com/nerdvegas/rez/pull/739
    #
    # Reference: https://rez-talk.slack.com/archives/CHELFCTFB/p1578604659006100
    #
    # Once that work is merged, replace `get_package_python_paths` with it.
    #
    root = finder.get_package_root(package)

    if is_built_package(package):
        return {
            path
            for path in paths if filer.in_directory(path, root, follow=False)
        }

    output = set()

    for path in paths:
        # If the Rez package is a source Rez package + has variants
        # we need to strip the "variants" out of `path`, before
        # returning it.
        #
        try:
            variant_less_path = next(
                _iter_variant_extracted_paths(root, path, package.variants
                                              or []))
        except StopIteration:
            pass
        else:
            output.add(variant_less_path)

            continue

        if filer.in_directory(path, root, follow=False) or filer.in_directory(
                path, root, follow=True):
            output.add(path)

            continue

    return output