diff --git a/examples/simple_server.py b/examples/simple_server.py index 155453c9..24e3570f 100644 --- a/examples/simple_server.py +++ b/examples/simple_server.py @@ -3,8 +3,10 @@ from sanic.response import json app = Sanic(__name__) + @app.route("/") async def test(request): - return json({ "test": True }) + return json({"test": True}) -app.run(host="0.0.0.0", port=8000) \ No newline at end of file + +app.run(host="0.0.0.0", port=8000) diff --git a/examples/try_everything.py b/examples/try_everything.py index 8e0b8679..e6a58d74 100644 --- a/examples/try_everything.py +++ b/examples/try_everything.py @@ -5,29 +5,35 @@ from sanic.exceptions import ServerError app = Sanic(__name__) + @app.route("/") async def test_async(request): - return json({ "test": True }) - + return json({"test": True}) + + @app.route("/sync", methods=['GET', 'POST']) def test_sync(request): - return json({ "test": True }) + return json({"test": True}) + @app.route("/dynamic//") def test_params(request, name, id): return text("yeehaww {} {}".format(name, id)) + @app.route("/exception") def exception(request): raise ServerError("It's dead jim") + # ----------------------------------------------- # # Exceptions # ----------------------------------------------- # @app.exception(ServerError) async def test(request, exception): - return json({ "exception": "{}".format(exception), "status": exception.status_code }, status=exception.status_code) + return json({"exception": "{}".format(exception), "status": exception.status_code}, status=exception.status_code) + # ----------------------------------------------- # # Read from request @@ -35,15 +41,18 @@ async def test(request, exception): @app.route("/json") def post_json(request): - return json({ "received": True, "message": request.json }) + return json({"received": True, "message": request.json}) + @app.route("/form") def post_json(request): - return json({ "received": True, "form_data": request.form, "test": request.form.get('test') }) + return json({"received": True, "form_data": request.form, "test": request.form.get('test')}) + @app.route("/query_string") def query_string(request): - return json({ "parsed": True, "args": request.args, "url": request.url, "query_string": request.query_string }) + return json({"parsed": True, "args": request.args, "url": request.url, "query_string": request.query_string}) + # ----------------------------------------------- # # Run Server @@ -51,9 +60,10 @@ def query_string(request): def after_start(loop): log.info("OH OH OH OH OHHHHHHHH") + + def before_stop(loop): log.info("TRIED EVERYTHING") + app.run(host="0.0.0.0", port=8000, debug=True, after_start=after_start, before_stop=before_stop) - - diff --git a/sanic/__init__.py b/sanic/__init__.py index 240e97b3..52dc810a 100644 --- a/sanic/__init__.py +++ b/sanic/__init__.py @@ -1 +1 @@ -from .sanic import Sanic \ No newline at end of file +from .sanic import Sanic diff --git a/sanic/config.py b/sanic/config.py index 72b050b8..3fc174bc 100644 --- a/sanic/config.py +++ b/sanic/config.py @@ -20,5 +20,5 @@ class Config: ▌ ▐ ▀▀▄▄▄▀ ▀▀▄▄▀ """ - REQUEST_MAX_SIZE = 100000000 # 100 megababies - REQUEST_TIMEOUT = 60 # 60 seconds \ No newline at end of file + REQUEST_MAX_SIZE = 100000000 # 100 megababies + REQUEST_TIMEOUT = 60 # 60 seconds diff --git a/sanic/exceptions.py b/sanic/exceptions.py index f082e528..b459f47b 100644 --- a/sanic/exceptions.py +++ b/sanic/exceptions.py @@ -1,43 +1,51 @@ from .response import text from traceback import format_exc + class SanicException(Exception): - def __init__(self, message, status_code=None): - super().__init__(message) - if status_code is not None: - self.status_code = status_code + def __init__(self, message, status_code=None): + super().__init__(message) + if status_code is not None: + self.status_code = status_code + class NotFound(SanicException): - status_code = 404 + status_code = 404 + + class InvalidUsage(SanicException): - status_code = 400 + status_code = 400 + + class ServerError(SanicException): - status_code = 500 + status_code = 500 + class Handler: - handlers = None - def __init__(self, sanic): - self.handlers = {} - self.sanic = sanic + handlers = None - def add(self, exception, handler): - self.handlers[exception] = handler + def __init__(self, sanic): + self.handlers = {} + self.sanic = sanic - def response(self, request, exception): - """ - Fetches and executes an exception handler and returns a reponse object - :param request: Request - :param exception: Exception to handle - :return: Response object - """ - handler = self.handlers.get(type(exception), self.default) - response = handler(request=request, exception=exception) - return response + def add(self, exception, handler): + self.handlers[exception] = handler - def default(self, request, exception): - if issubclass(type(exception), SanicException): - return text("Error: {}".format(exception), status=getattr(exception, 'status_code', 500)) - elif self.sanic.debug: - return text("Error: {}\nException: {}".format(exception, format_exc()), status=500) - else: - return text("An error occurred while generating the request", status=500) \ No newline at end of file + def response(self, request, exception): + """ + Fetches and executes an exception handler and returns a reponse object + :param request: Request + :param exception: Exception to handle + :return: Response object + """ + handler = self.handlers.get(type(exception), self.default) + response = handler(request=request, exception=exception) + return response + + def default(self, request, exception): + if issubclass(type(exception), SanicException): + return text("Error: {}".format(exception), status=getattr(exception, 'status_code', 500)) + elif self.sanic.debug: + return text("Error: {}\nException: {}".format(exception, format_exc()), status=500) + else: + return text("An error occurred while generating the request", status=500) diff --git a/sanic/log.py b/sanic/log.py index 6893c42c..b7548203 100644 --- a/sanic/log.py +++ b/sanic/log.py @@ -1,4 +1,4 @@ import logging logging.basicConfig(level=logging.INFO, format="%(asctime)s: %(levelname)s: %(message)s") -log = logging.getLogger(__name__) \ No newline at end of file +log = logging.getLogger(__name__) diff --git a/sanic/middleware.py b/sanic/middleware.py index a48d1ef1..d19a0288 100644 --- a/sanic/middleware.py +++ b/sanic/middleware.py @@ -1,4 +1,4 @@ class Middleware: - def __init__(self, process_request=None, process_response=None): - self.process_request = process_request - self.process_response = process_response \ No newline at end of file + def __init__(self, process_request=None, process_response=None): + self.process_request = process_request + self.process_response = process_response diff --git a/sanic/request.py b/sanic/request.py index a6711885..e7f0dc57 100644 --- a/sanic/request.py +++ b/sanic/request.py @@ -6,20 +6,25 @@ from ujson import loads as json_loads from .log import log + class RequestParameters(dict): """ Hosts a dict with lists as values where get returns the first value of the list and getlist returns the whole shebang """ + def __init__(self, *args, **kwargs): self.super = super() self.super.__init__(*args, **kwargs) + def get(self, name, default=None): values = self.super.get(name) return values[0] if values else default + def getlist(self, name, default=None): return self.super.get(name, default) + class Request: __slots__ = ( 'url', 'headers', 'version', 'method', @@ -75,7 +80,7 @@ class Request: @property def files(self): if self.parsed_files is None: - _ = self.form # compute form to get files + _ = self.form # compute form to get files return self.parsed_files @@ -89,7 +94,10 @@ class Request: return self.parsed_args + File = namedtuple('File', ['type', 'body', 'name']) + + def parse_multipart_form(body, boundary): """ Parses a request body and returns fields and files @@ -117,7 +125,7 @@ def parse_multipart_form(body, boundary): colon_index = form_line.index(':') form_header_field = form_line[0:colon_index] - form_header_value, form_parameters = parse_header(form_line[colon_index+2:]) + form_header_value, form_parameters = parse_header(form_line[colon_index + 2:]) if form_header_field == 'Content-Disposition': if 'filename' in form_parameters: @@ -126,11 +134,10 @@ def parse_multipart_form(body, boundary): elif form_header_field == 'Content-Type': file_type = form_header_value - post_data = form_part[line_index:-4] if file_name or file_type: files[field_name] = File(type=file_type, name=file_name, body=post_data) else: fields[field_name] = post_data.decode('utf-8') - return fields, files \ No newline at end of file + return fields, files diff --git a/sanic/response.py b/sanic/response.py index 6b13dcbc..c1a0569f 100644 --- a/sanic/response.py +++ b/sanic/response.py @@ -18,6 +18,7 @@ STATUS_CODES = { 504: 'Gateway Timeout', } + class HTTPResponse: __slots__ = ('body', 'status', 'content_type', 'headers') @@ -43,18 +44,25 @@ class HTTPResponse: additional_headers.append('{}: {}\r\n'.format(name, value).encode('utf-8')) return b''.join([ - 'HTTP/{} {} {}\r\n'.format(version, self.status, STATUS_CODES.get(self.status, 'FAIL')).encode(), - b'Content-Type: ', self.content_type.encode(), b'\r\n', - b'Content-Length: ', str(len(self.body)).encode(), b'\r\n', - b'Connection: ', ('keep-alive' if keep_alive else 'close').encode(), b'\r\n', - ] + additional_headers + [ - b'\r\n', - self.body, - ]) + 'HTTP/{} {} {}\r\n'.format(version, self.status, + STATUS_CODES.get(self.status, 'FAIL')).encode(), + b'Content-Type: ', self.content_type.encode(), b'\r\n', + b'Content-Length: ', str(len(self.body)).encode(), b'\r\n', + b'Connection: ', ('keep-alive' if keep_alive else 'close').encode(), b'\r\n', + ] + additional_headers + [ + b'\r\n', + self.body, + ]) + def json(body, status=200, headers=None): - return HTTPResponse(ujson.dumps(body), headers=headers, status=status, content_type="application/json; charset=utf-8") + return HTTPResponse(ujson.dumps(body), headers=headers, status=status, + content_type="application/json; charset=utf-8") + + def text(body, status=200, headers=None): return HTTPResponse(body, status=status, headers=headers, content_type="text/plain; charset=utf-8") + + def html(body, status=200, headers=None): - return HTTPResponse(body, status=status, headers=headers, content_type="text/html; charset=utf-8") \ No newline at end of file + return HTTPResponse(body, status=status, headers=headers, content_type="text/html; charset=utf-8") diff --git a/sanic/router.py b/sanic/router.py index 399605db..892ba655 100644 --- a/sanic/router.py +++ b/sanic/router.py @@ -5,6 +5,7 @@ from .exceptions import NotFound, InvalidUsage Route = namedtuple("Route", ['handler', 'methods', 'pattern', 'parameters']) Parameter = namedtuple("Parameter", ['name', 'cast']) + class Router: """ Router supports basic routing with parameters and method checks @@ -42,9 +43,10 @@ class Router: """ # Dict for faster lookups of if method allowed - methods_dict = { method: True for method in methods } if methods else None + methods_dict = {method: True for method in methods} if methods else None parameters = [] + def add_parameter(match): # We could receive NAME or NAME:PATTERN parts = match.group(1).split(':') @@ -93,11 +95,13 @@ class Router: if route: if route.methods and not request.method in route.methods: - raise InvalidUsage("Method {} not allowed for URL {}".format(request.method, request.url), status_code=405) + raise InvalidUsage("Method {} not allowed for URL {}".format(request.method, request.url), + status_code=405) return route.handler, args, kwargs else: raise NotFound("Requested URL {} not found".format(request.url)) + class SimpleRouter: """ Simple router records and reads all routes from a dictionary @@ -110,14 +114,15 @@ class SimpleRouter: def add(self, uri, methods, handler): # Dict for faster lookups of method allowed - methods_dict = { method: True for method in methods } if methods else None + methods_dict = {method: True for method in methods} if methods else None self.routes[uri] = Route(handler=handler, methods=methods_dict, pattern=uri, parameters=None) def get(self, request): route = self.routes.get(request.url) if route: if route.methods and not request.method in route.methods: - raise InvalidUsage("Method {} not allowed for URL {}".format(request.method, request.url), status_code=405) + raise InvalidUsage("Method {} not allowed for URL {}".format(request.method, request.url), + status_code=405) return route.handler, [], {} else: - raise NotFound("Requested URL {} not found".format(request.url)) \ No newline at end of file + raise NotFound("Requested URL {} not found".format(request.url)) diff --git a/sanic/sanic.py b/sanic/sanic.py index 4013413d..f17cd4af 100644 --- a/sanic/sanic.py +++ b/sanic/sanic.py @@ -12,6 +12,7 @@ from .router import Router from .server import serve from .exceptions import ServerError + class Sanic: def __init__(self, name, router=None, error_handler=None): self.name = name @@ -34,6 +35,7 @@ class Sanic: :param methods: list or tuple of methods allowed :return: decorated function """ + def response(handler): self.router.add(uri=uri, methods=methods, handler=handler) return handler @@ -48,6 +50,7 @@ class Sanic: :param methods: list or tuple of methods allowed :return: decorated function """ + def response(handler): for exception in exceptions: self.error_handler.add(exception, handler) @@ -63,6 +66,7 @@ class Sanic: """ middleware = None attach_to = 'request' + def register_middleware(middleware): if attach_to == 'request': self.request_middleware.append(middleware) @@ -156,7 +160,7 @@ class Sanic: :param before_stop: Function to be executed when a stop signal is received before it is respected :return: Nothing """ - self.error_handler.debug=True + self.error_handler.debug = True self.debug = debug if debug: diff --git a/sanic/server.py b/sanic/server.py index f824d17e..338435c8 100644 --- a/sanic/server.py +++ b/sanic/server.py @@ -3,6 +3,7 @@ from inspect import isawaitable from signal import SIGINT, SIGTERM import httptools + try: import uvloop as async_loop except: @@ -11,17 +12,19 @@ except: from .log import log from .request import Request + class Signal: stopped = False + class HttpProtocol(asyncio.Protocol): + __slots__ = ('loop', 'transport', 'connections', 'signal', # event loop, connection + 'parser', 'request', 'url', 'headers', # request params + 'request_handler', 'request_timeout', 'request_max_size', # request config + '_total_request_size', '_timeout_handler') # connection management - __slots__ = ('loop', 'transport', 'connections', 'signal', # event loop, connection - 'parser', 'request', 'url', 'headers', # request params - 'request_handler', 'request_timeout', 'request_max_size', # request config - '_total_request_size', '_timeout_handler') # connection management - - def __init__(self, *, loop, request_handler, signal=Signal(), connections={}, request_timeout=60, request_max_size=None): + def __init__(self, *, loop, request_handler, signal=Signal(), connections={}, request_timeout=60, + request_max_size=None): self.loop = loop self.transport = None self.request = None @@ -37,6 +40,7 @@ class HttpProtocol(asyncio.Protocol): self._timeout_handler = None # -------------------------------------------- # + # Connection # -------------------------------------------- # @@ -51,9 +55,10 @@ class HttpProtocol(asyncio.Protocol): self.cleanup() def connection_timeout(self): - self.bail_out("Request timed out, connection closed") + self.bail_out("Request timed out, connection closed") + + # -------------------------------------------- # - # -------------------------------------------- # # Parsing # -------------------------------------------- # @@ -86,7 +91,7 @@ class HttpProtocol(asyncio.Protocol): def on_headers_complete(self): self.request = Request( - url_bytes=self.url, + url_bytes=self.url, headers=dict(self.headers), version=self.parser.get_http_version(), method=self.parser.get_method().decode() @@ -94,6 +99,7 @@ class HttpProtocol(asyncio.Protocol): def on_body(self, body): self.request.body = body + def on_message_complete(self): self.loop.create_task(self.request_handler(self.request, self.write_response)) @@ -133,20 +139,22 @@ class HttpProtocol(asyncio.Protocol): return True return False -def serve(host, port, request_handler, after_start=None, before_stop=None, debug=False, request_timeout=60, request_max_size=None): + +def serve(host, port, request_handler, after_start=None, before_stop=None, debug=False, request_timeout=60, + request_max_size=None): # Create Event Loop loop = async_loop.new_event_loop() asyncio.set_event_loop(loop) # I don't think we take advantage of this # And it slows everything waaayyy down - #loop.set_debug(debug) + # loop.set_debug(debug) connections = {} signal = Signal() server_coroutine = loop.create_server(lambda: HttpProtocol( loop=loop, - connections = connections, - signal = signal, + connections=connections, + signal=signal, request_handler=request_handler, request_timeout=request_timeout, request_max_size=request_max_size, diff --git a/setup.py b/setup.py index 6e0ed72b..54521390 100644 --- a/setup.py +++ b/setup.py @@ -22,4 +22,4 @@ setup( 'Development Status :: 1 - Alpha', 'Environment :: Web Environment', ], -) \ No newline at end of file +) diff --git a/tests/performance/sanic/http_response.py b/tests/performance/sanic/http_response.py index dda47737..71b1f755 100644 --- a/tests/performance/sanic/http_response.py +++ b/tests/performance/sanic/http_response.py @@ -4,13 +4,13 @@ import os import inspect currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) -sys.path.insert(0,currentdir + '/../../../') +sys.path.insert(0, currentdir + '/../../../') import timeit from sanic.response import json -print(json({ "test":True }).output()) +print(json({"test": True}).output()) print("Running New 100,000 times") times = 0 @@ -20,7 +20,7 @@ for n in range(6): print("Took {} seconds".format(time)) total_time += time times += 1 -print("Average: {}".format(total_time/times)) +print("Average: {}".format(total_time / times)) print("Running Old 100,000 times") times = 0 @@ -30,4 +30,4 @@ for n in range(6): print("Took {} seconds".format(time)) total_time += time times += 1 -print("Average: {}".format(total_time/times)) \ No newline at end of file +print("Average: {}".format(total_time / times)) diff --git a/tests/performance/sanic/simple_server.py b/tests/performance/sanic/simple_server.py index 5d92364d..d19ffa54 100644 --- a/tests/performance/sanic/simple_server.py +++ b/tests/performance/sanic/simple_server.py @@ -3,15 +3,17 @@ import os import inspect currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) -sys.path.insert(0,currentdir + '/../../../') +sys.path.insert(0, currentdir + '/../../../') from sanic import Sanic from sanic.response import json app = Sanic("test") + @app.route("/") async def test(request): - return json({ "test": True }) + return json({"test": True}) -app.run(host="0.0.0.0", port=sys.argv[1]) \ No newline at end of file + +app.run(host="0.0.0.0", port=sys.argv[1]) diff --git a/tests/performance/sanic/varied_server.py b/tests/performance/sanic/varied_server.py index 6eba929c..2c788387 100644 --- a/tests/performance/sanic/varied_server.py +++ b/tests/performance/sanic/varied_server.py @@ -3,7 +3,7 @@ import os import inspect currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) -sys.path.insert(0,currentdir + '/../../../') +sys.path.insert(0, currentdir + '/../../../') from sanic import Sanic from sanic.response import json, text @@ -11,36 +11,44 @@ from sanic.exceptions import ServerError app = Sanic("test") + @app.route("/") async def test(request): - return json({ "test": True }) - + return json({"test": True}) + + @app.route("/sync", methods=['GET', 'POST']) def test(request): - return json({ "test": True }) + return json({"test": True}) @app.route("/text//") def rtext(request, name, butt): return text("yeehaww {} {}".format(name, butt)) + @app.route("/exception") def exception(request): raise ServerError("yep") + @app.route("/exception/async") async def test(request): raise ServerError("asunk") + @app.route("/post_json") def post_json(request): - return json({ "received": True, "message": request.json }) + return json({"received": True, "message": request.json}) + @app.route("/query_string") def query_string(request): - return json({ "parsed": True, "args": request.args, "url": request.url, "query_string": request.query_string }) + return json({"parsed": True, "args": request.args, "url": request.url, "query_string": request.query_string}) + import sys + app.run(host="0.0.0.0", port=sys.argv[1]) @@ -55,7 +63,7 @@ app.run(host="0.0.0.0", port=sys.argv[1]) # for n in range(30): # connection = await asyncio_redis.Connection.create(host='192.168.99.100', port=6379) # sanic.redis.append(connection) - + # c=0 # @app.route("/postgres") diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py index ce538220..28e766cd 100644 --- a/tests/test_exceptions.py +++ b/tests/test_exceptions.py @@ -49,5 +49,3 @@ def test_invalid_usage_exception(): def test_not_found_exception(): request, response = sanic_endpoint_test(exception_app, uri='/404') assert response.status == 404 - - diff --git a/tests/test_middleware.py b/tests/test_middleware.py index 59d6d8f2..1b338d31 100644 --- a/tests/test_middleware.py +++ b/tests/test_middleware.py @@ -4,78 +4,85 @@ from sanic.request import Request from sanic.response import json, text, HTTPResponse from sanic.utils import sanic_endpoint_test + # ------------------------------------------------------------ # # GET # ------------------------------------------------------------ # def test_middleware_request(): - app = Sanic('test_middleware_request') + app = Sanic('test_middleware_request') - results = [] - @app.middleware - async def handler(request): - results.append(request) + results = [] - @app.route('/') - async def handler(request): - return text('OK') + @app.middleware + async def handler(request): + results.append(request) - request, response = sanic_endpoint_test(app) + @app.route('/') + async def handler(request): + return text('OK') + + request, response = sanic_endpoint_test(app) + + assert response.text == 'OK' + assert type(results[0]) is Request - assert response.text == 'OK' - assert type(results[0]) is Request def test_middleware_response(): - app = Sanic('test_middleware_response') + app = Sanic('test_middleware_response') - results = [] - @app.middleware('request') - async def process_response(request): - results.append(request) - @app.middleware('response') - async def process_response(request, response): - results.append(request) - results.append(response) + results = [] - @app.route('/') - async def handler(request): - return text('OK') + @app.middleware('request') + async def process_response(request): + results.append(request) - request, response = sanic_endpoint_test(app) + @app.middleware('response') + async def process_response(request, response): + results.append(request) + results.append(response) + + @app.route('/') + async def handler(request): + return text('OK') + + request, response = sanic_endpoint_test(app) + + assert response.text == 'OK' + assert type(results[0]) is Request + assert type(results[1]) is Request + assert issubclass(type(results[2]), HTTPResponse) - assert response.text == 'OK' - assert type(results[0]) is Request - assert type(results[1]) is Request - assert issubclass(type(results[2]), HTTPResponse) def test_middleware_override_request(): - app = Sanic('test_middleware_override_request') + app = Sanic('test_middleware_override_request') - @app.middleware - async def halt_request(request): - return text('OK') + @app.middleware + async def halt_request(request): + return text('OK') - @app.route('/') - async def handler(request): - return text('FAIL') + @app.route('/') + async def handler(request): + return text('FAIL') - response = sanic_endpoint_test(app, gather_request=False) + response = sanic_endpoint_test(app, gather_request=False) + + assert response.status == 200 + assert response.text == 'OK' - assert response.status == 200 - assert response.text == 'OK' def test_middleware_override_response(): - app = Sanic('test_middleware_override_response') + app = Sanic('test_middleware_override_response') - @app.middleware('response') - async def process_response(request, response): - return text('OK') + @app.middleware('response') + async def process_response(request, response): + return text('OK') - @app.route('/') - async def handler(request): - return text('FAIL') + @app.route('/') + async def handler(request): + return text('FAIL') - request, response = sanic_endpoint_test(app) + request, response = sanic_endpoint_test(app) - assert response.status == 200 - assert response.text == 'OK' \ No newline at end of file + assert response.status == 200 + assert response.text == 'OK' diff --git a/tests/test_requests.py b/tests/test_requests.py index 770e7563..42dc3e8e 100644 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -3,77 +3,80 @@ from sanic import Sanic from sanic.response import json, text from sanic.utils import sanic_endpoint_test + # ------------------------------------------------------------ # # GET # ------------------------------------------------------------ # def test_sync(): - app = Sanic('test_text') + app = Sanic('test_text') - @app.route('/') - def handler(request): - return text('Hello') + @app.route('/') + def handler(request): + return text('Hello') - request, response = sanic_endpoint_test(app) + request, response = sanic_endpoint_test(app) + + assert response.text == 'Hello' - assert response.text == 'Hello' def test_text(): - app = Sanic('test_text') + app = Sanic('test_text') - @app.route('/') - async def handler(request): - return text('Hello') + @app.route('/') + async def handler(request): + return text('Hello') - request, response = sanic_endpoint_test(app) + request, response = sanic_endpoint_test(app) - assert response.text == 'Hello' + assert response.text == 'Hello' def test_json(): - app = Sanic('test_json') + app = Sanic('test_json') - @app.route('/') - async def handler(request): - return json({"test":True}) + @app.route('/') + async def handler(request): + return json({"test": True}) - request, response = sanic_endpoint_test(app) + request, response = sanic_endpoint_test(app) - try: - results = json_loads(response.text) - except: - raise ValueError("Expected JSON response but got '{}'".format(response)) + try: + results = json_loads(response.text) + except: + raise ValueError("Expected JSON response but got '{}'".format(response)) - assert results.get('test') == True + assert results.get('test') == True def test_query_string(): - app = Sanic('test_query_string') + app = Sanic('test_query_string') - @app.route('/') - async def handler(request): - return text('OK') + @app.route('/') + async def handler(request): + return text('OK') - request, response = sanic_endpoint_test(app, params=[("test1", 1), ("test2", "false"), ("test2", "true")]) + request, response = sanic_endpoint_test(app, params=[("test1", 1), ("test2", "false"), ("test2", "true")]) + + assert request.args.get('test1') == '1' + assert request.args.get('test2') == 'false' - assert request.args.get('test1') == '1' - assert request.args.get('test2') == 'false' # ------------------------------------------------------------ # # POST # ------------------------------------------------------------ # def test_post_json(): - app = Sanic('test_post_json') + app = Sanic('test_post_json') - @app.route('/') - async def handler(request): - return text('OK') + @app.route('/') + async def handler(request): + return text('OK') - payload = {'test': 'OK'} - headers = {'content-type': 'application/json'} + payload = {'test': 'OK'} + headers = {'content-type': 'application/json'} - request, response = sanic_endpoint_test(app, data=json_dumps(payload), headers=headers) + request, response = sanic_endpoint_test(app, data=json_dumps(payload), headers=headers) - assert request.json.get('test') == 'OK' - assert response.text == 'OK' \ No newline at end of file + assert request.json.get('test') == 'OK' + assert response.text == 'OK' diff --git a/tests/test_routes.py b/tests/test_routes.py index 2f1ff4b8..c1885271 100644 --- a/tests/test_routes.py +++ b/tests/test_routes.py @@ -3,93 +3,97 @@ from sanic import Sanic from sanic.response import json, text from sanic.utils import sanic_endpoint_test + # ------------------------------------------------------------ # # UTF-8 # ------------------------------------------------------------ # def test_dynamic_route(): - app = Sanic('test_dynamic_route') + app = Sanic('test_dynamic_route') - results = [] + results = [] - @app.route('/folder/') - async def handler(request, name): - results.append(name) - return text('OK') + @app.route('/folder/') + async def handler(request, name): + results.append(name) + return text('OK') - request, response = sanic_endpoint_test(app, uri='/folder/test123') + request, response = sanic_endpoint_test(app, uri='/folder/test123') + + assert response.text == 'OK' + assert results[0] == 'test123' - assert response.text == 'OK' - assert results[0] == 'test123' def test_dynamic_route_string(): - app = Sanic('test_dynamic_route_string') + app = Sanic('test_dynamic_route_string') - results = [] + results = [] - @app.route('/folder/') - async def handler(request, name): - results.append(name) - return text('OK') + @app.route('/folder/') + async def handler(request, name): + results.append(name) + return text('OK') - request, response = sanic_endpoint_test(app, uri='/folder/test123') + request, response = sanic_endpoint_test(app, uri='/folder/test123') + + assert response.text == 'OK' + assert results[0] == 'test123' - assert response.text == 'OK' - assert results[0] == 'test123' def test_dynamic_route_int(): - app = Sanic('test_dynamic_route_int') + app = Sanic('test_dynamic_route_int') - results = [] + results = [] - @app.route('/folder/') - async def handler(request, folder_id): - results.append(folder_id) - return text('OK') + @app.route('/folder/') + async def handler(request, folder_id): + results.append(folder_id) + return text('OK') - request, response = sanic_endpoint_test(app, uri='/folder/12345') - assert response.text == 'OK' - assert type(results[0]) is int + request, response = sanic_endpoint_test(app, uri='/folder/12345') + assert response.text == 'OK' + assert type(results[0]) is int - request, response = sanic_endpoint_test(app, uri='/folder/asdf') - assert response.status == 404 + request, response = sanic_endpoint_test(app, uri='/folder/asdf') + assert response.status == 404 def test_dynamic_route_number(): - app = Sanic('test_dynamic_route_int') + app = Sanic('test_dynamic_route_int') - results = [] + results = [] - @app.route('/weight/') - async def handler(request, weight): - results.append(weight) - return text('OK') + @app.route('/weight/') + async def handler(request, weight): + results.append(weight) + return text('OK') - request, response = sanic_endpoint_test(app, uri='/weight/12345') - assert response.text == 'OK' - assert type(results[0]) is float + request, response = sanic_endpoint_test(app, uri='/weight/12345') + assert response.text == 'OK' + assert type(results[0]) is float - request, response = sanic_endpoint_test(app, uri='/weight/1234.56') - assert response.status == 200 + request, response = sanic_endpoint_test(app, uri='/weight/1234.56') + assert response.status == 200 + + request, response = sanic_endpoint_test(app, uri='/weight/1234-56') + assert response.status == 404 - request, response = sanic_endpoint_test(app, uri='/weight/1234-56') - assert response.status == 404 def test_dynamic_route_regex(): - app = Sanic('test_dynamic_route_int') + app = Sanic('test_dynamic_route_int') - @app.route('/folder/') - async def handler(request, folder_id): - return text('OK') + @app.route('/folder/') + async def handler(request, folder_id): + return text('OK') - request, response = sanic_endpoint_test(app, uri='/folder/test') - assert response.status == 200 + request, response = sanic_endpoint_test(app, uri='/folder/test') + assert response.status == 200 - request, response = sanic_endpoint_test(app, uri='/folder/test1') - assert response.status == 404 + request, response = sanic_endpoint_test(app, uri='/folder/test1') + assert response.status == 404 - request, response = sanic_endpoint_test(app, uri='/folder/test-123') - assert response.status == 404 + request, response = sanic_endpoint_test(app, uri='/folder/test-123') + assert response.status == 404 - request, response = sanic_endpoint_test(app, uri='/folder/') - assert response.status == 200 + request, response = sanic_endpoint_test(app, uri='/folder/') + assert response.status == 200 diff --git a/tests/test_utf8.py b/tests/test_utf8.py index da285d00..8530aeac 100644 --- a/tests/test_utf8.py +++ b/tests/test_utf8.py @@ -3,52 +3,56 @@ from sanic import Sanic from sanic.response import json, text from sanic.utils import sanic_endpoint_test + # ------------------------------------------------------------ # # UTF-8 # ------------------------------------------------------------ # def test_utf8_query_string(): - app = Sanic('test_utf8_query_string') + app = Sanic('test_utf8_query_string') - @app.route('/') - async def handler(request): - return text('OK') + @app.route('/') + async def handler(request): + return text('OK') + + request, response = sanic_endpoint_test(app, params=[("utf8", '✓')]) + assert request.args.get('utf8') == '✓' - request, response = sanic_endpoint_test(app, params=[("utf8", '✓')]) - assert request.args.get('utf8') == '✓' def test_utf8_response(): - app = Sanic('test_utf8_response') + app = Sanic('test_utf8_response') - @app.route('/') - async def handler(request): - return text('✓') + @app.route('/') + async def handler(request): + return text('✓') + + request, response = sanic_endpoint_test(app) + assert response.text == '✓' - request, response = sanic_endpoint_test(app) - assert response.text == '✓' def skip_test_utf8_route(): - app = Sanic('skip_test_utf8_route') + app = Sanic('skip_test_utf8_route') - @app.route('/') - async def handler(request): - return text('OK') + @app.route('/') + async def handler(request): + return text('OK') + + # UTF-8 Paths are not supported + request, response = sanic_endpoint_test(app, route='/✓', uri='/✓') + assert response.text == 'OK' - # UTF-8 Paths are not supported - request, response = sanic_endpoint_test(app, route='/✓', uri='/✓') - assert response.text == 'OK' def test_utf8_post_json(): - app = Sanic('test_utf8_post_json') + app = Sanic('test_utf8_post_json') - @app.route('/') - async def handler(request): - return text('OK') + @app.route('/') + async def handler(request): + return text('OK') - payload = {'test': '✓'} - headers = {'content-type': 'application/json'} + payload = {'test': '✓'} + headers = {'content-type': 'application/json'} - request, response = sanic_endpoint_test(app, data=json_dumps(payload), headers=headers) + request, response = sanic_endpoint_test(app, data=json_dumps(payload), headers=headers) - assert request.json.get('test') == '✓' - assert response.text == 'OK' \ No newline at end of file + assert request.json.get('test') == '✓' + assert response.text == 'OK'