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

Bas Couwenberg gitlab at salsa.debian.org
Tue Feb 5 14:58:42 GMT 2019


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


Commits:
aa8c0f07 by Bas Couwenberg at 2019-02-05T14:33:39Z
New upstream version 1.0.16
- - - - -


12 changed files:

- CHANGES.txt
- rasterio/__init__.py
- rasterio/_base.pyx
- rasterio/_crs.pyx
- rasterio/_io.pyx
- rasterio/_shim1.pyx
- rasterio/crs.py
- rasterio/env.py
- rasterio/shim_rasterioex.pxi
- tests/test_crs.py
- tests/test_env.py
- tests/test_gcps.py


Changes:

=====================================
CHANGES.txt
=====================================
@@ -1,6 +1,22 @@
 Changes
 =======
 
+1.0.16 (2019-02-04)
+-------------------
+
+- A bug preventing GCPs from being created with new BufferedDatasetWriter
+  instances (#1600) has been fixed (#1610).
+- A previously unreported bug preventing BufferedDatasetWriters from being
+  opened in r+ mode has been fixed.
+- A regression in creating CRS objects from PROJ4 strings that include
+  "+wktext" (#1609) has been fixed.
+- Regressions in str representations of empty CRS objects and the handling of
+  unreferenced datasets in rasterio._base have been fixed (#1616).
+- GDAL seems to work best if GDAL_DATA is set as early as possible. Ideally it
+  is set when building the library or in the environment before importing
+  Rasterio, but for wheels we patch GDAL_DATA into os.environ when rasterio.env
+  is imported. This resolves #1611.
+
 1.0.15 (2019-01-27)
 -------------------
 


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


=====================================
rasterio/_base.pyx
=====================================
@@ -267,7 +267,7 @@ cdef class DatasetBase(object):
         if wkt:
             return CRS.from_wkt(wkt)
         else:
-            return CRS()
+            return None
 
     def read_crs(self):
         """Return the GDAL dataset's stored CRS"""


=====================================
rasterio/_crs.pyx
=====================================
@@ -3,10 +3,10 @@
 
 import logging
 
+import rasterio._env
 from rasterio._err import CPLE_BaseError, CPLE_NotSupportedError
 from rasterio.compat import string_types
 from rasterio.errors import CRSError
-from rasterio.env import env_ctx_if_needed
 
 from rasterio._base cimport _osr_from_crs as osr_from_crs
 from rasterio._base cimport _safe_osr_release
@@ -175,10 +175,8 @@ cdef class _CRS(object):
 
         try:
             exc_wrap_ogrerr(exc_wrap_int(OSRImportFromProj4(obj._osr, <const char *>proj_b)))
-
         except CPLE_BaseError as exc:
             raise CRSError("The PROJ4 dict could not be understood. {}".format(exc))
-
         else:
             return obj
 
@@ -247,13 +245,10 @@ cdef class _CRS(object):
 
         try:
             errcode = exc_wrap_ogrerr(OSRImportFromWkt(obj._osr, &wkt_c))
-
             if morph_from_esri_dialect:
                 exc_wrap_ogrerr(OSRMorphFromESRI(obj._osr))
-
         except CPLE_BaseError as exc:
             raise CRSError("The WKT could not be parsed. {}".format(exc))
-
         else:
             return obj
 
@@ -414,12 +409,11 @@ _param_data = """
 +vopt
 +W
 +westo
++wktext
 +x_0       False easting
 +y_0       False northing
 +zone      UTM zone
 """
 
-with env_ctx_if_needed():
-    _lines = filter(lambda x: len(x) > 1, _param_data.split("\n"))
-    all_proj_keys = list(set(line.split()[0].lstrip("+").strip()
-                             for line in _lines)) + ['no_mayo']
+_lines = filter(lambda x: len(x) > 1, _param_data.split("\n"))
+all_proj_keys = list(set(line.split()[0].lstrip("+").strip() for line in _lines)) + ['no_mayo']


=====================================
rasterio/_io.pyx
=====================================
@@ -117,15 +117,20 @@ cdef int io_auto(data, GDALRasterBandH band, bint write, int resampling=0) excep
     cdef float height = data.shape[-2]
     cdef float width = data.shape[-1]
 
-    if ndims == 2:
-        return io_band(band, write, 0.0, 0.0, width, height, data,
-                       resampling=resampling)
-    elif ndims == 3:
-        indexes = np.arange(1, data.shape[0] + 1, dtype='intp')
-        return io_multi_band(band, write, 0.0, 0.0, width, height, data,
-                             indexes, resampling=resampling)
-    else:
-        raise ValueError("Specified data must have 2 or 3 dimensions")
+    try:
+
+        if ndims == 2:
+            return io_band(band, write, 0.0, 0.0, width, height, data, resampling=resampling)
+
+        elif ndims == 3:
+            indexes = np.arange(1, data.shape[0] + 1, dtype='intp')
+            return io_multi_band(band, write, 0.0, 0.0, width, height, data, indexes, resampling=resampling)
+
+        else:
+            raise ValueError("Specified data must have 2 or 3 dimensions")
+
+    except CPLE_BaseError as cplerr:
+        raise RasterioIOError(str(cplerr))
 
 
 cdef class DatasetReaderBase(DatasetBase):
@@ -673,25 +678,22 @@ cdef class DatasetReaderBase(DatasetBase):
         indexes_arr = np.array(indexes, dtype='intp')
         indexes_count = <int>indexes_arr.shape[0]
 
-        if masks:
-            # Warn if nodata attribute is shadowing an alpha band.
-            if self.count == 4 and self.colorinterp[3] == ColorInterp.alpha:
-                for flags in self.mask_flag_enums:
-                    if MaskFlags.nodata in flags:
-                        warnings.warn(NodataShadowWarning())
+        try:
+
+            if masks:
+                # Warn if nodata attribute is shadowing an alpha band.
+                if self.count == 4 and self.colorinterp[3] == ColorInterp.alpha:
+                    for flags in self.mask_flag_enums:
+                        if MaskFlags.nodata in flags:
+                            warnings.warn(NodataShadowWarning())
 
-            retval = io_multi_mask(
-                            self._hds, 0, xoff, yoff, width, height,
-                            out, indexes_arr, resampling=resampling)
+                io_multi_mask(self._hds, 0, xoff, yoff, width, height, out, indexes_arr, resampling=resampling)
 
-        else:
-            retval = io_multi_band(self._hds, 0, xoff, yoff, width, height,
-                                  out, indexes_arr, resampling=resampling)
+            else:
+                io_multi_band(self._hds, 0, xoff, yoff, width, height, out, indexes_arr, resampling=resampling)
 
-        if retval in (1, 2, 3):
-            raise IOError("Read or write failed")
-        elif retval == 4:
-            raise ValueError("NULL band")
+        except CPLE_BaseError as cplerr:
+            raise RasterioIOError("Read or write failed. {}".format(cplerr))
 
         return out
 
@@ -1354,13 +1356,11 @@ cdef class DatasetWriterBase(DatasetReaderBase):
 
         indexes_arr = np.array(indexes, dtype='intp')
         indexes_count = <int>indexes_arr.shape[0]
-        retval = io_multi_band(self._hds, 1, xoff, yoff, width, height,
-                               src, indexes_arr)
 
-        if retval in (1, 2, 3):
-            raise IOError("Read or write failed")
-        elif retval == 4:
-            raise ValueError("NULL band")
+        try:
+            io_multi_band(self._hds, 1, xoff, yoff, width, height, src, indexes_arr)
+        except CPLE_BaseError as cplerr:
+            raise RasterioIOError("Read or write failed. {}".format(cplerr))
 
     def write_band(self, bidx, src, window=None):
         """Write the src array into the `bidx` band.
@@ -1540,15 +1540,19 @@ cdef class DatasetWriterBase(DatasetReaderBase):
             width = self.width
             height = self.height
 
-        if mask_array is True:
-            GDALFillRaster(mask, 255, 0)
-        elif mask_array is False:
-            GDALFillRaster(mask, 0, 0)
-        elif mask_array.dtype == np.bool:
-            array = 255 * mask_array.astype(np.uint8)
-            retval = io_band(mask, 1, xoff, yoff, width, height, array)
-        else:
-            retval = io_band(mask, 1, xoff, yoff, width, height, mask_array)
+        try:
+            if mask_array is True:
+                GDALFillRaster(mask, 255, 0)
+            elif mask_array is False:
+                GDALFillRaster(mask, 0, 0)
+            elif mask_array.dtype == np.bool:
+                array = 255 * mask_array.astype(np.uint8)
+                io_band(mask, 1, xoff, yoff, width, height, array)
+            else:
+                io_band(mask, 1, xoff, yoff, width, height, mask_array)
+
+        except CPLE_BaseError as cplerr:
+            raise RasterioIOError("Read or write failed. {}".format(cplerr))
 
     def build_overviews(self, factors, resampling=Resampling.nearest):
         """Build overviews at one or more decimation factors for all
@@ -1782,22 +1786,32 @@ cdef class InMemoryRaster:
             self._hds = NULL
 
     def read(self):
+
         if self._image is None:
-            raise IOError("You need to write data before you can read the data.")
+            raise RasterioIOError("You need to write data before you can read the data.")
+
+        try:
+            if self._image.ndim == 2:
+                io_auto(self._image, self.band(1), False)
+            else:
+                io_auto(self._image, self._hds, False)
+
+        except CPLE_BaseError as cplerr:
+            raise RasterioIOError("Read or write failed. {}".format(cplerr))
 
-        if self._image.ndim == 2:
-            exc_wrap_int(io_auto(self._image, self.band(1), False))
-        else:
-            exc_wrap_int(io_auto(self._image, self._hds, False))
         return self._image
 
     def write(self, np.ndarray image):
         self._image = image
-        if image.ndim == 2:
-            exc_wrap_int(io_auto(self._image, self.band(1), True))
-        else:
-            exc_wrap_int(io_auto(self._image, self._hds, True))
 
+        try:
+            if image.ndim == 2:
+                io_auto(self._image, self.band(1), True)
+            else:
+                io_auto(self._image, self._hds, True)
+
+        except CPLE_BaseError as cplerr:
+            raise RasterioIOError("Read or write failed. {}".format(cplerr))
 
 
 cdef class BufferedDatasetWriterBase(DatasetWriterBase):
@@ -1956,10 +1970,11 @@ cdef class BufferedDatasetWriterBase(DatasetWriterBase):
                 self.write_transform(self._transform)
             if self._crs:
                 self._set_crs(self._crs)
-            if self._gcps:
-                self._set_gcps(self._gcps, self._crs)
+            if self._init_gcps:
+                self._set_gcps(self._init_gcps, self._crs)
 
         elif self.mode == 'r+':
+            fname = name_b
             try:
                 temp = exc_wrap_pointer(GDALOpenShared(fname, <GDALAccess>0))
             except Exception as exc:
@@ -1969,7 +1984,7 @@ cdef class BufferedDatasetWriterBase(DatasetWriterBase):
                 GDALCreateCopy(memdrv, "temp", temp, 1, NULL, NULL, NULL))
 
             drv = GDALGetDatasetDriver(temp)
-            self.driver = get_driver_name(drv)
+            self.driver = get_driver_name(drv).decode('utf-8')
             GDALClose(temp)
 
         # Instead of calling _begin() we do the following.


=====================================
rasterio/_shim1.pyx
=====================================
@@ -10,7 +10,7 @@ from rasterio import dtypes
 from rasterio.enums import Resampling
 
 cimport numpy as np
-from rasterio._err cimport exc_wrap_pointer
+from rasterio._err cimport exc_wrap_int, exc_wrap_pointer
 
 from rasterio.errors import GDALOptionNotImplementedError
 
@@ -88,7 +88,7 @@ cdef int io_band(
             band, mode, xoff, yoff, xsize, ysize, buf, bufxsize, bufysize,
             buftype, bufpixelspace, buflinespace)
 
-    return retval
+    return exc_wrap_int(retval)
 
 
 cdef int io_multi_band(
@@ -121,17 +121,21 @@ cdef int io_multi_band(
     cdef int xsize = <int>width
     cdef int ysize = <int>height
 
-    with nogil:
-        bandmap = <int *>CPLMalloc(count*sizeof(int))
-        for i in range(count):
-            bandmap[i] = <int>indexes[i]
-        retval = GDALDatasetRasterIO(
-            hds, mode, xoff, yoff, xsize, ysize, buf,
-            bufxsize, bufysize, buftype, count, bandmap,
-            bufpixelspace, buflinespace, bufbandspace)
-        CPLFree(bandmap)
+    bandmap = <int *>CPLMalloc(count*sizeof(int))
+    for i in range(count):
+        bandmap[i] = <int>indexes[i]
 
-    return retval
+    try:
+        with nogil:
+            retval = GDALDatasetRasterIO(
+                hds, mode, xoff, yoff, xsize, ysize, buf,
+                bufxsize, bufysize, buftype, count, bandmap,
+                bufpixelspace, buflinespace, bufbandspace)
+
+        return exc_wrap_int(retval)
+
+    finally:
+        CPLFree(bandmap)
 
 
 cdef int io_multi_mask(
@@ -183,4 +187,4 @@ cdef int io_multi_mask(
             if retval:
                 break
 
-    return retval
+    return exc_wrap_int(retval)


=====================================
rasterio/crs.py
=====================================
@@ -71,7 +71,17 @@ class CRS(collections.Mapping):
             if 'init' in data:
                 data['init'] = data['init'].replace('EPSG:', 'epsg:')
 
-            proj = ' '.join(['+{}={}'.format(key, val) for key, val in data.items()])
+            proj_parts = []
+
+            for key, val in data.items():
+                if val is False or None:
+                    continue
+                elif val is True:
+                    proj_parts.append('+{}'.format(key))
+                else:
+                    proj_parts.append('+{}={}'.format(key, val))
+
+            proj = ' '.join(proj_parts)
             self._crs = _CRS.from_proj4(proj)
 
         else:
@@ -157,11 +167,18 @@ class CRS(collections.Mapping):
         dict
 
         """
-        epsg_code = self.to_epsg()
-        if epsg_code:
-            return {'init': 'epsg:{}'.format(epsg_code)}
+        if self._crs is None:
+            raise CRSError("Undefined CRS has no dict representation")
+
         else:
-            return self._crs.to_dict()
+            epsg_code = self.to_epsg()
+            if epsg_code:
+                return {'init': 'epsg:{}'.format(epsg_code)}
+            else:
+                try:
+                    return self._crs.to_dict()
+                except CRSError:
+                    return {}
 
     @property
     def data(self):


=====================================
rasterio/env.py
=====================================
@@ -8,7 +8,9 @@ import re
 import threading
 import warnings
 
-from rasterio._env import GDALEnv, get_gdal_config, set_gdal_config
+from rasterio._env import (
+        GDALEnv, get_gdal_config, set_gdal_config,
+        GDALDataFinder, PROJDataFinder)
 from rasterio.compat import string_types, getargspec
 from rasterio.errors import (
     EnvError, GDALVersionError, RasterioDeprecationWarning)
@@ -598,3 +600,22 @@ def require_gdal_version(version, param=None, values=None, is_max_version=False,
         return wrapper
 
     return decorator
+
+
+# Patch the environment if needed, such as in the installed wheel case.
+
+if 'GDAL_DATA' not in os.environ:
+
+    path = GDALDataFinder().search()
+
+    if path:
+        os.environ['GDAL_DATA'] = path
+        log.debug("GDAL_DATA not found in environment, set to %r.", path)
+
+if 'PROJ_LIB' not in os.environ:
+
+    path = PROJDataFinder().search()
+
+    if path:
+        os.environ['PROJ_LIB'] = path
+        log.debug("PROJ data not found in environment, set to %r.", path)


=====================================
rasterio/shim_rasterioex.pxi
=====================================
@@ -6,6 +6,8 @@ from rasterio.enums import Resampling
 
 cimport numpy as np
 
+from rasterio._err cimport exc_wrap_int
+
 
 cdef extern from "cpl_progress.h":
 
@@ -73,7 +75,7 @@ cdef int io_band(GDALRasterBandH band, int mode, float x0, float y0,
             band, <GDALRWFlag>mode, xoff, yoff, xsize, ysize, buf, bufxsize, bufysize,
             buftype, bufpixelspace, buflinespace, &extras)
 
-    return retval
+    return exc_wrap_int(retval)
 
 
 cdef int io_multi_band(GDALDatasetH hds, int mode, float x0, float y0,
@@ -117,17 +119,21 @@ cdef int io_multi_band(GDALDatasetH hds, int mode, float x0, float y0,
     extras.pfnProgress = NULL
     extras.pProgressData = NULL
 
-    with nogil:
-        bandmap = <int *>CPLMalloc(count*sizeof(int))
-        for i in range(count):
-            bandmap[i] = <int>indexes[i]
-        retval = GDALDatasetRasterIOEx(
-            hds, <GDALRWFlag>mode, xoff, yoff, xsize, ysize, buf,
-            bufxsize, bufysize, buftype, count, bandmap,
-            bufpixelspace, buflinespace, bufbandspace, &extras)
-        CPLFree(bandmap)
+    bandmap = <int *>CPLMalloc(count*sizeof(int))
+    for i in range(count):
+        bandmap[i] = <int>indexes[i]
 
-    return retval
+    try:
+        with nogil:
+            retval = GDALDatasetRasterIOEx(
+                hds, <GDALRWFlag>mode, xoff, yoff, xsize, ysize, buf,
+                bufxsize, bufysize, buftype, count, bandmap,
+                bufpixelspace, buflinespace, bufbandspace, &extras)
+
+        return exc_wrap_int(retval)
+
+    finally:
+        CPLFree(bandmap)
 
 
 cdef int io_multi_mask(GDALDatasetH hds, int mode, float x0, float y0,
@@ -187,7 +193,8 @@ cdef int io_multi_mask(GDALDatasetH hds, int mode, float x0, float y0,
             retval = GDALRasterIOEx(
                 hmask, <GDALRWFlag>mode, xoff, yoff, xsize, ysize, buf, bufxsize,
                 bufysize, <GDALDataType>1, bufpixelspace, buflinespace, &extras)
+
             if retval:
                 break
 
-    return retval
+    return exc_wrap_int(retval)


=====================================
tests/test_crs.py
=====================================
@@ -88,6 +88,12 @@ def test_read_esri_wkt():
         }
 
 
+def test_read_no_crs():
+    """crs of a dataset with no SRS is None"""
+    with rasterio.open('tests/data/389225main_sw_1965_1024.jpg') as src:
+        assert src.crs is None
+
+
 # Ensure that CRS sticks when we write a file.
 @pytest.mark.gdalbin
 def test_write_3857(tmpdir):
@@ -385,3 +391,38 @@ def test_implicit_proj_dict(projection_string):
 def test_capitalized_epsg_init():
     """Ensure that old behavior is preserved"""
     assert CRS(init='EPSG:4326').to_epsg() == 4326
+
+
+def test_issue1609_wktext_a():
+    """Check on fix of issue 1609"""
+    src_proj = {'ellps': 'WGS84',
+            'proj': 'stere',
+            'lat_0': -90.0,
+            'lon_0': 0.0,
+            'x_0': 0.0,
+            'y_0': 0.0,
+            'lat_ts': -70,
+            'no_defs': True}
+    wkt = CRS(src_proj).wkt
+    assert 'PROJECTION["Polar_Stereographic"]' in wkt
+    assert 'PARAMETER["latitude_of_origin",-70]' in wkt
+
+
+def test_issue1609_wktext_b():
+    """Check on fix of issue 1609"""
+    dst_proj = {'ellps': 'WGS84',
+               'h': 9000000.0,
+               'lat_0': -78.0,
+               'lon_0': 0.0,
+               'proj': 'nsper',
+               'units': 'm',
+               'x_0': 0,
+               'y_0': 0,
+               'wktext': True}
+    wkt = CRS(dst_proj).wkt
+    assert '+wktext' in wkt
+
+
+def test_empty_crs_str():
+    """str(CRS()) should be empty string"""
+    assert str(CRS()) == ''
\ No newline at end of file


=====================================
tests/test_env.py
=====================================
@@ -126,6 +126,7 @@ def test_ensure_env_decorator_sets_gdal_data(gdalenv, monkeypatch):
 
 def test_ensure_env_decorator_sets_gdal_data_prefix(gdalenv, monkeypatch, tmpdir):
     """ensure_env finds GDAL data under a prefix"""
+
     @ensure_env
     def f():
         return getenv()['GDAL_DATA']


=====================================
tests/test_gcps.py
=====================================
@@ -1,5 +1,6 @@
 """Tests of ground control points"""
 
+import numpy
 import pytest
 
 import rasterio
@@ -79,6 +80,35 @@ def test_write_read_gcps(tmpdir):
         assert (200.0, 2000.0, 0.0) == (point.x, point.y, point.z)
 
 
+def test_write_read_gcps_buffereddatasetwriter(tmpdir):
+    filename = str(tmpdir.join('test.jpg'))
+    gcps = [GroundControlPoint(1, 1, 100.0, 1000.0, z=0.0)]
+
+    with rasterio.open(filename, 'w', driver='JPEG', dtype='uint8', count=3,
+                       width=10, height=10, crs='epsg:4326', gcps=gcps) as dst:
+        dst.write(numpy.ones((3, 10, 10), dtype='uint8'))
+
+    with rasterio.open(filename, 'r+') as dst:
+        gcps, crs = dst.gcps
+        assert crs.to_epsg() == 4326
+        assert len(gcps) == 1
+        point = gcps[0]
+        assert (1, 1) == (point.row, point.col)
+        assert (100.0, 1000.0, 0.0) == (point.x, point.y, point.z)
+
+        dst.gcps = [
+            GroundControlPoint(1, 1, 100.0, 1000.0, z=0.0),
+            GroundControlPoint(2, 2, 200.0, 2000.0, z=0.0)], crs
+
+        gcps, crs = dst.gcps
+
+        assert crs.to_epsg() == 4326
+        assert len(gcps) == 2
+        point = gcps[1]
+        assert (2, 2) == (point.row, point.col)
+        assert (200.0, 2000.0, 0.0) == (point.x, point.y, point.z)
+
+
 def test_read_vrt_gcps(tmpdir):
     vrtfile = tmpdir.join('test.vrt')
     vrtfile.write("""



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

-- 
View it on GitLab: https://salsa.debian.org/debian-gis-team/rasterio/commit/aa8c0f070ddc59335aa8cd353a63d9334697c42d
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/20190205/1d6cd11d/attachment-0001.html>


More information about the Pkg-grass-devel mailing list