Skip to content

Commit

Permalink
geojsontojson: Add meta output, with output field coverage
Browse files Browse the repository at this point in the history
Will be adding more to meta later, like errors on conversion.

Added field coverage because thought would be helpful for
Open-Telecoms-Data/cove-ofds#6
but actually I added to wrong conversion!
Leaving as may be useful and that is simpler than removing.

Also fix: bug in get_json() that meant it could not be called twice
  • Loading branch information
odscjames committed Nov 7, 2022
1 parent dc834f6 commit 480d925
Show file tree
Hide file tree
Showing 8 changed files with 307 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Improved in GeoJSON to JSON:
- Makes Phases into references & populates phases array (Nodes, Spans)
- Makes Organisations into references & populates organisations array (Nodes, Spans)
- Add meta output, with output field coverage
- Fix bug that meant get_json() could not be called twice

### Changed

Expand Down
9 changes: 9 additions & 0 deletions libcoveofds/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ def main():
geojson_to_json_parser.add_argument(
"outputfilename", help="Output filename to write JSON data to"
)
geojson_to_json_parser.add_argument(
"--outputmetafilename",
help="Output filename to write meta JSON data to",
required=False,
)

args = parser.parse_args()

Expand Down Expand Up @@ -119,6 +124,10 @@ def main():
with open(args.outputfilename, "w") as fp:
json.dump(converter.get_json(), fp, indent=4)

if args.outputmetafilename:
with open(args.outputmetafilename, "w") as fp:
json.dump(converter.get_meta_json(), fp, indent=4)


if __name__ == "__main__":
main()
15 changes: 15 additions & 0 deletions libcoveofds/geojson.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import copy

from libcove2.common import fields_present_generator


class JSONToGeoJSONConverter:
def __init__(self):
Expand Down Expand Up @@ -268,6 +270,8 @@ def _process_organisation(self, network_id: str, organisation: dict) -> str:
def get_json(self) -> dict:
out: dict = {"networks": []}
for network in self._networks.values():
# We are going to change network, so we need to take a copy
network = copy.deepcopy(network)
# Arrays have minItems: 1 set - so if no content, remove the empty array
for key in ["nodes", "spans", "phases", "organisations", "contracts"]:
if not network[key]:
Expand All @@ -278,3 +282,14 @@ def get_json(self) -> dict:
network[key] = list(network[key].values())
out["networks"].append(network)
return out

