Compare commits

..

10 Commits

Author SHA1 Message Date
Adam Hopkins
0a84b6cfdb Merge branch 'main' into fix-2388-strtobool 2022-02-02 20:44:19 +02:00
Stephen Sadowski
2750f0f82a lint: fixed linting (again) across all files 2022-02-01 15:15:55 -06:00
Stephen Sadowski
0f5de2ef2c fix: replace strtobool inside setup.py; including from sanic.utils is a no-go 2022-02-01 15:07:12 -06:00
Stephen Sadowski
aef131af90 fix: linting errors 2022-02-01 14:33:34 -06:00
Stephen Sadowski
6e40292974 test: add strtobool validation test for deprecation replacement 2022-02-01 14:15:35 -06:00
Stephen Sadowski
db92c1fedd fix: update sanic.utils.str_to_bool to match deprecated strtobool, changed setup.py to use sanic.utils.str_to_bool 2022-02-01 14:11:52 -06:00
Stephen Sadowski
bbffdcbd68 fix: added message when ValueError is raised for strtobool replacement 2022-01-24 06:52:36 -06:00
Stephen Sadowski
768d0e09b5 fix: removed distutils dependency in setup.py per PEP 632 2022-01-23 19:57:30 -06:00
Stephen Sadowski
9d04f24298 fix: E501 line too long. 2022-01-23 18:48:49 -06:00
Stephen Sadowski
6f18c82879 fix: replace distutils.strtobool() with locally implemented version per PEP 632 2022-01-23 09:43:14 -06:00
13 changed files with 99 additions and 123 deletions

View File

