82 lines
3.6 KiB
Plaintext
82 lines
3.6 KiB
Plaintext
|
|
https://click.palletsprojects.com/en/7.x/#documentation
|
|
https://dbader.org/blog/mastering-click-advanced-python-command-line-apps
|
|
|
|
Use click but with the poetry cleo style of importing and structuring the commands
|
|
|
|
@click.command() - creates a command out of the function
|
|
|
|
@click.argument('name') - creates an argument for the command
|
|
(e.g poetry install, install is the argument)
|
|
|
|
@click.option - creates options for the command
|
|
pass the option flags as strings, '--option', '-o'
|
|
pass a help string , help='help string'
|
|
specify to use an os env , envvar="API_KEY"
|
|
|
|
|
|
|
|
https://click.palletsprojects.com/en/5.x/options/
|
|
|
|
- use / in an option to set a flag as true of false
|
|
|
|
setting arguments: https://click.palletsprojects.com/en/5.x/arguments/#arguments
|
|
|
|
|
|
https://github.com/pallets/click/tree/master/examples/complex/complex
|
|
for a good example on structure using click in a module
|
|
|
|
|
|
Callbacks and eager options to implement flags such as a version
|
|
https://click.palletsprojects.com/en/5.x/options/#callbacks-and-eager-options
|
|
|
|
Can use
|
|
@click.version_option(version=version)
|
|
to implement a version
|
|
|
|
|
|
|
|
Make pass decorator explained:
|
|
https://stackoverflow.com/questions/49511933/better-usage-of-make-pass-decorator-in-python-click
|
|
|
|
Show how to run command line programs from within a script from the example above ^^
|
|
|
|
|
|
For complex example:
|
|
|
|
We use the class Environment to store any base arguments passed (e.g a path)
|
|
This is optional, but is useful if we need an argument initially and want to do something to use it later in another subcommand.
|
|
|
|
This gets passed as a decorator to each command we create
|
|
|
|
We can then use this class to retrieve the inputs in each command in each module
|
|
|
|
We use this class to also handle logging, using click.echo() to print things if needed.
|
|
|
|
We avoid using the group functionality in click, by using a custom class that inherits from click.MultiCommand.
|
|
|
|
We can use this class to override the list_commands() and get_command() methods to list and do the commands we write.
|
|
|
|
Each one of those commands can go in their own folder, be decorated with the Environment class and have their commands passed
|
|
|
|
ctx refers to the instance of the class we passed in with the decorator when using click.make_pass_decorator()
|
|
|
|
when using this decorator, the first argument to the function will refer to the instanced class we passed in
|
|
|
|
|
|
we can also import defaults which we can store in a class
|
|
|
|
say we have a class that reads default values from a config file locally. it also sets default values without a config file. we store all of this in a class using properties.
|
|
|
|
when creating an option we can use this class to fall back on if the option isnt passed to the command. to do this we create a subclass of click.Option, and use 2 closures.
|
|
|
|
2 closures are needed because we pass in 2 things: the settings instance class and the value of the option itself.
|
|
|
|
this allows to use the class attributes when creating options, and also allows us access to attributes when writing the commands, without needing two seperate instances
|
|
|
|
we could avoid doing this, by following the complex example. here there is one class which is passed in, but the default aren't set in click. instead the defauts are set in a class and passed in with the decorator.
|
|
|
|
we can have a class for each command that needs it, and we set the defaults by putting a if option is None in the command/subcommand itself, and setting the value to the class value if it's not provided.
|
|
|
|
if we do it this way, we would need a class for each command that needs it, and pass it in. or we could have one class, and use the method above to do it.
|