mirror of
https://github.com/rasterio/rasterio.git
synced 2025-12-08 17:36:12 +00:00
Add param error handling.
Surface the geographic and projected crs testing functions to the crs module and use them within edit-info. Merge the edit-info cmd into the info module alongside the info cmd. Add a few more tests of the error handling to get to 100% coverage of the info cmd module.
This commit is contained in:
parent
3a783277f7
commit
9fed2a005b
@ -10,6 +10,7 @@
|
||||
# {'proj': 'longlat', 'ellps': 'WGS84', 'datum': 'WGS84', 'no_defs': True}
|
||||
#
|
||||
|
||||
from rasterio._base import is_geographic_crs, is_projected_crs
|
||||
from rasterio.five import string_types
|
||||
|
||||
def to_string(crs):
|
||||
|
||||
@ -1,65 +0,0 @@
|
||||
"""Edit raster dataset metadata from the command line."""
|
||||
|
||||
import json
|
||||
import logging
|
||||
|
||||
import click
|
||||
|
||||
import rasterio
|
||||
from rasterio.rio.cli import cli, file_in_arg
|
||||
from rasterio.transform import guard_transform
|
||||
|
||||
|
||||
@cli.command(short_help="Edit dataset metadata.")
|
||||
@file_in_arg
|
||||
@click.option('--nodata', type=float, default=None,
|
||||
help="New nodata value")
|
||||
@click.option('--crs', help="New coordinate reference system")
|
||||
@click.option('--transform', help="New affine transform matrix")
|
||||
@click.option('--tag', 'tags', multiple=True, metavar='KEY=VAL',
|
||||
help="New tag.")
|
||||
@click.pass_context
|
||||
def edit(ctx, input, nodata, crs, transform, tags):
|
||||
"""Edit a dataset's metadata: coordinate reference system, affine
|
||||
transformation matrix, nodata value, and tags.
|
||||
|
||||
CRS may be either a PROJ.4 or EPSG:nnnn string, or a JSON-encoded
|
||||
PROJ.4 object.
|
||||
|
||||
Transforms are either JSON-encoded Affine objects (preferred) like
|
||||
|
||||
[300.038, 0.0, 101985.0, 0.0, -300.042, 2826915.0]
|
||||
|
||||
or JSON-encoded GDAL geotransform arrays like
|
||||
|
||||
[101985.0, 300.038, 0.0, 2826915.0, 0.0, -300.042]
|
||||
"""
|
||||
verbosity = (ctx.obj and ctx.obj.get('verbosity')) or 1
|
||||
logger = logging.getLogger('rio')
|
||||
|
||||
with rasterio.drivers(CPL_DEBUG=(verbosity > 2)) as env:
|
||||
with rasterio.open(input, 'r+') as dst:
|
||||
|
||||
# Update nodata.
|
||||
if nodata:
|
||||
dst.nodata = nodata
|
||||
|
||||
# Update CRS. Value might be a PROJ.4 string or a JSON
|
||||
# encoded dict.
|
||||
if crs:
|
||||
crs = crs.strip()
|
||||
try:
|
||||
crs = json.loads(crs)
|
||||
except ValueError:
|
||||
pass
|
||||
dst.crs = crs
|
||||
|
||||
# Update transform. Value might be a JSON encoded
|
||||
# Affine object or a GDAL geotransform array.
|
||||
if transform:
|
||||
dst.transform = guard_transform(json.loads(transform))
|
||||
|
||||
# Update tags.
|
||||
if tags:
|
||||
tags = dict(p.split('=') for p in tags)
|
||||
dst.update_tags(**tags)
|
||||
@ -1,4 +1,4 @@
|
||||
# Info command.
|
||||
"""Fetch and edit raster dataset metadata from the command line."""
|
||||
|
||||
import json
|
||||
import logging
|
||||
@ -9,6 +9,94 @@ import click
|
||||
import rasterio
|
||||
import rasterio.crs
|
||||
from rasterio.rio.cli import cli, bidx_opt, file_in_arg, masked_opt
|
||||
from rasterio.transform import guard_transform
|
||||
|
||||
|
||||
@cli.command('edit-info', short_help="Edit dataset metadata.")
|
||||
@file_in_arg
|
||||
@click.option('--nodata', type=float, default=None,
|
||||
help="New nodata value")
|
||||
@click.option('--crs', help="New coordinate reference system")
|
||||
@click.option('--transform', help="New affine transform matrix")
|
||||
@click.option('--tag', 'tags', multiple=True, metavar='KEY=VAL',
|
||||
help="New tag.")
|
||||
@click.pass_context
|
||||
def edit(ctx, input, nodata, crs, transform, tags):
|
||||
"""Edit a dataset's metadata: coordinate reference system, affine
|
||||
transformation matrix, nodata value, and tags.
|
||||
|
||||
CRS may be either a PROJ.4 or EPSG:nnnn string, or a JSON-encoded
|
||||
PROJ.4 object.
|
||||
|
||||
Transforms are either JSON-encoded Affine objects (preferred) like
|
||||
|
||||
[300.038, 0.0, 101985.0, 0.0, -300.042, 2826915.0]
|
||||
|
||||
or JSON-encoded GDAL geotransform arrays like
|
||||
|
||||
[101985.0, 300.038, 0.0, 2826915.0, 0.0, -300.042]
|
||||
"""
|
||||
verbosity = (ctx.obj and ctx.obj.get('verbosity')) or 1
|
||||
logger = logging.getLogger('rio')
|
||||
|
||||
with rasterio.drivers(CPL_DEBUG=(verbosity > 2)) as env:
|
||||
with rasterio.open(input, 'r+') as dst:
|
||||
|
||||
# Update nodata.
|
||||
if nodata is not None:
|
||||
|
||||
from rasterio._io import in_dtype_range
|
||||
dtype = dst.dtypes[0]
|
||||
if not in_dtype_range(nodata, dtype):
|
||||
raise click.BadParameter(
|
||||
"outside the range of the file's "
|
||||
"data type (%s)." % dtype,
|
||||
param=nodata, param_hint='nodata')
|
||||
|
||||
dst.nodata = nodata
|
||||
|
||||
|
||||
# Update CRS. Value might be a PROJ.4 string or a JSON
|
||||
# encoded dict.
|
||||
if crs:
|
||||
new_crs = crs.strip()
|
||||
try:
|
||||
new_crs = json.loads(crs)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
if not (rasterio.crs.is_geographic_crs(new_crs) or
|
||||
rasterio.crs.is_projected_crs(new_crs)):
|
||||
raise click.BadParameter(
|
||||
"'%s' is not a recognized CRS." % crs,
|
||||
param=crs, param_hint='crs')
|
||||
|
||||
dst.crs = new_crs
|
||||
|
||||
# Update transform. Value might be a JSON encoded
|
||||
# Affine object or a GDAL geotransform array.
|
||||
if transform:
|
||||
try:
|
||||
transform_obj = json.loads(transform)
|
||||
except ValueError:
|
||||
raise click.BadParameter(
|
||||
"'%s' is not a JSON array." % transform,
|
||||
param=transform, param_hint='transform')
|
||||
|
||||
try:
|
||||
transform_obj = guard_transform(transform_obj)
|
||||
except:
|
||||
raise click.BadParameter(
|
||||
"'%s' is not recognized as an Affine or GDAL "
|
||||
"geotransform array." % transform,
|
||||
param=transform, param_hint='transform')
|
||||
|
||||
dst.transform = transform_obj
|
||||
|
||||
# Update tags.
|
||||
if tags:
|
||||
tags = dict(p.split('=') for p in tags)
|
||||
dst.update_tags(**tags)
|
||||
|
||||
|
||||
@cli.command(short_help="Print information about the rio environment.")
|
||||
|
||||
2
setup.py
2
setup.py
@ -207,7 +207,7 @@ setup_args = dict(
|
||||
[rasterio.rio_commands]
|
||||
bounds=rasterio.rio.rio:bounds
|
||||
calc=rasterio.rio.calc:calc
|
||||
edit=rasterio.rio.edit:edit
|
||||
edit-info=rasterio.rio.info:edit
|
||||
env=rasterio.rio.info:env
|
||||
info=rasterio.rio.info:info
|
||||
insp=rasterio.rio.rio:insp
|
||||
|
||||
@ -5,12 +5,19 @@ import sys
|
||||
from click.testing import CliRunner
|
||||
|
||||
import rasterio
|
||||
from rasterio.rio.edit import edit
|
||||
from rasterio.rio.info import edit
|
||||
|
||||
|
||||
logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
|
||||
|
||||
|
||||
def test_edit_nodata_err(data):
|
||||
runner = CliRunner()
|
||||
inputfile = str(data.join('RGB.byte.tif'))
|
||||
result = runner.invoke(edit, [inputfile, '--nodata', '-1'])
|
||||
assert result.exit_code == 2
|
||||
|
||||
|
||||
def test_edit_nodata(data):
|
||||
runner = CliRunner()
|
||||
inputfile = str(data.join('RGB.byte.tif'))
|
||||
@ -20,6 +27,13 @@ def test_edit_nodata(data):
|
||||
assert src.nodata == 255.0
|
||||
|
||||
|
||||
def test_edit_crs_err(data):
|
||||
runner = CliRunner()
|
||||
inputfile = str(data.join('RGB.byte.tif'))
|
||||
result = runner.invoke(edit, [inputfile, '--crs', 'LOL:WUT'])
|
||||
assert result.exit_code == 2
|
||||
|
||||
|
||||
def test_edit_crs_epsg(data):
|
||||
runner = CliRunner()
|
||||
inputfile = str(data.join('RGB.byte.tif'))
|
||||
@ -48,6 +62,20 @@ def test_edit_crs_obj(data):
|
||||
assert src.crs == {'init': 'epsg:32618'}
|
||||
|
||||
|
||||
def test_edit_transform_err_not_json(data):
|
||||
runner = CliRunner()
|
||||
inputfile = str(data.join('RGB.byte.tif'))
|
||||
result = runner.invoke(edit, [inputfile, '--transform', 'LOL'])
|
||||
assert result.exit_code == 2
|
||||
|
||||
|
||||
def test_edit_transform_err_bad_array(data):
|
||||
runner = CliRunner()
|
||||
inputfile = str(data.join('RGB.byte.tif'))
|
||||
result = runner.invoke(edit, [inputfile, '--transform', '[1,2]'])
|
||||
assert result.exit_code == 2
|
||||
|
||||
|
||||
def test_edit_transform_affine(data):
|
||||
runner = CliRunner()
|
||||
inputfile = str(data.join('RGB.byte.tif'))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user