diff --git a/e2e/MODULE.bazel b/e2e/MODULE.bazel index bfd97d350..0f2684069 100644 --- a/e2e/MODULE.bazel +++ b/e2e/MODULE.bazel @@ -346,6 +346,19 @@ uv.unstable_annotate_packages( ) # }}} +# For cases/uv-include-group-versions (PEP 735 include-group version preference) +# {{{ +uv.project( + hub_name = "pypi", + lock = "//cases/uv-include-group-versions:uv.lock", + pyproject = "//cases/uv-include-group-versions:pyproject.toml", +) +uv.unstable_annotate_packages( + src = "//cases/uv-legacy-deps-750:annotations.toml", + lock = "//cases/uv-include-group-versions:uv.lock", +) +# }}} + # For cases/uv-abi3-compat-853 # Regression: abi3 wheel compatibility must propagate to newer Python minors. # {{{ diff --git a/e2e/cases/uv-include-group-versions/BUILD.bazel b/e2e/cases/uv-include-group-versions/BUILD.bazel new file mode 100644 index 000000000..12a291d1f --- /dev/null +++ b/e2e/cases/uv-include-group-versions/BUILD.bazel @@ -0,0 +1,20 @@ +load("@aspect_rules_py//py/unstable:defs.bzl", "py_venv_test") + +py_venv_test( + name = "include_group_versions_build", + srcs = ["__test__.py"], + main = "__test__.py", + python_version = "3.10", + venv = "igv-build", + deps = ["@pypi//packaging"], +) + +py_venv_test( + name = "include_group_versions_test", + srcs = ["__test__.py"], + args = ["igv-test"], + main = "__test__.py", + python_version = "3.10", + venv = "igv-test", + deps = ["@pypi//packaging"], +) diff --git a/e2e/cases/uv-include-group-versions/__test__.py b/e2e/cases/uv-include-group-versions/__test__.py new file mode 100644 index 000000000..5a446a9e7 --- /dev/null +++ b/e2e/cases/uv-include-group-versions/__test__.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 +"""Test that PEP 735 include-group version preferences are preserved. + +This project declares two pairs of conflicting dependency groups: +- igv-build-base / igv-build use packaging==24.0 +- igv-test-base / igv-test use packaging==21.3 + +Each outer group includes its base group via {include-group = ...}. uv.lock +records a different packaging version for each group. This test verifies that +rules_py installs the per-group version selected by uv.lock. +""" + +import sys +from importlib.metadata import version + +GROUPS = { + "igv-build": "24.0", + "igv-test": "21.3", +} + + +def main(): + group = sys.argv[1] if len(sys.argv) > 1 else "igv-build" + expected = GROUPS[group] + actual = version("packaging") + print(f"{group}/packaging: {actual} (expected {expected})") + assert actual == expected, ( + f"Expected packaging=={expected} for {group} group, got {actual}" + ) + + +if __name__ == "__main__": + main() diff --git a/e2e/cases/uv-include-group-versions/pyproject.toml b/e2e/cases/uv-include-group-versions/pyproject.toml new file mode 100644 index 000000000..2c63f6d7a --- /dev/null +++ b/e2e/cases/uv-include-group-versions/pyproject.toml @@ -0,0 +1,19 @@ +[project] +name = "include-group-versions-test" +version = "0.0.0" +requires-python = "== 3.10.19" +dependencies = [] + +[dependency-groups] +igv-build-base = ["packaging==24.0"] +igv-test-base = ["packaging==21.3"] +igv-build = [{include-group = "igv-build-base"}] +igv-test = [{include-group = "igv-test-base"}] + +[tool.uv] +conflicts = [ + [{ group = "igv-build-base" }, { group = "igv-test-base" }], + [{ group = "igv-build" }, { group = "igv-test" }], + [{ group = "igv-build-base" }, { group = "igv-test" }], + [{ group = "igv-test-base" }, { group = "igv-build" }], +] diff --git a/e2e/cases/uv-include-group-versions/uv.lock b/e2e/cases/uv-include-group-versions/uv.lock new file mode 100644 index 000000000..4080a1af7 --- /dev/null +++ b/e2e/cases/uv-include-group-versions/uv.lock @@ -0,0 +1,73 @@ +version = 1 +revision = 3 +requires-python = "==3.10.19" +conflicts = [[ + { package = "include-group-versions-test", group = "igv-build-base" }, + { package = "include-group-versions-test", group = "igv-test-base" }, +], [ + { package = "include-group-versions-test", group = "igv-build" }, + { package = "include-group-versions-test", group = "igv-test" }, +], [ + { package = "include-group-versions-test", group = "igv-build-base" }, + { package = "include-group-versions-test", group = "igv-test" }, +], [ + { package = "include-group-versions-test", group = "igv-build" }, + { package = "include-group-versions-test", group = "igv-test-base" }, +]] + +[[package]] +name = "include-group-versions-test" +version = "0.0.0" +source = { virtual = "." } + +[package.dev-dependencies] +igv-build = [ + { name = "packaging", version = "24.0", source = { registry = "https://pypi.org/simple" } }, +] +igv-build-base = [ + { name = "packaging", version = "24.0", source = { registry = "https://pypi.org/simple" } }, +] +igv-test = [ + { name = "packaging", version = "21.3", source = { registry = "https://pypi.org/simple" } }, +] +igv-test-base = [ + { name = "packaging", version = "21.3", source = { registry = "https://pypi.org/simple" } }, +] + +[package.metadata] + +[package.metadata.requires-dev] +igv-build = [{ name = "packaging", specifier = "==24.0" }] +igv-build-base = [{ name = "packaging", specifier = "==24.0" }] +igv-test = [{ name = "packaging", specifier = "==21.3" }] +igv-test-base = [{ name = "packaging", specifier = "==21.3" }] + +[[package]] +name = "packaging" +version = "21.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyparsing" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/df/9e/d1a7217f69310c1db8fdf8ab396229f55a699ce34a203691794c5d1cad0c/packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb", size = 84848, upload-time = "2021-11-18T00:39:13.586Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/05/8e/8de486cbd03baba4deef4142bd643a3e7bbe954a784dc1bb17142572d127/packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522", size = 40750, upload-time = "2021-11-18T00:39:10.932Z" }, +] + +[[package]] +name = "packaging" +version = "24.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ee/b5/b43a27ac7472e1818c4bafd44430e69605baefe1f34440593e0332ec8b4d/packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9", size = 147882, upload-time = "2024-03-10T09:39:28.33Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/49/df/1fceb2f8900f8639e278b056416d49134fb8d84c5942ffaa01ad34782422/packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5", size = 53488, upload-time = "2024-03-10T09:39:25.947Z" }, +] + +[[package]] +name = "pyparsing" +version = "3.3.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f3/91/9c6ee907786a473bf81c5f53cf703ba0957b23ab84c264080fb5a450416f/pyparsing-3.3.2.tar.gz", hash = "sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc", size = 6851574, upload-time = "2026-01-21T03:57:59.36Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl", hash = "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d", size = 122781, upload-time = "2026-01-21T03:57:55.912Z" }, +]