Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions build_defs/python.build_defs
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ def pip_library(name:str, version:str, labels:list=[], hashes:list=None, package
repo = repo or CONFIG.PYTHON.DEFAULT_PIP_REPO
if repo:
if looks_like_build_label(repo): # Looks like a build label, not a URL.
repo_flag = f'-f %(location {repo})'
repo_flag = f'-f $(location {repo})'
deps += [repo]
else:
repo_flag = '-f ' + repo
Expand Down Expand Up @@ -507,6 +507,7 @@ def pip_library(name:str, version:str, labels:list=[], hashes:list=None, package
test_only = test_only,
output_dirs = [pip_target_dir],
srcs = patches if patch else [],
deps = [repo] if looks_like_build_label(repo) else [],
building_description = 'Fetching...',
tools = tools,
sandbox = False,
Expand All @@ -516,7 +517,7 @@ def pip_library(name:str, version:str, labels:list=[], hashes:list=None, package
# Don't include the dependency whl's into our whl. They are later picked up by py_binary anyway.
cmd = f'$TOOLS_ARCAT z --suffix="" --exclude_suffix=whl --include_other -i . -r $PKG/{name}:$PKG'
if not licences:
cmd += ' && find . -name METADATA -or -name PKG-INFO | grep -v "^./build/" | xargs grep -E "License ?:" | grep -v UNKNOWN | cat || true'
cmd += ' && find . -name METADATA -or -name PKG-INFO | grep -v "^./build/" | xargs grep -E "License(-Expression)? ?:" | grep -v UNKNOWN | cat || true'

return build_rule(
name = name,
Expand Down Expand Up @@ -661,7 +662,7 @@ def python_wheel(name:str, version:str, labels:list=[], hashes:list=None, packag
cmd += ['find . %s | xargs rm -rf' % ' -or '.join(['-name "%s"' % s for s in strip])]
if not licences:
cmd += ['find . -name METADATA -or -name PKG-INFO | grep -v "^./build/" | '
'xargs grep -hE "License ?:" | grep -v UNKNOWN | cat || true']
'xargs grep -hE "License(-Expression)? ?:" | grep -v UNKNOWN | cat || true']
if patch:
patches, c = _patch_cmd(patch)
cmd += c
Expand Down Expand Up @@ -848,6 +849,9 @@ def _add_licences(name, output):
# section still seems to know what they are licenced as.
add_licence(name, line.split(' :: ')[-1])
found = True
elif line.startswith('License-Expression: '):
add_licence(name, line.removeprefix('License-Expression: '))
found = True
if not found:
name = name.lstrip('_').split('#')[0]
msg = f'No licence found for {name}, should add licences = [...] to the rule'
Expand Down
8 changes: 8 additions & 0 deletions test/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,14 @@ plugin_e2e_test(
},
)

# Test that pip_library correctly auto-detects licences from a PEP 639 `License-Expression:`
# metadata field (as well as the legacy `License:` field).
plugin_e2e_test(
name = "pip_library_license_expression_test",
repo = "license_expression_repo",
test_cmd = "plz build //third_party/python:fakepkg",
)

# Test that python_wheel targets can have name_scheme as a list or a string

python_test(
Expand Down
3 changes: 3 additions & 0 deletions test/license_expression_repo/.plzconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[Plugin "python"]
Target = //plugins:python
RequireLicences = true
4 changes: 4 additions & 0 deletions test/license_expression_repo/plugins/BUILD_FILE
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
plugin_repo(
name = "python",
revision = "e2e",
)
25 changes: 25 additions & 0 deletions test/license_expression_repo/third_party/python/BUILD_FILE
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
subinclude("///python//build_defs:python")

package(
# The pip_library target below installs from a local wheelhouse fixture, not the network -
# make sure we don't accidentally try to look it up on PyPI.
python = {
"use_pypi": False,
},
)

# A local "package index" directory containing a single fixture wheel whose METADATA only
# declares a PEP 639 `License-Expression:` field (no legacy `License:` or `Classifier: License`),
# to exercise pip_library's auto-detection of that field.
genrule(
name = "wheelhouse",
srcs = ["wheelhouse/fakepkg-1.0.0-py3-none-any.whl"],
cmd = "mkdir -p wheelhouse && cp $SRCS wheelhouse/",
output_dirs = ["wheelhouse"],
)

pip_library(
name = "fakepkg",
repo = ":wheelhouse",
version = "1.0.0",
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we should generate this wheel at test time, just to prove there's nothing weird going on in this plugin (a la CVE-2024-3094)? It'd be pretty straightforward too, given that we could build it with arcat. If you want to save keystrokes and a bit of complexity, fakepkg/__init__.py isn't necessary - a wheel consisting only of metadata is legit (and occasionally seen in the wild as a way of implementing virtual packages).

Binary file not shown.
Loading