Skip to content

Commit

Permalink
chore: publish a runfiles library as a wheel
Browse files Browse the repository at this point in the history
Wire it up to GH actions so it is published for each release.

Tested locally with:
bazel build python/runfiles:wheel --embed_label=1.0.2 --stamp
PYTHONPATH=bazel-bin/python/runfiles/bazel_runfiles-_BUILD_EMBED_LABEL_-py3-none-any.whl python
>>> import runfiles
>>> runfiles.Create()

Note, I would have liked to call the package bazel-runfiles, but this isn't possible without either refactoring the paths in this repo, or doing some fancy starlark to copy files around to create a folder that we turn into the wheel.
There is no project https://pypi.org/project/runfiles though there is a https://pypi.org/project/runfile

We could try harder to get the name we prefer.
  • Loading branch information
alexeagle committed Jan 19, 2023
1 parent aab11ab commit 0e5b5f8
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 46 deletions.
12 changes: 11 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,17 @@ jobs:
- name: Checkout
uses: actions/checkout@v2
- name: Prepare workspace snippet
run: .github/workflows/workspace_snippet.sh ${{ env.GITHUB_REF_NAME }} > release_notes.txt
run: .github/workflows/workspace_snippet.sh > release_notes.txt
- name: Build wheel dist
run: bazel build --stamp --embed_label=${{ env.GITHUB_REF_NAME }} //python/runfiles:wheel
- name: Publish runfiles package to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
# Note, the PYPI_API_TOKEN was added on
# https://github.com/bazelbuild/rules_python/settings/secrets/actions
# and currently uses a token which authenticates as https://pypi.org/user/alexeagle/
password: ${{ secrets.PYPI_API_TOKEN }}
packages_dir: bazel-bin/python/runfiles
- name: Release
uses: softprops/action-gh-release@v1
with:
Expand Down
23 changes: 22 additions & 1 deletion python/runfiles/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
# limitations under the License.

load("//python:defs.bzl", "py_library")
load("//python:packaging.bzl", "py_wheel")

filegroup(
name = "distribution",
Expand All @@ -22,6 +23,26 @@ filegroup(

py_library(
name = "runfiles",
srcs = ["runfiles.py"],
srcs = [
"__init__.py",
"runfiles.py",
],
visibility = ["//visibility:public"],
)

# TODO(alexeagle): add some example which depends on this wheel to verify it can be used
py_wheel(
name = "wheel",
# From https://pypi.org/classifiers/
classifiers = [
"Development Status :: 5 - Production/Stable",
"License :: OSI Approved :: Apache Software License",
],
description_file = "README.md",
distribution = "bazel_runfiles",
homepage = "https://github.com/bazelbuild/rules_python",
strip_path_prefixes = ["python"],
version = "{BUILD_EMBED_LABEL}",
visibility = ["//visibility:public"],
deps = [":runfiles"],
)
51 changes: 51 additions & 0 deletions python/runfiles/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# bazel-runfiles library

This is a Bazel Runfiles lookup library for Bazel-built Python binaries and tests.

Typical Usage
-------------

1. Add the 'runfiles' dependency along with other third-party dependencies, for example in your
`requirements.txt` file.

2. Depend on this runfiles library from your build rule, like you would other third-party libraries.

py_binary(
name = "my_binary",
...
deps = [requirement("runfiles")],
)

3. Import the runfiles library.

import runfiles

4. Create a Runfiles object and use rlocation to look up runfile paths:

r = runfiles.Create()
...
with open(r.Rlocation("my_workspace/path/to/my/data.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
import runfiles

r = runfiles.Create()
env = {}
...
env.update(r.EnvVars())
p = subprocess.Popen([r.Rlocation("path/to/binary")], env, ...)
1 change: 1 addition & 0 deletions python/runfiles/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .runfiles import *
44 changes: 0 additions & 44 deletions python/runfiles/runfiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,50 +13,6 @@
# limitations under the License.

"""Runfiles lookup library for Bazel-built Python binaries and tests.
USAGE:
1. Depend on this runfiles library from your build rule:
py_binary(
name = "my_binary",
...
deps = ["@rules_python//python/runfiles"],
)
2. Import the runfiles library.
from python.runfiles import runfiles
3. Create a Runfiles object and use rlocation to look up runfile paths:
r = runfiles.Create()
...
with open(r.Rlocation("my_workspace/path/to/my/data.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.python.runfiles import runfiles
r = runfiles.Create()
env = {}
...
env.update(r.EnvVars())
p = subprocess.Popen([r.Rlocation("path/to/binary")], env, ...)
"""

import os
Expand Down

0 comments on commit 0e5b5f8

Please sign in to comment.