Skip to content

Commit

Permalink
refactor(uv): move around uv implementation files (#2580)
Browse files Browse the repository at this point in the history
This PR starts establishing a structure that will eventually become a
part of our API. This is a prerequisite for #2578 which removes the
versions.bzl file in favour of a more dynamic configuration of the
extension. We also remove the `defs.bzl` to establish a one symbol per
file convention.

Things that I wish we could change is `//python/uv:extensions.bzl` and
the fact that we have `extensions` in the load path. I think it cannot
be removed, because that may break the BCR test. On the other hand,
maybe we could remove it and do an alpha release to verify this
assumption.

Work towards #1975
  • Loading branch information
aignas authored Jan 26, 2025
1 parent 0475c9e commit 18f76f9
Show file tree
Hide file tree
Showing 15 changed files with 162 additions and 58 deletions.
2 changes: 1 addition & 1 deletion MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ use_repo(

# EXPERIMENTAL: This is experimental and may be removed without notice
uv = use_extension(
"//python/uv:extensions.bzl",
"//python/uv:uv.bzl",
"uv",
dev_dependency = True,
)
Expand Down
6 changes: 5 additions & 1 deletion docs/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
load("@dev_pip//:requirements.bzl", "requirement")
load("//python/private:bzlmod_enabled.bzl", "BZLMOD_ENABLED") # buildifier: disable=bzl-visibility
load("//python/private:util.bzl", "IS_BAZEL_7_OR_HIGHER") # buildifier: disable=bzl-visibility
load("//python/uv/private:lock.bzl", "lock") # buildifier: disable=bzl-visibility
load("//python/uv:lock.bzl", "lock") # buildifier: disable=bzl-visibility
load("//sphinxdocs:readthedocs.bzl", "readthedocs_install")
load("//sphinxdocs:sphinx.bzl", "sphinx_build_binary", "sphinx_docs")
load("//sphinxdocs:sphinx_docs_library.bzl", "sphinx_docs_library")
Expand Down Expand Up @@ -105,6 +105,10 @@ sphinx_stardocs(
"//python/private/api:py_common_api_bzl",
"//python/private/pypi:config_settings_bzl",
"//python/private/pypi:pkg_aliases_bzl",
"//python/uv:lock_bzl",
"//python/uv:uv_bzl",
"//python/uv:uv_toolchain_bzl",
"//python/uv:uv_toolchain_info_bzl",
] + ([
# Bazel 6 + Stardoc isn't able to parse something about the python bzlmod extension
"//python/extensions:python_bzl",
Expand Down
2 changes: 1 addition & 1 deletion examples/bzlmod/MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ python.single_version_platform_override(
use_repo(python, "python_3_10", "python_3_9", "python_versions", "pythons_hub")

# EXPERIMENTAL: This is experimental and may be removed without notice
uv = use_extension("@rules_python//python/uv:extensions.bzl", "uv")
uv = use_extension("@rules_python//python/uv:uv.bzl", "uv")
uv.toolchain(uv_version = "0.4.25")
use_repo(uv, "uv_toolchains")

Expand Down
28 changes: 12 additions & 16 deletions python/uv/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@ filegroup(
visibility = ["//:__subpackages__"],
)

# For stardoc to reference the files
exports_files(["defs.bzl"])

toolchain_type(
name = "uv_toolchain_type",
visibility = ["//visibility:public"],
Expand All @@ -48,34 +45,33 @@ current_toolchain(
)

bzl_library(
name = "defs",
srcs = ["defs.bzl"],
name = "lock_bzl",
srcs = ["lock.bzl"],
# EXPERIMENTAL: Visibility is restricted to allow for changes.
visibility = ["//:__subpackages__"],
deps = ["//python/uv/private:lock_bzl"],
)

bzl_library(
name = "extensions",
srcs = ["extensions.bzl"],
name = "uv_bzl",
srcs = ["uv.bzl"],
# EXPERIMENTAL: Visibility is restricted to allow for changes.
visibility = ["//:__subpackages__"],
deps = [":repositories"],
deps = ["//python/uv/private:uv_bzl"],
)

bzl_library(
name = "repositories",
srcs = ["repositories.bzl"],
name = "uv_toolchain_bzl",
srcs = ["uv_toolchain.bzl"],
# EXPERIMENTAL: Visibility is restricted to allow for changes.
visibility = ["//:__subpackages__"],
deps = [
"//python/uv/private:toolchains_repo",
"//python/uv/private:versions",
],
deps = ["//python/uv/private:uv_toolchain_bzl"],
)

bzl_library(
name = "toolchain",
srcs = ["toolchain.bzl"],
name = "uv_toolchain_info_bzl",
srcs = ["uv_toolchain_info.bzl"],
# EXPERIMENTAL: Visibility is restricted to allow for changes.
visibility = ["//:__subpackages__"],
deps = ["//python/uv/private:uv_toolchain_info_bzl"],
)
22 changes: 22 additions & 0 deletions python/uv/lock.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Copyright 2025 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.

"""The `uv` locking rule.
EXPERIMENTAL: This is experimental and may be removed without notice
"""

load("//python/uv/private:lock.bzl", _lock = "lock")

lock = _lock
52 changes: 47 additions & 5 deletions python/uv/private/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -21,28 +21,70 @@ filegroup(
)

bzl_library(
name = "current_toolchain",
name = "current_toolchain_bzl",
srcs = ["current_toolchain.bzl"],
visibility = ["//python/uv:__subpackages__"],
)

bzl_library(
name = "toolchain_types",
name = "lock_bzl",
srcs = ["lock.bzl"],
visibility = ["//python/uv:__subpackages__"],
deps = [
"//python:py_binary_bzl",
"//python/private:bzlmod_enabled_bzl",
"@bazel_skylib//rules:write_file",
],
)

bzl_library(
name = "toolchain_types_bzl",
srcs = ["toolchain_types.bzl"],
visibility = ["//python/uv:__subpackages__"],
)

bzl_library(
name = "toolchains_repo",
srcs = ["toolchains_repo.bzl"],
name = "uv_bzl",
srcs = ["uv.bzl"],
visibility = ["//python/uv:__subpackages__"],
deps = [":uv_repositories_bzl"],
)

bzl_library(
name = "uv_repositories_bzl",
srcs = ["uv_repositories.bzl"],
visibility = ["//python/uv:__subpackages__"],
deps = [
":toolchain_types_bzl",
":uv_toolchains_repo_bzl",
":versions_bzl",
],
)

bzl_library(
name = "uv_toolchain_bzl",
srcs = ["uv_toolchain.bzl"],
visibility = ["//python/uv:__subpackages__"],
deps = [":uv_toolchain_info_bzl"],
)

bzl_library(
name = "uv_toolchain_info_bzl",
srcs = ["uv_toolchain_info.bzl"],
visibility = ["//python/uv:__subpackages__"],
)

bzl_library(
name = "uv_toolchains_repo_bzl",
srcs = ["uv_toolchains_repo.bzl"],
visibility = ["//python/uv:__subpackages__"],
deps = [
"//python/private:text_util_bzl",
],
)

bzl_library(
name = "versions",
name = "versions_bzl",
srcs = ["versions.bzl"],
visibility = ["//python/uv:__subpackages__"],
)
24 changes: 9 additions & 15 deletions python/uv/private/lock.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -26,25 +26,23 @@ _REQUIREMENTS_TARGET_COMPATIBLE_WITH = select({
"//conditions:default": [],
}) if BZLMOD_ENABLED else ["@platforms//:incompatible"]

def lock(*, name, srcs, out, upgrade = False, universal = True, python_version = None, args = [], **kwargs):
def lock(*, name, srcs, out, upgrade = False, universal = True, args = [], **kwargs):
"""Pin the requirements based on the src files.
Differences with the current {obj}`compile_pip_requirements` rule:
- This is implemented in shell and uv.
- This does not error out if the output file does not exist yet.
- Supports transitions out of the box.
Args:
name: The name of the target to run for updating the requirements.
srcs: The srcs to use as inputs.
out: The output file.
upgrade: Tell `uv` to always upgrade the dependencies instead of
keeping them as they are.
universal: Tell `uv` to generate a universal lock file.
python_version: Tell `rules_python` to use a particular version.
Defaults to the default py toolchain.
args: Extra args to pass to the rule.
**kwargs: Extra kwargs passed to the binary rule.
Differences with the current pip-compile rule:
- This is implemented in shell and uv.
- This does not error out if the output file does not exist yet.
- Supports transitions out of the box.
args: Extra args to pass to `uv`.
**kwargs: Extra kwargs passed to the {obj}`py_binary` rule.
"""
pkg = native.package_name()
update_target = name + ".update"
Expand Down Expand Up @@ -92,10 +90,6 @@ def lock(*, name, srcs, out, upgrade = False, universal = True, python_version =
Label("//python:current_py_toolchain"),
],
)
if python_version:
py_binary_rule = lambda *args, **kwargs: py_binary(python_version = python_version, *args, **kwargs)
else:
py_binary_rule = py_binary

# Write a script that can be used for updating the in-tree version of the
# requirements file
Expand All @@ -116,7 +110,7 @@ def lock(*, name, srcs, out, upgrade = False, universal = True, python_version =
],
)

py_binary_rule(
py_binary(
name = update_target,
srcs = [update_target + ".py"],
main = update_target + ".py",
Expand Down
13 changes: 8 additions & 5 deletions python/uv/extensions.bzl → python/uv/private/uv.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,18 @@ EXPERIMENTAL: This is experimental and may be removed without notice
A module extension for working with uv.
"""

load("//python/uv:repositories.bzl", "uv_register_toolchains")
load(":uv_repositories.bzl", "uv_repositories")

_DOC = """\
A module extension for working with uv.
"""

uv_toolchain = tag_class(attrs = {
"uv_version": attr.string(doc = "Explicit version of uv.", mandatory = True),
})
uv_toolchain = tag_class(
doc = "Configure uv toolchain for lock file generation.",
attrs = {
"uv_version": attr.string(doc = "Explicit version of uv.", mandatory = True),
},
)

def _uv_toolchain_extension(module_ctx):
for mod in module_ctx.modules:
Expand All @@ -38,7 +41,7 @@ def _uv_toolchain_extension(module_ctx):
"NOTE: We may wish to enforce a policy where toolchain configuration is only allowed in the root module, or in rules_python. See https://github.com/bazelbuild/bazel/discussions/22024",
)

uv_register_toolchains(
uv_repositories(
uv_version = toolchain.uv_version,
register_toolchains = False,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ EXPERIMENTAL: This is experimental and may be removed without notice
Create repositories for uv toolchain dependencies
"""

load("//python/uv/private:toolchain_types.bzl", "UV_TOOLCHAIN_TYPE")
load("//python/uv/private:toolchains_repo.bzl", "uv_toolchains_repo")
load("//python/uv/private:versions.bzl", "UV_PLATFORMS", "UV_TOOL_VERSIONS")
load(":toolchain_types.bzl", "UV_TOOLCHAIN_TYPE")
load(":uv_toolchains_repo.bzl", "uv_toolchains_repo")
load(":versions.bzl", "UV_PLATFORMS", "UV_TOOL_VERSIONS")

UV_BUILD_TMPL = """\
# Generated by repositories.bzl
load("@rules_python//python/uv:toolchain.bzl", "uv_toolchain")
load("@rules_python//python/uv:uv_toolchain.bzl", "uv_toolchain")
uv_toolchain(
name = "uv_toolchain",
Expand Down Expand Up @@ -77,13 +77,13 @@ uv_repository = repository_rule(
},
)

# buildifier: disable=unnamed-macro
def uv_register_toolchains(uv_version = None, register_toolchains = True):
def uv_repositories(name = "uv_toolchains", uv_version = None, register_toolchains = True):
"""Convenience macro which does typical toolchain setup
Skip this macro if you need more control over the toolchain setup.
Args:
name: {type}`str` The name of the toolchains repo.
uv_version: The uv toolchain version to download.
register_toolchains: If true, repositories will be generated to produce and register `uv_toolchain` targets.
"""
Expand All @@ -109,12 +109,12 @@ def uv_register_toolchains(uv_version = None, register_toolchains = True):
toolchain_compatible_with_by_toolchain[toolchain_name] = UV_PLATFORMS[platform].compatible_with

uv_toolchains_repo(
name = "uv_toolchains",
name = name,
toolchain_type = str(UV_TOOLCHAIN_TYPE),
toolchain_names = toolchain_names,
toolchain_labels = toolchain_labels_by_toolchain,
toolchain_compatible_with = toolchain_compatible_with_by_toolchain,
)

if register_toolchains:
native.register_toolchains("@uv_toolchains//:all")
native.register_toolchains("@{}/:all".format(name))
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ EXPERIMENTAL: This is experimental and may be removed without notice
This module implements the uv toolchain rule
"""

load("//python/uv/private:providers.bzl", "UvToolchainInfo")
load(":uv_toolchain_info.bzl", "UvToolchainInfo")

def _uv_toolchain_impl(ctx):
uv = ctx.attr.uv
Expand Down
File renamed without changes.
File renamed without changes.
22 changes: 22 additions & 0 deletions python/uv/uv.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Copyright 2025 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.

""" EXPERIMENTAL: This is experimental and may be removed without notice.
The uv toolchain extension.
"""

load("//python/uv/private:uv.bzl", _uv = "uv")

uv = _uv
22 changes: 22 additions & 0 deletions python/uv/uv_toolchain.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Copyright 2025 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.

"""The `uv_toolchain` rule.
EXPERIMENTAL: This is experimental and may be removed without notice
"""

load("//python/uv/private:uv_toolchain.bzl", _uv_toolchain = "uv_toolchain")

uv_toolchain = _uv_toolchain
Loading

0 comments on commit 18f76f9

Please sign in to comment.