From bb2bd2fe538416133b4b426eb6231d74366084bc Mon Sep 17 00:00:00 2001 From: Adam Hopkins Date: Tue, 28 May 2019 16:13:12 +0300 Subject: [PATCH 1/9] Point extensions page to awesome-sanic repo (#1596) --- docs/sanic/extensions.md | 76 +--------------------------------------- 1 file changed, 1 insertion(+), 75 deletions(-) diff --git a/docs/sanic/extensions.md b/docs/sanic/extensions.md index a912f3b9..157ee7cb 100644 --- a/docs/sanic/extensions.md +++ b/docs/sanic/extensions.md @@ -1,75 +1 @@ -# Extensions - -A list of Sanic extensions created by the community. - - -## Extension and Plugin Development - -- [Sanic-Plugins-Framework](https://github.com/ashleysommer/sanicpluginsframework): Library for easily creating and using Sanic plugins. -- [sanic-script](https://github.com/tim2anna/sanic-script): An extension for Sanic that adds support for writing commands to your application. - -## Security - -- [Sanic JWT](https://github.com/ahopkins/sanic-jwt): Authentication, JWT, and permission scoping for Sanic. -- [Secure](https://github.com/cakinney/secure): Secure 🔒 is a lightweight package that adds optional security headers and cookie attributes for Python web frameworks. -- [Sessions](https://github.com/subyraman/sanic_session): Support for sessions. Allows using redis, memcache or an in memory store. -- [CORS](https://github.com/ashleysommer/sanic-cors): A port of flask-cors. -- [Sanic-JWT-Extended](https://github.com/devArtoria/Sanic-JWT-Extended): Provides extended JWT support for -- [UserAgent](https://github.com/lixxu/sanic-useragent): Add `user_agent` to request -- [Limiter](https://github.com/bohea/sanic-limiter): Rate limiting for sanic. -- [sanic-oauth](https://gitlab.com/SirEdvin/sanic-oauth): OAuth Library with many provider and OAuth1/OAuth2 support. -- [Sanic-Auth](https://github.com/pyx/sanic-auth): A minimal backend agnostic session-based user authentication mechanism for Sanic. -- [Sanic-CookieSession](https://github.com/pyx/sanic-cookiesession): A client-side only, cookie-based session, similar to the built-in session in Flask. - -## Documentation - -- [OpenAPI/Swagger](https://github.com/channelcat/sanic-openapi): OpenAPI support, plus a Swagger UI. -- [Sanic-RestPlus](https://github.com/ashleysommer/sanic-restplus): A port of Flask-RestPlus for Sanic. Full-featured REST API with SwaggerUI generation. -- [sanic-transmute](https://github.com/yunstanford/sanic-transmute): A Sanic extension that generates APIs from python function and classes, and also generates Swagger UI/documentation automatically. - -## ORM and Database Integration - -- [Motor](https://github.com/lixxu/sanic-motor): Simple motor wrapper. -- [Sanic CRUD](https://github.com/Typhon66/sanic_crud): CRUD REST API generation with peewee models. -- [sanic-graphql](https://github.com/graphql-python/sanic-graphql): GraphQL integration with Sanic -- [GINO](https://github.com/fantix/gino): An asyncio ORM on top of SQLAlchemy core, delivered with a Sanic extension. ([Documentation](https://python-gino.readthedocs.io/)) -- [Databases](https://github.com/encode/databases): Async database access for SQLAlchemy core, with support for PostgreSQL, MySQL, and SQLite. - -## Unit Testing - -- [pytest-sanic](https://github.com/yunstanford/pytest-sanic): A pytest plugin for Sanic. It helps you to test your code asynchronously. - -## Project Creation Template - -- [cookiecutter-sanic](https://github.com/harshanarayana/cookiecutter-sanic): Get your sanic application up and running in a matter of second in a well defined project structure. - Batteries included for deployment, unit testing, automated release management and changelog generation. - -## Templating - -- [Sanic-WTF](https://github.com/pyx/sanic-wtf): Sanic-WTF makes using WTForms with Sanic and CSRF (Cross-Site Request Forgery) protection a little bit easier. -- [Jinja2](https://github.com/lixxu/sanic-jinja2): Support for Jinja2 template. -- [jinja2-sanic](https://github.com/yunstanford/jinja2-sanic): a jinja2 template renderer for Sanic.([Documentation](http://jinja2-sanic.readthedocs.io/en/latest/)) - -## API Helper Utilities - -- [sanic-sse](https://github.com/inn0kenty/sanic_sse): [Server-Sent Events](https://en.wikipedia.org/wiki/Server-sent_events) implementation for Sanic. -- [Compress](https://github.com/subyraman/sanic_compress): Allows you to easily gzip Sanic responses. A port of Flask-Compress. -- [Pagination](https://github.com/lixxu/python-paginate): Simple pagination support. -- [Sanic EnvConfig](https://github.com/jamesstidard/sanic-envconfig): Pull environment variables into your sanic config. - -## i18n/l10n Support -- [Babel](https://github.com/lixxu/sanic-babel): Adds i18n/l10n support to Sanic applications with the help of the `Babel` library - -## Custom Middlewares - -- [Dispatch](https://github.com/ashleysommer/sanic-dispatcher): A dispatcher inspired by `DispatcherMiddleware` in werkzeug. Can act as a Sanic-to-WSGI adapter. - -## Monitoring and Reporting - -- [sanic-prometheus](https://github.com/dkruchinin/sanic-prometheus): Prometheus metrics for Sanic -- [sanic-zipkin](https://github.com/kevinqqnj/sanic-zipkin): Easily report request/function/RPC traces to zipkin/jaeger, through aiozipkin. - - -## Sample Applications - -- [Sanic-nginx-docker-example](https://github.com/itielshwartz/sanic-nginx-docker-example): Simple and easy to use example of Sanic behined nginx using docker-compose. +Moved to the [`awesome-sanic`](https://github.com/mekicha/awesome-sanic) list. \ No newline at end of file From a57c14c70bca3514d502db3ce53fd3262d1af149 Mon Sep 17 00:00:00 2001 From: Adam Hopkins Date: Tue, 28 May 2019 16:30:07 +0300 Subject: [PATCH 2/9] Add requests-async as a hard requirement. See #1592 (#1595) --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 861ce013..63413d0e 100644 --- a/setup.py +++ b/setup.py @@ -82,6 +82,7 @@ requirements = [ "aiofiles>=0.3.0", "websockets>=6.0,<7.0", "multidict>=4.0,<5.0", + "requests-async==0.5.0", ] tests_require = [ @@ -90,7 +91,6 @@ tests_require = [ "gunicorn", "pytest-cov", "httpcore==0.3.0", - "requests-async==0.5.0", "beautifulsoup4", uvloop, ujson, From c15158224b873d8686f2960b73958e0011d2a877 Mon Sep 17 00:00:00 2001 From: Adam Hopkins Date: Thu, 30 May 2019 17:10:00 +0300 Subject: [PATCH 3/9] Set testing.PORT on all app.create_server() in tests (#1593) --- tests/test_logo.py | 21 ++++++++++++++++----- tests/test_server_events.py | 2 +- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/tests/test_logo.py b/tests/test_logo.py index d99e117f..2f9cb90f 100644 --- a/tests/test_logo.py +++ b/tests/test_logo.py @@ -2,6 +2,7 @@ import asyncio import logging from sanic.config import BASE_LOGO +from sanic.testing import PORT try: @@ -13,7 +14,9 @@ except BaseException: def test_logo_base(app, caplog): - server = app.create_server(debug=True, return_asyncio_server=True) + server = app.create_server( + debug=True, return_asyncio_server=True, port=PORT + ) loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) loop._stopping = False @@ -32,7 +35,9 @@ def test_logo_base(app, caplog): def test_logo_false(app, caplog): app.config.LOGO = False - server = app.create_server(debug=True, return_asyncio_server=True) + server = app.create_server( + debug=True, return_asyncio_server=True, port=PORT + ) loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) loop._stopping = False @@ -45,13 +50,17 @@ def test_logo_false(app, caplog): app.stop() assert caplog.record_tuples[ROW][1] == logging.INFO - assert caplog.record_tuples[ROW][2] == "Goin' Fast @ http://127.0.0.1:8000" + assert caplog.record_tuples[ROW][ + 2 + ] == "Goin' Fast @ http://127.0.0.1:{}".format(PORT) def test_logo_true(app, caplog): app.config.LOGO = True - server = app.create_server(debug=True, return_asyncio_server=True) + server = app.create_server( + debug=True, return_asyncio_server=True, port=PORT + ) loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) loop._stopping = False @@ -70,7 +79,9 @@ def test_logo_true(app, caplog): def test_logo_custom(app, caplog): app.config.LOGO = "My Custom Logo" - server = app.create_server(debug=True, return_asyncio_server=True) + server = app.create_server( + debug=True, return_asyncio_server=True, port=PORT + ) loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) loop._stopping = False diff --git a/tests/test_server_events.py b/tests/test_server_events.py index be17e801..c5573486 100644 --- a/tests/test_server_events.py +++ b/tests/test_server_events.py @@ -84,7 +84,7 @@ async def test_trigger_before_events_create_server(app): async def init_db(app, loop): app.db = MySanicDb() - await app.create_server(debug=True, return_asyncio_server=True) + await app.create_server(debug=True, return_asyncio_server=True, port=PORT) assert hasattr(app, "db") assert isinstance(app.db, MySanicDb) From f21db608598793cb3cf24bd838ab382a79b6b30a Mon Sep 17 00:00:00 2001 From: Yun Xu Date: Mon, 3 Jun 2019 22:08:24 -0700 Subject: [PATCH 4/9] fix: handle expect header --- sanic/exceptions.py | 5 ++++ sanic/request.py | 2 +- sanic/server.py | 18 ++++++++++++- tests/test_request_stream.py | 49 ++++++++++++++++++++++++++++++++++++ 4 files changed, 72 insertions(+), 2 deletions(-) diff --git a/sanic/exceptions.py b/sanic/exceptions.py index b06c76d1..2c4ab2c0 100644 --- a/sanic/exceptions.py +++ b/sanic/exceptions.py @@ -218,6 +218,11 @@ class ContentRangeError(SanicException): } +@add_status_code(417) +class HeaderExpectationFailed(SanicException): + pass + + @add_status_code(403) class Forbidden(SanicException): pass diff --git a/sanic/request.py b/sanic/request.py index dfb3d1ff..15c2d5c4 100644 --- a/sanic/request.py +++ b/sanic/request.py @@ -29,7 +29,7 @@ except ImportError: DEFAULT_HTTP_CONTENT_TYPE = "application/octet-stream" - +EXPECT_HEADER = "EXPECT" # HTTP/1.1: https://www.w3.org/Protocols/rfc2616/rfc2616-sec7.html#sec7.2.1 # > If the media type remains unknown, the recipient SHOULD treat it diff --git a/sanic/server.py b/sanic/server.py index a2038e3c..b4673cac 100644 --- a/sanic/server.py +++ b/sanic/server.py @@ -15,6 +15,7 @@ from httptools.parser.errors import HttpParserError from multidict import CIMultiDict from sanic.exceptions import ( + HeaderExpectationFailed, InvalidUsage, PayloadTooLarge, RequestTimeout, @@ -22,7 +23,7 @@ from sanic.exceptions import ( ServiceUnavailable, ) from sanic.log import access_logger, logger -from sanic.request import Request, StreamBuffer +from sanic.request import Request, StreamBuffer, EXPECT_HEADER from sanic.response import HTTPResponse @@ -314,6 +315,10 @@ class HttpProtocol(asyncio.Protocol): if self._keep_alive_timeout_handler: self._keep_alive_timeout_handler.cancel() self._keep_alive_timeout_handler = None + + if self.request.headers.get(EXPECT_HEADER): + self.expect_handler() + if self.is_request_stream: self._is_stream_handler = self.router.is_stream_handler( self.request @@ -324,6 +329,17 @@ class HttpProtocol(asyncio.Protocol): ) self.execute_request_handler() + def expect_handler(self): + """ + Handler for Expect Header. + """ + expect = self.request.headers.get(EXPECT_HEADER) + if self.request.version == "1.1": + if expect.lower() == "100-continue": + self.transport.write(b"HTTP/1.1 100 Continue\r\n\r\n") + else: + self.write_error(HeaderExpectationFailed("Unknow Expect: {expect}".format(expect=expect))) + def on_body(self, body): if self.is_request_stream and self._is_stream_handler: self._request_stream_task = self.loop.create_task( diff --git a/tests/test_request_stream.py b/tests/test_request_stream.py index d845dc85..823bd4e4 100644 --- a/tests/test_request_stream.py +++ b/tests/test_request_stream.py @@ -1,4 +1,6 @@ +import pytest from sanic.blueprints import Blueprint +from sanic.exceptions import HeaderExpectationFailed from sanic.request import StreamBuffer from sanic.response import stream, text from sanic.views import CompositionView, HTTPMethodView @@ -40,6 +42,53 @@ def test_request_stream_method_view(app): assert response.text == data +def test_request_stream_100_continue(app): + + class SimpleView(HTTPMethodView): + + @stream_decorator + async def post(self, request): + assert isinstance(request.stream, StreamBuffer) + result = "" + while True: + body = await request.stream.read() + if body is None: + break + result += body.decode("utf-8") + return text(result) + + app.add_route(SimpleView.as_view(), "/method_view") + + assert app.is_request_stream is True + + request, response = app.test_client.post("/method_view", data=data, headers={"EXPECT": "100-continue"}) + assert response.status == 200 + assert response.text == data + + +def test_request_stream_100_continue_raise_HeaderExpectationFailed(app): + + class SimpleView(HTTPMethodView): + + @stream_decorator + async def post(self, request): + assert isinstance(request.stream, StreamBuffer) + result = "" + while True: + body = await request.stream.read() + if body is None: + break + result += body.decode("utf-8") + return text(result) + + app.add_route(SimpleView.as_view(), "/method_view") + + assert app.is_request_stream is True + with pytest.raises(ValueError) as e: + app.test_client.post("/method_view", data=data, headers={"EXPECT": "100-continue-extra"}) + assert "Unknow Expect: 100-continue-extra" in str(e) + + def test_request_stream_app(app): """for self.is_request_stream = True and decorators""" From 2631f10c5e3531d921a3446c0bc7b2fa43db3a17 Mon Sep 17 00:00:00 2001 From: Yun Xu Date: Mon, 3 Jun 2019 22:12:10 -0700 Subject: [PATCH 5/9] lint: fix isort and flake8 complains --- sanic/server.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sanic/server.py b/sanic/server.py index b4673cac..460436a6 100644 --- a/sanic/server.py +++ b/sanic/server.py @@ -23,7 +23,7 @@ from sanic.exceptions import ( ServiceUnavailable, ) from sanic.log import access_logger, logger -from sanic.request import Request, StreamBuffer, EXPECT_HEADER +from sanic.request import EXPECT_HEADER, Request, StreamBuffer from sanic.response import HTTPResponse @@ -338,7 +338,11 @@ class HttpProtocol(asyncio.Protocol): if expect.lower() == "100-continue": self.transport.write(b"HTTP/1.1 100 Continue\r\n\r\n") else: - self.write_error(HeaderExpectationFailed("Unknow Expect: {expect}".format(expect=expect))) + self.write_error( + HeaderExpectationFailed( + "Unknow Expect: {expect}".format(expect=expect) + ) + ) def on_body(self, body): if self.is_request_stream and self._is_stream_handler: From 39d134994d7652b5d380c6ee35eb7264677fa4c2 Mon Sep 17 00:00:00 2001 From: Yun Xu Date: Tue, 4 Jun 2019 10:25:32 -0700 Subject: [PATCH 6/9] minor: address pr feedbacks, small refactoring and fix --- sanic/server.py | 2 +- tests/test_request_stream.py | 41 ++++++++++++------------------------ 2 files changed, 14 insertions(+), 29 deletions(-) diff --git a/sanic/server.py b/sanic/server.py index 460436a6..f8a9b203 100644 --- a/sanic/server.py +++ b/sanic/server.py @@ -340,7 +340,7 @@ class HttpProtocol(asyncio.Protocol): else: self.write_error( HeaderExpectationFailed( - "Unknow Expect: {expect}".format(expect=expect) + "Unknown Expect: {expect}".format(expect=expect) ) ) diff --git a/tests/test_request_stream.py b/tests/test_request_stream.py index 823bd4e4..7e406ac0 100644 --- a/tests/test_request_stream.py +++ b/tests/test_request_stream.py @@ -42,8 +42,11 @@ def test_request_stream_method_view(app): assert response.text == data -def test_request_stream_100_continue(app): - +@pytest.mark.parametrize("headers, expect_raise_exception", [ +({"EXPECT": "100-continue"}, False), +({"EXPECT": "100-continue-extra"}, True), +]) +def test_request_stream_100_continue(app, headers, expect_raise_exception): class SimpleView(HTTPMethodView): @stream_decorator @@ -61,34 +64,16 @@ def test_request_stream_100_continue(app): assert app.is_request_stream is True - request, response = app.test_client.post("/method_view", data=data, headers={"EXPECT": "100-continue"}) - assert response.status == 200 - assert response.text == data + if not expect_raise_exception: + request, response = app.test_client.post("/method_view", data=data, headers={"EXPECT": "100-continue"}) + assert response.status == 200 + assert response.text == data + else: + with pytest.raises(ValueError) as e: + app.test_client.post("/method_view", data=data, headers={"EXPECT": "100-continue-extra"}) + assert "Unknow Expect: 100-continue-extra" in str(e) -def test_request_stream_100_continue_raise_HeaderExpectationFailed(app): - - class SimpleView(HTTPMethodView): - - @stream_decorator - async def post(self, request): - assert isinstance(request.stream, StreamBuffer) - result = "" - while True: - body = await request.stream.read() - if body is None: - break - result += body.decode("utf-8") - return text(result) - - app.add_route(SimpleView.as_view(), "/method_view") - - assert app.is_request_stream is True - with pytest.raises(ValueError) as e: - app.test_client.post("/method_view", data=data, headers={"EXPECT": "100-continue-extra"}) - assert "Unknow Expect: 100-continue-extra" in str(e) - - def test_request_stream_app(app): """for self.is_request_stream = True and decorators""" From 1b1a51c1bbda2ad9d6de268ea6b4e82be4f63e25 Mon Sep 17 00:00:00 2001 From: Yun Xu Date: Tue, 4 Jun 2019 10:37:03 -0700 Subject: [PATCH 7/9] minor: fix typo in error msg --- tests/test_request_stream.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_request_stream.py b/tests/test_request_stream.py index 7e406ac0..70fa621b 100644 --- a/tests/test_request_stream.py +++ b/tests/test_request_stream.py @@ -71,7 +71,7 @@ def test_request_stream_100_continue(app, headers, expect_raise_exception): else: with pytest.raises(ValueError) as e: app.test_client.post("/method_view", data=data, headers={"EXPECT": "100-continue-extra"}) - assert "Unknow Expect: 100-continue-extra" in str(e) + assert "Unknown Expect: 100-continue-extra" in str(e) def test_request_stream_app(app): From 13079c6e30d000226b358a916ce323082683daf9 Mon Sep 17 00:00:00 2001 From: Harsha Narayana Date: Thu, 6 Jun 2019 17:51:58 +0530 Subject: [PATCH 8/9] GIT-1591 Strict Slashes behavior fix (#1594) * fix: GIT-1591: fix strict_slashes option inheriting behavior Signed-off-by: Harsha Narayana * doc: GIT-1591: add documentation exlaining the strict_slashes behavior Signed-off-by: Harsha Narayana * fix: GIT-1591: fix deprecated for test_client Signed-off-by: Harsha Narayana --- docs/sanic/routing.md | 39 +++++++++++++++++++++++++++ sanic/blueprints.py | 2 +- tests/test_blueprints.py | 46 ++++++++++++++++++++++++++++++++ tests/test_keep_alive_timeout.py | 10 +++---- tests/test_redirect.py | 4 +-- tests/test_request_cancel.py | 8 +++--- tests/test_request_stream.py | 1 - tests/test_request_timeout.py | 13 ++++----- tests/test_response.py | 4 +-- 9 files changed, 102 insertions(+), 25 deletions(-) diff --git a/docs/sanic/routing.md b/docs/sanic/routing.md index 54ea56a6..c016bd70 100644 --- a/docs/sanic/routing.md +++ b/docs/sanic/routing.md @@ -241,6 +241,45 @@ def handler(request): app.blueprint(bp) ``` +The behavior of how the `strict_slashes` flag follows a defined hierarchy which decides if a specific route +falls under the `strict_slashes` behavior. + +```bash +|___ Route + |___ Blueprint + |___ Application +``` + +Above hierarchy defines how the `strict_slashes` flag will behave. The first non `None` value of the `strict_slashes` +found in the above order will be applied to the route in question. + +```python +from sanic import Sanic, Blueprint +from sanic.response import text + +app = Sanic("sample_strict_slashes", strict_slashes=True) + +@app.get("/r1") +def r1(request): + return text("strict_slashes is applicable from App level") + +@app.get("/r2", strict_slashes=False) +def r2(request): + return text("strict_slashes is not applicable due to False value set in route level") + +bp = Blueprint("bp", strict_slashes=False) + +@bp.get("/r3", strict_slashes=True) +def r3(request): + return text("strict_slashes applicable from blueprint route level") + +bp1 = Blueprint("bp1", strict_slashes=True) + +@bp.get("/r4") +def r3(request): + return text("strict_slashes applicable from blueprint level") +``` + ## User defined route name A custom route name can be used by passing a `name` argument while registering the route which will diff --git a/sanic/blueprints.py b/sanic/blueprints.py index c50de648..b4894f62 100644 --- a/sanic/blueprints.py +++ b/sanic/blueprints.py @@ -37,7 +37,7 @@ class Blueprint: url_prefix=None, host=None, version=None, - strict_slashes=False, + strict_slashes=None, ): """ In *Sanic* terminology, a **Blueprint** is a logical collection of diff --git a/tests/test_blueprints.py b/tests/test_blueprints.py index f0a67bd7..16a97309 100644 --- a/tests/test_blueprints.py +++ b/tests/test_blueprints.py @@ -687,3 +687,49 @@ def test_register_blueprint(app, debug): "version 1.0. Please use the blueprint method" " instead" ) + + +def test_strict_slashes_behavior_adoption(app): + app.strict_slashes = True + + @app.get("/test") + def handler_test(request): + return text("Test") + + assert app.test_client.get("/test")[1].status == 200 + assert app.test_client.get("/test/")[1].status == 404 + + bp = Blueprint("bp") + + @bp.get("/one", strict_slashes=False) + def one(request): + return text("one") + + @bp.get("/second") + def second(request): + return text("second") + + app.blueprint(bp) + + assert app.test_client.get("/one")[1].status == 200 + assert app.test_client.get("/one/")[1].status == 200 + + assert app.test_client.get("/second")[1].status == 200 + assert app.test_client.get("/second/")[1].status == 404 + + bp2 = Blueprint("bp2", strict_slashes=False) + + @bp2.get("/third") + def third(request): + return text("third") + + app.blueprint(bp2) + assert app.test_client.get("/third")[1].status == 200 + assert app.test_client.get("/third/")[1].status == 200 + + @app.get("/f1", strict_slashes=False) + def f1(request): + return text("f1") + + assert app.test_client.get("/f1")[1].status == 200 + assert app.test_client.get("/f1/")[1].status == 200 diff --git a/tests/test_keep_alive_timeout.py b/tests/test_keep_alive_timeout.py index c6fc0831..672d78ac 100644 --- a/tests/test_keep_alive_timeout.py +++ b/tests/test_keep_alive_timeout.py @@ -24,7 +24,9 @@ old_conn = None class ReusableSanicConnectionPool(httpcore.ConnectionPool): async def acquire_connection(self, origin): global old_conn - connection = self.active_connections.pop_by_origin(origin, http2_only=True) + connection = self.active_connections.pop_by_origin( + origin, http2_only=True + ) if connection is None: connection = self.keepalive_connections.pop_by_origin(origin) @@ -187,11 +189,7 @@ class ReuseableSanicTestClient(SanicTestClient): self._session = ResusableSanicSession() try: response = await getattr(self._session, method.lower())( - url, - verify=False, - timeout=request_keepalive, - *args, - **kwargs, + url, verify=False, timeout=request_keepalive, *args, **kwargs ) except NameError: raise Exception(response.status_code) diff --git a/tests/test_redirect.py b/tests/test_redirect.py index 86c4ace3..8e6c35f0 100644 --- a/tests/test_redirect.py +++ b/tests/test_redirect.py @@ -110,7 +110,7 @@ def test_redirect_with_header_injection(redirect_app): @pytest.mark.parametrize("test_str", ["sanic-test", "sanictest", "sanic test"]) -async def test_redirect_with_params(app, test_client, test_str): +async def test_redirect_with_params(app, sanic_client, test_str): @app.route("/api/v1/test//") async def init_handler(request, test): assert test == test_str @@ -121,7 +121,7 @@ async def test_redirect_with_params(app, test_client, test_str): assert test == test_str return text("OK") - test_cli = await test_client(app) + test_cli = await sanic_client(app) response = await test_cli.get("/api/v1/test/{}/".format(quote(test_str))) assert response.status == 200 diff --git a/tests/test_request_cancel.py b/tests/test_request_cancel.py index e9499f6d..916f4d14 100644 --- a/tests/test_request_cancel.py +++ b/tests/test_request_cancel.py @@ -4,7 +4,7 @@ import contextlib from sanic.response import stream, text -async def test_request_cancel_when_connection_lost(loop, app, test_client): +async def test_request_cancel_when_connection_lost(loop, app, sanic_client): app.still_serving_cancelled_request = False @app.get("/") @@ -14,7 +14,7 @@ async def test_request_cancel_when_connection_lost(loop, app, test_client): app.still_serving_cancelled_request = True return text("OK") - test_cli = await test_client(app) + test_cli = await sanic_client(app) # schedule client call task = loop.create_task(test_cli.get("/")) @@ -33,7 +33,7 @@ async def test_request_cancel_when_connection_lost(loop, app, test_client): assert app.still_serving_cancelled_request is False -async def test_stream_request_cancel_when_conn_lost(loop, app, test_client): +async def test_stream_request_cancel_when_conn_lost(loop, app, sanic_client): app.still_serving_cancelled_request = False @app.post("/post/", stream=True) @@ -53,7 +53,7 @@ async def test_stream_request_cancel_when_conn_lost(loop, app, test_client): return stream(streaming) - test_cli = await test_client(app) + test_cli = await sanic_client(app) # schedule client call task = loop.create_task(test_cli.post("/post/1")) diff --git a/tests/test_request_stream.py b/tests/test_request_stream.py index d845dc85..65472a1e 100644 --- a/tests/test_request_stream.py +++ b/tests/test_request_stream.py @@ -111,7 +111,6 @@ def test_request_stream_app(app): result += body.decode("utf-8") return text(result) - assert app.is_request_stream is True request, response = app.test_client.get("/get") diff --git a/tests/test_request_timeout.py b/tests/test_request_timeout.py index 3a41e462..e3e02d7c 100644 --- a/tests/test_request_timeout.py +++ b/tests/test_request_timeout.py @@ -13,15 +13,12 @@ class DelayableSanicConnectionPool(httpcore.ConnectionPool): self._request_delay = request_delay super().__init__(*args, **kwargs) - async def send( - self, - request, - stream=False, - ssl=None, - timeout=None, - ): + async def send(self, request, stream=False, ssl=None, timeout=None): connection = await self.acquire_connection(request.url.origin) - if connection.h11_connection is None and connection.h2_connection is None: + if ( + connection.h11_connection is None + and connection.h2_connection is None + ): await connection.connect(ssl=ssl, timeout=timeout) if self._request_delay: await asyncio.sleep(self._request_delay) diff --git a/tests/test_response.py b/tests/test_response.py index 4e305191..c47dd1db 100644 --- a/tests/test_response.py +++ b/tests/test_response.py @@ -231,9 +231,7 @@ def test_chunked_streaming_returns_correct_content(streaming_app): assert response.text == "foo,bar" -def test_non_chunked_streaming_adds_correct_headers( - non_chunked_streaming_app -): +def test_non_chunked_streaming_adds_correct_headers(non_chunked_streaming_app): request, response = non_chunked_streaming_app.test_client.get("/") assert "Transfer-Encoding" not in response.headers assert response.headers["Content-Type"] == "text/csv" From 09acd64ba1772f0c27c2623fc3db1a613edd2dbd Mon Sep 17 00:00:00 2001 From: "G.Ted" Date: Tue, 11 Jun 2019 11:09:29 +0900 Subject: [PATCH 9/9] Fix typo in request_data.md, docs. --- docs/sanic/request_data.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sanic/request_data.md b/docs/sanic/request_data.md index 065d8e13..885cde71 100644 --- a/docs/sanic/request_data.md +++ b/docs/sanic/request_data.md @@ -193,7 +193,7 @@ The output will be: { "parsed": true, "url": "http:\/\/0.0.0.0:8000\/query_string?test1=value1&test2=&test3=value3", - "args_with_blank_values": {"test1": ["value1""], "test2": "", "test3": ["value3"]}, + "args_with_blank_values": {"test1": ["value1"], "test2": "", "test3": ["value3"]}, "query_string": "test1=value1&test2=&test3=value3" } ```