Skip to content

Commit

Permalink
use sha256 for ensuring that pip repo names are valid and dont clash
Browse files Browse the repository at this point in the history
  • Loading branch information
aignas committed Jun 1, 2024
1 parent 5c80375 commit 1c87068
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 16 deletions.
9 changes: 9 additions & 0 deletions python/private/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,15 @@ bzl_library(
],
)

bzl_library(
name = "pip_repo_name_bzl",
srcs = ["pip_repo_name.bzl"],
deps = [
":normalize_name_bzl",
":parse_whl_name_bzl",
],
)

bzl_library(
name = "pypi_index_bzl",
srcs = ["pypi_index.bzl"],
Expand Down
1 change: 1 addition & 0 deletions python/private/bzlmod/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ bzl_library(
"//python/private:normalize_name_bzl",
"//python/private:parse_requirements_bzl",
"//python/private:parse_whl_name_bzl",
"//python/private:pip_repo_name_bzl",
"//python/private:version_label_bzl",
":bazel_features_bzl",
] + [
Expand Down
18 changes: 2 additions & 16 deletions python/private/bzlmod/pip.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ load("//python/private:auth.bzl", "AUTH_ATTRS")
load("//python/private:normalize_name.bzl", "normalize_name")
load("//python/private:parse_requirements.bzl", "host_platform", "parse_requirements", "select_requirement")
load("//python/private:parse_whl_name.bzl", "parse_whl_name")
load("//python/private:pip_repo_name.bzl", "pip_repo_name")
load("//python/private:pypi_index.bzl", "simpleapi_download")
load("//python/private:render_pkg_aliases.bzl", "whl_alias")
load("//python/private:repo_utils.bzl", "repo_utils")
Expand Down Expand Up @@ -260,7 +261,7 @@ def _create_whl_repos(module_ctx, pip_attr, whl_map, whl_overrides, group_map, s
# This is no-op because pip is not used to download the wheel.
whl_library_args.pop("download_only", None)

repo_name = _repo_name(pip_name, distribution.filename)
repo_name = pip_repo_name(pip_name, distribution.filename, distribution.sha256)
whl_library_args["requirement"] = requirement.srcs.requirement
whl_library_args["urls"] = [distribution.url]
whl_library_args["sha256"] = distribution.sha256
Expand Down Expand Up @@ -317,21 +318,6 @@ def _create_whl_repos(module_ctx, pip_attr, whl_map, whl_overrides, group_map, s
),
)

def _repo_name(prefix, filename):
if not filename.endswith(".whl"):
# Then the filename is basically foo-3.2.1.<ext>
name = normalize_name(filename)
else:
parsed = parse_whl_name(filename)
name = "{}_{}_{}_{}_{}".format(
parsed.distribution,
parsed.version,
parsed.python_tag,
parsed.abi_tag,
parsed.platform_tag,
)
return "{}__{}".format(prefix, normalize_name(name))

def _pip_impl(module_ctx):
"""Implementation of a class tag that creates the pip hub and corresponding pip spoke whl repositories.
Expand Down
39 changes: 39 additions & 0 deletions python/private/pip_repo_name.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Copyright 2024 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.

"""A function to convert a dist name to a valid bazel repo name.
"""

load(":normalize_name.bzl", "normalize_name")
load(":parse_whl_name.bzl", "parse_whl_name")

def pip_repo_name(prefix, filename, sha256):
"""Return a valid whl_library repo name given a distribution filename.
Args:
prefix: str, the prefix of the whl_library.
filename: str, the filename of the distribution.
sha256: str, the sha256 of the distribution.
Returns:
a string that can be used in `whl_library`.
"""
if not filename.endswith(".whl"):
# Then the filename is basically foo-3.2.1.<ext>
name = normalize_name(filename.rpartition("-")[0])
else:
parsed = parse_whl_name(filename)
name = normalize_name(parsed.distribution)

return "{}__{}_{}".format(prefix, name, sha256[:8])
3 changes: 3 additions & 0 deletions tests/private/pip_repo_name/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
load(":pip_repo_name_tests.bzl", "pip_repo_name_test_suite")

pip_repo_name_test_suite(name = "pip_repo_name_tests")
52 changes: 52 additions & 0 deletions tests/private/pip_repo_name/pip_repo_name_tests.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Copyright 2023 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.

""

load("@rules_testing//lib:test_suite.bzl", "test_suite")
load("//python/private:pip_repo_name.bzl", "pip_repo_name") # buildifier: disable=bzl-visibility

_tests = []

def _test_simple(env):
got = pip_repo_name("prefix", "foo-1.2.3-py3-none-any.whl", "deadbeef")
env.expect.that_str(got).equals("prefix__foo_deadbeef")

_tests.append(_test_simple)

def _test_sdist(env):
got = pip_repo_name("prefix", "foo-1.2.3.tar.gz", "deadbeef000deadbeef")
env.expect.that_str(got).equals("prefix__foo_deadbeef")

_tests.append(_test_sdist)

def _test_platform_whl(env):
got = pip_repo_name(
"prefix",
"foo-1.2.3-cp39.cp310-abi3-manylinux1_x86_64.manylinux_2_17_x86_64.whl",
"deadbeef000deadbeef",
)

# We only need the first segment of each
env.expect.that_str(got).equals("prefix__foo_deadbeef")

_tests.append(_test_platform_whl)

def pip_repo_name_test_suite(name):
"""Create the test suite.
Args:
name: the name of the test suite
"""
test_suite(name = name, basic_tests = _tests)

0 comments on commit 1c87068

Please sign in to comment.