Merge branch 'master' into patch-1

This commit is contained in:
Adam Hopkins 2020-12-25 06:48:42 +02:00 committed by GitHub
commit 38337446cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 39 additions and 128 deletions

View File

@ -17,11 +17,11 @@ environment:
PYTHON_VERSION: "3.8.x"
PYTHON_ARCH: "64"
- TOXENV: py39-no-ext
PYTHON: "C:\\Python39-x64\\python"
PYTHONPATH: "C:\\Python39-x64"
PYTHON_VERSION: "3.9.x"
PYTHON_ARCH: "64"
# - TOXENV: py39-no-ext
# PYTHON: "C:\\Python39-x64\\python"
# PYTHONPATH: "C:\\Python39-x64"
# PYTHON_VERSION: "3.9.x"
# PYTHON_ARCH: "64"
init: SET "PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%"

View File

@ -58,10 +58,6 @@ More information about
the available arguments to `httpx` can be found
[in the documentation for `httpx <https://www.encode.io/httpx/>`_.
Additionally, Sanic has an asynchronous testing client. The difference is that the async client will not stand up an
instance of your application, but will instead reach inside it using ASGI. All listeners and middleware are still
executed.
.. code-block:: python
@pytest.mark.asyncio
async def test_index_returns_200():

View File

@ -10,6 +10,7 @@ from pathlib import Path
from sanic import Sanic, response
app = Sanic(__name__)
@ -42,7 +43,9 @@ async def handler_file(request):
@app.route("/file_stream")
async def handler_file_stream(request):
return await response.file_stream(Path("../") / "setup.py", chunk_size=1024)
return await response.file_stream(
Path("../") / "setup.py", chunk_size=1024
)
@app.route("/stream", stream=True)

View File

@ -714,28 +714,6 @@ class Sanic:
self._blueprint_order.append(blueprint)
blueprint.register(self, options)
def register_blueprint(self, *args, **kwargs):
"""
Proxy method provided for invoking the :func:`blueprint` method
.. note::
To be deprecated in 1.0. Use :func:`blueprint` instead.
:param args: Blueprint object or (list, tuple) thereof
:param kwargs: option dictionary with blueprint defaults
:return: None
"""
if self.debug:
warnings.simplefilter("default")
warnings.warn(
"Use of register_blueprint will be deprecated in "
"version 1.0. Please use the blueprint method"
" instead",
DeprecationWarning,
)
return self.blueprint(*args, **kwargs)
def url_for(self, view_name: str, **kwargs):
r"""Build a URL based on a view name and the values provided.
@ -1026,7 +1004,6 @@ class Sanic:
workers: int = 1,
protocol: Optional[Type[Protocol]] = None,
backlog: int = 100,
stop_event: Any = None,
register_sys_signals: bool = True,
access_log: Optional[bool] = None,
unix: Optional[str] = None,
@ -1056,9 +1033,6 @@ class Sanic:
:param backlog: a number of unaccepted connections that the system
will allow before refusing new connections
:type backlog: int
:param stop_event: event to be triggered
before stopping the app - deprecated
:type stop_event: None
:param register_sys_signals: Register SIG* events
:type register_sys_signals: bool
:param access_log: Enables writing access logs (slows server)
@ -1086,13 +1060,6 @@ class Sanic:
protocol = (
WebSocketProtocol if self.websocket_enabled else HttpProtocol
)
if stop_event is not None:
if debug:
warnings.simplefilter("default")
warnings.warn(
"stop_event will be removed from future versions.",
DeprecationWarning,
)
# if access_log is passed explicitly change config.ACCESS_LOG
if access_log is not None:
self.config.ACCESS_LOG = access_log
@ -1149,7 +1116,6 @@ class Sanic:
sock: Optional[socket] = None,
protocol: Type[Protocol] = None,
backlog: int = 100,
stop_event: Any = None,
access_log: Optional[bool] = None,
unix: Optional[str] = None,
return_asyncio_server=False,
@ -1182,9 +1148,6 @@ class Sanic:
:param backlog: a number of unaccepted connections that the system
will allow before refusing new connections
:type backlog: int
:param stop_event: event to be triggered
before stopping the app - deprecated
:type stop_event: None
:param access_log: Enables writing access logs (slows server)
:type access_log: bool
:param return_asyncio_server: flag that defines whether there's a need
@ -1204,13 +1167,6 @@ class Sanic:
protocol = (
WebSocketProtocol if self.websocket_enabled else HttpProtocol
)
if stop_event is not None:
if debug:
warnings.simplefilter("default")
warnings.warn(
"stop_event will be removed from future versions.",
DeprecationWarning,
)
# if access_log is passed explicitly change config.ACCESS_LOG
if access_log is not None:
self.config.ACCESS_LOG = access_log
@ -1292,7 +1248,6 @@ class Sanic:
loop=None,
protocol=HttpProtocol,
backlog=100,
stop_event=None,
register_sys_signals=True,
run_async=False,
auto_reload=False,
@ -1307,13 +1262,6 @@ class Sanic:
context = create_default_context(purpose=Purpose.CLIENT_AUTH)
context.load_cert_chain(cert, keyfile=key)
ssl = context
if stop_event is not None:
if debug:
warnings.simplefilter("default")
warnings.warn(
"stop_event will be removed from future versions.",
DeprecationWarning,
)
if self.config.PROXIES_COUNT and self.config.PROXIES_COUNT < 0:
raise ValueError(
"PROXIES_COUNT cannot be negative. "

View File

@ -136,15 +136,18 @@ class Request:
return f"<{class_name}: {self.method} {self.path}>"
def body_init(self):
""".. deprecated:: 20.3"""
""".. deprecated:: 20.3
To be removed in 21.3"""
self.body = []
def body_push(self, data):
""".. deprecated:: 20.3"""
""".. deprecated:: 20.3
To be removed in 21.3"""
self.body.append(data)
def body_finish(self):
""".. deprecated:: 20.3"""
""".. deprecated:: 20.3
To be removed in 21.3"""
self.body = b"".join(self.body)
async def receive_body(self):

View File

@ -1,5 +1,3 @@
import warnings
from functools import partial
from mimetypes import guess_type
from os import path
@ -26,6 +24,8 @@ class BaseHTTPResponse:
self.asgi = False
def _encode_body(self, data):
if data is None:
return b""
return data.encode() if hasattr(data, "encode") else data
def _parse_headers(self):
@ -45,7 +45,7 @@ class BaseHTTPResponse:
body=b"",
):
""".. deprecated:: 20.3:
This function is not public API and will be removed."""
This function is not public API and will be removed in 21.3."""
# self.headers get priority over content_type
if self.content_type and "Content-Type" not in self.headers:
@ -149,22 +149,15 @@ class HTTPResponse(BaseHTTPResponse):
status=200,
headers=None,
content_type=None,
body_bytes=b"",
):
super().__init__()
self.content_type = content_type
self.body = body_bytes if body is None else self._encode_body(body)
self.body = self._encode_body(body)
self.status = status
self.headers = Header(headers or {})
self._cookies = None
if body_bytes:
warnings.warn(
"Parameter `body_bytes` is deprecated, use `body` instead",
DeprecationWarning,
)
def output(self, version="1.1", keep_alive=False, keep_alive_timeout=None):
body = b""
if has_message_body(self.status):
@ -228,20 +221,10 @@ def text(
:param content_type: the content type (string) of the response
"""
if not isinstance(body, str):
warnings.warn(
"Types other than str will be deprecated in future versions for"
f" response.text, got type {type(body).__name__})",
DeprecationWarning,
raise TypeError(
f"Bad body type. Expected str, got {type(body).__name__})"
)
# Type conversions are deprecated and quite b0rked but still supported for
# text() until applications get fixed. This try-except should be removed.
try:
# Avoid repr(body).encode() b0rkage for body that is already encoded.
# memoryview used only to test bytes-ishness.
with memoryview(body):
pass
except TypeError:
body = f"{body}" # no-op if body is already str
return HTTPResponse(
body, status=status, headers=headers, content_type=content_type
)

View File

@ -5,6 +5,7 @@ import codecs
import os
import re
import sys
from distutils.util import strtobool
from setuptools import setup
@ -24,6 +25,7 @@ class PyTest(TestCommand):
def run_tests(self):
import shlex
import pytest
errno = pytest.main(shlex.split(self.pytest_args))
@ -38,7 +40,9 @@ def open_local(paths, mode="r", encoding="utf8"):
with open_local(["sanic", "__version__.py"], encoding="latin1") as fp:
try:
version = re.findall(r"^__version__ = \"([^']+)\"\r?$", fp.read(), re.M)[0]
version = re.findall(
r"^__version__ = \"([^']+)\"\r?$", fp.read(), re.M
)[0]
except IndexError:
raise RuntimeError("Unable to determine version.")
@ -72,7 +76,9 @@ setup_kwargs = {
"entry_points": {"console_scripts": ["sanic = sanic.__main__:main"]},
}
env_dependency = '; sys_platform != "win32" ' 'and implementation_name == "cpython"'
env_dependency = (
'; sys_platform != "win32" ' 'and implementation_name == "cpython"'
)
ujson = "ujson>=1.35" + env_dependency
uvloop = "uvloop>=0.5.3" + env_dependency
@ -89,9 +95,9 @@ requirements = [
tests_require = [
"pytest==5.2.1",
"multidict>=5.0,<6.0",
"gunicorn",
"gunicorn==20.0.4",
"pytest-cov",
"httpcore==0.3.0",
"httpcore==0.11.*",
"beautifulsoup4",
uvloop,
ujson,

View File

@ -825,21 +825,6 @@ def test_duplicate_blueprint(app):
)
@pytest.mark.parametrize("debug", [True, False, None])
def test_register_blueprint(app, debug):
bp = Blueprint("bp")
app.debug = debug
with pytest.warns(DeprecationWarning) as record:
app.register_blueprint(bp)
assert record[0].message.args[0] == (
"Use of register_blueprint will be deprecated in "
"version 1.0. Please use the blueprint method"
" instead"
)
def test_strict_slashes_behavior_adoption(app):
app.strict_slashes = True

View File

@ -41,7 +41,8 @@ def test_response_body_not_a_string(app):
return text(random_num)
request, response = app.test_client.get("/hello")
assert response.text == str(random_num)
assert response.status == 500
assert b"Internal Server Error" in response.body
async def sample_streaming_fn(response):
@ -624,17 +625,3 @@ def test_empty_response(app):
request, response = app.test_client.get("/test")
assert response.content_type is None
assert response.body == b""
def test_response_body_bytes_deprecated(app):
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("always")
HTTPResponse(body_bytes=b"bytes")
assert len(w) == 1
assert issubclass(w[0].category, DeprecationWarning)
assert (
"Parameter `body_bytes` is deprecated, use `body` instead"
in str(w[0].message)
)

10
tox.ini
View File

@ -7,18 +7,18 @@ setenv =
{py36,py37,py38,py39,pyNightly}-no-ext: SANIC_NO_UJSON=1
{py36,py37,py38,py39,pyNightly}-no-ext: SANIC_NO_UVLOOP=1
deps =
coverage
coverage==5.3
pytest==5.2.1
pytest-cov
pytest-sanic
pytest-sugar
pytest-benchmark
pytest-dependency
httpcore==0.3.0
httpcore==0.11.*
httpx==0.15.4
chardet<=2.3.0
chardet==3.*
beautifulsoup4
gunicorn
gunicorn==20.0.4
uvicorn
websockets>=8.1,<9.0
commands =
@ -76,7 +76,7 @@ deps =
recommonmark>=0.5.0
docutils
pygments
gunicorn
gunicorn==20.0.4
commands =
make docs-test