-
-
Notifications
You must be signed in to change notification settings - Fork 645
exp: pypi- allow users to pass any versions #3482
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -184,6 +184,13 @@ def construct_config_settings( | |||||
|
|
||||||
| def _python_version_flag_impl(ctx): | ||||||
| value = ctx.build_setting_value | ||||||
| if value: | ||||||
| # FIXME @aignas 2025-12-27: is this the right thing to do here? Should we do this only for | ||||||
| # the `FeatureFlagInfo`? | ||||||
| # | ||||||
| # ensure that the values here are normalized | ||||||
| value = version.parse(value).string | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
|
||||||
| return [ | ||||||
| # BuildSettingInfo is the original provider returned, so continue to | ||||||
| # return it for compatibility | ||||||
|
|
@@ -203,9 +210,9 @@ _python_version_flag = rule( | |||||
| ) | ||||||
|
|
||||||
| def _python_version_major_minor_flag_impl(ctx): | ||||||
| input = _flag_value(ctx.attr._python_version_flag) | ||||||
| if input: | ||||||
| ver = version.parse(input) | ||||||
| value = _flag_value(ctx.attr._python_version_flag) | ||||||
| if value: | ||||||
| ver = version.parse(value) | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For robustness, it's better to parse with
Suggested change
|
||||||
| value = "{}.{}".format(ver.release[0], ver.release[1]) | ||||||
| else: | ||||||
| value = "" | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,9 +15,9 @@ load(":requirements_files_by_platform.bzl", "requirements_files_by_platform") | |
| load(":whl_config_setting.bzl", "whl_config_setting") | ||
| load(":whl_repo_name.bzl", "pypi_repo_name", "whl_repo_name") | ||
|
|
||
| def _major_minor_version(version_str): | ||
| def _normalize_version(version_str): | ||
| ver = version.parse(version_str) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| return "{}.{}".format(ver.release[0], ver.release[1]) | ||
| return ver.string | ||
|
|
||
| def hub_builder( | ||
| *, | ||
|
|
@@ -288,7 +288,8 @@ def _detect_interpreter(self, pip_attr): | |
| python_interpreter_target = pip_attr.python_interpreter_target | ||
| if python_interpreter_target == None and not pip_attr.python_interpreter: | ||
| python_name = "python_{}_host".format( | ||
| pip_attr.python_version.replace(".", "_"), | ||
| # normalize the version when getting the available interpreter | ||
| version.parse(pip_attr.python_version).string.replace(".", "_"), | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| ) | ||
| if python_name not in self._available_interpreters: | ||
| fail(( | ||
|
|
@@ -478,7 +479,8 @@ def _create_whl_repos( | |
| netrc = self._config.netrc or pip_attr.netrc, | ||
| use_downloader = _use_downloader(self, pip_attr.python_version, whl.name), | ||
| auth_patterns = self._config.auth_patterns or pip_attr.auth_patterns, | ||
| python_version = _major_minor_version(pip_attr.python_version), | ||
| # TODO @aignas 2025-12-27: normalize version tests | ||
| python_version = _normalize_version(pip_attr.python_version), | ||
| is_multiple_versions = whl.is_multiple_versions, | ||
| interpreter = interpreter, | ||
| enable_pipstar = enable_pipstar, | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -14,13 +14,18 @@ | |||||
|
|
||||||
| "" | ||||||
|
|
||||||
| load(":version.bzl", v = "version") | ||||||
|
|
||||||
| def version_label(version, *, sep = ""): | ||||||
| """A version fragment derived from python minor version | ||||||
| """A version fragment derived from python minor version. | ||||||
|
|
||||||
| This replaces dots with the provided separator. | ||||||
|
|
||||||
| Examples: | ||||||
| version_label("3.9") == "39" | ||||||
| version_label("3.9.12", sep="_") == "3_9" | ||||||
| version_label("3.9.12", sep="_") == "3_9_12" | ||||||
| version_label("3.11") == "311" | ||||||
| version_label("3.11.12") == "31112" | ||||||
|
|
||||||
| Args: | ||||||
| version: Python version. | ||||||
|
|
@@ -30,7 +35,5 @@ def version_label(version, *, sep = ""): | |||||
| Returns: | ||||||
| The fragment of the version. | ||||||
| """ | ||||||
| major, _, version = version.partition(".") | ||||||
| minor, _, _ = version.partition(".") | ||||||
|
|
||||||
| return major + sep + minor | ||||||
| parsed = v.parse(version) | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| return parsed.string.replace(".", sep) | ||||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -17,6 +17,8 @@ | |||||
| load("@rules_testing//lib:test_suite.bzl", "test_suite") | ||||||
| load("@rules_testing//lib:truth.bzl", "subjects") | ||||||
| load("//python/private:repo_utils.bzl", "REPO_DEBUG_ENV_VAR", "REPO_VERBOSITY_ENV_VAR", "repo_utils") # buildifier: disable=bzl-visibility | ||||||
| load("//python/private:version.bzl", _version = "version") # buildifier: disable=bzl-visibility | ||||||
| load("//python/private:version_label.bzl", "version_label") # buildifier: disable=bzl-visibility | ||||||
| load("//python/private/pypi:hub_builder.bzl", _hub_builder = "hub_builder") # buildifier: disable=bzl-visibility | ||||||
| load("//python/private/pypi:parse_simpleapi_html.bzl", "parse_simpleapi_html") # buildifier: disable=bzl-visibility | ||||||
| load("//python/private/pypi:platform.bzl", _plat = "platform") # buildifier: disable=bzl-visibility | ||||||
|
|
@@ -114,40 +116,58 @@ def hub_builder( | |||||
| return self | ||||||
|
|
||||||
| def _test_simple(env): | ||||||
| builder = hub_builder(env) | ||||||
| builder.pip_parse( | ||||||
| _mock_mctx( | ||||||
| os_name = "osx", | ||||||
| arch_name = "aarch64", | ||||||
| ), | ||||||
| _parse( | ||||||
| hub_name = "pypi", | ||||||
| python_version = "3.15", | ||||||
| requirements_lock = "requirements.txt", | ||||||
| ), | ||||||
| ) | ||||||
| pypi = builder.build() | ||||||
| for python_version, _ in { | ||||||
| "3.15": "315", | ||||||
| "3.15.0alpha2": "3150a2", | ||||||
| "3.15.0rc2": "3150rc2", | ||||||
| "3.15.2": "3152", | ||||||
| }.items(): | ||||||
| # All of the versions should be normalized | ||||||
| normalized_python_version = _version.parse(python_version).string | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This call is unsafe as
Suggested change
|
||||||
|
|
||||||
| pypi.exposed_packages().contains_exactly(["simple"]) | ||||||
| pypi.group_map().contains_exactly({}) | ||||||
| pypi.whl_map().contains_exactly({ | ||||||
| "simple": { | ||||||
| "pypi_315_simple": [ | ||||||
| whl_config_setting( | ||||||
| version = "3.15", | ||||||
| ), | ||||||
| ], | ||||||
| }, | ||||||
| }) | ||||||
| pypi.whl_libraries().contains_exactly({ | ||||||
| "pypi_315_simple": { | ||||||
| "config_load": "@pypi//:config.bzl", | ||||||
| "dep_template": "@pypi//{name}:{target}", | ||||||
| "python_interpreter_target": "unit_test_interpreter_target", | ||||||
| "requirement": "simple==0.0.1 --hash=sha256:deadbeef --hash=sha256:deadbaaf", | ||||||
| }, | ||||||
| }) | ||||||
| pypi.extra_aliases().contains_exactly({}) | ||||||
| builder = hub_builder( | ||||||
| env, | ||||||
| available_interpreters = { | ||||||
| # We are using this instead of `version_label` to keep backwards compatibility | ||||||
| "python_{}_host".format(normalized_python_version.replace(".", "_")): "unit_test_interpreter_target", | ||||||
| }, | ||||||
| ) | ||||||
| builder.pip_parse( | ||||||
| _mock_mctx( | ||||||
| os_name = "osx", | ||||||
| arch_name = "aarch64", | ||||||
| ), | ||||||
| _parse( | ||||||
| hub_name = "pypi", | ||||||
| # the input version can be whatever | ||||||
| python_version = python_version, | ||||||
| requirements_lock = "requirements.txt", | ||||||
| ), | ||||||
| ) | ||||||
| pypi = builder.build() | ||||||
|
|
||||||
| pypi.exposed_packages().contains_exactly(["simple"]) | ||||||
| pypi.group_map().contains_exactly({}) | ||||||
| pypi.whl_map().contains_exactly({ | ||||||
| "simple": { | ||||||
| # this should normalize the version inside | ||||||
| "pypi_{}_simple".format(version_label(python_version)): [ | ||||||
| whl_config_setting( | ||||||
| version = normalized_python_version, | ||||||
| ), | ||||||
| ], | ||||||
| }, | ||||||
| }) | ||||||
| pypi.whl_libraries().contains_exactly({ | ||||||
| # this should normalize the version inside | ||||||
| "pypi_{}_simple".format(version_label(python_version)): { | ||||||
| "config_load": "@pypi//:config.bzl", | ||||||
| "dep_template": "@pypi//{name}:{target}", | ||||||
| "python_interpreter_target": "unit_test_interpreter_target", | ||||||
| "requirement": "simple==0.0.1 --hash=sha256:deadbeef --hash=sha256:deadbaaf", | ||||||
| }, | ||||||
| }) | ||||||
| pypi.extra_aliases().contains_exactly({}) | ||||||
|
|
||||||
| _tests.append(_test_simple) | ||||||
|
|
||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What sort of normalization is this applying that matters?
I think it's fair to say: the provided value is expected to be a valid python version string. If it's not, behavior is undefined.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wanted to make sure that when the user specifies
3.15.0alpha0it is normalized to3.15.0a0and then we depend on normalized values when creating our own config settings.