Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions python/runfiles/runfiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,16 +68,23 @@
import os
import posixpath

if False:
# Mypy needs these symbols imported, but since they only exist in python 3.5+,
# this import may fail at runtime. Luckily mypy can follow this conditional import.
from typing import Callable, Dict, Optional, Tuple, Union

def CreateManifestBased(manifest_path):
# type: (str) -> _Runfiles
return _Runfiles(_ManifestBased(manifest_path))


def CreateDirectoryBased(runfiles_dir_path):
# type: (str) -> _Runfiles
return _Runfiles(_DirectoryBased(runfiles_dir_path))


def Create(env=None):
# type: (Optional[Dict[str, str]]) -> Optional[_Runfiles]
"""Returns a new `Runfiles` instance.

The returned object is either:
Expand Down Expand Up @@ -120,9 +127,11 @@ class _Runfiles(object):
"""

def __init__(self, strategy):
# type: (Union[_ManifestBased, _DirectoryBased]) -> None
self._strategy = strategy

def Rlocation(self, path):
# type: (str) -> Optional[str]
"""Returns the runtime path of a runfile.

Runfiles are data-dependencies of Bazel-built binaries and tests.
Expand Down Expand Up @@ -162,6 +171,7 @@ def Rlocation(self, path):
return self._strategy.RlocationChecked(path)

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

The caller should set the returned key-value pairs in the environment of
Expand All @@ -179,6 +189,7 @@ class _ManifestBased(object):
"""`Runfiles` strategy that parses a runfiles-manifest to look up runfiles."""

def __init__(self, path):
# type: (str) -> None
if not path:
raise ValueError()
if not isinstance(path, str):
Expand All @@ -187,10 +198,12 @@ def __init__(self, path):
self._runfiles = _ManifestBased._LoadRunfiles(path)

def RlocationChecked(self, path):
# type: (str) -> Optional[str]
return self._runfiles.get(path)

@staticmethod
def _LoadRunfiles(path):
# type: (str) -> Dict[str, str]
"""Loads the runfiles manifest."""
result = {}
with open(path, "r") as f:
Expand All @@ -205,6 +218,7 @@ def _LoadRunfiles(path):
return result

def _GetRunfilesDir(self):
# type: () -> str
if self._path.endswith("/MANIFEST") or self._path.endswith("\\MANIFEST"):
return self._path[: -len("/MANIFEST")]
elif self._path.endswith(".runfiles_manifest"):
Expand All @@ -213,6 +227,7 @@ def _GetRunfilesDir(self):
return ""

def EnvVars(self):
# type: () -> Dict[str, str]
directory = self._GetRunfilesDir()
return {
"RUNFILES_MANIFEST_FILE": self._path,
Expand All @@ -227,19 +242,23 @@ class _DirectoryBased(object):
"""`Runfiles` strategy that appends runfiles paths to the runfiles root."""

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

def RlocationChecked(self, path):
# type: (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 EnvVars(self):
# type: () -> Dict[str, str]
return {
"RUNFILES_DIR": self._runfiles_root,
# TODO(laszlocsomor): remove JAVA_RUNFILES once the Java launcher can
Expand All @@ -251,6 +270,7 @@ def EnvVars(self):
def _PathsFrom(
argv0, runfiles_mf, runfiles_dir, is_runfiles_manifest, is_runfiles_directory
):
# type: (str, str, str, Callable[[str], bool], Callable[[str], bool]) -> Tuple[str, str]
"""Discover runfiles manifest and runfiles directory paths.

Args:
Expand Down