From 3ae4344bbd3b5e8bcb039bf701f53b68b317f57b Mon Sep 17 00:00:00 2001 From: Claude Paroz Date: Wed, 7 Apr 2021 17:38:37 +0200 Subject: [PATCH] Dropped support for GEOS 3.5 and GDAL 2.0. --- django/contrib/gis/gdal/prototypes/raster.py | 13 +++--------- django/contrib/gis/gdal/raster/band.py | 2 -- django/contrib/gis/gdal/raster/source.py | 2 -- docs/ref/contrib/gis/install/geolibs.txt | 12 +++++------ docs/releases/4.0.txt | 2 ++ tests/gis_tests/gdal_tests/test_raster.py | 21 ++++---------------- 6 files changed, 14 insertions(+), 38 deletions(-) diff --git a/django/contrib/gis/gdal/prototypes/raster.py b/django/contrib/gis/gdal/prototypes/raster.py index 32b4f70f11d..600493a442c 100644 --- a/django/contrib/gis/gdal/prototypes/raster.py +++ b/django/contrib/gis/gdal/prototypes/raster.py @@ -5,7 +5,7 @@ related data structures. from ctypes import POINTER, c_bool, c_char_p, c_double, c_int, c_void_p from functools import partial -from django.contrib.gis.gdal.libgdal import GDAL_VERSION, std_call +from django.contrib.gis.gdal.libgdal import std_call from django.contrib.gis.gdal.prototypes.generation import ( chararray_output, const_string_output, double_output, int_output, void_output, voidptr_output, @@ -40,6 +40,7 @@ copy_ds = voidptr_output( add_band_ds = void_output(std_call('GDALAddBand'), [c_void_p, c_int]) get_ds_description = const_string_output(std_call('GDALGetDescription'), [c_void_p]) get_ds_driver = voidptr_output(std_call('GDALGetDatasetDriver'), [c_void_p]) +get_ds_info = const_string_output(std_call('GDALInfo'), [c_void_p, c_void_p]) get_ds_xsize = int_output(std_call('GDALGetRasterXSize'), [c_void_p]) get_ds_ysize = int_output(std_call('GDALGetRasterYSize'), [c_void_p]) get_ds_raster_count = int_output(std_call('GDALGetRasterCount'), [c_void_p]) @@ -56,11 +57,6 @@ get_ds_metadata_item = const_string_output(std_call('GDALGetMetadataItem'), [c_v set_ds_metadata_item = const_string_output(std_call('GDALSetMetadataItem'), [c_void_p, c_char_p, c_char_p, c_char_p]) free_dsl = void_output(std_call('CSLDestroy'), [POINTER(c_char_p)], errcheck=False) -if GDAL_VERSION >= (2, 1): - get_ds_info = const_string_output(std_call('GDALInfo'), [c_void_p, c_void_p]) -else: - get_ds_info = None - # Raster Band Routines band_io = void_output( std_call('GDALRasterIO'), @@ -75,10 +71,7 @@ get_band_datatype = int_output(std_call('GDALGetRasterDataType'), [c_void_p]) get_band_color_interp = int_output(std_call('GDALGetRasterColorInterpretation'), [c_void_p]) get_band_nodata_value = double_output(std_call('GDALGetRasterNoDataValue'), [c_void_p, POINTER(c_int)]) set_band_nodata_value = void_output(std_call('GDALSetRasterNoDataValue'), [c_void_p, c_double]) -if GDAL_VERSION >= (2, 1): - delete_band_nodata_value = void_output(std_call('GDALDeleteRasterNoDataValue'), [c_void_p]) -else: - delete_band_nodata_value = None +delete_band_nodata_value = void_output(std_call('GDALDeleteRasterNoDataValue'), [c_void_p]) get_band_statistics = void_output( std_call('GDALGetRasterStatistics'), [ diff --git a/django/contrib/gis/gdal/raster/band.py b/django/contrib/gis/gdal/raster/band.py index 61c65352130..6739a52628b 100644 --- a/django/contrib/gis/gdal/raster/band.py +++ b/django/contrib/gis/gdal/raster/band.py @@ -152,8 +152,6 @@ class GDALBand(GDALRasterBase): Set the nodata value for this band. """ if value is None: - if not capi.delete_band_nodata_value: - raise ValueError('GDAL >= 2.1 required to delete nodata values.') capi.delete_band_nodata_value(self._ptr) elif not isinstance(value, (int, float)): raise ValueError('Nodata value must be numeric or None.') diff --git a/django/contrib/gis/gdal/raster/source.py b/django/contrib/gis/gdal/raster/source.py index d3129368e23..4d2f0dd9483 100644 --- a/django/contrib/gis/gdal/raster/source.py +++ b/django/contrib/gis/gdal/raster/source.py @@ -500,6 +500,4 @@ class GDALRaster(GDALRasterBase): Return information about this raster in a string format equivalent to the output of the gdalinfo command line utility. """ - if not capi.get_ds_info: - raise ValueError('GDAL ≥ 2.1 is required for using the info property.') return capi.get_ds_info(self.ptr, None).decode() diff --git a/docs/ref/contrib/gis/install/geolibs.txt b/docs/ref/contrib/gis/install/geolibs.txt index 818e5abaa4b..058653c7d21 100644 --- a/docs/ref/contrib/gis/install/geolibs.txt +++ b/docs/ref/contrib/gis/install/geolibs.txt @@ -5,28 +5,26 @@ Installing Geospatial libraries GeoDjango uses and/or provides interfaces for the following open source geospatial libraries: -======================== ==================================== ================================ ====================================== +======================== ==================================== ================================ ================================= Program Description Required Supported Versions -======================== ==================================== ================================ ====================================== -:doc:`GEOS <../geos>` Geometry Engine Open Source Yes 3.9, 3.8, 3.7, 3.6, 3.5 +======================== ==================================== ================================ ================================= +:doc:`GEOS <../geos>` Geometry Engine Open Source Yes 3.9, 3.8, 3.7, 3.6 `PROJ`_ Cartographic Projections library Yes (PostgreSQL and SQLite only) 7.x. 6.x, 5.x, 4.x -:doc:`GDAL <../gdal>` Geospatial Data Abstraction Library Yes 3.2, 3.1, 3.0, 2.4, 2.3, 2.2, 2.1, 2.0 +:doc:`GDAL <../gdal>` Geospatial Data Abstraction Library Yes 3.2, 3.1, 3.0, 2.4, 2.3, 2.2, 2.1 :doc:`GeoIP <../geoip2>` IP-based geolocation library No 2 `PostGIS`__ Spatial extensions for PostgreSQL Yes (PostgreSQL only) 3.0, 2.5, 2.4 `SpatiaLite`__ Spatial extensions for SQLite Yes (SQLite only) 4.3 -======================== ==================================== ================================ ====================================== +======================== ==================================== ================================ ================================= Note that older or more recent versions of these libraries *may* also work totally fine with GeoDjango. Your mileage may vary. .. Libs release dates: - GEOS 3.5.0 2015-08-15 GEOS 3.6.0 2016-10-25 GEOS 3.7.0 2018-09-10 GEOS 3.8.0 2019-10-10 GEOS 3.9.0 2020-12-14 - GDAL 2.0.0 2015-06 GDAL 2.1.0 2016-04 GDAL 2.2.0 2017-05 GDAL 2.3.0 2018-05 diff --git a/docs/releases/4.0.txt b/docs/releases/4.0.txt index a3429b6baf3..ab06cbb40f5 100644 --- a/docs/releases/4.0.txt +++ b/docs/releases/4.0.txt @@ -314,6 +314,8 @@ backends. * Support for PostGIS 2.3 is removed. +* Support for GDAL 2.0 and GEOS 3.5 is removed. + Dropped support for PostgreSQL 9.6 ---------------------------------- diff --git a/tests/gis_tests/gdal_tests/test_raster.py b/tests/gis_tests/gdal_tests/test_raster.py index 7f690759f63..6858abc4d89 100644 --- a/tests/gis_tests/gdal_tests/test_raster.py +++ b/tests/gis_tests/gdal_tests/test_raster.py @@ -4,7 +4,7 @@ import struct import tempfile from unittest import mock -from django.contrib.gis.gdal import GDAL_VERSION, GDALRaster, SpatialReference +from django.contrib.gis.gdal import GDALRaster, SpatialReference from django.contrib.gis.gdal.error import GDALException from django.contrib.gis.gdal.raster.band import GDALBand from django.contrib.gis.shortcuts import numpy @@ -270,8 +270,6 @@ class GDALRasterTests(SimpleTestCase): self.assertEqual(result, [23] * 4) def test_set_nodata_none_on_raster_creation(self): - if GDAL_VERSION < (2, 1): - self.skipTest("GDAL >= 2.1 is required for this test.") # Create raster without data and without nodata value. rast = GDALRaster({ 'datatype': 1, @@ -322,11 +320,6 @@ class GDALRasterTests(SimpleTestCase): self.assertNotIn('OWNER', source.metadata['DEFAULT']) def test_raster_info_accessor(self): - if GDAL_VERSION < (2, 1): - msg = 'GDAL ≥ 2.1 is required for using the info property.' - with self.assertRaisesMessage(ValueError, msg): - self.rs.info - return infos = self.rs.info # Data info_lines = [line.strip() for line in infos.split('\n') if line.strip() != ''] @@ -389,8 +382,7 @@ class GDALRasterTests(SimpleTestCase): compressed = GDALRaster(compressed.name) self.assertEqual(compressed.metadata['IMAGE_STRUCTURE']['COMPRESSION'], 'PACKBITS',) self.assertEqual(compressed.bands[0].metadata['IMAGE_STRUCTURE']['PIXELTYPE'], 'SIGNEDBYTE') - if GDAL_VERSION >= (2, 1): - self.assertIn('Block=40x23', compressed.info) + self.assertIn('Block=40x23', compressed.info) def test_raster_warp(self): # Create in memory raster @@ -796,13 +788,8 @@ class GDALBandTests(SimpleTestCase): 'height': 1, 'bands': [{'data': [0], 'nodata_value': 1}], }) - if GDAL_VERSION < (2, 1): - msg = 'GDAL >= 2.1 required to delete nodata values.' - with self.assertRaisesMessage(ValueError, msg): - rsmem.bands[0].nodata_value = None - else: - rsmem.bands[0].nodata_value = None - self.assertIsNone(rsmem.bands[0].nodata_value) + rsmem.bands[0].nodata_value = None + self.assertIsNone(rsmem.bands[0].nodata_value) def test_band_data_replication(self): band = GDALRaster({