pax_global_header00006660000000000000000000000064133527262770014530gustar00rootroot0000000000000052 comment=68ebfec504cab226735429e99d7f9a38d6ee9aae cligj-0.5.0/000077500000000000000000000000001335272627700126225ustar00rootroot00000000000000cligj-0.5.0/.gitignore000077500000000000000000000012771335272627700146240ustar00rootroot00000000000000# Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] # C extensions *.so # Distribution / packaging .Python env/ venv/ build/ develop-eggs/ dist/ downloads/ eggs/ lib/ lib64/ parts/ sdist/ var/ *.egg-info/ .installed.cfg *.egg # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .coverage .cache nosetests.xml coverage.xml # Translations *.mo *.pot # Django stuff: *.log # Sphinx documentation docs/_build/ # PyBuilder target/ # PyCharm IDE .idea/ cligj-0.5.0/.travis.yml000077500000000000000000000005131335272627700147350ustar00rootroot00000000000000sudo: false language: python python: - "2.7" - "3.3" - "3.4" - "3.5" install: - "pip install coveralls" - "pip install -e .[test]" script: - py.test --cov cligj --cov-report term-missing after_success: - coveralls deploy: on: tags: true provider: pypi distributions: "sdist bdist_wheel" user: mapboxci cligj-0.5.0/CHANGES.txt000066400000000000000000000021611335272627700144330ustar00rootroot00000000000000Changes ======= 0.5.0 (2018-09-26) ------------------ - Version 0.4.0 is not compatible with click 7, but version 0.5.0 is (#23). - The features_in_arg handler now takes sequences of geometry objects (#14). - The iter_features function has a new per-feature callback and is ready for use in other projects like Fiona (#15). - The plugins module has been removed (#17). 0.4.0 (2015-12-17) ------------------ - Introduces a click argument, `features_in_arg`, which utilizes a click callback to normalize the input of geojson features (#9). - Release from tagged Travis CI builds (#10). 0.3.0 (2015-08-12) ------------------ - Deprecation of the cligj.plugins module (#6). Please switch to the click-plugins module: https://github.com/click-contrib/click-plugins. The cligj.plugins module will be removed from cligj at version 1.0. 0.2.0 (2015-05-28) ------------------ - Addition of a pluggable command group class and a corresponding click-style decorator (#2, #3). 0.1.0 (2015-01-06) ------------------ - Initial release: a collection of GeoJSON-related command line arguments and options for use with Click (#1). cligj-0.5.0/LICENSE000077500000000000000000000026751335272627700136440ustar00rootroot00000000000000Copyright (c) 2014, Mapbox All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of cligj nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. cligj-0.5.0/README.rst000077500000000000000000000105731335272627700143220ustar00rootroot00000000000000cligj ====== .. image:: https://travis-ci.org/mapbox/cligj.svg :target: https://travis-ci.org/mapbox/cligj .. image:: https://coveralls.io/repos/mapbox/cligj/badge.png?branch=master :target: https://coveralls.io/r/mapbox/cligj?branch=master Common arguments and options for GeoJSON processing commands, using Click. `cligj` is for Python developers who create command line interfaces for geospatial data. `cligj` allows you to quickly build consistent, well-tested and interoperable CLIs for handling GeoJSON. Arguments --------- ``files_in_arg`` Multiple files ``files_inout_arg`` Multiple files, last of which is an output file. ``features_in_arg`` GeoJSON Features input which accepts multiple representations of GeoJSON features and returns the input data as an iterable of GeoJSON Feature-like dictionaries Options -------- ``verbose_opt`` ``quiet_opt`` ``format_opt`` JSON formatting options ~~~~~~~~~~~~~~~~~~~~~~~ ``indent_opt`` ``compact_opt`` Coordinate precision option ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``precision_opt`` Geographic (default), projected, or Mercator switch ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``projection_geographic_opt`` ``projection_projected_opt`` ``projection_mercator_opt`` Feature collection or feature sequence switch ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``sequence_opt`` ``use_rs_opt`` GeoJSON output mode option ~~~~~~~~~~~~~~~~~~~~~~~~~~ ``geojson_type_collection_opt`` ``geojson_type_feature_opt`` ``def geojson_type_bbox_opt`` Example ------- Here's an example of a command that writes out GeoJSON features as a collection or, optionally, a sequence of individual features. Since most software that reads and writes GeoJSON expects a text containing a single feature collection, that's the default, and a LF-delimited sequence of texts containing one GeoJSON feature each is a feature that is turned on using the ``--sequence`` option. To write sequences of feature texts that conform to the `JSON Text Sequences proposed standard `__ (and might contain pretty-printed JSON) with the ASCII Record Separator (0x1e) as a delimiter, use the ``--rs`` option .. code-block:: python import click import cligj import json def process_features(features): for feature in features: # TODO process feature here yield feature @click.command() @cligj.features_in_arg @cligj.sequence_opt @cligj.use_rs_opt def pass_features(features, sequence, use_rs): if sequence: for feature in process_features(features): if use_rs: click.echo(u'\x1e', nl=False) click.echo(json.dumps(feature)) else: click.echo(json.dumps( {'type': 'FeatureCollection', 'features': list(process_features(features))})) On the command line, the generated help text explains the usage .. code-block:: console Usage: pass_features [OPTIONS] FEATURES... Options: --sequence / --no-sequence Write a LF-delimited sequence of texts containing individual objects or write a single JSON text containing a feature collection object (the default). --rs / --no-rs Use RS (0x1E) as a prefix for individual texts in a sequence as per http://tools.ietf.org/html /draft-ietf-json-text-sequence-13 (default is False). --help Show this message and exit. And can be used like this .. code-block:: console $ cat data.geojson {'type': 'FeatureCollection', 'features': [{'type': 'Feature', 'id': '1'}, {'type': 'Feature', 'id': '2'}]} $ pass_features data.geojson {'type': 'FeatureCollection', 'features': [{'type': 'Feature', 'id': '1'}, {'type': 'Feature', 'id': '2'}]} $ cat data.geojson | pass_features {'type': 'FeatureCollection', 'features': [{'type': 'Feature', 'id': '1'}, {'type': 'Feature', 'id': '2'}]} $ cat data.geojson | pass_features --sequence {'type': 'Feature', 'id': '1'} {'type': 'Feature', 'id': '2'} $ cat data.geojson | pass_features --sequence --rs ^^{'type': 'Feature', 'id': '1'} ^^{'type': 'Feature', 'id': '2'} In this example, ``^^`` represents 0x1e. cligj-0.5.0/cligj/000077500000000000000000000000001335272627700137125ustar00rootroot00000000000000cligj-0.5.0/cligj/__init__.py000077500000000000000000000065011335272627700160300ustar00rootroot00000000000000# cligj # Shared arguments and options. import click from .features import normalize_feature_inputs # Arguments. # Multiple input files. files_in_arg = click.argument( 'files', nargs=-1, type=click.Path(resolve_path=True), required=True, metavar="INPUTS...") # Multiple files, last of which is an output file. files_inout_arg = click.argument( 'files', nargs=-1, type=click.Path(resolve_path=True), required=True, metavar="INPUTS... OUTPUT") # Features from files, command line args, or stdin. # Returns the input data as an iterable of GeoJSON Feature-like # dictionaries. features_in_arg = click.argument( 'features', nargs=-1, callback=normalize_feature_inputs, metavar="FEATURES...") # Options. verbose_opt = click.option( '--verbose', '-v', count=True, help="Increase verbosity.") quiet_opt = click.option( '--quiet', '-q', count=True, help="Decrease verbosity.") # Format driver option. format_opt = click.option( '-f', '--format', '--driver', 'driver', default='GTiff', help="Output format driver") # JSON formatting options. indent_opt = click.option( '--indent', type=int, default=None, help="Indentation level for JSON output") compact_opt = click.option( '--compact/--not-compact', default=False, help="Use compact separators (',', ':').") # Coordinate precision option. precision_opt = click.option( '--precision', type=int, default=-1, help="Decimal precision of coordinates.") # Geographic (default), projected, or Mercator switch. projection_geographic_opt = click.option( '--geographic', 'projection', flag_value='geographic', default=True, help="Output in geographic coordinates (the default).") projection_projected_opt = click.option( '--projected', 'projection', flag_value='projected', help="Output in dataset's own, projected coordinates.") projection_mercator_opt = click.option( '--mercator', 'projection', flag_value='mercator', help="Output in Web Mercator coordinates.") # Feature collection or feature sequence switch. sequence_opt = click.option( '--sequence/--no-sequence', default=False, help="Write a LF-delimited sequence of texts containing individual " "objects or write a single JSON text containing a feature " "collection object (the default).") use_rs_opt = click.option( '--rs/--no-rs', 'use_rs', default=False, help="Use RS (0x1E) as a prefix for individual texts in a sequence " "as per http://tools.ietf.org/html/draft-ietf-json-text-sequence-13 " "(default is False).") # GeoJSON output mode option. def geojson_type_collection_opt(default=False): return click.option( '--collection', 'geojson_type', flag_value='collection', default=default, help="Output as GeoJSON feature collection(s).") def geojson_type_feature_opt(default=False): return click.option( '--feature', 'geojson_type', flag_value='feature', default=default, help="Output as GeoJSON feature(s).") def geojson_type_bbox_opt(default=False): return click.option( '--bbox', 'geojson_type', flag_value='bbox', default=default, help="Output as GeoJSON bounding box array(s).") cligj-0.5.0/cligj/features.py000066400000000000000000000146331335272627700161110ustar00rootroot00000000000000from itertools import chain import json import re import click def normalize_feature_inputs(ctx, param, value): """Click callback that normalizes feature input values. Returns a generator over features from the input value. Parameters ---------- ctx: a Click context param: the name of the argument or option value: object The value argument may be one of the following: 1. A list of paths to files containing GeoJSON feature collections or feature sequences. 2. A list of string-encoded coordinate pairs of the form "[lng, lat]", or "lng, lat", or "lng lat". If no value is provided, features will be read from stdin. """ for feature_like in value or ('-',): try: with click.open_file(feature_like) as src: for feature in iter_features(iter(src)): yield feature except IOError: coords = list(coords_from_query(feature_like)) yield { 'type': 'Feature', 'properties': {}, 'geometry': { 'type': 'Point', 'coordinates': coords}} def iter_features(geojsonfile, func=None): """Extract GeoJSON features from a text file object. Given a file-like object containing a single GeoJSON feature collection text or a sequence of GeoJSON features, iter_features() iterates over lines of the file and yields GeoJSON features. Parameters ---------- geojsonfile: a file-like object The geojsonfile implements the iterator protocol and yields lines of JSON text. func: function, optional A function that will be applied to each extracted feature. It takes a feature object and may return a replacement feature or None -- in which case iter_features does not yield. """ func = func or (lambda x: x) first_line = next(geojsonfile) # Does the geojsonfile contain RS-delimited JSON sequences? if first_line.startswith(u'\x1e'): text_buffer = first_line.strip(u'\x1e') for line in geojsonfile: if line.startswith(u'\x1e'): if text_buffer: obj = json.loads(text_buffer) if 'coordinates' in obj: obj = to_feature(obj) newfeat = func(obj) if newfeat: yield newfeat text_buffer = line.strip(u'\x1e') else: text_buffer += line # complete our parsing with a for-else clause. else: obj = json.loads(text_buffer) if 'coordinates' in obj: obj = to_feature(obj) newfeat = func(obj) if newfeat: yield newfeat # If not, it may contains LF-delimited GeoJSON objects or a single # multi-line pretty-printed GeoJSON object. else: # Try to parse LF-delimited sequences of features or feature # collections produced by, e.g., `jq -c ...`. try: obj = json.loads(first_line) if obj['type'] == 'Feature': newfeat = func(obj) if newfeat: yield newfeat for line in geojsonfile: newfeat = func(json.loads(line)) if newfeat: yield newfeat elif obj['type'] == 'FeatureCollection': for feat in obj['features']: newfeat = func(feat) if newfeat: yield newfeat elif 'coordinates' in obj: newfeat = func(to_feature(obj)) if newfeat: yield newfeat for line in geojsonfile: newfeat = func(to_feature(json.loads(line))) if newfeat: yield newfeat # Indented or pretty-printed GeoJSON features or feature # collections will fail out of the try clause above since # they'll have no complete JSON object on their first line. # To handle these, we slurp in the entire file and parse its # text. except ValueError: text = "".join(chain([first_line], geojsonfile)) obj = json.loads(text) if obj['type'] == 'Feature': newfeat = func(obj) if newfeat: yield newfeat elif obj['type'] == 'FeatureCollection': for feat in obj['features']: newfeat = func(feat) if newfeat: yield newfeat elif 'coordinates' in obj: newfeat = func(to_feature(obj)) if newfeat: yield newfeat def to_feature(obj): """Takes a feature or a geometry returns feature verbatim or wraps geom in a feature with empty properties """ if obj['type'] == 'Feature': return obj elif 'coordinates' in obj: return { 'type': 'Feature', 'properties': {}, 'geometry': obj} else: raise ValueError("Object is not a feature or geometry") def iter_query(query): """Accept a filename, stream, or string. Returns an iterator over lines of the query.""" try: itr = click.open_file(query).readlines() except IOError: itr = [query] return itr def coords_from_query(query): """Transform a query line into a (lng, lat) pair of coordinates.""" try: coords = json.loads(query) except ValueError: query = query.replace(',', ' ') vals = query.split() coords = [float(v) for v in vals] return tuple(coords[:2]) def normalize_feature_objects(feature_objs): """Takes an iterable of GeoJSON-like Feature mappings or an iterable of objects with a geo interface and normalizes it to the former.""" for obj in feature_objs: if hasattr(obj, "__geo_interface__") and \ 'type' in obj.__geo_interface__.keys() and \ obj.__geo_interface__['type'] == 'Feature': yield obj.__geo_interface__ elif isinstance(obj, dict) and 'type' in obj and \ obj['type'] == 'Feature': yield obj else: raise ValueError("Did not recognize object {0}" "as GeoJSON Feature".format(obj)) cligj-0.5.0/setup.py000077500000000000000000000014601335272627700143400ustar00rootroot00000000000000from codecs import open as codecs_open from setuptools import setup, find_packages # Get the long description from the relevant file with codecs_open('README.rst', encoding='utf-8') as f: long_description = f.read() setup(name='cligj', version='0.5.0', description=u"Click params for commmand line interfaces to GeoJSON", long_description=long_description, classifiers=[], keywords='', author=u"Sean Gillies", author_email='sean@mapbox.com', url='https://github.com/mapbox/cligj', license='BSD', packages=find_packages(exclude=['ez_setup', 'examples', 'tests']), include_package_data=True, zip_safe=False, install_requires=[ 'click >= 4.0, < 8' ], extras_require={ 'test': ['pytest-cov'], }) cligj-0.5.0/tests/000077500000000000000000000000001335272627700137645ustar00rootroot00000000000000cligj-0.5.0/tests/conftest.py000066400000000000000000000002031335272627700161560ustar00rootroot00000000000000from click.testing import CliRunner import pytest @pytest.fixture(scope='function') def runner(request): return CliRunner() cligj-0.5.0/tests/onepoint.geojson000066400000000000000000000001651335272627700172070ustar00rootroot00000000000000{"geometry": {"coordinates": [-122.7282, 45.5801], "type": "Point"}, "id": "0", "properties": {}, "type": "Feature"} cligj-0.5.0/tests/point_pretty_geom.txt000066400000000000000000000000771335272627700203000ustar00rootroot00000000000000{ "coordinates": [-122.7282, 45.5801], "type": "Point" } cligj-0.5.0/tests/test_cli.py000077500000000000000000000131221335272627700161460ustar00rootroot00000000000000import os import os.path import click import cligj def test_files_in(runner): @click.command() @cligj.files_in_arg def cmd(files): for f in files: click.echo(f) result = runner.invoke(cmd, ['1.tif', '2.tif']) assert not result.exception assert result.output.splitlines() == [ os.path.join(os.getcwd(), '1.tif'), os.path.join(os.getcwd(), '2.tif'), ] def test_files_inout(runner): @click.command() @cligj.files_inout_arg def cmd(files): for f in files: click.echo(f) result = runner.invoke(cmd, ['1.tif', '2.tif']) assert not result.exception assert result.output.splitlines() == [ os.path.join(os.getcwd(), '1.tif'), os.path.join(os.getcwd(), '2.tif'), ] def test_verbose(runner): @click.command() @cligj.verbose_opt def cmd(verbose): click.echo("%s" % verbose) result = runner.invoke(cmd, ['-vv']) assert not result.exception assert result.output.splitlines() == ['2'] def test_quiet(runner): @click.command() @cligj.quiet_opt def cmd(quiet): click.echo("%s" % quiet) result = runner.invoke(cmd, ['-qq']) assert not result.exception assert result.output.splitlines() == ['2'] def test_format(runner): @click.command() @cligj.format_opt def cmd(driver): click.echo("%s" % driver) result = runner.invoke(cmd, ['--driver', 'lol']) assert not result.exception assert result.output.splitlines() == ['lol'] result = runner.invoke(cmd, ['--format', 'lol']) assert not result.exception assert result.output.splitlines() == ['lol'] result = runner.invoke(cmd, ['-f', 'lol']) assert not result.exception assert result.output.splitlines() == ['lol'] result = runner.invoke(cmd) assert not result.exception assert result.output.splitlines() == ['GTiff'] def test_indent(runner): @click.command() @cligj.indent_opt def cmd(indent): click.echo("%s" % indent) result = runner.invoke(cmd, ['--indent', '2']) assert not result.exception assert result.output.splitlines() == ['2'] result = runner.invoke(cmd) assert not result.exception assert result.output.splitlines() == ['None'] def test_compact(runner): @click.command() @cligj.compact_opt def cmd(compact): click.echo("%s" % compact) result = runner.invoke(cmd, ['--compact']) assert not result.exception assert result.output.splitlines() == ['True'] result = runner.invoke(cmd, ['--not-compact']) assert not result.exception assert result.output.splitlines() == ['False'] result = runner.invoke(cmd) assert not result.exception assert result.output.splitlines() == ['False'] def test_precision(runner): @click.command() @cligj.precision_opt def cmd(precision): click.echo("%s" % precision) result = runner.invoke(cmd, ['--precision', '2']) assert not result.exception assert result.output.splitlines() == ['2'] result = runner.invoke(cmd) assert not result.exception assert result.output.splitlines() == ['-1'] def test_projection(runner): @click.command() @cligj.projection_geographic_opt @cligj.projection_projected_opt @cligj.projection_mercator_opt def cmd(projection): click.echo("%s" % projection) result = runner.invoke(cmd, ['--geographic']) assert not result.exception assert result.output.splitlines() == ['geographic'] result = runner.invoke(cmd, ['--projected']) assert not result.exception assert result.output.splitlines() == ['projected'] result = runner.invoke(cmd, ['--mercator']) assert not result.exception assert result.output.splitlines() == ['mercator'] result = runner.invoke(cmd) assert not result.exception assert result.output.splitlines() == ['geographic'] def test_sequence(runner): @click.command() @cligj.sequence_opt def cmd(sequence): click.echo("%s" % sequence) result = runner.invoke(cmd) assert not result.exception assert result.output.splitlines() == ['False'] result = runner.invoke(cmd, ['--sequence']) assert not result.exception assert result.output.splitlines() == ['True'] result = runner.invoke(cmd, ['--no-sequence']) assert not result.exception assert result.output.splitlines() == ['False'] def test_sequence_rs(runner): @click.command() @cligj.sequence_opt @cligj.use_rs_opt def cmd(sequence, use_rs): click.echo("%s" % sequence) click.echo("%s" % use_rs) result = runner.invoke(cmd, ['--sequence', '--rs']) assert not result.exception assert result.output.splitlines() == ['True', 'True'] result = runner.invoke(cmd, ['--sequence']) assert not result.exception assert result.output.splitlines() == ['True', 'False'] def test_geojson_type(runner): @click.command() @cligj.geojson_type_collection_opt(True) @cligj.geojson_type_feature_opt(False) @cligj.geojson_type_bbox_opt(False) def cmd(geojson_type): click.echo("%s" % geojson_type) result = runner.invoke(cmd) assert not result.exception assert result.output.splitlines() == ['collection'] result = runner.invoke(cmd, ['--collection']) assert not result.exception assert result.output.splitlines() == ['collection'] result = runner.invoke(cmd, ['--feature']) assert not result.exception assert result.output.splitlines() == ['feature'] result = runner.invoke(cmd, ['--bbox']) assert not result.exception assert result.output.splitlines() == ['bbox'] cligj-0.5.0/tests/test_features.py000066400000000000000000000120031335272627700172070ustar00rootroot00000000000000import json import sys import pytest from cligj.features import \ coords_from_query, iter_query, to_feature, \ normalize_feature_inputs, normalize_feature_objects def test_iter_query_string(): assert iter_query("lolwut") == ["lolwut"] def test_iter_query_file(tmpdir): filename = str(tmpdir.join('test.txt')) with open(filename, 'w') as f: f.write("lolwut") assert iter_query(filename) == ["lolwut"] def test_coords_from_query_json(): assert coords_from_query("[-100, 40]") == (-100, 40) def test_coords_from_query_csv(): assert coords_from_query("-100, 40") == (-100, 40) def test_coords_from_query_ws(): assert coords_from_query("-100 40") == (-100, 40) @pytest.fixture def expected_features(): with open("tests/twopoints.geojson") as src: fc = json.loads(src.read()) return fc['features'] def _geoms(features): geoms = [] for feature in features: geoms.append(feature['geometry']) return geoms def test_featurecollection_file(expected_features): features = normalize_feature_inputs( None, 'features', ["tests/twopoints.geojson"]) assert _geoms(features) == _geoms(expected_features) def test_featurecollection_pretty_file(expected_features): features = normalize_feature_inputs( None, 'features', ["tests/twopoints-pretty.json"]) assert _geoms(features) == _geoms(expected_features) def test_featurecollection_stdin(expected_features): sys.stdin = open("tests/twopoints.geojson", 'r') features = normalize_feature_inputs(None, 'features', []) assert _geoms(features) == _geoms(expected_features) def test_featuresequence(expected_features): features = normalize_feature_inputs( None, 'features', ["tests/twopoints_seq.txt"]) assert _geoms(features) == _geoms(expected_features) # TODO test path to sequence files fail def test_featuresequence_stdin(expected_features): sys.stdin = open("tests/twopoints_seq.txt", 'r') features = normalize_feature_inputs(None, 'features', []) assert _geoms(features) == _geoms(expected_features) def test_singlefeature(expected_features): features = normalize_feature_inputs( None, 'features', ["tests/onepoint.geojson"]) assert _geoms(features) == _geoms([expected_features[0]]) def test_singlefeature_stdin(expected_features): sys.stdin = open("tests/onepoint.geojson", 'r') features = normalize_feature_inputs(None, 'features', []) assert _geoms(features) == _geoms([expected_features[0]]) def test_featuresequencers(expected_features): features = normalize_feature_inputs( None, 'features', ["tests/twopoints_seqrs.txt"]) assert _geoms(features) == _geoms(expected_features) def test_featuresequencers_stdin(expected_features): sys.stdin = open("tests/twopoints_seqrs.txt", 'r') features = normalize_feature_inputs(None, 'features', []) assert _geoms(features) == _geoms(expected_features) def test_coordarrays(expected_features): inputs = ["[-122.7282, 45.5801]", "[-121.3153, 44.0582]"] features = normalize_feature_inputs(None, 'features', inputs) assert _geoms(features) == _geoms(expected_features) def test_coordpairs_comma(expected_features): inputs = ["-122.7282, 45.5801", "-121.3153, 44.0582"] features = normalize_feature_inputs(None, 'features', inputs) assert _geoms(features) == _geoms(expected_features) def test_coordpairs_space(expected_features): inputs = ["-122.7282 45.5801", "-121.3153 44.0582"] features = normalize_feature_inputs(None, 'features', inputs) assert _geoms(features) == _geoms(expected_features) def test_geometrysequence(expected_features): features = normalize_feature_inputs(None, 'features', ["tests/twopoints_geom_seq.txt"]) assert _geoms(features) == _geoms(expected_features) def test_geometrysequencers(expected_features): features = normalize_feature_inputs(None, 'features', ["tests/twopoints_geom_seqrs.txt"]) assert _geoms(features) == _geoms(expected_features) def test_geometrypretty(expected_features): features = normalize_feature_inputs(None, 'features', ["tests/point_pretty_geom.txt"]) assert _geoms(features)[0] == _geoms(expected_features)[0] class MockGeo(object): def __init__(self, feature): self.__geo_interface__ = feature def test_normalize_feature_objects(expected_features): objs = [MockGeo(f) for f in expected_features] assert expected_features == list(normalize_feature_objects(objs)) assert expected_features == list(normalize_feature_objects(expected_features)) def test_normalize_feature_objects_bad(expected_features): objs = [MockGeo(f) for f in expected_features] objs.append(MockGeo(dict())) with pytest.raises(ValueError): list(normalize_feature_objects(objs)) def test_to_feature(expected_features): geom = expected_features[0]['geometry'] feat = {'type': 'Feature', 'properties': {}, 'geometry': geom} assert to_feature(feat) == to_feature(geom) with pytest.raises(ValueError): assert to_feature({'type': 'foo'}) cligj-0.5.0/tests/twopoints-pretty.json000066400000000000000000000044421335272627700202560ustar00rootroot00000000000000{ "features": [ { "bbox": [ -122.9292140099711, 45.37948199034149, -122.44106199104115, 45.858097009742835 ], "center": [ -122.7282, 45.5801 ], "context": [ { "id": "postcode.2503633822", "text": "97203" }, { "id": "region.3470299826", "text": "Oregon" }, { "id": "country.4150104525", "short_code": "us", "text": "United States" } ], "geometry": { "coordinates": [ -122.7282, 45.5801 ], "type": "Point" }, "id": "place.42767", "place_name": "Portland, Oregon, United States", "properties": {}, "relevance": 0.999, "text": "Portland", "type": "Feature" }, { "bbox": [ -121.9779540096568, 43.74737999114854, -120.74788099000016, 44.32812500969035 ], "center": [ -121.3153, 44.0582 ], "context": [ { "id": "postcode.3332732485", "text": "97701" }, { "id": "region.3470299826", "text": "Oregon" }, { "id": "country.4150104525", "short_code": "us", "text": "United States" } ], "geometry": { "coordinates": [ -121.3153, 44.0582 ], "type": "Point" }, "id": "place.3965", "place_name": "Bend, Oregon, United States", "properties": {}, "relevance": 0.999, "text": "Bend", "type": "Feature" } ], "type": "FeatureCollection" } cligj-0.5.0/tests/twopoints.geojson000066400000000000000000000020661335272627700174240ustar00rootroot00000000000000{"features": [{"bbox": [-122.9292140099711, 45.37948199034149, -122.44106199104115, 45.858097009742835], "center": [-122.7282, 45.5801], "context": [{"id": "postcode.2503633822", "text": "97203"}, {"id": "region.3470299826", "text": "Oregon"}, {"id": "country.4150104525", "short_code": "us", "text": "United States"}], "geometry": {"coordinates": [-122.7282, 45.5801], "type": "Point"}, "id": "place.42767", "place_name": "Portland, Oregon, United States", "properties": {}, "relevance": 0.999, "text": "Portland", "type": "Feature"}, {"bbox": [-121.9779540096568, 43.74737999114854, -120.74788099000016, 44.32812500969035], "center": [-121.3153, 44.0582], "context": [{"id": "postcode.3332732485", "text": "97701"}, {"id": "region.3470299826", "text": "Oregon"}, {"id": "country.4150104525", "short_code": "us", "text": "United States"}], "geometry": {"coordinates": [-121.3153, 44.0582], "type": "Point"}, "id": "place.3965", "place_name": "Bend, Oregon, United States", "properties": {}, "relevance": 0.999, "text": "Bend", "type": "Feature"}], "type": "FeatureCollection"} cligj-0.5.0/tests/twopoints_geom_seq.txt000066400000000000000000000001561335272627700204540ustar00rootroot00000000000000{"coordinates": [-122.7282, 45.5801], "type": "Point"} {"coordinates": [-121.3153, 44.0582], "type": "Point"} cligj-0.5.0/tests/twopoints_geom_seqrs.txt000066400000000000000000000002041335272627700210130ustar00rootroot00000000000000{ "coordinates": [-122.7282, 45.5801], "type": "Point" } { "coordinates": [-121.3153, 44.0582], "type": "Point" } cligj-0.5.0/tests/twopoints_seq.txt000066400000000000000000000003521335272627700174430ustar00rootroot00000000000000{"geometry": {"coordinates": [-122.7282, 45.5801], "type": "Point"}, "id": "0", "properties": {}, "type": "Feature"} {"geometry": {"coordinates": [-121.3153, 44.0582], "type": "Point"}, "id": "1", "properties": {}, "type": "Feature"} cligj-0.5.0/tests/twopoints_seqrs.txt000066400000000000000000000003761335272627700200160ustar00rootroot00000000000000{"geometry": {"coordinates": [-122.7282, 45.5801], "type": "Point"}, "id": "0", "properties": {}, "type": "Feature"} {"geometry": { "coordinates": [-121.3153, 44.0582], "type": "Point"}, "id": "1", "properties": {}, "type": "Feature"}