[Git][debian-gis-team/rasterio][upstream] New upstream version 1.2.3

Bas Couwenberg gitlab at salsa.debian.org
Tue Apr 27 05:06:03 BST 2021



Bas Couwenberg pushed to branch upstream at Debian GIS Project / rasterio


Commits:
369df47b by Bas Couwenberg at 2021-04-27T05:49:05+02:00
New upstream version 1.2.3
- - - - -


20 changed files:

- .travis.yml
- CHANGES.txt
- rasterio/__init__.py
- rasterio/_env.pyx
- rasterio/_io.pyx
- rasterio/_warp.pyx
- rasterio/enums.py
- rasterio/env.py
- rasterio/errors.py
- rasterio/io.py
- rasterio/merge.py
- rasterio/rio/overview.py
- rasterio/windows.py
- + tests/data/float_raster_with_nodata.tif
- tests/test__env.py
- tests/test_enums.py
- tests/test_merge.py
- tests/test_overviews.py
- tests/test_rpcs.py
- tests/test_windows.py


Changes:

=====================================
.travis.yml
=====================================
@@ -43,7 +43,7 @@ jobs:
         PROJVERSION="6.2.1"
     - python: "3.8"
       env:
-        GDALVERSION="3.2.1"
+        GDALVERSION="3.2.2"
         PROJVERSION="7.2.1"
     - python: "3.8"
       env:


=====================================
CHANGES.txt
=====================================
@@ -1,6 +1,20 @@
 Changes
 =======
 
+1.2.3 (2021-04-26)
+------------------
+
+- Change usage of super() to be Python 3 compatible only.
+- Use numpy.isclose instead of equals when merging float data (fixes #2163).
+- The restriction on resampling methods available to overviews has been made
+  more clear with the addition of a not-yet-public _OverviewResampling enum
+  (#2157).
+- Fix a regression introduced in 1.2.2: from_bounds() can again return Windows
+  of zero height or width.
+- Search for GDAL data in installed packages is done before searching in
+  built-in locations when entering an Env, as is already done when importing
+  rasterio.env.
+
 1.2.2 (2021-04-06)
 ------------------
 


=====================================
rasterio/__init__.py
=====================================
@@ -27,7 +27,7 @@ import rasterio.enums
 import rasterio.path
 
 __all__ = ['band', 'open', 'pad', 'Env']
-__version__ = "1.2.2"
+__version__ = "1.2.3"
 __gdal_version__ = gdal_version()
 
 # Rasterio attaches NullHandler to the 'rasterio' logger and its


=====================================
rasterio/_env.pyx
=====================================
@@ -333,7 +333,7 @@ cdef class GDALEnv(ConfigEnv):
     """Configuration and driver management"""
 
     def __init__(self, **options):
-        super(GDALEnv, self).__init__(**options)
+        super().__init__(**options)
         self._have_registered_drivers = False
 
     def start(self):
@@ -350,40 +350,49 @@ cdef class GDALEnv(ConfigEnv):
                     OGRRegisterAll()
 
                     if 'GDAL_DATA' in os.environ:
+                        log.debug("GDAL_DATA found in environment.")
                         self.update_config_options(GDAL_DATA=os.environ['GDAL_DATA'])
-                        log.debug("GDAL_DATA found in environment: %r.", os.environ['GDAL_DATA'])
-
-                    # See https://github.com/mapbox/rasterio/issues/1631.
-                    elif GDALDataFinder().find_file("header.dxf"):
-                        log.debug("GDAL data files are available at built-in paths")
 
                     else:
-                        path = GDALDataFinder().search()
+                        path = GDALDataFinder().search_wheel()
 
                         if path:
+                            log.debug("GDAL data found in package: path=%r.", path)
                             self.update_config_options(GDAL_DATA=path)
-                            log.debug("GDAL_DATA not found in environment, set to %r.", path)
+
+                        # See https://github.com/mapbox/rasterio/issues/1631.
+                        elif GDALDataFinder().find_file("header.dxf"):
+                            log.debug("GDAL data files are available at built-in paths.")
+
+                        else:
+                            path = GDALDataFinder().search()
+
+                            if path:
+                                log.debug("GDAL data found in other locations: path=%r.", path)
+                                self.update_config_options(GDAL_DATA=path)
 
                     if 'PROJ_LIB' in os.environ:
-                        log.debug("PROJ_LIB found in environment: %r.", os.environ['PROJ_LIB'])
+                        log.debug("PROJ_LIB found in environment.")
                         path = os.environ["PROJ_LIB"]
                         set_proj_data_search_path(path)
 
-                    elif PROJDataFinder().search_wheel():
-                        path = PROJDataFinder().search_wheel()
-                        log.debug("PROJ data found in wheel, setting to %r.", path)
-                        set_proj_data_search_path(path)
-
-                    elif PROJDataFinder().has_data():
-                        log.debug("PROJ data files are available at built-in paths")
-
                     else:
-                        path = PROJDataFinder().search()
+                        path = PROJDataFinder().search_wheel()
 
                         if path:
-                            log.debug("PROJ data not found in environment, setting to %r.", path)
+                            log.debug("PROJ data found in package: path=%r.", path)
                             set_proj_data_search_path(path)
 
+                        elif PROJDataFinder().has_data():
+                            log.debug("PROJ data files are available at built-in paths.")
+
+                        else:
+                            path = PROJDataFinder().search()
+
+                            if path:
+                                log.debug("PROJ data found in other locations: path=%r.", path)
+                                set_proj_data_search_path(path)
+
                     if driver_count() == 0:
                         CPLPopErrorHandler()
                         raise ValueError("Drivers not registered.")
@@ -394,7 +403,7 @@ cdef class GDALEnv(ConfigEnv):
                     # actually makes it this far.
                     self._have_registered_drivers = True
 
-        log.debug("Started GDALEnv %r.", self)
+        log.debug("Started GDALEnv: self=%r.", self)
 
     def stop(self):
         # NB: do not restore the CPL error handler to its default


=====================================
rasterio/_io.pyx
=====================================
@@ -1602,7 +1602,9 @@ cdef class DatasetWriterBase(DatasetReaderBase):
                 4: 'LANCZOS',
                 5: 'AVERAGE',
                 6: 'MODE',
-                7: 'GAUSS'}
+                7: 'GAUSS',
+                14: 'RMS',
+            }
             resampling_alg = resampling_map[Resampling(resampling.value)]
 
         except (KeyError, ValueError):


