Skip to content
Merged
Show file tree
Hide file tree
Changes from 54 commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
2c12496
fix(pypi): default platform_version to 0
aignas May 3, 2025
118590c
wip: finish PEP508/PEP440 impl for version matching
aignas May 3, 2025
aa613f8
wip
aignas May 3, 2025
28ff6be
wip
aignas May 3, 2025
2fc298b
Clarify comment about fallback behavior
rickeylev May 3, 2025
fb92a2c
factor out helper evaluate assert
rickeylev May 3, 2025
6d511c6
add generic test for arbitrary expressions
rickeylev May 3, 2025
1c45c9e
add missing dep to build target
rickeylev May 3, 2025
7fef735
removed unused _VERSION_CMP
rickeylev May 3, 2025
68178a3
add bzl_library for pep440 code
rickeylev May 4, 2025
7c6699b
run pre-commit formatting
rickeylev May 4, 2025
2231024
fix bad evaluate call
rickeylev May 4, 2025
a302509
maybe fix == comparison wth star suffix
rickeylev May 4, 2025
b7860ae
remove 'upper' helper and simplify prefix matching
aignas May 5, 2025
0666d56
handle zero padding correctly
aignas May 5, 2025
a98f654
implement more of the test cases for the gt operator
aignas May 5, 2025
db949b2
fix tests
aignas May 6, 2025
fe0ca65
Add more implementation for the version comparisons
aignas May 6, 2025
f357a32
add tests from the page
aignas May 6, 2025
67c6e49
handle post.dev versions
aignas May 6, 2025
4db2ff7
handle pre-release ordering
aignas May 6, 2025
fef7a3c
handle dev
aignas May 6, 2025
1872cbc
finish implementing the correct ordering for most versions
aignas May 6, 2025
5d7fc1a
Implement local version matching
aignas May 6, 2025
3267dad
simplify the key test
aignas May 6, 2025
704fa64
add notes
aignas May 6, 2025
8f2c0c5
add tests for inclusive matches
aignas May 6, 2025
e545c7d
for now fix the test
aignas May 6, 2025
436ef9d
instead of fixing the test, do something more clever - check for equa…
aignas May 6, 2025
b84d109
get rid of a parser
aignas May 6, 2025
a5f45f4
move the implementation for the compatible version matcher
aignas May 8, 2025
3106315
create an eqq operator and simplify
aignas May 9, 2025
22da480
Add a new file for parsing versions
aignas May 9, 2025
4469bee
simplify the implementation
aignas May 9, 2025
f3a9969
simplify
aignas May 9, 2025
6047094
reorder methods
aignas May 9, 2025
af8eee9
reorder methods more
aignas May 9, 2025
e64c199
dedupe code for normalization and the actual version parsing
aignas May 9, 2025
74b029d
dedupe code for normalization and the actual version parsing
aignas May 9, 2025
a3820a8
reformat
aignas May 9, 2025
42c866f
reformat
aignas May 9, 2025
2d7d9e5
rework the code structure a little
aignas May 9, 2025
743fd38
refactor recursiveness
aignas May 9, 2025
ea6c127
reorder the code
aignas May 9, 2025
cbbb345
refactor: do not use object oriented style
aignas May 10, 2025
c56ac32
fix epoch parsing
aignas May 10, 2025
f7eec91
finish adding tests
aignas May 10, 2025
ff23111
simplify the parsing function
aignas May 10, 2025
90ce28c
add changelog
aignas May 10, 2025
9c8d123
fixup
aignas May 10, 2025
aca2ad8
Merge branch 'main' into refactor-use-pep440-version-parser
aignas May 10, 2025
ab1972d
move the pep440 version tests to its own file
aignas May 10, 2025
9a22e1f
comment: rename a leftover eqq from previous times
aignas May 10, 2025
8c90d9f
consolidate changelog entry
rickeylev May 10, 2025
655cd52
Update python/private/version.bzl
rickeylev May 10, 2025
c837f10
Update python/private/version.bzl
rickeylev May 10, 2025
188a9e7
Update python/private/version.bzl
rickeylev May 10, 2025
773b1a7
run buildifier
aignas May 11, 2025
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
4 changes: 2 additions & 2 deletions .bazelrc
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
# (Note, we cannot use `common --deleted_packages` because the bazel version command doesn't support it)
# To update these lines, execute
# `bazel run @rules_bazel_integration_test//tools:update_deleted_packages`
build --deleted_packages=examples/build_file_generation,examples/build_file_generation/random_number_generator,examples/bzlmod,examples/bzlmod/entry_points,examples/bzlmod/entry_points/tests,examples/bzlmod/libs/my_lib,examples/bzlmod/other_module,examples/bzlmod/other_module/other_module/pkg,examples/bzlmod/patches,examples/bzlmod/py_proto_library,examples/bzlmod/py_proto_library/example.com/another_proto,examples/bzlmod/py_proto_library/example.com/proto,examples/bzlmod/runfiles,examples/bzlmod/tests,examples/bzlmod/tests/other_module,examples/bzlmod/whl_mods,examples/bzlmod_build_file_generation,examples/bzlmod_build_file_generation/other_module/other_module/pkg,examples/bzlmod_build_file_generation/runfiles,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_proto_library,examples/py_proto_library/example.com/another_proto,examples/py_proto_library/example.com/proto,gazelle,gazelle/manifest,gazelle/manifest/generate,gazelle/manifest/hasher,gazelle/manifest/test,gazelle/modules_mapping,gazelle/python,gazelle/python/private,gazelle/pythonconfig,tests/integration/compile_pip_requirements,tests/integration/compile_pip_requirements_test_from_external_repo,tests/integration/custom_commands,tests/integration/ignore_root_user_error,tests/integration/ignore_root_user_error/submodule,tests/integration/local_toolchains,tests/integration/pip_parse,tests/integration/pip_parse/empty,tests/integration/py_cc_toolchain_registered,tests/modules/other,tests/modules/other/nspkg_delta,tests/modules/other/nspkg_gamma
query --deleted_packages=examples/build_file_generation,examples/build_file_generation/random_number_generator,examples/bzlmod,examples/bzlmod/entry_points,examples/bzlmod/entry_points/tests,examples/bzlmod/libs/my_lib,examples/bzlmod/other_module,examples/bzlmod/other_module/other_module/pkg,examples/bzlmod/patches,examples/bzlmod/py_proto_library,examples/bzlmod/py_proto_library/example.com/another_proto,examples/bzlmod/py_proto_library/example.com/proto,examples/bzlmod/runfiles,examples/bzlmod/tests,examples/bzlmod/tests/other_module,examples/bzlmod/whl_mods,examples/bzlmod_build_file_generation,examples/bzlmod_build_file_generation/other_module/other_module/pkg,examples/bzlmod_build_file_generation/runfiles,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_proto_library,examples/py_proto_library/example.com/another_proto,examples/py_proto_library/example.com/proto,gazelle,gazelle/manifest,gazelle/manifest/generate,gazelle/manifest/hasher,gazelle/manifest/test,gazelle/modules_mapping,gazelle/python,gazelle/python/private,gazelle/pythonconfig,tests/integration/compile_pip_requirements,tests/integration/compile_pip_requirements_test_from_external_repo,tests/integration/custom_commands,tests/integration/ignore_root_user_error,tests/integration/ignore_root_user_error/submodule,tests/integration/local_toolchains,tests/integration/pip_parse,tests/integration/pip_parse/empty,tests/integration/py_cc_toolchain_registered,tests/modules/other,tests/modules/other/nspkg_delta,tests/modules/other/nspkg_gamma
build --deleted_packages=examples/build_file_generation,examples/build_file_generation/random_number_generator,examples/bzlmod,examples/bzlmod_build_file_generation,examples/bzlmod_build_file_generation/other_module/other_module/pkg,examples/bzlmod_build_file_generation/runfiles,examples/bzlmod/entry_points,examples/bzlmod/entry_points/tests,examples/bzlmod/libs/my_lib,examples/bzlmod/other_module,examples/bzlmod/other_module/other_module/pkg,examples/bzlmod/patches,examples/bzlmod/py_proto_library,examples/bzlmod/py_proto_library/example.com/another_proto,examples/bzlmod/py_proto_library/example.com/proto,examples/bzlmod/runfiles,examples/bzlmod/tests,examples/bzlmod/tests/other_module,examples/bzlmod/whl_mods,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_proto_library,examples/py_proto_library/example.com/another_proto,examples/py_proto_library/example.com/proto,gazelle,gazelle/manifest,gazelle/manifest/generate,gazelle/manifest/hasher,gazelle/manifest/test,gazelle/modules_mapping,gazelle/python,gazelle/pythonconfig,gazelle/python/private,tests/integration/compile_pip_requirements,tests/integration/compile_pip_requirements_test_from_external_repo,tests/integration/custom_commands,tests/integration/ignore_root_user_error,tests/integration/ignore_root_user_error/submodule,tests/integration/local_toolchains,tests/integration/pip_parse,tests/integration/pip_parse/empty,tests/integration/py_cc_toolchain_registered,tests/modules/other,tests/modules/other/nspkg_delta,tests/modules/other/nspkg_gamma
query --deleted_packages=examples/build_file_generation,examples/build_file_generation/random_number_generator,examples/bzlmod,examples/bzlmod_build_file_generation,examples/bzlmod_build_file_generation/other_module/other_module/pkg,examples/bzlmod_build_file_generation/runfiles,examples/bzlmod/entry_points,examples/bzlmod/entry_points/tests,examples/bzlmod/libs/my_lib,examples/bzlmod/other_module,examples/bzlmod/other_module/other_module/pkg,examples/bzlmod/patches,examples/bzlmod/py_proto_library,examples/bzlmod/py_proto_library/example.com/another_proto,examples/bzlmod/py_proto_library/example.com/proto,examples/bzlmod/runfiles,examples/bzlmod/tests,examples/bzlmod/tests/other_module,examples/bzlmod/whl_mods,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_proto_library,examples/py_proto_library/example.com/another_proto,examples/py_proto_library/example.com/proto,gazelle,gazelle/manifest,gazelle/manifest/generate,gazelle/manifest/hasher,gazelle/manifest/test,gazelle/modules_mapping,gazelle/python,gazelle/pythonconfig,gazelle/python/private,tests/integration/compile_pip_requirements,tests/integration/compile_pip_requirements_test_from_external_repo,tests/integration/custom_commands,tests/integration/ignore_root_user_error,tests/integration/ignore_root_user_error/submodule,tests/integration/local_toolchains,tests/integration/pip_parse,tests/integration/pip_parse/empty,tests/integration/py_cc_toolchain_registered,tests/modules/other,tests/modules/other/nspkg_delta,tests/modules/other/nspkg_gamma

