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

Bas Couwenberg gitlab at salsa.debian.org
Fri Oct 26 06:34:41 BST 2018


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


Commits:
6a96aed5 by Bas Couwenberg at 2018-10-26T05:05:14Z
New upstream version 1.0.9
- - - - -


20 changed files:

- CHANGES.txt
- README.rst
- docs/cli.rst
- rasterio/__init__.py
- rasterio/_base.pyx
- rasterio/_crs.pyx
- rasterio/_env.pyx
- rasterio/_err.pyx
- rasterio/_warp.pyx
- rasterio/enums.py
- rasterio/env.py
- rasterio/features.py
- rasterio/session.py
- rasterio/shutil.pyx
- tests/test_driver_management.py
- tests/test_env.py
- tests/test_features.py
- tests/test_read_resample.py
- tests/test_tag_item.py
- tests/test_warpedvrt.py


Changes:

=====================================
CHANGES.txt
=====================================
@@ -1,6 +1,35 @@
 Changes
 =======
 
+1.0.9 (2019-10-25)
+------------------
+
+Bug fixes:
+
+- Delegate test of the environment for existing session credentials to the
+  session class to generalize credentialization of GDAL to cloud providers
+  other than AWS (#1520). The env.hascreds function is no longer used in
+  Rasterio and has been marked as deprecated.
+- Switch to use of botocore Credentials.get_frozen_credentials (#1521).
+- Numpy masked arrays with the normal Numpy mask sense (True == invalid) are
+  now supported as input for feature.shapes(). The mask keyword argument of the
+  function keeps to the GDAL sense of masks (nonzero == invalid) and the
+  documentation has been improved to communicate this (#1517).
+- The defaults for WarpedVRT's `src_nodata` and `nodata` keyword arguments are
+  no longer None, but are markers for the default behavior: inheritance of
+  nodata values from the VRT's source dataset. Values of `None` for these
+  keyword arguments means that the VRT does not inherit from the source and has
+  no nodata value at all (#1503).
+- WEBP has been added to the Compression enum. Exploitation of this new
+  compression mode will require GDAL 2.4.
+- Rasterio now check for two AWS environment variables before creating a
+  session (#1494).
+- The ensure_env_with_credentials decorator which wraps rasterio.open will no
+  longer clobber the credentials in a surrounding environment or seek
+  credentials when they already exist (#1507).
+- The comparison of CRS objects to dicts and strs that we pledged to remove at
+  1.0 has at last been removed (#1492).
+
 1.0.8 (2018-10-02)
 ------------------
 
@@ -81,10 +110,12 @@ This version corrects errors made in building binary wheels for 1.0.3. There
 are no bug fixes or new features in this version.
 
 1.0.3 (2018-08-01)
-------------------
 
 Bug fixes:
 
+- A regression in GeoJSON source handling in rio-rasterize (#1425) has been
+  fixed.
+- Rasterization of linear rings (#1431) is now supported.
 - The input file handler of rio-rasterize has been changed so that it does not
   reject GeoJSON files (#1425).
 - Linear rings have been added as acceptable input for rio-rasterize and other


=====================================
README.rst
=====================================
@@ -230,6 +230,13 @@ this from the downloads folder:
     $ pip install GDAL-2.0.2-cp27-none-win32.whl
     $ pip install rasterio-0.34.0-cp27-cp27m-win32.whl
 
+You can also install rasterio with conda using Anaconda's conda-forge channel.
+
+.. code-block:: console
+
+    $ conda install -c conda-forge rasterio 
+
+
 Source Distributions
 --------------------
 


=====================================
docs/cli.rst
=====================================
@@ -452,6 +452,15 @@ Information about existing overviews can be printed using the --ls option.
 
     $ rio overview --ls
 
+The block size (tile width and height) used for overviews (internal
+or external) can be specified by setting the ``GDAL_TIFF_OVR_BLOCKSIZE``
+environment variable to a power-of-two value between 64 and 4096. The
+default value is 128.
+
+.. code-block:: console
+
+    $ GDAL_TIFF_OVR_BLOCKSIZE=256 rio overview --build 2^1..4
+
 
 rasterize
 ---------


=====================================
rasterio/__init__.py
=====================================
@@ -25,7 +25,7 @@ from rasterio.drivers import is_blacklisted
 from rasterio.dtypes import (
     bool_, ubyte, uint8, uint16, int16, uint32, int32, float32, float64,
     complex_, check_dtype)
-from rasterio.env import ensure_env_credentialled, Env
+from rasterio.env import ensure_env_with_credentials, Env
 from rasterio.errors import RasterioIOError
 from rasterio.compat import string_types
 from rasterio.io import (
@@ -43,7 +43,7 @@ import rasterio.path
 
 
 __all__ = ['band', 'open', 'pad', 'Env']
-__version__ = "1.0.8"
+__version__ = "1.0.9"
 __gdal_version__ = gdal_version()
 
 # Rasterio attaches NullHandler to the 'rasterio' logger and its
@@ -55,7 +55,7 @@ log = logging.getLogger(__name__)
 log.addHandler(NullHandler())
 
 
- at ensure_env_credentialled
+ at ensure_env_with_credentials
 def open(fp, mode='r', driver=None, width=None, height=None, count=None,
          crs=None, transform=None, dtype=None, nodata=None, sharing=True,
          **kwargs):
@@ -119,7 +119,7 @@ def open(fp, mode='r', driver=None, width=None, height=None, count=None,
 
     Returns
     -------
-    A ``DatasetReader`` or ``DatasetUpdater`` object.
+    A ``DatasetReader`` or ``DatasetWriter`` object.
 
     Examples
     --------


=====================================
rasterio/_base.pyx
=====================================
@@ -197,7 +197,7 @@ cdef class DatasetBase(object):
 
             try:
                 self._hds = open_dataset(filename, flags, driver, kwargs, None)
-            except CPLE_OpenFailedError as err:
+            except CPLE_BaseError as err:
                 raise RasterioIOError(str(err))
 
         self.name = path.name
@@ -993,7 +993,7 @@ cdef class DatasetBase(object):
         else:
             band = self._hds
 
-        if ovr:
+        if ovr is not None:
             obj = GDALGetOverview(band, ovr)
             if obj == NULL:
               raise BandOverviewError(


=====================================
rasterio/_crs.pyx
=====================================
@@ -5,12 +5,11 @@ include "gdal.pxi"
 
 import json
 import logging
-import warnings
 
 from rasterio._err import CPLE_BaseError
 from rasterio.compat import UserDict
 from rasterio.compat import string_types
-from rasterio.errors import CRSError, RasterioDeprecationWarning
+from rasterio.errors import CRSError
 
 from rasterio._base cimport _osr_from_crs as osr_from_crs
 from rasterio._base cimport _safe_osr_release
@@ -74,25 +73,10 @@ class _CRS(UserDict):
             if not self or not other:
                 return not self and not other
 
-            # use dictionary equality rules first
-            elif isinstance(other, dict):
-                warnings.warn(
-                    "Comparison to dict will be removed in 1.0",
-                    RasterioDeprecationWarning
-                )
-                if UserDict(self.data) == UserDict(other):
-                    return True
-
-            else:
-                if isinstance(other, str):
-                    warnings.warn(
-                        "Comparison to str will be removed in 1.0",
-                        RasterioDeprecationWarning
-                    )
-                osr_crs1 = osr_from_crs(self)
-                osr_crs2 = osr_from_crs(other)
-                retval = OSRIsSame(osr_crs1, osr_crs2)
-                return bool(retval == 1)
+            osr_crs1 = osr_from_crs(self)
+            osr_crs2 = osr_from_crs(other)
+            retval = OSRIsSame(osr_crs1, osr_crs2)
+            return bool(retval == 1)
 
         finally:
             _safe_osr_release(osr_crs1)


=====================================
rasterio/_env.pyx
=====================================
@@ -55,7 +55,7 @@ cdef bint is_64bit = sys.maxsize > 2 ** 32
 
 cdef void log_error(CPLErr err_class, int err_no, const char* msg) with gil:
     """Send CPL debug messages and warnings to Python's logger."""
-    log = logging.getLogger('rasterio._gdal')
+    log = logging.getLogger(__name__)
     if err_class < 3:
         if err_no in code_map:
             log.log(level_map[err_class], "%s in %s", code_map[err_no], msg)


=====================================
rasterio/_err.pyx
=====================================
@@ -99,6 +99,10 @@ class CPLE_AWSSignatureDoesNotMatchError(CPLE_BaseError):
     pass
 
 
+class CPLE_AWSError(CPLE_BaseError):
+    pass
+
+
 # Map of GDAL error numbers to the Python exceptions.
 exception_map = {
     1: CPLE_AppDefinedError,
@@ -119,7 +123,9 @@ exception_map = {
     13: CPLE_AWSObjectNotFoundError,
     14: CPLE_AWSAccessDeniedError,
     15: CPLE_AWSInvalidCredentialsError,
-    16: CPLE_AWSSignatureDoesNotMatchError}
+    16: CPLE_AWSSignatureDoesNotMatchError,
+    17: CPLE_AWSError
+}
 
 
 # CPL Error types as an enum.


=====================================
rasterio/_warp.pyx
=====================================
@@ -592,11 +592,14 @@ def _calculate_default_transform(src_crs, dst_crs, width, height,
     return dst_affine, dst_width, dst_height
 
 
+DEFAULT_NODATA_FLAG = object()
+
+
 cdef class WarpedVRTReaderBase(DatasetReaderBase):
 
     def __init__(self, src_dataset, src_crs=None, dst_crs=None, crs=None,
                  resampling=Resampling.nearest, tolerance=0.125,
-                 src_nodata=None, dst_nodata=None, nodata=None,
+                 src_nodata=DEFAULT_NODATA_FLAG, dst_nodata=None, nodata=DEFAULT_NODATA_FLAG,
                  dst_width=None, width=None, dst_height=None, height=None,
                  src_transform=None, dst_transform=None, transform=None,
                  init_dest_nodata=True, src_alpha=0, add_alpha=False,
@@ -612,7 +615,8 @@ cdef class WarpedVRTReaderBase(DatasetReaderBase):
         src_transfrom : Affine, optional
             Overrides the transform of `src_dataset`.
         src_nodata : float, optional
-            Overrides the nodata value of `src_dataset`.
+            Overrides the nodata value of `src_dataset`, which is the
+            default.
         crs : CRS or str, optional
             The coordinate reference system at the end of the warp
             operation.  Default: the crs of `src_dataset`. dst_crs is
@@ -727,8 +731,8 @@ cdef class WarpedVRTReaderBase(DatasetReaderBase):
         self.resampling = resampling
         self.tolerance = tolerance
 
-        self.src_nodata = self.src_dataset.nodata if src_nodata is None else src_nodata
-        self.dst_nodata = self.src_nodata if nodata is None else nodata
+        self.src_nodata = self.src_dataset.nodata if src_nodata is DEFAULT_NODATA_FLAG else src_nodata
+        self.dst_nodata = self.src_nodata if nodata is DEFAULT_NODATA_FLAG else nodata
         self.dst_width = width
         self.dst_height = height
         self.dst_transform = transform


=====================================
rasterio/enums.py
=====================================
@@ -28,13 +28,14 @@ class ColorInterp(IntEnum):
 class Resampling(IntEnum):
     """Available warp resampling algorithms.
 
-    The subset of 'nearest', 'cubic', 'average', 'mode', and 'gauss'
-    are available in making dataset overviews.
+    The first 8, 'nearest', 'bilinear', 'cubic', 'cubic_spline',
+    'lanczos', 'average', 'mode', and 'gauss', are available for making
+    dataset overviews.
 
     'max', 'min', 'med', 'q1', 'q3' are only supported in GDAL >= 2.0.0.
 
-    'nearest', 'bilinear', 'cubic', 'cubic_spline', 'lanczos', 'average', 'mode'
-    are always available (GDAL >= 1.10).
+    'nearest', 'bilinear', 'cubic', 'cubic_spline', 'lanczos',
+    'average', 'mode' are always available (GDAL >= 1.10).
 
     Note: 'gauss' is not available to the functions in rio.warp.
     """
@@ -66,6 +67,7 @@ class Compression(Enum):
     none = 'NONE'
     zstd = 'ZSTD'
     lerc = 'LERC'
+    webp = 'WEBP'
 
 
 class Interleaving(Enum):


=====================================
rasterio/env.py
=====================================
@@ -8,16 +8,11 @@ import re
 import threading
 import warnings
 
-import rasterio
-from rasterio._env import (
-    GDALEnv, del_gdal_config, get_gdal_config, set_gdal_config)
+from rasterio._env import GDALEnv, get_gdal_config, set_gdal_config
 from rasterio.compat import string_types, getargspec
-from rasterio.dtypes import check_dtype
 from rasterio.errors import (
     EnvError, GDALVersionError, RasterioDeprecationWarning)
-from rasterio.path import parse_path, UnparsedPath, ParsedPath
 from rasterio.session import Session, AWSSession, DummySession
-from rasterio.transform import guard_transform
 
 
 class ThreadEnv(threading.local):
@@ -194,7 +189,7 @@ class Env(object):
                 region_name=region_name,
                 profile_name=profile_name,
                 aws_unsigned=aws_unsigned)
-        elif 'AWS_ACCESS_KEY_ID' in os.environ:
+        elif 'AWS_ACCESS_KEY_ID' in os.environ and 'AWS_SECRET_ACCESS_KEY' in os.environ:
             self.session = AWSSession()
         else:
             self.session = DummySession()
@@ -226,16 +221,6 @@ class Env(object):
         options.update(**kwargs)
         return Env(*args, **options)
 
-    @property
-    def is_credentialized(self):
-        """Test for existence of cloud credentials
-
-        Returns
-        -------
-        bool
-        """
-        return hascreds()  # bool(self.session)
-
     def credentialize(self):
         """Get credentials and configure GDAL
 
@@ -247,7 +232,7 @@ class Env(object):
         None
 
         """
-        if hascreds():
+        if self.session.hascreds(getenv()):
             pass
         else:
             cred_opts = self.session.get_credential_options()
@@ -338,9 +323,8 @@ def setenv(**options):
 
 
 def hascreds():
-    gdal_config = local._env.get_config_options()
-    return bool('AWS_ACCESS_KEY_ID' in gdal_config and
-                'AWS_SECRET_ACCESS_KEY' in gdal_config)
+    warnings.warn("Please use Env.session.hascreds() instead", RasterioDeprecationWarning)
+    return local._env is not None and all(key in local._env.get_config_options() for key in ['AWS_ACCESS_KEY_ID', 'AWS_SECRET_ACCESS_KEY'])
 
 
 def delenv():
@@ -368,6 +352,12 @@ def ensure_env(f):
 
 
 def ensure_env_credentialled(f):
+    """DEPRECATED alias for ensure_env_with_credentials"""
+    warnings.warn("Please use ensure_env_with_credentials instead", RasterioDeprecationWarning)
+    return ensure_env_with_credentials(f)
+
+
+def ensure_env_with_credentials(f):
     """Ensures a config environment exists and is credentialized
 
     Parameters
@@ -394,9 +384,15 @@ def ensure_env_credentialled(f):
             env_ctor = Env.from_defaults
 
         if isinstance(args[0], str):
-            session = Session.from_path(args[0])
+            session_cls = Session.cls_from_path(args[0])
+
+            if local._env and session_cls.hascreds(getenv()):
+                session_cls = DummySession
+
+            session = session_cls()
+
         else:
-            session = Session.from_path(None)
+            session = DummySession()
 
         with env_ctor(session=session):
             return f(*args, **kwds)
@@ -449,7 +445,7 @@ class GDALVersion(object):
         elif isinstance(input, string_types):
             # Extract major and minor version components.
             # alpha, beta, rc suffixes ignored
-            match = re.search('^\d+\.\d+', input)
+            match = re.search(r'^\d+\.\d+', input)
             if not match:
                 raise ValueError(
                     "value does not appear to be a valid GDAL version "


=====================================
rasterio/features.py
=====================================
@@ -78,8 +78,12 @@ def shapes(source, mask=None, connectivity=4, transform=IDENTITY):
         Data type must be one of rasterio.int16, rasterio.int32,
         rasterio.uint8, rasterio.uint16, or rasterio.float32.
     mask : numpy ndarray or rasterio Band object, optional
-        Values of False or 0 will be excluded from feature generation
-        Must evaluate to bool (rasterio.bool_ or rasterio.uint8)
+        Must evaluate to bool (rasterio.bool_ or rasterio.uint8). Values
+        of False or 0 will be excluded from feature generation.  Note
+        well that this is the inverse sense from Numpy's, where a mask
+        value of True indicates invalid data in an array. If `source` is
+        a Numpy masked array and `mask` is None, the source's mask will
+        be inverted and used in place of `mask`.
     connectivity : int, optional
         Use 4 or 8 pixel connectivity for grouping pixels into features
     transform : Affine transformation, optional
@@ -104,6 +108,10 @@ def shapes(source, mask=None, connectivity=4, transform=IDENTITY):
     memory.
 
     """
+    if hasattr(source, 'mask') and mask is None:
+        mask = ~source.mask
+        source = source.data
+
     transform = guard_transform(transform)
     for s, v in _shapes(source, mask, connectivity, transform):
         yield s, v


=====================================
rasterio/session.py
=====================================
@@ -1,7 +1,7 @@
 """Abstraction for sessions in various clouds."""
 
 
-from rasterio.path import parse_path, UnparsedPath, ParsedPath
+from rasterio.path import parse_path, UnparsedPath
 
 
 class Session(object):
@@ -18,6 +18,24 @@ class Session(object):
 
     """
 
+    @classmethod
+    def hascreds(cls, config):
+        """Determine if the given configuration has proper credentials
+
+        Parameters
+        ----------
+        cls : class
+            A Session class.
+        config : dict
+            GDAL configuration as a dict.
+
+        Returns
+        -------
+        bool
+
+        """
+        return NotImplementedError
+
     def get_credential_options(self):
         """Get credentials as GDAL configuration options
 
@@ -50,40 +68,56 @@ class Session(object):
             return cls(session)
 
     @staticmethod
-    def from_path(path, *args, **kwargs):
-        """Create a session object suited to the data at `path`.
+    def cls_from_path(path):
+        """Find the session class suited to the data at `path`.
 
         Parameters
         ----------
         path : str
             A dataset path or identifier.
-        args : sequence
-            Positional arguments for the foreign session constructor.
-        kwargs : dict
-            Keyword arguments for the foreign session constructor.
 
         Returns
         -------
-        Session
+        class
 
         """
         if not path:
-            return DummySession()
+            return DummySession
 
         path = parse_path(path)
 
         if isinstance(path, UnparsedPath) or path.is_local:
-            return DummySession()
+            return DummySession
 
         elif path.scheme == "s3" or "amazonaws.com" in path.path:
-            return AWSSession(*args, **kwargs)
+            return AWSSession
 
         # This factory can be extended to other cloud providers here.
         # elif path.scheme == "cumulonimbus":  # for example.
         #     return CumulonimbusSession(*args, **kwargs)
 
         else:
-            return DummySession()
+            return DummySession
+
+    @staticmethod
+    def from_path(path, *args, **kwargs):
+        """Create a session object suited to the data at `path`.
+
+        Parameters
+        ----------
+        path : str
+            A dataset path or identifier.
+        args : sequence
+            Positional arguments for the foreign session constructor.
+        kwargs : dict
+            Keyword arguments for the foreign session constructor.
+
+        Returns
+        -------
+        Session
+
+        """
+        return Session.cls_from_path(path)(*args, **kwargs)
 
 
 class DummySession(Session):
@@ -100,6 +134,24 @@ class DummySession(Session):
         self._session = None
         self.credentials = {}
 
+    @classmethod
+    def hascreds(cls, config):
+        """Determine if the given configuration has proper credentials
+
+        Parameters
+        ----------
+        cls : class
+            A Session class.
+        config : dict
+            GDAL configuration as a dict.
+
+        Returns
+        -------
+        bool
+
+        """
+        return True
+
     def get_credential_options(self):
         """Get credentials as GDAL configuration options
 
@@ -157,22 +209,41 @@ class AWSSession(Session):
         self.unsigned = aws_unsigned
         self._creds = self._session._session.get_credentials()
 
+    @classmethod
+    def hascreds(cls, config):
+        """Determine if the given configuration has proper credentials
+
+        Parameters
+        ----------
+        cls : class
+            A Session class.
+        config : dict
+            GDAL configuration as a dict.
+
+        Returns
+        -------
+        bool
+
+        """
+        return 'AWS_ACCESS_KEY_ID' in config and 'AWS_SECRET_ACCESS_KEY' in config
+
     @property
     def credentials(self):
         """The session credentials as a dict"""
-        creds = {}
+        res = {}
         if self._creds:
-            if self._creds.access_key:  # pragma: no branch
-                creds['aws_access_key_id'] = self._creds.access_key
-            if self._creds.secret_key:  # pragma: no branch
-                creds['aws_secret_access_key'] = self._creds.secret_key
-            if self._creds.token:
-                creds['aws_session_token'] = self._creds.token
+            frozen_creds = self._creds.get_frozen_credentials()
+            if frozen_creds.access_key:  # pragma: no branch
+                res['aws_access_key_id'] = frozen_creds.access_key
+            if frozen_creds.secret_key:  # pragma: no branch
+                res['aws_secret_access_key'] = frozen_creds.secret_key
+            if frozen_creds.token:
+                res['aws_session_token'] = frozen_creds.token
         if self._session.region_name:
-            creds['aws_region'] = self._session.region_name
+            res['aws_region'] = self._session.region_name
         if self.requester_pays:
-            creds['aws_request_payer'] = 'requester'
-        return creds
+            res['aws_request_payer'] = 'requester'
+        return res
 
     def get_credential_options(self):
         """Get credentials as GDAL configuration options


=====================================
rasterio/shutil.pyx
=====================================
@@ -7,7 +7,7 @@ import logging
 
 from rasterio._io cimport DatasetReaderBase
 from rasterio._err cimport exc_wrap_int, exc_wrap_pointer
-from rasterio.env import ensure_env_credentialled
+from rasterio.env import ensure_env_with_credentials
 from rasterio._err import CPLE_OpenFailedError
 from rasterio.errors import DriverRegistrationError, RasterioIOError
 from rasterio.path import parse_path, vsi_path
@@ -16,7 +16,7 @@ from rasterio.path import parse_path, vsi_path
 log = logging.getLogger(__name__)
 
 
- at ensure_env_credentialled
+ at ensure_env_with_credentials
 def exists(path):
 
     """Determine if a dataset exists by attempting to open it.
@@ -47,7 +47,7 @@ def exists(path):
                 GDALClose(h_dataset)
 
 
- at ensure_env_credentialled
+ at ensure_env_with_credentials
 def copy(src, dst, driver='GTiff', strict=True, **creation_options):
 
     """Copy a raster from a path or open dataset handle to a new destination
@@ -120,7 +120,7 @@ def copy(src, dst, driver='GTiff', strict=True, **creation_options):
                     GDALClose(src_dataset)
 
 
- at ensure_env_credentialled
+ at ensure_env_with_credentials
 def copyfiles(src, dst):
 
     """Copy files associated with a dataset from one location to another.
@@ -162,7 +162,7 @@ def copyfiles(src, dst):
                 GDALClose(h_dataset)
 
 
- at ensure_env_credentialled
+ at ensure_env_with_credentials
 def delete(path, driver=None):
 
     """Delete a GDAL dataset


=====================================
tests/test_driver_management.py
=====================================
@@ -20,7 +20,7 @@ def test_drivers_bwd_compat():
 
 def test_cpl_debug_true(tmpdir):
     """Setting CPL_DEBUG=True results in GDAL debug messages."""
-    log = logging.getLogger('rasterio._gdal')
+    log = logging.getLogger('rasterio._env')
     log.setLevel(logging.DEBUG)
     logfile = str(tmpdir.join('test.log'))
     fh = logging.FileHandler(logfile)


=====================================
tests/test_env.py
=====================================
@@ -13,6 +13,7 @@ from rasterio.env import Env, defenv, delenv, getenv, setenv, ensure_env, ensure
 from rasterio.env import GDALVersion, require_gdal_version
 from rasterio.errors import EnvError, RasterioIOError, GDALVersionError
 from rasterio.rio.main import main_group
+from rasterio.session import AWSSession
 
 from .conftest import requires_gdal21
 
@@ -23,8 +24,6 @@ credentials = pytest.mark.skipif(
     reason="S3 raster access requires credentials")
 
 
-logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
-
 L8TIF = "s3://landsat-pds/L8/139/045/LC81390452014295LGN00/LC81390452014295LGN00_B1.TIF"
 L8TIFB2 = "s3://landsat-pds/L8/139/045/LC81390452014295LGN00/LC81390452014295LGN00_B2.TIF"
 httpstif = "https://landsat-pds.s3.amazonaws.com/L8/139/045/LC81390452014295LGN00/LC81390452014295LGN00_B1.TIF"
@@ -167,9 +166,9 @@ def test_aws_session(gdalenv):
         aws_access_key_id='id', aws_secret_access_key='key',
         aws_session_token='token', region_name='null-island-1')
     with rasterio.env.Env(session=aws_session) as s:
-        assert s.session._creds.access_key == 'id'
-        assert s.session._creds.secret_key == 'key'
-        assert s.session._creds.token == 'token'
+        assert s.session._session.get_credentials().get_frozen_credentials().access_key == 'id'
+        assert s.session._session.get_credentials().get_frozen_credentials().secret_key == 'key'
+        assert s.session._session.get_credentials().get_frozen_credentials().token == 'token'
         assert s.session._session.region_name == 'null-island-1'
 
 
@@ -739,3 +738,22 @@ def test_rio_env_no_credentials(tmpdir, monkeypatch, runner):
 
     with rasterio.Env() as env:
         assert env.drivers()
+
+
+def test_nested_credentials(monkeypatch):
+    """Check that rasterio.open() doesn't wipe out surrounding credentials"""
+
+    @ensure_env_credentialled
+    def fake_opener(path):
+        return getenv()
+
+    with rasterio.Env(session=AWSSession(aws_access_key_id='foo', aws_secret_access_key='bar')):
+        assert getenv()['AWS_ACCESS_KEY_ID'] == 'foo'
+        assert getenv()['AWS_SECRET_ACCESS_KEY'] == 'bar'
+
+        monkeypatch.setenv('AWS_ACCESS_KEY_ID', 'lol')
+        monkeypatch.setenv('AWS_SECRET_ACCESS_KEY', 'wut')
+
+        gdalenv = fake_opener('s3://foo/bar')
+        assert gdalenv['AWS_ACCESS_KEY_ID'] == 'foo'
+        assert gdalenv['AWS_SECRET_ACCESS_KEY'] == 'bar'


=====================================
tests/test_features.py
=====================================
@@ -845,6 +845,25 @@ def test_shapes_mask(basic_image):
     assert value == 1
 
 
+def test_shapes_masked_array(basic_image):
+    """Only pixels not masked out should be converted to features."""
+    mask = np.full(basic_image.shape, False, dtype=rasterio.bool_)
+    mask[4:5, 4:5] = True
+
+    results = list(shapes(np.ma.masked_array(basic_image, mask=mask)))
+
+    assert len(results) == 2
+
+    shape, value = results[0]
+    assert shape == {
+        'coordinates': [
+            [(2, 2), (2, 5), (4, 5), (4, 4), (5, 4), (5, 2), (2, 2)]
+        ],
+        'type': 'Polygon'
+    }
+    assert value == 1
+
+
 def test_shapes_blank_mask(basic_image):
     """Mask is blank so results should mask shapes without mask."""
     assert np.array_equal(


=====================================
tests/test_read_resample.py
=====================================
@@ -1,3 +1,8 @@
+"""
+Rasterio exposes GDAL's resampling/decimation on I/O. These are the tests
+that it does this correctly.
+"""
+
 import numpy as np
 
 import rasterio
@@ -7,9 +12,6 @@ from rasterio.windows import Window
 from .conftest import requires_gdal2
 
 
-# Rasterio exposes GDAL's resampling/decimation on I/O. These are the tests
-# that it does this correctly.
-#
 # Rasterio's test dataset is 718 rows by 791 columns.
 
 def test_read_out_shape_resample_down():
@@ -38,6 +40,7 @@ def test_read_out_shape_resample_up():
         assert data.mean() == s.read(1, masked=True).mean()
 
 
+# TODO: justify or remove this test.
 def test_read_downsample_alpha():
     with rasterio.Env(GTIFF_IMPLICIT_JPEG_OVR=False):
         with rasterio.open('tests/data/alpha.tif') as src:
@@ -51,15 +54,31 @@ def test_read_downsample_alpha():
 
 
 @requires_gdal2
-def test_resample_alg():
+def test_resample_alg_effect_1():
     """default (nearest) and cubic produce different results"""
     with rasterio.open('tests/data/RGB.byte.tif') as s:
+        # Existence of overviews can upset our expectations, so we
+        # guard against that here.
+        assert not any([s.overviews(bidx) for bidx in s.indexes])
         out_shape = (s.height // 2, s.width // 2)
         nearest = s.read(1, out_shape=out_shape)
         cubic = s.read(1, out_shape=out_shape, resampling=Resampling.cubic)
         assert np.any(nearest != cubic)
 
 
+ at requires_gdal2
+def test_resample_alg_effect_2():
+    """Average and bilinear produce different results"""
+    with rasterio.open('tests/data/RGB.byte.tif') as s:
+        # Existence of overviews can upset our expectations, so we
+        # guard against that here.
+        assert not any([s.overviews(bidx) for bidx in s.indexes])
+        out_shape = (s.height // 2, s.width // 2)
+        avg = s.read(1, out_shape=out_shape, resampling=Resampling.average)
+        bilin = s.read(1, out_shape=out_shape, resampling=Resampling.bilinear)
+        assert np.any(avg != bilin)
+
+
 @requires_gdal2
 def test_float_window():
     """floating point windows work"""


=====================================
tests/test_tag_item.py
=====================================
@@ -21,6 +21,7 @@ def test_get_tag_item():
 def test_get_tag_item_Tiff():
     with rasterio.open('tests/data/cogeo.tif') as src:
         assert src.get_tag_item('IFD_OFFSET', 'TIFF', bidx=1) == '8'
+        assert src.get_tag_item('IFD_OFFSET', 'TIFF', bidx=1, ovr=0) == '1104'
         assert src.get_tag_item('IFD_OFFSET', 'TIFF', bidx=1, ovr=1) == '1504'
         assert not src.get_tag_item('IF', 'TIFF', bidx=1)
         with pytest.raises(Exception):


=====================================
tests/test_warpedvrt.py
=====================================
@@ -60,6 +60,20 @@ def test_warped_vrt(path_rgb_byte_tif):
         assert vrt.mask_flag_enums == ([MaskFlags.nodata],) * 3
 
 
+ at requires_gdal21
+def test_warped_vrt_nondefault_nodata(path_rgb_byte_tif):
+    """A VirtualVRT has expected nondefault nodata values."""
+    with rasterio.open(path_rgb_byte_tif) as src:
+        vrt = WarpedVRT(src, crs=DST_CRS, src_nodata=None, nodata=None)
+        assert vrt.dst_crs == CRS.from_string(DST_CRS)
+        assert vrt.src_nodata is None
+        assert vrt.dst_nodata is None
+        assert vrt.tolerance == 0.125
+        assert vrt.resampling == Resampling.nearest
+        assert vrt.warp_extras == {"init_dest": "NO_DATA"}
+        assert vrt.mask_flag_enums == ([MaskFlags.all_valid],) * 3
+
+
 @requires_gdal21(reason="Nodata deletion requires GDAL 2.1+")
 def test_warped_vrt_add_alpha(path_rgb_byte_tif):
     """A VirtualVRT has the expected VRT properties."""



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

-- 
View it on GitLab: https://salsa.debian.org/debian-gis-team/rasterio/commit/6a96aed58a9bb907ac66dea72a5aaf4d79c0839b
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/20181026/a0e552d5/attachment-0001.html>


More information about the Pkg-grass-devel mailing list