-
-
Notifications
You must be signed in to change notification settings - Fork 545
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(refactoring): Introduce a Python CLI app layout #738
chore(refactoring): Introduce a Python CLI app layout #738
Conversation
Cool. Thanks. Too much of Python'ish stuff for me 🤣
Could you please drop a README.md file with the above info into the directory with these files for future reference? Thank you. |
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 there so much boilerplate -_-
from .terraform_docs_replace import ( | ||
populate_argument_parser as populate_replace_docs_argument_parser, | ||
) | ||
|
||
|
||
PARSER_MAP = { | ||
'replace-docs': populate_replace_docs_argument_parser, | ||
} |
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 I will need to add here all python hooks?
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.
And how it should work with common.py
?
I don't understand how I will use it with
args, hook_config, files, _tf_init_args, env_vars_strs = common.parse_cmdline(argv) |
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, this mapping is for parsers, and another file has a mapping for callables with the logic.
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 don't understand how I will use it with
You won't need to call common.parse_cmdline(argv)
manually in several places anymore. It'll be called for you, and you'll get the result of a parse_args()
invocation into a function you'll define to accept an argparse.Namespace
instance.
Why you used Sorry, but I have no idea how to reuse half of code implemented here with actual hooks |
Because it is a working example of implementing custom check subcommands until you add new ones. You can swap it out for new things later.
Hence, the example integration of the only existing thing. I'll drop the instructions into a readme as suggested. |
I've added a document. While doing that, I realized that I can simplify the new subcommand integration a bit, so I've marked this as a draft until I do that. |
Pretty nice and clear ❤️ |
cdf5b6e
to
3af52a9
Compare
@yermulnik @MaxymVlasov this is now mergeable, but #734 should go in first to unblock the CI. |
pre-commit.ci run |
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.
LGTM. Though since @MaxymVlasov is mainly the only one who develops code at this moment I'm deferring final decision to him.
This includes a structure with purpose-based modules and a standard mechanism for adding more subcommands. When adding a new subcommand, one has to wire the `invoke_cli_app()` and `populate_argument_parser()` from their new module into the mappings defined in `_cli_subcommands.py` and `_cli_parsing.py` respectively. This is the only integration point necessary. `populate_argument_parser()` accepts a subparser instance of `argparse.ArgumentParser()` that a new subcommand would need to attach new arguments into. It does not need to return anything. And the `invoke_cli_app()` hook is called with an instance of `argparse.Namespace()` with all the arguments parsed and pre-processed. This function is supposed to have the main check logic and return an instance of `._structs.ReturnCode()` or `int`.
Previously, adding a new subcommand required importing it into two separate Python modules, adding them into two mappings, maintaining the same dictionary key string. This is prone to human error and is underintegrated. This patch makes it easier by defining a required subcommand module shape on the typing level. Now, one just need to implement two hook- functions and a constant with specific signatures and import it in a single place.
1c12549
to
52cf580
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.
Let's hope that I'll understand all later :)
IT somehow works with new hooks, but need some polishing, which will be done in other PRs
This PR is included in version 1.97.0 🎉 |
This includes a structure with purpose-based modules and a standard mechanism for adding more subcommands.
When adding a new subcommand, one has to define the
invoke_cli_app()
andpopulate_argument_parser()
hooks in their new module together with aCLI_SUBCOMMAND_NAME
string constant. I can then be wired into the framework via_cli_subcommands.py
. This is the only integration point necessary.populate_argument_parser()
accepts a subparser instance ofargparse.ArgumentParser()
that a new subcommand would need to attach new arguments into. It does not need to return anything. And theinvoke_cli_app()
hook is called with an instance ofargparse.Namespace()
with all the arguments parsed and pre-processed. This function is supposed to have the main check logic and return an instance of._structs.ReturnCode()
orint
.CLI_SUBCOMMAND_NAME
needs to be annotated as aFinal[str]
.pre-commit
integration is done through the runpy interface:python -m pre_commit_terraform <subcommand>
.The import package folder also contains a more detailed maintenance manual: https://github.com/antonbabenko/pre-commit-terraform/tree/8e77580805322e5d264a2667b4f4cba53e8bf94c/src/pre_commit_terraform#readme.
Put an
x
into the box if that apply:Description of your changes
I think the most important details are in the commit messages. Everything that is unlikely to change much over time is in "_private" modules.
How can we test changes
Something like
python -Im pip install -e . && python -Im pre_commit_terraform replace-docs
. Or invoke it via pre-commit.