Skip to content
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

chore: remove mandatory default values for python version flag #2217

Merged

Conversation

aignas
Copy link
Collaborator

@aignas aignas commented Sep 12, 2024

This is a different take on #2205.

Summary:

  • Remove version constraints from the //python/config_settings:python_version.
  • Remove is_python_config_setting macro and use a different implementation to
    retain the same functionality.

This in general will improve the situation on how the toolchains are registered
and hopefully is a step towards resolving issues for #2081.

Copy link
Contributor

@rickeylev rickeylev left a comment

Choose a reason for hiding this comment

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

I had an inkling of an idea that might make the config_setting generation we do much easier: use FeatureFlagInfo.

Basically, have a separate flag read the full-version flag. It returns the major.minor part. Because it returns the value using FeatureFlagInfo, it can then affect config_setting resolution. We can then do away with all the config setting groups.

So something like:

def _python_major_minor_impl(ctx):
  full_version = ctx.attr._python_version_flag
  major_minor = <parse full into X.Y>
  return [FeatureFlagInfo(value=major_minor)]

python_major_minor = rule(
  impl = _python_major_minor,
  build_setting_value = config.string(flag=False)
  attrs = {"_python_version_flag": attr.label("//python/config_settings:python_version")}
)

python_major_minor(name = "_python_major_minor")

[
config_setting(
  name = "is_python_3.{}",
  flag_values = {":_python_major_minor": "3.{}"}
)
for v in (5, 6, 7, 8, 9, 10, ...)
]

Comment on lines 22 to 28
if ctx.attr.values and value not in ctx.attr.values:
fail((
"Invalid --python_version value: {actual}\nAllowed values {allowed}"
).format(
actual = value,
allowed = ", ".join(sorted(ctx.attr.values)),
))
Copy link
Contributor

Choose a reason for hiding this comment

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

Lets just drop the values restriction on the flag entirely. I'm just not convinced all the extra wiring is worth it, and it just artificially constrains the values, requiring extra work from users to get a value into the list.

Since the flag is no longer coupled to the known values, move the flag definition to be directly in the BUILD file, like the other flags.

Worst case, you set a value that doesn't map to a toolchain, and you end up getting the default. Surprising, but not that bad. We can also build in guard elsewhere that use information from the analysis phase instead of loading phase. The two ideas that come to mind are:

  • In py_binary or equiv, make the //python:toolchain_type (fake) optional. If toolchain lookup fails, then we compare the flag to the list of known values. If the flag isn't in the list, then we print an error about the missing toolchain and mention the flag not being in the list of known values as a hint.
  • In the python_version flag definition, make values a label and point it to e.g. @pythons_hub//:known_versions (if bzlmod is true). Then fail at analysis time in the flag logic.
  • Make everything depend on an internal "check the flag value" target that does the above.

The second option in particular would make the bzlmod/workspace situation much easier -- we can just put an X if bzlmod else None clause in the attr.label value itself.

@@ -54,6 +55,15 @@ def py_repositories():
internal_config_repo,
name = "rules_python_internal",
)
maybe(
hub_repo,
name = "pythons_hub",
Copy link
Contributor

Choose a reason for hiding this comment

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

Hrm. How do we get the list of values into pythons_hub for workspace builds?
Or is the idea: we just want the repo to exist so that load() can work?

python/private/config_settings.bzl Show resolved Hide resolved
With the suggested snippet of code, this greatly simplified the codebase
@aignas aignas force-pushed the chore/remove-default-values-for-python-version branch from d7a90fa to 60dae67 Compare September 15, 2024 06:36
@aignas
Copy link
Collaborator Author

aignas commented Sep 15, 2024

I have pivoted the change and just removed all of the is_python_config_setting with the suggested rule. This has been a really nice thing to do and it solved a lot of complexity I needed to go over when I was implementing the pypi integration.

)

_python_major_minor(
name = "python_version_major_minor",
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

name is up for bike shedding.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think the name is fine -- just make it more internal sounding -- prefix it with "_". It's not a flag, and shouldn't be directly set, so lets just hide it as best we can so it isn't an attractive nuisance.

(or move it under private somewhere, but we have other internal names here, so i think an underscore is sufficient).

Copy link
Contributor

@rickeylev rickeylev left a comment

Choose a reason for hiding this comment

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

Other than the underscore prefix and CI errors, LGTM

)

_python_major_minor(
name = "python_version_major_minor",
Copy link
Contributor

Choose a reason for hiding this comment

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

I think the name is fine -- just make it more internal sounding -- prefix it with "_". It's not a flag, and shouldn't be directly set, so lets just hide it as best we can so it isn't an attractive nuisance.

(or move it under private somewhere, but we have other internal names here, so i think an underscore is sufficient).

actual = "_{}_group".format(name),
visibility = kwargs.get("visibility", []),
)
_PYTHON_MINOR_VERSION_FLAG = str(Label("//python/config_settings:python_version_major_minor"))
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggest to name the symbol after the underlying name

Suggested change
_PYTHON_MINOR_VERSION_FLAG = str(Label("//python/config_settings:python_version_major_minor"))
_PYTHON_MAJOR_MINOR_VERSION_FLAG = str(Label("//python/config_settings:python_version_major_minor"))

@rickeylev rickeylev marked this pull request as ready for review September 16, 2024 21:48
@aignas aignas added this pull request to the merge queue Sep 17, 2024
Merged via the queue into bazelbuild:main with commit 654b4d5 Sep 17, 2024
4 checks passed
@aignas aignas deleted the chore/remove-default-values-for-python-version branch September 17, 2024 05:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants