This is an automated email from the git hooks/post-receive script. johanvdw-guest pushed a commit to branch master in repository fiona.
commit 276e641265b49fc882e00d2bd3cd1cc1978de1a7 Author: Johan Van de Wauw <johan.vandew...@gmail.com> Date: Wed Oct 22 22:26:58 2014 +0200 Imported Upstream version 1.4.6 --- CHANGES.txt | 13 +- Fiona.egg-info/PKG-INFO | 15 +- Fiona.egg-info/SOURCES.txt | 4 + Fiona.egg-info/requires.txt | 2 +- PKG-INFO | 15 +- VERSION.txt | 2 +- docs/cli.rst | 27 +++ fiona/__init__.py | 2 +- fiona/fio/bounds.py | 85 +++++++ fiona/fio/cat.py | 82 +++++-- fiona/fio/cli.py | 24 ++ fiona/fio/fio.py | 7 +- fiona/fio/stream.py | 55 +++++ fiona/ogrext.c | 554 ++++++++++++++++++++------------------------ setup.cfg | 2 +- tests/test_bounds.py | 4 + tests/test_fio_bounds.py | 86 +++++++ tests/test_fio_cat.py | 105 +++++++++ tests/test_geopackage.py | 9 + tests/test_schema.py | 20 ++ 20 files changed, 782 insertions(+), 331 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 59152eb..5932ba9 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,9 +1,20 @@ Changes ======= +1.4.6 (2014-10-21) +------------------ +- Handle 3D coordinates in bounds() #178. + +1.4.5 (2014-10-18) +------------------ +- Add --bbox option to fio-cat (#163). +- Skip geopackage tests if run from an sdist (#167). +- Add fio-bounds and fio-distrib. +- Restore fio-dump to working order. + 1.4.4 (2014-10-13) ------------------ -- Fix accidental requirement on GDAL 1.10 introduced in 1.4.3 (#164). +- Fix accidental requirement on GDAL 1.11 introduced in 1.4.3 (#164). 1.4.3 (2014-10-10) ------------------ diff --git a/Fiona.egg-info/PKG-INFO b/Fiona.egg-info/PKG-INFO index 27b36f1..dc48fef 100644 --- a/Fiona.egg-info/PKG-INFO +++ b/Fiona.egg-info/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: Fiona -Version: 1.4.4 +Version: 1.4.6 Summary: Fiona reads and writes spatial data files Home-page: http://github.com/Toblerity/Fiona Author: Sean Gillies @@ -288,9 +288,20 @@ Description: ===== Changes ======= + 1.4.6 (2014-10-21) + ------------------ + - Handle 3D coordinates in bounds() #178. + + 1.4.5 (2014-10-18) + ------------------ + - Add --bbox option to fio-cat (#163). + - Skip geopackage tests if run from an sdist (#167). + - Add fio-bounds and fio-distrib. + - Restore fio-dump to working order. + 1.4.4 (2014-10-13) ------------------ - - Fix accidental requirement on GDAL 1.10 introduced in 1.4.3 (#164). + - Fix accidental requirement on GDAL 1.11 introduced in 1.4.3 (#164). 1.4.3 (2014-10-10) ------------------ diff --git a/Fiona.egg-info/SOURCES.txt b/Fiona.egg-info/SOURCES.txt index 5b2796c..55a7ccf 100644 --- a/Fiona.egg-info/SOURCES.txt +++ b/Fiona.egg-info/SOURCES.txt @@ -16,9 +16,11 @@ setup.py ./fiona/tool.py ./fiona/transform.py ./fiona/fio/__init__.py +./fiona/fio/bounds.py ./fiona/fio/cat.py ./fiona/fio/cli.py ./fiona/fio/fio.py +./fiona/fio/stream.py Fiona.egg-info/PKG-INFO Fiona.egg-info/SOURCES.txt Fiona.egg-info/dependency_links.txt @@ -47,6 +49,8 @@ tests/test_collection.py tests/test_crs.py tests/test_drivers.py tests/test_feature.py +tests/test_fio_bounds.py +tests/test_fio_cat.py tests/test_geojson.py tests/test_geometry.py tests/test_geopackage.py diff --git a/Fiona.egg-info/requires.txt b/Fiona.egg-info/requires.txt index 424e67c..19f7fd7 100644 --- a/Fiona.egg-info/requires.txt +++ b/Fiona.egg-info/requires.txt @@ -1,2 +1,2 @@ click -six +six \ No newline at end of file diff --git a/PKG-INFO b/PKG-INFO index 27b36f1..dc48fef 100644 --- a/PKG-INFO +++ b/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: Fiona -Version: 1.4.4 +Version: 1.4.6 Summary: Fiona reads and writes spatial data files Home-page: http://github.com/Toblerity/Fiona Author: Sean Gillies @@ -288,9 +288,20 @@ Description: ===== Changes ======= + 1.4.6 (2014-10-21) + ------------------ + - Handle 3D coordinates in bounds() #178. + + 1.4.5 (2014-10-18) + ------------------ + - Add --bbox option to fio-cat (#163). + - Skip geopackage tests if run from an sdist (#167). + - Add fio-bounds and fio-distrib. + - Restore fio-dump to working order. + 1.4.4 (2014-10-13) ------------------ - - Fix accidental requirement on GDAL 1.10 introduced in 1.4.3 (#164). + - Fix accidental requirement on GDAL 1.11 introduced in 1.4.3 (#164). 1.4.3 (2014-10-10) ------------------ diff --git a/VERSION.txt b/VERSION.txt index e1df5de..7b5753f 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -1.4.4 \ No newline at end of file +1.4.6 \ No newline at end of file diff --git a/docs/cli.rst b/docs/cli.rst index d33d87c..be4d25d 100644 --- a/docs/cli.rst +++ b/docs/cli.rst @@ -15,15 +15,42 @@ Fiona's new command line interface is a program named "fio". --help Show this message and exit. Commands: + bounds Print the extent of GeoJSON objects cat Concatenate and print the features of datasets collect Collect a sequence of features. dump Dump a dataset to GeoJSON. + env Print information about the rio environment. info Print information about a dataset. insp Open a dataset and start an interpreter. load Load GeoJSON to a dataset in another format. It is developed using the ``click`` package and is new in 1.1.6. +bounds +------ + +New in 1.4.5. + +Fio-bounds reads LF or RS-delimited GeoJSON texts, either features or +collections, from stdin and prints their bounds with or without other data to +stdout. + +With no options, it works like this: + +.. code-block:: console + + $ fio cat docs/data/test_uk.shp | head -n 1 \ + > | fio bounds + [0.735, 51.357216, 0.947778, 51.444717] + +Using ``--with-id`` gives you + +.. code-block:: console + + $ fio cat docs/data/test_uk.shp | head -n 1 \ + > | fio bounds --with-id + {"id": "0", "bbox": [0.735, 51.357216, 0.947778, 51.444717]} + cat --- diff --git a/fiona/__init__.py b/fiona/__init__.py index 38a6e0b..829be19 100644 --- a/fiona/__init__.py +++ b/fiona/__init__.py @@ -63,7 +63,7 @@ writing modes) flush contents to disk when their ``with`` blocks end. """ __all__ = ['bounds', 'listlayers', 'open', 'prop_type', 'prop_width'] -__version__ = "1.4.4" +__version__ = "1.4.6" import logging import os diff --git a/fiona/fio/bounds.py b/fiona/fio/bounds.py new file mode 100644 index 0000000..cf30132 --- /dev/null +++ b/fiona/fio/bounds.py @@ -0,0 +1,85 @@ +import json +import logging +import sys + +import click + +import fiona +from fiona.fio.cli import cli, obj_gen + + +# Bounds command +@cli.command(short_help="Print the extent of GeoJSON objects") +@click.option('--precision', type=int, default=-1, metavar="N", + help="Decimal precision of coordinates.") +@click.option('--explode/--no-explode', default=False, + help="Explode collections into features (default: no).") +@click.option('--with-id/--without-id', default=False, + help="Print GeoJSON ids and bounding boxes together " + "(default: without).") +@click.option('--with-obj/--without-obj', default=False, + help="Print GeoJSON objects and bounding boxes together " + "(default: without).") +@click.option('--x-json-seq-rs/--x-json-seq-no-rs', default=False, + help="Use RS as text separator instead of LF. " + "Experimental (default: no).") +@click.pass_context +def bounds(ctx, precision, explode, with_id, with_obj, x_json_seq_rs): + """Print the bounding boxes of GeoJSON objects read from stdin. + + Optionally explode collections and print the bounds of their + features. + + To print identifiers for input objects along with their bounds + as a {id: identifier, bbox: bounds} JSON object, use --with-id. + + To print the input objects themselves along with their bounds + as GeoJSON object, use --with-obj. This has the effect of updating + input objects with {id: identifier, bbox: bounds}. + """ + verbosity = (ctx.obj and ctx.obj['verbosity']) or 2 + logger = logging.getLogger('fio') + stdin = click.get_text_stream('stdin') + stdout = click.get_text_stream('stdout') + try: + source = obj_gen(stdin) + for i, obj in enumerate(source): + obj_id = obj.get('id', 'collection:' + str(i)) + xs = [] + ys = [] + features = obj.get('features') or [obj] + for j, feat in enumerate(features): + feat_id = feat.get('id', 'feature:' + str(i)) + w, s, e, n = fiona.bounds(feat) + if precision > 0: + w, s, e, n = (round(v, precision) + for v in (w, s, e, n)) + if explode: + if with_id: + rec = {'parent': obj_id, 'id': feat_id, 'bbox': (w, s, e, n)} + elif with_obj: + feat.update(parent=obj_id, bbox=(w, s, e, n)) + rec = feat + else: + rec = (w, s, e, n) + stdout.write(json.dumps(rec)) + stdout.write('\n') + else: + xs.extend([w, e]) + ys.extend([s, n]) + if not explode: + w, s, e, n = (min(xs), min(ys), max(xs), max(ys)) + if with_id: + rec = {'id': obj_id, 'bbox': (w, s, e, n)} + elif with_obj: + obj.update(id=obj_id, bbox=(w, s, e, n)) + rec = obj + else: + rec = (w, s, e, n) + stdout.write(json.dumps(rec)) + stdout.write('\n') + + sys.exit(0) + except Exception: + logger.exception("Failed. Exception caught") + sys.exit(1) diff --git a/fiona/fio/cat.py b/fiona/fio/cat.py index 2986d8c..e650cbd 100644 --- a/fiona/fio/cat.py +++ b/fiona/fio/cat.py @@ -7,7 +7,7 @@ import click import fiona from fiona.transform import transform_geom -from fiona.fio.cli import cli +from fiona.fio.cli import cli, obj_gen def make_ld_context(context_items): @@ -64,26 +64,29 @@ def id_record(rec): # One or more files. @click.argument('input', nargs=-1, type=click.Path(exists=True)) # Coordinate precision option. -@click.option('--precision', type=int, default=-1, +@click.option('--precision', type=int, default=-1, metavar="N", help="Decimal precision of coordinates.") -@click.option('--indent', default=None, type=int, +@click.option('--indent', default=None, type=int, metavar="N", help="Indentation level for pretty printed output.") @click.option('--compact/--no-compact', default=False, help="Use compact separators (',', ':').") @click.option('--ignore-errors/--no-ignore-errors', default=False, help="log errors but do not stop serialization.") -@click.option('--dst_crs', default=None, help="Destination CRS.") +@click.option('--dst_crs', default=None, metavar="EPSG:NNNN", + help="Destination CRS.") # Use ASCII RS control code to signal a sequence item (False is default). # See http://tools.ietf.org/html/draft-ietf-json-text-sequence-05. # Experimental. @click.option('--x-json-seq-rs/--x-json-seq-no-rs', default=True, help="Use RS as text separator instead of LF. Experimental.") +@click.option('--bbox', default=None, metavar="w,s,e,n", + help="filter for features intersecting a bounding box") @click.pass_context def cat(ctx, input, precision, indent, compact, ignore_errors, dst_crs, - x_json_seq_rs): + x_json_seq_rs, bbox): """Concatenate and print the features of input datasets as a sequence of GeoJSON features.""" - verbosity = ctx.obj['verbosity'] + verbosity = (ctx.obj and ctx.obj['verbosity']) or 2 logger = logging.getLogger('fio') sink = click.get_text_stream('stdout') @@ -98,13 +101,16 @@ def cat(ctx, input, precision, indent, compact, ignore_errors, dst_crs, with fiona.drivers(CPL_DEBUG=verbosity>2): for path in input: with fiona.open(path) as src: - for feat in src: + if bbox: + bbox = tuple(map(float, bbox.split(','))) + for i, feat in src.items(bbox=bbox): if dst_crs or precision > 0: g = transform_geom( src.crs, dst_crs, feat['geometry'], antimeridian_cutting=True, precision=precision) feat['geometry'] = g + feat['bbox'] = fiona.bounds(g) if x_json_seq_rs: sink.write(u'\u001e') json.dump(feat, sink, **dump_kwds) @@ -118,28 +124,29 @@ def cat(ctx, input, precision, indent, compact, ignore_errors, dst_crs, # Collect command @cli.command(short_help="Collect a sequence of features.") # Coordinate precision option. -@click.option('--precision', type=int, default=-1, +@click.option('--precision', type=int, default=-1, metavar="N", help="Decimal precision of coordinates.") -@click.option('--indent', default=None, type=int, +@click.option('--indent', default=None, type=int, metavar="N", help="Indentation level for pretty printed output.") @click.option('--compact/--no-compact', default=False, help="Use compact separators (',', ':').") @click.option('--record-buffered/--no-record-buffered', default=False, - help="Economical buffering of writes at record, not collection " - "(default), level.") + help="Economical buffering of writes at record, not collection " + "(default), level.") @click.option('--ignore-errors/--no-ignore-errors', default=False, help="log errors but do not stop serialization.") -@click.option('--src_crs', default=None, help="Source CRS.") +@click.option('--src_crs', default=None, metavar="EPSG:NNNN", + help="Source CRS.") @click.option('--with-ld-context/--without-ld-context', default=False, - help="add a JSON-LD context to JSON output.") + help="add a JSON-LD context to JSON output.") @click.option('--add-ld-context-item', multiple=True, - help="map a term to a URI and add it to the output's JSON LD context.") + help="map a term to a URI and add it to the output's JSON LD context.") @click.pass_context def collect(ctx, precision, indent, compact, record_buffered, ignore_errors, src_crs, with_ld_context, add_ld_context_item): """Make a GeoJSON feature collection from a sequence of GeoJSON features and print it.""" - verbosity = ctx.obj['verbosity'] + verbosity = (ctx.obj and ctx.obj['verbosity']) or 2 logger = logging.getLogger('fio') stdin = click.get_text_stream('stdin') sink = click.get_text_stream('stdout') @@ -178,7 +185,9 @@ def collect(ctx, precision, indent, compact, record_buffered, ignore_errors, yield feat else: def feature_gen(): - yield json.loads(first_line) + feat = json.loads(first_line) + feat['geometry'] = transformer(feat['geometry']) + yield feat for line in stdin: feat = json.loads(line) feat['geometry'] = transformer(feat['geometry']) @@ -292,6 +301,37 @@ def collect(ctx, precision, indent, compact, record_buffered, ignore_errors, sys.exit(1) +# Distribute command +@cli.command(short_help="Distribute features from a collection") +@click.option('--x-json-seq-rs/--x-json-seq-no-rs', default=False, + help="Use RS as text separator instead of LF. " + "Experimental (default: no).") +@click.pass_context +def distrib(ctx, x_json_seq_rs): + """Print the features of GeoJSON objects read from stdin. + """ + verbosity = (ctx.obj and ctx.obj['verbosity']) or 2 + logger = logging.getLogger('fio') + stdin = click.get_text_stream('stdin') + stdout = click.get_text_stream('stdout') + try: + source = obj_gen(stdin) + for i, obj in enumerate(source): + obj_id = obj.get('id', 'collection:' + str(i)) + features = obj.get('features') or [obj] + for j, feat in enumerate(features): + if obj.get('type') == 'FeatureCollection': + feat['parent'] = obj_id + feat_id = feat.get('id', 'feature:' + str(i)) + feat['id'] = feat_id + stdout.write(json.dumps(feat)) + stdout.write('\n') + sys.exit(0) + except Exception: + logger.exception("Failed. Exception caught") + sys.exit(1) + + # Dump command @cli.command(short_help="Dump a dataset to GeoJSON.") @click.argument('input', type=click.Path(), required=True) @@ -327,7 +367,7 @@ def dump(ctx, input, encoding, precision, indent, compact, record_buffered, x_json_seq, x_json_seq_rs): """Dump a dataset either as a GeoJSON feature collection (the default) or a sequence of GeoJSON features.""" - verbosity = ctx.obj['verbosity'] + verbosity = (ctx.obj and ctx.obj['verbosity']) or 2 logger = logging.getLogger('fio') sink = click.get_text_stream('stdout') @@ -342,8 +382,8 @@ def dump(ctx, input, encoding, precision, indent, compact, record_buffered, if encoding: open_kwds['encoding'] = encoding - def transformer(feat): - tg = partial(transform_geom, src_crs, 'EPSG:4326', + def transformer(crs, feat): + tg = partial(transform_geom, crs, 'EPSG:4326', antimeridian_cutting=True, precision=precision) feat['geometry'] = tg(feat['geometry']) return feat @@ -356,7 +396,7 @@ def dump(ctx, input, encoding, precision, indent, compact, record_buffered, if x_json_seq: for feat in source: - feat = transformer(feat) + feat = transformer(source.crs, feat) if x_json_seq_rs: sink.write(u'\u001e') json.dump(feat, sink, **dump_kwds) @@ -466,7 +506,7 @@ def dump(ctx, input, encoding, precision, indent, compact, record_buffered, collection['features'] = [ id_record(transformer(rec)) for rec in source] else: - collection['features'] = [transformer(rec) for rec in source] + collection['features'] = [transformer(source.crs, rec) for rec in source] json.dump(collection, sink, **dump_kwds) sys.exit(0) diff --git a/fiona/fio/cli.py b/fiona/fio/cli.py index 8d38fa0..9ad6bd8 100644 --- a/fiona/fio/cli.py +++ b/fiona/fio/cli.py @@ -1,3 +1,4 @@ +import json import logging import sys import warnings @@ -34,3 +35,26 @@ def cli(ctx, verbose, quiet): configure_logging(verbosity) ctx.obj = {} ctx.obj['verbosity'] = verbosity + + +def obj_gen(lines): + """Return a generator of JSON objects loaded from ``lines``.""" + first_line = next(lines) + if first_line.startswith(u'\x1e'): + def gen(): + buffer = first_line.strip(u'\x1e') + for line in lines: + if line.startswith(u'\x1e'): + if buffer: + yield json.loads(buffer) + buffer = line.strip(u'\x1e') + else: + buffer += line + else: + yield json.loads(buffer) + else: + def gen(): + yield json.loads(first_line) + for line in lines: + yield json.loads(line) + return gen() diff --git a/fiona/fio/fio.py b/fiona/fio/fio.py index 0bb61d4..925eebe 100644 --- a/fiona/fio/fio.py +++ b/fiona/fio/fio.py @@ -17,7 +17,8 @@ import fiona import fiona.crs from fiona.transform import transform_geom from fiona.fio.cli import cli -from fiona.fio.cat import cat, dump +from fiona.fio.cat import cat, collect, dump, distrib +from fiona.fio.bounds import bounds FIELD_TYPES_MAP_REV = dict([(v, k) for k, v in fiona.FIELD_TYPES_MAP.items()]) @@ -26,12 +27,12 @@ warnings.simplefilter('default') # Commands are below. -@cli.command(short_help="Print information about the rio environment.") +@cli.command(short_help="Print information about the fio environment.") @click.option('--formats', 'key', flag_value='formats', default=True, help="Enumerate the available formats.") @click.pass_context def env(ctx, key): - """Print information about the Rasterio environment: available + """Print information about the Fiona environment: available formats, etc. """ verbosity = (ctx.obj and ctx.obj.get('verbosity')) or 1 diff --git a/fiona/fio/stream.py b/fiona/fio/stream.py new file mode 100644 index 0000000..e7513d2 --- /dev/null +++ b/fiona/fio/stream.py @@ -0,0 +1,55 @@ +import json +import logging +import sys +import warnings + +import click + +import fiona +from fiona.fio.bounds import bounds +from fiona.fio.cli import obj_gen, generator, processor, streaming + + +@streaming.command('open', short_help="Stream GeoJSON objects read from stdin") +@generator +@click.pass_context +def open_stream(ctx): + """Read lines of JSON text and for each, yield a GeoJSON object. + + Begins a pipeline of internally streamed GeoJSON objects. + """ + verbosity = (ctx.obj and ctx.obj['verbosity']) or 2 + logger = logging.getLogger('fio') + stdin = click.get_text_stream('stdin') + try: + source = obj_gen(stdin) + for obj in source: + yield obj + sys.exit(0) + except Exception: + logger.exception("Failed. Exception caught") + sys.exit(1) + + +@streaming.command('close', short_help="Write streamed GeoJSON objects to stdout") +@click.option('--seq', is_flag=True, default=False, + help="Use RS as text separator instead of LF. " + "Experimental (default: no).") +@processor +@click.pass_context +def close_stream(stream, ctx, seq): + """Write streamed GeoJSON objects to stdout. + + Closes a pipeline of internally streamed GeoJSON objects. + """ + verbosity = (ctx.obj and ctx.obj['verbosity']) or 2 + logger = logging.getLogger('fio') + try: + for obj in stream: + if seq: + click.echo(u'\001e') + click.echo(json.dumps(obj)) + sys.exit(0) + except Exception: + logger.exception("Failed. Exception caught") + sys.exit(1) diff --git a/fiona/ogrext.c b/fiona/ogrext.c index 895cfbd..a04c333 100644 --- a/fiona/ogrext.c +++ b/fiona/ogrext.c @@ -813,13 +813,26 @@ static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg); -static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected); - -static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index); - -static CYTHON_INLINE int __Pyx_IterFinish(void); - -static int __Pyx_IternextUnpackEndCheck(PyObject *retval, Py_ssize_t expected); +#define __Pyx_GetItemInt(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck) \ + (__Pyx_fits_Py_ssize_t(i, type, is_signed) ? \ + __Pyx_GetItemInt_Fast(o, (Py_ssize_t)i, is_list, wraparound, boundscheck) : \ + (is_list ? (PyErr_SetString(PyExc_IndexError, "list index out of range"), (PyObject*)NULL) : \ + __Pyx_GetItemInt_Generic(o, to_py_func(i)))) +#define __Pyx_GetItemInt_List(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck) \ + (__Pyx_fits_Py_ssize_t(i, type, is_signed) ? \ + __Pyx_GetItemInt_List_Fast(o, (Py_ssize_t)i, wraparound, boundscheck) : \ + (PyErr_SetString(PyExc_IndexError, "list index out of range"), (PyObject*)NULL)) +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i, + int wraparound, int boundscheck); +#define __Pyx_GetItemInt_Tuple(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck) \ + (__Pyx_fits_Py_ssize_t(i, type, is_signed) ? \ + __Pyx_GetItemInt_Tuple_Fast(o, (Py_ssize_t)i, wraparound, boundscheck) : \ + (PyErr_SetString(PyExc_IndexError, "tuple index out of range"), (PyObject*)NULL)) +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i, + int wraparound, int boundscheck); +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j); +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, + int is_list, int wraparound, int boundscheck); static CYTHON_INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb); static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb); @@ -844,27 +857,6 @@ static CYTHON_INLINE PyObject* __Pyx_decode_c_string( const char* encoding, const char* errors, PyObject* (*decode_func)(const char *s, Py_ssize_t size, const char *errors)); -#define __Pyx_GetItemInt(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck) \ - (__Pyx_fits_Py_ssize_t(i, type, is_signed) ? \ - __Pyx_GetItemInt_Fast(o, (Py_ssize_t)i, is_list, wraparound, boundscheck) : \ - (is_list ? (PyErr_SetString(PyExc_IndexError, "list index out of range"), (PyObject*)NULL) : \ - __Pyx_GetItemInt_Generic(o, to_py_func(i)))) -#define __Pyx_GetItemInt_List(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck) \ - (__Pyx_fits_Py_ssize_t(i, type, is_signed) ? \ - __Pyx_GetItemInt_List_Fast(o, (Py_ssize_t)i, wraparound, boundscheck) : \ - (PyErr_SetString(PyExc_IndexError, "list index out of range"), (PyObject*)NULL)) -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i, - int wraparound, int boundscheck); -#define __Pyx_GetItemInt_Tuple(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck) \ - (__Pyx_fits_Py_ssize_t(i, type, is_signed) ? \ - __Pyx_GetItemInt_Tuple_Fast(o, (Py_ssize_t)i, wraparound, boundscheck) : \ - (PyErr_SetString(PyExc_IndexError, "tuple index out of range"), (PyObject*)NULL)) -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i, - int wraparound, int boundscheck); -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j); -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, - int is_list, int wraparound, int boundscheck); - static CYTHON_INLINE int __Pyx_PySequence_Contains(PyObject* item, PyObject* seq, int eq) { int result = PySequence_Contains(seq, item); return unlikely(result < 0) ? result : (result == (eq == Py_EQ)); @@ -872,6 +864,14 @@ static CYTHON_INLINE int __Pyx_PySequence_Contains(PyObject* item, PyObject* seq static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); +static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected); + +static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index); + +static CYTHON_INLINE int __Pyx_IterFinish(void); + +static int __Pyx_IternextUnpackEndCheck(PyObject *retval, Py_ssize_t expected); + static CYTHON_INLINE int __Pyx_PyBytes_Equals(PyObject* s1, PyObject* s2, int equals); static CYTHON_INLINE int __Pyx_PyUnicode_Equals(PyObject* s1, PyObject* s2, int equals); @@ -1082,12 +1082,12 @@ static void __Pyx_AddTraceback(const char *funcname, int c_line, static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level); +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value); + static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value); static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *); -static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value); - static CYTHON_INLINE PyObject* __Pyx_PyInt_From_unsigned_int(unsigned int value); static CYTHON_INLINE unsigned int __Pyx_PyInt_As_unsigned_int(PyObject *); @@ -1233,8 +1233,6 @@ static char __pyx_k_f[] = "f"; static char __pyx_k_i[] = "i"; static char __pyx_k_s[] = "+%s"; static char __pyx_k_w[] = "w"; -static char __pyx_k_x[] = "x"; -static char __pyx_k_y[] = "y"; static char __pyx_k_3D[] = "3D "; static char __pyx_k__7[] = "-"; static char __pyx_k_id[] = "id"; @@ -1262,6 +1260,7 @@ static char __pyx_k_s_s[] = "+%s=%s"; static char __pyx_k_six[] = "six"; static char __pyx_k_str[] = "str"; static char __pyx_k_sys[] = "sys"; +static char __pyx_k_xyz[] = "xyz"; static char __pyx_k_zip[] = "zip"; static char __pyx_k_EPSG[] = "EPSG"; static char __pyx_k_args[] = "args"; @@ -1775,8 +1774,7 @@ static PyObject *__pyx_n_s_warn; static PyObject *__pyx_n_s_warnings; static PyObject *__pyx_n_s_wktext; static PyObject *__pyx_n_s_writerecs_locals_validate_geomet; -static PyObject *__pyx_n_s_x; -static PyObject *__pyx_n_s_y; +static PyObject *__pyx_n_s_xyz; static PyObject *__pyx_n_s_year; static PyObject *__pyx_n_s_zip; static PyObject *__pyx_int_0; @@ -2340,8 +2338,7 @@ static PyObject *__pyx_pw_5fiona_6ogrext_4_bounds(PyObject *__pyx_self, PyObject } static PyObject *__pyx_pf_5fiona_6ogrext_3_bounds(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_geometry) { - PyObject *__pyx_v_x = NULL; - PyObject *__pyx_v_y = NULL; + PyObject *__pyx_v_xyz = NULL; PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; @@ -2352,8 +2349,7 @@ static PyObject *__pyx_pf_5fiona_6ogrext_3_bounds(CYTHON_UNUSED PyObject *__pyx_ PyObject *__pyx_t_6 = NULL; PyObject *__pyx_t_7 = NULL; PyObject *__pyx_t_8 = NULL; - PyObject *(*__pyx_t_9)(PyObject *); - int __pyx_t_10; + int __pyx_t_9; int __pyx_lineno = 0; const char *__pyx_filename = NULL; int __pyx_clineno = 0; @@ -2363,8 +2359,8 @@ static PyObject *__pyx_pf_5fiona_6ogrext_3_bounds(CYTHON_UNUSED PyObject *__pyx_ * def _bounds(geometry): * """Bounding box of a GeoJSON geometry""" * try: # <<<<<<<<<<<<<< - * x, y = zip(*list(_explode(geometry['coordinates']))) - * return min(x), min(y), max(x), max(y) + * xyz = tuple(zip(*list(_explode(geometry['coordinates'])))) + * return min(xyz[0]), min(xyz[1]), max(xyz[0]), max(xyz[1]) */ { __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3); @@ -2376,8 +2372,8 @@ static PyObject *__pyx_pf_5fiona_6ogrext_3_bounds(CYTHON_UNUSED PyObject *__pyx_ /* "fiona/ogrext.pyx":110 * """Bounding box of a GeoJSON geometry""" * try: - * x, y = zip(*list(_explode(geometry['coordinates']))) # <<<<<<<<<<<<<< - * return min(x), min(y), max(x), max(y) + * xyz = tuple(zip(*list(_explode(geometry['coordinates'])))) # <<<<<<<<<<<<<< + * return min(xyz[0]), min(xyz[1]), max(xyz[0]), max(xyz[1]) * except (KeyError, TypeError): */ __pyx_t_5 = __Pyx_GetModuleGlobalName(__pyx_n_s_explode); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 110; __pyx_clineno = __LINE__; goto __pyx_L3_error;} @@ -2424,143 +2420,107 @@ static PyObject *__pyx_pf_5fiona_6ogrext_3_bounds(CYTHON_UNUSED PyObject *__pyx_ __pyx_t_4 = __Pyx_PyObject_Call(__pyx_builtin_zip, __pyx_t_5, NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 110; __pyx_clineno = __LINE__; goto __pyx_L3_error;} __Pyx_GOTREF(__pyx_t_4); __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; - if ((likely(PyTuple_CheckExact(__pyx_t_4))) || (PyList_CheckExact(__pyx_t_4))) { - PyObject* sequence = __pyx_t_4; - #if CYTHON_COMPILING_IN_CPYTHON - Py_ssize_t size = Py_SIZE(sequence); - #else - Py_ssize_t size = PySequence_Size(sequence); - #endif - if (unlikely(size != 2)) { - if (size > 2) __Pyx_RaiseTooManyValuesError(2); - else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); - {__pyx_filename = __pyx_f[0]; __pyx_lineno = 110; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - } - #if CYTHON_COMPILING_IN_CPYTHON - if (likely(PyTuple_CheckExact(sequence))) { - __pyx_t_5 = PyTuple_GET_ITEM(sequence, 0); - __pyx_t_8 = PyTuple_GET_ITEM(sequence, 1); - } else { - __pyx_t_5 = PyList_GET_ITEM(sequence, 0); - __pyx_t_8 = PyList_GET_ITEM(sequence, 1); - } - __Pyx_INCREF(__pyx_t_5); - __Pyx_INCREF(__pyx_t_8); - #else - __pyx_t_5 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 110; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - __Pyx_GOTREF(__pyx_t_5); - __pyx_t_8 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 110; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - __Pyx_GOTREF(__pyx_t_8); - #endif - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - } else { - Py_ssize_t index = -1; - __pyx_t_6 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 110; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - __Pyx_GOTREF(__pyx_t_6); - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - __pyx_t_9 = Py_TYPE(__pyx_t_6)->tp_iternext; - index = 0; __pyx_t_5 = __pyx_t_9(__pyx_t_6); if (unlikely(!__pyx_t_5)) goto __pyx_L11_unpacking_failed; - __Pyx_GOTREF(__pyx_t_5); - index = 1; __pyx_t_8 = __pyx_t_9(__pyx_t_6); if (unlikely(!__pyx_t_8)) goto __pyx_L11_unpacking_failed; - __Pyx_GOTREF(__pyx_t_8); - if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_6), 2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 110; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - __pyx_t_9 = NULL; - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; - goto __pyx_L12_unpacking_done; - __pyx_L11_unpacking_failed:; - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; - __pyx_t_9 = NULL; - if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); - {__pyx_filename = __pyx_f[0]; __pyx_lineno = 110; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - __pyx_L12_unpacking_done:; - } - __pyx_v_x = __pyx_t_5; - __pyx_t_5 = 0; - __pyx_v_y = __pyx_t_8; - __pyx_t_8 = 0; + __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 110; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __Pyx_GOTREF(__pyx_t_5); + PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_4); + __Pyx_GIVEREF(__pyx_t_4); + __pyx_t_4 = 0; + __pyx_t_4 = __Pyx_PyObject_Call(((PyObject *)((PyObject*)(&PyTuple_Type))), __pyx_t_5, NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 110; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_v_xyz = ((PyObject*)__pyx_t_4); + __pyx_t_4 = 0; /* "fiona/ogrext.pyx":111 * try: - * x, y = zip(*list(_explode(geometry['coordinates']))) - * return min(x), min(y), max(x), max(y) # <<<<<<<<<<<<<< + * xyz = tuple(zip(*list(_explode(geometry['coordinates'])))) + * return min(xyz[0]), min(xyz[1]), max(xyz[0]), max(xyz[1]) # <<<<<<<<<<<<<< * except (KeyError, TypeError): * return None */ __Pyx_XDECREF(__pyx_r); - __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_t_4 = __Pyx_GetItemInt_Tuple(__pyx_v_xyz, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(__pyx_t_4 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L3_error;}; __Pyx_GOTREF(__pyx_t_4); - __Pyx_INCREF(__pyx_v_x); - PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_x); - __Pyx_GIVEREF(__pyx_v_x); - __pyx_t_8 = __Pyx_PyObject_Call(__pyx_builtin_min, __pyx_t_4, NULL); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - __Pyx_GOTREF(__pyx_t_8); - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - __Pyx_GOTREF(__pyx_t_4); - __Pyx_INCREF(__pyx_v_y); - PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_y); - __Pyx_GIVEREF(__pyx_v_y); - __pyx_t_5 = __Pyx_PyObject_Call(__pyx_builtin_min, __pyx_t_4, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L3_error;} __Pyx_GOTREF(__pyx_t_5); - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_4); + __Pyx_GIVEREF(__pyx_t_4); + __pyx_t_4 = 0; + __pyx_t_4 = __Pyx_PyObject_Call(__pyx_builtin_min, __pyx_t_5, NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L3_error;} __Pyx_GOTREF(__pyx_t_4); - __Pyx_INCREF(__pyx_v_x); - PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_x); - __Pyx_GIVEREF(__pyx_v_x); - __pyx_t_6 = __Pyx_PyObject_Call(__pyx_builtin_max, __pyx_t_4, NULL); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_5 = __Pyx_GetItemInt_Tuple(__pyx_v_xyz, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(__pyx_t_5 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L3_error;}; + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_8 = PyTuple_New(1); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __Pyx_GOTREF(__pyx_t_8); + PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_5); + __Pyx_GIVEREF(__pyx_t_5); + __pyx_t_5 = 0; + __pyx_t_5 = __Pyx_PyObject_Call(__pyx_builtin_min, __pyx_t_8, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_8 = __Pyx_GetItemInt_Tuple(__pyx_v_xyz, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(__pyx_t_8 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L3_error;}; + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_6 = PyTuple_New(1); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L3_error;} __Pyx_GOTREF(__pyx_t_6); - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - __Pyx_GOTREF(__pyx_t_4); - __Pyx_INCREF(__pyx_v_y); - PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_y); - __Pyx_GIVEREF(__pyx_v_y); - __pyx_t_7 = __Pyx_PyObject_Call(__pyx_builtin_max, __pyx_t_4, NULL); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - __Pyx_GOTREF(__pyx_t_7); - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - __pyx_t_4 = PyTuple_New(4); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - __Pyx_GOTREF(__pyx_t_4); - PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_8); + PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_8); __Pyx_GIVEREF(__pyx_t_8); - PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_5); + __pyx_t_8 = 0; + __pyx_t_8 = __Pyx_PyObject_Call(__pyx_builtin_max, __pyx_t_6, NULL); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_6 = __Pyx_GetItemInt_Tuple(__pyx_v_xyz, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(__pyx_t_6 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L3_error;}; + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_7 = PyTuple_New(1); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __Pyx_GOTREF(__pyx_t_7); + PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_6); + __Pyx_GIVEREF(__pyx_t_6); + __pyx_t_6 = 0; + __pyx_t_6 = __Pyx_PyObject_Call(__pyx_builtin_max, __pyx_t_7, NULL); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_7 = PyTuple_New(4); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __Pyx_GOTREF(__pyx_t_7); + PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_4); + __Pyx_GIVEREF(__pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_7, 1, __pyx_t_5); __Pyx_GIVEREF(__pyx_t_5); - PyTuple_SET_ITEM(__pyx_t_4, 2, __pyx_t_6); + PyTuple_SET_ITEM(__pyx_t_7, 2, __pyx_t_8); + __Pyx_GIVEREF(__pyx_t_8); + PyTuple_SET_ITEM(__pyx_t_7, 3, __pyx_t_6); __Pyx_GIVEREF(__pyx_t_6); - PyTuple_SET_ITEM(__pyx_t_4, 3, __pyx_t_7); - __Pyx_GIVEREF(__pyx_t_7); - __pyx_t_8 = 0; + __pyx_t_4 = 0; __pyx_t_5 = 0; + __pyx_t_8 = 0; __pyx_t_6 = 0; + __pyx_r = __pyx_t_7; __pyx_t_7 = 0; - __pyx_r = __pyx_t_4; - __pyx_t_4 = 0; goto __pyx_L7_try_return; } __pyx_L3_error:; - __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; - __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; /* "fiona/ogrext.pyx":112 - * x, y = zip(*list(_explode(geometry['coordinates']))) - * return min(x), min(y), max(x), max(y) + * xyz = tuple(zip(*list(_explode(geometry['coordinates'])))) + * return min(xyz[0]), min(xyz[1]), max(xyz[0]), max(xyz[1]) * except (KeyError, TypeError): # <<<<<<<<<<<<<< * return None * */ - __pyx_t_10 = PyErr_ExceptionMatches(__pyx_builtin_KeyError) || PyErr_ExceptionMatches(__pyx_builtin_TypeError); - if (__pyx_t_10) { + __pyx_t_9 = PyErr_ExceptionMatches(__pyx_builtin_KeyError) || PyErr_ExceptionMatches(__pyx_builtin_TypeError); + if (__pyx_t_9) { __Pyx_AddTraceback("fiona.ogrext._bounds", __pyx_clineno, __pyx_lineno, __pyx_filename); - if (__Pyx_GetException(&__pyx_t_4, &__pyx_t_7, &__pyx_t_6) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L5_except_error;} - __Pyx_GOTREF(__pyx_t_4); + if (__Pyx_GetException(&__pyx_t_7, &__pyx_t_6, &__pyx_t_8) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L5_except_error;} __Pyx_GOTREF(__pyx_t_7); __Pyx_GOTREF(__pyx_t_6); + __Pyx_GOTREF(__pyx_t_8); /* "fiona/ogrext.pyx":113 - * return min(x), min(y), max(x), max(y) + * return min(xyz[0]), min(xyz[1]), max(xyz[0]), max(xyz[1]) * except (KeyError, TypeError): * return None # <<<<<<<<<<<<<< * @@ -2569,9 +2529,9 @@ static PyObject *__pyx_pf_5fiona_6ogrext_3_bounds(CYTHON_UNUSED PyObject *__pyx_ __Pyx_XDECREF(__pyx_r); __Pyx_INCREF(Py_None); __pyx_r = Py_None; - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; goto __pyx_L6_except_return; } goto __pyx_L5_except_error; @@ -2613,8 +2573,7 @@ static PyObject *__pyx_pf_5fiona_6ogrext_3_bounds(CYTHON_UNUSED PyObject *__pyx_ __Pyx_AddTraceback("fiona.ogrext._bounds", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; __pyx_L0:; - __Pyx_XDECREF(__pyx_v_x); - __Pyx_XDECREF(__pyx_v_y); + __Pyx_XDECREF(__pyx_v_xyz); __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; @@ -18700,8 +18659,7 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = { {&__pyx_n_s_warnings, __pyx_k_warnings, sizeof(__pyx_k_warnings), 0, 0, 1, 1}, {&__pyx_n_s_wktext, __pyx_k_wktext, sizeof(__pyx_k_wktext), 0, 0, 1, 1}, {&__pyx_n_s_writerecs_locals_validate_geomet, __pyx_k_writerecs_locals_validate_geomet, sizeof(__pyx_k_writerecs_locals_validate_geomet), 0, 0, 1, 1}, - {&__pyx_n_s_x, __pyx_k_x, sizeof(__pyx_k_x), 0, 0, 1, 1}, - {&__pyx_n_s_y, __pyx_k_y, sizeof(__pyx_k_y), 0, 0, 1, 1}, + {&__pyx_n_s_xyz, __pyx_k_xyz, sizeof(__pyx_k_xyz), 0, 0, 1, 1}, {&__pyx_n_s_year, __pyx_k_year, sizeof(__pyx_k_year), 0, 0, 1, 1}, {&__pyx_n_s_zip, __pyx_k_zip, sizeof(__pyx_k_zip), 0, 0, 1, 1}, {0, 0, 0, 0, 0, 0, 0} @@ -19478,10 +19436,10 @@ static int __Pyx_InitCachedConstants(void) { * """Bounding box of a GeoJSON geometry""" * try: */ - __pyx_tuple__80 = PyTuple_Pack(3, __pyx_n_s_geometry, __pyx_n_s_x, __pyx_n_s_y); if (unlikely(!__pyx_tuple__80)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_tuple__80 = PyTuple_Pack(2, __pyx_n_s_geometry, __pyx_n_s_xyz); if (unlikely(!__pyx_tuple__80)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_tuple__80); __Pyx_GIVEREF(__pyx_tuple__80); - __pyx_codeobj__81 = (PyObject*)__Pyx_PyCode_New(1, 0, 3, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__80, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_Users_sean_code_Fiona_fiona_ogr, __pyx_n_s_bounds, 107, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__81)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_codeobj__81 = (PyObject*)__Pyx_PyCode_New(1, 0, 2, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__80, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_Users_sean_code_Fiona_fiona_ogr, __pyx_n_s_bounds, 107, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__81)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;} /* "fiona/ogrext.pyx":115 * return None @@ -20839,60 +20797,82 @@ static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObjec } #endif -static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected) { - PyErr_Format(PyExc_ValueError, - "too many values to unpack (expected %" CYTHON_FORMAT_SSIZE_T "d)", expected); -} - -static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) { - PyErr_Format(PyExc_ValueError, - "need more than %" CYTHON_FORMAT_SSIZE_T "d value%.1s to unpack", - index, (index == 1) ? "" : "s"); +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) { + PyObject *r; + if (!j) return NULL; + r = PyObject_GetItem(o, j); + Py_DECREF(j); + return r; } - -static CYTHON_INLINE int __Pyx_IterFinish(void) { +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i, + int wraparound, int boundscheck) { #if CYTHON_COMPILING_IN_CPYTHON - PyThreadState *tstate = PyThreadState_GET(); - PyObject* exc_type = tstate->curexc_type; - if (unlikely(exc_type)) { - if (likely(exc_type == PyExc_StopIteration) || PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration)) { - PyObject *exc_value, *exc_tb; - exc_value = tstate->curexc_value; - exc_tb = tstate->curexc_traceback; - tstate->curexc_type = 0; - tstate->curexc_value = 0; - tstate->curexc_traceback = 0; - Py_DECREF(exc_type); - Py_XDECREF(exc_value); - Py_XDECREF(exc_tb); - return 0; - } else { - return -1; - } + if (wraparound & unlikely(i < 0)) i += PyList_GET_SIZE(o); + if ((!boundscheck) || likely((0 <= i) & (i < PyList_GET_SIZE(o)))) { + PyObject *r = PyList_GET_ITEM(o, i); + Py_INCREF(r); + return r; } - return 0; + return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i)); #else - if (unlikely(PyErr_Occurred())) { - if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) { - PyErr_Clear(); - return 0; - } else { - return -1; - } + return PySequence_GetItem(o, i); +#endif +} +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i, + int wraparound, int boundscheck) { +#if CYTHON_COMPILING_IN_CPYTHON + if (wraparound & unlikely(i < 0)) i += PyTuple_GET_SIZE(o); + if ((!boundscheck) || likely((0 <= i) & (i < PyTuple_GET_SIZE(o)))) { + PyObject *r = PyTuple_GET_ITEM(o, i); + Py_INCREF(r); + return r; } - return 0; + return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i)); +#else + return PySequence_GetItem(o, i); #endif } - -static int __Pyx_IternextUnpackEndCheck(PyObject *retval, Py_ssize_t expected) { - if (unlikely(retval)) { - Py_DECREF(retval); - __Pyx_RaiseTooManyValuesError(expected); - return -1; +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, + int is_list, int wraparound, int boundscheck) { +#if CYTHON_COMPILING_IN_CPYTHON + if (is_list || PyList_CheckExact(o)) { + Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyList_GET_SIZE(o); + if ((!boundscheck) || (likely((n >= 0) & (n < PyList_GET_SIZE(o))))) { + PyObject *r = PyList_GET_ITEM(o, n); + Py_INCREF(r); + return r; + } + } + else if (PyTuple_CheckExact(o)) { + Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyTuple_GET_SIZE(o); + if ((!boundscheck) || likely((n >= 0) & (n < PyTuple_GET_SIZE(o)))) { + PyObject *r = PyTuple_GET_ITEM(o, n); + Py_INCREF(r); + return r; + } } else { - return __Pyx_IterFinish(); + PySequenceMethods *m = Py_TYPE(o)->tp_as_sequence; + if (likely(m && m->sq_item)) { + if (wraparound && unlikely(i < 0) && likely(m->sq_length)) { + Py_ssize_t l = m->sq_length(o); + if (likely(l >= 0)) { + i += l; + } else { + if (PyErr_ExceptionMatches(PyExc_OverflowError)) + PyErr_Clear(); + else + return NULL; + } + } + return m->sq_item(o, i); + } } - return 0; +#else + if (is_list || PySequence_Check(o)) { + return PySequence_GetItem(o, i); + } +#endif + return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i)); } static CYTHON_INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb) { @@ -21204,93 +21184,71 @@ static CYTHON_INLINE PyObject* __Pyx_decode_c_string( } } -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) { - PyObject *r; - if (!j) return NULL; - r = PyObject_GetItem(o, j); - Py_DECREF(j); - return r; -} -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i, - int wraparound, int boundscheck) { -#if CYTHON_COMPILING_IN_CPYTHON - if (wraparound & unlikely(i < 0)) i += PyList_GET_SIZE(o); - if ((!boundscheck) || likely((0 <= i) & (i < PyList_GET_SIZE(o)))) { - PyObject *r = PyList_GET_ITEM(o, i); - Py_INCREF(r); - return r; +static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) { + if (unlikely(!type)) { + PyErr_SetString(PyExc_SystemError, "Missing type object"); + return 0; } - return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i)); -#else - return PySequence_GetItem(o, i); -#endif + if (likely(PyObject_TypeCheck(obj, type))) + return 1; + PyErr_Format(PyExc_TypeError, "Cannot convert %.200s to %.200s", + Py_TYPE(obj)->tp_name, type->tp_name); + return 0; } -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i, - int wraparound, int boundscheck) { -#if CYTHON_COMPILING_IN_CPYTHON - if (wraparound & unlikely(i < 0)) i += PyTuple_GET_SIZE(o); - if ((!boundscheck) || likely((0 <= i) & (i < PyTuple_GET_SIZE(o)))) { - PyObject *r = PyTuple_GET_ITEM(o, i); - Py_INCREF(r); - return r; - } - return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i)); -#else - return PySequence_GetItem(o, i); -#endif + +static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected) { + PyErr_Format(PyExc_ValueError, + "too many values to unpack (expected %" CYTHON_FORMAT_SSIZE_T "d)", expected); } -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, - int is_list, int wraparound, int boundscheck) { + +static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) { + PyErr_Format(PyExc_ValueError, + "need more than %" CYTHON_FORMAT_SSIZE_T "d value%.1s to unpack", + index, (index == 1) ? "" : "s"); +} + +static CYTHON_INLINE int __Pyx_IterFinish(void) { #if CYTHON_COMPILING_IN_CPYTHON - if (is_list || PyList_CheckExact(o)) { - Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyList_GET_SIZE(o); - if ((!boundscheck) || (likely((n >= 0) & (n < PyList_GET_SIZE(o))))) { - PyObject *r = PyList_GET_ITEM(o, n); - Py_INCREF(r); - return r; - } - } - else if (PyTuple_CheckExact(o)) { - Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyTuple_GET_SIZE(o); - if ((!boundscheck) || likely((n >= 0) & (n < PyTuple_GET_SIZE(o)))) { - PyObject *r = PyTuple_GET_ITEM(o, n); - Py_INCREF(r); - return r; - } - } else { - PySequenceMethods *m = Py_TYPE(o)->tp_as_sequence; - if (likely(m && m->sq_item)) { - if (wraparound && unlikely(i < 0) && likely(m->sq_length)) { - Py_ssize_t l = m->sq_length(o); - if (likely(l >= 0)) { - i += l; - } else { - if (PyErr_ExceptionMatches(PyExc_OverflowError)) - PyErr_Clear(); - else - return NULL; - } - } - return m->sq_item(o, i); + PyThreadState *tstate = PyThreadState_GET(); + PyObject* exc_type = tstate->curexc_type; + if (unlikely(exc_type)) { + if (likely(exc_type == PyExc_StopIteration) || PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration)) { + PyObject *exc_value, *exc_tb; + exc_value = tstate->curexc_value; + exc_tb = tstate->curexc_traceback; + tstate->curexc_type = 0; + tstate->curexc_value = 0; + tstate->curexc_traceback = 0; + Py_DECREF(exc_type); + Py_XDECREF(exc_value); + Py_XDECREF(exc_tb); + return 0; + } else { + return -1; } } + return 0; #else - if (is_list || PySequence_Check(o)) { - return PySequence_GetItem(o, i); + if (unlikely(PyErr_Occurred())) { + if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) { + PyErr_Clear(); + return 0; + } else { + return -1; + } } + return 0; #endif - return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i)); } -static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) { - if (unlikely(!type)) { - PyErr_SetString(PyExc_SystemError, "Missing type object"); - return 0; +static int __Pyx_IternextUnpackEndCheck(PyObject *retval, Py_ssize_t expected) { + if (unlikely(retval)) { + Py_DECREF(retval); + __Pyx_RaiseTooManyValuesError(expected); + return -1; + } else { + return __Pyx_IterFinish(); } - if (likely(PyObject_TypeCheck(obj, type))) - return 1; - PyErr_Format(PyExc_TypeError, "Cannot convert %.200s to %.200s", - Py_TYPE(obj)->tp_name, type->tp_name); return 0; } @@ -22511,6 +22469,32 @@ bad: return module; } +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) { + const long neg_one = (long) -1, const_zero = 0; + const int is_unsigned = neg_one > const_zero; + if (is_unsigned) { + if (sizeof(long) < sizeof(long)) { + return PyInt_FromLong((long) value); + } else if (sizeof(long) <= sizeof(unsigned long)) { + return PyLong_FromUnsignedLong((unsigned long) value); + } else if (sizeof(long) <= sizeof(unsigned long long)) { + return PyLong_FromUnsignedLongLong((unsigned long long) value); + } + } else { + if (sizeof(long) <= sizeof(long)) { + return PyInt_FromLong((long) value); + } else if (sizeof(long) <= sizeof(long long)) { + return PyLong_FromLongLong((long long) value); + } + } + { + int one = 1; int little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&value; + return _PyLong_FromByteArray(bytes, sizeof(long), + little, !is_unsigned); + } +} + static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value) { const int neg_one = (int) -1, const_zero = 0; const int is_unsigned = neg_one > const_zero; @@ -22653,32 +22637,6 @@ raise_neg_overflow: return (int) -1; } -static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) { - const long neg_one = (long) -1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; - if (is_unsigned) { - if (sizeof(long) < sizeof(long)) { - return PyInt_FromLong((long) value); - } else if (sizeof(long) <= sizeof(unsigned long)) { - return PyLong_FromUnsignedLong((unsigned long) value); - } else if (sizeof(long) <= sizeof(unsigned long long)) { - return PyLong_FromUnsignedLongLong((unsigned long long) value); - } - } else { - if (sizeof(long) <= sizeof(long)) { - return PyInt_FromLong((long) value); - } else if (sizeof(long) <= sizeof(long long)) { - return PyLong_FromLongLong((long long) value); - } - } - { - int one = 1; int little = (int)*(unsigned char *)&one; - unsigned char *bytes = (unsigned char *)&value; - return _PyLong_FromByteArray(bytes, sizeof(long), - little, !is_unsigned); - } -} - static CYTHON_INLINE PyObject* __Pyx_PyInt_From_unsigned_int(unsigned int value) { const unsigned int neg_one = (unsigned int) -1, const_zero = 0; const int is_unsigned = neg_one > const_zero; diff --git a/setup.cfg b/setup.cfg index b4e5efc..5c205e9 100644 --- a/setup.cfg +++ b/setup.cfg @@ -5,6 +5,6 @@ verbosity = 3 [egg_info] tag_build = -tag_date = 0 tag_svn_revision = 0 +tag_date = 0 diff --git a/tests/test_bounds.py b/tests/test_bounds.py index 9261c0d..420f5e2 100644 --- a/tests/test_bounds.py +++ b/tests/test_bounds.py @@ -13,3 +13,7 @@ def test_bounds(): 51.357216, 0.947778, 51.444717) + +def test_bounds_z(): + g = {'type': 'Point', 'coordinates': [10,10,10]} + assert fiona.bounds(g) == (10, 10, 10, 10) diff --git a/tests/test_fio_bounds.py b/tests/test_fio_bounds.py new file mode 100644 index 0000000..45a77a1 --- /dev/null +++ b/tests/test_fio_bounds.py @@ -0,0 +1,86 @@ +import json + +import click +from click.testing import CliRunner + +from fiona.fio import bounds + + +input = u'\x1e{"geometry": {"coordinates": [[[100094.81257811641, 6684726.008762141], [98548.69617048775, 6684924.5976624405], [87664.09899970173, 6686905.046363058], [86952.87877302397, 6687103.688267614], [85283.08641112497, 6688045.252446961], [84540.91936600611, 6688936.450241844], [82963.96745943041, 6691364.418923092], [82469.15232285221, 6692405.682380612], [81819.82573305666, 6693843.436658373], [82438.31682390235, 6697660.772804541], [83365.94214068248, 6700140.454427341], [8463 [...] + + + +def test_fail(): + runner = CliRunner() + result = runner.invoke(bounds.bounds, [], '5') + assert result.exit_code == 1 + + +def test_bounds(): + runner = CliRunner() + result = runner.invoke(bounds.bounds, [], input) + assert result.exit_code == 0 + assert len(json.loads(result.output.strip())) == 4 + assert round(json.loads(result.output.strip())[0], 1) == 81819.8 + + +def test_bounds_precision(): + runner = CliRunner() + result = runner.invoke(bounds.bounds, ['--precision', 1], input) + assert result.exit_code == 0 + assert len(json.loads(result.output.strip())) == 4 + assert json.loads(result.output.strip())[0] == 81819.8 + + +def test_bounds_explode(): + runner = CliRunner() + result = runner.invoke(bounds.bounds, ['--explode'], input) + assert result.exit_code == 0 + assert len(json.loads(result.output.strip())) == 4 + assert round(json.loads(result.output.strip())[0], 1) == 81819.8 + + +def test_bounds_with_id(): + runner = CliRunner() + result = runner.invoke(bounds.bounds, ['--with-id'], input) + assert result.exit_code == 0 + obj = json.loads(result.output.strip()) + assert 'id' in obj + assert 'bbox' in obj + assert len(obj['bbox']) == 4 + assert round(obj['bbox'][0], 1) == 81819.8 + + +def test_bounds_explode_with_id(): + runner = CliRunner() + result = runner.invoke(bounds.bounds, ['--explode', '--with-id'], input) + assert result.exit_code == 0 + obj = json.loads(result.output.strip()) + assert 'id' in obj + assert 'bbox' in obj + assert len(obj['bbox']) == 4 + assert round(obj['bbox'][0], 1) == 81819.8 + + +def test_bounds_with_obj(): + runner = CliRunner() + result = runner.invoke(bounds.bounds, ['--with-obj'], input) + assert result.exit_code == 0 + obj = json.loads(result.output.strip()) + assert 'geometry' in obj + assert 'id' in obj + assert 'bbox' in obj + assert len(obj['bbox']) == 4 + assert round(obj['bbox'][0], 1) == 81819.8 + + +def test_bounds_explode_with_obj(): + runner = CliRunner() + result = runner.invoke(bounds.bounds, ['--explode', '--with-obj'], input) + assert result.exit_code == 0 + obj = json.loads(result.output.strip()) + assert 'geometry' in obj + assert 'id' in obj + assert 'bbox' in obj + assert len(obj['bbox']) == 4 + assert round(obj['bbox'][0], 1) == 81819.8 diff --git a/tests/test_fio_cat.py b/tests/test_fio_cat.py new file mode 100644 index 0000000..e865a08 --- /dev/null +++ b/tests/test_fio_cat.py @@ -0,0 +1,105 @@ +import json + +import click +from click.testing import CliRunner + +from fiona.fio import cat + + +input = u'\x1e{"geometry": {"coordinates": [[[100094.81257811641, 6684726.008762141], [98548.69617048775, 6684924.5976624405], [87664.09899970173, 6686905.046363058], [86952.87877302397, 6687103.688267614], [85283.08641112497, 6688045.252446961], [84540.91936600611, 6688936.450241844], [82963.96745943041, 6691364.418923092], [82469.15232285221, 6692405.682380612], [81819.82573305666, 6693843.436658373], [82438.31682390235, 6697660.772804541], [83365.94214068248, 6700140.454427341], [8463 [...] + +input_collection = u'\x1e{"features": [{"geometry": {"coordinates": [[[100094.81257811641, 6684726.008762141], [98548.69617048775, 6684924.5976624405], [87664.09899970173, 6686905.046363058], [86952.87877302397, 6687103.688267614], [85283.08641112497, 6688045.252446961], [84540.91936600611, 6688936.450241844], [82963.96745943041, 6691364.418923092], [82469.15232285221, 6692405.682380612], [81819.82573305666, 6693843.436658373], [82438.31682390235, 6697660.772804541], [83365.94214068248, [...] + + +def test_cat(): + runner = CliRunner() + result = runner.invoke( + cat.cat, + ['docs/data/test_uk.shp'], + catch_exceptions=False) + assert result.exit_code == 0 + assert result.output.count('"Feature"') == 48 + + +def test_cat_bbox_no(): + runner = CliRunner() + result = runner.invoke( + cat.cat, + ['docs/data/test_uk.shp', '--bbox', '-90,10,-80,20'], + catch_exceptions=False) + assert result.exit_code == 0 + assert result.output == "" + + +def test_cat_bbox_yes(): + runner = CliRunner() + result = runner.invoke( + cat.cat, + ['docs/data/test_uk.shp', '--bbox', '-10,50,0,60'], + catch_exceptions=False) + assert result.exit_code == 0 + assert result.output.count('"Feature"') == 44 + + +def test_collect_rs(): + runner = CliRunner() + result = runner.invoke( + cat.collect, + ['--src_crs', 'EPSG:3857'], + input, + catch_exceptions=False) + assert result.exit_code == 0 + assert result.output == u'{"features": [{"geometry": {"coordinates": [[[0.8991670000000086, 51.357216], [0.8852780000000007, 51.358329999999995], [0.7874999999999889, 51.369438], [0.7811109999999931, 51.37055199999999], [0.766110999999994, 51.375831999999996], [0.7594439999999931, 51.380828999999984], [0.7452780000000093, 51.39443999999999], [0.7408329999999906, 51.40027599999999], [0.735000000000005, 51.408332999999985], [0.7405559999999894, 51.42971799999999], [0.7488889999999875, [...] + + +def test_collect_no_rs(): + runner = CliRunner() + result = runner.invoke( + cat.collect, + ['--src_crs', 'EPSG:3857'], + input, + catch_exceptions=False) + assert result.exit_code == 0 + assert result.output == u'{"features": [{"geometry": {"coordinates": [[[0.8991670000000086, 51.357216], [0.8852780000000007, 51.358329999999995], [0.7874999999999889, 51.369438], [0.7811109999999931, 51.37055199999999], [0.766110999999994, 51.375831999999996], [0.7594439999999931, 51.380828999999984], [0.7452780000000093, 51.39443999999999], [0.7408329999999906, 51.40027599999999], [0.735000000000005, 51.408332999999985], [0.7405559999999894, 51.42971799999999], [0.7488889999999875, [...] + + +def test_collect_ld(): + runner = CliRunner() + result = runner.invoke( + cat.collect, + ['--with-ld-context', '--add-ld-context-item', 'foo=bar'], + input, + catch_exceptions=False) + assert result.exit_code == 0 + assert '"@context": {' in result.output + assert '"foo": "bar"' in result.output + + +def test_collect_rec_buffered(): + runner = CliRunner() + result = runner.invoke(cat.collect, ['--record-buffered'], input) + assert result.exit_code == 0 + assert '"FeatureCollection"' in result.output + + +def test_distrib(): + runner = CliRunner() + result = runner.invoke(cat.distrib, [], input) + assert result.exit_code == 0 + assert json.loads(result.output.strip())['id'] == '0' + + + +def test_distrib(): + runner = CliRunner() + result = runner.invoke(cat.distrib, [], input_collection) + assert result.exit_code == 0 + assert json.loads(result.output.strip())['parent'] == 'collection:0' + assert json.loads(result.output.strip())['id'] == '0' + + +def test_dump(): + runner = CliRunner() + result = runner.invoke(cat.dump, ['docs/data/test_uk.shp']) + assert result.exit_code == 0 + assert '"FeatureCollection"' in result.output diff --git a/tests/test_geopackage.py b/tests/test_geopackage.py index 3cc599d..d990d34 100644 --- a/tests/test_geopackage.py +++ b/tests/test_geopackage.py @@ -1,15 +1,20 @@ import logging import os +import os.path import shutil import sys import tempfile import unittest +import pytest + import fiona from fiona.collection import supported_drivers from fiona.errors import FionaValueError, DriverError, SchemaError, CRSError from fiona.ogrext import calc_gdal_version_num, get_gdal_version_num + + logging.basicConfig(stream=sys.stderr, level=logging.DEBUG) @@ -21,6 +26,8 @@ class ReadingTest(unittest.TestCase): def tearDown(self): pass + @pytest.mark.skipif(not os.path.exists('docs/data/test_uk.gpkg'), + reason="Requires geopackage fixture") def test_gpkg(self): if get_gdal_version_num() < calc_gdal_version_num(1, 11, 0): self.assertRaises(DriverError, fiona.open, 'docs/data/test_uk.gpkg', 'r', driver="GPKG") @@ -37,6 +44,8 @@ class WritingTest(unittest.TestCase): def tearDown(self): shutil.rmtree(self.tempdir) + @pytest.mark.skipif(not os.path.exists('docs/data/test_uk.gpkg'), + reason="Requires geopackage fixture") def test_gpkg(self): schema = {'geometry': 'Point', 'properties': [('title', 'str')]} diff --git a/tests/test_schema.py b/tests/test_schema.py index 092c3e7..d922601 100644 --- a/tests/test_schema.py +++ b/tests/test_schema.py @@ -124,3 +124,23 @@ class ShapefileSchema(unittest.TestCase): f = next(c) self.assertEqual(f['properties']['EstimatedP'], 27773.0) +def test_issue177(tmpdir): + name = str(tmpdir.join("output.shp")) + + kwargs = { + 'driver': 'ESRI Shapefile', + 'crs': 'EPSG:4326', + 'schema': { + 'geometry': 'Point', + 'properties': [('a_fieldname', 'float')]}} + + with fiona.open(name, 'w', **kwargs) as dst: + rec = {} + rec['geometry'] = {'type': 'Point', 'coordinates': (0, 0)} + rec['properties'] = {'a_fieldname': 3.0} + dst.write(rec) + + with fiona.open(name) as src: + first = next(src) + assert first['geometry'] == {'type': 'Point', 'coordinates': (0, 0)} + assert first['properties']['a_fieldnam'] == 3.0 -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/fiona.git _______________________________________________ Pkg-grass-devel mailing list Pkg-grass-devel@lists.alioth.debian.org http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-grass-devel