=====================================
rasterio/_warp.pyx
=====================================
@@ -1153,14 +1153,14 @@ cdef class WarpedVRTReaderBase(DatasetReaderBase):
         if kwargs.get("boundless", False):
             raise ValueError("WarpedVRT does not permit boundless reads")
         else:
-            return super(WarpedVRTReaderBase, self).read(indexes=indexes, out=out, window=window, masked=masked, out_shape=out_shape, resampling=resampling, fill_value=fill_value, out_dtype=out_dtype)
+            return super().read(indexes=indexes, out=out, window=window, masked=masked, out_shape=out_shape, resampling=resampling, fill_value=fill_value, out_dtype=out_dtype)
 
     def read_masks(self, indexes=None, out=None, out_shape=None, window=None, resampling=Resampling.nearest, **kwargs):
         """Read raster band masks as a multidimensional array"""
         if kwargs.get("boundless", False):
             raise ValueError("WarpedVRT does not permit boundless reads")
         else:
-            return super(WarpedVRTReaderBase, self).read_masks(indexes=indexes, out=out, window=window, out_shape=out_shape, resampling=resampling)
+            return super().read_masks(indexes=indexes, out=out, window=window, out_shape=out_shape, resampling=resampling)
 
 
 def _suggested_proxy_vrt_doc(width, height, transform=None, crs=None, gcps=None):


=====================================
rasterio/enums.py
=====================================
@@ -60,6 +60,30 @@ class Resampling(IntEnum):
     rms = 14
 
 
+class _OverviewResampling(IntEnum):
+    """Available Overview resampling algorithms.
+
+    The first 8, 'nearest', 'bilinear', 'cubic', 'cubic_spline',
+    'lanczos', 'average', 'mode', and 'gauss', are available for making
+    dataset overviews.
+
+    'nearest', 'bilinear', 'cubic', 'cubic_spline', 'lanczos',
+    'average', 'mode' are always available (GDAL >= 1.10).
+
+    'rms' is only supported in GDAL >= 3.3.
+
+    """
+    nearest = 0
+    bilinear = 1
+    cubic = 2
+    cubic_spline = 3
+    lanczos = 4
+    average = 5
+    mode = 6
+    gauss = 7
+    rms = 14
+
+
 class Compression(Enum):
     """Available compression algorithms."""
     jpeg = 'JPEG'
