https://github.com/jaymon/captain
command line python scripts for humans
https://github.com/jaymon/captain
cli cli-app cli-command cli-script cli-utilities cli-utility python python-script
Last synced: 3 months ago
JSON representation
command line python scripts for humans
- Host: GitHub
- URL: https://github.com/jaymon/captain
- Owner: Jaymon
- License: mit
- Created: 2014-02-07T05:48:27.000Z (over 11 years ago)
- Default Branch: master
- Last Pushed: 2024-02-24T00:26:52.000Z (over 1 year ago)
- Last Synced: 2024-04-24T20:03:03.056Z (about 1 year ago)
- Topics: cli, cli-app, cli-command, cli-script, cli-utilities, cli-utility, python, python-script
- Language: Python
- Size: 239 KB
- Stars: 13
- Watchers: 7
- Forks: 1
- Open Issues: 10
-
Metadata Files:
- Readme: README.md
- License: LICENSE.txt
Awesome Lists containing this project
README
# Captain
Easy python cli scripts for people that just want get things done.
## Usage
A valid `captain` cli script needs just two things:
1. A `Default` class that extends `captain.Command` and has a `handle()` method (can be async):
```python
from captain import Command
class Default(Command):
async def handle(self, foo, bar):
return 0
```2. Calling `captain.application()` at the end of your script:
```python
from captain import Command, application
class Default(Command):
async def handle(self, foo, bar):
return 0if __name__ == "__main__":
application()
```That's it! Whatever arguments you define in your class's `Default.handle()` method will be options on the command line. A captain script is called just like any other python command line script, so to run the above example you could do:
$ python path/to/script.py --foo=1 --bar=2
## Argument Decorator
The `captain.arg()` decorator provides a nice passthrough api to the full [argparse.ArgumentParser.add_argument() method](https://docs.python.org/3/library/argparse.html#the-add-argument-method) if you want to fine tune how arguments are passed into your script:
```python
from captain import Command, application, argclass Default(Command):
@arg('--foo', '-f', action="store_true")
@arg('arg', metavar='ARG')
async def handle(self, *args, **kwargs):
'''this is the help description'''
self.output.out(args)
self.output.out(kwargs)if __name__ == "__main__":
application()
```Would print a help string like this:
usage: script.py [-h] [--foo FOO] ARG
this is the help description
positional arguments:
ARGoptional arguments:
-h, --help show this help message and exit
--foo FOO, -f FOO## Command Output
The `captain.io.Output` class makes it easy to print stuff in your script while still giving you full control by being able to configure the logger if you need to. It also will obey the global `--quiet` flag that Captain adds to every script.
It's available in the `handle()` method by using `self.output`:
```python
from captain import Commandclass Default(Command):
async def handle(self, *args, **kwargs):
var1 = "print"var2 = "stdout"
self.output.out("this will {} to {}", var1, var2)var2 = "stderr"
self.output.err("this will {} to {}", var1, var2)e = ValueError("this will print with stacktrace and everything")
self.output.exception(e)
```The `captain.io.Output` class has a lot of nice little helper methods but Captain can also work with modules like [clint](https://github.com/kennethreitz/clint) if you need to do more advanced cli output.
## Examples
A typical python cli script
```python
import argparseif __name__ == '__main__':
parser = argparse.ArgumentParser(description='fancy script description')
parser.add_argument("--foo", action='store_true')
parser.add_argument("--bar", default=0, type=int)
parser.add_argument("args", nargs='*')
args = parser.parse_args()
sys.exit(0)
```would become:
```python
import captainclass Default(captain.Command):
async def handle(foo=False, bar=0, *args):
'''fancy script description'''
return 0if __name__ == '__main__':
captain.application()
```### Subcommands
Captain supports multiple subcommands defined in the script by naming your `captain.Command` child classes something other than `Default`:
```python
# cli.pyimport captain
class Foo(captain.Command):
async def handle(self):
passclass Bar(captain.Command):
async def handle(self):
passif __name__ == '__main__':
captain.application()
```So `foo` could be called using:
$ python cli.py foo
And `bar` could be called using:
$ python cli.py bar
### Embedding captain in another package
If you want a script from you package to be usable using both `python -m example` and maybe a `console_scripts` entry point defined in `setup.py`, you can set up your package's `__main__.py` module like this:
```python
# example/__main__.pyfrom captain import Command, application
class Default(captain.Command):
async def handle(self):
pass
if __name__ == "__main__":
application()
```And then in your `setup.py` script you can add:
```python
entry_points = {
'console_scripts': [
'example = example.__main__:application'
],
}
```That's all there is to it.
## Install
Use pip:
$ pip install captain
For latest and greatest:
$ pip install -U "git+https://github.com/Jaymon/captain#egg=captain"