예제 #1
0
def test_write_read_geojson_with_props(gjson, props):
    byte_stream = io.BytesIO()
    writer = geostream.writer(byte_stream, props)
    writer.write_feature(gjson)
    byte_stream.seek(0)
    header1, header2, prop_len = struct.unpack(
        'Bii', byte_stream.read(struct.calcsize('Bii')))
    assert header1 in GEOSTREAM_SCHEMA_VERSIONS
    assert header2 == GEOJSON_EPSG_SRID
    assert prop_len > 0
    p = byte_stream.read(prop_len)
    header_props = cbor2.loads(p)
    assert header_props["unit"] == "something"
    length = struct.unpack('i', byte_stream.read(struct.calcsize('i')))[0]
    zipped_data = byte_stream.read(length)
    trailing_length = struct.unpack('i',
                                    byte_stream.read(struct.calcsize('i')))[0]
    assert len(zipped_data) == length
    assert length == trailing_length
    byte_stream.seek(0)
    reader = geostream.reader(byte_stream)
    assert reader.srid == GEOJSON_EPSG_SRID
    assert reader.schema_version in GEOSTREAM_SCHEMA_VERSIONS
    assert reader.properties == props
    read_features = [f for f in reader]
    assert len(read_features) == 1
    assert gjson == read_features[0]
    byte_stream.seek(0)
    rev_reader = geostream.reader(byte_stream, reverse=True)
    assert rev_reader.srid == GEOJSON_EPSG_SRID
    assert rev_reader.schema_version in GEOSTREAM_SCHEMA_VERSIONS
    assert rev_reader.properties == props
    rev_features = [f for f in rev_reader]
    assert len(rev_features) == 1
    assert gjson == read_features[0]
예제 #2
0
def test_read_invalid_schema_from_stream_raises_exception(feat_collection_2):
    with pytest.raises(ValueError):
        collection = feat_collection_2
        collection_props = {"unit": "something", "key": "uuid"}
        byte_stream = io.BytesIO()
        writer = geostream.writer(byte_stream, collection_props)
        writer.write_feature_collection(collection)
        byte_stream.seek(0)
        byte_stream.write(struct.pack("B", 0))
        byte_stream.seek(0)
        geostream.reader(byte_stream)
예제 #3
0
def test_read_truncated_after_feature_length(feat_collection_2):
    collection = feat_collection_2
    collection_props = {}
    byte_stream = io.BytesIO()
    writer = geostream.writer(byte_stream, collection_props)
    writer.write_feature_collection(collection)
    byte_stream.write(struct.pack(
        "i",
        2))  # append the length of a second feature, but don't append data
    byte_stream.seek(0)
    reader = geostream.reader(byte_stream)
    read_features = [f for f in reader]
    assert len(read_features) == 1
예제 #4
0
def test_read_truncated_feature_data(feat_collection_2):
    collection = feat_collection_2
    byte_stream = io.BytesIO()
    writer = geostream.writer(byte_stream)
    writer.write_feature_collection(collection)
    byte_stream.seek(0)
    good_data = byte_stream.read()
    bad_byte_stream = io.BytesIO()
    bad_byte_stream.write(
        good_data[:-5])  # truncate trailing length and 1 byte of feature data
    bad_byte_stream.seek(0)
    reader = geostream.reader(bad_byte_stream)
    read_features = [f for f in reader]
    assert len(read_features) == 0
예제 #5
0
def test_reverse_read_gjson_features_from_longer_stream(feat_collection_3):
    collection = feat_collection_3
    collection_props = {"unit": "something", "key": "uuid"}
    byte_stream = io.BytesIO()
    writer = geostream.writer(byte_stream, collection_props)
    for i in range(0, 100):
        writer.write_feature_collection(collection)
    byte_stream.seek(0)
    reader = geostream.reader(byte_stream, reverse=True)
    assert reader.srid == GEOJSON_EPSG_SRID
    assert reader.schema_version in GEOSTREAM_SCHEMA_VERSIONS
    assert reader.properties == collection_props
    read_features = [f for f in reader]
    assert len(read_features) == 300
    feature_list = feat_collection_3["features"]
    assert feature_list[0] == read_features[2]
    assert feature_list[1] == read_features[1]
    assert feature_list[2] == read_features[0]
예제 #6
0
def test_reverse_read_empty_stream_raises_exception():
    with pytest.raises(struct.error):
        byte_stream = io.BytesIO()
        geostream.reader(byte_stream, reverse=True)
예제 #7
0
def cli():
    args = parse_args()

    output_one_named_file = False
    output_path = None
    if args.out:
        output_path = Path(args.out)
        if output_path.suffix == ".json":
            if len(args.inputs) == 1 and Path(args.inputs[0]).is_file():
                output_one_named_file = True
            else:
                sys.stderr.write(
                    f"Output path must be a directory for multiple input files, not: {args.out}\n"
                )
                exit(1)
        elif not output_path.exists():
            try:
                output_path.mkdir(parents=True)
            except Exception as e:
                sys.stderr.write(
                    f"Un-writeable output path: {args.out}. Error: {e}")
        elif not output_path.is_dir():
            sys.stderr.write(
                f"Existing output path must be a directory: {args.out}\n")
            exit(1)

    select = {}
    if args.select:
        try:
            select = json.loads(args.select)
        except Exception as e:
            sys.stderr.write(
                f"Invalid select text, must be valid JSON string: {args.select}. Error: {e}\n"
            )
            exit(1)

    for gjz_file in [f for i in args.inputs for f in iglob(i)]:
        input_gjz = Path(gjz_file)

        if not input_gjz.is_file() or not input_gjz.exists():
            print(
                f"Skipped: {gjz_file}, which is not a file or does not exist")
            continue
        if input_gjz.suffix != ".gjz":
            print(
                f"Skipped: {gjz_file}, which does not have the name extension: .gjz"
            )
            continue

        if output_one_named_file:
            output_file = output_path
        elif output_path is not None:
            output_file = output_path.joinpath(input_gjz.stem + ".json")
        else:
            output_file = input_gjz.parent.joinpath(input_gjz.stem + ".json")

        if args.verbose:
            print(f"Unpacking: {gjz_file} into: {output_file}")

        with input_gjz.open("rb") as bf:
            try:
                reader = geostream.reader(bf, reverse=args.reverse)
            except Exception as e:
                print(f"...failed to open {gjz_file}, error: {e}")
                continue

            if select:
                selected = filter(
                    lambda feat: all(item in feat.properties.items()
                                     for item in select.items()), reader)
            else:
                selected = reader

            if args.verbose:
                _feature_count.append(0)
                selected = map(_count_features, selected)

            geojson_collection = FeatureCollection(
                features=selected,
                properties=reader.properties,
                srid=reader.srid)

            try:
                with output_file.open("w") as tf:
                    dump_fn = partial(
                        json.dump,
                        geojson_collection,
                        tf,
                        allow_nan=False,
                        iterable_as_array=True,
                        default=_cbor2types_to_json,
                    )
                    if args.pretty:
                        dump_fn(indent=4, sort_keys=True)
                    else:
                        dump_fn()
            except Exception as e:
                sys.stderr.write(
                    f"...bad out directory path, failed to open: {output_file}, error: {e}"
                )
                exit(1)

            if args.verbose:
                filtered = f"selected by: {select}" if select else "selected all"
                print(f"...unpacked {_feature_count[0]} Features, {filtered}")