Last active
August 29, 2015 13:56
-
-
Save mpkocher/9073529 to your computer and use it in GitHub Desktop.
Commandline Subparser with Validation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import sys | |
import argparse | |
import logging | |
__version__ = '0.1' | |
log = logging.getLogger(__name__) | |
def adder(a, b): | |
"""Mock lib code that should be imported via mypackage.awesome.""" | |
print a + b | |
def divider(a, b): | |
"""Mock lib code that should be imported.""" | |
print a / float(b) | |
return 0 | |
def _validate_number(v): | |
"""Validating function for int and floats""" | |
try: | |
n = int(v) | |
return n | |
except ValueError: | |
n = float(v) | |
return n | |
def _validate_non_zero_number(n): | |
n = _validate_number(n) | |
if n != 0: | |
return n | |
else: | |
raise ValueError("Unable to divide by zero.") | |
def _adder(args): | |
""" | |
Simple wrapping layer to not mix the argparsing IO layer into the lib | |
code. The lib code should always be importable. | |
""" | |
adder(args.a, args.b) | |
return 0 | |
def _divider(args): | |
divider(args.a, args.b) | |
return 0 | |
def get_parser(): | |
"""Returns an argparser.ArgumentParser instance that uses subparsers""" | |
parser = argparse.ArgumentParser(description='Simple example', | |
version=__version__) | |
sp = parser.add_subparsers(help='commands') | |
add_p = sp.add_parser('add', help="Add two numbers") | |
add_p.add_argument('a', type=_validate_number, help="A number") | |
add_p.add_argument('b', type=_validate_number, help='A number') | |
add_p.set_defaults(func=_adder) | |
div_p = sp.add_parser('divide', help="Divide two numbers") | |
div_p.add_argument('a', type=_validate_number, help="A number") | |
div_p.add_argument('b', type=_validate_non_zero_number, help="A non-zero number") | |
div_p.set_defaults(func=_divider) | |
return parser | |
def main(args_list): | |
"""Main point of entry""" | |
p = get_parser() | |
args = p.parse_args(args_list) | |
rcode = args.func(args) | |
return rcode | |
if __name__ == '__main__': | |
sys.exit(main(sys.argv[1:])) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import logging | |
import unittest | |
import shlex | |
import example_validation_subparsers | |
log = logging.getLogger(__name__) | |
def _split(raw_args): | |
"""Split and log the results""" | |
args_list = shlex.split(raw_args) | |
log.debug("raw args '{r}' to arg list {a}".format(a=args_list, r=raw_args)) | |
return args_list | |
class TestAdderMain(unittest.TestCase): | |
def test_basic(self): | |
raw_args = 'add 1 2.0' | |
args_list = _split(raw_args) | |
rcode = example_subparsers.main(args_list) | |
self.assertEqual(rcode, 0) | |
class TestDivideMain(unittest.TestCase): | |
def test_basic(self): | |
raw_args = 'divide 1 2.0' | |
args_list = _split(raw_args) | |
rcode = example_subparsers.main(args_list) | |
self.assertEqual(rcode, 0) | |
def test_divide_by_zero(self): | |
raw_args = 'divide 1 0' | |
args_list = _split(raw_args) | |
with self.assertRaises(SystemExit) as e: | |
log.info(e) | |
example_subparsers.main(args_list) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment