Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple non-flagged arguments with cement

I am writing a python command line interface tool on top of cement. Cement is working quite well for standard argument parseing. However, I want to be able to add a specific amount of non-flagged arguments. Let me explain.

Typical command line tool:

cmd subcmd -flag -stored=flag

Now, lets say I want to add some arguments without flags, for example how cd works

cd my/dir

my/dir is an argument without a flag.

Is there anyway to do this with cement?

My current example cement app:

# define application controllers
class MyAppBaseController(controller.CementBaseController):
    class Meta:
        label = 'base'
        interface = controller.IController
        description = "My Application Does Amazing Things"
        arguments = [
            (['--base-opt'], dict(help="option under base controller")),
            ]

    @controller.expose(help="base controller default command", hide=True)
    def default(self):
        self.app.args.parse_args(['--help'])
        print "Inside MyAppBaseController.default()"

    @controller.expose(help="another base controller command")
    def command1(self):
        print "Inside MyAppBaseController.command1()"

So lets say I wanted to do myapp command1 some/dir some_string

is there a way to parse those arguments?

like image 913
Nick Humrich Avatar asked Jun 24 '14 20:06

Nick Humrich


2 Answers

You can do this using optional positional arguments in ArgParse. There is actually an issue open in GitHub for better documentation on this subject:

https://github.com/datafolklabs/cement/issues/256

Basically, if you want "command1" to handle the operation, then "some/dir some_string" would be positional arguments. You could add the following to MyAppBaseController.Meta.arguments:

( ['extra_arguments'], dict(action='store', nargs='*') ),

And then access those arguments like this inside of the command function:

if self.app.pargs.extra_arguments: print "Extra Argument 0: %s" % self.app.pargs.extra_arguments[0] print "Extra Argument 1: %s" % self.app.pargs.extra_arguments[1]

like image 133
derks Avatar answered Nov 12 '22 03:11

derks


As said in the Cement doc: "Cement defines an argument interface called IArgument, as well as the default ArgParseArgumentHandler that implements the interface. This handler is built on top of the ArgParse module which is included in the Python standard library"

You could achieve this by telling the argparse module to consume one argument from the arguments list an store it in the name attribute of the pargs list.

# define application controllers
class MyAppBaseController(controller.CementBaseController):
    class Meta:
        label = 'base'
        interface = controller.IController
        description = "My Application Does Amazing Things"
        arguments = [
            (['--base-opt'], dict(help="option under base controller")),
        ]

    @controller.expose(help="base controller default command", hide=True)
    def default(self):
        self.app.args.parse_args(['--help'])
        print "Inside MyAppBaseController.default()"

    @controller.expose(
        help="another base controller command",
        arguments=[
            (['path'],
             dict(type=str, metavar='PATH', nargs='?', action='store', default='.')),
            (['string'],
             dict(type=str, metavar='STRING', nargs='?', action='store', default='')),
        ]
    )
    def command1(self):
        print "Inside MyAppBaseController.command1() path: %s string: %s" % (self.app.pargs.name, self.app.pargs.string)
like image 22
secci Avatar answered Nov 12 '22 03:11

secci