test --test_output=errors

Expand Down
6 changes: 3 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,9 @@ END_UNRELEASED_TEMPLATE
(the default), the subprocess's stdout/stderr will be logged.
* (toolchains) Local toolchains can be activated with custom flags. See
[Conditionally using local toolchains] docs for how to configure.
* (pypi) `RULES_PYTHON_ENABLE_PIPSTAR` environment variable: when `1`, the Starlark
implementation of wheel METADATA parsing is used (which has improved multi-platform
build support).
* (pypi) Starlark-based evaluation of environment markers (requirements.txt conditionals)
available (not enabled by default) for improved multi-platform build support.
Set the `RULES_PYTHON_ENABLE_PIPSTAR=1` environment variable to enable it.

{#v0-0-0-removed}
### Removed
Expand Down
2 changes: 1 addition & 1 deletion python/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,9 @@ bzl_library(
"//python/private:bzlmod_enabled_bzl",
"//python/private:py_package.bzl",
"//python/private:py_wheel_bzl",
"//python/private:py_wheel_normalize_pep440.bzl",
"//python/private:stamp_bzl",
"//python/private:util_bzl",
"//python/private:version.bzl",
"@bazel_skylib//rules:native_binary",
],
)
Expand Down
7 changes: 6 additions & 1 deletion python/private/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,11 @@ bzl_library(
],
)

