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?
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]
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With