From 3c755794dfb452f3a44cee24b89cefaa42dd1a4e Mon Sep 17 00:00:00 2001 From: Bruno Alla Date: Tue, 8 Apr 2025 09:29:40 +0100 Subject: [PATCH] Cleanup dependencies and conditions for unsupported Python versions (#9681) * Remove optional install backports.zoneinfo for unsupported Python versions and associated code * Remove conditions in tests for unsupported Python versions * Remove condition for unsupported Python versions --- rest_framework/utils/serializer_helpers.py | 28 ++++++++++------------ setup.py | 2 +- tests/test_fields.py | 11 +-------- tests/test_generics.py | 14 ----------- tests/test_model_serializer.py | 5 ---- tests/test_request.py | 5 ---- tests/test_response.py | 7 ------ tests/test_serializer.py | 9 ------- tests/test_serializer_lists.py | 6 ----- 9 files changed, 15 insertions(+), 72 deletions(-) diff --git a/rest_framework/utils/serializer_helpers.py b/rest_framework/utils/serializer_helpers.py index 0e59aa66a..e6bd84f30 100644 --- a/rest_framework/utils/serializer_helpers.py +++ b/rest_framework/utils/serializer_helpers.py @@ -1,5 +1,4 @@ import contextlib -import sys from collections.abc import Mapping, MutableMapping from django.utils.encoding import force_str @@ -29,21 +28,20 @@ class ReturnDict(dict): # but preserve the raw data. return (dict, (dict(self),)) - if sys.version_info >= (3, 9): - # These are basically copied from OrderedDict, with `serializer` added. - def __or__(self, other): - if not isinstance(other, dict): - return NotImplemented - new = self.__class__(self, serializer=self.serializer) - new.update(other) - return new + # These are basically copied from OrderedDict, with `serializer` added. + def __or__(self, other): + if not isinstance(other, dict): + return NotImplemented + new = self.__class__(self, serializer=self.serializer) + new.update(other) + return new - def __ror__(self, other): - if not isinstance(other, dict): - return NotImplemented - new = self.__class__(other, serializer=self.serializer) - new.update(self) - return new + def __ror__(self, other): + if not isinstance(other, dict): + return NotImplemented + new = self.__class__(other, serializer=self.serializer) + new.update(self) + return new class ReturnList(list): diff --git a/setup.py b/setup.py index 952b5f50a..e5e78c2c7 100755 --- a/setup.py +++ b/setup.py @@ -81,7 +81,7 @@ setup( author_email='tom@tomchristie.com', # SEE NOTE BELOW (*) packages=find_packages(exclude=['tests*']), include_package_data=True, - install_requires=["django>=4.2", 'backports.zoneinfo;python_version<"3.9"'], + install_requires=["django>=4.2"], python_requires=">=3.9", zip_safe=False, classifiers=[ diff --git a/tests/test_fields.py b/tests/test_fields.py index 1403a6a35..7c55dfcc5 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -2,12 +2,12 @@ import datetime import math import os import re -import sys import uuid import warnings from decimal import ROUND_DOWN, ROUND_UP, Decimal from enum import auto from unittest.mock import patch +from zoneinfo import ZoneInfo import pytest @@ -30,11 +30,6 @@ from rest_framework.fields import ( ) from tests.models import UUIDForeignKeyTarget -if sys.version_info >= (3, 9): - from zoneinfo import ZoneInfo -else: - from backports.zoneinfo import ZoneInfo - utc = datetime.timezone.utc # Tests for helper functions. @@ -641,10 +636,6 @@ class Test5087Regression: class TestTyping(TestCase): - @pytest.mark.skipif( - sys.version_info < (3, 7), - reason="subscriptable classes requires Python 3.7 or higher", - ) def test_field_is_subscriptable(self): assert serializers.Field is serializers.Field["foo"] diff --git a/tests/test_generics.py b/tests/test_generics.py index 9990389c9..8748e8f17 100644 --- a/tests/test_generics.py +++ b/tests/test_generics.py @@ -1,5 +1,3 @@ -import sys - import pytest from django.db import models from django.http import Http404 @@ -703,23 +701,11 @@ class TestSerializer(TestCase): class TestTyping(TestCase): - @pytest.mark.skipif( - sys.version_info < (3, 7), - reason="subscriptable classes requires Python 3.7 or higher", - ) def test_genericview_is_subscriptable(self): assert generics.GenericAPIView is generics.GenericAPIView["foo"] - @pytest.mark.skipif( - sys.version_info < (3, 7), - reason="subscriptable classes requires Python 3.7 or higher", - ) def test_listview_is_subscriptable(self): assert generics.ListAPIView is generics.ListAPIView["foo"] - @pytest.mark.skipif( - sys.version_info < (3, 7), - reason="subscriptable classes requires Python 3.7 or higher", - ) def test_instanceview_is_subscriptable(self): assert generics.RetrieveAPIView is generics.RetrieveAPIView["foo"] diff --git a/tests/test_model_serializer.py b/tests/test_model_serializer.py index f1f9518cb..eac51ae70 100644 --- a/tests/test_model_serializer.py +++ b/tests/test_model_serializer.py @@ -9,7 +9,6 @@ import datetime import decimal import json # noqa import re -import sys import tempfile import pytest @@ -397,10 +396,6 @@ class TestDurationFieldMapping(TestCase): fields = '__all__' expected = dedent(""" - TestSerializer(): - id = IntegerField(label='ID', read_only=True) - duration_field = DurationField(max_value=datetime.timedelta(3), min_value=datetime.timedelta(1)) - """) if sys.version_info < (3, 7) else dedent(""" TestSerializer(): id = IntegerField(label='ID', read_only=True) duration_field = DurationField(max_value=datetime.timedelta(days=3), min_value=datetime.timedelta(days=1)) diff --git a/tests/test_request.py b/tests/test_request.py index 4263f2682..fe3efd96b 100644 --- a/tests/test_request.py +++ b/tests/test_request.py @@ -3,7 +3,6 @@ Tests for content parsing, and form-overloaded content parsing. """ import copy import os.path -import sys import tempfile import pytest @@ -375,9 +374,5 @@ class TestDeepcopy(TestCase): class TestTyping(TestCase): - @pytest.mark.skipif( - sys.version_info < (3, 7), - reason="subscriptable classes requires Python 3.7 or higher", - ) def test_request_is_subscriptable(self): assert Request is Request["foo"] diff --git a/tests/test_response.py b/tests/test_response.py index 00b5691b0..a5eeae882 100644 --- a/tests/test_response.py +++ b/tests/test_response.py @@ -1,6 +1,3 @@ -import sys - -import pytest from django.test import TestCase, override_settings from django.urls import include, path, re_path @@ -289,9 +286,5 @@ class Issue807Tests(TestCase): class TestTyping(TestCase): - @pytest.mark.skipif( - sys.version_info < (3, 7), - reason="subscriptable classes requires Python 3.7 or higher", - ) def test_response_is_subscriptable(self): assert Response is Response["foo"] diff --git a/tests/test_serializer.py b/tests/test_serializer.py index 10fa8afb9..cefa2ee38 100644 --- a/tests/test_serializer.py +++ b/tests/test_serializer.py @@ -1,7 +1,6 @@ import inspect import pickle import re -import sys from collections import ChainMap from collections.abc import Mapping @@ -205,10 +204,6 @@ class TestSerializer: exceptions.ErrorDetail(string='Raised error', code='invalid') ]} - @pytest.mark.skipif( - sys.version_info < (3, 7), - reason="subscriptable classes requires Python 3.7 or higher", - ) def test_serializer_is_subscriptable(self): assert serializers.Serializer is serializers.Serializer["foo"] @@ -743,10 +738,6 @@ class TestDeclaredFieldInheritance: class Test8301Regression: - @pytest.mark.skipif( - sys.version_info < (3, 9), - reason="dictionary union operator requires Python 3.9 or higher", - ) def test_ReturnDict_merging(self): # Serializer.data returns ReturnDict, this is essentially a test for that. diff --git a/tests/test_serializer_lists.py b/tests/test_serializer_lists.py index 4070de7a5..42ebf4771 100644 --- a/tests/test_serializer_lists.py +++ b/tests/test_serializer_lists.py @@ -1,5 +1,3 @@ -import sys - import pytest from django.http import QueryDict from django.utils.datastructures import MultiValueDict @@ -60,10 +58,6 @@ class TestListSerializer: assert serializer.is_valid() assert serializer.validated_data == expected_output - @pytest.mark.skipif( - sys.version_info < (3, 7), - reason="subscriptable classes requires Python 3.7 or higher", - ) def test_list_serializer_is_subscriptable(self): assert serializers.ListSerializer is serializers.ListSerializer["foo"]