Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 102 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
script-manager
==============


[![Build Status](https://scrutinizer-ci.com/g/yetone/script-manager/badges/build.png?b=master)](https://scrutinizer-ci.com/g/yetone/script-manager/build-status/master)


A command-line interface. Just a simple and crude implementation of Flask-Script.


# Examples

If you create a `test.py` file like this:

```python
from script_manager import Manager

manager = Manager('I am a command')


@manager.command
def run(host='127.0.0.1', port=8080, hehe=1):
print('Running at http://{}:{}'.format(host, port))


@manager.command
def test(name, age):
"""Just print my information

:param name: This is my name
:param age: This is my age
"""
print('My name is {}, and I have {} years old.'.format(name, age))


if __name__ == '__main__':
manager.run()
```

Then you can run command in shell:

```shell
➜ python test.py -h
usage: test.py [-h] run test

I am a command

positional arguments:
run
test Just print my information

optional arguments:
-h, --help show this help message and exit

```

and:

```shell
➜ python test.py run -h
usage: test.py [-h] [-H HOST] [-p PORT] [--hehe HEHE]

optional arguments:
-h, --help show this help message and exit
-H HOST, --host HOST
-p PORT, --port PORT
--hehe HEHE

```

and:

```shell
➜ python test.py test -h
usage: test.py [-h] name age

Just print my information

positional arguments:
name This is my name
age This is my age

optional arguments:
-h, --help show this help message and exit

```

and:

```shell
➜ python test.py run -H 0.0.0.0 -p 8888
Running at http://0.0.0.0:8888

```

and:

```shell
➜ python test.py test yetone 12
My name is yetone, and I have 12 years old.

```
7 changes: 0 additions & 7 deletions README.rst

This file was deleted.

28 changes: 24 additions & 4 deletions script_manager/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ def __init__(self, func, docstring=None):
docstring = parse_docstring(func.__doc__)
self.docstring = docstring

self.arg_parser = argparse.ArgumentParser(description=self.docstring and self.docstring.description)
self.arg_parser = argparse.ArgumentParser(
description=self.docstring and self.docstring.description
)

argspec = getargspec(func)
args = argspec.args
Expand All @@ -24,6 +26,9 @@ def __init__(self, func, docstring=None):
defaults = defaults or {}

for arg in args + list(defaults.keys()):
if arg == 'help':
raise Exception("Your arg can't named as 'help'!")

arg_kwargs = {}

if self.docstring and arg in self.docstring.params:
Expand All @@ -49,16 +54,31 @@ def __init__(self, func, docstring=None):
else:
arg_kwargs['type'] = type(default)

self.add_argument('-%s' % arg[0],
'--%s' % arg,
**arg_kwargs)
prefix_letter = arg[0]
if prefix_letter == 'h':
prefix_letter = 'H'

brief_flag = '-%s' % prefix_letter
flag = '--%s' % arg

string_actions = self.get_string_actions()

if brief_flag in string_actions:
brief_flag = None

arg_args = filter(None, (brief_flag, flag))

self.add_argument(*arg_args, **arg_kwargs)

self.func = func
self.__doc__ = func.__doc__

def add_argument(self, *args, **kwargs):
self.arg_parser.add_argument(*args, **kwargs)

def get_string_actions(self):
return self.arg_parser._option_string_actions

def run(self, *args):
_args = self.arg_parser.parse_args(args)
self.func(**_args.__dict__)
14 changes: 14 additions & 0 deletions tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ def run(command_line, manager_run):


class Test(unittest.TestCase):

@pytest.fixture(autouse=True)
def inject_fixtures(self, capsys):
self.capsys = capsys
Expand Down Expand Up @@ -162,3 +163,16 @@ def wow(a, b, c=1):
self.assertIn("I'm a", out)
self.assertIn("I'm b", out)
self.assertIn("I'm c", out)

def test_conflict_flag(self):
manager = Manager()

@manager.command
def hello(host='127.0.0.1', boy=1, bird=2):
print('hello')

run('manage.py hello -h', manager.run)
out, err = self.capsys.readouterr()
self.assertIn('-H HOST, --host HOST', out)
self.assertIn('-b BOY, --boy BOY', out)
self.assertIn('--bird BIRD', out)
6 changes: 4 additions & 2 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,7 @@ envlist = py{27,36}

[testenv]
passenv = *
deps = pytest
commands = pytest tests.py
deps =
pytest
pytest-cov
commands = pytest tests.py --cov=script_manager