From ed83e95e8dc53c7035d90a2c0786a81ddaf046d0 Mon Sep 17 00:00:00 2001 From: Peter Ebden Date: Tue, 8 Sep 2026 15:41:38 +0100 Subject: [PATCH 1/3] Accept License-Expression field as well as just License --- build_defs/python.build_defs | 10 ++++--- test/BUILD | 8 ++++++ test/license_expression_repo/.plzconfig | 3 +++ .../plugins/BUILD_FILE | 4 +++ .../third_party/python/BUILD_FILE | 25 ++++++++++++++++++ .../wheelhouse/fakepkg-1.0.0-py3-none-any.whl | Bin 0 -> 758 bytes 6 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 test/license_expression_repo/.plzconfig create mode 100644 test/license_expression_repo/plugins/BUILD_FILE create mode 100644 test/license_expression_repo/third_party/python/BUILD_FILE create mode 100644 test/license_expression_repo/third_party/python/wheelhouse/fakepkg-1.0.0-py3-none-any.whl diff --git a/build_defs/python.build_defs b/build_defs/python.build_defs index 2435ac29..97af2a5b 100644 --- a/build_defs/python.build_defs +++ b/build_defs/python.build_defs @@ -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 @@ -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, @@ -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, @@ -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 @@ -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' diff --git a/test/BUILD b/test/BUILD index d12cad3f..91fd408c 100644 --- a/test/BUILD +++ b/test/BUILD @@ -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( diff --git a/test/license_expression_repo/.plzconfig b/test/license_expression_repo/.plzconfig new file mode 100644 index 00000000..e5f64a6a --- /dev/null +++ b/test/license_expression_repo/.plzconfig @@ -0,0 +1,3 @@ +[Plugin "python"] +Target = //plugins:python +RequireLicences = true diff --git a/test/license_expression_repo/plugins/BUILD_FILE b/test/license_expression_repo/plugins/BUILD_FILE new file mode 100644 index 00000000..bd8b3fd9 --- /dev/null +++ b/test/license_expression_repo/plugins/BUILD_FILE @@ -0,0 +1,4 @@ +plugin_repo( + name = "python", + revision = "e2e", +) diff --git a/test/license_expression_repo/third_party/python/BUILD_FILE b/test/license_expression_repo/third_party/python/BUILD_FILE new file mode 100644 index 00000000..a9db0870 --- /dev/null +++ b/test/license_expression_repo/third_party/python/BUILD_FILE @@ -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", +) diff --git a/test/license_expression_repo/third_party/python/wheelhouse/fakepkg-1.0.0-py3-none-any.whl b/test/license_expression_repo/third_party/python/wheelhouse/fakepkg-1.0.0-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..b5c0aa17ffc8b8f8493a987017abd2145aff8824 GIT binary patch literal 758 zcmWIWW@Zs#U|`^2D67_p1u__zKm-s7194hnc4|R(x_*3oW?p7Ve7s&kB{M?+ik5}n z>jIsDN~?fa4xvTYP|pAeQ!7MYr-rs-z%xRs@{_EN+ zu3UWR)!gw)>XjrzqE}jBXI@%d)V_V|vpW`dCwC~zsXmljx6ZEONpsBHzs)fXTxiyB z&op#)1X}A2#0q$<_jL_%ba4!E{Oqgi>Eo&6d4<Ymf)T zanGB)C0|LtkSzF_qPF~*=<-*)!bC)tiaDp$*gEe(vtE?{NP{2HS`e1SV|}=XtE&(9 zc@N*S7ZDa;F@8|wf7V;qOXsBirXY{gYcw=)$!kQsy1asS zItg7~E5fDKTl)Fa=b%#I&ssZy4q;>xVa6SIK-Yl5mPQbTB_`1gK#xg?b_Rwmjm8KA zaKtORS?JM%Fl!SYvtW^gZW?+hBTO@7gnJFcW#BLm@MdKLDQ5vfHK5{MK+M1Z01(a7 A7ytkO literal 0 HcmV?d00001 From 1aeba2ad708534ac81a93290d35aedfcbb9405ab Mon Sep 17 00:00:00 2001 From: Peter Ebden Date: Tue, 15 Sep 2026 13:40:43 +0100 Subject: [PATCH 2/3] Generate wheel at build time instead of checking in --- .../third_party/python/BUILD_FILE | 21 ++++++++++++++---- .../fakepkg-1.0.0.dist-info/METADATA | 4 ++++ .../fakepkg-1.0.0.dist-info/RECORD | 4 ++++ .../fakepkg_src/fakepkg-1.0.0.dist-info/WHEEL | 4 ++++ .../python/fakepkg_src/fakepkg/__init__.py | 0 .../wheelhouse/fakepkg-1.0.0-py3-none-any.whl | Bin 758 -> 0 bytes 6 files changed, 29 insertions(+), 4 deletions(-) create mode 100644 test/license_expression_repo/third_party/python/fakepkg_src/fakepkg-1.0.0.dist-info/METADATA create mode 100644 test/license_expression_repo/third_party/python/fakepkg_src/fakepkg-1.0.0.dist-info/RECORD create mode 100644 test/license_expression_repo/third_party/python/fakepkg_src/fakepkg-1.0.0.dist-info/WHEEL create mode 100644 test/license_expression_repo/third_party/python/fakepkg_src/fakepkg/__init__.py delete mode 100644 test/license_expression_repo/third_party/python/wheelhouse/fakepkg-1.0.0-py3-none-any.whl diff --git a/test/license_expression_repo/third_party/python/BUILD_FILE b/test/license_expression_repo/third_party/python/BUILD_FILE index a9db0870..25c060f8 100644 --- a/test/license_expression_repo/third_party/python/BUILD_FILE +++ b/test/license_expression_repo/third_party/python/BUILD_FILE @@ -8,12 +8,25 @@ package( }, ) -# 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. +# Builds a fixture wheel from plain-text sources 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 = "fakepkg_whl", + srcs = [ + "fakepkg_src/fakepkg/__init__.py", + "fakepkg_src/fakepkg-1.0.0.dist-info/METADATA", + "fakepkg_src/fakepkg-1.0.0.dist-info/WHEEL", + "fakepkg_src/fakepkg-1.0.0.dist-info/RECORD", + ], + outs = ["fakepkg-1.0.0-py3-none-any.whl"], + cmd = "cd $PKG/fakepkg_src && $TOOLS_ARCAT z -d -i . -o $OUT", + tools = {"arcat": [CONFIG.ARCAT_TOOL]}, +) + genrule( name = "wheelhouse", - srcs = ["wheelhouse/fakepkg-1.0.0-py3-none-any.whl"], + srcs = [":fakepkg_whl"], cmd = "mkdir -p wheelhouse && cp $SRCS wheelhouse/", output_dirs = ["wheelhouse"], ) diff --git a/test/license_expression_repo/third_party/python/fakepkg_src/fakepkg-1.0.0.dist-info/METADATA b/test/license_expression_repo/third_party/python/fakepkg_src/fakepkg-1.0.0.dist-info/METADATA new file mode 100644 index 00000000..c2444db9 --- /dev/null +++ b/test/license_expression_repo/third_party/python/fakepkg_src/fakepkg-1.0.0.dist-info/METADATA @@ -0,0 +1,4 @@ +Metadata-Version: 2.4 +Name: fakepkg +Version: 1.0.0 +License-Expression: MIT diff --git a/test/license_expression_repo/third_party/python/fakepkg_src/fakepkg-1.0.0.dist-info/RECORD b/test/license_expression_repo/third_party/python/fakepkg_src/fakepkg-1.0.0.dist-info/RECORD new file mode 100644 index 00000000..c6a9efec --- /dev/null +++ b/test/license_expression_repo/third_party/python/fakepkg_src/fakepkg-1.0.0.dist-info/RECORD @@ -0,0 +1,4 @@ +fakepkg/__init__.py,, +fakepkg-1.0.0.dist-info/METADATA,, +fakepkg-1.0.0.dist-info/WHEEL,, +fakepkg-1.0.0.dist-info/RECORD,, diff --git a/test/license_expression_repo/third_party/python/fakepkg_src/fakepkg-1.0.0.dist-info/WHEEL b/test/license_expression_repo/third_party/python/fakepkg_src/fakepkg-1.0.0.dist-info/WHEEL new file mode 100644 index 00000000..d3aa0df6 --- /dev/null +++ b/test/license_expression_repo/third_party/python/fakepkg_src/fakepkg-1.0.0.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: fixture +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/test/license_expression_repo/third_party/python/fakepkg_src/fakepkg/__init__.py b/test/license_expression_repo/third_party/python/fakepkg_src/fakepkg/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/license_expression_repo/third_party/python/wheelhouse/fakepkg-1.0.0-py3-none-any.whl b/test/license_expression_repo/third_party/python/wheelhouse/fakepkg-1.0.0-py3-none-any.whl deleted file mode 100644 index b5c0aa17ffc8b8f8493a987017abd2145aff8824..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 758 zcmWIWW@Zs#U|`^2D67_p1u__zKm-s7194hnc4|R(x_*3oW?p7Ve7s&kB{M?+ik5}n z>jIsDN~?fa4xvTYP|pAeQ!7MYr-rs-z%xRs@{_EN+ zu3UWR)!gw)>XjrzqE}jBXI@%d)V_V|vpW`dCwC~zsXmljx6ZEONpsBHzs)fXTxiyB z&op#)1X}A2#0q$<_jL_%ba4!E{Oqgi>Eo&6d4<Ymf)T zanGB)C0|LtkSzF_qPF~*=<-*)!bC)tiaDp$*gEe(vtE?{NP{2HS`e1SV|}=XtE&(9 zc@N*S7ZDa;F@8|wf7V;qOXsBirXY{gYcw=)$!kQsy1asS zItg7~E5fDKTl)Fa=b%#I&ssZy4q;>xVa6SIK-Yl5mPQbTB_`1gK#xg?b_Rwmjm8KA zaKtORS?JM%Fl!SYvtW^gZW?+hBTO@7gnJFcW#BLm@MdKLDQ5vfHK5{MK+M1Z01(a7 A7ytkO From fe54071f5f25b2138557195af8311272ee0416f1 Mon Sep 17 00:00:00 2001 From: Peter Ebden Date: Tue, 15 Sep 2026 13:43:21 +0100 Subject: [PATCH 3/3] Simplify a bit --- .../third_party/python/BUILD_FILE | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/test/license_expression_repo/third_party/python/BUILD_FILE b/test/license_expression_repo/third_party/python/BUILD_FILE index 25c060f8..35d639ab 100644 --- a/test/license_expression_repo/third_party/python/BUILD_FILE +++ b/test/license_expression_repo/third_party/python/BUILD_FILE @@ -13,14 +13,9 @@ package( # pip_library's auto-detection of that field. genrule( name = "fakepkg_whl", - srcs = [ - "fakepkg_src/fakepkg/__init__.py", - "fakepkg_src/fakepkg-1.0.0.dist-info/METADATA", - "fakepkg_src/fakepkg-1.0.0.dist-info/WHEEL", - "fakepkg_src/fakepkg-1.0.0.dist-info/RECORD", - ], + srcs = ["fakepkg_src"], outs = ["fakepkg-1.0.0-py3-none-any.whl"], - cmd = "cd $PKG/fakepkg_src && $TOOLS_ARCAT z -d -i . -o $OUT", + cmd = "cd $SRC && $TOOLS_ARCAT z -d -i . -o $OUT", tools = {"arcat": [CONFIG.ARCAT_TOOL]}, )