Jaymon / captain

command line python scripts for humans
MIT License
13 stars 1 forks source link

Set values onto the Command instance #66

Closed Jaymon closed 2 months ago

Jaymon commented 3 years ago

Add an @arg flag that would set the value onto the class instance instead of passing it to the handle method, something like:

# command.py
class Default(Command):
    @arg("--foo", instance=True)
    def handle(self):
        self.output.out("Foo: {}", self.foo)
$ python command.py --foo=5
Foo: 5
Jaymon commented 1 year ago

I have hooks into how this could work, it would happen in parse.ArgumentParser.parse_handle_args. You can take a look at how that method sets parsed onto the Command instance to see how this would work.

Basically, you would need parse.ArgumentParser.add_handler to find all the instance arguments the same way it does it for the group functionality. Then you would modify parse_handle_args to find those arguments and add them to the Command instance and strip them from the *args and **kwargs that are returned

Jaymon commented 2 months ago

I think there is a better way to handle this that goes along with https://github.com/Jaymon/captain/issues/86, basically doing something like this:

from captain import Command, Argument

class Default(Command):

    foo = Argument("--foo", "-f", required=True)
    bar = Argument("--bar", "-b", action="store_true")

    def handle(self):
        self.output.out("foo: {}, bar: {}", self.foo, self.bar)

Then the parser would check the command class and find all the Argument class properties and add those to the parser that it creates, so this would be completely valid:

$ python <SCRIPT> --foo=1 --bar
foo: 1, bar: True
$ python <SCRIPT> --foo=2
foo: 2, bar: False

This would also have the effect of being able to define arguments on a parent class and have the child class easily inherit those also which makes customization and expansion easily, for example, if you have a group of commands that all need host and port you can create a parent command that defines those and then all the child commands will inherit those arguments.

You could also have them be passed into the handle method, so this would also be valid:

from captain import Command, Argument

class Default(Command):

    foo = Argument("--foo", "-f", required=True)
    bar = Argument("--bar", "-b", action="store_true")

    def handle(self, foo):
        self.output.out("foo: {}, bar: {}", foo, self.bar)