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:
Sean Gillies 2016-04-12 16:41:40 -06:00
parent bb7cb1a1c1
commit 12f8fc7e3f
59 changed files with 891 additions and 863 deletions

View File

@ -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)

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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:

View File

@ -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)

View File

@ -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
View 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)

View File

@ -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")

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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()

View File

@ -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]

View File

@ -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]

View File

@ -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:

View File

@ -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))

View File

@ -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]

View File

@ -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'

View File

@ -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)

View File

@ -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()

View File

@ -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)

View File

@ -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:

View File

@ -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:

View File

@ -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

View File

@ -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:

View File

@ -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:

View File

@ -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))

View File

@ -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()

View File

@ -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))

View File

@ -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")

View File

@ -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,

View File

@ -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/*']}

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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):

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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
View 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

View File

@ -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')))

View File

@ -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:

View File

@ -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()

View File

@ -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'

View File

@ -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")

View File

@ -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'))

View File

@ -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)

View File

@ -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'))

View File

@ -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)

View File

@ -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):

View File

@ -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))

View File

@ -1,4 +1,4 @@
from rasterio.warnings import NodataShadowWarning
from rasterio.errors import NodataShadowWarning
def test_nodata_shadow():

View File

@ -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)

View File

@ -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'},

View File

@ -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)