Repository: rasterio/rasterio

Issue:
Set minimum GDAL version
We need to clarify our minimum supported version of GDAL.

The README states >= 1.9

Our test suite starts at 1.11.5

We have tests and version-dependent functionality that vary a bit within the range 1.9 to 1.11.

So - we need to choose the minimum version, and then we need to start our test suite at that version.  Is it 1.9, 1.10, or 1.11?

We probably should raise an exception if we detect a version lower than our supported is being used.

I can run with this change once we've settled on the version.

\cc @sgillies @geowurster 



Discussion:
@brendan-ward I've been using UbuntuGIS as a guide and it has GDAL 2.1.3 (for trusty and xenial) in its stable PPA along with 1.10 (for precise): https://launchpad.net/~ubuntugis/+archive/ubuntu/ppa.

Radically, I think we could even require GDAL 2.1 or higher! This would cut off developers who can't upgrade their servers, of course. I don't know how many of these developers are out there or how serious a problem this is actually is in the age of containers and "serverless" web apps. A survey might be warranted.

For now, I think we should switch 1.11 for 1.10 in our test matrix, to cover the 1.10 on precise case and make 1.10 our minimum. UbuntuGIS has passed on 1.11, we may be able to as well.

I would be interested in a survey as well and maybe some download numbers from OSGeo, GitHub, and UbuntuGIS.  I don't think we can responsibly drop support for GDAL 1.0 until Rasterio 2.0.

I see a lot of bug fixes in [GDAL `1.11.0` changelog](https://trac.osgeo.org/gdal/wiki/Release/1.11.0-News) that are probably compelling reasons to upgrade and I'm surprised that UbuntuGIS skipped that version.  The [last version](https://trac.osgeo.org/gdal/wiki/DownloadSource) of 1.10 was released in August 2013 and the first version of `1.11` was released in April 2014 but GDAL 2 wasn't released until June 2015, so `1.11` and `2.0` were not released close enough together for users to skip from `1.10` directly to `2.0`.  Maybe `1.11` contains some large upgrade hurdle?

Given that information I'm in favor of dropping support for `1.9`, but continuing to test on the most recent releases of `1.10` and `1.11`.  As far as GDAL 2 goes, we probably could require GDAL 2.1 at this point but I would like to see some user numbers.

Resolving patch:
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -84,8 +84,7 @@ def copy_data_tree(datadir, destdir):
     import numpy as np
     include_dirs.append(np.get_include())
 except ImportError:
-    log.critical("Numpy and its headers are required to run setup(). Exiting.")
-    sys.exit(1)
+    sys.exit("ERROR: Numpy and its headers are required to run setup().")
 
 try:
     gdal_config = os.environ.get('GDAL_CONFIG', 'gdal-config')
@@ -133,15 +132,18 @@ def copy_data_tree(datadir, destdir):
              gdalversion)
 
 if not gdalversion:
-    log.fatal("A GDAL API version must be specified. Provide a path "
+    sys.exit("ERROR: A GDAL API version must be specified. Provide a path "
               "to gdal-config using a GDAL_CONFIG environment variable "
               "or use a GDAL_VERSION environment variable.")
-    sys.exit(1)
 
 gdal_version_parts = gdalversion.split('.')
 gdal_major_version = int(gdal_version_parts[0])
 gdal_minor_version = int(gdal_version_parts[1])
 
+if gdal_major_version == 1 and gdal_minor_version < 11:
+    sys.exit("ERROR: GDAL >= 1.11 is required for rasterio.  "
+             "Please upgrade GDAL.")
+
 # Conditionally copy the GDAL data. To be used in conjunction with
 # the bdist_wheel command to make self-contained binary wheels.
 if os.environ.get('PACKAGE_DATA'):
@@ -190,9 +192,6 @@ def run(self):
     'extra_link_args': extra_link_args,
     'define_macros': []}
 
