Skip to content

Commit

Permalink
Drop support to unsupported python and django versions
Browse files Browse the repository at this point in the history
  • Loading branch information
jairhenrique committed Nov 22, 2023
1 parent 0d80be0 commit 2c4569a
Show file tree
Hide file tree
Showing 17 changed files with 11 additions and 182 deletions.
6 changes: 1 addition & 5 deletions .github/workflows/test_full.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,8 @@ jobs:
strategy:
matrix:
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12']
django-version: ['<3.0', '<3.1', '<3.2', '<3.3', '<4.1', '<4.2', '<4.3']
django-version: ['<3.2', '<3.3', '<4.2', '<4.3']
exclude:
- python-version: '3.12'
django-version: '<3.0'
- python-version: '3.12'
django-version: '<3.1'
- python-version: '3.12'
django-version: '<3.2'
- python-version: '3.12'
Expand Down
3 changes: 0 additions & 3 deletions ninja/compatibility/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +0,0 @@
from ninja.compatibility.request import get_headers

__all__ = ["get_headers"]
57 changes: 0 additions & 57 deletions ninja/compatibility/datastructures.py

This file was deleted.

53 changes: 0 additions & 53 deletions ninja/compatibility/request.py

This file was deleted.

15 changes: 2 additions & 13 deletions ninja/compatibility/util.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
from typing import Callable, Union
from typing import Union

import django

__all__ = ["async_to_sync", "UNION_TYPES"]
__all__ = ["UNION_TYPES"]


# python3.10+ syntax of creating a union or optional type (with str | int)
Expand All @@ -13,12 +11,3 @@
UNION_TYPES = (Union, UnionType)
except ImportError:
UNION_TYPES = (Union,)


if django.VERSION < (3, 1): # pragma: no cover

def async_to_sync(func: Callable) -> Callable:
raise NotImplementedError("Django<3.1 does not have async support")

else:
from asgiref.sync import async_to_sync
5 changes: 1 addition & 4 deletions ninja/operation.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,11 @@
cast,
)

import django
import pydantic
from asgiref.sync import async_to_sync
from django.http import HttpRequest, HttpResponse, HttpResponseNotAllowed
from django.http.response import HttpResponseBase

from ninja.compatibility.util import async_to_sync
from ninja.constants import NOT_SET
from ninja.errors import AuthenticationError, ConfigError, ValidationError
from ninja.params.models import TModels
Expand Down Expand Up @@ -269,8 +268,6 @@ def _create_response_model(self, response_param: Any) -> Optional[Type[Schema]]:

class AsyncOperation(Operation):
def __init__(self, *args: Any, **kwargs: Any) -> None:
if django.VERSION < (3, 1): # pragma: no cover
raise Exception("Async operations are supported only with Django 3.1+")
super().__init__(*args, **kwargs)
self.is_async = True

Expand Down
3 changes: 1 addition & 2 deletions ninja/params/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
from pydantic import BaseModel
from pydantic.fields import FieldInfo

from ninja.compatibility import get_headers
from ninja.errors import HttpError
from ninja.types import DictStrAny

Expand Down Expand Up @@ -106,7 +105,7 @@ def get_request_data(
cls, request: HttpRequest, api: "NinjaAPI", path_params: DictStrAny
) -> Optional[DictStrAny]:
data = {}
headers = get_headers(request)
headers = request.headers
for name in cls.__ninja_flatten_map__:
if name in headers:
data[name] = headers[name]
Expand Down
3 changes: 1 addition & 2 deletions ninja/security/apikey.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

from django.http import HttpRequest

from ninja.compatibility.request import get_headers
from ninja.errors import HttpError
from ninja.security.base import AuthBase
from ninja.utils import check_csrf
Expand Down Expand Up @@ -58,5 +57,5 @@ class APIKeyHeader(APIKeyBase, ABC):
openapi_in: str = "header"

def _get_key(self, request: HttpRequest) -> Optional[str]:
headers = get_headers(request)
headers = request.headers
return headers.get(self.param_name)
5 changes: 2 additions & 3 deletions ninja/security/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
from django.conf import settings
from django.http import HttpRequest

from ninja.compatibility import get_headers
from ninja.security.base import AuthBase

__all__ = ["HttpAuthBase", "HttpBearer", "DecodeError", "HttpBasicAuth"]
Expand All @@ -25,7 +24,7 @@ class HttpBearer(HttpAuthBase, ABC):
header: str = "Authorization"

def __call__(self, request: HttpRequest) -> Optional[Any]:
headers = get_headers(request)
headers = request.headers
auth_value = headers.get(self.header)
if not auth_value:
return None
Expand All @@ -52,7 +51,7 @@ class HttpBasicAuth(HttpAuthBase, ABC): # TODO: maybe HttpBasicAuthBase
header = "Authorization"

def __call__(self, request: HttpRequest) -> Optional[Any]:
headers = get_headers(request)
headers = request.headers
auth_value = headers.get(self.header)
if not auth_value:
return None
Expand Down
6 changes: 2 additions & 4 deletions ninja/testing/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
from unittest.mock import Mock
from urllib.parse import urljoin

import django
from django.http import QueryDict, StreamingHttpResponse
from django.http.request import HttpHeaders

