Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

How to use do_func directly? #1400

Answered by kmvanbrunt
KelvinChung2000 asked this question in Q&A
Discussion options

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?

You must be logged in to vote

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

Comment options

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):
 ....
You must be logged in to vote
3 replies
Comment options

Should I patch it so that the decorator sends an empty string when no args are given?

Comment options

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.

Answer selected by KelvinChung2000
Comment options

kotfu Jan 8, 2025
Maintainer

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.

Comment options

@KelvinChung2000 We just published version 2.5.9 of cmd2 which includes the bug fix @kmvanbrunt mentioned which might help unblock you.

You must be logged in to vote
0 replies
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

AltStyle によって変換されたページ (->オリジナル) /