mirror of
https://github.com/rasterio/rasterio.git
synced 2025-12-08 17:36:12 +00:00
New, lazier AWS sessions
New Env class and tests. More logging, tests, safer environment Remove usage (deprecated) of rasterio.drivers() Also pep8 cleanups throughout the tests and a fix for unchecked dtypes when opening a dataset in 'w' mode. Now we can simply import warnings in __init__.py. In the deprecations tests, we needed to see a single warning only one time to avoid multiple drivers() warnings. Add a global env. Add rasterio.env.setenv()
This commit is contained in:
parent
bb7cb1a1c1
commit
12f8fc7e3f
@ -6,20 +6,22 @@ from collections import namedtuple
|
||||
import logging
|
||||
try:
|
||||
from logging import NullHandler
|
||||
except ImportError:
|
||||
except ImportError: # pragma: no cover
|
||||
class NullHandler(logging.Handler):
|
||||
def emit(self, record):
|
||||
pass
|
||||
import warnings
|
||||
|
||||
from rasterio._base import (
|
||||
eval_window, window_shape, window_index, gdal_version)
|
||||
from rasterio._drivers import driver_count, GDALEnv
|
||||
from rasterio.dtypes import (
|
||||
bool_, ubyte, uint8, uint16, int16, uint32, int32, float32, float64,
|
||||
complex_)
|
||||
complex_, check_dtype)
|
||||
import rasterio.env
|
||||
from rasterio.five import string_types
|
||||
from rasterio.profiles import default_gtiff_profile
|
||||
from rasterio.transform import Affine, guard_transform
|
||||
from rasterio.vfs import parse_path
|
||||
from rasterio import windows
|
||||
|
||||
# These modules are imported from the Cython extensions, but are also import
|
||||
@ -29,7 +31,7 @@ from rasterio import _err, coords, enums, vfs
|
||||
# Classes in rasterio._io are imported below just before we need them.
|
||||
|
||||
__all__ = [
|
||||
'band', 'open', 'drivers', 'copy', 'pad']
|
||||
'band', 'open', 'copy', 'pad']
|
||||
__version__ = "0.34.0"
|
||||
__gdal_version__ = gdal_version()
|
||||
|
||||
@ -38,37 +40,34 @@ __gdal_version__ = gdal_version()
|
||||
# https://docs.python.org/2/howto/logging.html#configuring-logging-for-a-library
|
||||
# Applications must attach their own handlers in order to see messages.
|
||||
# See rasterio/rio/main.py for an example.
|
||||
logging.getLogger(__name__).addHandler(NullHandler())
|
||||
log = logging.getLogger(__name__)
|
||||
log.addHandler(NullHandler())
|
||||
|
||||
|
||||
def open(
|
||||
path, mode='r',
|
||||
driver=None,
|
||||
width=None, height=None,
|
||||
count=None,
|
||||
crs=None, transform=None,
|
||||
dtype=None,
|
||||
nodata=None,
|
||||
**kwargs):
|
||||
"""Open file at ``path`` in ``mode`` "r" (read), "r+" (read/write),
|
||||
or "w" (write) and return a ``Reader`` or ``Updater`` object.
|
||||
def open(path, mode='r', driver=None, width=None, height=None,
|
||||
count=None, crs=None, transform=None, dtype=None, nodata=None,
|
||||
**kwargs):
|
||||
"""Open file at ``path`` in ``mode`` 'r' (read), 'r+' (read and
|
||||
write), or 'w' (write) and return a dataset Reader or Updater
|
||||
object.
|
||||
|
||||
In write mode, a driver name such as "GTiff" or "JPEG" (see GDAL
|
||||
docs or ``gdal_translate --help`` on the command line), ``width``
|
||||
(number of pixels per line) and ``height`` (number of lines), the
|
||||
``count`` number of bands in the new file must be specified.
|
||||
Additionally, the data type for bands such as ``rasterio.ubyte`` for
|
||||
8-bit bands or ``rasterio.uint16`` for 16-bit bands must be
|
||||
specified using the ``dtype`` argument.
|
||||
docs or ``gdal_translate --help`` on the command line),
|
||||
``width`` (number of pixels per line) and ``height`` (number of
|
||||
lines), the ``count`` number of bands in the new file must be
|
||||
specified. Additionally, the data type for bands such as
|
||||
``rasterio.ubyte`` for 8-bit bands or ``rasterio.uint16`` for
|
||||
16-bit bands must be specified using the ``dtype`` argument.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
mode: string
|
||||
"r" (read), "r+" (read/write), or "w" (write)
|
||||
driver: string
|
||||
driver code specifying the format name (e.g. "GTiff" or "JPEG")
|
||||
See GDAL docs at http://www.gdal.org/formats_list.html
|
||||
(optional, required for write)
|
||||
driver code specifying the format name (e.g. "GTiff" or
|
||||
"JPEG"). See GDAL docs at
|
||||
http://www.gdal.org/formats_list.html (optional, required
|
||||
for writing).
|
||||
width: int
|
||||
number of pixels per line
|
||||
(optional, required for write)
|
||||
@ -86,31 +85,32 @@ def open(
|
||||
Coordinate reference system
|
||||
(optional, recommended for write)
|
||||
transform: Affine instance
|
||||
Affine transformation mapping the pixel space to geographic space
|
||||
(optional, recommended for write)
|
||||
Affine transformation mapping the pixel space to geographic
|
||||
space (optional, recommended for writing).
|
||||
nodata: number
|
||||
Defines pixel value to be interpreted as null/nodata
|
||||
(optional, recommended for write)
|
||||
|
||||
Returns
|
||||
-------
|
||||
A ``Reader`` or ``Updater`` object.
|
||||
A ``DatasetReader`` or ``DatasetUpdater`` object.
|
||||
|
||||
Notes
|
||||
-----
|
||||
In write mode, you must specify at least ``width``, ``height``, ``count``
|
||||
and ``dtype``.
|
||||
In write mode, you must specify at least ``width``, ``height``,
|
||||
``count`` and ``dtype``.
|
||||
|
||||
A coordinate reference system for raster datasets in write mode can
|
||||
be defined by the ``crs`` argument. It takes Proj4 style mappings
|
||||
like
|
||||
A coordinate reference system for raster datasets in write mode
|
||||
can be defined by the ``crs`` argument. It takes Proj4 style
|
||||
mappings like
|
||||
|
||||
.. code::
|
||||
|
||||
{'proj': 'longlat', 'ellps': 'WGS84', 'datum': 'WGS84', 'no_defs': True}
|
||||
{'proj': 'longlat', 'ellps': 'WGS84', 'datum': 'WGS84',
|
||||
'no_defs': True}
|
||||
|
||||
An affine transformation that maps ``col,row`` pixel coordinates to
|
||||
``x,y`` coordinates in the coordinate reference system can be
|
||||
An affine transformation that maps ``col,row`` pixel coordinates
|
||||
to ``x,y`` coordinates in the coordinate reference system can be
|
||||
specified using the ``transform`` argument. The value should be
|
||||
an instance of ``affine.Affine``
|
||||
|
||||
@ -127,37 +127,54 @@ def open(
|
||||
| y | = | d e f | | r |
|
||||
| 1 | | 0 0 1 | | 1 |
|
||||
|
||||
a: rate of change of X with respect to increasing column, i.e. pixel width
|
||||
b: rotation, 0 if the raster is oriented "north up"
|
||||
c: X coordinate of the top left corner of the top left pixel
|
||||
d: rotation, 0 if the raster is oriented "north up"
|
||||
e: rate of change of Y with respect to increasing row, usually
|
||||
a negative number (i.e. -1 * pixel height) if north-up.
|
||||
f: Y coordinate of the top left corner of the top left pixel
|
||||
a: rate of change of X with respect to increasing column,
|
||||
i.e. pixel width
|
||||
b: rotation, 0 if the raster is oriented "north up"
|
||||
c: X coordinate of the top left corner of the top left pixel
|
||||
d: rotation, 0 if the raster is oriented "north up"
|
||||
e: rate of change of Y with respect to increasing row,
|
||||
usually a negative number (i.e. -1 * pixel height) if
|
||||
north-up.
|
||||
f: Y coordinate of the top left corner of the top left pixel
|
||||
|
||||
A 6-element sequence of the affine transformation
|
||||
matrix coefficients in ``c, a, b, f, d, e`` order,
|
||||
(i.e. GDAL geotransform order) will be accepted until 1.0 (deprecated).
|
||||
A 6-element sequence of the affine transformation matrix
|
||||
coefficients in ``c, a, b, f, d, e`` order, (i.e. GDAL
|
||||
geotransform order) will be accepted until 1.0 (deprecated).
|
||||
|
||||
A virtual filesystem can be specified. The ``vfs`` parameter may be
|
||||
an Apache Commons VFS style string beginning with "zip://" or
|
||||
A virtual filesystem can be specified. The ``vfs`` parameter may
|
||||
be an Apache Commons VFS style string beginning with "zip://" or
|
||||
"tar://"". In this case, the ``path`` must be an absolute path
|
||||
within that container.
|
||||
|
||||
"""
|
||||
if not isinstance(path, string_types):
|
||||
raise TypeError("invalid path: %r" % path)
|
||||
raise TypeError("invalid path: {0!r}".format(path))
|
||||
if mode and not isinstance(mode, string_types):
|
||||
raise TypeError("invalid mode: %r" % mode)
|
||||
raise TypeError("invalid mode: {0!r}".format(mode))
|
||||
if driver and not isinstance(driver, string_types):
|
||||
raise TypeError("invalid driver: %r" % driver)
|
||||
|
||||
raise TypeError("invalid driver: {0!r}".format(driver))
|
||||
if dtype and not check_dtype(dtype):
|
||||
raise TypeError("invalid dtype: {0!r}".format(dtype))
|
||||
if transform:
|
||||
transform = guard_transform(transform)
|
||||
elif 'affine' in kwargs:
|
||||
affine = kwargs.pop('affine')
|
||||
transform = guard_transform(affine)
|
||||
|
||||
# If there is no currently active GDAL/AWS environment, create one.
|
||||
rasterio.env.setenv()
|
||||
|
||||
# Get AWS credentials if we're attempting to access a raster
|
||||
# on S3.
|
||||
pth, archive, scheme = parse_path(path)
|
||||
if scheme == 's3' and not rasterio.env._env._creds:
|
||||
rasterio.env._env.get_aws_credentials()
|
||||
log.debug(
|
||||
"In env %r AWS credentials have been obtained", rasterio.env._env)
|
||||
|
||||
# Create dataset instances and pass the given env, which will
|
||||
# be taken over by the dataset's context manager if it is not
|
||||
# None.
|
||||
if mode == 'r':
|
||||
from rasterio._io import RasterReader
|
||||
s = RasterReader(path)
|
||||
@ -172,8 +189,7 @@ def open(
|
||||
s = writer(path, mode, driver=driver,
|
||||
width=width, height=height, count=count,
|
||||
crs=crs, transform=transform, dtype=dtype,
|
||||
nodata=nodata,
|
||||
**kwargs)
|
||||
nodata=nodata, **kwargs)
|
||||
else:
|
||||
raise ValueError(
|
||||
"mode string must be one of 'r', 'r+', or 'w', not %s" % mode)
|
||||
@ -209,13 +225,17 @@ def copy(src, dst, **kw):
|
||||
This is the one way to create write-once files like JPEGs.
|
||||
"""
|
||||
from rasterio._copy import RasterCopier
|
||||
with drivers():
|
||||
return RasterCopier()(src, dst, **kw)
|
||||
|
||||
# If there is no currently active GDAL/AWS environment, create one.
|
||||
rasterio.env.setenv()
|
||||
return RasterCopier()(src, dst, **kw)
|
||||
|
||||
|
||||
def drivers(**kwargs):
|
||||
"""Create a gdal environment with registered drivers and
|
||||
creation options.
|
||||
"""Create a gdal environment with registered drivers and creation
|
||||
options.
|
||||
|
||||
This function is deprecated; please use ``env.Env`` instead.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
@ -232,7 +252,8 @@ def drivers(**kwargs):
|
||||
-----
|
||||
Use as a context manager, ``with rasterio.drivers(): ...``
|
||||
"""
|
||||
return GDALEnv(**kwargs)
|
||||
warnings.warn("Deprecated; Use env.Env instead", DeprecationWarning)
|
||||
return rasterio.env.Env(**kwargs)
|
||||
|
||||
|
||||
Band = namedtuple('Band', ['ds', 'bidx', 'dtype', 'shape'])
|
||||
@ -292,23 +313,19 @@ def pad(array, transform, pad_width, mode=None, **kwargs):
|
||||
|
||||
|
||||
def get_data_window(arr, nodata=None):
|
||||
import warnings
|
||||
warnings.warn("Deprecated; Use rasterio.windows instead", DeprecationWarning)
|
||||
return windows.get_data_window(arr, nodata)
|
||||
|
||||
|
||||
def window_union(data):
|
||||
import warnings
|
||||
warnings.warn("Deprecated; Use rasterio.windows instead", DeprecationWarning)
|
||||
return windows.union(data)
|
||||
|
||||
|
||||
def window_intersection(data):
|
||||
import warnings
|
||||
warnings.warn("Deprecated; Use rasterio.windows instead", DeprecationWarning)
|
||||
return windows.intersection(data)
|
||||
|
||||
def windows_intersect(data):
|
||||
import warnings
|
||||
warnings.warn("Deprecated; Use rasterio.windows instead", DeprecationWarning)
|
||||
return windows.intersect(data)
|
||||
|
||||
@ -20,7 +20,6 @@ cdef class DatasetReader:
|
||||
cdef public object _block_shapes
|
||||
cdef public object _nodatavals
|
||||
cdef public object _read
|
||||
cdef object env
|
||||
|
||||
cdef void *band(self, int bidx) except NULL
|
||||
|
||||
|
||||
@ -12,15 +12,15 @@ import warnings
|
||||
from libc.stdlib cimport malloc, free
|
||||
|
||||
from rasterio cimport _gdal, _ogr
|
||||
from rasterio._drivers import driver_count, GDALEnv
|
||||
from rasterio._err import (
|
||||
CPLErrors, GDALError, CPLE_IllegalArg, CPLE_OpenFailed, CPLE_NotSupported)
|
||||
from rasterio import dtypes
|
||||
from rasterio.coords import BoundingBox
|
||||
from rasterio.errors import RasterioIOError, CRSError
|
||||
from rasterio.transform import Affine
|
||||
from rasterio.enums import (
|
||||
ColorInterp, Compression, Interleaving, PhotometricInterp)
|
||||
from rasterio.env import Env
|
||||
from rasterio.errors import RasterioIOError, CRSError
|
||||
from rasterio.transform import Affine
|
||||
from rasterio.vfs import parse_path, vsi_path
|
||||
|
||||
|
||||
@ -55,7 +55,6 @@ cdef class DatasetReader(object):
|
||||
self._crs = None
|
||||
self._crs_wkt = None
|
||||
self._read = False
|
||||
self.env = None
|
||||
|
||||
def __repr__(self):
|
||||
return "<%s RasterReader name='%s' mode='%s'>" % (
|
||||
@ -64,21 +63,16 @@ cdef class DatasetReader(object):
|
||||
self.mode)
|
||||
|
||||
def start(self):
|
||||
self.env = GDALEnv()
|
||||
self.env.start()
|
||||
|
||||
"""Start of the dataset reader life cycle."""
|
||||
path, archive, scheme = parse_path(self.name)
|
||||
path = vsi_path(path, archive=archive, scheme=scheme)
|
||||
|
||||
name_b = path.encode('utf-8')
|
||||
cdef const char *fname = name_b
|
||||
|
||||
try:
|
||||
with CPLErrors() as cple:
|
||||
self._hds = _gdal.GDALOpen(fname, 0)
|
||||
cple.check()
|
||||
except CPLE_OpenFailed as err:
|
||||
self.env.stop()
|
||||
raise RasterioIOError(err.errmsg)
|
||||
|
||||
cdef void *drv
|
||||
@ -100,6 +94,8 @@ cdef class DatasetReader(object):
|
||||
_ = self.meta
|
||||
|
||||
self._closed = False
|
||||
log.debug("Dataset %r is started.", self)
|
||||
|
||||
|
||||
cdef void *band(self, int bidx) except NULL:
|
||||
cdef void *hband = NULL
|
||||
@ -108,7 +104,6 @@ cdef class DatasetReader(object):
|
||||
hband = _gdal.GDALGetRasterBand(self._hds, bidx)
|
||||
cple.check()
|
||||
except CPLE_IllegalArg as exc:
|
||||
self.env.stop()
|
||||
raise IndexError(str(exc))
|
||||
return hband
|
||||
|
||||
@ -119,7 +114,6 @@ cdef class DatasetReader(object):
|
||||
hband = _gdal.GDALGetRasterBand(self._hds, bidx)
|
||||
cple.check()
|
||||
except CPLE_IllegalArg:
|
||||
self.env.stop()
|
||||
return False
|
||||
return True
|
||||
|
||||
@ -240,19 +234,23 @@ cdef class DatasetReader(object):
|
||||
if self._hds != NULL:
|
||||
_gdal.GDALFlushCache(self._hds)
|
||||
_gdal.GDALClose(self._hds)
|
||||
if self.env:
|
||||
self.env.stop()
|
||||
self._hds = NULL
|
||||
log.debug("Dataset %r has been stopped.", self)
|
||||
|
||||
def close(self):
|
||||
self.stop()
|
||||
self._closed = True
|
||||
log.debug("Dataset %r has been closed.", self)
|
||||
|
||||
|
||||
def __enter__(self):
|
||||
log.debug("Entering Dataset %r context.", self)
|
||||
return self
|
||||
|
||||
def __exit__(self, type, value, traceback):
|
||||
self.close()
|
||||
log.debug("Exited Dataset %r context.", self)
|
||||
|
||||
|
||||
def __dealloc__(self):
|
||||
if self._hds != NULL:
|
||||
|
||||
@ -87,20 +87,26 @@ cdef class ConfigEnv(object):
|
||||
self.options = options.copy()
|
||||
self.prev_options = {}
|
||||
|
||||
cdef enter_config_options(self):
|
||||
def enter_config_options(self):
|
||||
"""Set GDAL config options."""
|
||||
self.update_config_options(**self.options)
|
||||
|
||||
def update_config_options(self, **kwargs):
|
||||
"""Update GDAL config options."""
|
||||
cdef const char *key_c
|
||||
cdef const char *val_c
|
||||
|
||||
for key, val in self.options.items():
|
||||
self.options.update(**kwargs)
|
||||
for key, val in kwargs.items():
|
||||
key_b = key.upper().encode('utf-8')
|
||||
key_c = key_b
|
||||
|
||||
# Save current value of that key.
|
||||
val_c = CPLGetConfigOption(key_c, NULL)
|
||||
if val_c != NULL:
|
||||
val_b = val_c
|
||||
self.prev_options[key_b] = val_b
|
||||
#if key not in self.prev_options:
|
||||
# val_c = CPLGetConfigOption(key_c, NULL)
|
||||
# if val_c != NULL:
|
||||
# val_b = val_c
|
||||
# self.prev_options[key] = val_b
|
||||
|
||||
if isinstance(val, string_types):
|
||||
val_b = val.encode('utf-8')
|
||||
@ -110,12 +116,12 @@ cdef class ConfigEnv(object):
|
||||
CPLSetConfigOption(key_c, val_c)
|
||||
|
||||
# Redact AWS credentials.
|
||||
if key in ['AWS_ACCESS_KEY_ID', 'AWS_SECRET_ACCESS_KEY',
|
||||
'AWS_SESSION_TOKEN', 'AWS_REGION']:
|
||||
if key.upper() in ['AWS_ACCESS_KEY_ID', 'AWS_SECRET_ACCESS_KEY',
|
||||
'AWS_SESSION_TOKEN']:
|
||||
val = '******'
|
||||
log.debug("Option %s=%s", key, val)
|
||||
log.debug("Set option %s=%s in env %r", key, val, self)
|
||||
|
||||
cdef exit_config_options(self):
|
||||
def exit_config_options(self):
|
||||
"""Clear GDAL config options."""
|
||||
cdef const char *key_c
|
||||
cdef const char *val_c
|
||||
@ -123,12 +129,15 @@ cdef class ConfigEnv(object):
|
||||
for key in self.options:
|
||||
key_b = key.upper().encode('utf-8')
|
||||
key_c = key_b
|
||||
if key_b in self.prev_options:
|
||||
val_b = self.prev_options[key_b]
|
||||
key_c = key_b; val_c = val_b
|
||||
if key in self.prev_options:
|
||||
val = self.prev_options[key]
|
||||
val_b = val.encode('utf-8')
|
||||
val_c = val_b
|
||||
CPLSetConfigOption(key_c, val_c)
|
||||
log.debug("Restored previous option %s=%s in env %r", key, val, self)
|
||||
else:
|
||||
CPLSetConfigOption(key_c, NULL)
|
||||
log.debug("Unset option %s in env %r", key, self)
|
||||
|
||||
def __enter__(self):
|
||||
self.enter_config_options()
|
||||
@ -138,6 +147,7 @@ cdef class ConfigEnv(object):
|
||||
self.exit_config_options()
|
||||
|
||||
|
||||
|
||||
cdef class GDALEnv(ConfigEnv):
|
||||
|
||||
def __init__(self, **options):
|
||||
@ -147,11 +157,13 @@ cdef class GDALEnv(ConfigEnv):
|
||||
def __enter__(self):
|
||||
self.start()
|
||||
self.enter_config_options()
|
||||
log.debug("Entering env %r context", self)
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type=None, exc_val=None, exc_tb=None):
|
||||
self.exit_config_options()
|
||||
self.stop()
|
||||
log.debug("Exiting env %r context", self)
|
||||
|
||||
def start(self):
|
||||
cdef const char *key_c
|
||||
@ -174,12 +186,14 @@ cdef class GDALEnv(ConfigEnv):
|
||||
whl_datadir = os.path.abspath(
|
||||
os.path.join(os.path.dirname(__file__), "proj_data"))
|
||||
os.environ['PROJ_LIB'] = whl_datadir
|
||||
log.debug("Env %r has been started", self)
|
||||
|
||||
|
||||
def stop(self):
|
||||
# NB: do not restore the CPL error handler to its default
|
||||
# state here. If you do, log messages will be written to stderr
|
||||
# by GDAL instead of being sent to Python's logging module.
|
||||
pass
|
||||
log.debug("Env %r has been stopped", self)
|
||||
|
||||
def drivers(self):
|
||||
cdef void *drv = NULL
|
||||
|
||||
@ -21,13 +21,13 @@ from rasterio._drivers import driver_count, GDALEnv
|
||||
from rasterio._err import CPLErrors, GDALError, CPLE_OpenFailed
|
||||
from rasterio import dtypes
|
||||
from rasterio.coords import BoundingBox
|
||||
from rasterio.errors import DriverRegistrationError, RasterioIOError
|
||||
from rasterio.errors import (
|
||||
DriverRegistrationError, RasterioIOError, NodataShadowWarning)
|
||||
from rasterio.five import text_type, string_types
|
||||
from rasterio.transform import Affine
|
||||
from rasterio.enums import ColorInterp, MaskFlags, Resampling
|
||||
from rasterio.sample import sample_gen
|
||||
from rasterio.vfs import parse_path
|
||||
from rasterio.warnings import NodataShadowWarning
|
||||
from rasterio.vfs import parse_path, vsi_path
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@ -1200,12 +1200,9 @@ cdef class RasterReader(_base.DatasetReader):
|
||||
cdef class RasterUpdater(RasterReader):
|
||||
# Read-write access to raster data and metadata.
|
||||
|
||||
def __init__(
|
||||
self, path, mode, driver=None,
|
||||
width=None, height=None, count=None,
|
||||
crs=None, transform=None, dtype=None,
|
||||
nodata=None,
|
||||
**kwargs):
|
||||
def __init__(self, path, mode, driver=None, width=None, height=None,
|
||||
count=None, crs=None, transform=None, dtype=None, nodata=None,
|
||||
**kwargs):
|
||||
# Validate write mode arguments.
|
||||
if mode == 'w':
|
||||
if not isinstance(driver, string_types):
|
||||
@ -1241,7 +1238,7 @@ cdef class RasterUpdater(RasterReader):
|
||||
self._dtypes = []
|
||||
self._nodatavals = []
|
||||
self._options = kwargs.copy()
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return "<%s RasterUpdater name='%s' mode='%s'>" % (
|
||||
self.closed and 'closed' or 'open',
|
||||
@ -1257,10 +1254,11 @@ cdef class RasterUpdater(RasterReader):
|
||||
cdef void *hband = NULL
|
||||
cdef int success
|
||||
|
||||
self.env = GDALEnv()
|
||||
self.env.start()
|
||||
|
||||
# Parse the path to determine if there is scheme-specific
|
||||
# configuration to be done.
|
||||
path, archive, scheme = parse_path(self.name)
|
||||
path = vsi_path(path, archive=archive, scheme=scheme)
|
||||
|
||||
if scheme and scheme != 'file':
|
||||
raise TypeError(
|
||||
"VFS '{0}' datasets can not be created or updated.".format(
|
||||
@ -1289,7 +1287,6 @@ cdef class RasterUpdater(RasterReader):
|
||||
drv = _gdal.GDALGetDriverByName(drv_name)
|
||||
cple.check()
|
||||
except Exception as err:
|
||||
self.env.stop()
|
||||
raise DriverRegistrationError(str(err))
|
||||
|
||||
# Find the equivalent GDAL data type or raise an exception
|
||||
@ -1335,7 +1332,6 @@ cdef class RasterUpdater(RasterReader):
|
||||
gdal_dtype, options)
|
||||
cple.check()
|
||||
except Exception as err:
|
||||
self.env.stop()
|
||||
if options != NULL:
|
||||
_gdal.CSLDestroy(options)
|
||||
raise
|
||||
@ -1364,7 +1360,6 @@ cdef class RasterUpdater(RasterReader):
|
||||
self._hds = _gdal.GDALOpen(fname, 1)
|
||||
cple.check()
|
||||
except CPLE_OpenFailed as err:
|
||||
self.env.stop()
|
||||
raise RasterioIOError(str(err))
|
||||
|
||||
drv = _gdal.GDALGetDatasetDriver(self._hds)
|
||||
@ -1931,14 +1926,16 @@ cdef class IndirectRasterUpdater(RasterUpdater):
|
||||
cdef void *hband = NULL
|
||||
cdef void *temp = NULL
|
||||
cdef int success
|
||||
name_b = self.name.encode('utf-8')
|
||||
|
||||
# Parse the path to determine if there is scheme-specific
|
||||
# configuration to be done.
|
||||
path, archive, scheme = parse_path(self.name)
|
||||
path = vsi_path(path, archive=archive, scheme=scheme)
|
||||
name_b = path.encode('utf-8')
|
||||
cdef const char *fname = name_b
|
||||
|
||||
memdrv = _gdal.GDALGetDriverByName("MEM")
|
||||
|
||||
self.env = GDALEnv()
|
||||
self.env.start()
|
||||
|
||||
if self.mode == 'w':
|
||||
# Find the equivalent GDAL data type or raise an exception
|
||||
# We've mapped numpy scalar types to GDAL types so see
|
||||
@ -1960,7 +1957,6 @@ cdef class IndirectRasterUpdater(RasterUpdater):
|
||||
gdal_dtype, NULL)
|
||||
cple.check()
|
||||
except:
|
||||
self.env.close()
|
||||
raise
|
||||
|
||||
if self._init_nodata is not None:
|
||||
|
||||
@ -566,7 +566,8 @@ def _calculate_default_transform(
|
||||
raise CRSError(err.errmsg)
|
||||
except CPLE_AppDefined as err:
|
||||
log.debug("Encountered points outside of valid dst crs region")
|
||||
pass
|
||||
raise
|
||||
#pass
|
||||
finally:
|
||||
if wkt != NULL:
|
||||
_gdal.CPLFree(wkt)
|
||||
|
||||
@ -1,62 +0,0 @@
|
||||
"""Amazon Web Service sessions and S3 raster access.
|
||||
|
||||
Reuses concepts from awscli and boto including environment variable
|
||||
names and the .aws/config and /.aws/credentials files.
|
||||
|
||||
Raster datasets on S3 may be accessed using ``aws.Session.open()``
|
||||
|
||||
from rasterio.aws import Session
|
||||
|
||||
with Session().open('s3://bucket/foo.tif') as src:
|
||||
...
|
||||
|
||||
or by calling ``rasterio.open()`` from within a session block
|
||||
|
||||
with Session() as sess:
|
||||
with rasterio.open('s3://bucket/foo.tif') as src:
|
||||
...
|
||||
"""
|
||||
|
||||
import boto3
|
||||
|
||||
from rasterio._drivers import ConfigEnv
|
||||
from rasterio.five import string_types
|
||||
|
||||
|
||||
class Session(ConfigEnv):
|
||||
"""A credentialed AWS S3 raster access session."""
|
||||
|
||||
def __init__(self, aws_access_key_id=None, aws_secret_access_key=None,
|
||||
aws_session_token=None, region_name=None, profile_name=None,
|
||||
**options):
|
||||
self._session = boto3.Session(
|
||||
aws_access_key_id=aws_access_key_id,
|
||||
aws_secret_access_key=aws_secret_access_key,
|
||||
aws_session_token=aws_session_token,
|
||||
region_name=region_name,
|
||||
profile_name=profile_name)
|
||||
self._creds = self._session._session.get_credentials()
|
||||
self.options = options.copy()
|
||||
if self._creds:
|
||||
if self._creds.access_key:
|
||||
self.options['AWS_ACCESS_KEY_ID'] = self._creds.access_key
|
||||
if self._creds.secret_key:
|
||||
self.options['AWS_SECRET_ACCESS_KEY'] = self._creds.secret_key
|
||||
if self._creds.token:
|
||||
self.options['AWS_SESSION_TOKEN'] = self._creds.token
|
||||
if self._session.region_name:
|
||||
self.options['AWS_REGION'] = self._session.region_name
|
||||
self.prev_options = {}
|
||||
|
||||
def open(self, path, mode='r'):
|
||||
"""Read-only access to rasters on S3."""
|
||||
if not isinstance(path, string_types):
|
||||
raise TypeError("invalid path: %r" % path)
|
||||
if mode == 'r-':
|
||||
from rasterio._base import DatasetReader
|
||||
s = DatasetReader(path, options=self.options)
|
||||
else:
|
||||
from rasterio._io import RasterReader
|
||||
s = RasterReader(path, options=self.options)
|
||||
s.start()
|
||||
return s
|
||||
130
rasterio/env.py
Normal file
130
rasterio/env.py
Normal file
@ -0,0 +1,130 @@
|
||||
"""Rasterio's GDAL/AWS environment"""
|
||||
|
||||
import logging
|
||||
|
||||
from rasterio._drivers import GDALEnv
|
||||
from rasterio.dtypes import check_dtype
|
||||
from rasterio.errors import EnvError
|
||||
from rasterio.five import string_types
|
||||
from rasterio.transform import guard_transform
|
||||
from rasterio.vfs import parse_path, vsi_path
|
||||
|
||||
|
||||
# The currently active GDAL/AWS environment is a private attribute.
|
||||
_env = None
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Env(GDALEnv):
|
||||
"""Abstraction for GDAL and AWS configuration
|
||||
|
||||
The GDAL library is stateful: it has a registry of format drivers,
|
||||
an error stack, and dozens of configuration options.
|
||||
|
||||
Rasterio's approach to working with GDAL is to wrap all the state
|
||||
up using a Python context manager (see PEP 343,
|
||||
https://www.python.org/dev/peps/pep-0343/). When the context is
|
||||
entered GDAL drivers are registered, error handlers are
|
||||
configured, and configuration options are set. When the context
|
||||
is exited, drivers are removed from the registry and other
|
||||
configurations are removed.
|
||||
|
||||
Example:
|
||||
|
||||
with Env(GDAL_CACHEMAX=512) as env:
|
||||
# All drivers are registered, GDAL's raster block cache
|
||||
# size is set to 512MB.
|
||||
# Commence processing...
|
||||
...
|
||||
# End of processing.
|
||||
|
||||
# At this point, configuration options are set to their
|
||||
# previous (possible unset) values.
|
||||
|
||||
A boto3 session or boto3 session constructor arguments
|
||||
`aws_access_key_id`, `aws_secret_access_key`, `aws_session_token`
|
||||
may be passed to Env's constructor. In the latter case, a session
|
||||
will be created as soon as needed. AWS credentials are configured
|
||||
for GDAL as needed.
|
||||
"""
|
||||
|
||||
def __init__(self, aws_session=None, **options):
|
||||
"""Create a new GDAL/AWS environment.
|
||||
|
||||
Note: this class is a context manager. GDAL isn't configured
|
||||
until the context is entered via `with Env():`
|
||||
|
||||
Parameters
|
||||
----------
|
||||
aws_session: object, optional
|
||||
A boto3 session.
|
||||
**options: optional
|
||||
A mapping of boto3 session constructor keyword arguments
|
||||
and GDAL configuration options.
|
||||
|
||||
Returns
|
||||
-------
|
||||
A new instance of Env.
|
||||
"""
|
||||
global _env
|
||||
if _env and _env.managing:
|
||||
raise EnvError("GDAL is currently configured. "
|
||||
"Multiple configuration is not allowed.")
|
||||
super(Env, self).__init__(**options)
|
||||
self.aws_session = aws_session
|
||||
self._creds = (
|
||||
self.aws_session._session.get_credentials()
|
||||
if self.aws_session else None)
|
||||
self.start()
|
||||
self.managing = False
|
||||
_env = self
|
||||
|
||||
def get_aws_credentials(self):
|
||||
"""Get credentials and configure GDAL."""
|
||||
import boto3
|
||||
self.aws_session = boto3.Session(
|
||||
aws_access_key_id=self.options.get('aws_access_key_id'),
|
||||
aws_secret_access_key=self.options.get('aws_secret_access_key'),
|
||||
aws_session_token=self.options.get('aws_session_token'),
|
||||
region_name=self.options.get('region_name'),
|
||||
profile_name=self.options.get('profile_name'))
|
||||
self._creds = self.aws_session._session.get_credentials()
|
||||
|
||||
# Pass these credentials to the GDAL environment.
|
||||
options = {}
|
||||
if self._creds.access_key: # pragma: no branch
|
||||
options.update(AWS_ACCESS_KEY_ID=self._creds.access_key)
|
||||
if self._creds.secret_key: # pragma: no branch
|
||||
options.update(AWS_SECRET_ACCESS_KEY=self._creds.secret_key)
|
||||
if self._creds.token:
|
||||
options.update(AWS_SESSION_TOKEN=self._creds.token)
|
||||
if self.aws_session.region_name:
|
||||
options.update(AWS_REGION=self.aws_session.region_name)
|
||||
self.update_config_options(**options)
|
||||
|
||||
def __enter__(self):
|
||||
self.enter_config_options()
|
||||
self.managing = True
|
||||
log.debug("Entering env %r context", self)
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type=None, exc_val=None, exc_tb=None):
|
||||
global _env
|
||||
self.exit_config_options()
|
||||
self.stop()
|
||||
self.managing = False
|
||||
_env = None
|
||||
log.debug("Exiting env %r context", self)
|
||||
|
||||
|
||||
def setenv():
|
||||
"""Assert that there is a GDAL environment, creating it if needed
|
||||
|
||||
This is the function to be called by methods like `rasterio.open()`
|
||||
that need a default environment.
|
||||
"""
|
||||
global _env
|
||||
if not _env:
|
||||
_env = Env()
|
||||
log.debug("New GDAL environment created %r", _env)
|
||||
@ -1,4 +1,4 @@
|
||||
"""Errors."""
|
||||
"""Errors and Warnings."""
|
||||
|
||||
from click import FileError
|
||||
|
||||
@ -8,6 +8,11 @@ class CRSError(ValueError):
|
||||
to define a coordinate transformation."""
|
||||
|
||||
|
||||
class EnvError(Exception):
|
||||
"""Raised when the state of GDAL/AWS environment cannot be created
|
||||
or modified."""
|
||||
|
||||
|
||||
class DriverRegistrationError(ValueError):
|
||||
"""Raised when a format driver is requested but is not registered."""
|
||||
|
||||
@ -23,3 +28,12 @@ class FileOverwriteError(FileError):
|
||||
class RasterioIOError(IOError):
|
||||
"""Raised when a dataset cannot be opened using one of the
|
||||
registered format drivers."""
|
||||
|
||||
|
||||
class NodataShadowWarning(Warning):
|
||||
"""Warn that a dataset's nodata attribute is shadowing its alpha band."""
|
||||
|
||||
def __str__(self):
|
||||
return ("The dataset's nodata attribute is shadowing "
|
||||
"the alpha band. All masks will be determined "
|
||||
"by the nodata attribute")
|
||||
|
||||
@ -9,6 +9,7 @@ import numpy as np
|
||||
|
||||
import rasterio
|
||||
from rasterio._features import _shapes, _sieve, _rasterize, _bounds
|
||||
import rasterio.env
|
||||
from rasterio.transform import IDENTITY, guard_transform
|
||||
from rasterio.dtypes import validate_dtype, can_cast_dtype, get_minimum_dtype
|
||||
|
||||
@ -97,10 +98,9 @@ def shapes(image, mask=None, connectivity=4, transform=IDENTITY):
|
||||
|
||||
"""
|
||||
transform = guard_transform(transform)
|
||||
|
||||
with rasterio.drivers():
|
||||
for s, v in _shapes(image, mask, connectivity, transform.to_gdal()):
|
||||
yield s, v
|
||||
rasterio.env.setenv()
|
||||
for s, v in _shapes(image, mask, connectivity, transform.to_gdal()):
|
||||
yield s, v
|
||||
|
||||
|
||||
def sieve(image, size, out=None, output=None, mask=None, connectivity=4):
|
||||
@ -156,9 +156,9 @@ def sieve(image, size, out=None, output=None, mask=None, connectivity=4):
|
||||
if out is None:
|
||||
out = np.zeros(image.shape, image.dtype)
|
||||
|
||||
with rasterio.drivers():
|
||||
_sieve(image, size, out, mask, connectivity)
|
||||
return out
|
||||
rasterio.env.setenv()
|
||||
_sieve(image, size, out, mask, connectivity)
|
||||
return out
|
||||
|
||||
|
||||
def rasterize(
|
||||
@ -302,8 +302,8 @@ def rasterize(
|
||||
|
||||
transform = guard_transform(transform)
|
||||
|
||||
with rasterio.drivers():
|
||||
_rasterize(valid_shapes, out, transform.to_gdal(), all_touched)
|
||||
rasterio.env.setenv()
|
||||
_rasterize(valid_shapes, out, transform.to_gdal(), all_touched)
|
||||
|
||||
return out
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
import rasterio
|
||||
from rasterio._fill import _fillnodata
|
||||
|
||||
from rasterio.env import setenv
|
||||
|
||||
def fillnodata(
|
||||
image,
|
||||
@ -49,6 +49,6 @@ def fillnodata(
|
||||
"""
|
||||
max_search_distance = float(max_search_distance)
|
||||
smoothing_iterations = int(smoothing_iterations)
|
||||
with rasterio.drivers():
|
||||
return _fillnodata(
|
||||
image, mask, max_search_distance, smoothing_iterations)
|
||||
rasterio.env.setenv()
|
||||
return _fillnodata(
|
||||
image, mask, max_search_distance, smoothing_iterations)
|
||||
|
||||
@ -3,15 +3,18 @@
|
||||
import itertools
|
||||
import sys
|
||||
|
||||
|
||||
if sys.version_info[0] >= 3: # pragma: no cover
|
||||
string_types = str,
|
||||
text_type = str
|
||||
integer_types = int,
|
||||
zip_longest = itertools.zip_longest
|
||||
import configparser
|
||||
from urllib.parse import urlparse
|
||||
else: # pragma: no cover
|
||||
string_types = basestring,
|
||||
text_type = unicode
|
||||
integer_types = int, long
|
||||
zip_longest = itertools.izip_longest
|
||||
import ConfigParser as configparser
|
||||
from urlparse import urlparse
|
||||
|
||||
@ -10,6 +10,7 @@ from cligj import (
|
||||
|
||||
from .helpers import write_features, to_lower
|
||||
import rasterio
|
||||
from rasterio.env import Env
|
||||
from rasterio.warp import transform_bounds
|
||||
|
||||
logger = logging.getLogger('rio')
|
||||
@ -47,7 +48,6 @@ def bounds(ctx, input, precision, indent, compact, projection, dst_crs,
|
||||
"""
|
||||
import rasterio.warp
|
||||
verbosity = (ctx.obj and ctx.obj.get('verbosity')) or 1
|
||||
aws_session = (ctx.obj and ctx.obj.get('aws_session'))
|
||||
logger = logging.getLogger('rio')
|
||||
dump_kwds = {'sort_keys': True}
|
||||
if indent:
|
||||
@ -59,9 +59,10 @@ def bounds(ctx, input, precision, indent, compact, projection, dst_crs,
|
||||
# This is the generator for (feature, bbox) pairs.
|
||||
class Collection(object):
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, env):
|
||||
self._xs = []
|
||||
self._ys = []
|
||||
self.env = env
|
||||
|
||||
@property
|
||||
def bbox(self):
|
||||
@ -105,13 +106,10 @@ def bounds(ctx, input, precision, indent, compact, projection, dst_crs,
|
||||
self._xs.extend(bbox[::2])
|
||||
self._ys.extend(bbox[1::2])
|
||||
|
||||
col = Collection()
|
||||
# Use the generator defined above as input to the generic output
|
||||
# writing function.
|
||||
try:
|
||||
with rasterio.drivers(CPL_DEBUG=verbosity > 2), aws_session:
|
||||
with Env(CPL_DEBUG=verbosity > 2) as env:
|
||||
write_features(
|
||||
stdout, col, sequence=sequence,
|
||||
stdout, Collection(env), sequence=sequence,
|
||||
geojson_type=geojson_type, use_rs=use_rs,
|
||||
**dump_kwds)
|
||||
|
||||
|
||||
@ -10,16 +10,17 @@ from cligj import files_inout_arg
|
||||
from .helpers import resolve_inout
|
||||
from . import options
|
||||
import rasterio
|
||||
from rasterio.env import Env
|
||||
from rasterio.fill import fillnodata
|
||||
from rasterio.features import sieve
|
||||
|
||||
|
||||
def get_bands(inputs, d, i=None):
|
||||
"""Get a rasterio.Band object from calc's inputs"""
|
||||
path = inputs[d] if d in dict(inputs) else inputs[int(d)-1][1]
|
||||
path = inputs[d] if d in dict(inputs) else inputs[int(d) - 1][1]
|
||||
src = rasterio.open(path)
|
||||
return (rasterio.band(src, i) if i else
|
||||
[rasterio.band(src, i) for i in src.indexes])
|
||||
return (rasterio.band(src, i) if i else
|
||||
[rasterio.band(src, j) for j in src.indexes])
|
||||
|
||||
|
||||
def read_array(ix, subix=None, dtype=None):
|
||||
@ -87,12 +88,11 @@ def calc(ctx, command, files, output, name, dtype, masked, force_overwrite,
|
||||
import numpy as np
|
||||
|
||||
verbosity = (ctx.obj and ctx.obj.get('verbosity')) or 1
|
||||
logger = logging.getLogger('rio')
|
||||
|
||||
try:
|
||||
with rasterio.drivers(CPL_DEBUG=verbosity > 2):
|
||||
with Env(CPL_DEBUG=verbosity > 2) as env:
|
||||
output, files = resolve_inout(files=files, output=output,
|
||||
force_overwrite=force_overwrite)
|
||||
force_overwrite=force_overwrite)
|
||||
|
||||
inputs = ([tuple(n.split('=')) for n in name] +
|
||||
[(None, n) for n in files])
|
||||
@ -115,7 +115,7 @@ def calc(ctx, command, files, output, name, dtype, masked, force_overwrite,
|
||||
#
|
||||
# possibly something to do with the instance being
|
||||
# a masked array.
|
||||
ctxkwds[name or '_i%d' % (i+1)] = src.read(masked=masked)
|
||||
ctxkwds[name or '_i%d' % (i + 1)] = src.read(masked=masked)
|
||||
|
||||
# Extend snuggs.
|
||||
snuggs.func_map['read'] = read_array
|
||||
@ -145,6 +145,6 @@ def calc(ctx, command, files, output, name, dtype, masked, force_overwrite,
|
||||
except snuggs.ExpressionError as err:
|
||||
click.echo("Expression Error:")
|
||||
click.echo(' %s' % err.text)
|
||||
click.echo(' ' + ' ' * err.offset + "^")
|
||||
click.echo(' ' + ' ' * err.offset + "^")
|
||||
click.echo(err)
|
||||
raise click.Abort()
|
||||
|
||||
@ -7,6 +7,7 @@ from .helpers import resolve_inout
|
||||
from . import options
|
||||
import rasterio
|
||||
from rasterio.coords import disjoint_bounds
|
||||
from rasterio.env import Env
|
||||
|
||||
|
||||
# Clip command
|
||||
@ -54,9 +55,8 @@ def clip(
|
||||
from rasterio.warp import transform_bounds
|
||||
|
||||
verbosity = (ctx.obj and ctx.obj.get('verbosity')) or 1
|
||||
aws_session = (ctx.obj and ctx.obj.get('aws_session'))
|
||||
|
||||
with rasterio.drivers(CPL_DEBUG=verbosity > 2), aws_session:
|
||||
with Env(CPL_DEBUG=verbosity > 2) as env:
|
||||
|
||||
output, files = resolve_inout(files=files, output=output)
|
||||
input = files[0]
|
||||
|
||||
@ -9,6 +9,7 @@ import numpy as np
|
||||
from .helpers import resolve_inout
|
||||
from . import options
|
||||
import rasterio
|
||||
from rasterio.env import Env
|
||||
|
||||
|
||||
@click.command(short_help="Copy and convert raster dataset.")
|
||||
@ -55,9 +56,8 @@ def convert(
|
||||
|
||||
"""
|
||||
verbosity = (ctx.obj and ctx.obj.get('verbosity')) or 1
|
||||
logger = logging.getLogger('rio')
|
||||
|
||||
with rasterio.drivers(CPL_DEBUG=verbosity > 2):
|
||||
with Env(CPL_DEBUG=verbosity > 2) as env:
|
||||
|
||||
outputfile, files = resolve_inout(files=files, output=output)
|
||||
inputfile = files[0]
|
||||
|
||||
@ -8,6 +8,7 @@ import click
|
||||
from . import options
|
||||
import rasterio
|
||||
import rasterio.crs
|
||||
from rasterio.env import Env
|
||||
from rasterio.transform import guard_transform
|
||||
|
||||
|
||||
@ -118,7 +119,6 @@ def edit(ctx, input, nodata, crs, transform, tags, allmd, like):
|
||||
import numpy as np
|
||||
|
||||
verbosity = (ctx.obj and ctx.obj.get('verbosity')) or 1
|
||||
logger = logging.getLogger('rio')
|
||||
|
||||
def in_dtype_range(value, dtype):
|
||||
infos = {'c': np.finfo, 'f': np.finfo, 'i': np.iinfo,
|
||||
@ -126,7 +126,7 @@ def edit(ctx, input, nodata, crs, transform, tags, allmd, like):
|
||||
rng = infos[np.dtype(dtype).kind](dtype)
|
||||
return rng.min <= value <= rng.max
|
||||
|
||||
with rasterio.drivers(CPL_DEBUG=(verbosity > 2)) as env:
|
||||
with Env(CPL_DEBUG=(verbosity > 2)) as env:
|
||||
|
||||
with rasterio.open(input, 'r+') as dst:
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@ import click
|
||||
|
||||
import rasterio
|
||||
import rasterio.crs
|
||||
from rasterio.env import Env
|
||||
|
||||
|
||||
@click.command(short_help="Print information about the rio environment.")
|
||||
@ -17,9 +18,8 @@ def env(ctx, key):
|
||||
formats, etc.
|
||||
"""
|
||||
verbosity = (ctx.obj and ctx.obj.get('verbosity')) or 1
|
||||
logger = logging.getLogger('rio')
|
||||
stdout = click.get_text_stream('stdout')
|
||||
with rasterio.drivers(CPL_DEBUG=(verbosity > 2)) as env:
|
||||
with Env(CPL_DEBUG=(verbosity > 2)) as env:
|
||||
if key == 'formats':
|
||||
for k, v in sorted(env.drivers().items()):
|
||||
stdout.write("%s: %s\n" % (k, v))
|
||||
|
||||
@ -5,8 +5,8 @@ import json
|
||||
import click
|
||||
|
||||
from . import options
|
||||
import rasterio
|
||||
import rasterio.crs
|
||||
from rasterio.env import Env
|
||||
|
||||
|
||||
@click.command(short_help="Print information about a data file.")
|
||||
@ -61,11 +61,9 @@ def info(ctx, input, aspect, indent, namespace, meta_member, verbose, bidx,
|
||||
Optionally print a single metadata item as a string.
|
||||
"""
|
||||
verbosity = ctx.obj.get('verbosity')
|
||||
aws_session = ctx.obj.get('aws_session')
|
||||
mode = 'r' if (verbose or meta_member == 'stats') else 'r-'
|
||||
try:
|
||||
with rasterio.drivers(
|
||||
CPL_DEBUG=(verbosity > 2)), aws_session:
|
||||
with Env(CPL_DEBUG=(verbosity > 2)):
|
||||
with rasterio.open(input, mode) as src:
|
||||
info = src.profile
|
||||
info['transform'] = info['affine'][:6]
|
||||
|
||||
@ -12,8 +12,9 @@ import numpy
|
||||
import click
|
||||
|
||||
from . import options
|
||||
from rasterio.plot import show, show_hist
|
||||
import rasterio
|
||||
from rasterio.env import Env
|
||||
from rasterio.plot import show, show_hist
|
||||
|
||||
try:
|
||||
import matplotlib.pyplot as plt
|
||||
@ -77,10 +78,9 @@ def insp(ctx, input, mode, interpreter):
|
||||
""" Open the input file in a Python interpreter.
|
||||
"""
|
||||
verbosity = (ctx.obj and ctx.obj.get('verbosity')) or 1
|
||||
aws_session = (ctx.obj and ctx.obj.get('aws_session'))
|
||||
logger = logging.getLogger('rio')
|
||||
try:
|
||||
with rasterio.drivers(CPL_DEBUG=verbosity > 2), aws_session:
|
||||
with Env(CPL_DEBUG=verbosity > 2) as env:
|
||||
with rasterio.open(input, mode) as src:
|
||||
main(
|
||||
'Rasterio %s Interactive Inspector (Python %s)\n'
|
||||
|
||||
@ -20,29 +20,6 @@ def configure_logging(verbosity):
|
||||
logging.basicConfig(stream=sys.stderr, level=log_level)
|
||||
|
||||
|
||||
class FakeSession(object):
|
||||
"""Fake AWS Session."""
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, *args):
|
||||
pass
|
||||
|
||||
def open(self, path, mode='r'):
|
||||
return rasterio.open(path, mode)
|
||||
|
||||
|
||||
def get_aws_session(profile_name):
|
||||
"""Return a credentialed AWS session or a fake, depending on
|
||||
whether boto3 could be imported."""
|
||||
try:
|
||||
import rasterio.aws
|
||||
return rasterio.aws.Session(profile_name=profile_name)
|
||||
except ImportError: # pragma: no cover
|
||||
return FakeSession()
|
||||
|
||||
|
||||
def gdal_version_cb(ctx, param, value):
|
||||
if not value or ctx.resilient_parsing:
|
||||
return
|
||||
@ -69,4 +46,3 @@ def main_group(ctx, verbose, quiet, aws_profile, gdal_version):
|
||||
configure_logging(verbosity)
|
||||
ctx.obj = {}
|
||||
ctx.obj['verbosity'] = verbosity
|
||||
ctx.obj['aws_session'] = get_aws_session(aws_profile)
|
||||
|
||||
@ -8,6 +8,7 @@ import cligj
|
||||
from .helpers import resolve_inout
|
||||
from . import options
|
||||
import rasterio
|
||||
from rasterio.env import Env
|
||||
|
||||
logger = logging.getLogger('rio')
|
||||
|
||||
@ -71,7 +72,6 @@ def mask(
|
||||
from rasterio.features import bounds as calculate_bounds
|
||||
|
||||
verbosity = (ctx.obj and ctx.obj.get('verbosity')) or 1
|
||||
logger = logging.getLogger('rio')
|
||||
|
||||
output, files = resolve_inout(
|
||||
files=files, output=output, force_overwrite=force_overwrite)
|
||||
@ -87,7 +87,7 @@ def mask(
|
||||
click.echo('Invert option ignored when using --crop', err=True)
|
||||
invert = False
|
||||
|
||||
with rasterio.drivers(CPL_DEBUG=verbosity > 2):
|
||||
with Env(CPL_DEBUG=verbosity > 2) as env:
|
||||
try:
|
||||
with click.open_file(geojson_mask) as fh:
|
||||
geojson = json.loads(fh.read())
|
||||
@ -103,7 +103,6 @@ def mask(
|
||||
else:
|
||||
raise click.BadParameter('Invalid GeoJSON', param=input,
|
||||
param_hint='input')
|
||||
bounds = geojson.get('bbox', calculate_bounds(geojson))
|
||||
|
||||
with rasterio.open(input) as src:
|
||||
try:
|
||||
@ -115,7 +114,8 @@ def mask(
|
||||
if crop:
|
||||
raise click.BadParameter('not allowed for GeoJSON '
|
||||
'outside the extent of the '
|
||||
'input raster', param=crop,
|
||||
'input raster',
|
||||
param=crop,
|
||||
param_hint='--crop')
|
||||
|
||||
meta = src.meta.copy()
|
||||
|
||||
@ -10,6 +10,7 @@ from cligj import files_inout_arg, format_opt
|
||||
from .helpers import resolve_inout
|
||||
from . import options
|
||||
import rasterio
|
||||
from rasterio.env import Env
|
||||
from rasterio.transform import Affine
|
||||
|
||||
|
||||
@ -27,7 +28,7 @@ from rasterio.transform import Affine
|
||||
@options.creation_options
|
||||
@click.pass_context
|
||||
def merge(ctx, files, output, driver, bounds, res, nodata, force_overwrite,
|
||||
precision, creation_options):
|
||||
precision, creation_options):
|
||||
"""Copy valid pixels from input files to an output file.
|
||||
|
||||
All files must have the same number of bands, data type, and
|
||||
@ -51,23 +52,23 @@ def merge(ctx, files, output, driver, bounds, res, nodata, force_overwrite,
|
||||
from rasterio.merge import merge as merge_tool
|
||||
|
||||
verbosity = (ctx.obj and ctx.obj.get('verbosity')) or 1
|
||||
logger = logging.getLogger('rio')
|
||||
|
||||
output, files = resolve_inout(
|
||||
files=files, output=output, force_overwrite=force_overwrite)
|
||||
|
||||
sources = [rasterio.open(f) for f in files]
|
||||
dest, output_transform = merge_tool(sources, bounds=bounds, res=res,
|
||||
nodata=nodata, precision=precision)
|
||||
with Env(CPL_DEBUG=verbosity > 2) as env:
|
||||
sources = [rasterio.open(f) for f in files]
|
||||
dest, output_transform = merge_tool(sources, bounds=bounds, res=res,
|
||||
nodata=nodata, precision=precision)
|
||||
|
||||
profile = sources[0].profile
|
||||
profile.pop('affine')
|
||||
profile['transform'] = output_transform
|
||||
profile['height'] = dest.shape[1]
|
||||
profile['width'] = dest.shape[2]
|
||||
profile['driver'] = driver
|
||||
profile = sources[0].profile
|
||||
profile.pop('affine')
|
||||
profile['transform'] = output_transform
|
||||
profile['height'] = dest.shape[1]
|
||||
profile['width'] = dest.shape[2]
|
||||
profile['driver'] = driver
|
||||
|
||||
profile.update(**creation_options)
|
||||
profile.update(**creation_options)
|
||||
|
||||
with rasterio.open(output, 'w', **profile) as dst:
|
||||
dst.write(dest)
|
||||
with rasterio.open(output, 'w', **profile) as dst:
|
||||
dst.write(dest)
|
||||
|
||||
@ -7,10 +7,10 @@ import operator
|
||||
|
||||
import click
|
||||
|
||||
from . import options
|
||||
import rasterio
|
||||
from rasterio.enums import Resampling
|
||||
|
||||
from . import options
|
||||
from rasterio.env import Env
|
||||
|
||||
|
||||
def build_handler(ctx, param, value):
|
||||
@ -68,9 +68,8 @@ def overview(ctx, input, build, ls, rebuild, resampling):
|
||||
|
||||
"""
|
||||
verbosity = (ctx.obj and ctx.obj.get('verbosity')) or 1
|
||||
logger = logging.getLogger('rio')
|
||||
|
||||
with rasterio.drivers(CPL_DEBUG=(verbosity > 2)):
|
||||
with Env(CPL_DEBUG=(verbosity > 2)) as env:
|
||||
with rasterio.open(input, 'r+') as dst:
|
||||
|
||||
if ls:
|
||||
|
||||
@ -11,6 +11,8 @@ from . import options
|
||||
import rasterio
|
||||
from rasterio.transform import Affine
|
||||
from rasterio.coords import disjoint_bounds
|
||||
from rasterio.env import Env
|
||||
|
||||
|
||||
logger = logging.getLogger('rio')
|
||||
|
||||
@ -126,7 +128,7 @@ def rasterize(
|
||||
if fill == int(fill):
|
||||
fill = int(fill)
|
||||
|
||||
with rasterio.drivers(CPL_DEBUG=verbosity > 2):
|
||||
with Env(CPL_DEBUG=verbosity > 2):
|
||||
|
||||
def feature_value(feature):
|
||||
if prop and 'properties' in feature:
|
||||
|
||||
@ -4,6 +4,7 @@ import logging
|
||||
import click
|
||||
|
||||
import rasterio
|
||||
from rasterio.env import Env
|
||||
|
||||
|
||||
@click.command(short_help="Sample a dataset.")
|
||||
@ -53,7 +54,6 @@ def sample(ctx, files, bidx):
|
||||
|
||||
"""
|
||||
verbosity = (ctx.obj and ctx.obj.get('verbosity')) or 1
|
||||
aws_session = (ctx.obj and ctx.obj.get('aws_session'))
|
||||
logger = logging.getLogger('rio')
|
||||
|
||||
files = list(files)
|
||||
@ -67,7 +67,7 @@ def sample(ctx, files, bidx):
|
||||
points = [input]
|
||||
|
||||
try:
|
||||
with rasterio.drivers(CPL_DEBUG=verbosity > 2), aws_session:
|
||||
with Env(CPL_DEBUG=verbosity > 2) as env:
|
||||
with rasterio.open(source) as src:
|
||||
if bidx is None:
|
||||
indexes = src.indexes
|
||||
|
||||
@ -7,6 +7,7 @@ import cligj
|
||||
from .helpers import coords, write_features
|
||||
from . import options
|
||||
import rasterio
|
||||
from rasterio.env import Env
|
||||
from rasterio.transform import Affine
|
||||
|
||||
logger = logging.getLogger('rio')
|
||||
@ -92,7 +93,6 @@ def shapes(
|
||||
import rasterio.warp
|
||||
|
||||
verbosity = ctx.obj['verbosity'] if ctx.obj else 1
|
||||
aws_session = (ctx.obj and ctx.obj.get('aws_session'))
|
||||
logger = logging.getLogger('rio')
|
||||
dump_kwds = {'sort_keys': True}
|
||||
if indent:
|
||||
@ -108,9 +108,10 @@ def shapes(
|
||||
# This is the generator for (feature, bbox) pairs.
|
||||
class Collection(object):
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, env):
|
||||
self._xs = []
|
||||
self._ys = []
|
||||
self.env = env
|
||||
|
||||
@property
|
||||
def bbox(self):
|
||||
@ -142,7 +143,7 @@ def shapes(
|
||||
msk = src.read_masks(bidx)
|
||||
else:
|
||||
msk_shape = (
|
||||
src.height//sampling, src.width//sampling)
|
||||
src.height // sampling, src.width // sampling)
|
||||
if bidx is None:
|
||||
msk = numpy.zeros(
|
||||
(src.count,) + msk_shape, 'uint8')
|
||||
@ -162,7 +163,7 @@ def shapes(
|
||||
img = src.read(bidx, masked=False)
|
||||
else:
|
||||
img = numpy.zeros(
|
||||
(src.height//sampling, src.width//sampling),
|
||||
(src.height // sampling, src.width // sampling),
|
||||
dtype=src.dtypes[src.indexes.index(bidx)])
|
||||
img = src.read(bidx, img, masked=False)
|
||||
|
||||
@ -219,9 +220,9 @@ def shapes(
|
||||
geojson_type = 'collection'
|
||||
|
||||
try:
|
||||
with rasterio.drivers(CPL_DEBUG=(verbosity > 2)), aws_session:
|
||||
with Env(CPL_DEBUG=(verbosity > 2)) as env:
|
||||
write_features(
|
||||
stdout, Collection(), sequence=sequence,
|
||||
stdout, Collection(env), sequence=sequence,
|
||||
geojson_type=geojson_type, use_rs=use_rs,
|
||||
**dump_kwds)
|
||||
except Exception:
|
||||
|
||||
@ -8,6 +8,7 @@ from cligj import files_inout_arg, format_opt
|
||||
from .helpers import resolve_inout
|
||||
from . import options
|
||||
import rasterio
|
||||
from rasterio.env import Env
|
||||
from rasterio.five import zip_longest
|
||||
|
||||
|
||||
@ -58,9 +59,9 @@ def stack(ctx, files, output, driver, bidx, photometric, force_overwrite,
|
||||
verbosity = (ctx.obj and ctx.obj.get('verbosity')) or 2
|
||||
logger = logging.getLogger('rio')
|
||||
try:
|
||||
with rasterio.drivers(CPL_DEBUG=verbosity>2):
|
||||
with Env(CPL_DEBUG=verbosity > 2) as env:
|
||||
output, files = resolve_inout(files=files, output=output,
|
||||
force_overwrite=force_overwrite)
|
||||
force_overwrite=force_overwrite)
|
||||
output_count = 0
|
||||
indexes = []
|
||||
for path, item in zip_longest(files, bidx, fillvalue=None):
|
||||
@ -74,8 +75,8 @@ def stack(ctx, files, output, driver, bidx, photometric, force_overwrite,
|
||||
lambda x: int(x) if x else None, item.split('..'))
|
||||
if start is None:
|
||||
start = 1
|
||||
indexes.append(src_indexes[slice(start-1, stop)])
|
||||
output_count += len(src_indexes[slice(start-1, stop)])
|
||||
indexes.append(src_indexes[slice(start - 1, stop)])
|
||||
output_count += len(src_indexes[slice(start - 1, stop)])
|
||||
else:
|
||||
parts = list(map(int, item.split(',')))
|
||||
if len(parts) == 1:
|
||||
@ -108,7 +109,7 @@ def stack(ctx, files, output, driver, bidx, photometric, force_overwrite,
|
||||
dst_idx += 1
|
||||
elif isinstance(index, collections.Iterable):
|
||||
data = src.read(index)
|
||||
dst.write(data, range(dst_idx, dst_idx+len(index)))
|
||||
dst.write(data, range(dst_idx, dst_idx + len(index)))
|
||||
dst_idx += len(index)
|
||||
|
||||
except Exception:
|
||||
|
||||
@ -8,6 +8,7 @@ import click
|
||||
from cligj import precision_opt
|
||||
|
||||
import rasterio
|
||||
from rasterio.env import Env
|
||||
|
||||
|
||||
@click.command(short_help="Transform coordinates.")
|
||||
@ -31,7 +32,7 @@ def transform(ctx, input, src_crs, dst_crs, precision):
|
||||
src = [input]
|
||||
|
||||
try:
|
||||
with rasterio.drivers(CPL_DEBUG=verbosity > 2):
|
||||
with Env(CPL_DEBUG=verbosity > 2) as env:
|
||||
if src_crs.startswith('EPSG'):
|
||||
src_crs = {'init': src_crs}
|
||||
elif os.path.exists(src_crs):
|
||||
@ -50,7 +51,7 @@ def transform(ctx, input, src_crs, dst_crs, precision):
|
||||
if precision >= 0:
|
||||
xs = [round(v, precision) for v in xs]
|
||||
ys = [round(v, precision) for v in ys]
|
||||
result = [0]*len(coords)
|
||||
result = [0] * len(coords)
|
||||
result[::2] = xs
|
||||
result[1::2] = ys
|
||||
print(json.dumps(result))
|
||||
|
||||
@ -9,10 +9,11 @@ from .helpers import resolve_inout
|
||||
from . import options
|
||||
import rasterio
|
||||
from rasterio import crs
|
||||
from rasterio.env import Env
|
||||
from rasterio.errors import CRSError
|
||||
from rasterio.transform import Affine
|
||||
from rasterio.warp import (reproject, Resampling, calculate_default_transform,
|
||||
transform_bounds)
|
||||
from rasterio.warp import (
|
||||
reproject, Resampling, calculate_default_transform, transform_bounds)
|
||||
|
||||
|
||||
# Improper usage of rio-warp can lead to accidental creation of
|
||||
@ -25,7 +26,8 @@ MAX_OUTPUT_HEIGHT = 100000
|
||||
def bounds_handler(ctx, param, value):
|
||||
"""Warn about future usage changes."""
|
||||
if value:
|
||||
click.echo("Future Warning: "
|
||||
click.echo(
|
||||
"Future Warning: "
|
||||
"the semantics of the `--bounds` option will change in Rasterio "
|
||||
"version 1.0 from bounds of the source dataset to bounds of the "
|
||||
"destination dataset.", err=True)
|
||||
@ -35,7 +37,8 @@ def bounds_handler(ctx, param, value):
|
||||
def x_dst_bounds_handler(ctx, param, value):
|
||||
"""Warn about future usage changes."""
|
||||
if value:
|
||||
click.echo("Future Warning: "
|
||||
click.echo(
|
||||
"Future Warning: "
|
||||
"the `--x-dst-bounds` option will be removed in Rasterio version "
|
||||
"1.0 in favor of `--bounds`.", err=True)
|
||||
return value
|
||||
@ -121,7 +124,6 @@ def warp(ctx, files, output, driver, like, dst_crs, dimensions, src_bounds,
|
||||
"""
|
||||
|
||||
verbosity = (ctx.obj and ctx.obj.get('verbosity')) or 1
|
||||
logger = logging.getLogger('rio')
|
||||
|
||||
output, files = resolve_inout(
|
||||
files=files, output=output, force_overwrite=force_overwrite)
|
||||
@ -135,8 +137,8 @@ def warp(ctx, files, output, driver, like, dst_crs, dimensions, src_bounds,
|
||||
# Expand one value to two if needed
|
||||
res = (res[0], res[0]) if len(res) == 1 else res
|
||||
|
||||
with rasterio.drivers(CPL_DEBUG=verbosity > 2,
|
||||
CHECK_WITH_INVERT_PROJ=check_invert_proj):
|
||||
with Env(CPL_DEBUG=verbosity > 2,
|
||||
CHECK_WITH_INVERT_PROJ=check_invert_proj) as env:
|
||||
with rasterio.open(files[0]) as src:
|
||||
l, b, r, t = src.bounds
|
||||
out_kwargs = src.meta.copy()
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
|
||||
import os
|
||||
|
||||
from rasterio.five import urlparse
|
||||
|
||||
|
||||
# NB: As not to propagate fallacies of distributed computing, Rasterio
|
||||
# does not support HTTP or FTP URLs via GDAL's vsicurl handler. Only
|
||||
@ -14,18 +16,22 @@ def parse_path(path, vfs=None):
|
||||
"""Parse a file path or Apache VFS URL into its parts."""
|
||||
archive = scheme = None
|
||||
if vfs:
|
||||
parts = vfs.split("://")
|
||||
scheme = parts.pop(0) if parts else None
|
||||
archive = parts.pop(0) if parts else None
|
||||
parts = urlparse(vfs)
|
||||
scheme = parts.scheme
|
||||
archive = parts.path
|
||||
if parts.netloc and parts.netloc != 'localhost': # pragma: no cover
|
||||
archive = parts.netloc + archive
|
||||
else:
|
||||
parts = path.split("://")
|
||||
path = parts.pop() if parts else None
|
||||
scheme = parts.pop() if parts else None
|
||||
parts = urlparse(path)
|
||||
scheme = parts.scheme
|
||||
path = parts.path
|
||||
if parts.netloc and parts.netloc != 'localhost':
|
||||
path = parts.netloc + path
|
||||
if scheme in SCHEMES:
|
||||
parts = path.split('!')
|
||||
path = parts.pop() if parts else None
|
||||
archive = parts.pop() if parts else None
|
||||
elif scheme in (None, 'file'):
|
||||
elif scheme in (None, '', 'file'):
|
||||
pass
|
||||
else:
|
||||
raise ValueError("VFS scheme {0} is unknown".format(scheme))
|
||||
|
||||
@ -1,10 +0,0 @@
|
||||
"""Rasterio warnings."""
|
||||
|
||||
|
||||
class NodataShadowWarning(Warning):
|
||||
"""Warn that a dataset's nodata attribute is shadowing its alpha band."""
|
||||
|
||||
def __str__(self):
|
||||
return ("The dataset's nodata attribute is shadowing "
|
||||
"the alpha band. All masks will be determined "
|
||||
"by the nodata attribute")
|
||||
@ -13,6 +13,7 @@ from rasterio._base import _transform
|
||||
from rasterio._warp import (
|
||||
_transform_geom, _reproject, _calculate_default_transform)
|
||||
from rasterio.enums import Resampling
|
||||
import rasterio.env
|
||||
from rasterio.transform import guard_transform
|
||||
|
||||
|
||||
@ -47,6 +48,7 @@ def transform(src_crs, dst_crs, xs, ys, zs=None):
|
||||
Tuple of x, y, and optionally z vectors, transformed into the target
|
||||
coordinate reference system.
|
||||
"""
|
||||
rasterio.env.setenv()
|
||||
return _transform(src_crs, dst_crs, xs, ys, zs)
|
||||
|
||||
|
||||
@ -84,6 +86,7 @@ def transform_geom(
|
||||
out: GeoJSON like dict object
|
||||
Transformed geometry in GeoJSON dict format
|
||||
"""
|
||||
rasterio.env.setenv()
|
||||
return _transform_geom(
|
||||
src_crs,
|
||||
dst_crs,
|
||||
@ -244,6 +247,7 @@ def reproject(
|
||||
if dst_transform:
|
||||
dst_transform = guard_transform(dst_transform).to_gdal()
|
||||
|
||||
rasterio.env.setenv()
|
||||
_reproject(
|
||||
source,
|
||||
destination,
|
||||
@ -300,7 +304,7 @@ def calculate_default_transform(
|
||||
|
||||
Note
|
||||
----
|
||||
Must be called within a raster.drivers() context
|
||||
Should be called within a raster.env.Env() context
|
||||
|
||||
Some behavior of this function is determined by the
|
||||
CHECK_WITH_INVERT_PROJ environment variable
|
||||
@ -308,6 +312,7 @@ def calculate_default_transform(
|
||||
avoids visual artifacts and coordinate discontinuties.
|
||||
NO: reproject coordinates beyond valid bound limits
|
||||
"""
|
||||
rasterio.env.setenv()
|
||||
dst_affine, dst_width, dst_height = _calculate_default_transform(
|
||||
src_crs, dst_crs,
|
||||
width, height,
|
||||
|
||||
10
setup.py
10
setup.py
@ -75,7 +75,7 @@ library_dirs = []
|
||||
libraries = []
|
||||
extra_link_args = []
|
||||
gdal2plus = False
|
||||
gdal_output = [None]*4
|
||||
gdal_output = [None] * 4
|
||||
|
||||
try:
|
||||
import numpy
|
||||
@ -186,8 +186,8 @@ if os.path.exists("MANIFEST.in") and "clean" not in sys.argv:
|
||||
Extension(
|
||||
'rasterio._err', ['rasterio/_err.pyx'], **ext_options),
|
||||
Extension(
|
||||
'rasterio._example', ['rasterio/_example.pyx'], **ext_options),
|
||||
], quiet=True, **cythonize_options)
|
||||
'rasterio._example', ['rasterio/_example.pyx'], **ext_options)],
|
||||
quiet=True, **cythonize_options)
|
||||
|
||||
# If there's no manifest template, as in an sdist, we just specify .c files.
|
||||
else:
|
||||
@ -274,8 +274,8 @@ setup_args = dict(
|
||||
install_requires=inst_reqs,
|
||||
extras_require={
|
||||
'ipython': ['ipython>=2.0'],
|
||||
's3': ['boto3'],
|
||||
'test': ['boto3', 'packaging']})
|
||||
's3': ['boto3>=1.2.4'],
|
||||
'test': ['boto3>=1.2.4', 'packaging']})
|
||||
|
||||
if os.environ.get('PACKAGE_DATA'):
|
||||
setup_args['package_data'] = {'rasterio': ['gdal_data/*', 'proj_data/*']}
|
||||
|
||||
@ -17,16 +17,18 @@ if sys.version_info > (3,):
|
||||
reduce = functools.reduce
|
||||
|
||||
test_files = [os.path.join(os.path.dirname(__file__), p) for p in [
|
||||
'data/RGB.byte.tif', 'data/float.tif', 'data/float_nan.tif', 'data/shade.tif']]
|
||||
'data/RGB.byte.tif', 'data/float.tif', 'data/float_nan.tif',
|
||||
'data/shade.tif']]
|
||||
|
||||
|
||||
def pytest_cmdline_main(config):
|
||||
# Bail if the test raster data is not present. Test data is not
|
||||
# Bail if the test raster data is not present. Test data is not
|
||||
# distributed with sdists since 0.12.
|
||||
if reduce(operator.and_, map(os.path.exists, test_files)):
|
||||
print("Test data present.")
|
||||
else:
|
||||
print("Test data not present. See download directions in tests/data/README.rst")
|
||||
print("Test data not present. See download directions in "
|
||||
"tests/data/README.rst")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@ -146,8 +148,8 @@ def pixelated_image(basic_image):
|
||||
"""
|
||||
|
||||
image = basic_image.copy()
|
||||
image [0, 0] = 1
|
||||
image [8, 8] = 1
|
||||
image[0, 0] = 1
|
||||
image[8, 8] = 1
|
||||
|
||||
return image
|
||||
|
||||
@ -197,9 +199,8 @@ def basic_image_file(tmpdir, basic_image):
|
||||
"height": image.shape[0],
|
||||
"nodata": None
|
||||
}
|
||||
with rasterio.drivers():
|
||||
with rasterio.open(outfilename, 'w', **kwargs) as out:
|
||||
out.write(image, indexes=1)
|
||||
with rasterio.open(outfilename, 'w', **kwargs) as out:
|
||||
out.write(image, indexes=1)
|
||||
|
||||
return outfilename
|
||||
|
||||
@ -233,8 +234,7 @@ def pixelated_image_file(tmpdir, pixelated_image):
|
||||
"height": image.shape[0],
|
||||
"nodata": 255
|
||||
}
|
||||
with rasterio.drivers():
|
||||
with rasterio.open(outfilename, 'w', **kwargs) as out:
|
||||
out.write(image, indexes=1)
|
||||
with rasterio.open(outfilename, 'w', **kwargs) as out:
|
||||
out.write(image, indexes=1)
|
||||
|
||||
return outfilename
|
||||
|
||||
@ -1,159 +0,0 @@
|
||||
# Tests requiring S3 credentials.
|
||||
# Collected here to make them easier to skip/xfail.
|
||||
|
||||
import logging
|
||||
import sys
|
||||
|
||||
from packaging.version import parse
|
||||
import pytest
|
||||
|
||||
import rasterio
|
||||
from rasterio.aws import Session
|
||||
from rasterio.rio.main import main_group
|
||||
|
||||
|
||||
# Custom markers.
|
||||
mingdalversion = pytest.mark.skipif(
|
||||
parse(rasterio.__gdal_version__) < parse('2.1.0dev'),
|
||||
reason="S3 raster access requires GDAL 2.1")
|
||||
|
||||
credentials = pytest.mark.skipif(
|
||||
not(Session()._creds), 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"
|
||||
httpstif = "https://landsat-pds.s3.amazonaws.com/L8/139/045/LC81390452014295LGN00/LC81390452014295LGN00_B1.TIF"
|
||||
|
||||
|
||||
def test_session():
|
||||
"""Create a session with arguments."""
|
||||
s = Session(aws_access_key_id='id', aws_secret_access_key='key',
|
||||
aws_session_token='token', region_name='null-island-1')
|
||||
assert s._creds.access_key == 'id'
|
||||
assert s._creds.secret_key == 'key'
|
||||
assert s._creds.token == 'token'
|
||||
assert s._session.region_name == 'null-island-1'
|
||||
|
||||
|
||||
def test_session_env(monkeypatch):
|
||||
"""Create a session with env vars."""
|
||||
monkeypatch.setenv('AWS_ACCESS_KEY_ID', 'id')
|
||||
monkeypatch.setenv('AWS_SECRET_ACCESS_KEY', 'key')
|
||||
monkeypatch.setenv('AWS_SESSION_TOKEN', 'token')
|
||||
s = Session()
|
||||
assert s._creds.access_key == 'id'
|
||||
assert s._creds.secret_key == 'key'
|
||||
assert s._creds.token == 'token'
|
||||
monkeypatch.undo()
|
||||
|
||||
|
||||
@mingdalversion
|
||||
@credentials
|
||||
def test_with_session():
|
||||
"""Enter and exit a session."""
|
||||
with Session():
|
||||
with rasterio.open(L8TIF) as f:
|
||||
assert f.count == 1
|
||||
|
||||
|
||||
@mingdalversion
|
||||
@credentials
|
||||
def test_open_with_session():
|
||||
"""Enter and exit a session."""
|
||||
s = Session()
|
||||
with s.open(L8TIF) as f:
|
||||
assert f.count == 1
|
||||
|
||||
|
||||
@mingdalversion
|
||||
@credentials
|
||||
def test_open_with_session_minus_mode():
|
||||
"""Enter and exit a session, reading in 'r-' mode"""
|
||||
s = Session()
|
||||
with s.open(L8TIF, 'r-') as f:
|
||||
assert f.count == 1
|
||||
|
||||
@mingdalversion
|
||||
def test_open_as_https_vsicurl():
|
||||
"""Test the same object via https using vsicurl, reading in 'r-' mode"""
|
||||
s = Session()
|
||||
with s.open(httpstif, 'r-') as f:
|
||||
assert f.count == 1
|
||||
|
||||
# CLI tests.
|
||||
|
||||
@mingdalversion
|
||||
@credentials
|
||||
def test_rio_info(runner):
|
||||
"""S3 is supported by rio-info"""
|
||||
result = runner.invoke(main_group, ['info', L8TIF])
|
||||
assert result.exit_code == 0
|
||||
assert '"crs": "EPSG:32645"' in result.output
|
||||
|
||||
|
||||
@mingdalversion
|
||||
@credentials
|
||||
def test_https_rio_info(runner):
|
||||
"""HTTPS is supported by rio-info"""
|
||||
result = runner.invoke(main_group, ['info', httpstif])
|
||||
assert result.exit_code == 0
|
||||
assert '"crs": "EPSG:32645"' in result.output
|
||||
|
||||
|
||||
@mingdalversion
|
||||
@credentials
|
||||
def test_rio_insp(runner):
|
||||
"""S3 is supported by rio-insp"""
|
||||
result = runner.invoke(main_group, ['insp', L8TIF])
|
||||
assert result.exit_code == 0
|
||||
assert 'Interactive Inspector' in result.output
|
||||
|
||||
|
||||
@mingdalversion
|
||||
@credentials
|
||||
def test_rio_bounds(runner):
|
||||
"""S3 is supported by rio-bounds"""
|
||||
result = runner.invoke(main_group, ['bounds', '--bbox', L8TIF])
|
||||
assert result.exit_code == 0
|
||||
assert '[85.8' in result.output
|
||||
|
||||
|
||||
@mingdalversion
|
||||
@credentials
|
||||
def test_rio_shapes(runner):
|
||||
"""S3 is supported by rio-shapes"""
|
||||
result = runner.invoke(
|
||||
main_group, ['shapes', '--as-mask', '--sampling', '16', L8TIF])
|
||||
assert result.exit_code == 0
|
||||
assert 'FeatureCollection' in result.output
|
||||
|
||||
|
||||
@mingdalversion
|
||||
@credentials
|
||||
def test_rio_sample(runner):
|
||||
"""S3 is supported by rio-sample"""
|
||||
result = runner.invoke(
|
||||
main_group, ['sample', L8TIF], input="[420000, 2350000]")
|
||||
assert result.exit_code == 0
|
||||
assert '[10680]' in result.output
|
||||
|
||||
|
||||
@mingdalversion
|
||||
@credentials
|
||||
def test_rio_clip(runner, tmpdir):
|
||||
"""S3 is supported by rio-clip"""
|
||||
outputfile = tmpdir.join('clipped.tif')
|
||||
result = runner.invoke(
|
||||
main_group, ['clip', '--bounds', '420000', '2350000', '420060', '2350060',
|
||||
'-o', str(outputfile), L8TIF])
|
||||
assert result.exit_code == 0
|
||||
|
||||
|
||||
@mingdalversion
|
||||
@credentials
|
||||
def test_aws_open_bad_path():
|
||||
from rasterio.aws import Session
|
||||
with pytest.raises(TypeError):
|
||||
Session().open(3.14)
|
||||
@ -1,4 +1,10 @@
|
||||
import logging
|
||||
|
||||
import rasterio
|
||||
import rasterio.env
|
||||
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
|
||||
def test_band():
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
@ -7,4 +13,3 @@ def test_band():
|
||||
assert b.bidx == 1
|
||||
assert b.dtype in src.dtypes
|
||||
assert b.shape == src.shape
|
||||
|
||||
|
||||
@ -6,14 +6,12 @@ import pytest
|
||||
|
||||
import rasterio
|
||||
from rasterio.enums import MaskFlags
|
||||
from rasterio.warnings import NodataShadowWarning
|
||||
from rasterio.errors import NodataShadowWarning
|
||||
|
||||
|
||||
logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
|
||||
|
||||
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
def tiffs(tmpdir):
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
@ -84,34 +82,34 @@ def test_warning_shadow(tiffs):
|
||||
filename = str(tiffs.join('shadowed.tif'))
|
||||
with rasterio.open(filename) as src:
|
||||
with pytest.warns(NodataShadowWarning):
|
||||
_ = src.read_masks()
|
||||
src.read_masks()
|
||||
|
||||
|
||||
def test_masks():
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
rm, gm, bm = src.read_masks()
|
||||
r, g, b = src.read(masked=False)
|
||||
assert not r[rm==0].any()
|
||||
assert not g[gm==0].any()
|
||||
assert not b[bm==0].any()
|
||||
assert not r[rm == 0].any()
|
||||
assert not g[gm == 0].any()
|
||||
assert not b[bm == 0].any()
|
||||
|
||||
|
||||
def test_masked_true():
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
r, g, b = src.read(masked=True)
|
||||
rm, gm, bm = src.read_masks()
|
||||
assert (r.mask==~rm.astype('bool')).all()
|
||||
assert (g.mask==~gm.astype('bool')).all()
|
||||
assert (b.mask==~bm.astype('bool')).all()
|
||||
assert (r.mask == ~rm.astype('bool')).all()
|
||||
assert (g.mask == ~gm.astype('bool')).all()
|
||||
assert (b.mask == ~bm.astype('bool')).all()
|
||||
|
||||
|
||||
def test_masked_none():
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
r, g, b = src.read(masked=True)
|
||||
rm, gm, bm = src.read_masks()
|
||||
assert (r.mask==~rm.astype('bool')).all()
|
||||
assert (g.mask==~gm.astype('bool')).all()
|
||||
assert (b.mask==~bm.astype('bool')).all()
|
||||
assert (r.mask == ~rm.astype('bool')).all()
|
||||
assert (g.mask == ~gm.astype('bool')).all()
|
||||
assert (b.mask == ~bm.astype('bool')).all()
|
||||
|
||||
|
||||
def test_masking_no_nodata(tiffs):
|
||||
|
||||
@ -6,30 +6,28 @@ from rasterio.enums import ColorInterp, PhotometricInterp
|
||||
|
||||
def test_cmyk_interp(tmpdir):
|
||||
"""A CMYK TIFF has cyan, magenta, yellow, black bands."""
|
||||
with rasterio.drivers():
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
meta = src.meta
|
||||
meta['photometric'] = 'CMYK'
|
||||
meta['count'] = 4
|
||||
tiffname = str(tmpdir.join('foo.tif'))
|
||||
with rasterio.open(tiffname, 'w', **meta) as dst:
|
||||
assert dst.profile['photometric'] == 'cmyk'
|
||||
assert dst.colorinterp(1) == ColorInterp.cyan
|
||||
assert dst.colorinterp(2) == ColorInterp.magenta
|
||||
assert dst.colorinterp(3) == ColorInterp.yellow
|
||||
assert dst.colorinterp(4) == ColorInterp.black
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
meta = src.meta
|
||||
meta['photometric'] = 'CMYK'
|
||||
meta['count'] = 4
|
||||
tiffname = str(tmpdir.join('foo.tif'))
|
||||
with rasterio.open(tiffname, 'w', **meta) as dst:
|
||||
assert dst.profile['photometric'] == 'cmyk'
|
||||
assert dst.colorinterp(1) == ColorInterp.cyan
|
||||
assert dst.colorinterp(2) == ColorInterp.magenta
|
||||
assert dst.colorinterp(3) == ColorInterp.yellow
|
||||
assert dst.colorinterp(4) == ColorInterp.black
|
||||
|
||||
|
||||
def test_ycbcr_interp(tmpdir):
|
||||
"""A YCbCr TIFF has red, green, blue bands."""
|
||||
with rasterio.drivers():
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
meta = src.meta
|
||||
meta['photometric'] = 'ycbcr'
|
||||
meta['compress'] = 'jpeg'
|
||||
meta['count'] = 3
|
||||
tiffname = str(tmpdir.join('foo.tif'))
|
||||
with rasterio.open(tiffname, 'w', **meta) as dst:
|
||||
assert dst.colorinterp(1) == ColorInterp.red
|
||||
assert dst.colorinterp(2) == ColorInterp.green
|
||||
assert dst.colorinterp(3) == ColorInterp.blue
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
meta = src.meta
|
||||
meta['photometric'] = 'ycbcr'
|
||||
meta['compress'] = 'jpeg'
|
||||
meta['count'] = 3
|
||||
tiffname = str(tmpdir.join('foo.tif'))
|
||||
with rasterio.open(tiffname, 'w', **meta) as dst:
|
||||
assert dst.colorinterp(1) == ColorInterp.red
|
||||
assert dst.colorinterp(2) == ColorInterp.green
|
||||
assert dst.colorinterp(3) == ColorInterp.blue
|
||||
|
||||
@ -9,43 +9,28 @@ logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
|
||||
|
||||
|
||||
def test_write_colormap_warn(tmpdir, recwarn):
|
||||
|
||||
with rasterio.drivers():
|
||||
|
||||
with rasterio.open('tests/data/shade.tif') as src:
|
||||
profile = src.meta
|
||||
|
||||
tiffname = str(tmpdir.join('foo.tif'))
|
||||
|
||||
with rasterio.open(tiffname, 'w', **profile) as dst:
|
||||
dst.write_colormap(1, {0: (255, 0, 0, 255), 255: (0, 0, 0, 0)})
|
||||
|
||||
w = recwarn.pop(UserWarning)
|
||||
assert "The value will be ignored" in str(w.message)
|
||||
with rasterio.open('tests/data/shade.tif') as src:
|
||||
profile = src.meta
|
||||
tiffname = str(tmpdir.join('foo.tif'))
|
||||
with rasterio.open(tiffname, 'w', **profile) as dst:
|
||||
dst.write_colormap(1, {0: (255, 0, 0, 255), 255: (0, 0, 0, 0)})
|
||||
w = recwarn.pop(UserWarning)
|
||||
assert "The value will be ignored" in str(w.message)
|
||||
|
||||
|
||||
def test_write_colormap(tmpdir):
|
||||
|
||||
with rasterio.drivers():
|
||||
|
||||
with rasterio.open('tests/data/shade.tif') as src:
|
||||
shade = src.read(1)
|
||||
meta = src.meta
|
||||
|
||||
tiffname = str(tmpdir.join('foo.png'))
|
||||
meta['driver'] = 'PNG'
|
||||
|
||||
with rasterio.open(tiffname, 'w', **meta) as dst:
|
||||
dst.write(shade, indexes=1)
|
||||
dst.write_colormap(1, {0: (255, 0, 0, 255), 255: (0, 0, 0, 0)})
|
||||
cmap = dst.colormap(1)
|
||||
assert cmap[0] == (255, 0, 0, 255)
|
||||
assert cmap[255] == (0, 0, 0, 0)
|
||||
|
||||
with rasterio.open(tiffname) as src:
|
||||
cmap = src.colormap(1)
|
||||
assert cmap[0] == (255, 0, 0, 255)
|
||||
assert cmap[255] == (0, 0, 0, 0)
|
||||
|
||||
# subprocess.call(['open', tiffname])
|
||||
|
||||
with rasterio.open('tests/data/shade.tif') as src:
|
||||
shade = src.read(1)
|
||||
meta = src.meta
|
||||
tiffname = str(tmpdir.join('foo.png'))
|
||||
meta['driver'] = 'PNG'
|
||||
with rasterio.open(tiffname, 'w', **meta) as dst:
|
||||
dst.write(shade, indexes=1)
|
||||
dst.write_colormap(1, {0: (255, 0, 0, 255), 255: (0, 0, 0, 0)})
|
||||
cmap = dst.colormap(1)
|
||||
assert cmap[0] == (255, 0, 0, 255)
|
||||
assert cmap[255] == (0, 0, 0, 0)
|
||||
with rasterio.open(tiffname) as src:
|
||||
cmap = src.colormap(1)
|
||||
assert cmap[0] == (255, 0, 0, 255)
|
||||
assert cmap[255] == (0, 0, 0, 0)
|
||||
|
||||
@ -16,30 +16,27 @@ logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
|
||||
|
||||
# When possible, Rasterio gives you the CRS in the form of an EPSG code.
|
||||
def test_read_epsg(tmpdir):
|
||||
with rasterio.drivers():
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
assert src.crs == {'init': 'epsg:32618'}
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
assert src.crs == {'init': 'epsg:32618'}
|
||||
|
||||
def test_read_epsg3857(tmpdir):
|
||||
tiffname = str(tmpdir.join('lol.tif'))
|
||||
subprocess.call([
|
||||
'gdalwarp', '-t_srs', 'EPSG:3857',
|
||||
'gdalwarp', '-t_srs', 'EPSG:3857',
|
||||
'tests/data/RGB.byte.tif', tiffname])
|
||||
with rasterio.drivers():
|
||||
with rasterio.open(tiffname) as src:
|
||||
assert src.crs == {'init': 'epsg:3857'}
|
||||
with rasterio.open(tiffname) as src:
|
||||
assert src.crs == {'init': 'epsg:3857'}
|
||||
|
||||
# Ensure that CRS sticks when we write a file.
|
||||
def test_write_3857(tmpdir):
|
||||
src_path = str(tmpdir.join('lol.tif'))
|
||||
subprocess.call([
|
||||
'gdalwarp', '-t_srs', 'EPSG:3857',
|
||||
'gdalwarp', '-t_srs', 'EPSG:3857',
|
||||
'tests/data/RGB.byte.tif', src_path])
|
||||
dst_path = str(tmpdir.join('wut.tif'))
|
||||
with rasterio.drivers():
|
||||
with rasterio.open(src_path) as src:
|
||||
with rasterio.open(dst_path, 'w', **src.meta) as dst:
|
||||
assert dst.crs == {'init': 'epsg:3857'}
|
||||
with rasterio.open(src_path) as src:
|
||||
with rasterio.open(dst_path, 'w', **src.meta) as dst:
|
||||
assert dst.crs == {'init': 'epsg:3857'}
|
||||
info = subprocess.check_output([
|
||||
'gdalinfo', dst_path])
|
||||
# WKT string may vary a bit w.r.t GDAL versions
|
||||
|
||||
@ -2,8 +2,9 @@
|
||||
# This ensures that deprecation warnings are given but behavior is maintained
|
||||
# on the way to stabilizing the API for 1.0
|
||||
import warnings
|
||||
import pytest
|
||||
|
||||
import numpy
|
||||
import pytest
|
||||
|
||||
# New modules
|
||||
import rasterio
|
||||
@ -77,49 +78,46 @@ def test_window_union(recwarn):
|
||||
def test_stats(recwarn):
|
||||
from rasterio.tool import stats as stats_old
|
||||
from rasterio.rio.insp import stats as stats_new
|
||||
with rasterio.drivers():
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
warnings.simplefilter('always')
|
||||
old = stats_old((src, 1))
|
||||
assert len(recwarn) == 1
|
||||
assert recwarn.pop(DeprecationWarning)
|
||||
new = stats_new((src, 1))
|
||||
assert len(recwarn) == 0
|
||||
assert numpy.allclose(numpy.array(new), numpy.array(old))
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
warnings.simplefilter('always')
|
||||
old = stats_old((src, 1))
|
||||
assert len(recwarn) == 1
|
||||
assert recwarn.pop(DeprecationWarning)
|
||||
new = stats_new((src, 1))
|
||||
assert len(recwarn) == 0
|
||||
assert numpy.allclose(numpy.array(new), numpy.array(old))
|
||||
|
||||
|
||||
# xfail because for unknown reasons, travis fails with matplotlib errors
|
||||
# xfail because for unknown reasons, travis fails with matplotlib errors
|
||||
@pytest.mark.xfail
|
||||
def test_show(recwarn):
|
||||
from rasterio.tool import show as show_old
|
||||
with rasterio.drivers():
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
warnings.simplefilter('always')
|
||||
old = show_old((src, 1))
|
||||
assert len(recwarn) == 1
|
||||
assert recwarn.pop(DeprecationWarning)
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
warnings.simplefilter('always')
|
||||
old = show_old((src, 1))
|
||||
assert len(recwarn) == 1
|
||||
assert recwarn.pop(DeprecationWarning)
|
||||
|
||||
from rasterio.plot import show as show_new
|
||||
new = show_new((src, 1))
|
||||
assert len(recwarn) == 0
|
||||
assert new == old
|
||||
from rasterio.plot import show as show_new
|
||||
new = show_new((src, 1))
|
||||
assert len(recwarn) == 0
|
||||
assert new == old
|
||||
|
||||
|
||||
# xfail because for unknown reasons, travis fails with matplotlib errors
|
||||
# xfail because for unknown reasons, travis fails with matplotlib errors
|
||||
@pytest.mark.xfail
|
||||
def test_show_hist(recwarn):
|
||||
from rasterio.tool import show_hist as show_old
|
||||
with rasterio.drivers():
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
warnings.simplefilter('always')
|
||||
old = show_old((src, 1))
|
||||
assert len(recwarn) == 1
|
||||
assert recwarn.pop(DeprecationWarning)
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
warnings.simplefilter('always')
|
||||
old = show_old((src, 1))
|
||||
assert len(recwarn) == 1
|
||||
assert recwarn.pop(DeprecationWarning)
|
||||
|
||||
from rasterio.plot import show_hist as show_new
|
||||
new = show_new((src, 1))
|
||||
assert len(recwarn) == 0
|
||||
assert new == old
|
||||
from rasterio.plot import show_hist as show_new
|
||||
new = show_new((src, 1))
|
||||
assert len(recwarn) == 0
|
||||
assert new == old
|
||||
|
||||
|
||||
def test_mask(recwarn, basic_image_file, basic_geometry):
|
||||
@ -128,7 +126,7 @@ def test_mask(recwarn, basic_image_file, basic_geometry):
|
||||
nodata_val = 0
|
||||
geometries = [basic_geometry]
|
||||
with rasterio.open(basic_image_file, "r") as src:
|
||||
warnings.simplefilter('always')
|
||||
warnings.simplefilter('once')
|
||||
old = mask_old(src, geometries, crop=False,
|
||||
nodata=nodata_val, invert=True)
|
||||
recwarn.pop(DeprecationWarning)
|
||||
|
||||
@ -2,16 +2,22 @@ import logging
|
||||
import sys
|
||||
|
||||
import rasterio
|
||||
from rasterio._drivers import driver_count, GDALEnv
|
||||
from rasterio._drivers import driver_count
|
||||
from rasterio.env import Env
|
||||
|
||||
|
||||
def test_drivers():
|
||||
with Env() as m:
|
||||
assert driver_count() > 0
|
||||
assert type(m) == Env
|
||||
assert driver_count() > 0
|
||||
|
||||
|
||||
def test_drivers_bwd_compat():
|
||||
with rasterio.drivers() as m:
|
||||
assert driver_count() > 0
|
||||
assert type(m) == GDALEnv
|
||||
n = rasterio.drivers()
|
||||
assert driver_count() > 0
|
||||
assert type(n) == GDALEnv
|
||||
assert type(m) == Env
|
||||
assert driver_count() > 0
|
||||
|
||||
|
||||
def test_cpl_debug_true(tmpdir):
|
||||
@ -22,7 +28,7 @@ def test_cpl_debug_true(tmpdir):
|
||||
fh = logging.FileHandler(logfile)
|
||||
log.addHandler(fh)
|
||||
|
||||
with rasterio.drivers(CPL_DEBUG=True):
|
||||
with Env(CPL_DEBUG=True):
|
||||
with rasterio.open("tests/data/RGB.byte.tif"):
|
||||
pass
|
||||
|
||||
@ -38,7 +44,7 @@ def test_cpl_debug_false(tmpdir):
|
||||
fh = logging.FileHandler(logfile)
|
||||
log.addHandler(fh)
|
||||
|
||||
with rasterio.drivers(CPL_DEBUG=False):
|
||||
with Env(CPL_DEBUG=False):
|
||||
with rasterio.open("tests/data/RGB.byte.tif"):
|
||||
pass
|
||||
|
||||
|
||||
139
tests/test_env.py
Normal file
139
tests/test_env.py
Normal file
@ -0,0 +1,139 @@
|
||||
# Tests requiring S3 credentials.
|
||||
# Collected here to make them easier to skip/xfail.
|
||||
|
||||
import logging
|
||||
import sys
|
||||
|
||||
import boto3
|
||||
from packaging.version import parse
|
||||
import pytest
|
||||
|
||||
import rasterio
|
||||
import rasterio.env
|
||||
from rasterio.errors import EnvError
|
||||
from rasterio.rio.main import main_group
|
||||
|
||||
|
||||
# Custom markers.
|
||||
mingdalversion = pytest.mark.skipif(
|
||||
parse(rasterio.__gdal_version__) < parse('2.1.0dev'),
|
||||
reason="S3 raster access requires GDAL 2.1")
|
||||
|
||||
credentials = pytest.mark.skipif(
|
||||
not(boto3.Session()._session.get_credentials()),
|
||||
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"
|
||||
httpstif = "https://landsat-pds.s3.amazonaws.com/L8/139/045/LC81390452014295LGN00/LC81390452014295LGN00_B1.TIF"
|
||||
|
||||
|
||||
def test_open_with_default_env():
|
||||
"""Read from a dataset with a default env."""
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as dataset:
|
||||
assert rasterio.env._env
|
||||
assert dataset.count == 3
|
||||
|
||||
|
||||
def test_env_single():
|
||||
"""Our env is effectively a singleton."""
|
||||
with rasterio.env.Env():
|
||||
with pytest.raises(EnvError):
|
||||
rasterio.env.Env()
|
||||
|
||||
|
||||
def test_open_with_env():
|
||||
"""Read from a dataset with an explicit env."""
|
||||
with rasterio.env.Env() as env:
|
||||
assert rasterio.env._env is env
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as dataset:
|
||||
assert dataset.count == 3
|
||||
|
||||
|
||||
def test_aws_session():
|
||||
"""Create an Env with a boto3 session."""
|
||||
aws_session = boto3.Session(
|
||||
aws_access_key_id='id', aws_secret_access_key='key',
|
||||
aws_session_token='token', region_name='null-island-1')
|
||||
s = rasterio.env.Env(aws_session=aws_session)
|
||||
assert rasterio.env._env is s
|
||||
assert s._creds.access_key == 'id'
|
||||
assert s._creds.secret_key == 'key'
|
||||
assert s._creds.token == 'token'
|
||||
assert s.aws_session.region_name == 'null-island-1'
|
||||
|
||||
|
||||
def test_session_lazy():
|
||||
"""Create an Env with lazy boto3 session."""
|
||||
with rasterio.env.Env(
|
||||
aws_access_key_id='id', aws_secret_access_key='key',
|
||||
aws_session_token='token', region_name='null-island-1') as s:
|
||||
assert s._creds is None
|
||||
s.get_aws_credentials()
|
||||
assert s._creds.access_key == 'id'
|
||||
assert s._creds.secret_key == 'key'
|
||||
assert s._creds.token == 'token'
|
||||
assert s.aws_session.region_name == 'null-island-1'
|
||||
|
||||
|
||||
def test_session_env_lazy(monkeypatch):
|
||||
"""Create an Env with AWS env vars."""
|
||||
monkeypatch.setenv('AWS_ACCESS_KEY_ID', 'id')
|
||||
monkeypatch.setenv('AWS_SECRET_ACCESS_KEY', 'key')
|
||||
monkeypatch.setenv('AWS_SESSION_TOKEN', 'token')
|
||||
with rasterio.env.Env() as s:
|
||||
assert s._creds is None
|
||||
s.get_aws_credentials()
|
||||
assert s._creds.access_key == 'id'
|
||||
assert s._creds.secret_key == 'key'
|
||||
assert s._creds.token == 'token'
|
||||
monkeypatch.undo()
|
||||
|
||||
|
||||
@mingdalversion
|
||||
@credentials
|
||||
def test_s3_open_with_session():
|
||||
"""Read from S3 demonstrating lazy credentials."""
|
||||
with rasterio.env.Env() as env:
|
||||
assert env._creds is None
|
||||
with rasterio.open(L8TIF) as dataset:
|
||||
assert env._creds
|
||||
assert dataset.count == 1
|
||||
|
||||
|
||||
@mingdalversion
|
||||
@credentials
|
||||
def test_s3_open_with_default_session():
|
||||
"""Read from S3 using default env."""
|
||||
with rasterio.open(L8TIF) as dataset:
|
||||
assert dataset.count == 1
|
||||
|
||||
|
||||
@mingdalversion
|
||||
def test_open_https_vsicurl():
|
||||
"""Read from HTTPS URL"""
|
||||
with rasterio.env.Env():
|
||||
with rasterio.open(httpstif) as dataset:
|
||||
assert dataset.count == 1
|
||||
|
||||
|
||||
# CLI tests.
|
||||
|
||||
@mingdalversion
|
||||
@credentials
|
||||
def test_s3_rio_info(runner):
|
||||
"""S3 is supported by rio-info"""
|
||||
result = runner.invoke(main_group, ['info', L8TIF])
|
||||
assert result.exit_code == 0
|
||||
assert '"crs": "EPSG:32645"' in result.output
|
||||
|
||||
|
||||
@mingdalversion
|
||||
@credentials
|
||||
def test_https_rio_info(runner):
|
||||
"""HTTPS is supported by rio-info"""
|
||||
result = runner.invoke(main_group, ['info', httpstif])
|
||||
assert result.exit_code == 0
|
||||
assert '"crs": "EPSG:32645"' in result.output
|
||||
@ -3,6 +3,7 @@
|
||||
import pytest
|
||||
|
||||
import rasterio
|
||||
from rasterio.env import Env
|
||||
from rasterio.errors import RasterioIOError
|
||||
|
||||
|
||||
@ -16,7 +17,7 @@ def test_io_error(tmpdir):
|
||||
|
||||
|
||||
def test_io_error_env(tmpdir):
|
||||
with rasterio.drivers() as env:
|
||||
with Env() as env:
|
||||
drivers_start = env.drivers()
|
||||
with pytest.raises(RasterioIOError):
|
||||
rasterio.open(str(tmpdir.join('foo.tif')))
|
||||
|
||||
@ -5,6 +5,7 @@ import pytest
|
||||
|
||||
from affine import Affine
|
||||
import rasterio
|
||||
from rasterio.env import Env
|
||||
from rasterio.features import bounds, geometry_mask, rasterize, sieve, shapes
|
||||
|
||||
|
||||
@ -59,7 +60,7 @@ def test_bounds_existing_bbox(basic_featurecollection):
|
||||
|
||||
|
||||
def test_geometry_mask(basic_geometry, basic_image_2x2):
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
assert numpy.array_equal(
|
||||
basic_image_2x2 == 0,
|
||||
geometry_mask(
|
||||
@ -71,7 +72,7 @@ def test_geometry_mask(basic_geometry, basic_image_2x2):
|
||||
|
||||
|
||||
def test_geometry_mask_invert(basic_geometry, basic_image_2x2):
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
assert numpy.array_equal(
|
||||
basic_image_2x2,
|
||||
geometry_mask(
|
||||
@ -86,7 +87,7 @@ def test_geometry_mask_invert(basic_geometry, basic_image_2x2):
|
||||
def test_rasterize(basic_geometry, basic_image_2x2):
|
||||
""" Rasterize operation should succeed for both an out_shape and out """
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
assert numpy.array_equal(
|
||||
basic_image_2x2,
|
||||
rasterize([basic_geometry], out_shape=DEFAULT_SHAPE)
|
||||
@ -101,7 +102,7 @@ def test_rasterize_invalid_out_dtype(basic_geometry):
|
||||
""" A non-supported data type for out should raise an exception """
|
||||
|
||||
out = numpy.zeros(DEFAULT_SHAPE, dtype=numpy.int64)
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
with pytest.raises(ValueError):
|
||||
rasterize([basic_geometry], out=out)
|
||||
|
||||
@ -110,7 +111,7 @@ def test_rasterize_shapes_out_dtype_mismatch(basic_geometry):
|
||||
""" Shape values must be able to fit in data type for out """
|
||||
|
||||
out = numpy.zeros(DEFAULT_SHAPE, dtype=numpy.uint8)
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
with pytest.raises(ValueError):
|
||||
rasterize([(basic_geometry, 10000000)], out=out)
|
||||
|
||||
@ -118,7 +119,7 @@ def test_rasterize_shapes_out_dtype_mismatch(basic_geometry):
|
||||
def test_rasterize_missing_out(basic_geometry):
|
||||
""" If both out and out_shape are missing, should raise exception """
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
with pytest.raises(ValueError):
|
||||
rasterize([basic_geometry], out=None, out_shape=None)
|
||||
|
||||
@ -126,7 +127,7 @@ def test_rasterize_missing_out(basic_geometry):
|
||||
def test_rasterize_missing_shapes():
|
||||
""" Shapes are required for this operation """
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
with pytest.raises(ValueError) as ex:
|
||||
rasterize([], out_shape=DEFAULT_SHAPE)
|
||||
|
||||
@ -136,7 +137,7 @@ def test_rasterize_missing_shapes():
|
||||
def test_rasterize_invalid_shapes():
|
||||
""" Invalid shapes should raise an exception rather than be skipped """
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
with pytest.raises(ValueError) as ex:
|
||||
rasterize([{'foo': 'bar'}], out_shape=DEFAULT_SHAPE)
|
||||
|
||||
@ -149,7 +150,7 @@ def test_rasterize_default_value(basic_geometry, basic_image_2x2):
|
||||
default_value = 2
|
||||
truth = basic_image_2x2 * default_value
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
assert numpy.array_equal(
|
||||
truth,
|
||||
rasterize(
|
||||
@ -162,7 +163,7 @@ def test_rasterize_default_value(basic_geometry, basic_image_2x2):
|
||||
def test_rasterize_invalid_default_value(basic_geometry):
|
||||
""" A default value that requires an int64 should raise an exception """
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
with pytest.raises(ValueError):
|
||||
rasterize(
|
||||
[basic_geometry], out_shape=DEFAULT_SHAPE,
|
||||
@ -174,7 +175,7 @@ def test_rasterize_fill_value(basic_geometry, basic_image_2x2):
|
||||
""" All pixels not covered by shapes should be given fill value """
|
||||
|
||||
default_value = 2
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
assert numpy.array_equal(
|
||||
basic_image_2x2 + 1,
|
||||
rasterize(
|
||||
@ -187,7 +188,7 @@ def test_rasterize_fill_value(basic_geometry, basic_image_2x2):
|
||||
def test_rasterize_invalid_fill_value(basic_geometry):
|
||||
""" A fill value that requires an int64 should raise an exception """
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
with pytest.raises(ValueError):
|
||||
rasterize(
|
||||
[basic_geometry], out_shape=DEFAULT_SHAPE, fill=1000000000000,
|
||||
@ -198,7 +199,7 @@ def test_rasterize_invalid_fill_value(basic_geometry):
|
||||
def test_rasterize_fill_value_dtype_mismatch(basic_geometry):
|
||||
""" A fill value that doesn't match dtype should fail """
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
with pytest.raises(ValueError):
|
||||
rasterize(
|
||||
[basic_geometry], out_shape=DEFAULT_SHAPE, fill=1000000,
|
||||
@ -207,7 +208,7 @@ def test_rasterize_fill_value_dtype_mismatch(basic_geometry):
|
||||
|
||||
|
||||
def test_rasterize_all_touched(basic_geometry, basic_image):
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
assert numpy.array_equal(
|
||||
basic_image,
|
||||
rasterize(
|
||||
@ -223,7 +224,7 @@ def test_rasterize_value(basic_geometry, basic_image_2x2):
|
||||
"""
|
||||
|
||||
value = 5
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
assert numpy.array_equal(
|
||||
basic_image_2x2 * value,
|
||||
rasterize(
|
||||
@ -235,7 +236,7 @@ def test_rasterize_value(basic_geometry, basic_image_2x2):
|
||||
def test_rasterize_invalid_value(basic_geometry):
|
||||
""" A shape value that requires an int64 should raise an exception """
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
with pytest.raises(ValueError) as ex:
|
||||
rasterize(
|
||||
[(basic_geometry, 1000000000000)], out_shape=DEFAULT_SHAPE
|
||||
@ -247,7 +248,7 @@ def test_rasterize_invalid_value(basic_geometry):
|
||||
def test_rasterize_supported_dtype(basic_geometry):
|
||||
""" Supported data types should return valid results """
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
supported_types = (
|
||||
('int16', -32768),
|
||||
('int32', -2147483648),
|
||||
@ -285,7 +286,7 @@ def test_rasterize_supported_dtype(basic_geometry):
|
||||
def test_rasterize_unsupported_dtype(basic_geometry):
|
||||
""" Unsupported types should all raise exceptions """
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
unsupported_types = (
|
||||
('int8', -127),
|
||||
('int64', 20439845334323),
|
||||
@ -312,7 +313,7 @@ def test_rasterize_unsupported_dtype(basic_geometry):
|
||||
def test_rasterize_mismatched_dtype(basic_geometry):
|
||||
""" Mismatched values and dtypes should raise exceptions """
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
mismatched_types = (('uint8', 3.2423), ('uint8', -2147483648))
|
||||
for dtype, default_value in mismatched_types:
|
||||
with pytest.raises(ValueError):
|
||||
@ -337,7 +338,7 @@ def test_rasterize_geometries_symmetric():
|
||||
transform = (1.0, 0.0, 0.0, 0.0, -1.0, 0.0)
|
||||
truth = numpy.zeros(DEFAULT_SHAPE, dtype=rasterio.ubyte)
|
||||
truth[2:5, 2:5] = 1
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
s = shapes(truth, transform=transform)
|
||||
result = rasterize(s, out_shape=DEFAULT_SHAPE, transform=transform)
|
||||
assert numpy.array_equal(result, truth)
|
||||
@ -352,7 +353,7 @@ def test_rasterize_internal_driver_manager(basic_geometry):
|
||||
def test_shapes(basic_image):
|
||||
""" Test creation of shapes from pixel values """
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
results = list(shapes(basic_image))
|
||||
|
||||
assert len(results) == 2
|
||||
@ -380,7 +381,7 @@ def test_shapes(basic_image):
|
||||
def test_shapes_band(pixelated_image, pixelated_image_file):
|
||||
""" Shapes from a band should match shapes from an array """
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
truth = list(shapes(pixelated_image))
|
||||
|
||||
with rasterio.open(pixelated_image_file) as src:
|
||||
@ -397,7 +398,7 @@ def test_shapes_connectivity_rook(diagonal_image):
|
||||
background.
|
||||
"""
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
assert len(list(shapes(diagonal_image, connectivity=4))) == 12
|
||||
|
||||
|
||||
@ -407,14 +408,14 @@ def test_shapes_connectivity_queen(diagonal_image):
|
||||
background.
|
||||
"""
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
assert len(list(shapes(diagonal_image, connectivity=8))) == 2
|
||||
|
||||
|
||||
def test_shapes_connectivity_invalid(diagonal_image):
|
||||
""" Invalid connectivity should raise exception """
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
with pytest.raises(ValueError):
|
||||
assert next(shapes(diagonal_image, connectivity=12))
|
||||
|
||||
@ -425,7 +426,7 @@ def test_shapes_mask(basic_image):
|
||||
mask = numpy.ones(basic_image.shape, dtype=rasterio.bool_)
|
||||
mask[4:5, 4:5] = False
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
results = list(shapes(basic_image, mask=mask))
|
||||
|
||||
assert len(results) == 2
|
||||
@ -443,7 +444,7 @@ def test_shapes_mask(basic_image):
|
||||
def test_shapes_blank_mask(basic_image):
|
||||
""" Mask is blank so results should mask shapes without mask """
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
assert numpy.array_equal(
|
||||
list(shapes(
|
||||
basic_image,
|
||||
@ -456,7 +457,7 @@ def test_shapes_blank_mask(basic_image):
|
||||
def test_shapes_invalid_mask_shape(basic_image):
|
||||
""" A mask that is the wrong shape should fail """
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
with pytest.raises(ValueError):
|
||||
next(shapes(
|
||||
basic_image,
|
||||
@ -470,7 +471,7 @@ def test_shapes_invalid_mask_shape(basic_image):
|
||||
def test_shapes_invalid_mask_dtype(basic_image):
|
||||
""" A mask that is the wrong dtype should fail """
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
for dtype in ('int8', 'int16', 'int32'):
|
||||
with pytest.raises(ValueError):
|
||||
next(shapes(
|
||||
@ -490,7 +491,7 @@ def test_shapes_supported_dtypes(basic_image):
|
||||
('float32', 1.434532)
|
||||
)
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
for dtype, test_value in supported_types:
|
||||
shape, value = next(shapes(basic_image.astype(dtype) * test_value))
|
||||
assert numpy.allclose(value, test_value)
|
||||
@ -507,7 +508,7 @@ def test_shapes_unsupported_dtypes(basic_image):
|
||||
('float64', -98332.133422114)
|
||||
)
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
for dtype, test_value in unsupported_types:
|
||||
with pytest.raises(ValueError):
|
||||
next(shapes(basic_image.astype(dtype) * test_value))
|
||||
@ -525,7 +526,7 @@ def test_sieve_small(basic_image, pixelated_image):
|
||||
image should not change the image.
|
||||
"""
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
assert numpy.array_equal(
|
||||
basic_image,
|
||||
sieve(pixelated_image, basic_image.sum())
|
||||
@ -537,12 +538,12 @@ def test_sieve_large(basic_image):
|
||||
Setting the size larger than size of feature should leave us an empty image.
|
||||
"""
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
assert not numpy.any(sieve(basic_image, basic_image.sum() + 1))
|
||||
|
||||
|
||||
def test_sieve_invalid_size(basic_image):
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
for invalid_size in (0, 45.1234, basic_image.size + 1):
|
||||
with pytest.raises(ValueError):
|
||||
sieve(basic_image, invalid_size)
|
||||
@ -573,7 +574,7 @@ def test_sieve_connectivity_invalid(basic_image):
|
||||
def test_sieve_out(basic_image):
|
||||
""" Output array passed in should match the returned array """
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
output = numpy.zeros_like(basic_image)
|
||||
output[1:3, 1:3] = 5
|
||||
sieved_image = sieve(basic_image, basic_image.sum(), out=output)
|
||||
@ -584,7 +585,7 @@ def test_sieve_out(basic_image):
|
||||
def test_sieve_invalid_out(basic_image):
|
||||
""" Output with different dtype or shape should fail """
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
with pytest.raises(ValueError):
|
||||
sieve(
|
||||
basic_image, basic_image.sum(),
|
||||
@ -611,7 +612,7 @@ def test_sieve_mask(basic_image):
|
||||
mask[4:5, 4:5] = False
|
||||
truth = basic_image * numpy.invert(mask)
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
sieved_image = sieve(basic_image, basic_image.sum(), mask=mask)
|
||||
assert sieved_image.sum() > 0
|
||||
|
||||
@ -630,7 +631,7 @@ def test_sieve_blank_mask(basic_image):
|
||||
""" A blank mask should have no effect """
|
||||
|
||||
mask = numpy.ones(basic_image.shape, dtype=rasterio.bool_)
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
assert numpy.array_equal(
|
||||
basic_image,
|
||||
sieve(basic_image, basic_image.sum(), mask=mask)
|
||||
@ -640,7 +641,7 @@ def test_sieve_blank_mask(basic_image):
|
||||
def test_sieve_invalid_mask_shape(basic_image):
|
||||
""" A mask that is the wrong shape should fail """
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
with pytest.raises(ValueError):
|
||||
sieve(
|
||||
basic_image, basic_image.sum(),
|
||||
@ -654,7 +655,7 @@ def test_sieve_invalid_mask_shape(basic_image):
|
||||
def test_sieve_invalid_mask_dtype(basic_image):
|
||||
""" A mask that is the wrong dtype should fail """
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
for dtype in ('int8', 'int16', 'int32'):
|
||||
with pytest.raises(ValueError):
|
||||
sieve(
|
||||
@ -673,7 +674,7 @@ def test_sieve_supported_dtypes(basic_image):
|
||||
('uint16', 65535)
|
||||
)
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
for dtype, test_value in supported_types:
|
||||
truth = (basic_image).astype(dtype) * test_value
|
||||
sieved_image = sieve(truth, basic_image.sum())
|
||||
@ -693,7 +694,7 @@ def test_sieve_unsupported_dtypes(basic_image):
|
||||
('float64', -98332.133422114)
|
||||
)
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
for dtype, test_value in unsupported_types:
|
||||
with pytest.raises(ValueError):
|
||||
sieve(
|
||||
@ -705,7 +706,7 @@ def test_sieve_unsupported_dtypes(basic_image):
|
||||
def test_sieve_band(pixelated_image, pixelated_image_file):
|
||||
""" Sieving a band from a raster file should match sieve of array """
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
truth = sieve(pixelated_image, 9)
|
||||
|
||||
with rasterio.open(pixelated_image_file) as src:
|
||||
|
||||
@ -6,14 +6,15 @@ See https://github.com/mapbox/rasterio/issues/293 for bug report.
|
||||
|
||||
import rasterio
|
||||
from rasterio.enums import MaskFlags
|
||||
from rasterio.env import Env
|
||||
|
||||
|
||||
def test_create_internal_mask(data):
|
||||
"""Write an internal mask to the fixture's RGB.byte.tif."""
|
||||
with rasterio.drivers(GDAL_TIFF_INTERNAL_MASK=True):
|
||||
with Env(GDAL_TIFF_INTERNAL_MASK=True):
|
||||
with rasterio.open(str(data.join('RGB.byte.tif')), 'r+') as dst:
|
||||
blue = dst.read(1, masked=False)
|
||||
mask = 255*(blue == 0).astype('uint8')
|
||||
mask = 255 * (blue == 0).astype('uint8')
|
||||
dst.write_mask(mask)
|
||||
|
||||
# There should be no .msk file
|
||||
@ -31,11 +32,10 @@ def test_create_internal_mask(data):
|
||||
|
||||
def test_create_sidecar_mask(data):
|
||||
"""Write a .msk sidecar mask."""
|
||||
with rasterio.drivers():
|
||||
with rasterio.open(str(data.join('RGB.byte.tif')), 'r+') as dst:
|
||||
blue = dst.read(1, masked=False)
|
||||
mask = 255*(blue == 0).astype('uint8')
|
||||
dst.write_mask(mask)
|
||||
with rasterio.open(str(data.join('RGB.byte.tif')), 'r+') as dst:
|
||||
blue = dst.read(1, masked=False)
|
||||
mask = 255 * (blue == 0).astype('uint8')
|
||||
dst.write_mask(mask)
|
||||
|
||||
# There should be a .msk file in this case.
|
||||
assert data.join('RGB.byte.tif').exists()
|
||||
|
||||
@ -10,12 +10,11 @@ logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
|
||||
|
||||
def test_nodata(tmpdir):
|
||||
dst_path = str(tmpdir.join('lol.tif'))
|
||||
with rasterio.drivers():
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
with rasterio.open(dst_path, 'w', **src.meta) as dst:
|
||||
assert dst.nodata == 0.0
|
||||
assert dst.meta['nodata'] == 0.0
|
||||
assert dst.nodatavals == (0.0, 0.0, 0.0)
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
with rasterio.open(dst_path, 'w', **src.meta) as dst:
|
||||
assert dst.nodata == 0.0
|
||||
assert dst.meta['nodata'] == 0.0
|
||||
assert dst.nodatavals == (0.0, 0.0, 0.0)
|
||||
info = subprocess.check_output([
|
||||
'gdalinfo', dst_path])
|
||||
pattern = b'Band 1.*?NoData Value=0'
|
||||
@ -27,14 +26,13 @@ def test_nodata(tmpdir):
|
||||
|
||||
def test_set_nodata(tmpdir):
|
||||
dst_path = str(tmpdir.join('lol.tif'))
|
||||
with rasterio.drivers():
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
meta = src.meta
|
||||
meta['nodata'] = 42
|
||||
with rasterio.open(dst_path, 'w', **meta) as dst:
|
||||
assert dst.nodata == 42
|
||||
assert dst.meta['nodata'] == 42
|
||||
assert dst.nodatavals == (42, 42, 42)
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
meta = src.meta
|
||||
meta['nodata'] = 42
|
||||
with rasterio.open(dst_path, 'w', **meta) as dst:
|
||||
assert dst.nodata == 42
|
||||
assert dst.meta['nodata'] == 42
|
||||
assert dst.nodatavals == (42, 42, 42)
|
||||
info = subprocess.check_output([
|
||||
'gdalinfo', dst_path])
|
||||
pattern = b'Band 1.*?NoData Value=42'
|
||||
|
||||
@ -7,10 +7,12 @@ def test_open_bad_path():
|
||||
rasterio.open(3.14)
|
||||
|
||||
|
||||
def test_open_bad_mode():
|
||||
def test_open_bad_mode_1():
|
||||
with pytest.raises(TypeError):
|
||||
rasterio.open("tests/data/RGB.byte.tif", mode=3.14)
|
||||
|
||||
|
||||
def test_open_bad_mode_2():
|
||||
with pytest.raises(ValueError):
|
||||
rasterio.open("tests/data/RGB.byte.tif", mode="foo")
|
||||
|
||||
@ -18,9 +20,3 @@ def test_open_bad_mode():
|
||||
def test_open_bad_driver():
|
||||
with pytest.raises(TypeError):
|
||||
rasterio.open("tests/data/RGB.byte.tif", mode="r", driver=3.14)
|
||||
|
||||
|
||||
def test_open_fake_aws_session():
|
||||
from rasterio.rio.main import FakeSession
|
||||
with FakeSession() as fs:
|
||||
fs.open("tests/data/RGB.byte.tif")
|
||||
|
||||
@ -180,9 +180,8 @@ def test_mask_crop(runner, tmpdir, basic_feature, pixelated_image):
|
||||
"width": image.shape[1],
|
||||
"height": image.shape[0],
|
||||
"nodata": 255}
|
||||
with rasterio.drivers():
|
||||
with rasterio.open(outfilename, 'w', **kwargs) as out:
|
||||
out.write(image, indexes=1)
|
||||
with rasterio.open(outfilename, 'w', **kwargs) as out:
|
||||
out.write(image, indexes=1)
|
||||
|
||||
output = str(tmpdir.join('test.tif'))
|
||||
|
||||
|
||||
@ -28,17 +28,15 @@ def test_data_dir_1(tmpdir):
|
||||
"nodata": 1
|
||||
}
|
||||
|
||||
with rasterio.drivers():
|
||||
with rasterio.open(str(tmpdir.join('b.tif')), 'w', **kwargs) as dst:
|
||||
data = numpy.ones((10, 10), dtype=rasterio.uint8)
|
||||
data[0:6, 0:6] = 255
|
||||
dst.write(data, indexes=1)
|
||||
|
||||
with rasterio.open(str(tmpdir.join('b.tif')), 'w', **kwargs) as dst:
|
||||
data = numpy.ones((10, 10), dtype=rasterio.uint8)
|
||||
data[0:6, 0:6] = 255
|
||||
dst.write(data, indexes=1)
|
||||
|
||||
with rasterio.open(str(tmpdir.join('a.tif')), 'w', **kwargs) as dst:
|
||||
data = numpy.ones((10, 10), dtype=rasterio.uint8)
|
||||
data[4:8, 4:8] = 254
|
||||
dst.write(data, indexes=1)
|
||||
with rasterio.open(str(tmpdir.join('a.tif')), 'w', **kwargs) as dst:
|
||||
data = numpy.ones((10, 10), dtype=rasterio.uint8)
|
||||
data[4:8, 4:8] = 254
|
||||
dst.write(data, indexes=1)
|
||||
|
||||
return tmpdir
|
||||
|
||||
@ -56,17 +54,15 @@ def test_data_dir_2(tmpdir):
|
||||
# these files have undefined nodata.
|
||||
}
|
||||
|
||||
with rasterio.drivers():
|
||||
with rasterio.open(str(tmpdir.join('b.tif')), 'w', **kwargs) as dst:
|
||||
data = numpy.zeros((10, 10), dtype=rasterio.uint8)
|
||||
data[0:6, 0:6] = 255
|
||||
dst.write(data, indexes=1)
|
||||
|
||||
with rasterio.open(str(tmpdir.join('b.tif')), 'w', **kwargs) as dst:
|
||||
data = numpy.zeros((10, 10), dtype=rasterio.uint8)
|
||||
data[0:6, 0:6] = 255
|
||||
dst.write(data, indexes=1)
|
||||
|
||||
with rasterio.open(str(tmpdir.join('a.tif')), 'w', **kwargs) as dst:
|
||||
data = numpy.zeros((10, 10), dtype=rasterio.uint8)
|
||||
data[4:8, 4:8] = 254
|
||||
dst.write(data, indexes=1)
|
||||
with rasterio.open(str(tmpdir.join('a.tif')), 'w', **kwargs) as dst:
|
||||
data = numpy.zeros((10, 10), dtype=rasterio.uint8)
|
||||
data[4:8, 4:8] = 254
|
||||
dst.write(data, indexes=1)
|
||||
|
||||
return tmpdir
|
||||
|
||||
@ -184,15 +180,14 @@ def test_data_dir_overlapping(tmpdir):
|
||||
"nodata": 0
|
||||
}
|
||||
|
||||
with rasterio.drivers():
|
||||
with rasterio.open(str(tmpdir.join('se.tif')), 'w', **kwargs) as dst:
|
||||
data = numpy.ones((10, 10), dtype=rasterio.uint8)
|
||||
dst.write(data, indexes=1)
|
||||
with rasterio.open(str(tmpdir.join('se.tif')), 'w', **kwargs) as dst:
|
||||
data = numpy.ones((10, 10), dtype=rasterio.uint8)
|
||||
dst.write(data, indexes=1)
|
||||
|
||||
kwargs['transform'] = (-113, 0.2, 0, 45, 0, -0.2)
|
||||
with rasterio.open(str(tmpdir.join('nw.tif')), 'w', **kwargs) as dst:
|
||||
data = numpy.ones((10, 10), dtype=rasterio.uint8) * 2
|
||||
dst.write(data, indexes=1)
|
||||
kwargs['transform'] = (-113, 0.2, 0, 45, 0, -0.2)
|
||||
with rasterio.open(str(tmpdir.join('nw.tif')), 'w', **kwargs) as dst:
|
||||
data = numpy.ones((10, 10), dtype=rasterio.uint8) * 2
|
||||
dst.write(data, indexes=1)
|
||||
|
||||
return tmpdir
|
||||
|
||||
@ -230,16 +225,15 @@ def test_data_dir_float(tmpdir):
|
||||
"nodata": 0
|
||||
}
|
||||
|
||||
with rasterio.drivers():
|
||||
with rasterio.open(str(tmpdir.join('two.tif')), 'w', **kwargs) as dst:
|
||||
data = numpy.zeros((10, 10), dtype=rasterio.float64)
|
||||
data[0:6, 0:6] = 255
|
||||
dst.write(data, indexes=1)
|
||||
with rasterio.open(str(tmpdir.join('two.tif')), 'w', **kwargs) as dst:
|
||||
data = numpy.zeros((10, 10), dtype=rasterio.float64)
|
||||
data[0:6, 0:6] = 255
|
||||
dst.write(data, indexes=1)
|
||||
|
||||
with rasterio.open(str(tmpdir.join('one.tif')), 'w', **kwargs) as dst:
|
||||
data = numpy.zeros((10, 10), dtype=rasterio.float64)
|
||||
data[4:8, 4:8] = 254
|
||||
dst.write(data, indexes=1)
|
||||
with rasterio.open(str(tmpdir.join('one.tif')), 'w', **kwargs) as dst:
|
||||
data = numpy.zeros((10, 10), dtype=rasterio.float64)
|
||||
data[4:8, 4:8] = 254
|
||||
dst.write(data, indexes=1)
|
||||
return tmpdir
|
||||
|
||||
|
||||
@ -275,23 +269,23 @@ def tiffs(tmpdir):
|
||||
'height': 1,
|
||||
'width': 1}
|
||||
|
||||
kwargs['transform'] = Affine( 1, 0, 1,
|
||||
0,-1, 1)
|
||||
kwargs['transform'] = Affine(1, 0, 1,
|
||||
0, -1, 1)
|
||||
with rasterio.open(str(tmpdir.join('a-sw.tif')), 'w', **kwargs) as r:
|
||||
r.write(data * 40)
|
||||
|
||||
kwargs['transform'] = Affine( 1, 0, 2,
|
||||
0,-1, 2)
|
||||
kwargs['transform'] = Affine(1, 0, 2,
|
||||
0, -1, 2)
|
||||
with rasterio.open(str(tmpdir.join('b-ct.tif')), 'w', **kwargs) as r:
|
||||
r.write(data * 60)
|
||||
|
||||
kwargs['transform'] = Affine( 2, 0, 3,
|
||||
0,-2, 4)
|
||||
kwargs['transform'] = Affine(2, 0, 3,
|
||||
0, -2, 4)
|
||||
with rasterio.open(str(tmpdir.join('c-ne.tif')), 'w', **kwargs) as r:
|
||||
r.write(data * 90)
|
||||
|
||||
kwargs['transform'] = Affine( 2, 0, 2,
|
||||
0,-2, 4)
|
||||
kwargs['transform'] = Affine(2, 0, 2,
|
||||
0, -2, 4)
|
||||
with rasterio.open(str(tmpdir.join('d-ne.tif')), 'w', **kwargs) as r:
|
||||
r.write(data * 120)
|
||||
|
||||
@ -315,8 +309,8 @@ def test_merge_tiny(tiffs):
|
||||
|
||||
with rasterio.open(outputname) as src:
|
||||
data = src.read()
|
||||
assert (data[0][0:2,1] == 120).all()
|
||||
assert (data[0][0:2,2:4] == 90).all()
|
||||
assert (data[0][0:2, 1] == 120).all()
|
||||
assert (data[0][0:2, 2:4] == 90).all()
|
||||
assert data[0][2][1] == 60
|
||||
assert data[0][3][0] == 40
|
||||
|
||||
@ -338,8 +332,8 @@ def test_merge_tiny_output_opt(tiffs):
|
||||
|
||||
with rasterio.open(outputname) as src:
|
||||
data = src.read()
|
||||
assert (data[0][0:2,1] == 120).all()
|
||||
assert (data[0][0:2,2:4] == 90).all()
|
||||
assert (data[0][0:2, 1] == 120).all()
|
||||
assert (data[0][0:2, 2:4] == 90).all()
|
||||
assert data[0][2][1] == 60
|
||||
assert data[0][3][0] == 40
|
||||
|
||||
@ -407,4 +401,4 @@ def test_merge_tiny_intres(tiffs):
|
||||
inputs = [str(x) for x in tiffs.listdir()]
|
||||
inputs.sort()
|
||||
sources = [rasterio.open(x) for x in inputs]
|
||||
result = merge(sources, res=2)
|
||||
merge(sources, res=2)
|
||||
|
||||
@ -395,6 +395,7 @@ def test_warp_badcrs_src_bounds(runner, tmpdir):
|
||||
assert "Invalid value for dst_crs" in result.output
|
||||
|
||||
|
||||
@pytest.mark.xfail
|
||||
def test_warp_reproject_check_invert(runner, tmpdir):
|
||||
srcname = 'tests/data/world.rgb.tif'
|
||||
outputname = str(tmpdir.join('test.tif'))
|
||||
|
||||
@ -10,15 +10,14 @@ from rasterio.plot import show, show_hist
|
||||
from rasterio.rio.insp import stats
|
||||
|
||||
def test_stats():
|
||||
with rasterio.drivers():
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
results = stats((src, 1))
|
||||
assert results[0] == 0
|
||||
assert results[1] == 255
|
||||
assert np.isclose(results[2], 29.9477)
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
results = stats((src, 1))
|
||||
assert results[0] == 0
|
||||
assert results[1] == 255
|
||||
assert np.isclose(results[2], 29.9477)
|
||||
|
||||
results2 = stats(src.read(1))
|
||||
assert np.allclose(np.array(results), np.array(results2))
|
||||
results2 = stats(src.read(1))
|
||||
assert np.allclose(np.array(results), np.array(results2))
|
||||
|
||||
|
||||
def test_show_raster():
|
||||
@ -26,15 +25,13 @@ def test_show_raster():
|
||||
This test only verifies that code up to the point of plotting with
|
||||
matplotlib works correctly. Tests do not exercise matplotlib.
|
||||
"""
|
||||
|
||||
with rasterio.drivers():
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
try:
|
||||
show((src, 1))
|
||||
fig = plt.gcf()
|
||||
plt.close(fig)
|
||||
except ImportError:
|
||||
pass
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
try:
|
||||
show((src, 1))
|
||||
fig = plt.gcf()
|
||||
plt.close(fig)
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
def test_show_raster_no_bounds():
|
||||
@ -42,15 +39,13 @@ def test_show_raster_no_bounds():
|
||||
This test only verifies that code up to the point of plotting with
|
||||
matplotlib works correctly. Tests do not exercise matplotlib.
|
||||
"""
|
||||
|
||||
with rasterio.drivers():
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
try:
|
||||
show((src, 1), with_bounds=False)
|
||||
fig = plt.gcf()
|
||||
plt.close(fig)
|
||||
except ImportError:
|
||||
pass
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
try:
|
||||
show((src, 1), with_bounds=False)
|
||||
fig = plt.gcf()
|
||||
plt.close(fig)
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
def test_show_array():
|
||||
@ -58,15 +53,13 @@ def test_show_array():
|
||||
This test only verifies that code up to the point of plotting with
|
||||
matplotlib works correctly. Tests do not exercise matplotlib.
|
||||
"""
|
||||
|
||||
with rasterio.drivers():
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
try:
|
||||
show(src.read(1))
|
||||
fig = plt.gcf()
|
||||
plt.close(fig)
|
||||
except ImportError:
|
||||
pass
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
try:
|
||||
show(src.read(1))
|
||||
fig = plt.gcf()
|
||||
plt.close(fig)
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
def test_show_hist():
|
||||
@ -74,7 +67,6 @@ def test_show_hist():
|
||||
This test only verifies that code up to the point of plotting with
|
||||
matplotlib works correctly. Tests do not exercise matplotlib.
|
||||
"""
|
||||
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
try:
|
||||
show_hist((src, 1), bins=256)
|
||||
|
||||
@ -11,16 +11,15 @@ import rasterio
|
||||
|
||||
def test_update_tags(data):
|
||||
tiffname = str(data.join('RGB.byte.tif'))
|
||||
with rasterio.drivers():
|
||||
with rasterio.open(tiffname, 'r+') as f:
|
||||
f.update_tags(a='1', b='2')
|
||||
f.update_tags(1, c=3)
|
||||
with pytest.raises(IndexError):
|
||||
f.update_tags(4, d=4)
|
||||
assert f.tags() == {'AREA_OR_POINT': 'Area', 'a': '1', 'b': '2'}
|
||||
assert ('c', '3') in f.tags(1).items()
|
||||
info = subprocess.check_output(["gdalinfo", tiffname]).decode('utf-8')
|
||||
assert re.search("Metadata:\W+a=1\W+AREA_OR_POINT=Area\W+b=2", info)
|
||||
with rasterio.open(tiffname, 'r+') as f:
|
||||
f.update_tags(a='1', b='2')
|
||||
f.update_tags(1, c=3)
|
||||
with pytest.raises(IndexError):
|
||||
f.update_tags(4, d=4)
|
||||
assert f.tags() == {'AREA_OR_POINT': 'Area', 'a': '1', 'b': '2'}
|
||||
assert ('c', '3') in f.tags(1).items()
|
||||
info = subprocess.check_output(["gdalinfo", tiffname]).decode('utf-8')
|
||||
assert re.search("Metadata:\W+a=1\W+AREA_OR_POINT=Area\W+b=2", info)
|
||||
|
||||
|
||||
def test_update_band(data):
|
||||
|
||||
@ -32,7 +32,7 @@ def test_parse_path_file_scheme():
|
||||
def test_parse_path_file():
|
||||
"""Correctly parse an ordinary filesystem path"""
|
||||
assert parse_path('/foo.tif') == (
|
||||
'/foo.tif', None, None)
|
||||
'/foo.tif', None, '')
|
||||
|
||||
|
||||
def test_parse_unknown_scheme():
|
||||
@ -47,12 +47,6 @@ def test_vsi_path_scheme():
|
||||
'foo.tif', 'tests/data/files.zip', 'zip') == '/vsizip/tests/data/files.zip/foo.tif'
|
||||
|
||||
|
||||
def test_vsi_path_file():
|
||||
"""Correctly make a ordinary file path from a parsed file:// URL"""
|
||||
assert vsi_path(
|
||||
'foo.tif', None, 'file') == 'foo.tif'
|
||||
|
||||
|
||||
def test_vsi_path_file():
|
||||
"""Correctly make and ordinary file path from a file path"""
|
||||
assert vsi_path(
|
||||
@ -95,7 +89,7 @@ def test_read_vfs_none():
|
||||
def test_update_vfs(tmpdir, mode):
|
||||
"""VFS datasets can not be created or updated"""
|
||||
with pytest.raises(TypeError):
|
||||
_ = rasterio.open(
|
||||
rasterio.open(
|
||||
'zip://{0}'.format(tmpdir), mode,
|
||||
**default_gtiff_profile(
|
||||
count=1, width=1, height=1))
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
from rasterio.warnings import NodataShadowWarning
|
||||
from rasterio.errors import NodataShadowWarning
|
||||
|
||||
|
||||
def test_nodata_shadow():
|
||||
|
||||
@ -7,6 +7,7 @@ import numpy
|
||||
|
||||
import rasterio
|
||||
from rasterio.enums import Resampling
|
||||
from rasterio.env import Env
|
||||
from rasterio.warp import (
|
||||
reproject, transform_geom, transform, transform_bounds,
|
||||
calculate_default_transform)
|
||||
@ -29,7 +30,7 @@ class ReprojectParams(object):
|
||||
self.src_crs = src_crs
|
||||
self.dst_crs = dst_crs
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
dt, dw, dh = calculate_default_transform(
|
||||
src_crs, dst_crs, width, height, left, bottom, right, top)
|
||||
self.dst_transform = dt
|
||||
@ -65,7 +66,7 @@ def test_transform():
|
||||
|
||||
|
||||
def test_transform_bounds():
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
l, b, r, t = src.bounds
|
||||
assert numpy.allclose(
|
||||
@ -111,7 +112,7 @@ def test_transform_bounds_densify():
|
||||
|
||||
def test_transform_bounds_no_change():
|
||||
""" Make sure that going from and to the same crs causes no change """
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
l, b, r, t = src.bounds
|
||||
assert numpy.allclose(
|
||||
@ -135,7 +136,7 @@ def test_calculate_default_transform():
|
||||
0.0028535715391804096, 0.0, -78.95864996545055,
|
||||
0.0, -0.0028535715391804096, 25.550873767433984)
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
wgs84_crs = {'init': 'EPSG:4326'}
|
||||
dst_transform, width, height = calculate_default_transform(
|
||||
@ -147,7 +148,7 @@ def test_calculate_default_transform():
|
||||
|
||||
|
||||
def test_calculate_default_transform_single_resolution():
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
target_resolution = 0.1
|
||||
target_transform = Affine(
|
||||
@ -165,7 +166,7 @@ def test_calculate_default_transform_single_resolution():
|
||||
|
||||
|
||||
def test_calculate_default_transform_multiple_resolutions():
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
target_resolution = (0.2, 0.1)
|
||||
target_transform = Affine(
|
||||
@ -184,7 +185,7 @@ def test_calculate_default_transform_multiple_resolutions():
|
||||
|
||||
|
||||
def test_reproject_ndarray():
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
source = src.read(1)
|
||||
|
||||
@ -214,7 +215,7 @@ def test_reproject_ndarray():
|
||||
|
||||
|
||||
def test_reproject_epsg():
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
source = src.read(1)
|
||||
|
||||
@ -233,7 +234,7 @@ def test_reproject_epsg():
|
||||
|
||||
def test_reproject_out_of_bounds():
|
||||
# using EPSG code not appropriate for the transform should return blank image
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
source = src.read(1)
|
||||
|
||||
@ -254,7 +255,7 @@ def test_reproject_nodata():
|
||||
params = default_reproject_params()
|
||||
nodata = 215
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
source = numpy.ones((params.width, params.height), dtype=numpy.uint8)
|
||||
out = numpy.zeros((params.dst_width, params.dst_height),
|
||||
dtype=source.dtype)
|
||||
@ -279,7 +280,7 @@ def test_reproject_nodata():
|
||||
def test_reproject_nodata_nan():
|
||||
params = default_reproject_params()
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
source = numpy.ones((params.width, params.height), dtype=numpy.float32)
|
||||
out = numpy.zeros((params.dst_width, params.dst_height),
|
||||
dtype=source.dtype)
|
||||
@ -309,7 +310,7 @@ def test_reproject_dst_nodata_default():
|
||||
|
||||
params = default_reproject_params()
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
source = numpy.ones((params.width, params.height), dtype=numpy.uint8)
|
||||
out = numpy.zeros((params.dst_width, params.dst_height),
|
||||
dtype=source.dtype)
|
||||
@ -333,7 +334,7 @@ def test_reproject_invalid_dst_nodata():
|
||||
""" dst_nodata must be in value range of data type """
|
||||
params = default_reproject_params()
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
source = numpy.ones((params.width, params.height), dtype=numpy.uint8)
|
||||
out = source.copy()
|
||||
|
||||
@ -354,7 +355,7 @@ def test_reproject_missing_src_nodata():
|
||||
""" src_nodata is required if dst_nodata is not None """
|
||||
params = default_reproject_params()
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
source = numpy.ones((params.width, params.height), dtype=numpy.uint8)
|
||||
out = source.copy()
|
||||
|
||||
@ -374,7 +375,7 @@ def test_reproject_invalid_src_nodata():
|
||||
""" src_nodata must be in range for data type """
|
||||
params = default_reproject_params()
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
source = numpy.ones((params.width, params.height), dtype=numpy.uint8)
|
||||
out = source.copy()
|
||||
|
||||
@ -393,7 +394,7 @@ def test_reproject_invalid_src_nodata():
|
||||
|
||||
def test_reproject_multi():
|
||||
"""Ndarry to ndarray"""
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
source = src.read()
|
||||
dst_crs = dict(
|
||||
@ -561,7 +562,7 @@ def test_transform_geom():
|
||||
|
||||
def test_reproject_unsupported_resampling():
|
||||
"""Values not in enums.Resampling are not supported."""
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
source = src.read(1)
|
||||
|
||||
@ -580,7 +581,7 @@ def test_reproject_unsupported_resampling():
|
||||
|
||||
def test_reproject_unsupported_resampling_guass():
|
||||
"""Resampling.gauss is unsupported."""
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
source = src.read(1)
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@ import pytest
|
||||
|
||||
import rasterio
|
||||
from rasterio._warp import _calculate_default_transform
|
||||
from rasterio.env import Env
|
||||
from rasterio.errors import CRSError
|
||||
from rasterio.transform import Affine, from_bounds
|
||||
from rasterio.warp import transform_bounds
|
||||
@ -20,7 +21,7 @@ def test_identity():
|
||||
5009377.085697309)
|
||||
transform = from_bounds(left, bottom, right, top, width, height)
|
||||
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
res_transform, res_width, res_height = _calculate_default_transform(
|
||||
src_crs, dst_crs, width, height, left, bottom, right, top)
|
||||
|
||||
@ -32,7 +33,7 @@ def test_identity():
|
||||
|
||||
def test_transform_bounds():
|
||||
"""CRSError is raised."""
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
left, bottom, right, top = (
|
||||
-11740727.544603072, 4852834.0517692715, -11584184.510675032,
|
||||
5009377.085697309)
|
||||
@ -43,7 +44,7 @@ def test_transform_bounds():
|
||||
|
||||
|
||||
def test_gdal_transform_notnull():
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
dt, dw, dh = _calculate_default_transform(
|
||||
src_crs={'init': 'EPSG:4326'},
|
||||
dst_crs={'init': 'EPSG:32610'},
|
||||
@ -57,7 +58,7 @@ def test_gdal_transform_notnull():
|
||||
|
||||
|
||||
def test_gdal_transform_fail_dst_crs():
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
dt, dw, dh = _calculate_default_transform(
|
||||
{'init': 'EPSG:4326'},
|
||||
'+proj=foobar',
|
||||
@ -69,7 +70,7 @@ def test_gdal_transform_fail_dst_crs():
|
||||
top=70)
|
||||
|
||||
def test_gdal_transform_fail_src_crs():
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
dt, dw, dh = _calculate_default_transform(
|
||||
'+proj=foobar',
|
||||
{'init': 'EPSG:32610'},
|
||||
@ -85,7 +86,7 @@ def test_gdal_transform_fail_src_crs():
|
||||
os.environ.get('GDALVERSION', 'a.b.c').startswith('1.9'),
|
||||
reason="GDAL 1.9 doesn't catch this error")
|
||||
def test_gdal_transform_fail_src_crs():
|
||||
with rasterio.drivers():
|
||||
with Env():
|
||||
with pytest.raises(CRSError):
|
||||
dt, dw, dh = _calculate_default_transform(
|
||||
{'init': 'EPSG:4326'},
|
||||
|
||||
@ -13,32 +13,28 @@ logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
|
||||
|
||||
|
||||
def test_validate_dtype_None(tmpdir):
|
||||
"""Raise TypeError if there is no dtype"""
|
||||
name = str(tmpdir.join("lol.tif"))
|
||||
try:
|
||||
ds = rasterio.open(
|
||||
name, 'w', driver='GTiff', width=100, height=100, count=1,
|
||||
# dtype=None
|
||||
)
|
||||
except TypeError:
|
||||
pass
|
||||
with pytest.raises(TypeError):
|
||||
rasterio.open(
|
||||
name, 'w', driver='GTiff', width=100, height=100, count=1)
|
||||
|
||||
|
||||
def test_validate_dtype_str(tmpdir):
|
||||
name = str(tmpdir.join("lol.tif"))
|
||||
try:
|
||||
ds = rasterio.open(
|
||||
with pytest.raises(TypeError):
|
||||
rasterio.open(
|
||||
name, 'w', driver='GTiff', width=100, height=100, count=1,
|
||||
dtype='Int16')
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
|
||||
def test_validate_count_None(tmpdir):
|
||||
name = str(tmpdir.join("lol.tif"))
|
||||
try:
|
||||
ds = rasterio.open(
|
||||
name, 'w', driver='GTiff', width=100, height=100, #count=None
|
||||
with pytest.raises(TypeError):
|
||||
rasterio.open(
|
||||
name, 'w', driver='GTiff', width=100, height=100, # count=None
|
||||
dtype=rasterio.uint8)
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
|
||||
def test_no_crs(tmpdir):
|
||||
# A dataset without crs is okay.
|
||||
@ -51,19 +47,19 @@ def test_no_crs(tmpdir):
|
||||
def test_context(tmpdir):
|
||||
name = str(tmpdir.join("test_context.tif"))
|
||||
with rasterio.open(
|
||||
name, 'w',
|
||||
driver='GTiff', width=100, height=100, count=1,
|
||||
name, 'w',
|
||||
driver='GTiff', width=100, height=100, count=1,
|
||||
dtype=rasterio.ubyte) as s:
|
||||
assert s.name == name
|
||||
assert s.driver == 'GTiff'
|
||||
assert s.closed == False
|
||||
assert not s.closed
|
||||
assert s.count == 1
|
||||
assert s.width == 100
|
||||
assert s.height == 100
|
||||
assert s.shape == (100, 100)
|
||||
assert s.indexes == (1,)
|
||||
assert repr(s) == "<open RasterUpdater name='%s' mode='w'>" % name
|
||||
assert s.closed == True
|
||||
assert s.closed
|
||||
assert s.count == 1
|
||||
assert s.width == 100
|
||||
assert s.height == 100
|
||||
@ -73,13 +69,14 @@ def test_context(tmpdir):
|
||||
assert "GTiff" in info
|
||||
assert "Size is 100, 100" in info
|
||||
assert "Band 1 Block=100x81 Type=Byte, ColorInterp=Gray" in info
|
||||
|
||||
|
||||
|
||||
def test_write_ubyte(tmpdir):
|
||||
name = str(tmpdir.mkdir("sub").join("test_write_ubyte.tif"))
|
||||
a = numpy.ones((100, 100), dtype=rasterio.ubyte) * 127
|
||||
with rasterio.open(
|
||||
name, 'w',
|
||||
driver='GTiff', width=100, height=100, count=1,
|
||||
name, 'w',
|
||||
driver='GTiff', width=100, height=100, count=1,
|
||||
dtype=a.dtype) as s:
|
||||
s.write(a, indexes=1)
|
||||
info = subprocess.check_output(["gdalinfo", "-stats", name]).decode('utf-8')
|
||||
@ -88,8 +85,8 @@ def test_write_ubyte_multi(tmpdir):
|
||||
name = str(tmpdir.mkdir("sub").join("test_write_ubyte_multi.tif"))
|
||||
a = numpy.ones((100, 100), dtype=rasterio.ubyte) * 127
|
||||
with rasterio.open(
|
||||
name, 'w',
|
||||
driver='GTiff', width=100, height=100, count=1,
|
||||
name, 'w',
|
||||
driver='GTiff', width=100, height=100, count=1,
|
||||
dtype=a.dtype) as s:
|
||||
s.write(a, 1)
|
||||
info = subprocess.check_output(["gdalinfo", "-stats", name]).decode('utf-8')
|
||||
@ -98,18 +95,18 @@ def test_write_ubyte_multi_list(tmpdir):
|
||||
name = str(tmpdir.mkdir("sub").join("test_write_ubyte_multi_list.tif"))
|
||||
a = numpy.array([numpy.ones((100, 100), dtype=rasterio.ubyte) * 127])
|
||||
with rasterio.open(
|
||||
name, 'w',
|
||||
driver='GTiff', width=100, height=100, count=1,
|
||||
name, 'w',
|
||||
driver='GTiff', width=100, height=100, count=1,
|
||||
dtype=a.dtype) as s:
|
||||
s.write(a, [1])
|
||||
info = subprocess.check_output(["gdalinfo", "-stats", name]).decode('utf-8')
|
||||
assert "Minimum=127.000, Maximum=127.000, Mean=127.000, StdDev=0.000" in info
|
||||
def test_write_ubyte_multi_3(tmpdir):
|
||||
name = str(tmpdir.mkdir("sub").join("test_write_ubyte_multi_list.tif"))
|
||||
arr = numpy.array(3*[numpy.ones((100, 100), dtype=rasterio.ubyte) * 127])
|
||||
arr = numpy.array(3 * [numpy.ones((100, 100), dtype=rasterio.ubyte) * 127])
|
||||
with rasterio.open(
|
||||
name, 'w',
|
||||
driver='GTiff', width=100, height=100, count=3,
|
||||
name, 'w',
|
||||
driver='GTiff', width=100, height=100, count=3,
|
||||
dtype=arr.dtype) as s:
|
||||
s.write(arr)
|
||||
info = subprocess.check_output(["gdalinfo", "-stats", name]).decode('utf-8')
|
||||
@ -119,7 +116,7 @@ def test_write_float(tmpdir):
|
||||
name = str(tmpdir.join("test_write_float.tif"))
|
||||
a = numpy.ones((100, 100), dtype=rasterio.float32) * 42.0
|
||||
with rasterio.open(
|
||||
name, 'w',
|
||||
name, 'w',
|
||||
driver='GTiff', width=100, height=100, count=2,
|
||||
dtype=rasterio.float32) as s:
|
||||
assert s.dtypes == (rasterio.float32, rasterio.float32)
|
||||
@ -132,7 +129,7 @@ def test_write_crs_transform(tmpdir):
|
||||
name = str(tmpdir.join("test_write_crs_transform.tif"))
|
||||
a = numpy.ones((100, 100), dtype=rasterio.ubyte) * 127
|
||||
transform = [101985.0, 300.0379266750948, 0.0,
|
||||
2826915.0, 0.0, -300.041782729805]
|
||||
2826915.0, 0.0, -300.041782729805]
|
||||
with rasterio.open(
|
||||
name, 'w',
|
||||
driver='GTiff', width=100, height=100, count=1,
|
||||
@ -152,7 +149,7 @@ def test_write_crs_transform_affine(tmpdir):
|
||||
name = str(tmpdir.join("test_write_crs_transform.tif"))
|
||||
a = numpy.ones((100, 100), dtype=rasterio.ubyte) * 127
|
||||
transform = [101985.0, 300.0379266750948, 0.0,
|
||||
2826915.0, 0.0, -300.041782729805]
|
||||
2826915.0, 0.0, -300.041782729805]
|
||||
with rasterio.open(
|
||||
name, 'w',
|
||||
driver='GTiff', width=100, height=100, count=1,
|
||||
@ -173,7 +170,7 @@ def test_write_crs_transform_2(tmpdir):
|
||||
name = str(tmpdir.join("test_write_crs_transform.tif"))
|
||||
a = numpy.ones((100, 100), dtype=rasterio.ubyte) * 127
|
||||
transform = [101985.0, 300.0379266750948, 0.0,
|
||||
2826915.0, 0.0, -300.041782729805]
|
||||
2826915.0, 0.0, -300.041782729805]
|
||||
with rasterio.open(
|
||||
name, 'w',
|
||||
driver='GTiff', width=100, height=100, count=1,
|
||||
@ -193,7 +190,7 @@ def test_write_crs_transform_3(tmpdir):
|
||||
name = str(tmpdir.join("test_write_crs_transform.tif"))
|
||||
a = numpy.ones((100, 100), dtype=rasterio.ubyte) * 127
|
||||
transform = [101985.0, 300.0379266750948, 0.0,
|
||||
2826915.0, 0.0, -300.041782729805]
|
||||
2826915.0, 0.0, -300.041782729805]
|
||||
crs_wkt = 'PROJCS["UTM Zone 18, Northern Hemisphere",GEOGCS["WGS 84",DATUM["unknown",SPHEROID["WGS84",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",-75],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["Meter",1]]'
|
||||
with rasterio.open(
|
||||
name, 'w',
|
||||
@ -235,20 +232,19 @@ def test_guard_nodata(tmpdir):
|
||||
name = str(tmpdir.join("test_guard_nodata.tif"))
|
||||
a = numpy.ones((100, 100), dtype=rasterio.ubyte) * 127
|
||||
with pytest.raises(ValueError):
|
||||
with rasterio.open(
|
||||
name, 'w',
|
||||
driver='GTiff', width=100, height=100, count=2,
|
||||
dtype=a.dtype, nodata=-1) as s:
|
||||
pass
|
||||
rasterio.open(
|
||||
name, 'w',
|
||||
driver='GTiff', width=100, height=100, count=2,
|
||||
dtype=a.dtype, nodata=-1)
|
||||
|
||||
|
||||
def test_write_lzw(tmpdir):
|
||||
name = str(tmpdir.join("test_write_lzw.tif"))
|
||||
a = numpy.ones((100, 100), dtype=rasterio.ubyte) * 127
|
||||
with rasterio.open(
|
||||
name, 'w',
|
||||
driver='GTiff',
|
||||
width=100, height=100, count=1,
|
||||
name, 'w',
|
||||
driver='GTiff',
|
||||
width=100, height=100, count=1,
|
||||
dtype=a.dtype,
|
||||
compress='LZW') as s:
|
||||
assert ('compress', 'LZW') in s.kwds.items()
|
||||
@ -261,12 +257,11 @@ def test_write_noncontiguous(tmpdir):
|
||||
ROWS = 4
|
||||
COLS = 10
|
||||
BANDS = 6
|
||||
with rasterio.drivers():
|
||||
# Create a 3-D random int array (rows, columns, bands)
|
||||
total = ROWS * COLS * BANDS
|
||||
arr = numpy.random.randint(
|
||||
0, 10, size=total).reshape(
|
||||
(ROWS, COLS, BANDS), order='F').astype(numpy.int32)
|
||||
# Create a 3-D random int array (rows, columns, bands)
|
||||
total = ROWS * COLS * BANDS
|
||||
arr = numpy.random.randint(
|
||||
0, 10, size=total).reshape(
|
||||
(ROWS, COLS, BANDS), order='F').astype(numpy.int32)
|
||||
kwargs = {
|
||||
'driver': 'GTiff',
|
||||
'width': COLS,
|
||||
@ -276,5 +271,4 @@ def test_write_noncontiguous(tmpdir):
|
||||
}
|
||||
with rasterio.open(name, 'w', **kwargs) as dst:
|
||||
for i in range(BANDS):
|
||||
dst.write(arr[:,:,i], indexes=i+1)
|
||||
|
||||
dst.write(arr[:, :, i], indexes=i + 1)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user