@@ -100,6 +124,7 @@ class PhotometricInterp(Enum):
     icclab = 'ICCLAB'
     itulab = 'ITULAB'
 
+
 class MergeAlg(Enum):
     """Available rasterization algorithms"""
     replace = 'REPLACE'


=====================================
rasterio/env.py
=====================================
@@ -621,19 +621,19 @@ if 'GDAL_DATA' not in os.environ:
     path = GDALDataFinder().search_wheel()
 
     if path:
+        log.debug("GDAL data found in package: path=%r.", path)
         set_gdal_config("GDAL_DATA", path)
-        log.debug("GDAL data found in package, GDAL_DATA set to %r.", path)
 
     # See https://github.com/mapbox/rasterio/issues/1631.
     elif GDALDataFinder().find_file("header.dxf"):
-        log.debug("GDAL data files are available at built-in paths")
+        log.debug("GDAL data files are available at built-in paths.")
 
     else:
         path = GDALDataFinder().search()
 
         if path:
             set_gdal_config("GDAL_DATA", path)
-            log.debug("GDAL_DATA not found in environment, set to %r.", path)
+            log.debug("GDAL data found in other locations: path=%r.", path)
 
 if "PROJ_LIB" in os.environ:
     path = os.environ["PROJ_LIB"]
@@ -641,16 +641,16 @@ if "PROJ_LIB" in os.environ:
 
 elif PROJDataFinder().search_wheel():
     path = PROJDataFinder().search_wheel()
-    log.debug("PROJ data found in wheel, setting to %r.", path)
+    log.debug("PROJ data found in package: path=%r.", path)
     set_proj_data_search_path(path)
 
 # See https://github.com/mapbox/rasterio/issues/1631.
 elif PROJDataFinder().has_data():
-    log.debug("PROJ data files are available at built-in paths")
+    log.debug("PROJ data files are available at built-in paths.")
 
 else:
     path = PROJDataFinder().search()
 
     if path:
-        log.debug("PROJ data not found in environment, setting to %r.", path)
+        log.debug("PROJ data found in other locations: path=%r.", path)
         set_proj_data_search_path(path)


=====================================
rasterio/errors.py
=====================================
@@ -38,7 +38,7 @@ class FileOverwriteError(FileError):
 
     def __init__(self, message):
         """Raise FileOverwriteError with message as hint."""
-        super(FileOverwriteError, self).__init__('', hint=message)
+        super().__init__('', hint=message)
 
 
 class RasterioIOError(IOError):


=====================================
rasterio/io.py
=====================================
@@ -101,8 +101,9 @@ class MemoryFile(MemoryFileBase):
         -------
         MemoryFile
         """
-        super(MemoryFile, self).__init__(
-            file_or_bytes=file_or_bytes, dirname=dirname, filename=filename, ext=ext)
+        super().__init__(
+            file_or_bytes=file_or_bytes, dirname=dirname, filename=filename, ext=ext
+        )
 
     @ensure_env
     def open(self, driver=None, width=None, height=None, count=None, crs=None,
@@ -153,7 +154,7 @@ class ZipMemoryFile(MemoryFile):
     """
 
     def __init__(self, file_or_bytes=None):
-        super(ZipMemoryFile, self).__init__(file_or_bytes, ext='zip')
+        super().__init__(file_or_bytes, ext="zip")
 
     @ensure_env
     def open(self, path, driver=None, sharing=False, **kwargs):


=====================================
rasterio/merge.py
=====================================
@@ -330,6 +330,8 @@ def merge(
 
         if math.isnan(nodataval):
             region_mask = np.isnan(region)
+        elif np.issubdtype(region.dtype, np.floating):
+            region_mask = np.isclose(region, nodataval)
         else:
             region_mask = region == nodataval
 


=====================================
rasterio/rio/overview.py
=====================================
@@ -9,7 +9,7 @@ import click
 
 from . import options
 import rasterio
-from rasterio.enums import Resampling
+from rasterio.enums import _OverviewResampling as OverviewResampling
 
 
 def build_handler(ctx, param, value):
@@ -70,8 +70,7 @@ def get_maximum_overview_level(width, height, minsize=256):
 @click.option('--rebuild', help="Reconstruct existing overviews.",
               is_flag=True, default=False)
 @click.option('--resampling', help="Resampling algorithm.",
-              type=click.Choice(
-                  [it.name for it in Resampling if it.value in [0, 1, 2, 3, 4, 5, 6, 7]]),
+              type=click.Choice([it.name for it in OverviewResampling]),
               default='nearest', show_default=True)
 @click.pass_context
 def overview(ctx, input, build, ls, rebuild, resampling):
@@ -126,14 +125,14 @@ def overview(ctx, input, build, ls, rebuild, resampling):
                     ns='rio_overview').get('resampling') or resampling
 
                 dst.build_overviews(
-                    list(factors), Resampling[resampling_method])
+                    list(factors), OverviewResampling[resampling_method])
 
         elif build:
             with rasterio.open(input, 'r+') as dst:
                 if build == "auto":
                     overview_level = get_maximum_overview_level(dst.width, dst.height)
                     build = [2 ** j for j in range(1, overview_level + 1)]
