diff --git a/.travis.yml b/.travis.yml index ac577011..fd20da4c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,12 +5,6 @@ cache: - $HOME/.cache/pip matrix: include: - - env: TOX_ENV=py36 - python: 3.6 - name: "Python 3.6 with Extensions" - - env: TOX_ENV=py36-no-ext - python: 3.6 - name: "Python 3.6 without Extensions" - env: TOX_ENV=py37 python: 3.7 dist: xenial @@ -41,9 +35,6 @@ matrix: dist: bionic sudo: true name: "Python 3.9 without Extensions" - - env: TOX_ENV=type-checking - python: 3.6 - name: "Python 3.6 Type checks" - env: TOX_ENV=type-checking python: 3.7 name: "Python 3.7 Type checks" @@ -54,17 +45,6 @@ matrix: python: 3.9 dist: bionic name: "Python 3.9 Type checks" - - env: TOX_ENV=lint - python: 3.6 - name: "Python 3.6 Linter checks" - - env: TOX_ENV=check - python: 3.6 - name: "Python 3.6 Package checks" - - env: TOX_ENV=security - python: 3.6 - dist: xenial - sudo: true - name: "Python 3.6 Bandit security scan" - env: TOX_ENV=security python: 3.7 dist: xenial diff --git a/README.rst b/README.rst index 2472a076..844a9144 100644 --- a/README.rst +++ b/README.rst @@ -130,6 +130,7 @@ And, we can verify it is working: ``curl localhost:8000 -i`` **Now, let's go build something fast!** +Minimum Python version is 3.7. If you need Python 3.6 support, please use v20.12LTS. Documentation ------------- diff --git a/docs/sanic/api_reference.rst b/docs/sanic/api_reference.rst index 01df38b3..796148f7 100644 --- a/docs/sanic/api_reference.rst +++ b/docs/sanic/api_reference.rst @@ -109,12 +109,6 @@ sanic.server :members: :show-inheritance: -sanic.static ------------- - -.. automodule:: sanic.static - :members: - :show-inheritance: sanic.views ----------- diff --git a/sanic/app.py b/sanic/app.py index 3958f9e2..998c49b8 100644 --- a/sanic/app.py +++ b/sanic/app.py @@ -159,7 +159,7 @@ class Sanic(BaseSanic): is delayed until before server start. `See user guide - `_ + `__ :param task: future, couroutine or awaitable """ @@ -357,7 +357,7 @@ class Sanic(BaseSanic): the output URL's query string. `See user guide - `_ + `__ :param view_name: string referencing the view name :param kwargs: keys and values that are used to build request diff --git a/sanic/request.py b/sanic/request.py index d63bbd13..c17bb324 100644 --- a/sanic/request.py +++ b/sanic/request.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from typing import ( TYPE_CHECKING, Any, diff --git a/sanic/response.py b/sanic/response.py index 3f2b40ee..761ad0ab 100644 --- a/sanic/response.py +++ b/sanic/response.py @@ -10,14 +10,13 @@ from typing import ( Dict, Iterator, Optional, + Protocol, Tuple, Union, ) from urllib.parse import quote_plus from warnings import warn -from typing_extensions import Protocol - from sanic.compat import Header, open_async from sanic.cookies import CookieJar from sanic.helpers import has_message_body, remove_entity_headers diff --git a/sanic/server.py b/sanic/server.py index 96f394ca..82869208 100644 --- a/sanic/server.py +++ b/sanic/server.py @@ -24,7 +24,6 @@ import os import secrets import socket import stat -import sys from asyncio import CancelledError from asyncio.transports import Transport @@ -58,7 +57,9 @@ class Signal: class ConnInfo: - """Local and remote addresses and SSL status info.""" + """ + Local and remote addresses and SSL status info. + """ __slots__ = ( "sockname", @@ -146,7 +147,6 @@ class HttpProtocol(asyncio.Protocol): ): asyncio.set_event_loop(loop) self.loop = loop - deprecated_loop = self.loop if sys.version_info < (3, 7) else None self.app: Sanic = app self.url = None self.transport: Optional[Transport] = None @@ -168,8 +168,8 @@ class HttpProtocol(asyncio.Protocol): self.state = state if state else {} if "requests_count" not in self.state: self.state["requests_count"] = 0 - self._data_received = asyncio.Event(loop=deprecated_loop) - self._can_write = asyncio.Event(loop=deprecated_loop) + self._data_received = asyncio.Event() + self._can_write = asyncio.Event() self._can_write.set() self._exception = None self._unix = unix diff --git a/setup.py b/setup.py index 31f2c119..265e681e 100644 --- a/setup.py +++ b/setup.py @@ -64,12 +64,11 @@ setup_kwargs = { "packages": ["sanic"], "package_data": {"sanic": ["py.typed"]}, "platforms": "any", - "python_requires": ">=3.6", + "python_requires": ">=3.7", "classifiers": [ "Development Status :: 4 - Beta", "Environment :: Web Environment", "License :: OSI Approved :: MIT License", - "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", @@ -81,7 +80,7 @@ env_dependency = ( '; sys_platform != "win32" ' 'and implementation_name == "cpython"' ) ujson = "ujson>=1.35" + env_dependency -uvloop = "uvloop>=0.5.3,<0.15.0" + env_dependency +uvloop = "uvloop>=0.5.3" + env_dependency requirements = [ "sanic-routing", diff --git a/tests/test_app.py b/tests/test_app.py index f82eb5da..b5810000 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -32,9 +32,6 @@ def test_app_loop_running(app): assert response.text == "pass" -@pytest.mark.skipif( - sys.version_info < (3, 7), reason="requires python3.7 or higher" -) def test_create_asyncio_server(app): if not uvloop_installed(): loop = asyncio.get_event_loop() @@ -44,9 +41,6 @@ def test_create_asyncio_server(app): assert srv.is_serving() is True -@pytest.mark.skipif( - sys.version_info < (3, 7), reason="requires python3.7 or higher" -) def test_asyncio_server_no_start_serving(app): if not uvloop_installed(): loop = asyncio.get_event_loop() @@ -59,9 +53,6 @@ def test_asyncio_server_no_start_serving(app): assert srv.is_serving() is False -@pytest.mark.skipif( - sys.version_info < (3, 7), reason="requires python3.7 or higher" -) def test_asyncio_server_start_serving(app): if not uvloop_installed(): loop = asyncio.get_event_loop() diff --git a/tests/test_asgi.py b/tests/test_asgi.py index d5111c87..1859560d 100644 --- a/tests/test_asgi.py +++ b/tests/test_asgi.py @@ -86,11 +86,7 @@ def test_listeners_triggered(): with pytest.warns(UserWarning): server.run() - all_tasks = ( - asyncio.Task.all_tasks() - if sys.version_info < (3, 7) - else asyncio.all_tasks(asyncio.get_event_loop()) - ) + all_tasks = asyncio.all_tasks(asyncio.get_event_loop()) for task in all_tasks: task.cancel() @@ -140,11 +136,7 @@ def test_listeners_triggered_async(app): with pytest.warns(UserWarning): server.run() - all_tasks = ( - asyncio.Task.all_tasks() - if sys.version_info < (3, 7) - else asyncio.all_tasks(asyncio.get_event_loop()) - ) + all_tasks = asyncio.all_tasks(asyncio.get_event_loop()) for task in all_tasks: task.cancel()