Skip to content

Commit

Permalink
A different external API for entrypoints without a macro
Browse files Browse the repository at this point in the history
  • Loading branch information
aignas committed Jul 25, 2023
1 parent 9d28b0f commit 1b88ae3
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 47 deletions.
6 changes: 6 additions & 0 deletions examples/bzlmod/MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ use_repo(pip, "whl_mods_hub")
# Because we do not have a python_version defined here
# pip.parse uses the python toolchain that is set as default.
pip.parse(
entry_points = {
"yamllint": ["yamllint"],
},
hub_name = "pip",
requirements_lock = "//:requirements_lock_3_9.txt",
requirements_windows = "//:requirements_windows_3_9.txt",
Expand All @@ -106,6 +109,9 @@ pip.parse(
},
)
pip.parse(
entry_points = {
"yamllint": ["yamllint"],
},
hub_name = "pip",
python_version = "3.10",
requirements_lock = "//:requirements_lock_3_10.txt",
Expand Down
3 changes: 1 addition & 2 deletions examples/bzlmod/entry_point/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
load("@pip//:requirements.bzl", "entry_point")
load("@rules_python//python:defs.bzl", "py_test")

alias(
name = "yamllint",
actual = entry_point("yamllint"),
actual = "@pip//yamllint/bin:yamllint",
)

py_test(
Expand Down
30 changes: 25 additions & 5 deletions python/extensions/pip.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,10 @@ def _create_versioned_pip_and_whl_repos(module_ctx, pip_attr, whl_map):
extra_pip_args = pip_attr.extra_pip_args + parse_result.options

if hub_name not in whl_map:
whl_map[hub_name] = {}
whl_map[hub_name] = struct(
wheels = {},
entry_points = {},
)

whl_modifications = {}
if pip_attr.whl_modifications != None:
Expand Down Expand Up @@ -143,10 +146,20 @@ def _create_versioned_pip_and_whl_repos(module_ctx, pip_attr, whl_map):
environment = pip_attr.environment,
)

if whl_name not in whl_map[hub_name]:
whl_map[hub_name][whl_name] = []
if whl_name not in whl_map[hub_name].wheels:
whl_map[hub_name].wheels[whl_name] = []

whl_map[hub_name].wheels[whl_name].append(full_version(pip_attr.python_version))

for whl_name, scripts in pip_attr.entry_points.items():
if whl_name not in whl_map[hub_name].entry_points:
whl_map[hub_name].entry_points[whl_name] = {}

whl_map[hub_name][whl_name].append(full_version(pip_attr.python_version))
for script in scripts:
if script not in whl_map[hub_name].entry_points[whl_name]:
whl_map[hub_name].entry_points[whl_name][script] = []

whl_map[hub_name].entry_points[whl_name][script].append(full_version(pip_attr.python_version))

def _pip_impl(module_ctx):
"""Implementation of a class tag that creates the pip hub(s) and corresponding pip spoke, alias and whl repositories.
Expand Down Expand Up @@ -288,12 +301,19 @@ def _pip_impl(module_ctx):
pip_hub_repository(
name = hub_name,
repo_name = hub_name,
whl_map = whl_map,
whl_map = whl_map.wheels,
whl_entry_points = {
whl_name: json.encode(values)
for whl_name, values in whl_map.entry_points.items()
},
default_version = full_version(DEFAULT_PYTHON_VERSION),
)

def _pip_parse_ext_attrs():
attrs = dict({
"entry_points": attr.string_list_dict(
doc = "TODO",
),
"hub_name": attr.string(
mandatory = True,
doc = """
Expand Down
8 changes: 8 additions & 0 deletions python/extensions/private/pip_hub_repository.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ def _impl(rctx):
aliases = render_pkg_aliases(
repo_name = repo_name,
whl_map = rctx.attr.whl_map,
whl_entry_points = {
whl_name: json.decode(values)
for whl_name, values in rctx.attr.whl_entry_points.items()
},
default_version = rctx.attr.default_version,
rules_python = rctx.attr._template.workspace_name,
)
Expand Down Expand Up @@ -84,6 +88,10 @@ setting.""",
mandatory = True,
doc = "The apparent name of the repo. This is needed because in bzlmod, the name attribute becomes the canonical name.",
),
"whl_entry_points": attr.string_dict(
mandatory = False,
doc = "The entry points that we will create aliases for.",
),
"whl_map": attr.string_list_dict(
mandatory = True,
doc = "The wheel map where values are python versions",
Expand Down
86 changes: 46 additions & 40 deletions python/private/render_pkg_aliases.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ def _render_alias(
repo_name,
dep,
target,
default_version,
versions,
rules_python):
rules_python,
default_version = None):
"""Render an alias for common targets
If the versions is passed, then the `rules_python` must be passed as well and
Expand Down Expand Up @@ -71,13 +71,14 @@ def _render_alias(
)
selects[condition] = actual

default_actual = "@{repo_name}_{version}_{dep}//:{target}".format(
repo_name = repo_name,
version = version_label(default_version),
dep = dep,
target = target,
)
selects["//conditions:default"] = default_actual
if default_version:
default_actual = "@{repo_name}_{version}_{dep}//:{target}".format(
repo_name = repo_name,
version = version_label(default_version),
dep = dep,
target = target,
)
selects["//conditions:default"] = default_actual

return _SELECT.format(
name = name,
Expand All @@ -89,22 +90,21 @@ def _render_alias(
),
)

def _render_entry_points(repo_name, dep):
return """\
load("@{repo_name}_{dep}//:entry_points.bzl", "entry_points")
[
alias(
name = script,
actual = "@{repo_name}_{dep}//:" + target,
visibility = ["//visibility:public"],
)
for script, target in entry_points.items()
]
""".format(
repo_name = repo_name,
dep = dep,
)
def _render_entry_points(repo_name, dep, entry_points, default_version = None, rules_python = None, prefix = "rules_python_wheel_entry_point_"):
return "\n\n".join([
"""package(default_visibility = ["//visibility:public"])""",
] + [
_render_alias(
name = normalize_name(script),
repo_name = repo_name,
dep = dep,
target = prefix + normalize_name(script),
versions = versions,
default_version = default_version,
rules_python = rules_python,
)
for script, versions in entry_points.items()
])

def _render_common_aliases(repo_name, name, versions = None, default_version = None, rules_python = None):
return "\n\n".join([
Expand All @@ -131,7 +131,14 @@ def _render_common_aliases(repo_name, name, versions = None, default_version = N
for target in ["pkg", "whl", "data", "dist_info"]
])

def render_pkg_aliases(*, repo_name, bzl_packages = None, whl_map = None, rules_python = None, default_version = None):
def render_pkg_aliases(
*,
repo_name,
bzl_packages = None,
whl_map = None,
whl_entry_points = None,
rules_python = None,
default_version = None):
"""Create alias declarations for each PyPI package.
The aliases should be appended to the pip_repository BUILD.bazel file. These aliases
Expand All @@ -155,8 +162,14 @@ def render_pkg_aliases(*, repo_name, bzl_packages = None, whl_map = None, rules_
contents = {}
for name in bzl_packages:
versions = None
entry_points = None

if whl_map != None:
versions = whl_map[name]

if whl_entry_points != None:
entry_points = whl_entry_points.get(name, {})

name = normalize_name(name)

filename = "{}/BUILD.bazel".format(name)
Expand All @@ -168,22 +181,15 @@ def render_pkg_aliases(*, repo_name, bzl_packages = None, whl_map = None, rules_
default_version = default_version,
).strip()

if versions == None:
# NOTE: this code would be normally executed in the non-bzlmod
# scenario, where we are requesting friendly aliases to be
# generated. In that case, we will not be creating aliases for
# entry_points to leave the behaviour unchanged from previous
# rules_python versions.
continue

# NOTE @aignas 2023-07-07: we are not creating aliases using a select
# and the version specific aliases because we would need to fetch the
# package for all versions in order to construct the said select.
for version in versions:
filename = "{}/bin_py{}/BUILD.bazel".format(name, version_label(version))
if entry_points:
# Generate aliases where we have the select statement
filename = "{}/bin/BUILD.bazel".format(name)
contents[filename] = _render_entry_points(
repo_name = "{}_{}".format(repo_name, version_label(version)),
repo_name = repo_name,
dep = name,
rules_python = rules_python,
default_version = default_version,
entry_points = entry_points,
).strip()

return contents

0 comments on commit 1b88ae3

Please sign in to comment.