-
Notifications
You must be signed in to change notification settings - Fork 128
How to use do_func directly?
#1400
-
I am working on an application which provides a command that runs multiple commands, something like the following:
@with_category(CMD_FABRIC_FLOW)
def do_run_FABulous_fabric(self, *ignored):
"""Generates the fabric based on the CSV file, creates bitstream specification
of the fabric, top wrapper of the fabric, Nextpnr model of the fabric and
geometry information of the fabric. Does this by calling the respective functions
'do_gen_[function]'.
"""
logger.info("Running FABulous")
self.do_gen_fabric()
self.do_gen_bitStream_spec()
self.do_gen_top_wrapper()
self.do_gen_model_npnr()
self.do_gen_geometry("")
logger.info("FABulous fabric flow complete")
return
You might notice the self.do_gen_geometry("") have the extra double quote pair there; this is because without them during the call, it will result in the following error:
File "/home/kelvin/FABulous_fork/.venv/lib/python3.12/site-packages/cmd2/decorators.py", line 345, in cmd_wrapper
cmd2_app, statement_arg = _parse_positionals(args)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/kelvin/FABulous_fork/.venv/lib/python3.12/site-packages/cmd2/decorators.py", line 95, in _parse_positionals
next_arg = args[pos + 1]
~~~~^^^^^^^^^
IndexError: tuple index out of range
The gen_gemometry command takes an optional positional argument.
This is caused by the fact that there is nothing for argparse to parse. I can work around it by doing what I have done, as this is not exposed to the user, which is fine.
However, now I would also like to expose the command to TCL and allow the user to execute TCL script. When I register a similar type of function, command with an optional positional argument, the TCL execution will fail with the same error. To make the error go away, in the TCL script will need to write gen_geometry "", which is annoying and does not look nice. I would like to know the best way to deal with this problem?
Beta Was this translation helpful? Give feedback.
All reactions
I wouldn't patch the cmd2 code unless you're willing to re-patch it every time we put out a new release.
It's easier to write your own decorator to do that.
Replies: 2 comments 3 replies
-
Your code actually exposed a bug in ours. We aren't checking the length of args properly and that's why you're getting the index out range error. You should really be seeing:
TypeError('Expected arguments: cmd: cmd2.Cmd, statement: Union[Statement, str] Not found')
Since command functions expect a str or Statement, you'll need to pass one in for us to send to argparse.
Maybe create a new decorator that adds an empy string to args if none has been passed in.
Then you would decorate your function with something like:
@allow_blank @with_argparser(...) def do_gen_geometry(self, args: argparse.Namespace): ....
Beta Was this translation helpful? Give feedback.
All reactions
-
Should I patch it so that the decorator sends an empty string when no args are given?
Beta Was this translation helpful? Give feedback.
All reactions
-
I wouldn't patch the cmd2 code unless you're willing to re-patch it every time we put out a new release.
It's easier to write your own decorator to do that.
Beta Was this translation helpful? Give feedback.
All reactions
-
Here's another option, instead of calling the do_ functions, call cmd2.onecmd_plus_hooks().
@with_category(CMD_FABRIC_FLOW)
def do_run_FABulous_fabric(self, *ignored):
"""Generates the fabric based on the CSV file, creates bitstream specification
of the fabric, top wrapper of the fabric, Nextpnr model of the fabric and
geometry information of the fabric. Does this by calling the respective functions
'do_gen_[function]'.
"""
logger.info("Running FABulous")
self.onecmd_plus_hooks("gen_fabric")
self.onecmd_plus_hooks("gen_bitStream_spec")
self.onecmd_plus_hooks("gen_top_wrapper")
self.onecmd_plus_hooks("gen_model_npnr")
self.onecmd_plus_hooks("gen_geometry")
logger.info("FABulous fabric flow complete")
return
onecmd_plus_hooks is the method used by cmd2 to parse use input, call appropriate command lifecycle hooks, and then call the specified do_ method.
I didn't try running this code, and there could be some undesirable side effects. One that immediately comes to mind is
that if you are using the command timer, you'll get the time reported for every step (gen_fabric, gen_bitStream_spec, etc) instead of for all steps combined. But it might be worth a try to experiment with this approach.
Beta Was this translation helpful? Give feedback.
All reactions
-
@KelvinChung2000 We just published version 2.5.9 of cmd2 which includes the bug fix @kmvanbrunt mentioned which might help unblock you.
Beta Was this translation helpful? Give feedback.