# Copyright 2018 The Bazel Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Runfiles lookup library for Bazel-built Python binaries and tests.

See @rules_python//python/runfiles/README.md for usage instructions.

:::{versionadded} 1.7.0
Support for Bazel's `--incompatible_compact_repo_mapping_manifest` flag was added.
This enables prefix-based repository mappings to reduce memory usage for large
dependency graphs under bzlmod.
:::
"""

from __future__ import annotations

import inspect
import os
import pathlib
import posixpath
import sys
from collections import defaultdict
from collections.abc import Generator, Iterator
from typing import cast

if sys.version_info >= (3, 12):
    from typing import override
else:
    from typing import TypeVar

    _FuncT = TypeVar("_FuncT")

    def override(func: _FuncT) -> _FuncT:
        return func


if sys.version_info >= (3, 11):
    from typing import Self
elif sys.version_info >= (3, 10):
    from typing import TypeAlias

    Self: TypeAlias = "Path"  # pyrefly: ignore[invalid-type-form]
else:
    from typing import Any as Self


class _RepositoryMapping:
    """Repository mapping for resolving apparent repository names to canonical ones.

    Handles both exact mappings and prefix-based mappings introduced by the
    --incompatible_compact_repo_mapping_manifest flag.
    """

    def __init__(
        self,
        exact_mappings: dict[tuple[str, str], str],
        prefixed_mappings: dict[tuple[str, str], str],
    ) -> None:
        """Initialize repository mapping with exact and prefixed mappings.

        Args:
            exact_mappings: Dict mapping (source_canonical, target_apparent) -> target_canonical
            prefixed_mappings: Dict mapping (source_prefix, target_apparent) -> target_canonical
        """
        self._exact_mappings = exact_mappings

        # Group prefixed mappings by target_apparent for faster lookups
        self._grouped_prefixed_mappings = defaultdict(list)
        for (
            prefix_source,
            target_app,
        ), target_canonical in prefixed_mappings.items():
            self._grouped_prefixed_mappings[target_app].append(
                (prefix_source, target_canonical)
            )

    @staticmethod
    def create_from_file(repo_mapping_path: str | None) -> _RepositoryMapping:
        """Create RepositoryMapping from a repository mapping manifest file.

        Args:
            repo_mapping_path: Path to the repository mapping file, or None if not available

        Returns:
            RepositoryMapping instance with parsed mappings
        """
        # If the repository mapping file can't be found, that is not an error: We
        # might be running without Bzlmod enabled or there may not be any runfiles.
        # In this case, just apply empty repo mappings.
        if not repo_mapping_path:
            return _RepositoryMapping({}, {})

        try:
            with open(repo_mapping_path, "r", encoding="utf-8", newline="\n") as f:
                content = f.read()
        except FileNotFoundError:
            return _RepositoryMapping({}, {})

        exact_mappings = {}
        prefixed_mappings = {}
        for line in content.splitlines():
            source_canonical, target_apparent, target_canonical = line.split(",")
            if source_canonical.endswith("*"):
                # This is a prefixed mapping - remove the '*' for prefix matching
                prefix = source_canonical[:-1]
                prefixed_mappings[(prefix, target_apparent)] = target_canonical
            else:
                # This is an exact mapping
                exact_mappings[(source_canonical, target_apparent)] = target_canonical

        return _RepositoryMapping(exact_mappings, prefixed_mappings)

    def lookup(self, source_repo: str | None, target_apparent: str) -> str | None:
        """Look up repository mapping for the given source and target.

        This handles both exact mappings and prefix-based mappings introduced by the
        --incompatible_compact_repo_mapping_manifest flag. Exact mappings are tried
        first, followed by prefix-based mappings where order matters.

        Args:
            source_repo: Source canonical repository name
            target_apparent: Target apparent repository name

        Returns:
            target_canonical repository name, or None if no mapping exists
        """
        if source_repo is None:
            return None

        key = (source_repo, target_apparent)

        # Try exact mapping first
        if key in self._exact_mappings:
            return self._exact_mappings[key]

        # Try prefixed mapping if no exact match found
        if target_apparent in self._grouped_prefixed_mappings:
            for prefix_source, target_canonical in self._grouped_prefixed_mappings[
                target_apparent
            ]:
                if source_repo.startswith(prefix_source):
                    return target_canonical

        # No mapping found
        return None

    def is_empty(self) -> bool:
        """Check if this repository mapping is empty (no exact or prefixed mappings).

        Returns:
            True if there are no mappings, False otherwise
        """
        return (
            len(self._exact_mappings) == 0 and len(self._grouped_prefixed_mappings) == 0
        )


class Path(pathlib.Path):
    """A pathlib-like path object for runfiles.

    This class extends `pathlib.Path` and resolves paths
    using the associated `Runfiles` instance when converted to a string.
    """

    # Static type checkers may not realize `self` in the methods
    # refers to our Path class instead of pathlib.Path
    _runfiles: Runfiles | None
    _source_repo: str | None

    # For Python < 3.12 compatibility when subclassing Path directly
    _flavour = getattr(type(pathlib.Path()), "_flavour", None)

    def __new__(
        cls,
        *args: str | os.PathLike,
        runfiles: Runfiles | None = None,
        source_repo: str | None = None,
    ) -> Self:
        """Private constructor. Use Runfiles.root() to create instances."""
        obj = cast("Path", super().__new__(cls, *args))
        obj._runfiles = runfiles
        obj._source_repo = source_repo
        return cast(Self, obj)

    def __init__(
        self,
        *args: str | os.PathLike,
        runfiles: Runfiles | None = None,
        source_repo: str | None = None,
    ) -> None:
        # In Python 3.12+, pathlib was refactored and Path.__init__ now accepts
        # *args. Prior to 3.12, Path did not define __init__, so
        # super().__init__(*args) would fall through to object.__init__, which
        # raises a TypeError because it takes no arguments.
        if sys.version_info >= (3, 12):
            super().__init__(*args)
        else:
            super().__init__()

    # We override resolve() and absolute() to ensure that in Python < 3.12,
    # where pathlib internally uses object.__new__ instead of our custom
    # __new__ or with_segments(), the runfiles state is preserved. We delegate
    # to self._as_path() because super().resolve() creates intermediate objects
    # that would otherwise crash during internal stat() calls.
    @override
    def resolve(self, strict: bool = False) -> Self:
        return type(self)(
            self._as_path().resolve(strict=strict),
            runfiles=self._runfiles,
            source_repo=self._source_repo,
        )

    @override
    def absolute(self) -> Self:
        return type(self)(
            self._as_path().absolute(),
            runfiles=self._runfiles,
            source_repo=self._source_repo,
        )

    @override
    def with_segments(self, *pathsegments: str | os.PathLike) -> Self:
        """Used by Python 3.12+ pathlib to create new path objects."""
        return type(self)(
            *pathsegments,
            runfiles=self._runfiles,
            source_repo=self._source_repo,
        )

    # For Python < 3.12
    def _make_child(self, args: tuple[str, ...]) -> Self:
        # _make_child is an internal CPython method in Python < 3.12 omitted from
        # typeshed stubs. We ignore [missing-attribute] for pyrefly.
        obj = cast("Path", super()._make_child(args))  # pyrefly: ignore[missing-attribute]
        obj._runfiles = self._runfiles
        obj._source_repo = self._source_repo
        return cast(Self, obj)

    @property
    @override
    def parents(self) -> tuple[Self, ...]:
        return tuple(
            type(self)(
                p,
                runfiles=self._runfiles,
                source_repo=self._source_repo,
            )
            for p in super().parents
        )

    @property
    @override
    def parent(self) -> Self:
        return type(self)(
            super().parent,
            runfiles=self._runfiles,
            source_repo=self._source_repo,
        )

    @property
    def runfile_path(self) -> str:
        """Returns the runfiles-root relative path."""
        path_posix = super().__str__().replace("\\", "/")
        if path_posix == ".":
            return ""
        return path_posix

    @override
    def with_name(self, name: str) -> Self:
        return type(self)(
            super().with_name(name),
            runfiles=self._runfiles,
            source_repo=self._source_repo,
        )

    @override
    def with_suffix(self, suffix: str) -> Self:
        return type(self)(
            super().with_suffix(suffix),
            runfiles=self._runfiles,
            source_repo=self._source_repo,
        )

    def _as_path(self) -> pathlib.Path:
        return pathlib.Path(str(self))

    @override
    def stat(self, *, follow_symlinks: bool = True) -> os.stat_result:
        return self._as_path().stat(follow_symlinks=follow_symlinks)

    @override
    def lstat(self) -> os.stat_result:
        return self._as_path().lstat()

    @override
    def exists(self, *, follow_symlinks: bool = True) -> bool:
        if not follow_symlinks and sys.version_info >= (3, 12):
            return self._as_path().exists(follow_symlinks=follow_symlinks)
        return self._as_path().exists()

    @override
    def is_dir(self, *, follow_symlinks: bool = True) -> bool:
        if not follow_symlinks and sys.version_info >= (3, 13):
            return self._as_path().is_dir(follow_symlinks=follow_symlinks)
        return self._as_path().is_dir()

    @override
    def is_file(self, *, follow_symlinks: bool = True) -> bool:
        if not follow_symlinks and sys.version_info >= (3, 13):
            return self._as_path().is_file(follow_symlinks=follow_symlinks)
        return self._as_path().is_file()

    @override
    def is_symlink(self) -> bool:
        return self._as_path().is_symlink()

    @override
    def is_block_device(self) -> bool:
        return self._as_path().is_block_device()

    @override
    def is_char_device(self) -> bool:
        return self._as_path().is_char_device()

    @override
    def is_fifo(self) -> bool:
        return self._as_path().is_fifo()

    @override
    def is_socket(self) -> bool:
        return self._as_path().is_socket()

    # Path.open in pathlib has multiple overloads in typeshed. We use a
    # simplified delegation signature here.
    @override
    def open(  # pyrefly: ignore[bad-override]
        self,
        mode: str = "r",
        buffering: int = -1,
        encoding: str | None = None,
        errors: str | None = None,
        newline: str | None = None,
    ):
        return self._as_path().open(
            mode=mode,
            buffering=buffering,
            encoding=encoding,
            errors=errors,
            newline=newline,
        )

    @override
    def read_bytes(self) -> bytes:
        return self._as_path().read_bytes()

    @override
    def read_text(
        self,
        encoding: str | None = None,
        errors: str | None = None,
        newline: str | None = None,
    ) -> str:
        if sys.version_info >= (3, 13) and newline is not None:
            return self._as_path().read_text(
                encoding=encoding,
                errors=errors,
                newline=newline,
            )
        return self._as_path().read_text(encoding=encoding, errors=errors)

    @override
    def iterdir(self) -> Generator[Self, None, None]:
        resolved = self._as_path()
        for p in resolved.iterdir():
            yield self / p.name

    # Return types and keyword arguments vary across Python versions in typeshed.
    @override
    def glob(  # pyrefly: ignore[bad-override]
        self,
        pattern: str,
        *,
        case_sensitive: bool | None = None,
        recurse_symlinks: bool = False,
    ) -> Iterator[Self]:
        resolved = self._as_path()
        if sys.version_info >= (3, 13):
            it = resolved.glob(
                pattern,
                case_sensitive=case_sensitive,
                recurse_symlinks=recurse_symlinks,
            )
        elif sys.version_info >= (3, 12):
            it = resolved.glob(pattern, case_sensitive=case_sensitive)
        else:
            it = resolved.glob(pattern)
        for p in it:
            yield self / p.relative_to(resolved)

    # Return types and keyword arguments vary across Python versions in typeshed.
    @override
    def rglob(  # pyrefly: ignore[bad-override]
        self,
        pattern: str,
        *,
        case_sensitive: bool | None = None,
        recurse_symlinks: bool = False,
    ) -> Iterator[Self]:
        resolved = self._as_path()
        if sys.version_info >= (3, 13):
            it = resolved.rglob(
                pattern,
                case_sensitive=case_sensitive,
                recurse_symlinks=recurse_symlinks,
            )
        elif sys.version_info >= (3, 12):
            it = resolved.rglob(pattern, case_sensitive=case_sensitive)
        else:
            it = resolved.rglob(pattern)
        for p in it:
            yield self / p.relative_to(resolved)

    @override
    def match(
        self,
        path_pattern: str,
        *,
        case_sensitive: bool | None = None,
    ) -> bool:
        if sys.version_info >= (3, 12):
            return self._as_path().match(path_pattern, case_sensitive=case_sensitive)
        return self._as_path().match(path_pattern)

    def __repr__(self) -> str:
        return "runfiles.Path({!r})".format(self.runfile_path)

    def __str__(self) -> str:
        assert self._runfiles is not None  # type assert
        path_posix = super().__str__().replace("\\", "/")
        if not path_posix or path_posix == ".":
            # pylint: disable=protected-access
            return self._runfiles._python_runfiles_root  # pyrefly: ignore[missing-attribute]
        resolved = self._runfiles.Rlocation(path_posix, source_repo=self._source_repo)
        if resolved is not None:
            return resolved

        # pylint: disable=protected-access
        return posixpath.join(self._runfiles._python_runfiles_root, path_posix)  # pyrefly: ignore[missing-attribute]

    def __fspath__(self) -> str:
        return str(self)

    def runfiles_root(self) -> "Path":
        """Returns a Path object representing the runfiles root."""
        assert self._runfiles is not None  # type assert
        return self._runfiles.root(source_repo=self._source_repo)


class _ManifestBased:
    """`Runfiles` strategy that parses a runfiles-manifest to look up runfiles."""

    def __init__(self, path: str) -> None:
        if not path:
            raise ValueError()
        if not isinstance(path, str):
            raise TypeError()
        self._path = path
        self._runfiles = _ManifestBased._LoadRunfiles(path)

    def RlocationChecked(self, path: str) -> str | None:
        """Returns the runtime path of a runfile."""
        exact_match = self._runfiles.get(path)
        if exact_match:
            return exact_match
        # If path references a runfile that lies under a directory that
        # itself is a runfile, then only the directory is listed in the
        # manifest. Look up all prefixes of path in the manifest and append
        # the relative path from the prefix to the looked up path.
        prefix_end = len(path)
        while True:
            prefix_end = path.rfind("/", 0, prefix_end - 1)
            if prefix_end == -1:
                return None
            prefix_match = self._runfiles.get(path[0:prefix_end])
            if prefix_match:
                return prefix_match + "/" + path[prefix_end + 1 :]

    @staticmethod
    def _LoadRunfiles(path: str) -> dict[str, str]:
        """Loads the runfiles manifest."""
        result = {}
        with open(path, "r", encoding="utf-8", newline="\n") as f:
            for line in f:
                line = line.rstrip("\n")
                if line.startswith(" "):
                    # In lines that start with a space, spaces, newlines, and backslashes are escaped as \s, \n, and \b in
                    # link and newlines and backslashes are escaped in target.
                    escaped_link, escaped_target = line[1:].split(" ", maxsplit=1)
                    link = (
                        escaped_link.replace(r"\s", " ")
                        .replace(r"\n", "\n")
                        .replace(r"\b", "\\")
                    )
                    target = escaped_target.replace(r"\n", "\n").replace(r"\b", "\\")
                else:
                    link, target = line.split(" ", maxsplit=1)

                if target:
                    result[link] = target
                else:
                    result[link] = link
        return result

    def _GetRunfilesDir(self) -> str:
        if self._path.endswith("/MANIFEST") or self._path.endswith("\\MANIFEST"):
            return self._path[: -len("/MANIFEST")]
        if self._path.endswith(".runfiles_manifest"):
            return self._path[: -len("_manifest")]
        return ""

    def EnvVars(self) -> dict[str, str]:
        directory = self._GetRunfilesDir()
        return {
            "RUNFILES_MANIFEST_FILE": self._path,
            "RUNFILES_DIR": directory,
            # TODO(laszlocsomor): remove JAVA_RUNFILES once the Java launcher can
            # pick up RUNFILES_DIR.
            "JAVA_RUNFILES": directory,
        }


class _DirectoryBased:
    """`Runfiles` strategy that appends runfiles paths to the runfiles root."""

    def __init__(self, path: str) -> None:
        if not path:
            raise ValueError()
        if not isinstance(path, str):
            raise TypeError()
        self._runfiles_root = path

    def RlocationChecked(self, path: str) -> str:
        # Use posixpath instead of os.path, because Bazel only creates a runfiles
        # tree on Unix platforms, so `Create()` will only create a directory-based
        # runfiles strategy on those platforms.
        return posixpath.join(self._runfiles_root, path)

    def _GetRunfilesDir(self) -> str:
        return self._runfiles_root

    def EnvVars(self) -> dict[str, str]:
        return {
            "RUNFILES_DIR": self._runfiles_root,
            # TODO(laszlocsomor): remove JAVA_RUNFILES once the Java launcher can
            # pick up RUNFILES_DIR.
            "JAVA_RUNFILES": self._runfiles_root,
        }


class Runfiles:
    """Returns the runtime location of runfiles.

    Runfiles are data-dependencies of Bazel-built binaries and tests.
    """

    def __init__(self, strategy: _ManifestBased | _DirectoryBased) -> None:
        self._strategy = strategy
        self._python_runfiles_root = strategy._GetRunfilesDir()
        self._repo_mapping = _RepositoryMapping.create_from_file(
            strategy.RlocationChecked("_repo_mapping")
        )

    def root(self, source_repo: str | None = None) -> Path:
        """Returns a Path object representing the runfiles root.

        The repository mapping used by the returned Path object is that of the
        caller of this method.
        """
        if source_repo is None and not self._repo_mapping.is_empty():
            source_repo = self.CurrentRepository(frame=2)
        return Path(runfiles=self, source_repo=source_repo)

    def Rlocation(self, path: str, source_repo: str | None = None) -> str | None:
        """Returns the runtime path of a runfile.

        Runfiles are data-dependencies of Bazel-built binaries and tests.

        The returned path may not be valid. The caller should check the path's
        validity and that the path exists.

        The function may return None. In that case the caller can be sure that the
        rule does not know about this data-dependency.

        Args:
          path: string; runfiles-root-relative path of the runfile
          source_repo: string; optional; the canonical name of the repository
            whose repository mapping should be used to resolve apparent to
            canonical repository names in `path`. If `None` (default), the
            repository mapping of the repository containing the caller of this
            method is used. Explicitly setting this parameter should only be
            necessary for libraries that want to wrap the runfiles library. Use
            `CurrentRepository` to obtain canonical repository names.
        Returns:
          the path to the runfile, which the caller should check for existence, or
          None if the method doesn't know about this runfile
        Raises:
          TypeError: if `path` is not a string
          ValueError: if `path` is None or empty, or it's absolute or not normalized
        """
        if not path:
            raise ValueError()
        if not isinstance(path, str):
            raise TypeError()
        if (
            path.startswith("../")
            or "/.." in path
            or path.startswith("./")
            or "/./" in path
            or path.endswith("/.")
            or "//" in path
        ):
            raise ValueError('path is not normalized: "%s"' % path)
        if path[0] == "\\":
            raise ValueError('path is absolute without a drive letter: "%s"' % path)
        if os.path.isabs(path):
            return path

        if source_repo is None and not self._repo_mapping.is_empty():
            # Look up runfiles using the repository mapping of the caller of the
            # current method. If the repo mapping is empty, determining this
            # name is not necessary.
            source_repo = self.CurrentRepository(frame=2)

        # Split off the first path component, which contains the repository
        # name (apparent or canonical).
        target_repo, _, remainder = path.partition("/")
        target_canonical = self._repo_mapping.lookup(source_repo, target_repo)
        if not remainder or target_canonical is None:
            # One of the following is the case:
            # - not using Bzlmod, so the repository mapping is empty and
            #   apparent and canonical repository names are the same
            # - target_repo is already a canonical repository name and does not
            #   have to be mapped.
            # - path did not contain a slash and referred to a root symlink,
            #   which also should not be mapped.
            return self._strategy.RlocationChecked(path)

        assert source_repo is not None, (
            "BUG: if the `source_repo` is None, we should never go past the `if` statement above"
        )

        # Look up the target repository using the repository mapping
        if target_canonical is not None:
            return self._strategy.RlocationChecked(target_canonical + "/" + remainder)

        # No mapping found - assume target_repo is already canonical or
        # we're not using Bzlmod
        return self._strategy.RlocationChecked(path)

    def EnvVars(self) -> dict[str, str]:
        """Returns environment variables for subprocesses.

        The caller should set the returned key-value pairs in the environment of
        subprocesses in case those subprocesses are also Bazel-built binaries that
        need to use runfiles.

        Returns:
          {string: string}; a dict; keys are environment variable names, values are
          the values for these environment variables
        """
        return self._strategy.EnvVars()

    def CurrentRepository(self, frame: int = 1) -> str:
        """Returns the canonical name of the caller's Bazel repository.

        For example, this function returns '' (the empty string) when called
        from the main repository and a string of the form
        'rules_python~0.13.0` when called from code in the repository
        corresponding to the rules_python Bazel module.

        More information about the difference between canonical repository
        names and the `@repo` part of labels is available at:
        <https://bazel.build/build/bzlmod#repository-names>

        NOTE: This function inspects the callstack to determine where in the
        runfiles the caller is located to determine which repository it came
        from. This may fail or produce incorrect results depending on who the
        caller is, for example if it is not represented by a Python source
        file. Use the `frame` argument to control the stack lookup.

        Args:
            frame: int; the stack frame to return the repository name for.
            Defaults to 1, the caller of the CurrentRepository function.

        Returns:
            The canonical name of the Bazel repository containing the file
            containing the frame-th caller of this function

        Raises:
            ValueError: if the caller cannot be determined or the caller's file
            path is not contained in the Python runfiles tree
        """
        try:
            # pylint: disable-next=protected-access
            caller_path = inspect.getfile(sys._getframe(frame))
        except (TypeError, ValueError) as exc:
            raise ValueError("failed to determine caller's file path") from exc
        caller_runfiles_path = os.path.relpath(caller_path, self._python_runfiles_root)
        if caller_runfiles_path.startswith(".." + os.path.sep):
            # With Python 3.10 and earlier, sys.path contains the directory
            # of the script, which can result in a module being loaded from
            # outside the runfiles tree. In this case, assume that the module is
            # located in the main repository.
            # With Python 3.11 and higher, the Python launcher sets
            # PYTHONSAFEPATH, which prevents this behavior.
            # On Windows, the current toolchain being used has a buggy zip file
            # bootstrap, which leaves RUNFILES_DIR pointing at the first stage
            # path and not the module path. In this case too, assume that the
            # module is located in the main repository.
            # TODO: This doesn't cover the case of a script being run from an
            #       external repository, which could be heuristically detected
            #       by parsing the script's path.
            if (sys.version_info.minor <= 10 or sys.platform == "win32") and sys.path[
                0
            ] != self._python_runfiles_root:
                return ""
            raise ValueError(
                "{} does not lie under the runfiles root {}".format(
                    caller_path, self._python_runfiles_root
                )
            )

        caller_runfiles_directory = caller_runfiles_path[
            : caller_runfiles_path.find(os.path.sep)
        ]
        # With Bzlmod, the runfiles directory of the main repository is always
        # named "_main". Without Bzlmod, the value returned by this function is
        # never used, so we just assume Bzlmod is enabled.
        if caller_runfiles_directory == "_main":
            # The canonical name of the main repository (also known as the
            # workspace) is the empty string.
            return ""
        # For all other repositories, the name of the runfiles directory is the
        # canonical name.
        return caller_runfiles_directory

    # TODO: Update return type to Self when 3.11 is the min version
    # https://peps.python.org/pep-0673/
    @staticmethod
    def CreateManifestBased(manifest_path: str) -> "Runfiles":
        return Runfiles(_ManifestBased(manifest_path))

    # TODO: Update return type to Self when 3.11 is the min version
    # https://peps.python.org/pep-0673/
    @staticmethod
    def CreateDirectoryBased(runfiles_dir_path: str) -> "Runfiles":
        return Runfiles(_DirectoryBased(runfiles_dir_path))

    # TODO: Update return type to Self when 3.11 is the min version
    # https://peps.python.org/pep-0673/
    @staticmethod
    def Create(env: dict[str, str] | None = None) -> Runfiles | None:
        """Returns a new `Runfiles` instance.

        The returned object is either:
        - manifest-based, meaning it looks up runfile paths from a manifest file, or
        - directory-based, meaning it looks up runfile paths under a given directory
        path

        If `env` contains "RUNFILES_MANIFEST_FILE" with non-empty value, this method
        returns a manifest-based implementation. The object eagerly reads and caches
        the whole manifest file upon instantiation; this may be relevant for
        performance consideration.

        Otherwise, if `env` contains "RUNFILES_DIR" with non-empty value (checked in
        this priority order), this method returns a directory-based implementation.

        If neither cases apply, this method returns null.

        Args:
        env: {string: string}; optional; the map of environment variables. If None,
            this function uses the environment variable map of this process.
        Raises:
        IOError: if some IO error occurs.
        """
        env_map = os.environ if env is None else env
        manifest = env_map.get("RUNFILES_MANIFEST_FILE")
        if manifest:
            return CreateManifestBased(manifest)

        directory = env_map.get("RUNFILES_DIR")
        if directory:
            return CreateDirectoryBased(directory)

        return None

    # TODO: Update return type to Self when 3.11 is the min version
    # https://peps.python.org/pep-0673/
    @staticmethod
    def CreateOrRaise(env: dict[str, str] | None = None) -> Runfiles:
        """Returns a new `Runfiles` instance, or raises an error.

        The returned object is either:
        - manifest-based, meaning it looks up runfile paths from a manifest
          file, or
        - directory-based, meaning it looks up runfile paths under a given
          directory path

        If `env` contains "RUNFILES_MANIFEST_FILE" with non-empty value, this
        method returns a manifest-based implementation. The object eagerly
        reads and caches the whole manifest file upon instantiation; this may
        be relevant for performance consideration.

        Otherwise, if `env` contains "RUNFILES_DIR" with non-empty value
        (checked in this priority order), this method returns a directory-based
        implementation.

        If neither cases apply, this method raises a `RuntimeError`.

        Args:
          env: {string: string}; optional; the map of environment variables. If
            None, this function uses the environment variable map of this
            process.
        Raises:
          RuntimeError: if runfiles cannot be found.

        :::{versionadded} VERSION_NEXT_FEATURE
        :::
        """
        runfiles = Runfiles.Create(env=env)
        if runfiles is None:
            raise RuntimeError(
                "Cannot create Runfiles: $RUNFILES_MANIFEST_FILE and $RUNFILES_DIR are both unset or empty"
            )
        return runfiles


# Support legacy imports by defining a private symbol.
_Runfiles = Runfiles


def CreateManifestBased(manifest_path: str) -> Runfiles:
    return Runfiles.CreateManifestBased(manifest_path)


def CreateDirectoryBased(runfiles_dir_path: str) -> Runfiles:
    return Runfiles.CreateDirectoryBased(runfiles_dir_path)


def Create(env: dict[str, str] | None = None) -> Runfiles | None:
    return Runfiles.Create(env)


def CreateOrRaise(env: dict[str, str] | None = None) -> Runfiles:
    """Refer to `Runfiles.CreateOrRaise`.

    :::{versionadded} VERSION_NEXT_FEATURE
    :::
    """
    return Runfiles.CreateOrRaise(env)
