★ wanayoo — archive 1999 https://github.com/python-cmd2/cmd2/issues/940Nouvelle recherche | Portail wanayoo
Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

is there any scaffolding already done for this (for example with cookiecutter)? #940

Open
Laurentiu-Andronache opened this issue May 24, 2020 · 4 comments

Comments

@Laurentiu-Andronache
Copy link

@Laurentiu-Andronache Laurentiu-Andronache commented May 24, 2020

I'm looking to build a package that's simultaneously a library, a CLI and a CLU. cmd2 seems perfect for the task, but I'd love to use some already existing scaffolding that has proper organization and proper code quality standards. Is there such a thing?

@kotfu
Copy link
Member

@kotfu kotfu commented May 25, 2020

We don't have any scaffolding or templates yet, although I think we should keep this issue open as the vehicle to create one. However, I have another project called tomcatmanager which offers a python library, a CLU, and a CLI using cmd2. It might give you some ideas about how to construct your application.

One note about the design of tomcatmanager. To avoid duplication of code logic, commands given on the command line (CLU mode) are just passed through to the CLI. There are two key classes, one is the library, the other is the cmd2 subclass which is the interactive CLI.

When operating as a CLU, you have to strip off the command line arguments and pass them into the cmd2 based CLI interpreter, and then get the exit codes back out so you get useful exit codes in the shell. This design has many benefits (command syntax is always the same in CLU and CLI, no duplication of code, etc), but it's a little tricky to make work exactly right as a CLU.

I advise taking a look at main.py to see how that works. The two key elements are argparse.REMAINDER, and onecmd_plus_hooks(). You will also need to set up entry_points in setup.py.

Hope this is helpful.

@Laurentiu-Andronache
Copy link
Author

@Laurentiu-Andronache Laurentiu-Andronache commented May 25, 2020

It's very helpful, thank you.

@tleonhardt
Copy link
Member

@tleonhardt tleonhardt commented Jun 2, 2020

@Laurentiu-Andronache Your question is a good one and it makes me thing that we should probably work on adding some documentation about overall application patterns and recommended best-practices for using cmd2.

I recently helped some coworkers setup a package that is essentially exactly what you are talking about - a library, a CLI and a CLU and we followed a very different overall architectural pattern than @kotfu followed for tomcatmanager. In our case we had a bunch of pre-existing legacy CLU scripts which used argparse for parsing command-line arguments and we wanted to tie everything together into an interactive CLI for convenience of distribution and discoverability.

First we did some mild refactoring of the existing CLU scripts so that there were functions like the following for a script foo:

  • get_foo_parser()
    • Modified to return a cmd2 variant ArgumentParser with better error messages and help
  • foo(args)
    This is essentially the main() function which accepts the parsed arguments and encompasses all of the logic and uses the parsed arguments
  • A "main" block
    • Calls the function to get the parser, parses the arguments, and then calls the main function

Then we added a super thin do_foo() method to the CLI which uses the cmd2 argparse decorator and get_foo_parser() to setup the parsing and inside just calls foo(args).

NOTE: If we were writing all of the code from scratch and didn't already have the existing CLU scripts, then I think the approach @kotfu outlined above is probably a better one.

For the library we kept that in a separate package and then had a combined package for the CLI/CLU.

Some overall lessons learned regarding best practices:

  • Always have your do_foo commands set self.last_result
    • cmd2 doesn't require this, but it makes unit testing your code a hell of a lot easier and also makes it more convenient to use `run_pyscript
  • If there is any additional argument validation in addition to that done by argparse, it is helpful to create a validate_foo_args function which is used by both the CLU and CLI
@Laurentiu-Andronache
Copy link
Author

@Laurentiu-Andronache Laurentiu-Andronache commented Jun 2, 2020

Ultimately, we will still need that cookiecutter that you can just install in 2 seconds. And link to it in the documentation....

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
3 participants
You can’t perform that action at this time.