Closed Laurentiu-Andronache closed 3 years ago
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.
It's very helpful, thank you.
@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()
cmd2
variant ArgumentParser with better error messages and helpfoo(args)
This is essentially the main() function which accepts the parsed arguments and encompasses all of the logic and uses the parsed argumentsThen 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:
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_pyscriptargparse
, it is helpful to create a validate_foo_args
function which is used by both the CLU and CLIUltimately, we will still need that cookiecutter that you can just install in 2 seconds. And link to it in the documentation....
I also believe that the plugin example should be a cookiecutter template as well. Ideally both templates would be linked together so that you could quickly stand up a CLI as a framework and then if needed create a bunch of plugins for it that are also separate projects.
@jayrod I don't know the first ting about cookiecutter
, but if you want to move forward with your example, I'm pretty sure others would be happy to polish it up a little. So where are cookie cutter templates typically published? As part of cookiecutter? As part of the package, e.g. cmd2
? Or are they published separately?
So where are cookie cutter templates typically published? As part of cookiecutter? As part of the package, e.g.
cmd2
? Or are they published separately?
They should be published separately on github. I imagine there might be a basic cookiecutter project and one that is a plugin project.
My cookiecutter uses a custom plugin setup that I stole from one of the other projects that used cmd2. Perhaps the best practice should be to use the cmd2-plugin project already in the repo ??
I'd recommend keeping any cookie cutter templates somewhere underneath the the python-cmd2
GitHub Organization for discoverability. I'd be fine with them being in the main repo under the plugins or in a separate repository. If anyone wants to help out, let us know and we can get you the access you need.
I'd be more than willing to start from scratch. My cookie cutter template at the moment is a bit of a mess.
So I started over and created a new cookiecutter project using the firstapp cmd2 example. As I started going down the meta project rabbit hole I can see how others might benefit from such a project. The template provides for a clean setup and install that is fairly basic.
I modeled it after the cookiecutter pypackage project and I think I'll just add it to my repo.
@Laurentiu-Andronache
I just re-worked the cookiecutter template into a new repo. My old personal template was highly suggestive of the way I like to work and probably a bit complex for a starting place. The new repo name also reflects my intention to create other similar templates. This template is simple and basic
https://github.com/jayrod/cookiecutter-python-cmd2
I would like to make another template that is linux focused and will be XDGBDS compliant. This will allow me to start off with CMD2 features like default start up alias commands. The above repo is super super early in development but I am open for all issue requests and suggestions.
Whenever you are happy with your template(s), please submit a PR that adds info on how to use them to the README and/or Sphinx docs.
The project is actually at a decent place at the moment. I'd love some feedback on how far to go with it. It is a stripped down example of how to create a package around the basic_cmd2 example. I'm not sure exactly how to incorporate testing into it but I'd welcome some insights there.
I plan to add nox testing and bumpversion to the template as well but those items seem less worrisome.
What is a CR btw??
Ah sorry about the confusion. CR == Code Review, which in my mind is equivalent to a PR == Pull Request. To me, the two terms are synonymous. I think CR is a better term because it is more descriptive of the overall process. However, I try to stick with PR on GitHub to avoid confusion. But every now and then I slip up.
I'll take a look at your cookiecutter project sometime this weekend.
@jayrod I tried running the cookie cutter template and got a crash due to an unhandled exception. I created an issue for it: https://github.com/jayrod/cookiecutter-python-cmd2/issues/11
@jayrod After you pushed the doc instruction fix, I was able to create a basic cmd2
application using it. From taking a quick look, the code it generates looks OK to me. I'll experiment with it more later.
@tleonhardt I polished it up today as well. I removed the isort dependency from the cookiecutter generation process and instead added it to the generated application. I also updated the Readme documentation with an ascii cinema walkthrough and finally (what I'm a bit happy with) is that I added a functional test case that works with pytest using the cmd2_ext_test plugin.
So you can use the cookiecutter template to quickly create a cmd2 application based on one of three examples and hit the ground runnings.
I think there are some smaller issues to work out with the documentation and I could perhaps go further and make it easy to deploy the app using a makefile or something but for the most part it's good to go.
I appreciate you taking a look at it.
I got a little crazy and created a new template based on my plugin needs.
https://github.com/jayrod/cookiecutter-python-cmd2-ext-plug
It creates a base application that's ready to install and a sample plugin that's also installed in a separate package. It uses pluginlib to tie the two together via dynamic CommandSets.
I'm really happy with how it turned out and just how easy CMD2 made it.
@Laurentiu-Andronache Can you please take a look at the cookiecutter templates that @jayrod has created?
I think these satisfy the request in this issue. But I would like some confirmation if possible.
@jayrod I love that you made the advanced cookiecutter example that also creates a plugin and uses dynamic CommandSets!
@jayrod I love that you made the advanced cookiecutter example that also creates a plugin and uses dynamic CommandSets!
Thanks, I also just added a second type of plugins that allows for Settables from afar as well. So you can define a CommandSet AND Settables to go along with them.
Since there are now two nice cookiecutter templates and links to them from the README, I'm going to close this issue.
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?