-                dst.build_overviews(build, Resampling[resampling])
+                dst.build_overviews(build, OverviewResampling[resampling])
 
                 # Save the resampling method to a tag.
                 dst.update_tags(ns='rio_overview', resampling=resampling)


=====================================
rasterio/windows.py
=====================================
@@ -285,10 +285,10 @@ def from_bounds(
     if not isinstance(transform, Affine):  # TODO: RPCs?
         raise WindowError("A transform object is required to calculate the window")
 
-    if (right - left) / transform.a <= 0:
+    if (right - left) / transform.a < 0:
         raise WindowError("Bounds and transform are inconsistent")
 
-    if (bottom - top) / transform.e <= 0:
+    if (bottom - top) / transform.e < 0:
         raise WindowError("Bounds and transform are inconsistent")
 
     rows, cols = rowcol(


=====================================
tests/data/float_raster_with_nodata.tif
=====================================
Binary files /dev/null and b/tests/data/float_raster_with_nodata.tif differ


=====================================
tests/test__env.py
=====================================
@@ -34,6 +34,8 @@ def mock_debian(tmpdir):
     tmpdir.ensure("share/gdal/3.0/header.dxf")
     tmpdir.ensure("share/gdal/3.1/header.dxf")
     tmpdir.ensure("share/gdal/3.2/header.dxf")
+    tmpdir.ensure("share/gdal/3.3/header.dxf")
+    tmpdir.ensure("share/gdal/3.4/header.dxf")
     tmpdir.ensure("share/proj/epsg")
     return tmpdir
 


=====================================
tests/test_enums.py
=====================================
@@ -1,5 +1,7 @@
 """Enum tests"""
 
+import pytest
+
 from rasterio import enums
 
 
@@ -11,3 +13,9 @@ def test_grey_gray():
 def test_gray_gray():
     """Name of ColorInterp.gray is 'gray'"""
     assert enums.ColorInterp.gray.name == "gray"
+
+
+ at pytest.mark.parametrize("resamp", enums._OverviewResampling)
+def test_resampling(resamp):
+    """Make sure that resampling value are the same."""
+    assert resamp.value == enums.Resampling[resamp.name].value


=====================================
tests/test_merge.py
=====================================
@@ -51,3 +51,11 @@ def test_merge_method(test_data_dir_overlapping, method, value):
         datasets, output_count=output_count, method=method, dtype=numpy.uint64
     )
     numpy.testing.assert_array_equal(arr[:, 5:10, 5:10], value)
+
+
+def test_issue2163():
+    """Demonstrate fix for issue 2163"""
+    with rasterio.open("tests/data/float_raster_with_nodata.tif") as src:
+        data = src.read()
+        result, transform = merge([src])
+        assert numpy.allclose(data, result)


=====================================
tests/test_overviews.py
=====================================
@@ -1,5 +1,4 @@
 """Tests of overview counting and creation."""
-import math
 
 import numpy as np
 import pytest
@@ -7,6 +6,7 @@ import pytest
 from .conftest import requires_gdal2, requires_gdal33
 
 import rasterio
+from rasterio.enums import _OverviewResampling as OverviewResampling
 from rasterio.enums import Resampling
 from rasterio.env import GDALVersion
 from rasterio.errors import OverviewCreationError
@@ -24,7 +24,7 @@ def test_build_overviews_one(data):
     inputfile = str(data.join('RGB.byte.tif'))
     with rasterio.open(inputfile, 'r+') as src:
         overview_factors = [2]
-        src.build_overviews(overview_factors, resampling=Resampling.nearest)
+        src.build_overviews(overview_factors, resampling=OverviewResampling.nearest)
         assert src.overviews(1) == [2]
         assert src.overviews(2) == [2]
         assert src.overviews(3) == [2]
@@ -34,7 +34,7 @@ def test_build_overviews_two(data):
     inputfile = str(data.join('RGB.byte.tif'))
     with rasterio.open(inputfile, 'r+') as src:
         overview_factors = [2, 4]
-        src.build_overviews(overview_factors, resampling=Resampling.nearest)
+        src.build_overviews(overview_factors, resampling=OverviewResampling.nearest)
         assert src.overviews(1) == [2, 4]
         assert src.overviews(2) == [2, 4]
         assert src.overviews(3) == [2, 4]
@@ -48,7 +48,7 @@ def test_build_overviews_bilinear(data):
     inputfile = str(data.join('RGB.byte.tif'))
     with rasterio.open(inputfile, 'r+') as src:
         overview_factors = [2, 4]
-        src.build_overviews(overview_factors, resampling=Resampling.bilinear)
+        src.build_overviews(overview_factors, resampling=OverviewResampling.bilinear)
         assert src.overviews(1) == [2, 4]
         assert src.overviews(2) == [2, 4]
         assert src.overviews(3) == [2, 4]
@@ -58,7 +58,7 @@ def test_build_overviews_average(data):
     inputfile = str(data.join('RGB.byte.tif'))
     with rasterio.open(inputfile, 'r+') as src:
         overview_factors = [2, 4]
-        src.build_overviews(overview_factors, resampling=Resampling.average)
+        src.build_overviews(overview_factors, resampling=OverviewResampling.average)
         assert src.overviews(1) == [2, 4]
         assert src.overviews(2) == [2, 4]
         assert src.overviews(3) == [2, 4]
@@ -68,7 +68,7 @@ def test_build_overviews_gauss(data):
     inputfile = str(data.join('RGB.byte.tif'))
     with rasterio.open(inputfile, 'r+') as src:
         overview_factors = [2, 4]
-        src.build_overviews(overview_factors, resampling=Resampling.gauss)
+        src.build_overviews(overview_factors, resampling=OverviewResampling.gauss)
         assert src.overviews(1) == [2, 4]
         assert src.overviews(2) == [2, 4]
         assert src.overviews(3) == [2, 4]
@@ -89,7 +89,7 @@ def test_issue1333(data):
         with rasterio.open(inputfile, 'r+') as src:
             overview_factors = [1024, 2048]
             src.build_overviews(
-                overview_factors, resampling=Resampling.average)
+                overview_factors, resampling=OverviewResampling.average)
 
 
 @requires_gdal2