-#        ('GDAL_MAJOR_VERSION', gdal_major_version),
-#        ('GDAL_MINOR_VERSION', gdal_minor_version)]}
-
 if not os.name == "nt":
     # These options fail on Windows if using Visual Studio
     ext_options['extra_compile_args'] = ['-Wno-unused-parameter',
@@ -220,10 +219,9 @@ def run(self):
     log.info("MANIFEST.in found, presume a repo, cythonizing...")
 
     if not cythonize:
-        log.critical(
-            "Cython.Build.cythonize not found. "
+        sys.exit(
+            "ERROR: Cython.Build.cythonize not found. "
             "Cython is required to build from a repo.")
-        sys.exit(1)
 
     # Copy the GDAL version-specific shim module to _shim.pyx.
     if gdal_major_version == 2 and gdal_minor_version >= 1:


Test patch:
diff --git a/tests/conftest.py b/tests/conftest.py
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -504,14 +504,6 @@ def path_zip_file():
     gdal_version.major != 1,
     reason="Only relevant for GDAL 1.x")
 
-requires_less_than_gdal110 = pytest.mark.skipif(
-    gdal_version.at_least('1.10'),
-    reason="Requires GDAL 1.9.x or earlier")
-
-requires_gdal110 = pytest.mark.skipif(
-    not gdal_version.at_least('1.10'),
-    reason="Requires GDAL 1.10.x")
-
 requires_gdal2 = pytest.mark.skipif(
     not gdal_version.major >= 2,
     reason="Requires GDAL 2.x")
diff --git a/tests/test_rio_edit_info.py b/tests/test_rio_edit_info.py
--- a/tests/test_rio_edit_info.py
+++ b/tests/test_rio_edit_info.py
@@ -16,7 +16,7 @@
 from rasterio.rio.main import main_group
 import rasterio.shutil
 
-from .conftest import requires_gdal110, requires_less_than_gdal110, requires_gdal21
+from .conftest import requires_gdal21
 
 
 PARAM_HANDLER = {
@@ -57,32 +57,6 @@ def test_delete_crs_exclusive_opts(data):
     assert result.exit_code == 2
 
 
-@requires_gdal110
-def test_unset_crs(data):
-    runner = CliRunner()
-    inputfile = str(data.join('RGB.byte.tif'))
-    result = runner.invoke(main_group,
-                           ['edit-info', inputfile, '--unset-crs'])
-    assert result.exit_code == 0
-    with rasterio.open(inputfile) as src:
-        assert src.crs is None
-
-@requires_less_than_gdal110
-def test_unset_crs_gdal19(data):
-    """unsetting crs doesn't work for geotiff and gdal 1.9
-    and should emit an warning"""
-    runner = CliRunner()
-    inputfile = str(data.join('RGB.byte.tif'))
-    with rasterio.open(inputfile) as src:
-        orig_crs = src.crs
-    with pytest.warns(UserWarning):
-        result = runner.invoke(main_group,
-                               ['edit-info', inputfile, '--unset-crs'])
-    assert result.exit_code == 0
-    with rasterio.open(inputfile) as src:
-        assert src.crs == orig_crs  # nochange
-
-
 def test_edit_nodata_err(data):
     runner = CliRunner()
     inputfile = str(data.join('RGB.byte.tif'))
diff --git a/tests/test_rio_info.py b/tests/test_rio_info.py
--- a/tests/test_rio_info.py
+++ b/tests/test_rio_info.py
@@ -8,7 +8,7 @@
 from rasterio.rio.main import main_group
 from rasterio.env import GDALVersion
 
-from .conftest import requires_gdal110, requires_less_than_gdal110, requires_gdal21
+from .conftest import requires_gdal21
 
 
 with rasterio.Env() as env:
@@ -33,33 +33,6 @@ def test_delete_crs_exclusive_opts(data):
     assert result.exit_code == 2
 
 
-@requires_gdal110
-def test_unset_crs(data):
-    runner = CliRunner()
-    inputfile = str(data.join('RGB.byte.tif'))
-    result = runner.invoke(main_group,
-                           ['edit-info', inputfile, '--unset-crs'])
-    assert result.exit_code == 0
-    with rasterio.open(inputfile) as src:
-        assert src.crs is None
-
-
-@requires_less_than_gdal110
-def test_unset_crs_gdal19(data):
-    """unsetting crs doesn't work for geotiff and gdal 1.9
-    and should emit an warning"""
-    runner = CliRunner()
-    inputfile = str(data.join('RGB.byte.tif'))
-    with rasterio.open(inputfile) as src:
-        orig_crs = src.crs
-    with pytest.warns(UserWarning):
-        result = runner.invoke(main_group,
-                               ['edit-info', inputfile, '--unset-crs'])
-    assert result.exit_code == 0
-    with rasterio.open(inputfile) as src:
-        assert src.crs == orig_crs  # nochange
-
-
 def test_edit_nodata_err(data):
     runner = CliRunner()
     inputfile = str(data.join('RGB.byte.tif'))
diff --git a/tests/test_warp.py b/tests/test_warp.py
--- a/tests/test_warp.py
+++ b/tests/test_warp.py
@@ -37,13 +37,9 @@ def flatten_coords(coordinates):
 def supported_resampling(method):
     if method == Resampling.gauss:
         return False
-    gdal110plus_only = (
-        Resampling.mode, Resampling.average)
     gdal2plus_only = (
         Resampling.max, Resampling.min, Resampling.med,
         Resampling.q1, Resampling.q3)
-    if not gdal_version.at_least('1.10'):
-        return method not in gdal2plus_only and method not in gdal110plus_only
     if not gdal_version.at_least('2.0'):
         return method not in gdal2plus_only
     return True