Skip to content

Instantly share code, notes, and snippets.

@need12648430
Last active Dec 2, 2015
Embed
What would you like to do?
Quarrel: WSGI-style routing for command line tools, in about 50 lines
import sys
from quarrel import Quarrel
@Quarrel("multiply", int, int)
@Quarrel("multiply", int)
def multiply_int(a, b = 2):
print(a * b)
@Quarrel("greet", str)
def greet(name):
print("Hello, {}!".format(name))
@Quarrel("pick", list)
def pick(selection):
import random
print(random.choice(selection))
@Quarrel(None)
@Quarrel("help")
def help():
print("Welcome to the Quarrel sample!")
print("Try:")
print("example.py multiply 5") # 10
print("example.py multiply 5 5") # 25
print("example.py greet world") # Hello, world!
print("example.py pick one two three") # one, two, or three
if __name__ == "__main__":
if not Quarrel.route(sys.argv[1:]):
print(help())
from inspect import isclass
class Quarrel(object):
routes = []
def __init__(self, *args):
for arg in args:
if not (isclass(arg) or isinstance(arg, basestring) or arg is None):
raise ValueError()
self.args = args
def __call__(self, func):
Quarrel.routes.append((self.args, func))
return func
@staticmethod
def route(args):
if len(args) == 0:
for pattern, func in Quarrel.routes:
if len(pattern) == 1 and pattern[0] is None:
func()
return True
else:
for pattern, func in Quarrel.routes:
if pattern[-1] != list and len(pattern) != len(args):
continue
match = True
func_args = []
for i, part in enumerate(pattern):
if isclass(part):
if part == bool:
func_args.append(True if args[i].lower() in ["true", "yes", "y"] else False)
elif part == list:
func_args.append(args[i:])
break
else:
try:
func_args.append(part(args[i]))
except ValueError:
match = False
break
elif isinstance(part, basestring):
if part != args[i]:
match = False
break
if match:
func(*func_args)
return True
return False
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment