Skip to content

Commit

Permalink
Merge pull request #102 from timothycrosley/feature/automatic-file-ou…
Browse files Browse the repository at this point in the history
…tput-support

Feature/automatic file output support
  • Loading branch information
timothycrosley committed Nov 11, 2015
2 parents 27264d4 + 9a024b3 commit bbc0f05
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 8 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,4 @@ Changelog
- Input formatting functions now need to be responsible for dealing with text encoding and streaming
- Added additional default input format for `text/plain` and a few other common text based formats
- If no input format is available, but the body parameter is requested - the body stream is now returned
- Added support for a generic `file` output formatter that automatically determines the content type for the file
18 changes: 18 additions & 0 deletions hug/output_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@
"""
import json as json_converter
import mimetypes
import os
from datetime import date, datetime
from io import BytesIO

from falcon import HTTP_NOT_FOUND
from hug.format import camelcase, content_type

IMAGE_TYPES = ('png', 'jpg', 'bmp', 'eps', 'gif', 'im', 'jpeg', 'msp', 'pcx', 'ppm', 'spider', 'tiff', 'webp', 'xbm',
Expand Down Expand Up @@ -144,3 +146,19 @@ def video_handler(data):

for (video_type, video_mime) in VIDEO_TYPES:
globals()['{0}_video'.format(video_type)] = video(video_type, video_mime)


@content_type('file/dynamic')
def file(data, response):
'''A dynamically retrieved file'''
if hasattr(data, 'read'):
name, data = getattr(data, 'name', ''), data
elif os.path.isfile(data):
name, data = data, open(data, 'rb')
else:
response.content_type = 'text/plain'
response.status = HTTP_NOT_FOUND
return 'File not found!'

response.content_type = mimetypes.guess_type(name, None)[0]
return data
30 changes: 22 additions & 8 deletions tests/test_output_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def test_html():
hug.output_format.html("<html>Hello World!</html>") == "<html>Hello World!</html>"
hug.output_format.html(str(1)) == "1"
with open('README.md', 'rb') as html_file:
hasattr(hug.output_format.html(html_file), 'read')
assert hasattr(hug.output_format.html(html_file), 'read')


def test_json():
Expand Down Expand Up @@ -67,7 +67,7 @@ class NamedTupleObject(namedtuple('BaseTuple', ('name', 'value'))):
assert hug.input_format.json(BytesIO(hug.output_format.json(data))) == [1, 2, 3]

with open('README.md', 'rb') as json_file:
hasattr(hug.output_format.json(json_file), 'read')
assert hasattr(hug.output_format.json(json_file), 'read')


def test_pretty_json():
Expand All @@ -89,35 +89,49 @@ def test_json_camelcase():

def test_image():
'''Ensure that it's possible to output images with hug'''
hasattr(hug.output_format.png_image('logo.png'), 'read')
assert hasattr(hug.output_format.png_image('logo.png'), 'read')
with open('logo.png', 'rb') as image_file:
hasattr(hug.output_format.png_image(image_file), 'read')
assert hasattr(hug.output_format.png_image(image_file), 'read')

assert hug.output_format.png_image('Not Existent') == None

class FakeImageWithSave():
def save(self, to, format):
to.write(b'test')
hasattr(hug.output_format.png_image(FakeImageWithSave()), 'read')
assert hasattr(hug.output_format.png_image(FakeImageWithSave()), 'read')

class FakeImageWithSave():
def render(self):
return 'test'
assert hug.output_format.svg_xml_image(FakeImageWithSave()) == 'test'


def test_file():
'''Ensure that it's possible to easily output files'''
class FakeResponse(object):
pass

fake_response = FakeResponse()
assert hasattr(hug.output_format.file('logo.png', fake_response), 'read')
assert fake_response.content_type == 'image/png'
with open('logo.png', 'rb') as image_file:
hasattr(hug.output_format.file(image_file, fake_response), 'read')

assert not hasattr(hug.output_format.file('NON EXISTENT FILE', fake_response), 'read')


def test_video():
'''Ensure that it's possible to output videos with hug'''
hasattr(hug.output_format.mp4_video('example.gif'), 'read')
assert hasattr(hug.output_format.mp4_video('example.gif'), 'read')
with open('example.gif', 'rb') as image_file:
hasattr(hug.output_format.mp4_video(image_file), 'read')
assert hasattr(hug.output_format.mp4_video(image_file), 'read')

assert hug.output_format.mp4_video('Not Existent') == None

class FakeVideoWithSave():
def save(self, to, format):
to.write(b'test')
hasattr(hug.output_format.mp4_video(FakeVideoWithSave()), 'read')
assert hasattr(hug.output_format.mp4_video(FakeVideoWithSave()), 'read')

class FakeVideoWithSave():
def render(self):
Expand Down

0 comments on commit bbc0f05

Please sign in to comment.