-
Notifications
You must be signed in to change notification settings - Fork 558
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: enable local packages and PROJECT_ROOT expansion in requirements files #2517
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
load("@rules_python//python:defs.bzl", "py_test") | ||
load("@rules_python//python/entry_points:py_console_script_binary.bzl", "py_console_script_binary") | ||
|
||
py_test( | ||
name = "test_hello", | ||
srcs = ["test_hello.py"], | ||
deps = [ | ||
"@pypi//hello", | ||
], | ||
) | ||
|
||
py_console_script_binary( | ||
name = "hello_parse", | ||
pkg = "@pypi//hello", | ||
script = "parse", | ||
) | ||
|
||
sh_test( | ||
name = "test_hello_script", | ||
srcs = ["test_hello_script.sh"], | ||
data = [":hello_parse"], | ||
env = { | ||
"HELLO_PARSE": "$(rootpaths :hello_parse)", | ||
}, | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
module(name = "rules_python_pip_parse_local_package_example") | ||
|
||
bazel_dep(name = "rules_python", version = "0.0.0") | ||
local_path_override( | ||
module_name = "rules_python", | ||
path = "../..", | ||
) | ||
|
||
python = use_extension("@rules_python//python/extensions:python.bzl", "python") | ||
python.toolchain( | ||
# We can specify the exact version. | ||
python_version = "3.9.13", | ||
) | ||
|
||
pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip") | ||
pip.parse( | ||
hub_name = "pypi", | ||
# If we want to expand the PROJECT_ROOT variable in the requirement lock file, | ||
# we need to pass a label to the file defining the project root. | ||
project_root = "//:pyproject.toml", | ||
# We need to use the same version here as in the `python.toolchain` call. | ||
python_version = "3.9.13", | ||
requirements_lock = "//:requirements_lock.txt", | ||
) | ||
use_repo(pip, "pypi", "pypi_39_hello") |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
[project] | ||
name = "test" | ||
version = "0.0.0" | ||
dependencies = [ | ||
# Test | ||
"hello @ file://${PROJECT_ROOT}/hello", | ||
] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# This file was autogenerated by uv via the following command: | ||
# uv pip compile pyproject.toml -o requirements_lock.txt | ||
hello @ file://${PROJECT_ROOT}/hello | ||
# via test (pyproject.toml) | ||
hjson==3.1.0 | ||
# via hello |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import hello | ||
|
||
EXAMPLE_HJSON = """ | ||
{ | ||
# TL;DR | ||
human: Hjson | ||
machine: JSON | ||
} | ||
""" | ||
|
||
res = hello.parse(EXAMPLE_HJSON) | ||
assert res["human"] == "Hjson" | ||
assert res["machine"] == "JSON" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
TEST_HJSON=$(mktemp) | ||
|
||
echo "{ | ||
# TL;DR | ||
human: Hjson | ||
machine: JSON | ||
}" > $TEST_HJSON | ||
|
||
$HELLO_PARSE $TEST_HJSON |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -193,6 +193,10 @@ def _whl_library_impl(rctx): | |
# Manually construct the PYTHONPATH since we cannot use the toolchain here | ||
environment = _create_repository_execution_environment(rctx, python_interpreter, logger = logger) | ||
|
||
# Add a PROJECT_ROOT environment variable | ||
if rctx.attr.project_root: | ||
environment["PROJECT_ROOT"] = str(rctx.path(rctx.attr.project_root).dirname) | ||
|
||
whl_path = None | ||
if rctx.attr.whl_file: | ||
whl_path = rctx.path(rctx.attr.whl_file) | ||
|
@@ -255,6 +259,17 @@ def _whl_library_impl(rctx): | |
logger = logger, | ||
) | ||
|
||
# If the requirement was a local directory, then we need to watch its content | ||
# to recreate the repository when it is modified. | ||
# Assume that such packages are imported using a single line requirement | ||
# of the form [<name> @] file://<path> | ||
# We might have to perform some substitutions in the string before searching. | ||
subst_req = envsubst(rctx.attr.requirement, environment.keys(), lambda x, dft: environment[x]) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See https://github.com/bazelbuild/rules_python/pull/2517/files#diff-c007ed21502bf8ea19b98b3f1b402e7071615f8520e4291b00a71bca2cd451e8R114 how the |
||
if subst_req.startswith("file://"): | ||
_, path = subst_req.split("file://", 1) | ||
logger.info(lambda: "watching tree {} for wheel library {}".format(path, rctx.name)) | ||
rctx.watch_tree(path) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not sure if this is the correct behaviour - will we start watching more than just the intended python files? What if the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes if this is a directory then the correct behaviour should be to fall back to what #2345, or to use |
||
|
||
whl_path = rctx.path(json.decode(rctx.read("whl_file.json"))["whl_file"]) | ||
if not rctx.delete("whl_file.json"): | ||
fail("failed to delete the whl_file.json file") | ||
|
@@ -404,6 +419,9 @@ and the target that we need respectively. | |
"group_name": attr.string( | ||
doc = "Name of the group, if any.", | ||
), | ||
"project_root": attr.label( | ||
doc = "Label of the file defining the project root. If present, this label will be expanded to a path and its parent directory will be made available in the PROJECT_ROOT environment variable when building the wheel.", | ||
), | ||
"repo": attr.string( | ||
mandatory = True, | ||
doc = "Pointer to parent repo name. Used to make these rules rerun if the parent repo changes.", | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need an extra value here instead of adding
PROJECT_ROOT
intoenvsubst
attr?