from ninja import NinjaAPI, Router
from ninja.responses import NinjaJSONEncoder
Expand Down Expand Up @@ -132,10 +132,8 @@ def _build_request(
for k, v in request_params.pop("headers", {}).items()
}
)
if django.VERSION[:2] > (2, 1):
from ninja.compatibility.request import HttpHeaders

request.headers = HttpHeaders(request.META) # type: ignore
request.headers = HttpHeaders(request.META) # type: ignore

if isinstance(data, QueryDict):
request.POST = data
Expand Down
5 changes: 1 addition & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,16 @@ classifiers = [
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3 :: Only",
"Framework :: Django",
"Framework :: Django :: 2.2",
"Framework :: Django :: 3.0",
"Framework :: Django :: 3.1",
"Framework :: Django :: 3.2",
"Framework :: Django :: 4.0",
"Framework :: Django :: 4.1",
"Framework :: Django :: 4.2",
"Framework :: AsyncIO",
"Topic :: Internet :: WWW/HTTP :: HTTP Servers",
"Topic :: Internet :: WWW/HTTP",
]

requires = ["Django >=2.2", "pydantic >=2.0,<3.0.0"]
requires = ["Django >=3.1", "pydantic >=2.0,<3.0.0"]
description-file = "README.md"
requires-python = ">=3.7"

Expand Down
1 change: 0 additions & 1 deletion tests/test_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
from ninja.testing import TestAsyncClient


@pytest.mark.skipif(django.VERSION < (3, 1), reason="requires django 3.1 or higher")
@pytest.mark.asyncio
async def test_asyncio_operations():
api = NinjaAPI()
Expand Down
7 changes: 0 additions & 7 deletions tests/test_auth_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
from ninja.testing import TestAsyncClient, TestClient


@pytest.mark.skipif(django.VERSION < (3, 1), reason="requires django 3.1 or higher")
@pytest.mark.asyncio
async def test_async_view_handles_async_auth_func():
api = NinjaAPI()
Expand Down Expand Up @@ -36,7 +35,6 @@ async def view(request):
assert res.json() == {"key": "secret"}


@pytest.mark.skipif(django.VERSION < (3, 1), reason="requires django 3.1 or higher")
@pytest.mark.asyncio
async def test_async_view_handles_async_auth_cls():
api = NinjaAPI()
Expand Down Expand Up @@ -65,7 +63,6 @@ async def view(request):
assert res.json() == {"key": "secret"}


@pytest.mark.skipif(django.VERSION < (3, 1), reason="requires django 3.1 or higher")
@pytest.mark.asyncio
async def test_async_view_handles_multi_auth():
api = NinjaAPI()
Expand All @@ -92,7 +89,6 @@ async def view(request):
assert res.json() == {"key": "secret"}


@pytest.mark.skipif(django.VERSION < (3, 1), reason="requires django 3.1 or higher")
@pytest.mark.asyncio
async def test_async_view_handles_auth_errors():
api = NinjaAPI()
Expand All @@ -115,7 +111,6 @@ def on_custom_error(request, exc):
assert res.json() == {"custom": True}


@pytest.mark.skipif(django.VERSION < (3, 1), reason="requires django 3.1 or higher")
@pytest.mark.asyncio
async def test_sync_authenticate_method():
class KeyAuth(APIKeyQuery):
Expand All @@ -139,7 +134,6 @@ async def async_view(request):
assert res.json() == {"auth": "secret"}


@pytest.mark.skipif(django.VERSION < (3, 1), reason="requires django 3.1 or higher")
def test_async_authenticate_method_in_sync_context():
class KeyAuth(APIKeyQuery):
async def authenticate(self, request, key):
Expand All @@ -162,7 +156,6 @@ def sync_view(request):
assert res.json() == {"auth": "secret"}


@pytest.mark.skipif(django.VERSION < (3, 1), reason="requires django 3.1 or higher")
@pytest.mark.asyncio
async def test_async_with_bearer():
class BearerAuth(HttpBearer):
Expand Down
2 changes: 0 additions & 2 deletions tests/test_csrf_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ def _build_request(self, *args, **kwargs):
COOKIES = {settings.CSRF_COOKIE_NAME: TOKEN}


@pytest.mark.skipif(django.VERSION < (3, 1), reason="requires django 3.1 or higher")
@pytest.mark.asyncio
async def test_csrf_off():
csrf_OFF = NinjaAPI(urls_namespace="csrf_OFF")
Expand All @@ -35,7 +34,6 @@ async def post_off(request):
assert response.status_code == 200


@pytest.mark.skipif(django.VERSION < (3, 1), reason="requires django 3.1 or higher")
@pytest.mark.asyncio
async def test_csrf_on():
csrf_ON = NinjaAPI(urls_namespace="csrf_ON", csrf=True)
Expand Down
1 change: 0 additions & 1 deletion tests/test_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ def test_exceptions(route, status_code, json):
assert response.json() == json


@pytest.mark.skipif(django.VERSION < (3, 1), reason="requires django 3.1 or higher")
@pytest.mark.asyncio
async def test_asyncio_exceptions():
api = NinjaAPI()
Expand Down
3 changes: 0 additions & 3 deletions tests/test_orm_schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,9 +213,6 @@ class Meta:
}


@pytest.mark.skipif(
django.VERSION < (3, 1), reason="json field introduced in django 3.1"
)
def test_django_31_fields():
class ModelNewFields(models.Model):
jsonfield = models.JSONField()
Expand Down
Loading

0 comments on commit 2c4569a

Please sign in to comment.