@@ -8,6 +8,7 @@ on:
jobs:
testPy310:
if: github.event.pull_request.draft == false
name: ut-${{ matrix.config.tox-env }}-${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:

View File

@@ -140,7 +140,6 @@ To maintain the code consistency, Sanic uses following tools.
#. `isort <https://github.com/timothycrosley/isort>`_
#. `black <https://github.com/python/black>`_
#. `flake8 <https://github.com/PyCQA/flake8>`_
#. `slotscheck <https://github.com/ariebovenberg/slotscheck>`_
isort
*****
@@ -168,13 +167,7 @@ flake8
#. pycodestyle
#. Ned Batchelder's McCabe script
slotscheck
**********
``slotscheck`` ensures that there are no problems with ``__slots__``
(e.g. overlaps, or missing slots in base classes).
``isort``\ , ``black``\ , ``flake8`` and ``slotscheck`` checks are performed during ``tox`` lint checks.
``isort``\ , ``black`` and ``flake8`` checks are performed during ``tox`` lint checks.
The **easiest** way to make your code conform is to run the following before committing.

View File

@@ -6,5 +6,5 @@ data = ""
for i in range(1, 250000):
data += str(i)
r = requests.post('http://0.0.0.0:8000/stream', data=data)
r = requests.post("http://0.0.0.0:8000/stream", data=data)
print(r.text)

View File

@@ -44,8 +44,11 @@ from typing import (
from urllib.parse import urlencode, urlunparse
from warnings import filterwarnings
from sanic_routing.exceptions import FinalizationError, NotFound
from sanic_routing.route import Route
from sanic_routing.exceptions import ( # type: ignore
FinalizationError,
NotFound,
)
from sanic_routing.route import Route # type: ignore
from sanic.application.ext import setup_ext
from sanic.application.state import ApplicationState, Mode, ServerStage
@@ -139,6 +142,7 @@ class Sanic(BaseSanic, RunnerMixin, metaclass=TouchUpMeta):
"error_handler",
"go_fast",
"listeners",
"name",
"named_request_middleware",
"named_response_middleware",
"request_class",
@@ -1264,9 +1268,10 @@ class Sanic(BaseSanic, RunnerMixin, metaclass=TouchUpMeta):
...
def purge_tasks(self):
for key, task in self._task_registry.items():
for task in self.tasks:
if task.done() or task.cancelled():
self._task_registry[key] = None
name = task.get_name()
self._task_registry[name] = None
self._task_registry = {
k: v for k, v in self._task_registry.items() if v is not None

View File

@@ -16,9 +16,9 @@ class MiddlewareMixin(metaclass=SanicMeta):
self, middleware_or_request, attach_to="request", apply=True
):
"""
Decorate and register middleware to be called before a request
is handled or after a response is created. Can either be called as
*@app.middleware* or *@app.middleware('request')*.
Decorate and register middleware to be called before a request.
Can either be called as *@app.middleware* or
*@app.middleware('request')*
`See user guide re: middleware
<https://sanicframework.org/guide/basics/middleware.html>`__
@@ -47,25 +47,12 @@ class MiddlewareMixin(metaclass=SanicMeta):
)
def on_request(self, middleware=None):
"""Register a middleware to be called before a request is handled.
This is the same as *@app.middleware('request')*.
:param: middleware: A callable that takes in request.
"""
if callable(middleware):
return self.middleware(middleware, "request")
else:
return partial(self.middleware, attach_to="request")
def on_response(self, middleware=None):
"""Register a middleware to be called after a response is created.
This is the same as *@app.middleware('response')*.
:param: middleware:
A callable that takes in a request and its response.
"""
if callable(middleware):
return self.middleware(middleware, "response")
else:

View File

@@ -50,16 +50,6 @@ class BaseHTTPResponse:
The base class for all HTTP Responses
"""
__slots__ = (
"asgi",
"body",
"content_type",
"stream",
"status",
"headers",
"_cookies",
)
_dumps = json_dumps
def __init__(self):
@@ -166,7 +156,7 @@ class HTTPResponse(BaseHTTPResponse):
:type content_type: Optional[str]
"""
__slots__ = ()
__slots__ = ("body", "status", "content_type", "headers", "_cookies")
def __init__(
self,

View File

@@ -1,12 +1,26 @@
import asyncio
from distutils.util import strtobool
from os import getenv
from sanic.compat import OS_IS_WINDOWS
from sanic.log import error_logger
def strtobool(query: str) -> bool:
"""
reimplement strtobool per PEP 632 and python 3.12 deprecation
True values are y, yes, t, true, on and 1; false values are n, no, f,
false, off and 0. Raises ValueError if val is anything else.
"""
if query.lower() in ["y", "yes", "t", "true", "on", "1"]:
return True
elif query.lower() in ["n", "no", "f", "false", "off", "0"]:
return False
else:
raise ValueError(f"String value {query} cannot be converted to bool")
def try_use_uvloop() -> None:
"""
Use uvloop instead of the default asyncio loop.

View File

@@ -11,35 +11,18 @@ from sanic.helpers import import_string
def str_to_bool(val: str) -> bool:
"""Takes string and tries to turn it into bool as human would do.
"""
reimplement strtobool per PEP 632 and python 3.12 deprecation
If val is in case insensitive (
"y", "yes", "yep", "yup", "t",
"true", "on", "enable", "enabled", "1"
) returns True.
If val is in case insensitive (
"n", "no", "f", "false", "off", "disable", "disabled", "0"
) returns False.
Else Raise ValueError."""
val = val.lower()
if val in {
"y",
"yes",
"yep",
"yup",
"t",
"true",
"on",
"enable",
"enabled",
"1",
}:
True values are y, yes, t, true, on and 1; false values are n, no, f,
false, off and 0. Raises ValueError if val is anything else.
"""
if val.lower() in ["y", "yes", "t", "true", "on", "1"]:
return True
elif val in {"n", "no", "f", "false", "off", "disable", "disabled", "0"}:
elif val.lower() in ["n", "no", "f", "false", "off", "0"]:
return False
else:
raise ValueError(f"Invalid truth value {val}")
raise ValueError(f"String value {val} cannot be converted to bool")
def load_module_from_file_location(

View File

@@ -6,8 +6,6 @@ import os
import re
import sys
from distutils.util import strtobool
from setuptools import find_packages, setup
from setuptools.command.test import test as TestCommand
@@ -61,7 +59,7 @@ setup_kwargs = {
"Build fast. Run fast."
),
"long_description": long_description,
"packages": find_packages(),
"packages": find_packages(include=[]),
"package_data": {"sanic": ["py.typed"]},
"platforms": "any",
"python_requires": ">=3.7",
@@ -112,7 +110,6 @@ tests_require = [
"docutils",
"pygments",
"uvicorn<0.15.0",
"slotscheck>=0.8.0,<1",
types_ujson,
]
@@ -133,6 +130,23 @@ dev_require = tests_require + [
all_require = list(set(dev_require + docs_require))
# trying to self-refernce this from within sanic prior to install is
# problematic
def strtobool(val: str) -> bool:
"""
reimplement strtobool per PEP 632 and python 3.12 deprecation
True values are y, yes, t, true, on and 1; false values are n, no, f,
false, off and 0. Raises ValueError if val is anything else.
"""
if val.lower() in ["y", "yes", "t", "true", "on", "1"]:
return True
elif val.lower() in ["n", "no", "f", "false", "off", "0"]:
return False
else:
raise ValueError(f"String value {val} cannot be converted to bool")
if strtobool(os.environ.get("SANIC_NO_UJSON", "no")):
print("Installing without uJSON")
requirements.remove(ujson)

View File

@@ -5,7 +5,6 @@ from pathlib import Path
import pytest
from pyparsing import line
from sanic_routing import __version__ as __routing_version__
from sanic import __version__
@@ -53,10 +52,8 @@ def test_server_run(appname):
out, err, exitcode = capture(command)
lines = out.split(b"\n")
firstline = lines[starting_line(lines) + 1]
error_message = f"Lines found: {lines}\nErr output: {err}"
assert exitcode != 1
assert lines, error_message
assert firstline == b"Goin' Fast @ http://127.0.0.1:8000"
@@ -83,9 +80,6 @@ def test_tls_options(cmd):
out, err, exitcode = capture(command)
assert exitcode != 1
lines = out.split(b"\n")
error_message = f"Lines found: {lines}\nErr output: {err}"
assert lines, error_message
firstline = lines[starting_line(lines) + 1]
assert firstline == b"Goin' Fast @ https://127.0.0.1:9999"
@@ -108,9 +102,7 @@ def test_tls_wrong_options(cmd):
assert exitcode == 1
assert not out
lines = err.decode().split("\n")
error_message = f"Lines found: {lines}\nErr output: {err}"
assert lines, error_message
errmsg = lines[6]
assert errmsg == "TLS certificates must be specified by either of:"
@@ -127,11 +119,9 @@ def test_host_port_localhost(cmd):
out, err, exitcode = capture(command)
lines = out.split(b"\n")
expected = b"Goin' Fast @ http://localhost:9999"
error_message = f"Lines found: {lines}\nErr output: {err}"
assert exitcode != 1
assert lines, error_message
assert expected in lines, error_message
assert expected in lines, f"Lines found: {lines}\nErr output: {err}"
@pytest.mark.parametrize(
@@ -146,11 +136,9 @@ def test_host_port_ipv4(cmd):
out, err, exitcode = capture(command)
lines = out.split(b"\n")
expected = b"Goin' Fast @ http://127.0.0.127:9999"
error_message = f"Lines found: {lines}\nErr output: {err}"
assert exitcode != 1
assert lines, error_message
assert expected in lines, error_message
assert expected in lines, f"Lines found: {lines}\nErr output: {err}"
@pytest.mark.parametrize(
@@ -165,11 +153,9 @@ def test_host_port_ipv6_any(cmd):
out, err, exitcode = capture(command)
lines = out.split(b"\n")
expected = b"Goin' Fast @ http://[::]:9999"
error_message = f"Lines found: {lines}\nErr output: {err}"
assert exitcode != 1
assert lines, error_message
assert expected in lines, error_message
assert expected in lines, f"Lines found: {lines}\nErr output: {err}"
@pytest.mark.parametrize(
@@ -184,11 +170,9 @@ def test_host_port_ipv6_loopback(cmd):
out, err, exitcode = capture(command)
lines = out.split(b"\n")
expected = b"Goin' Fast @ http://[::1]:9999"
error_message = f"Lines found: {lines}\nErr output: {err}"
assert exitcode != 1
assert lines, error_message
assert expected in lines, error_message
assert expected in lines, f"Lines found: {lines}\nErr output: {err}"
@pytest.mark.parametrize(
@@ -222,12 +206,12 @@ def test_debug(cmd):
out, err, exitcode = capture(command)
lines = out.split(b"\n")
info = read_app_info(lines)
error_message = f"Lines found: {lines}\nErr output: {err}"
assert info, error_message
assert info["debug"] is True, error_message
assert info["auto_reload"] is False, error_message
assert "dev" not in info, error_message
assert info["debug"] is True, f"Lines found: {lines}\nErr output: {err}"
assert (
info["auto_reload"] is False
), f"Lines found: {lines}\nErr output: {err}"
assert "dev" not in info, f"Lines found: {lines}\nErr output: {err}"
@pytest.mark.parametrize("cmd", ("--dev", "-d"))
@@ -236,11 +220,11 @@ def test_dev(cmd):
out, err, exitcode = capture(command)
lines = out.split(b"\n")
info = read_app_info(lines)
error_message = f"Lines found: {lines}\nErr output: {err}"
assert info, error_message
assert info["debug"] is True, error_message
assert info["auto_reload"] is True, error_message
assert info["debug"] is True, f"Lines found: {lines}\nErr output: {err}"
assert (
info["auto_reload"] is True
), f"Lines found: {lines}\nErr output: {err}"
@pytest.mark.parametrize("cmd", ("--auto-reload", "-r"))
@@ -249,12 +233,12 @@ def test_auto_reload(cmd):
out, err, exitcode = capture(command)
lines = out.split(b"\n")
info = read_app_info(lines)
error_message = f"Lines found: {lines}\nErr output: {err}"
assert info, error_message
assert info["debug"] is False, error_message
assert info["auto_reload"] is True, error_message
assert "dev" not in info, error_message
assert info["debug"] is False, f"Lines found: {lines}\nErr output: {err}"
assert (
info["auto_reload"] is True
), f"Lines found: {lines}\nErr output: {err}"
assert "dev" not in info, f"Lines found: {lines}\nErr output: {err}"
@pytest.mark.parametrize(
@@ -265,10 +249,10 @@ def test_access_logs(cmd, expected):
out, err, exitcode = capture(command)
lines = out.split(b"\n")
info = read_app_info(lines)
error_message = f"Lines found: {lines}\nErr output: {err}"
assert info, error_message
assert info["access_log"] is expected, error_message
assert (
info["access_log"] is expected
), f"Lines found: {lines}\nErr output: {err}"
@pytest.mark.parametrize("cmd", ("--version", "-v"))
@@ -292,7 +276,7 @@ def test_noisy_exceptions(cmd, expected):
out, err, exitcode = capture(command)
lines = out.split(b"\n")
info = read_app_info(lines)
error_message = f"Lines found: {lines}\nErr output: {err}"
assert info, error_message
assert info["noisy_exceptions"] is expected, error_message
assert (
info["noisy_exceptions"] is expected
), f"Lines found: {lines}\nErr output: {err}"

View File

@@ -80,18 +80,6 @@ async def test_purge_tasks(app: Sanic):
assert len(app._task_registry) == 0
async def test_purge_tasks_with_create_task(app: Sanic):
app.add_task(asyncio.create_task(dummy(3)), name="dummy")
await app.cancel_task("dummy")
assert len(app._task_registry) == 1
app.purge_tasks()
assert len(app._task_registry) == 0
def test_shutdown_tasks_on_app_stop():
class TestSanic(Sanic):
shutdown_tasks = Mock()

View File

@@ -6,6 +6,7 @@ import pytest
from sanic.exceptions import LoadFileException
from sanic.utils import load_module_from_file_location
from sanic.utils import str_to_bool as strtobool
@pytest.mark.parametrize(
@@ -48,3 +49,20 @@ def test_load_module_from_file_location_using_env():
module = load_module_from_file_location(location)
assert isinstance(module, ModuleType)
@pytest.mark.parametrize(
"valid,values",
(
(True, ["y", "yes", "t", "true", "on", "1", "Y", "yEs", "True"]),
(False, ["n", "no", "f", "false", "off", "0", "N", "No", "False"]),
(None, ["yyy", "foo"]),
),
)
def test_strtobool(valid, values):
for value in values:
if valid is None:
with pytest.raises(ValueError):
strtobool(value)
else:
assert strtobool(value) is valid

View File

@@ -21,7 +21,6 @@ commands =
flake8 sanic
black --config ./.black.toml --check --verbose sanic/
isort --check-only sanic --profile=black
slotscheck --verbose -m sanic
[testenv:type-checking]
commands =