Skip to content

Commit 7de0d1b

Browse files
authored
More options to normalize_json; Add is_subset_of(json1, json2) (#21)
* normalize json * test interface * is subset * is_subset_of * ready to PR * fix * fix
1 parent 7dc1233 commit 7de0d1b

File tree

7 files changed

+101
-8
lines changed

7 files changed

+101
-8
lines changed

Makefile

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,9 @@ python_sdist:
105105
# tar -tvf dist/geobuf-*.tar.gz
106106
python_test: pytest
107107

108-
cli_test:
108+
cli_test: cli_test1 cli_test2 cli_test3 cli_test4
109+
110+
cli_test1:
109111
python3 -m pybind11_geobuf
110112
python3 -m pybind11_geobuf --help
111113
python3 -m pybind11_geobuf json2geobuf data/sample1.json build/sample1.pbf
@@ -120,6 +122,21 @@ cli_test2:
120122
python3 -m pybind11_geobuf round_trip data/sample2.json -o build/test/cxx_py --json2pb_use_python=False --pb2json_use_python=True
121123
python3 -m pybind11_geobuf round_trip data/sample2.json -o build/test/py_cxx --json2pb_use_python=True --pb2json_use_python=False
122124

125+
cli_test3:
126+
python3 -m pybind11_geobuf normalize_json data/feature_collection.json build/fc.json && cat build/fc.json | grep '"double": 3.142,'
127+
python3 -m pybind11_geobuf normalize_json data/feature_collection.json build/fc.json --round_geojson_non_geometry=None && cat build/fc.json | grep '"double": 3.141592653'
128+
python3 -m pybind11_geobuf normalize_json data/feature_collection.json build/fc.json --round_geojson_geometry=None && cat build/fc.json | grep 3.3333333333333
129+
python3 -m pybind11_geobuf normalize_json data/feature_collection.json build/fc.json --round_geojson_geometry=3,3,2 && cat build/fc.json | grep '120.285,'
130+
python3 -m pybind11_geobuf normalize_json data/feature_collection.json build/fc.json --round_geojson_geometry=0,0,0 && cat build/fc.json | grep '120,'
131+
python3 -m pybind11_geobuf normalize_json data/feature_collection.json build/fc.json --round_geojson_geometry=0,0,0 --denoise_double_0=False && cat build/fc.json | grep '120.0,'
132+
python3 -m pybind11_geobuf normalize_json data/feature_collection.json build/fc.json --round_geojson_geometry=8,8,-1 && cat build/fc.json | wc -l | grep 49
133+
python3 -m pybind11_geobuf normalize_json data/feature_collection.json build/fc.json --round_geojson_geometry=8,8,-1 --strip_geometry_z_0=False && cat build/fc.json | wc -l | grep 53
134+
135+
cli_test4:
136+
python3 -m pybind11_geobuf is_subset_of data/feature_collection.json data/feature_collection.json
137+
138+
.PHONY: cli_test cli_test1 cli_test2 cli_test3
139+
123140
# conda create -y -n py36 python=3.6
124141
# conda create -y -n py37 python=3.7
125142
# conda create -y -n py38 python=3.8

docs/about/release-notes.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ To upgrade `pybind11-geobuf` to the latest version, use pip:
1010
pip install -U pybind11-geobuf
1111
```
1212

13+
## Version 0.1.4 (2023-04-15)
14+
15+
* More options to normalize_json
16+
* Add `is_subset_of(json1, json2)`
17+
1318
## Version 0.1.3 (2023-04-11)
1419

1520
* Fix round geojson-non-geometry

pybind11_geobuf/__main__.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import os
2+
from typing import Tuple
23

34
from loguru import logger
45

56
from pybind11_geobuf import rapidjson # noqa
67
from pybind11_geobuf import Decoder, Encoder # noqa
8+
from pybind11_geobuf import is_subset_of as is_subset_of_impl # noqa
79
from pybind11_geobuf import normalize_json as normalize_json_impl # noqa
810
from pybind11_geobuf import pbf_decode as pbf_decode_impl # noqa
911

@@ -90,6 +92,10 @@ def normalize_json(
9092
sort_keys: bool = True,
9193
precision: int = -1,
9294
only_xy: bool = False,
95+
denoise_double_0: bool = True,
96+
strip_geometry_z_0: bool = True,
97+
round_geojson_non_geometry: int = 3,
98+
round_geojson_geometry: Tuple[int, int, int] = (8, 8, 3),
9399
):
94100
logger.info(
95101
f"normalize_json {input_path} ({__filesize(input_path):,} bytes)"
@@ -116,6 +122,10 @@ def normalize_json(
116122
output_path,
117123
indent=indent,
118124
sort_keys=sort_keys,
125+
denoise_double_0=denoise_double_0,
126+
strip_geometry_z_0=strip_geometry_z_0,
127+
round_geojson_non_geometry=round_geojson_non_geometry,
128+
round_geojson_geometry=round_geojson_geometry,
119129
), f"failed to normalize json to {output_path}"
120130
logger.info(f"wrote to {output_path} ({__filesize(output_path):,} bytes)")
121131

@@ -155,12 +165,6 @@ def round_trip(
155165
json2pb_use_python: bool = False,
156166
pb2json_use_python: bool = False,
157167
):
158-
"""
159-
_0.json
160-
_1.pbf
161-
_2.pbf.txt
162-
_3.json
163-
"""
164168
assert path.endswith((".json", ".geojson")) and os.path.isfile(path)
165169
path = os.path.abspath(path)
166170
output_dir = os.path.abspath(output_dir or os.path.dirname(path))
@@ -200,13 +204,18 @@ def round_trip(
200204
logger.info(f"wrote to {opath}")
201205

202206

207+
def is_subset_of(path1: str, path2: str):
208+
assert is_subset_of_impl(path1, path2)
209+
210+
203211
if __name__ == "__main__":
204212
import fire
205213

206214
fire.core.Display = lambda lines, out: print(*lines, file=out)
207215
fire.Fire(
208216
{
209217
"geobuf2json": geobuf2json,
218+
"is_subset_of": is_subset_of,
210219
"json2geobuf": json2geobuf,
211220
"normalize_geobuf": normalize_geobuf,
212221
"normalize_json": normalize_json,

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ def build_extension(self, ext):
127127
# logic and declaration, and simpler if you include description/version in a file.
128128
setup(
129129
name="pybind11_geobuf",
130-
version="0.1.3",
130+
version="0.1.4",
131131
author="tzx",
132132
author_email="dvorak4tzx@gmail.com",
133133
url="https://geobuf-cpp.readthedocs.io",

src/geobuf/rapidjson_helpers.hpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "rapidjson/stringbuffer.h"
1313
#include <fstream>
1414
#include <iostream>
15+
#include <set>
1516

1617
namespace cubao
1718
{
@@ -512,6 +513,54 @@ inline RapidjsonValue to_rapidjson(const mapbox::geojson::value &json)
512513
// return mapbox::geojson::convert<mapbox::geojson::value>(json);
513514
// }
514515

516+
inline bool is_subset_of(const RapidjsonValue &a, const RapidjsonValue &b)
517+
{
518+
if (a.IsArray()) {
519+
if (!b.IsArray() || a.Size() != b.Size()) {
520+
return false;
521+
}
522+
auto aArr = a.GetArray();
523+
auto bArr = b.GetArray();
524+
for (int i = 0, N = a.Size(); i < N; ++i) {
525+
if (!is_subset_of(aArr[i], bArr[i])) {
526+
return false;
527+
}
528+
}
529+
return true;
530+
}
531+
if (!a.IsObject()) {
532+
if (b.IsObject()) {
533+
return false;
534+
}
535+
return a == b;
536+
}
537+
if (!b.IsObject()) {
538+
return false;
539+
}
540+
auto aObj = a.GetObject();
541+
auto bObj = b.GetObject();
542+
std::set<std::string> aKeys, bKeys;
543+
std::for_each(aObj.MemberBegin(), aObj.MemberEnd(), [&](auto &kv) {
544+
aKeys.insert(
545+
std::string(kv.name.GetString(), kv.name.GetStringLength()));
546+
});
547+
std::for_each(bObj.MemberBegin(), bObj.MemberEnd(), [&](auto &kv) {
548+
bKeys.insert(
549+
std::string(kv.name.GetString(), kv.name.GetStringLength()));
550+
});
551+
if (!std::includes(bKeys.begin(), bKeys.end(), //
552+
aKeys.begin(), aKeys.end())) {
553+
return false;
554+
}
555+
for (const auto &k : aKeys) {
556+
if (!is_subset_of(aObj.FindMember(k.c_str())->value,
557+
bObj.FindMember(k.c_str())->value)) {
558+
return false;
559+
}
560+
}
561+
return true;
562+
}
563+
515564
} // namespace cubao
516565

517566
#endif

src/main.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,15 @@ PYBIND11_MODULE(_pybind11_geobuf, m)
7979
"round_geojson_geometry"_a = std::array<int, 3>{8, 8, 3},
8080
rvp::reference_internal);
8181

82+
m.def(
83+
"is_subset_of",
84+
[](const std::string &path1, const std::string &path2) {
85+
auto json1 = mapbox::geobuf::load_json(path1);
86+
auto json2 = mapbox::geobuf::load_json(path2);
87+
return cubao::is_subset_of(json1, json2);
88+
},
89+
"path1"_a, "path2"_a);
90+
8291
m.def(
8392
"str2json2str",
8493
[](const std::string &json_string, //

src/pybind11_rapidjson.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,10 @@ void bind_rapidjson(py::module &m)
109109
return values;
110110
},
111111
rvp::reference_internal)
112+
//
113+
.def("is_subset_of", [](const RapidjsonValue &self, const RapidjsonValue &other) -> bool {
114+
return is_subset_of(self, other);
115+
}, "other"_a)
112116
// load/dump file
113117
.def(
114118
"load",

0 commit comments

Comments
 (0)