aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/tools/runfiles
diff options
context:
space:
mode:
authorGravatar Laszlo Csomor <laszlocsomor@google.com>2018-04-10 02:18:48 -0700
committerGravatar Copybara-Service <copybara-piper@google.com>2018-04-10 02:19:57 -0700
commitf7549a6c2484d314c10fe8fe52c2d24d2a7de19e (patch)
tree0cc2aba07df33fd3b9a05bc875a4d601472370c5 /src/tools/runfiles
parentada8b30b6c1f7013e808dfee75655ffeee505be5 (diff)
python,runfiles: move to different package
Move the Python runfiles library from `@bazel_tools//tools/runfiles:py-runfiles` to `@bazel_tools//tools/python/runfiles:runfiles` Also rename the testdata runfiles.py to foo.py. This file was not a mock runfiles library, just a client file using the runfiles library that was also called runfiles.py Fixes https://github.com/bazelbuild/bazel/issues/4878 Change-Id: I874b230c93679d4454ac91e816932c8272ecc5c7 Closes #4981. Change-Id: I908e0ab7ec61225e82f70793b1a05432e7f0b07e PiperOrigin-RevId: 192256481
Diffstat (limited to 'src/tools/runfiles')
-rw-r--r--src/tools/runfiles/BUILD13
-rw-r--r--src/tools/runfiles/runfiles.py221
-rw-r--r--src/tools/runfiles/runfiles_test.py182
3 files changed, 0 insertions, 416 deletions
diff --git a/src/tools/runfiles/BUILD b/src/tools/runfiles/BUILD
index 0df3386cad..81e156d4b7 100644
--- a/src/tools/runfiles/BUILD
+++ b/src/tools/runfiles/BUILD
@@ -22,24 +22,11 @@ filegroup(
"BUILD.tools",
"runfiles.cc",
"runfiles.h",
- "runfiles.py",
"//src/tools/runfiles/java/com/google/devtools/build/runfiles:embedded_tools",
],
visibility = ["//src:__pkg__"],
)
-py_library(
- name = "py-runfiles",
- srcs = ["runfiles.py"],
-)
-
-py_test(
- name = "py-runfiles-test",
- srcs = ["runfiles_test.py"],
- main = "runfiles_test.py",
- deps = [":py-runfiles"],
-)
-
cc_library(
name = "cc-runfiles",
srcs = ["runfiles.cc"],
diff --git a/src/tools/runfiles/runfiles.py b/src/tools/runfiles/runfiles.py
deleted file mode 100644
index e4938b74b2..0000000000
--- a/src/tools/runfiles/runfiles.py
+++ /dev/null
@@ -1,221 +0,0 @@
-# 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.
-
-Usage:
-
-from bazel_tools.tools.runfiles import runfiles
-
-r = runfiles.Create()
-with open(r.Rlocation("io_bazel/foo/bar.txt"), "r") as f:
- contents = f.readlines()
-
-The code above creates a manifest- or directory-based implementations based on
-the environment variables in os.environ. See `Create()` for more info.
-
-If you want to explicitly create a manifest- or directory-based
-implementations, you can do so as follows:
-
- r1 = runfiles.CreateManifestBased("path/to/foo.runfiles_manifest")
-
- r2 = runfiles.CreateDirectoryBased("path/to/foo.runfiles/")
-
-If you want to start subprocesses that also need runfiles, you need to set the
-right environment variables for them:
-
- import subprocess
- from bazel_tools.tools.runfiles import runfiles
-
- r = runfiles.Create()
- env = {}
- ...
- env.update(r.EnvVars())
- p = subprocess.Popen([r.Rlocation("path/to/binary")], env, ...)
-"""
-
-import os
-import posixpath
-
-
-def CreateManifestBased(manifest_path):
- return _Runfiles(_ManifestBased(manifest_path))
-
-
-def CreateDirectoryBased(runfiles_dir_path):
- return _Runfiles(_DirectoryBased(runfiles_dir_path))
-
-
-def Create(env=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
-
-
-class _Runfiles(object):
- """Returns the runtime location of runfiles.
-
- Runfiles are data-dependencies of Bazel-built binaries and tests.
- """
-
- def __init__(self, strategy):
- self._strategy = strategy
-
- def Rlocation(self, path):
- """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
- 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 contains
- uplevel references
- """
- if not path:
- raise ValueError()
- if not isinstance(path, str):
- raise TypeError()
- if ".." in path:
- raise ValueError("path contains uplevel references: \"%s\"" % path)
- if path[0] == "\\":
- raise ValueError("path is absolute without a drive letter: \"%s\"" % path)
- if os.path.isabs(path):
- return path
- return self._strategy.RlocationChecked(path)
-
- def EnvVars(self):
- """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()
-
-
-class _ManifestBased(object):
- """`Runfiles` strategy that parses a runfiles-manifest to look up runfiles."""
-
- def __init__(self, path):
- if not path:
- raise ValueError()
- if not isinstance(path, str):
- raise TypeError()
- self._path = path
- self._runfiles = _ManifestBased._LoadRunfiles(path)
-
- def RlocationChecked(self, path):
- return self._runfiles.get(path)
-
- @staticmethod
- def _LoadRunfiles(path):
- """Loads the runfiles manifest."""
- result = {}
- with open(path, "r") as f:
- for line in f:
- line = line.strip()
- if line:
- tokens = line.split(" ", 1)
- if len(tokens) == 1:
- result[line] = line
- else:
- result[tokens[0]] = tokens[1]
- return result
-
- def _GetRunfilesDir(self):
- if self._path.endswith("/MANIFEST") or self._path.endswith("\\MANIFEST"):
- return self._path[:-len("/MANIFEST")]
- elif self._path.endswith(".runfiles_manifest"):
- return self._path[:-len("_manifest")]
- else:
- return ""
-
- def EnvVars(self):
- 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(object):
- """`Runfiles` strategy that appends runfiles paths to the runfiles root."""
-
- def __init__(self, path):
- if not path:
- raise ValueError()
- if not isinstance(path, str):
- raise TypeError()
- self._runfiles_root = path
-
- def RlocationChecked(self, path):
- # 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):
- 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,
- }
diff --git a/src/tools/runfiles/runfiles_test.py b/src/tools/runfiles/runfiles_test.py
deleted file mode 100644
index cfc3275288..0000000000
--- a/src/tools/runfiles/runfiles_test.py
+++ /dev/null
@@ -1,182 +0,0 @@
-# pylint: disable=g-bad-file-header
-# 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.
-
-import os
-import tempfile
-import unittest
-
-from src.tools.runfiles import runfiles
-
-
-class RunfilesTest(unittest.TestCase):
- # """Unit tests for `runfiles.Runfiles`."""
-
- def testRlocationArgumentValidation(self):
- r = runfiles.Create({"RUNFILES_DIR": "whatever"})
- self.assertRaises(ValueError, lambda: r.Rlocation(None))
- self.assertRaises(ValueError, lambda: r.Rlocation(""))
- self.assertRaises(TypeError, lambda: r.Rlocation(1))
- self.assertRaisesRegexp(ValueError, "contains uplevel",
- lambda: r.Rlocation("foo/.."))
- self.assertRaisesRegexp(ValueError, "is absolute without a drive letter",
- lambda: r.Rlocation("\\foo"))
-
- def testCreatesManifestBasedRunfiles(self):
- with _MockFile(contents=["a/b c/d"]) as mf:
- r = runfiles.Create({
- "RUNFILES_MANIFEST_FILE": mf.Path(),
- "RUNFILES_DIR": "ignored when RUNFILES_MANIFEST_FILE has a value",
- "TEST_SRCDIR": "always ignored",
- })
- self.assertEqual(r.Rlocation("a/b"), "c/d")
- self.assertIsNone(r.Rlocation("foo"))
-
- def testManifestBasedRunfilesEnvVars(self):
- with _MockFile(name="MANIFEST") as mf:
- r = runfiles.Create({
- "RUNFILES_MANIFEST_FILE": mf.Path(),
- "TEST_SRCDIR": "always ignored",
- })
- self.assertDictEqual(
- r.EnvVars(), {
- "RUNFILES_MANIFEST_FILE": mf.Path(),
- "RUNFILES_DIR": mf.Path()[:-len("/MANIFEST")],
- "JAVA_RUNFILES": mf.Path()[:-len("/MANIFEST")],
- })
-
- with _MockFile(name="foo.runfiles_manifest") as mf:
- r = runfiles.Create({
- "RUNFILES_MANIFEST_FILE": mf.Path(),
- "TEST_SRCDIR": "always ignored",
- })
- self.assertDictEqual(
- r.EnvVars(), {
- "RUNFILES_MANIFEST_FILE":
- mf.Path(),
- "RUNFILES_DIR": (
- mf.Path()[:-len("foo.runfiles_manifest")] + "foo.runfiles"),
- "JAVA_RUNFILES": (
- mf.Path()[:-len("foo.runfiles_manifest")] + "foo.runfiles"),
- })
-
- with _MockFile(name="x_manifest") as mf:
- r = runfiles.Create({
- "RUNFILES_MANIFEST_FILE": mf.Path(),
- "TEST_SRCDIR": "always ignored",
- })
- self.assertDictEqual(
- r.EnvVars(), {
- "RUNFILES_MANIFEST_FILE": mf.Path(),
- "RUNFILES_DIR": "",
- "JAVA_RUNFILES": "",
- })
-
- def testCreatesDirectoryBasedRunfiles(self):
- r = runfiles.Create({
- "RUNFILES_DIR": "runfiles/dir",
- "TEST_SRCDIR": "always ignored",
- })
- self.assertEqual(r.Rlocation("a/b"), "runfiles/dir/a/b")
- self.assertEqual(r.Rlocation("foo"), "runfiles/dir/foo")
-
- def testDirectoryBasedRunfilesEnvVars(self):
- r = runfiles.Create({
- "RUNFILES_DIR": "runfiles/dir",
- "TEST_SRCDIR": "always ignored",
- })
- self.assertDictEqual(r.EnvVars(), {
- "RUNFILES_DIR": "runfiles/dir",
- "JAVA_RUNFILES": "runfiles/dir",
- })
-
- def testFailsToCreateManifestBasedBecauseManifestDoesNotExist(self):
-
- def _Run():
- runfiles.Create({"RUNFILES_MANIFEST_FILE": "non-existing path"})
-
- self.assertRaisesRegexp(IOError, "non-existing path", _Run)
-
- def testFailsToCreateAnyRunfilesBecauseEnvvarsAreNotDefined(self):
- with _MockFile(contents=["a b"]) as mf:
- runfiles.Create({
- "RUNFILES_MANIFEST_FILE": mf.Path(),
- "RUNFILES_DIR": "whatever",
- "TEST_SRCDIR": "always ignored",
- })
- runfiles.Create({
- "RUNFILES_DIR": "whatever",
- "TEST_SRCDIR": "always ignored",
- })
- self.assertIsNone(runfiles.Create({"TEST_SRCDIR": "always ignored"}))
- self.assertIsNone(runfiles.Create({"FOO": "bar"}))
-
- def testManifestBasedRlocation(self):
- with _MockFile(contents=[
- "Foo/runfile1", "Foo/runfile2 C:/Actual Path\\runfile2",
- "Foo/Bar/runfile3 D:\\the path\\run file 3.txt"
- ]) as mf:
- r = runfiles.CreateManifestBased(mf.Path())
- self.assertEqual(r.Rlocation("Foo/runfile1"), "Foo/runfile1")
- self.assertEqual(r.Rlocation("Foo/runfile2"), "C:/Actual Path\\runfile2")
- self.assertEqual(
- r.Rlocation("Foo/Bar/runfile3"), "D:\\the path\\run file 3.txt")
- self.assertIsNone(r.Rlocation("unknown"))
- if RunfilesTest.IsWindows():
- self.assertEqual(r.Rlocation("c:/foo"), "c:/foo")
- self.assertEqual(r.Rlocation("c:\\foo"), "c:\\foo")
- else:
- self.assertEqual(r.Rlocation("/foo"), "/foo")
-
- def testDirectoryBasedRlocation(self):
- # The _DirectoryBased strategy simply joins the runfiles directory and the
- # runfile's path on a "/". This strategy does not perform any normalization,
- # nor does it check that the path exists.
- r = runfiles.CreateDirectoryBased("foo/bar baz//qux/")
- self.assertEqual(r.Rlocation("arg"), "foo/bar baz//qux/arg")
- if RunfilesTest.IsWindows():
- self.assertEqual(r.Rlocation("c:/foo"), "c:/foo")
- self.assertEqual(r.Rlocation("c:\\foo"), "c:\\foo")
- else:
- self.assertEqual(r.Rlocation("/foo"), "/foo")
-
- @staticmethod
- def IsWindows():
- return os.name == "nt"
-
-
-class _MockFile(object):
-
- def __init__(self, name=None, contents=None):
- self._contents = contents or []
- self._name = name or "x"
- self._path = None
-
- def __enter__(self):
- tmpdir = os.environ.get("TEST_TMPDIR")
- self._path = os.path.join(tempfile.mkdtemp(dir=tmpdir), self._name)
- with open(self._path, "wt") as f:
- f.writelines(l + "\n" for l in self._contents)
- return self
-
- def __exit__(self, exc_type, exc_value, traceback):
- os.remove(self._path)
- os.rmdir(os.path.dirname(self._path))
-
- def Path(self):
- return self._path
-
-
-if __name__ == "__main__":
- unittest.main()