@@ -101,19 +101,22 @@ def test_build_overviews_new_file(tmpdir, path_rgb_byte_tif):
             dst.write(src.read())
             overview_factors = [2, 4]
             dst.build_overviews(
-                overview_factors, resampling=Resampling.nearest)
+                overview_factors, resampling=OverviewResampling.nearest)
 
     with rasterio.open(dst_file, overview_level=1) as src:
         data = src.read()
         assert data.any()
 
 
+ at pytest.mark.parametrize("ovr_levels", [[2], [3], [2, 4, 8]])
 @requires_gdal33
-def test_ignore_overviews(data):
-    """open dataset with OVERVIEW_LEVEL=-1, overviews should be ignored"""
+def test_ignore_overviews(data, ovr_levels):
+    """open dataset with OVERVIEW_LEVEL=NONE, overviews should be ignored"""
     inputfile = str(data.join('RGB.byte.tif'))
+
+    # Add overview levels to the fixture.
     with rasterio.open(inputfile, 'r+') as src:
-        src.build_overviews([2], resampling=Resampling.nearest)
+        src.build_overviews(ovr_levels, resampling=Resampling.nearest)
 
     with rasterio.open(inputfile, OVERVIEW_LEVEL=-1) as src:
         assert src.overviews(1) == []
@@ -124,16 +127,33 @@ def test_ignore_overviews(data):
 @requires_gdal33
 def test_decimated_no_use_overview(red_green):
     """Force ignore existing overviews when performing decimated read"""
-    # Corrupt overview of red file
+    # Corrupt overview of red file by replacing red.tif.ovr with
+    # green.tif.ovr.  We have a GDAL overview reading bug if green
+    # pixels appear in a decimated read.
     green_ovr = red_green.join("green.tif.ovr")
