8000 chore: publish a runfiles library as a wheel (#995) · bazel-contrib/rules_python@1722988 · GitHub
[go: up one dir, main page]

Skip to content

Commit 1722988

Browse files
alexeaglerickeylev
andauthored
chore: publish a runfiles library as a wheel (#995)
* chore: publish a runfiles library as a wheel 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. * Apply suggestions from code review Co-authored-by: Richard Levasseur <richardlev@gmail.com> * more code review cleanup Co-authored-by: Richard Levasseur <richardlev@gmail.com>
1 parent bd3a719 commit 1722988

File tree

6 files changed

+99
-45
lines changed

6 files changed

+99
-45
lines changed

.github/workflows/release.yml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,17 @@ jobs:
1313
- name: Checkout
1414
uses: actions/checkout@v2
1515
- name: Prepare workspace snippet
16-
run: .github/workflows/workspace_snippet.sh ${{ env.GITHUB_REF_NAME }} > release_notes.txt
16+
run: .github/workflows/workspace_snippet.sh > release_notes.txt
17+
- name: Build wheel dist
18+
run: bazel build --stamp --embed_label=${{ env.GITHUB_REF_NAME }} //python/runfiles:wheel
19+
- name: Publish runfiles package to PyPI
20+
uses: pypa/gh-action-pypi-publish@release/v1
21+
with:
22+
# Note, the PYPI_API_TOKEN was added on
23+
# https://github.com/bazelbuild/rules_python/settings/secrets/actions
24+
# and currently uses a token which authenticates as https://pypi.org/user/alexeagle/
25+
password: ${{ secrets.PYPI_API_TOKEN }}
26+
packages_dir: bazel-bin/python/runfiles
1727
- name: Release
1828
uses: softprops/action-gh-release@v1
1929
with:

python/runfiles/BUILD.bazel

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# limitations under the License.
1414

1515
load("//python:defs.bzl", "py_library")
16+
load("//python: 8000 packaging.bzl", "py_wheel")
1617

1718
filegroup(
1819
name = "distribution",
@@ -22,6 +23,28 @@ filegroup(
2223

2324
py_library(
2425
name = "runfiles",
25-
srcs = ["runfiles.py"],
26+
srcs = [
27+
"__init__.py",
28+
"runfiles.py",
29+
],
2630
visibility = ["//visibility:public"],
2731
)
32+
33+
# This can be manually tested by running tests/runfiles/runfiles_wheel_integration_test.sh
34+
# We ought to have an automated integration test for it, too.
35+
# see https://github.com/bazelbuild/rules_python/issues/1002
36+
py_wheel(
37+
name = "wheel",
38+
# From https://pypi.org/classifiers/
39+
classifiers = [
40+
"Development Status :: 5 - Production/Stable",
41+
"License :: OSI Approved :: Apache Software License",
42+
],
43+
description_file = "README.md",
44+
distribution = "bazel_runfiles",
45+
homepage = "https://github.com/bazelbuild/rules_python",
46+
strip_path_prefixes = ["python"],
47+
version = "{BUILD_EMBED_LABEL}",
48+
visibility = ["//visibility:public"],
49+
deps = [":runfiles"],
50+
)

python/runfiles/README.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# bazel-runfiles library
2+
3+
This is a Bazel Runfiles lookup library for Bazel-built Python binaries and tests.
4+
5+
Typical Usage
6+
-------------
7+
8+
1. Add the 'runfiles' dependency along with other third-party dependencies, for example in your
9+
`requirements.txt` file.
10+
11+
2. Depend on this runfiles library from your build rule, like you would other third-party libraries.
12+
13+
py_binary(
14+
name = "my_binary",
15+
...
16+
deps = [requirement("runfiles")],
17+
)
18+
19+
3. Import the runfiles library.
20+
21+
import runfiles # not "from runfiles import runfiles"
22+
23+
4. Create a Runfiles object and use rlocation to look up runfile paths:
24+
25+
r = runfiles.Create()
26+
...
27+
with open(r.Rlocation("my_workspace/path/to/my/data.txt"), "r") as f:
28+
contents = f.readlines()
29+
...
30+
31+
The code above creates a manifest- or directory-based implementations based
32+
on the environment variables in os.environ. See `Create()` for more info.
33+
34+
If you want to explicitly create a manifest- or directory-based
35+
implementations, you can do so as follows:
36+
37+
r1 = runfiles.CreateManifestBased("path/to/foo.runfiles_manifest")
38+
39+
r2 = runfiles.CreateDirectoryBased("path/to/foo.runfiles/")
40+
41+
If you wnat to start subprocesses, and the subprocess can't automatically
42+
find the correct runfiles directory, you can explicitly set the right
43+
environment variables for them:
44+
45+
import subprocess
46+
import runfiles
47+
48+
r = runfiles.Create()
49+
env = {}
50+
...
51+
env.update(r.EnvVars())
52+
p = subprocess.Popen([r.Rlocation("path/to/binary")], env, ...)

python/runfiles/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from .runfiles import *

python/runfiles/runfiles.py

Lines changed: 1 addition & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -14,49 +14,7 @@
1414

1515
"""Runfiles lookup library for Bazel-built Python binaries and tests.
1616
17-
USAGE:
18-
19-
1. Depend on this runfiles library from your build rule:
20-
21-
py_binary(
22-
name = "my_binary",
23-
...
24-
deps = ["@rules_python//python/runfiles"],
25-
)
26-
27-
2. Import the runfiles library.
28-
29-
from python.runfiles import runfiles
30-
31-
3. Create a Runfiles object and use rlocation to look up runfile paths:
32-
33-
r = runfiles.Create()
34-
...
35-
with open(r.Rlocation("my_workspace/path/to/my/data.txt"), "r") as f:
36-
contents = f.readlines()
37-
...
38-
39-
The code above creates a manifest- or directory-based implementations based
40-
on the environment variables in os.environ. See `Create()` for more info.
41-
42-
If you want to explicitly create a manifest- or directory-based
43-
implementations, you can do so as follows:
44-
45-
r1 = runfiles.CreateManifestBased("path/to/foo.runfiles_manifest")
46-
47-
r2 = runfiles.CreateDirectoryBased("path/to/foo.runfiles/")
48-
49-
If you want to start subprocesses that also need runfiles, you need to set
50-
the right environment variables fo 8000 r them:
51-
52-
import subprocess
53-
from bazel_tools.tools.python.runfiles import runfiles
54-
55-
r = runfiles.Create()
56-
env = {}
57-
...
58-
env.update(r.EnvVars())
59-
p = subprocess.Popen([r.Rlocation("path/to/binary")], env, ...)
17+
See README.md for usage instructions.
6018
"""
6119
import inspect
6220
import os
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/usr/bin/env bash
2+
# Manual test, run outside of Bazel, to check that our runfiles wheel should be functional
3+
# for users who install it from pypi.
4+
set -o errexit
5+
6+
SCRIPTPATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
7+
8+
bazel 2>/dev/null build --stamp --embed_label=1.2.3 //python/runfiles:wheel
9+
wheelpath=$SCRIPTPATH/../../$(bazel 2>/dev/null cquery --output=files //python/runfiles:wheel)
10+
PYTHONPATH=$wheelpath python3 -c 'import importlib;print(importlib.import_module("runfiles"))'

0 commit comments

Comments
 (0)
0