-
-
Notifications
You must be signed in to change notification settings - Fork 646
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
WIP: Upgrade rule parsing to follow calls #14238
Conversation
This PR won't pass checks because I'm not bothering to get it all type-correct 😉 |
name = subsystem.options_scope.title() | ||
if subsystem.skip: | ||
return FmtResult.skip(formatter_name=name) | ||
setup = await get_setup() |
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.
Why this level of indirection for get_setup
?
Rather than run_linter_from_venv(..., get_setup=Get(ToolSetup, SetupRequest, ..))
?
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.
So why is it a callable? I just didn't think of that when I wrote it 😄
.... I mean, uh, I just wanted to demonstrate the parser parses lambdas 👀
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.
Oh, cool. :)
Hey @thejcannon : this is a really interesting direction: thank you for sketching it. I think that there is definitely room for more async-via-Gets code which is not itself
Introducing direct calls like you've done here still gets you most of the dependency injection (via I think that being able to skip memoization and avoid creating temporary dataclasses will be worthwhile in a bunch of cases (maybe not at public API boundaries?, but certainly internally) for performance and ease of use reasons, and so I'm probably on board with this. I know that it is much more challenging (maybe impossible, without explicit annotations/syntax?), but a thing that would be really, really killer would be the ability to use async class/instance methods of As a strawman, a syntax like: # On a `type[UnionBase]` class
await Summon(UnionBase, union_member_cls).class_method_of_union()
# On a `UnionBase` instance
await Summon(UnionBase, union_member_instance).instance_method_of_union() Similar to a EDIT: And I suppose that if we had this syntax, we'd want it to work for concrete types too, not just |
Hey @stuhood what do you think it would take to bring this from PoC into the repo? More tests obviously. Anything else? |
Yea, probably tests, and a pretty clear idea of the guidance that we'll put on https://www.pantsbuild.org/v2.11/docs/rules-api-concepts about when to use static functions vs
In particular, IMO: we probably shouldn't use static functions for public APIs (since none of our existing type-level documentation will work for them)... which actually means avoiding using them for the case you've demonstrated here. If But certainly there are lots of private cases that would be significantly cleaned up by calling a static function. So yea, minimal blockers here. |
For 3. it might be worth a quick check that the helper function starts with |
Another thought I had that might make this more stomachable. We could only collect info from functions decorated |
I like that a lot. At least while we experiment with this API. We can always remove the helper if we decide it's not necessary. Easier to take away than to add later. |
Just encountered a case (static function which wanted to await something) where this would have been nice to have! |
Yeah, I frequently have this thought nowadays. (Especially for the PEX code). Soon I'll pop this off my backlog |
Successor: #15025 |
This adds a file
rule_visitor.py
which exposes a functioncollect_awaitables
which is responsible for collecting the awaitables for a rule function.Here's the gist:
ast
to parse the function forCall
nodes, and handle theGet
andEffect
typesThe traversal is still pretty rudimentary, and includes guard rails. The idea is for the parser to be more permissive, but still not "perfect" or even "smart".
This PR also shows some Python tools using helpers in a helper module for exposition. There's probably a discussion to be had at where the line should be drawn between "use a normal
async
helper" and "use a newrule
". These changes are _mostly) for demonstration.One thing to note, too is that the helpers inputs don't need to be anything fancy, like hashable, which is different from rule inputs.
This came about because I want to add the # of files to the
LintResults
and didn't want to edit everywhere we create aLintResults
. If we had a helper, it'd be easy-peasy 🎉