-    green_ovr.rename(red_green.join("red.tif.ovr"))
+    green_ovr.move(red_green.join("red.tif.ovr"))
     assert not green_ovr.exists()
-    # Read the corrupted red overview
+
+    # Read the corrupted red overview.
     with rasterio.open(str(red_green.join("red.tif.ovr"))) as ovr:
-        ovr_data = ovr.read()
+        ovr_data = ovr.read(2)
         ovr_shape = ovr_data.shape
-        assert (ovr_data[1] == 204).all()
-    # Perform decimated read and ensure no use of file overview (different from corrupted)
-    with rasterio.open(str(red_green.join("red.tif")), OVERVIEW_LEVEL=-1) as src:
-        decimated_data = src.read(out_shape=ovr_shape)
+        assert (ovr_data == 204).all()  # Green pixels in band 2
+
+    # Perform decimated read and ensure no use of file overview
+    # (different from corrupted).
+    with rasterio.open(str(red_green.join("red.tif")), OVERVIEW_LEVEL="NONE") as src:
+        decimated_data = src.read(2, out_shape=ovr_shape)
         assert not np.array_equal(ovr_data, decimated_data)
+
+
+ at requires_gdal33
+def test_build_overviews_rms(data):
+    """Make sure RMS resampling works with gdal3.3."""
+    inputfile = str(data.join('RGB.byte.tif'))
+    with rasterio.open(inputfile, 'r+') as src:
+        overview_factors = [2, 4]
+        src.build_overviews(overview_factors, resampling=OverviewResampling.rms)
+        assert src.overviews(1) == [2, 4]
+        assert src.overviews(2) == [2, 4]
+        assert src.overviews(3) == [2, 4]


=====================================
tests/test_rpcs.py
=====================================
@@ -156,9 +156,12 @@ def test_rpcs_write_read_rpcs(tmpdir):
         assert isinstance(rpcs, RPC)
         expected = TEST_RPCS_FROM_GDAL
 
-        # GDAL doesn't include these metadata items on write
+        # GDAL < 3.3 does not ensure ERR_BIAS and ERR_RAND are written out
+        # so we wont either
         expected.pop('ERR_BIAS')
         expected.pop('ERR_RAND')
+        rpcs.err_bias = None
+        rpcs.err_rand = None
         
         assert sorted(rpcs.to_gdal().keys()) == sorted(expected.keys())
         


=====================================
tests/test_windows.py
=====================================
@@ -608,10 +608,26 @@ def test_from_bounds_rotation():
     assert win.height == pytest.approx(2.0 * height)
 
 
-def test_issue_2138():
+ at pytest.mark.parametrize(
+    "sy,left,bottom,right,top",
+    [(-0.001, 1.0, 45.7, 1.2, 45.9), (0.001, 1.0, 45.9, 1.2, 45.7)],
+)
+def test_issue_2138(sy, left, bottom, right, top):
     """WindowError is raised if bounds and transform are inconsistent"""
-    w, s, e, n = 1.0, 45.7, 1.2, 45.9
-    a = 0.001
-    transform = Affine.translation(w, n) * Affine.scale(a, -a)
+    transform = Affine.translation(left, top) * Affine.scale(0.001, sy)
     with pytest.raises(WindowError):
-        from_bounds(w, n, e, s, transform)
+        from_bounds(left, top, right, bottom, transform)
+
+
+ at pytest.mark.parametrize("sx", [-1.0, 1.0])
+def test_zero_width(sx):
+    """Permit a zero width window"""
+    transform = Affine.translation(0, 45.0) * Affine.scale(sx, -1.0)
+    assert from_bounds(0.0, 44.0, 0.0, 45.0, transform).width == 0
+
+
+ at pytest.mark.parametrize("sy", [-1.0, 1.0])
+def test_zero_height(sy):
+    """Permit a zero height window"""
+    transform = Affine.translation(0, 45.0) * Affine.scale(1.0, sy)
+    assert from_bounds(0.0, 44.0, 1.0, 44.0, transform).height == 0



View it on GitLab: https://salsa.debian.org/debian-gis-team/rasterio/-/commit/369df47b0ed8c1498a94032f4b5b557b94d07e9b

-- 
View it on GitLab: https://salsa.debian.org/debian-gis-team/rasterio/-/commit/369df47b0ed8c1498a94032f4b5b557b94d07e9b
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20210427/f4d368a9/attachment-0001.htm>


More information about the Pkg-grass-devel mailing list