Skip to content

Commit

Permalink
Initial work toward supporting configurable input data formats, as we…
Browse files Browse the repository at this point in the history
…ll as only injecting on request
  • Loading branch information
timothycrosley committed Aug 10, 2015
1 parent a119c9f commit 08406ed
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 16 deletions.
5 changes: 2 additions & 3 deletions hug/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,10 @@
OTHER DEALINGS IN THE SOFTWARE.
"""
from hug import documentation, input_format, output_format, run, test, types, defaults
from hug import documentation, input_format, output_format, run, test, types, defaults, format
from hug._version import current
from hug.decorators import call, connect, delete, get, head, options, patch, post, put, trace, default_output_format

__version__ = current
__all__ = ['run', 'types', 'test', 'input_format', 'output_format', 'documentation', 'call', 'delete', 'get', 'post',
'put', 'options', 'connect', 'head', 'patch', 'trace', 'terminal', 'output_format', '__version__',
'defaults']
'put', 'options', 'connect', 'head', 'patch', 'trace', 'terminal', 'format', '__version__', 'defaults']
35 changes: 29 additions & 6 deletions hug/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

class HugAPI(object):
'''Stores the information necessary to expose API calls within this module externally'''
__slots__ = ('versions', 'routes', '_output_format')
__slots__ = ('versions', 'routes', '_output_format', '_input_format')

def __init__(self):
self.versions = set()
Expand All @@ -26,6 +26,14 @@ def output_format(self):
def output_format(self, formatter):
self._output_format = formatter

def input_format(self, content_type):
return getattr(self, '_input_format', {}).get(content_type, hug.defaults.input_format.get(content_type, None))

def set_input_format(self, conent_type, handler):
if not getattr(self, '_output_format'):
self._output_format = {}
self.output_format['content_type'] = handler


def default_output_format(content_type='application/json'):
"""A decorator that allows you to override the default output format for an API"""
Expand All @@ -37,7 +45,17 @@ def decorator(formatter):
return decorator


def call(urls=None, accept=HTTP_METHODS, output=None, examples=(), versions=None, stream_body=False):
def default_input_format(content_type='application/json'):
"""A decorator that allows you to override the default output format for an API"""
def decorator(formatter):
module = sys.modules[formatter.__module__]
formatter = hug.output_format.content_type(content_type)(formatter)
module.__hug__.set_input_format(content_type, formatter)
return formatter
return decorator


def call(urls=None, accept=HTTP_METHODS, output=None, examples=(), versions=None, parse_body=True):
urls = (urls, ) if isinstance(urls, str) else urls
examples = (examples, ) if isinstance(examples, str) else examples
versions = (versions, ) if isinstance(versions, (int, float, None.__class__)) else versions
Expand Down Expand Up @@ -66,9 +84,11 @@ def interface(request, response, **kwargs):
response.content_type = function_output.content_type
input_parameters = kwargs
input_parameters.update(request.params)
if request.content_type == "application/json" and not stream_body:
body = json.loads(request.stream.read().decode('utf8'))
input_parameters.setdefault('body', body)
body_formatting_handler = parse_body and module.__hug__.input_format(request.content_type)
if body_formatting_handler:
body = body_formatting_handler(request.stream.read().decode('utf8'))
if 'body' in accepted_parameters:
input_parameters['body'] = body
if isinstance(body, dict):
input_parameters.update(body)

Expand All @@ -80,7 +100,10 @@ def interface(request, response, **kwargs):
except Exception as error:
errors[key] = str(error)

input_parameters['request'], input_parameters['response'] = (request, response)
if 'request' in accepted_parameters:
input_parameters['request'] = request
if 'response' in accepted_parameters:
input_parameters['response'] = response
for require in required:
if not require in input_parameters:
errors[require] = "Required parameter not supplied"
Expand Down
1 change: 1 addition & 0 deletions hug/defaults.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import hug

output_format = hug.output_format.json
input_format = {'application/json': hug.input_format.json}
2 changes: 2 additions & 0 deletions hug/input_format.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import json as json_converter
from hug.format import content_type
import re

UNDERSCORE = (re.compile('(.)([A-Z][a-z]+)'), re.compile('([a-z0-9])([A-Z])'))


@content_type('application/json')
def json(body):
return json_converter.loads(body)

Expand Down
8 changes: 1 addition & 7 deletions hug/output_format.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
import json as json_converter
from datetime import date, datetime


def content_type(content_type):
def decorator(method):
method.content_type = content_type
return method
return decorator
from hug.format import content_type


def _json_converter(item):
Expand Down

0 comments on commit 08406ed

Please sign in to comment.