def get_meta_json(self) -> dict:
out: dict = {"output_field_coverage": {}}
# field coverage
for key, value in fields_present_generator(self.get_json()):
if key not in out["output_field_coverage"]:
out["output_field_coverage"][key] = {"count": 1}
else:
out["output_field_coverage"][key]["count"] += 1
# return
return out
58 changes: 58 additions & 0 deletions tests/fixtures/geojson_to_json/basic_1.meta.expected.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"output_field_coverage": {
"/networks": {
"count": 1
},
"/networks/id": {
"count": 1
},
"/networks/name": {
"count": 1
},
"/networks/nodes": {
"count": 1
},
"/networks/nodes/id": {
"count": 2
},
"/networks/nodes/name": {
"count": 2
},
"/networks/nodes/location": {
"count": 2
},
"/networks/nodes/location/type": {
"count": 2
},
"/networks/nodes/location/coordinates": {
"count": 2
},
"/networks/nodes/status": {
"count": 1
},
"/networks/spans": {
"count": 1
},
"/networks/spans/id": {
"count": 1
},
"/networks/spans/name": {
"count": 1
},
"/networks/spans/start": {
"count": 1
},
"/networks/spans/end": {
"count": 1
},
"/networks/spans/route": {
"count": 1
},
"/networks/spans/route/type": {
"count": 1
},
"/networks/spans/route/coordinates": {
"count": 1
}
}
}
40 changes: 40 additions & 0 deletions tests/fixtures/geojson_to_json/no_geometry_1.meta.expected.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"output_field_coverage": {
"/networks": {
"count": 1
},
"/networks/id": {
"count": 1
},
"/networks/name": {
"count": 1
},
"/networks/nodes": {
"count": 1
},
"/networks/nodes/id": {
"count": 2
},
"/networks/nodes/name": {
"count": 2
},
"/networks/nodes/status": {
"count": 1
},
"/networks/spans": {
"count": 1
},
"/networks/spans/id": {
"count": 1
},
"/networks/spans/name": {
"count": 1
},
"/networks/spans/start": {
"count": 1
},
"/networks/spans/end": {
"count": 1
}
}
}
91 changes: 91 additions & 0 deletions tests/fixtures/geojson_to_json/organisations_1.meta.expected.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
{
"output_field_coverage": {
"/networks": {
"count": 1
},
"/networks/id": {
"count": 1
},
"/networks/name": {
"count": 1
},
"/networks/nodes": {
"count": 1
},
"/networks/nodes/id": {
"count": 2
},
"/networks/nodes/name": {
"count": 2
},
"/networks/nodes/physicalInfrastructureProvider": {
"count": 2
},
"/networks/nodes/physicalInfrastructureProvider/id": {
"count": 2
},
"/networks/nodes/networkProvider": {
"count": 2
},
"/networks/nodes/networkProvider/id": {
"count": 2
},
"/networks/nodes/location": {
"count": 2
},
"/networks/nodes/location/type": {
"count": 2
},
"/networks/nodes/location/coordinates": {
"count": 2
},
"/networks/nodes/status": {
"count": 1
},
"/networks/spans": {
"count": 1
},
"/networks/spans/id": {
"count": 1
},
"/networks/spans/name": {
"count": 1
},
"/networks/spans/start": {
"count": 1
},
"/networks/spans/end": {
"count": 1
},
"/networks/spans/physicalInfrastructureProvider": {
"count": 1
},
"/networks/spans/physicalInfrastructureProvider/id": {
"count": 1
},
"/networks/spans/networkProvider": {
"count": 1
},
"/networks/spans/networkProvider/id": {
"count": 1
},
"/networks/spans/route": {
"count": 1
},
"/networks/spans/route/type": {
"count": 1
},
"/networks/spans/route/coordinates": {
"count": 1
},
"/networks/organisations": {
"count": 1
},
"/networks/organisations/id": {
"count": 2
},
"/networks/organisations/name": {
"count": 2
}
}
}
82 changes: 82 additions & 0 deletions tests/fixtures/geojson_to_json/phases_1.meta.expected.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
{
"output_field_coverage": {
"/networks": {
"count": 1
},
"/networks/id": {
"count": 1
},
"/networks/name": {
"count": 1
},
"/networks/nodes": {
"count": 1
},
"/networks/nodes/id": {
"count": 2
},
"/networks/nodes/name": {
"count": 2
},
"/networks/nodes/phase": {
"count": 2
},
"/networks/nodes/phase/id": {
"count": 2
},
"/networks/nodes/location": {
"count": 2
},
"/networks/nodes/location/type": {
"count": 2
},
"/networks/nodes/location/coordinates": {
"count": 2
},
"/networks/nodes/status": {
"count": 1
},
"/networks/spans": {
"count": 1
},
"/networks/spans/id": {
"count": 1
},
"/networks/spans/name": {
"count": 1
},
"/networks/spans/start": {
"count": 1
},
"/networks/spans/end": {
"count": 1
},
"/networks/spans/phase": {
"count": 1
},
"/networks/spans/phase/id": {
"count": 1
},
"/networks/spans/route": {
"count": 1
},
"/networks/spans/route/type": {
"count": 1
},
"/networks/spans/route/coordinates": {
"count": 1
},
"/networks/phases": {
"count": 1
},
"/networks/phases/id": {
"count": 1
},
"/networks/phases/name": {
"count": 1
},
"/networks/phases/description": {
"count": 1
}
}
}
10 changes: 10 additions & 0 deletions tests/test_geojson_to_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ def test_geojson_to_json(filename):
"geojson_to_json",
filename + ".expected.json",
)
meta_expected_filename = os.path.join(
os.path.dirname(os.path.realpath(__file__)),
"fixtures",
"geojson_to_json",
filename + ".meta.expected.json",
)

with open(nodes_filename) as fp:
nodes_data = json.load(fp)
Expand All @@ -51,3 +57,7 @@ def test_geojson_to_json(filename):
with open(expected_filename) as fp:
expected_data = json.load(fp)
assert expected_data == converter.get_json()

with open(meta_expected_filename) as fp:
meta_expected_data = json.load(fp)
assert meta_expected_data == converter.get_meta_json()

0 comments on commit 480d925

Please sign in to comment.