Compare commits

...

2 commits

Author SHA1 Message Date
Midgard 5706443217
Rename RETAIN_ to VERBATIM_ 2024-01-16 02:33:44 +01:00
Midgard 9f5847088c
Remove fancy JsonRoundingFloat and JsonLatLon
because the Python JSON lib can't override the precise serialization
anyway. Ugh.
2024-01-16 02:33:06 +01:00
2 changed files with 18 additions and 73 deletions

View file

@ -1,6 +1,5 @@
from trainmap_backup import \ from trainmap_backup import \
camel_to_snake, transform_dict, RETAIN_KEY, RETAIN_VALUE, DISCARD, \ camel_to_snake, transform_dict, VERBATIM_KEY, VERBATIM_VALUE, DISCARD
JsonRoundingFloat, JsonLonLatCoord, json_encode
def test_camel_to_snake(): def test_camel_to_snake():
@ -16,9 +15,9 @@ def test_transform_dict():
assert transform_dict( assert transform_dict(
{ {
"discard": DISCARD, "discard": DISCARD,
"otherkey": ("newkey", RETAIN_VALUE), "otherkey": ("newkey", VERBATIM_VALUE),
"uppervalue": (RETAIN_KEY, str.upper), "uppervalue": (VERBATIM_KEY, str.upper),
"retainboth": (RETAIN_KEY, RETAIN_VALUE) "retainboth": (VERBATIM_KEY, VERBATIM_VALUE)
}, },
{ {
"discard": True, "discard": True,
@ -33,22 +32,3 @@ def test_transform_dict():
"uppervalue": "VALUE", "uppervalue": "VALUE",
"retainboth": "value", "retainboth": "value",
} }
def test_JsonRoundingFloat():
assert str(JsonRoundingFloat(1.1234567890123456789012345678901234567890, 2)) == "1.12"
assert str(JsonRoundingFloat(1.1234567890123456789012345678901234567890, 3)) == "1.123"
assert str(JsonRoundingFloat(1.1, 3)) == "1.1"
def test_JsonLonLatCoord():
assert str(JsonLonLatCoord(1.1234567890123456789012345678901234567890, 50.1234)) == \
"[1.123457, 50.1234]"
def test_json_encode():
assert json_encode(JsonLonLatCoord(1, 2)) == "[1, 2]"
assert json_encode([
JsonLonLatCoord(1, 2),
JsonLonLatCoord(3, 4),
]) == "[[1, 2], [3, 4]]"

View file

@ -1,6 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from dataclasses import dataclass
import re import re
import json import json
import socketio import socketio
@ -8,30 +7,8 @@ import socketio
WS_URL = "wss://trainmap.belgiantrain.be/socket.io/" WS_URL = "wss://trainmap.belgiantrain.be/socket.io/"
@dataclass class VERBATIM_KEY: pass
class JsonLonLatCoord: class VERBATIM_VALUE: pass
lon: float
lat: float
def __repr__(self):
return str(self.__to_json__())
def __to_json__(self):
# return f"[{self.lon:.6f}, {self.lat:.6f}]"
return [round(self.lon, 6), round(self.lat, 6)]
@dataclass
class JsonRoundingFloat:
value: float
decimals: int
def __repr__(self):
return str(self.__to_json__())
def __to_json__(self):
# return f"{{0:.{self.decimals}f}}".format(self.value)
return round(self.value, self.decimals)
class RETAIN_KEY: pass
class RETAIN_VALUE: pass
class DISCARD: pass class DISCARD: pass
def transform_dict(specification: dict, d: dict): def transform_dict(specification: dict, d: dict):
""" """
@ -40,18 +17,18 @@ def transform_dict(specification: dict, d: dict):
- keys that should be discarded: DISCARD - keys that should be discarded: DISCARD
- keys whose key and value should be retained verbatim: not present - keys whose key and value should be retained verbatim: not present
- keys whose key and/or value should be transformed, with None denoting no change: tuple of - keys whose key and/or value should be transformed, with None denoting no change: tuple of
(str, function), or any of those two RETAIN_KEY or RETAIN_VALUE respectively (str, function), or any of those two VERBATIM_KEY or VERBATIM_VALUE respectively
{ {
""" """
return { return {
( (
specification[k][0] specification[k][0]
if specification.get(k) not in (None, DISCARD) and specification[k][0] is not RETAIN_KEY if specification.get(k) not in (None, DISCARD) and specification[k][0] is not VERBATIM_KEY
else k else k
): ( ): (
specification[k][1](v) specification[k][1](v)
if specification.get(k) not in (None, DISCARD) and specification[k][1] is not RETAIN_VALUE if specification.get(k) not in (None, DISCARD) and specification[k][1] is not VERBATIM_VALUE
else v else v
) )
for k, v in d.items() for k, v in d.items()
@ -84,17 +61,17 @@ def filtered_data(data):
trip["trip_short_name"]: transform_dict({ trip["trip_short_name"]: transform_dict({
"trip_id": DISCARD, "trip_id": DISCARD,
"trip_short_name": DISCARD, "trip_short_name": DISCARD,
"position": (RETAIN_KEY, lambda l: ( "position": (VERBATIM_KEY, lambda p: (
JsonLonLatCoord(*l) [round(p[0], 6), round(p[1], 6)]
if isinstance(l, list) else l if isinstance(p, list) else p
)), )),
"current_traveled_distance": (RETAIN_KEY, lambda x: ( "current_traveled_distance": (VERBATIM_KEY, lambda x: (
JsonRoundingFloat(x, 1) round(x, 1)
if isinstance(x, float) else x if isinstance(x, float) else x
)), )),
"fromstationdistance": ("from_station_distance", RETAIN_VALUE), "fromstationdistance": ("from_station_distance", VERBATIM_VALUE),
"nextstationdistance": ("next_station_distance", RETAIN_VALUE), "nextstationdistance": ("next_station_distance", VERBATIM_VALUE),
"trip_headsign": (RETAIN_KEY, lambda x: transform_dict({ "trip_headsign": (VERBATIM_KEY, lambda x: transform_dict({
"default": DISCARD, "default": DISCARD,
"en": DISCARD, "en": DISCARD,
"de": DISCARD, "de": DISCARD,
@ -105,20 +82,8 @@ def filtered_data(data):
} }
class JsonEncoder(json.JSONEncoder):
def default(self, o):
if hasattr(o, "__to_json__"):
return o.__to_json__()
else:
return super().default(o)
def json_encode(data, *args, **kwargs):
return json.dumps(data, *args, cls=JsonEncoder, **kwargs)
def emit(data): def emit(data):
print(json_encode(filtered_data(data), ensure_ascii=False)) print(json.dumps(filtered_data(data), ensure_ascii=False))
def main(): def main():