Skip to content

Commit

Permalink
Fully working cli support for objects
Browse files Browse the repository at this point in the history
  • Loading branch information
timothycrosley committed Sep 22, 2016
1 parent 34d8c46 commit dc74ba6
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 28 deletions.
2 changes: 1 addition & 1 deletion hug/__init__.py
Expand Up @@ -40,7 +40,7 @@
from hug.decorators import (default_input_format, default_output_format, directive, extend_api,
middleware_class, request_middleware, response_middleware, startup, wraps)
from hug.route import (call, cli, connect, delete, exception, get, get_post, head, http, local,
not_found, object, cli_object, options, patch, post, put, sink, static, trace)
not_found, object, options, patch, post, put, sink, static, trace)
from hug.types import create as type

from hug import development_runner # isort:skip
Expand Down
28 changes: 16 additions & 12 deletions hug/route.py
Expand Up @@ -42,7 +42,10 @@ class Object(http):
def __init__(self, urls=None, accept=HTTP_METHODS, output=None, **kwargs):
super().__init__(urls=urls, accept=accept, output=output, **kwargs)

def __call__(self, method_or_class):
def __call__(self, method_or_class=None, **kwargs):
if not method_or_class and kwargs:
return self.where(**kwargs)

if isinstance(method_or_class, (MethodType, FunctionType)):
routes = getattr(method_or_class, '_hug_http_routes', [])
routes.append(self.route)
Expand All @@ -56,13 +59,13 @@ def __call__(self, method_or_class):
for argument in dir(instance):
argument = getattr(instance, argument, None)

http_routes = getattr(handler, '_hug_http_routes', ())
http_routes = getattr(argument, '_hug_http_routes', ())
for route in http_routes:
http(**router.accept(method).where(**route).route)(handler)
http(**self.where(**route).route)(argument)

cli_routes = getattr(argument, '_hug_cli_routes', ())
for route in cli_routes:
cli(**router.accept(method).where(**route).route)(handler)
cli(**self.where(**route).route)(argument)

return method_or_class

Expand All @@ -78,23 +81,25 @@ def decorator(class_definition):
handler = getattr(instance, method.lower(), None)
if handler:
http_routes = getattr(handler, '_hug_http_routes', ())
cli_routes = getattr(argument, '_hug_cli_routes', ())
if http_routes or cli_routes:
if http_routes:
for route in http_routes:
http(**router.accept(method).where(**route).route)(handler)
for route in cli_routes:
cli(**router.accept(method).where(**route).route)(handler)
else:
http(**router.accept(method).route)(handler)

cli_routes = getattr(handler, '_hug_cli_routes', ())
if cli_routes:
for route in cli_routes:
cli(**self.where(**route).route)(handler)
return class_definition
return decorator

def cli(self, method):
"""Registers a method on an Object as a CLI route"""
routes = getattr(method_or_class, '_hug_cli_routes', [])
routes = getattr(method, '_hug_cli_routes', [])
routes.append(self.route)
method_or_class._hug_cli_routes = routes
return method_or_class
method._hug_cli_routes = routes
return method


class API(object):
Expand Down Expand Up @@ -227,7 +232,6 @@ def put_post(self, *kargs, **kwargs):
put_post.__doc__ = "Exposes a Python method externally under both the HTTP POST and PUT methods"

object = Object()
cli_object = CLIObject

# DEPRECATED: for backwords compatibility with hug 1.x.x
call = http
44 changes: 29 additions & 15 deletions tests/test_route.py
Expand Up @@ -73,25 +73,39 @@ def post(self):
assert hug.test.post(api, 'home').data == 'bye'


class TestCLIObject(object):
"""A set of tests to ensure CLI class based routing works as intended"""
def test_routing_class_with_cli_commands():
"""Basic operation test"""
@hug.object(name='git', version='1.0.0')
class GIT(object):
"""An example of command like calls via an Object"""

def test_commands(self):
"""Basic operation test"""
@hug.object(name='git', version='1.0.0')
class GIT(object):
"""An example of command like calls via an Object"""
@hug.object.cli
def push(self, branch='master'):
return 'Pushing {}'.format(branch)

@hug.object.cli
def push(self, branch='master'):
return 'Pushing {}'.format(branch)
@hug.object.cli
def pull(self, branch='master'):
return 'Pulling {}'.format(branch)

@hug.object.cli
def pull(self, branch='master'):
return 'Pulling {}'.format(branch)
assert 'token' in hug.test.cli(GIT.push, branch='token')
assert 'another token' in hug.test.cli(GIT.pull, branch='another token')

assert 'token' in hug.test.cli(GIT.push, branch='token')
assert 'another token' in hug.test.cli(GIT.pull, branch='another token')

def test_routing_class_based_method_view_with_cli_routing():
"""Test creating class based routers using method mappings exposing cli endpoints"""
@hug.object.http_methods()
class EndPoint(object):

@hug.object.cli
def get(self):
return 'hi there!'

def post(self):
return 'bye'

assert hug.test.get(api, 'endpoint').data == 'hi there!'
assert hug.test.post(api, 'endpoint').data == 'bye'
assert hug.test.cli(EndPoint.get) == 'hi there!'


def test_routing_instance():
Expand Down

0 comments on commit dc74ba6

Please sign in to comment.