Skip to content

Commit

Permalink
let users point a bazooka a their foot wtih SetupKwargs plugins (pant…
Browse files Browse the repository at this point in the history
…sbuild#21394)

Preciously one could write a plugin and with `_allow_banned_keys` set
something like `install_requires`. The new and even more dangerous
`_overwrite_banned_keys` allows one to exclusively use values calculated
in their plugin.

The motivating use case is a plugin that builds a wheel with all
dependencies pinned to the value from lockfile.

ref pantsbuild#21252
  • Loading branch information
cburroughs authored Sep 17, 2024
1 parent 69255bd commit f3f55ea
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 9 deletions.
3 changes: 3 additions & 0 deletions docs/notes/2.23.x.md
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,9 @@ Several intrinsics have been renamed more succinctly, to make them more readable
An execute_process_or_raise() alias has been added for the fallible_to_exec_result_or_raise rule, so that
code that calls it by name on an implicitly executed process will be more readable.

Previously `SetupKwargs` took `_allow_banned_keys` which would allow one to pass in certain critical setuptools args (ex: `install_requires`) that Pants calculates for you. If you Really Really know what you are doing you can know also use `_overwrite_banned_keys` to exclusively use your own values and ignore the Pants calculated ones.


### Other minor tweaks

The "Provided by" information in the documentation now correctly reflects the proper backend to enable to activate a certain feature.
Expand Down
43 changes: 34 additions & 9 deletions src/python/pants/backend/python/util_rules/package_dists.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,9 +217,15 @@ class SetupKwargs:
"""The keyword arguments to the `setup()` function in the generated `setup.py`."""

_pickled_bytes: bytes
_overwrite_banned_keys: Tuple[str, ...]

def __init__(
self, kwargs: Mapping[str, Any], *, address: Address, _allow_banned_keys: bool = False
self,
kwargs: Mapping[str, Any],
*,
address: Address,
_allow_banned_keys: bool = False,
_overwrite_banned_keys: Tuple[str, ...] = (),
) -> None:
super().__init__()
if "name" not in kwargs:
Expand Down Expand Up @@ -249,7 +255,9 @@ def __init__(
"""
)
)

object.__setattr__(
self, "_overwrite_banned_keys", _overwrite_banned_keys if _overwrite_banned_keys else ()
)
# We serialize with `pickle` so that is hashable. We don't use `FrozenDict` because it
# would require that all values are immutable, and we may have lists and dictionaries as
# values. It's too difficult/clunky to convert those all, then to convert them back out of
Expand Down Expand Up @@ -645,18 +653,35 @@ async def determine_finalized_setup_kwargs(request: GenerateSetupPyRequest) -> F
next(str(ic.specifier) for ic in request.interpreter_constraints), # type: ignore[attr-defined]
)

# NB: We are careful to not overwrite these values, but we also don't expect them to have been
# set. The user must have gone out of their way to use a `SetupKwargs` plugin, and to have
# specified `SetupKwargs(_allow_banned_keys=True)`.
# The cascading defaults here are for two levels of "I know what I'm
# doing. Normally the plugin will calculate the appropriate values. If
# the user Really Knows what they are doing and has gone out of their way
# to use a `SetupKwargs` plugin, and to have also specified
# `SetupKwargs(_allow_banned_keys=True)`, then instead the values are
# merged. If the user REALLY REALLY knows what they are doing, they can
# use `_overwrite_banned_keys=("the-key",)` in their plugin to use only
# their value for that key.
def _overwrite_value(key: str) -> bool:
return key in resolved_setup_kwargs._overwrite_banned_keys

setup_kwargs.update(
{
"packages": (*sources.packages, *(setup_kwargs.get("packages", []))),
"packages": (
*(sources.packages if not _overwrite_value("packages") else []),
*(setup_kwargs.get("packages", [])),
),
"namespace_packages": (
*sources.namespace_packages,
*(sources.namespace_packages if not _overwrite_value("namespace_packages") else []),
*setup_kwargs.get("namespace_packages", []),
),
"package_data": {**dict(sources.package_data), **setup_kwargs.get("package_data", {})},
"install_requires": (*requirements, *setup_kwargs.get("install_requires", [])),
"package_data": {
**dict(sources.package_data if not _overwrite_value("package_data") else {}),
**setup_kwargs.get("package_data", {}),
},
"install_requires": (
*(requirements if not _overwrite_value("install_requires") else []),
*setup_kwargs.get("install_requires", []),
),
}
)

Expand Down

0 comments on commit f3f55ea

Please sign in to comment.