blob: 2920c4abe986322e2e56682f7633a85480d1b900 [file] [log] [blame]
"uv based venv generation"
load(":interpreter_path.bzl", "python_interpreter_path")
load(":transition_to_target.bzl", "transition_to_target")
_PY_TOOLCHAIN = "@bazel_tools//tools/python:toolchain_type"
def _uv_template(ctx, template, executable):
py_toolchain = ctx.toolchains[_PY_TOOLCHAIN]
ctx.actions.expand_template(
template = template,
output = executable,
substitutions = {
"{{uv}}": ctx.executable._uv.short_path,
"{{requirements_txt}}": ctx.file.requirements_txt.short_path,
"{{resolved_python}}": python_interpreter_path(py_toolchain.py3_runtime),
"{{destination_folder}}": ctx.attr.destination_folder,
"{{site_packages_extra_files}}": " ".join(["'" + file.short_path + "'" for file in ctx.files.site_packages_extra_files]),
"{{args}}": " \\\n ".join(ctx.attr.uv_args),
},
)
def _runfiles(ctx):
py_toolchain = ctx.toolchains[_PY_TOOLCHAIN]
runfiles = ctx.runfiles(
files = [ctx.file.requirements_txt] + ctx.files.site_packages_extra_files,
transitive_files = py_toolchain.py3_runtime.files,
)
runfiles = runfiles.merge(ctx.attr._uv[0].default_runfiles)
return runfiles
def _venv_impl(ctx):
executable = ctx.actions.declare_file(ctx.attr.name)
_uv_template(ctx, ctx.file.template, executable)
return DefaultInfo(
executable = executable,
runfiles = _runfiles(ctx),
)
_venv = rule(
attrs = {
"destination_folder": attr.string(default = "venv"),
"site_packages_extra_files": attr.label_list(default = [], doc = "Files to add to the site-packages folder inside the virtual environment. Useful for adding `sitecustomize.py` or `.pth` files", allow_files = True),
"requirements_txt": attr.label(mandatory = True, allow_single_file = True),
"_uv": attr.label(default = "@multitool//tools/uv", executable = True, cfg = transition_to_target),
"template": attr.label(allow_single_file = True),
"uv_args": attr.string_list(default = []),
},
toolchains = [_PY_TOOLCHAIN],
implementation = _venv_impl,
executable = True,
)
def create_venv(name, requirements_txt = None, target_compatible_with = None, destination_folder = None, site_packages_extra_files = [], uv_args = []):
_venv(
name = name,
destination_folder = destination_folder,
site_packages_extra_files = site_packages_extra_files,
requirements_txt = requirements_txt or "//:requirements.txt",
target_compatible_with = target_compatible_with,
uv_args = uv_args,
template = "@rules_uv//uv/private:create_venv.sh",
)
def sync_venv(name, requirements_txt = None, target_compatible_with = None, destination_folder = None, site_packages_extra_files = [], uv_args = []):
_venv(
name = name,
destination_folder = destination_folder,
site_packages_extra_files = site_packages_extra_files,
requirements_txt = requirements_txt or "//:requirements.txt",
target_compatible_with = target_compatible_with,
uv_args = uv_args,
template = "@rules_uv//uv/private:sync_venv.sh",
)