bzl_library(
name = "version_bzl",
srcs = ["version.bzl"],
)

bzl_library(
name = "version_label_bzl",
srcs = ["version_label.bzl"],
Expand Down Expand Up @@ -701,7 +706,7 @@ exports_files(
"repack_whl.py",
"py_package.bzl",
"py_wheel.bzl",
"py_wheel_normalize_pep440.bzl",
"version.bzl",
"reexports.bzl",
"stamp.bzl",
"util.bzl",
Expand Down
8 changes: 4 additions & 4 deletions python/private/py_wheel.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@

load(":py_info.bzl", "PyInfo")
load(":py_package.bzl", "py_package_lib")
load(":py_wheel_normalize_pep440.bzl", "normalize_pep440")
load(":stamp.bzl", "is_stamping_enabled")
load(":version.bzl", "version")

PyWheelInfo = provider(
doc = "Information about a wheel produced by `py_wheel`",
Expand Down Expand Up @@ -306,11 +306,11 @@ def _input_file_to_arg(input_file):
def _py_wheel_impl(ctx):
abi = _replace_make_variables(ctx.attr.abi, ctx)
python_tag = _replace_make_variables(ctx.attr.python_tag, ctx)
version = _replace_make_variables(ctx.attr.version, ctx)
version_str = _replace_make_variables(ctx.attr.version, ctx)

filename_segments = [
_escape_filename_distribution_name(ctx.attr.distribution),
normalize_pep440(version),
version.normalize(version_str),
_escape_filename_segment(python_tag),
_escape_filename_segment(abi),
_escape_filename_segment(ctx.attr.platform),
Expand Down Expand Up @@ -343,7 +343,7 @@ def _py_wheel_impl(ctx):

args = ctx.actions.args()
args.add("--name", ctx.attr.distribution)
args.add("--version", version)
args.add("--version", version_str)
args.add("--python_tag", python_tag)
args.add("--abi", abi)
args.add("--platform", ctx.attr.platform)
Expand Down
1 change: 1 addition & 0 deletions python/private/pypi/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ bzl_library(
srcs = ["pep508_env.bzl"],
deps = [
":pep508_platform_bzl",
"//python/private:version_bzl",
],
)

Expand Down
58 changes: 22 additions & 36 deletions python/private/pypi/pep508_evaluate.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,11 @@
"""

load("//python/private:enum.bzl", "enum")
load("//python/private:semver.bzl", "semver")
load("//python/private:version.bzl", "version")

# The expression parsing and resolution for the PEP508 is below
#

# Taken from
# https://peps.python.org/pep-0508/#grammar
#
# version_cmp = wsp* '<' | '<=' | '!=' | '==' | '>=' | '>' | '~=' | '==='
_VERSION_CMP = sorted(
[
i.strip(" '")
for i in "'<' | '<=' | '!=' | '==' | '>=' | '>' | '~=' | '==='".split(" | ")
],
key = lambda x: (-len(x), x),
)

_STATE = enum(
STRING = "string",
VAR = "var",
Expand Down Expand Up @@ -353,36 +341,34 @@ def _env_expr(left, op, right):
elif op == ">=":
return left >= right
else:
return fail("TODO: op unsupported: '{}'".format(op))
return fail("unsupported op: '{}' {} '{}'".format(left, op, right))

def _version_expr(left, op, right):
"""Evaluate a version comparison expression"""
left = semver(left)
right = semver(right)
_left = left.key()
_right = right.key()
if op == "<":
return _left < _right
_left = version.parse(left)
_right = version.parse(right)
if _left == None or _right == None:
# Per spec, if either can't be normalized to a version, then
# fallback to simple string comparison. Usually this is `platform_version`
# or `platform_release`, which vary depending on platform.
return _env_expr(left, op, right)

if op == "===":
return version.is_eeq(_left, _right)
elif op == "!=":
return version.is_ne(_left, _right)
elif op == "==":
return version.is_eq(_left, _right)
elif op == "<":
return version.is_lt(_left, _right)
elif op == ">":
return _left > _right
return version.is_gt(_left, _right)
elif op == "<=":
return _left <= _right
return version.is_le(_left, _right)
elif op == ">=":
return _left >= _right
elif op == "!=":
return _left != _right
elif op == "==":
# Matching of major, minor, patch only
return _left[:3] == _right[:3]
return version.is_ge(_left, _right)
elif op == "~=":
right_plus = right.upper()
_right_plus = right_plus.key()
return _left >= _right and _left < _right_plus
elif op == "===":
# Strict matching
return _left == _right
elif op in _VERSION_CMP:
fail("TODO: op unsupported: '{}'".format(op))
return version.is_compatible(_left, _right)
else:
return False # Let's just ignore the invalid ops

Expand Down
27 changes: 0 additions & 27 deletions python/private/semver.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -43,32 +43,6 @@ def _to_dict(self):
"pre_release": self.pre_release,
}

def _upper(self):
major = self.major
minor = self.minor
patch = self.patch
build = ""
pre_release = ""
version = self.str()

if patch != None:
minor = minor + 1
patch = 0
elif minor != None:
major = major + 1
minor = 0
elif minor == None:
major = major + 1

return _new(
major = major,
minor = minor,
patch = patch,
build = build,
pre_release = pre_release,
version = "~" + version,
)

def _new(*, major, minor, patch, pre_release, build, version = None):
# buildifier: disable=uninitialized
self = struct(
Expand All @@ -82,7 +56,6 @@ def _new(*, major, minor, patch, pre_release, build, version = None):
key = lambda: _key(self),
str = lambda: version,
to_dict = lambda: _to_dict(self),
upper = lambda: _upper(self),
)
return self

Expand Down
Loading