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

[Call-by-name] Replaced ast with libcst in migration code #21089

Merged
merged 11 commits into from
Jun 25, 2024

Conversation

sureshjoshi
Copy link
Member

@sureshjoshi sureshjoshi commented Jun 19, 2024

This PR addresses several ast-centric implementation problems. Using a concrete syntax tree allows us to do fancier migrations, and not have to write code to handle silly things like trailing commas or nested comments.

High level, libcst is amazing. All of the most complex code in the migration was replaced by a better transformer.

  • Gets with comments within parameter/args are now permitted (we might run into hiccups, but the hiccups are now related to implementation - not the entire concept of using an ast)
  • Having multiple Gets on the same line in a MultiGet no longer wipes out the latter Gets (Closes [Call-by-name]: Migration does not handle multiple MultiGet in the same line #21066)
  • Started on smarter implicitly usage (closes [Call-by-name] Handle implicitly cases better #21072) - for example, functions that take no arguments no longer have an implicitly attached
  • Gets within rule_helpers (or, now, just non-rule-decorated async functions) CAN BE correctly transformed (right now, the rule engine itself doesn't seem to pick these up)

The implicitly work done in this PR will eventually get pulled out into a custom linter/type-checker, as outside of this migration - we'll want to flag when users add new code with unnecessary implicitly usage.

Closes #21040

@sureshjoshi sureshjoshi added category:internal CI, fixes for not-yet-released features, etc. release-notes:not-required PR doesn't require mention in release notes labels Jun 19, 2024
@sureshjoshi sureshjoshi marked this pull request as ready for review June 20, 2024 15:35
@sureshjoshi
Copy link
Member Author

sureshjoshi commented Jun 20, 2024

In subsequent PRs (or, as part of subsequent migrations), I'll add some more implicitly rules and clean up some of the code. This is a visually a big change, that I didn't want to get much bigger.

Overall, less code, more functionality

Copy link
Member

@cognifloyd cognifloyd left a comment

Choose a reason for hiding this comment

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

I read through it, but my understanding of the call by name conversion is superficial, so someone else needs to review this in more depth. From what I can tell, LGTM.

@sureshjoshi
Copy link
Member Author

I read through it, but my understanding of the call by name conversion is superficial, so someone else needs to review this in more depth. From what I can tell, LGTM.

FWIW the end result should be "same as before, except with some bugs fixed". Most of the re-factoring was what was required to switch from AST to libcst. The only "novelty" was one implicitly optimization (removed when the called function requires args)

@@ -167,115 +176,6 @@ def _create_migration_plan(

return sorted(items, key=lambda x: (x["filepath"], x["function"]))

def _create_replacements_for_file(
Copy link
Member Author

Choose a reason for hiding this comment

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

Not needed, handled by libcst transformer

logging.error(f"TokenError in {file}: {e}")
return []

def _perform_replacements_on_file(self, file: Path, replacements: list[Replacement]):
Copy link
Member Author

Choose a reason for hiding this comment

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

Not needed, handled by libcst transformer


def contains_comments(self, source_code: str) -> bool:
Copy link
Member Author

Choose a reason for hiding this comment

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

Not needed, handled by libcst. ast wipes out comments by default, cst keeps them

@@ -9,6 +9,7 @@ chevron==0.14.0
fasteners==0.16.3
freezegun==1.2.1
ijson==3.2.3
libcst==1.4.0
Copy link
Member

Choose a reason for hiding this comment

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

do we want to guard this from leaking into pants runtime (beyond the migration code)?

__dependents_rules__(
( # Only the explorer server may depend on these libraries
(
"[fastapi]",
"[starlette]",
"[strawberry-graphql]",
"[uvicorn]",
),
"pants-plugins/pants_explorer/server/**",
"!*",
),
# Free for all on the rest
("*", "*"),
)

Copy link
Member

Choose a reason for hiding this comment

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

I think libcst is an excellent utility for migrations, of which this will not be the last. Allowing broader use of it seems like a plus to me. So I don't think we should restrict this dependency with dependency visibility rules.

Copy link
Member

Choose a reason for hiding this comment

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

I was feeling this could be useful as well, raised the question to get a conscious decision for it though, as there's been an on-going effort to reduce the number of 3rd party dependencies (albeit controversial at times) in #19282, so it would be good to have a clear record on the motivation for each dependency and it's intended use, I think.

@sureshjoshi sureshjoshi merged commit ecf0a7f into pantsbuild:main Jun 25, 2024
25 checks passed
@sureshjoshi sureshjoshi deleted the call-by-name-implicitly branch June 25, 2024 12:01
@sureshjoshi
Copy link
Member Author

Pulling these from source comments to main:

do we want to guard this from leaking into pants runtime (beyond the migration code)?

I think libcst is an excellent utility for migrations, of which this will not be the last. Allowing broader use of it seems like a plus to me. So I don't think we should restrict this dependency with dependency visibility rules.

I agree :)

so it would be good to have a clear record on the motivation for each dependency and it's intended use

I also agree :)

The motivation here is that libcst will be used in some implicitly checks and in the upcoming migrate goal I'm writing (or migrate fix-er`), so it'll end up in source code regardless.

I agree, overall, that we would like to reduce dependencies - or visibility them out.

I wonder if pex's new PEP723 support (or __visibility__) will help for those places where we have one-off build files, if they're not already hidden away from the rest of the code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
category:internal CI, fixes for not-yet-released features, etc. release-notes:not-required PR doesn't require mention in release notes
Projects
None yet
3 participants