-
-
Notifications
You must be signed in to change notification settings - Fork 649
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
expose a v2 ruleset for BinaryToolBase #8859
expose a v2 ruleset for BinaryToolBase #8859
Conversation
64a923d
to
36aaef7
Compare
…ecutables (#8860) ### Problem We use the same boilerplate in `cloc.py` and `download_pex_bin.py` to wrap a `Snapshot` consumed by a `UrlToFetch`, e.g.: https://github.com/pantsbuild/pants/blob/43ffe73ada2fcbc2571172193c30b906d2de944f/src/python/pants/backend/python/rules/download_pex_bin.py#L64-L65 ### Solution - Create `SingleFileExecutable` dataclass in `engine/fs.py`, which validates that the input has only one file, and has a convenience method `.exe_filename` to return a relative path to the wrapped executable which can be used in a hermetic process execution. - Use `SingleFileExecutable` for both `cloc` and `pex`. ### Result Along with #8859, this helps to simplify the experience of fetching an executable via `UrlToFetch`!
dc7bb8e
to
fa82282
Compare
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.
Cool! Will review tomorrow. (Please ping me on Slack if I forget)
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.
This looks good to me, modulo the changes to --help
messages.
I'm not approving, though, because I've never understood the BinaryTool pattern well enough to give an approval. Everything looks right to me, I only want to defer to someone with more confidence here.
In my view, the idea behind For example, adding Would love to help make this less mysterious in the future! |
d91944f
to
a62f73a
Compare
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.
Nice!
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.
Thanks for explaining how BinaryTool works!
5258b72
to
ff1da71
Compare
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.
Thanks a lot! I don't see anything blocking here, but it would be good to clean up the (ab)use of BinaryUtil.host_platform
a bit.
for platform_constraint, tool in cls.default_versions_and_digests.items() | ||
}, | ||
fingerprint=True, | ||
help='A dict mapping <platform constraint> -> (<version>, <fingerprint>, <size_bytes>).' |
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.
Can you think of a usecase for having a different version per platform? Feels like that could safely stay in the --version
field...
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.
If one of them needs to be patched for some platform-specific performance regression or security vulnerability!
@@ -115,6 +166,22 @@ def register_options(cls, register): | |||
version_registration_kwargs['fingerprint'] = True | |||
register('--version', **version_registration_kwargs) | |||
|
|||
register('--version-digest-mapping', type=dict, |
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.
How would you set one of these in a pants.ini file or on the command line? Are tuples representable in ini?
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.
Yes: we parse python literals from the ini
.
a824706
to
4e08ed4
Compare
0aa34cb
to
53b6a03
Compare
209efd1
to
e6573b9
Compare
update BinaryTool to have a default_digest field make DownloadPexBin.Factory use BinaryToolFetchRequest make cloc use BinaryToolFetchRequest docstrings for the new options, and misc fixups add RootRule add SingleFileExecutable @rule! add a note about how to calculate --fingerprint and --size-bytes! fix test failures move some logic out of BinaryToolBase and into an @rule fetch by PlatformConstraint! remove unnecessary classproperties update tests for macos version bound method
we do this by injecting DownloadedPexBin.Factory.global_instance()
1457caf
to
b2f0e6d
Compare
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.
Exciting!
The only concerning part is how this impacts ~unrelated tests like the Python linter tests. I'd appreciate checking out the two things I mentioned and, if possible, the last one about DownloadedPexBin.Factory
, which I know gave some challenges.
Thanks for making progress on this long-standing issue!
return (*super().rules(), *bandit_rules(), RootRule(BanditTarget)) | ||
return ( | ||
*super().rules(), | ||
*bandit_rules(), | ||
download_pex_bin.download_pex_bin, | ||
*pex.rules(), | ||
*python_native_code.rules(), | ||
*subprocess_environment.rules(), | ||
RootRule(BanditTarget), | ||
RootRule(download_pex_bin.DownloadedPexBin.Factory), | ||
) |
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.
Hm, this is a bit of a regression. The purpose of #9059 was to only need to have (*super().rules(), *bandit_rules(), RootRule(BanditTarget))
in the test runner and nothing else.
Can you please check these things:
- Can you remove
*pex.rules(), *python_native_code.rules(), *subprocess_environment.rules()
from here and see if the tests work? - Does this tool still work if you remove from
pants.ini
pants.backend.python
and only havepants.backend.python.lint.bandit
enabled?
If possible, it'd also be great to get the DownloadPexBin.Factory
thing working so that you don't need to special-case it here. I know you were having some trouble with that. What issue were you running into?
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 know you were having some trouble with that. What issue were you running into?
I don't recall this issue?
The purpose of #9059 was to only need to have (*super().rules(), *bandit_rules(), RootRule(BanditTarget))
This PR was from before then, so I suspect this change will work.
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.
Ok, removing the same from the python awslambda test didn't work. I don't know if this was really "special-cased" as you describe -- I recall @gshuflin had this issue yesterday where we needed to inject PythonSetup
in this exact way. I in fact used this PR to demonstrate how that was necessary. I'm not sure what kind of special-casing you're referring to with this comment and I am under the impression that injecting these as RootRule
s is correct. As @gshuflin was also discussing with me yesterday, if you're concerned about the boilerplate, factoring this code into a common test base class seems appropriate.
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 am under the impression that injecting these as RootRules is correct
We do not want to register subsystems as RootRule
s in tests, nor do we want to have to call init_subsystem
in V2 tests. The subystem_rule
declaration from production code should ideally work with the tests too.
Note that these lint tests did not previously need to call RootRule(PythonSetup)
, RootRule(SourceRootConfig)
, etc.
Originally, we actually did have to do this, but thanks to #8943 we no longer need to because we pass OptionsBootstrapper
to the tests.
--
I recall @gshuflin had this issue yesterday where we needed to inject PythonSetup in this exact way.
We figured out the issue yesterday and no longer need to pass RootRule(PythonSetup)
. The issue yesterday was that we were passing RootRule(BuildRoot)
when we shouldn't have, which meant then registering a bunch of rules that were unnecessary. See https://github.com/pantsbuild/pants/pull/9077/files#diff-dbe7c30c024e6830b7a7786c4521fbf2 for what we ended up registering.
if you're concerned about the boilerplate, factoring this code into a common test base class seems appropriate.
That's one option, but even better would be being able to go back to the only boilerplate being the test having to register this:
def rules():
return (*super().rules(), *bandit_rules(), RootRule(BanditTarget))
The first win would be to try this:
Can you remove *pex.rules(), *python_native_code.rules(), *subprocess_environment.rules() from here and see if the tests work?
The next win would be
It'd also be great to get the DownloadPexBin.Factory thing working so that you don't need to special-case it here
Per this, Ok, removing the same from the python awslambda test didn't work.
, it sounds like that second part is a little harder to do though. What is the issue you run into with that second change?
# If we pull in the subsystem_rule() as well from this file, we get an error saying the scope | ||
# 'download-pex-bin' was not found when trying to fetch the appropriate scope. | ||
download_pex_bin.download_pex_bin, |
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.
(See below commit in the bandit
file about the possibility of trying to fix this.)
return ( | ||
*super().rules(), | ||
*black_rules(), | ||
download_pex_bin.download_pex_bin, | ||
*pex.rules(), | ||
*python_native_code.rules(), | ||
*subprocess_environment.rules(), | ||
RootRule(BlackTarget), | ||
RootRule(download_pex_bin.DownloadedPexBin.Factory), | ||
) |
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.
Ditto on the bandit comments
return ( | ||
*super().rules(), | ||
*flake8_rules(), | ||
download_pex_bin.download_pex_bin, | ||
*pex.rules(), | ||
*python_native_code.rules(), | ||
*subprocess_environment.rules(), | ||
RootRule(Flake8Target), | ||
RootRule(download_pex_bin.DownloadedPexBin.Factory), | ||
) |
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.
Ditto on the bandit comments
return ( | ||
*super().rules(), | ||
*isort_rules(), | ||
download_pex_bin.download_pex_bin, | ||
*pex.rules(), | ||
*python_native_code.rules(), | ||
*subprocess_environment.rules(), | ||
RootRule(IsortTarget), | ||
RootRule(download_pex_bin.DownloadedPexBin.Factory), | ||
) |
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.
Ditto on the bandit comments
download_pex_bin.download_pex_bin, | ||
*pex.rules(), | ||
*python_native_code.rules(), | ||
*subprocess_environment.rules(), |
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.
Ditto on the bandit comments
}, | ||
fingerprint=True, | ||
help='A dict mapping <platform constraint> -> (<version>, <fingerprint>, <size_bytes>).' | ||
f'A "platform constraint" is any of {[c.value for c in PlatformConstraint]}, and ' |
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 love this dynamic help message!
'all environments it needs to be used for. The "fingerprint" and "size_bytes" ' | ||
'arguments are the result printed when running `sha256sum` and `wc -c` on ' | ||
'the downloaded file, respectively.') | ||
|
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.
Great! Thanks!
Recently, we added support for configuring the version of V2 binary tools like Pex in #8859. One of the tests was failing because the `download-pex-bin` option scope was not registered. This was because `pants.backend.awslambda.python` used to have an implicit dependency on `pants.backend.python` to work properly; without `pants.backend.python` registered, the AWSLambda backend would not work properly because it would not register all the subsystems and rules needed to stand on its own. This fixes it so that `pants.backend.awslambda.python` will work even if `pants.backend.python` is not registered. This also cleans up the linter tests to stop special-casing registration of `download_pex_bin.py`.
Problem
One step towards a conclusion for #7790.
v2 rules currently have no way to make use of the extremely useful infrastructure we have for downloading tools hosted by ourselves or others, exposed via the
NativeTool
andScript
subclasses ofBinaryToolBase
. This requires us to hard-code the digest and url to fetch from forcloc
andpex
, e.g.:pants/src/python/pants/backend/python/rules/download_pex_bin.py
Lines 67 to 73 in fd469cb
Solution
binary_tool.py
, which exposes aBinaryToolFetchRequest
object which wraps aBinaryToolBase
instance and converts into aUrlToFetch
.default_digest
field toBinaryToolBase
, along with the--fingerprint
and--size-bytes
options, so that tools can specify the expected digest for theirdefault_version
, while giving the user the ability to set--fingerprint
and--size-bytes
if they override the--version
.BinaryToolFetchRequest
instead of hardcoding the url and digest.Result
It should be much, much easier to integrate outside tools into v2
@rule
s! The above pex@rule
can now look like: