diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6f1d2f92..f0f6491c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,8 +29,6 @@ jobs: fail-fast: false matrix: env: - - python: '3.8' - TOXENV: py38-django42-djangorestframework314 - python: '3.9' TOXENV: py39-django42-djangorestframework314 - python: '3.10' diff --git a/rest_framework_gis/__init__.py b/rest_framework_gis/__init__.py index 4e805db2..b2d6732d 100644 --- a/rest_framework_gis/__init__.py +++ b/rest_framework_gis/__init__.py @@ -3,12 +3,12 @@ def get_version(): - version = '%s.%s' % (VERSION[0], VERSION[1]) + version = f'{VERSION[0]}.{VERSION[1]}' if VERSION[2]: - version = '%s.%s' % (version, VERSION[2]) + version = f'{version}.{VERSION[2]}' if VERSION[3:] == ('alpha', 0): version = '%s pre-alpha' % version else: if VERSION[3] != 'final': - version = '%s %s' % (version, VERSION[3]) + version = f'{version} {VERSION[3]}' return version diff --git a/rest_framework_gis/fields.py b/rest_framework_gis/fields.py index d22a7e78..bb0faa65 100644 --- a/rest_framework_gis/fields.py +++ b/rest_framework_gis/fields.py @@ -72,9 +72,7 @@ def to_internal_value(self, value): ) ) except (ValueError, TypeError, GDALException) as e: - raise ValidationError( - _('Unable to convert to python object: {}'.format(str(e))) - ) + raise ValidationError(_(f'Unable to convert to python object: {str(e)}')) def validate_empty_values(self, data): if data == '': @@ -127,8 +125,7 @@ def to_representation(self, value): class GeoJsonDict(OrderedDict): """ - Used for serializing GIS values to GeoJSON values - TODO: remove this when support for python 2.6/2.7 will be dropped + Used for serializing GIS values to GeoJSON values. """ def __init__(self, *args, **kwargs): diff --git a/rest_framework_gis/filters.py b/rest_framework_gis/filters.py index bc04872d..34311588 100644 --- a/rest_framework_gis/filters.py +++ b/rest_framework_gis/filters.py @@ -46,7 +46,7 @@ def get_filter_bbox(self, request): p1x, p1y, p2x, p2y = (float(n) for n in bbox_string.split(',')) except ValueError: raise ParseError( - 'Invalid bbox string supplied for parameter {0}'.format(self.bbox_param) + f'Invalid bbox string supplied for parameter {self.bbox_param}' ) x = Polygon.from_bbox((p1x, p1y, p2x, p2y)) @@ -66,7 +66,7 @@ def filter_queryset(self, request, queryset, view): bbox = self.get_filter_bbox(request) if not bbox: return queryset - return queryset.filter(Q(**{'%s__%s' % (filter_field, geoDjango_filter): bbox})) + return queryset.filter(Q(**{f'{filter_field}__{geoDjango_filter}': bbox})) def get_schema_operation_parameters(self, view): return [ @@ -127,7 +127,7 @@ def get_filter_bbox(self, request): z, x, y = (int(n) for n in tile_string.split('/')) except ValueError: raise ParseError( - 'Invalid tile string supplied for parameter {0}'.format(self.tile_param) + f'Invalid tile string supplied for parameter {self.tile_param}' ) bbox = Polygon.from_bbox(tile_edges(x, y, z)) @@ -158,7 +158,7 @@ def get_filter_point(self, request, **kwargs): (x, y) = (float(n) for n in point_string.split(',')) except ValueError: raise ParseError( - 'Invalid geometry string supplied for parameter {0}'.format( + 'Invalid geometry string supplied for parameter {}'.format( self.point_param ) ) @@ -212,7 +212,7 @@ def filter_queryset(self, request, queryset, view): dist = float(dist_string) except ValueError: raise ParseError( - 'Invalid distance string supplied for parameter {0}'.format( + 'Invalid distance string supplied for parameter {}'.format( self.dist_param ) ) @@ -222,7 +222,7 @@ def filter_queryset(self, request, queryset, view): dist = self.dist_to_deg(dist, point[1]) return queryset.filter( - Q(**{'%s__%s' % (filter_field, geoDjango_filter): (point, dist)}) + Q(**{f'{filter_field}__{geoDjango_filter}': (point, dist)}) ) def get_schema_operation_parameters(self, view): diff --git a/rest_framework_gis/schema.py b/rest_framework_gis/schema.py index 4364ca4b..18a6956e 100644 --- a/rest_framework_gis/schema.py +++ b/rest_framework_gis/schema.py @@ -101,9 +101,7 @@ def _map_geo_field(self, serializer, geo_field_name): try: return self.GEO_FIELD_TO_SCHEMA[geo_field.__class__] except KeyError: - warnings.warn( - "Geometry generation for {field} is not supported.".format(field=field) - ) + warnings.warn(f"Geometry generation for {field} is not supported.") return {} def map_field(self, field): diff --git a/rest_framework_gis/serializers.py b/rest_framework_gis/serializers.py index 1b808e44..3663196c 100644 --- a/rest_framework_gis/serializers.py +++ b/rest_framework_gis/serializers.py @@ -81,9 +81,7 @@ def __init__(self, *args, **kwargs): def check_excludes(field_name, field_role): """make sure the field is not excluded""" if hasattr(meta, 'exclude') and field_name in meta.exclude: - raise ImproperlyConfigured( - "You cannot exclude your '{0}'.".format(field_role) - ) + raise ImproperlyConfigured(f"You cannot exclude your '{field_role}'.") def add_to_fields(field_name): """Make sure the field is included in the fields""" diff --git a/setup.py b/setup.py index 4b0c6d92..6871b5f8 100644 --- a/setup.py +++ b/setup.py @@ -36,7 +36,6 @@ 'Framework :: Django', 'Programming Language :: Python', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', 'Programming Language :: Python :: 3.11', diff --git a/tests/django_restframework_gis_tests/migrations/0001_initial.py b/tests/django_restframework_gis_tests/migrations/0001_initial.py index f33b4b0c..95c34b4c 100644 --- a/tests/django_restframework_gis_tests/migrations/0001_initial.py +++ b/tests/django_restframework_gis_tests/migrations/0001_initial.py @@ -1,6 +1,4 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.9.4 on 2016-04-01 17:00 -from __future__ import unicode_literals import django.contrib.gis.db.models.fields from django.db import migrations, models diff --git a/tests/django_restframework_gis_tests/test_bbox.py b/tests/django_restframework_gis_tests/test_bbox.py index 60678a58..50a3c456 100644 --- a/tests/django_restframework_gis_tests/test_bbox.py +++ b/tests/django_restframework_gis_tests/test_bbox.py @@ -53,7 +53,7 @@ def test_list(self): elif fid == 2: self.assertEqual(feature['bbox'], self.bl2.bbox_geometry.extent) else: - self.fail("Unexpected id: {0}".format(fid)) + self.fail(f"Unexpected id: {fid}") BoxedLocation.objects.all().delete() def test_post_location_list_geojson(self): diff --git a/tests/django_restframework_gis_tests/test_fields.py b/tests/django_restframework_gis_tests/test_fields.py index 0b1b9111..b081529d 100644 --- a/tests/django_restframework_gis_tests/test_fields.py +++ b/tests/django_restframework_gis_tests/test_fields.py @@ -116,7 +116,7 @@ class BaseTestCase(TestCase): @staticmethod def get_instance(data_dict): - class Model(object): + class Model: def __init__(self, geojson_dict): self.geometry = GEOSGeometry(json.dumps(geojson_dict)) diff --git a/tests/django_restframework_gis_tests/test_filters.py b/tests/django_restframework_gis_tests/test_filters.py index 944385f8..2f1630af 100644 --- a/tests/django_restframework_gis_tests/test_filters.py +++ b/tests/django_restframework_gis_tests/test_filters.py @@ -273,13 +273,13 @@ def test_DistanceToPointFilter_filtering(self): distance = 5000 # meters point_on_alcatraz = [-122.4222, 37.82667] - url_params = '?dist=%0.4f&point=hello&format=json' % (distance,) + url_params = f'?dist={distance:0.4f}&point=hello&format=json' response = self.client.get( - '%s%s' % (self.location_within_distance_of_point_list_url, url_params) + f'{self.location_within_distance_of_point_list_url}{url_params}' ) self.assertEqual(response.status_code, 400) - url_params = '?dist=%0.4f&point=%0.4f,%0.4f&format=json' % ( + url_params = '?dist={:0.4f}&point={:0.4f},{:0.4f}&format=json'.format( distance, point_on_alcatraz[0], point_on_alcatraz[1], @@ -298,7 +298,7 @@ def test_DistanceToPointFilter_filtering(self): # Make sure we only get back the ones within the distance response = self.client.get( - '%s%s' % (self.location_within_distance_of_point_list_url, url_params) + f'{self.location_within_distance_of_point_list_url}{url_params}' ) self.assertEqual(len(response.data['features']), 1) for result in response.data['features']: @@ -306,13 +306,13 @@ def test_DistanceToPointFilter_filtering(self): # Make sure we get back all the ones within the distance distance = 7000 - url_params = '?dist=%0.4f&point=%0.4f,%0.4f&format=json' % ( + url_params = '?dist={:0.4f}&point={:0.4f},{:0.4f}&format=json'.format( distance, point_on_alcatraz[0], point_on_alcatraz[1], ) response = self.client.get( - '%s%s' % (self.location_within_distance_of_point_list_url, url_params) + f'{self.location_within_distance_of_point_list_url}{url_params}' ) self.assertEqual(len(response.data['features']), 2) for result in response.data['features']: @@ -322,7 +322,7 @@ def test_DistanceToPointFilter_filtering(self): # Make sure we only get back the ones within the distance degrees = 0.05 - url_params = '?dist=%0.4f&point=%0.4f,%0.4f&format=json' % ( + url_params = '?dist={:0.4f}&point={:0.4f},{:0.4f}&format=json'.format( degrees, point_on_alcatraz[0], point_on_alcatraz[1], @@ -347,7 +347,7 @@ def test_DistanceToPointOrderingFilter_filtering(self): url_params = '?point=hello&format=json' response = self.client.get( - '%s%s' % (self.location_order_distance_to_point, url_params) + f'{self.location_order_distance_to_point}{url_params}' ) self.assertEqual(response.status_code, 400) @@ -380,7 +380,7 @@ def test_DistanceToPointOrderingFilter_filtering(self): url_params = '?point=%i,%i&format=json' % (point[0], point[1]) response = self.client.get( - '%s%s' % (self.location_order_distance_to_point, url_params) + f'{self.location_order_distance_to_point}{url_params}' ) self.assertEqual(len(response.data['features']), 8) self.assertEqual( @@ -399,7 +399,7 @@ def test_DistanceToPointOrderingFilter_filtering(self): url_params = '?point=%i,%i&order=desc&format=json' % (point[0], point[1]) response = self.client.get( - '%s%s' % (self.location_order_distance_to_point, url_params) + f'{self.location_order_distance_to_point}{url_params}' ) self.assertEqual(len(response.data['features']), 8) self.assertEqual( @@ -444,11 +444,9 @@ def test_GeometryField_filtering(self): except AttributeError: quoted_param = urllib.parse.quote(point_inside_ggpark_geojson) - url_params = "?contains_properly=%s" % (quoted_param,) + url_params = f"?contains_properly={quoted_param}" - response = self.client.get( - '{0}{1}'.format(self.geojson_contained_in_geometry, url_params) - ) + response = self.client.get(f'{self.geojson_contained_in_geometry}{url_params}') self.assertEqual(len(response.data), 1) geometry_response = GEOSGeometry(json.dumps(response.data[0]['geometry'])) @@ -510,7 +508,7 @@ def test_TileFilter_ValueError(self): def test_DistanceToPointFilter_filtering_none(self): url_params = '?dist=5000&point=&format=json' response = self.client.get( - '%s%s' % (self.location_within_distance_of_point_list_url, url_params) + f'{self.location_within_distance_of_point_list_url}{url_params}' ) self.assertDictEqual( response.data, {'type': 'FeatureCollection', 'features': []} @@ -521,7 +519,7 @@ def test_DistanceToPointFilter_filter_field_none(self): GeojsonLocationWithinDistanceOfPointList.distance_filter_field = None url_params = '?dist=5000&point=&format=json' response = self.client.get( - '%s%s' % (self.location_within_distance_of_point_list_url, url_params) + f'{self.location_within_distance_of_point_list_url}{url_params}' ) self.assertDictEqual( response.data, {'type': 'FeatureCollection', 'features': []} @@ -531,7 +529,7 @@ def test_DistanceToPointFilter_filter_field_none(self): def test_DistanceToPointFilter_ValueError_point(self): url_params = '?dist=500.0&point=hello&format=json' response = self.client.get( - '%s%s' % (self.location_within_distance_of_point_list_url, url_params) + f'{self.location_within_distance_of_point_list_url}{url_params}' ) self.assertEqual( response.data['detail'], @@ -541,7 +539,7 @@ def test_DistanceToPointFilter_ValueError_point(self): def test_DistanceToPointFilter_ValueError_distance(self): url_params = '?dist=wrong&point=12.0,42.0&format=json' response = self.client.get( - '%s%s' % (self.location_within_distance_of_point_list_url, url_params) + f'{self.location_within_distance_of_point_list_url}{url_params}' ) self.assertEqual( response.data['detail'], @@ -551,7 +549,7 @@ def test_DistanceToPointFilter_ValueError_distance(self): def test_DistanceToPointOrderingFilter_filtering_none(self): url_params = '?point=&format=json' response = self.client.get( - '%s%s' % (self.location_order_distance_to_point, url_params) + f'{self.location_order_distance_to_point}{url_params}' ) self.assertDictEqual( response.data, {'type': 'FeatureCollection', 'features': []} @@ -564,7 +562,7 @@ def test_DistanceToPointOrderingFilter_ordering_filter_field_none(self): GeojsonLocationOrderDistanceToPointList.distance_ordering_filter_field = None url_params = '?point=&format=json' response = self.client.get( - '%s%s' % (self.location_order_distance_to_point, url_params) + f'{self.location_order_distance_to_point}{url_params}' ) self.assertDictEqual( response.data, {'type': 'FeatureCollection', 'features': []} diff --git a/tests/django_restframework_gis_tests/test_performance.py b/tests/django_restframework_gis_tests/test_performance.py index b69cacfe..2dad1808 100644 --- a/tests/django_restframework_gis_tests/test_performance.py +++ b/tests/django_restframework_gis_tests/test_performance.py @@ -49,7 +49,7 @@ class Meta: with Timer() as t: JSONRenderer().render(serializer.data) # print results - msg = 'GeoJSON rendering of {0} objects ' 'completed in {1}'.format( + msg = 'GeoJSON rendering of {} objects ' 'completed in {}'.format( self.NUMBER_OF_LOCATIONS, t.elapsed ) - print('\n\033[95m{0}\033[0m'.format(msg)) + print(f'\n\033[95m{msg}\033[0m') diff --git a/tests/django_restframework_gis_tests/tests.py b/tests/django_restframework_gis_tests/tests.py index 3d48ab0b..28983814 100644 --- a/tests/django_restframework_gis_tests/tests.py +++ b/tests/django_restframework_gis_tests/tests.py @@ -4,7 +4,6 @@ import json import pickle -import sys from unittest import skipIf import rest_framework @@ -284,10 +283,7 @@ def test_geojson_format(self): 'geometry': {'type': 'Point', 'coordinates': [135.0, 45.0]}, } response = self.client.get(url) - if sys.version_info > (3, 0, 0): - self.assertCountEqual(json.dumps(response.data), json.dumps(expected)) - else: - self.assertItemsEqual(json.dumps(response.data), json.dumps(expected)) + self.assertCountEqual(json.dumps(response.data), json.dumps(expected)) response = self.client.get(url, headers={"accept": 'text/html'}) self.assertContains(response, "Kool geojson test") @@ -549,10 +545,6 @@ def test_geojson_HTML_widget_value_pre_drf_39(self): self.assertContains(response, '