Skip to content

Commit

Permalink
Refactor Track and MultiTrack classes
Browse files Browse the repository at this point in the history
  • Loading branch information
cleder committed Dec 21, 2023
1 parent ca151d0 commit b0605e0
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 118 deletions.
133 changes: 38 additions & 95 deletions fastkml/gx.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@
The complete XML schema for elements in this extension namespace is
located at http://developers.google.com/kml/schema/kml22gx.xsd.
"""
import contextlib
import datetime
import logging
from dataclasses import dataclass
Expand All @@ -95,6 +94,10 @@
from fastkml.enums import AltitudeMode
from fastkml.enums import Verbosity
from fastkml.geometry import _Geometry
from fastkml.helpers import bool_subelement
from fastkml.helpers import subelement_bool_kwarg
from fastkml.helpers import xml_subelement_list
from fastkml.helpers import xml_subelement_list_kwarg
from fastkml.types import Element

__all__ = [
Expand Down Expand Up @@ -126,7 +129,7 @@ class Angle:
roll: float = 0.0


@dataclass(frozen=True) # XXX replace with _XMLObject
@dataclass(frozen=True)
class TrackItem:
"""A track item describes an objects position and heading at a specific time."""

Expand Down Expand Up @@ -221,19 +224,6 @@ def __init__(
geometry=geometry,
)

def __repr__(self) -> str:
return (
f"{self.__class__.__name__}("
f"ns={self.ns!r}, "
f"id={self.id!r}, "
f"target_id={self.target_id!r}, "
f"extrude={self.extrude!r}, "
f"tessellate={self.tessellate!r}, "
f"altitude_mode={self.altitude_mode}, "
f"track_items={self.track_items!r}"
")"
)

def etree_element(
self,
precision: Optional[int] = None,
Expand Down Expand Up @@ -342,7 +332,7 @@ def __init__(
tracks = multilinestring_to_tracks(geometry, ns=ns)
elif tracks:
geometry = tracks_to_geometry(tracks)
self.tracks = tracks
self.tracks = tracks or []
self.interpolate = interpolate
super().__init__(
ns=ns,
Expand All @@ -355,83 +345,28 @@ def __init__(
geometry=geometry,
)

def __repr__(self) -> str:
return (
f"{self.__class__.__name__}("
f"ns={self.ns!r}, "
f"id={self.id!r}, "
f"target_id={self.target_id!r}, "
f"extrude={self.extrude!r}, "
f"tessellate={self.tessellate!r}, "
f"altitude_mode={self.altitude_mode}, "
f"tracks={self.tracks!r}, "
f"interpolate={self.interpolate!r}"
")"
)

def etree_element(
self,
precision: Optional[int] = None,
verbosity: Verbosity = Verbosity.normal,
name_spaces: Optional[Dict[str, str]] = None,
) -> Element:
element = super().etree_element(precision=precision, verbosity=verbosity)
if self.interpolate is not None:
i_element = cast(
Element,
config.etree.SubElement( # type: ignore[attr-defined]
element,
f"{self.ns}interpolate",
),
)
i_element.text = str(int(self.interpolate))
for track in self.tracks or []:
element.append(
track.etree_element(
precision=precision,
verbosity=verbosity,
name_spaces=name_spaces,
),
)
return element

@classmethod
def _get_interpolate(
cls,
*,
ns: str,
name_spaces: Optional[Dict[str, str]] = None,
element: Element,
strict: bool,
) -> Optional[bool]:
interpolate = element.find(f"{ns}interpolate")
if interpolate is None:
return None
with contextlib.suppress(ValueError):
return bool(int(interpolate.text.strip()))
return None
bool_subelement(
self,
element=element,
attr_name="interpolate",
node_name="interpolate",
)
xml_subelement_list(
self,
element=element,
attr_name="tracks",
precision=precision,
verbosity=verbosity,
)

@classmethod
def _get_track_kwargs_from_element(
cls,
*,
ns: str,
name_spaces: Optional[Dict[str, str]] = None,
element: Element,
strict: bool,
) -> List[Track]:
return [
cast(
Track,
Track.class_from_element(
ns=ns,
element=track,
strict=strict,
),
)
for track in element.findall(f"{ns}Track")
if track is not None
]
return element

@classmethod
def _get_kwargs(
Expand All @@ -450,16 +385,24 @@ def _get_kwargs(
)
name_spaces = kwargs["name_spaces"]
assert name_spaces is not None
kwargs["interpolate"] = cls._get_interpolate(
ns=ns,
name_spaces=name_spaces,
element=element,
strict=strict,
kwargs.update(
subelement_bool_kwarg(
element=element,
ns=ns,
node_name="interpolate",
kwarg="interpolate",
strict=strict,
),
)
kwargs["tracks"] = cls._get_track_kwargs_from_element(
ns=name_spaces["gx"],
name_spaces=name_spaces,
element=element,
strict=strict,
kwargs.update(
xml_subelement_list_kwarg(
element=element,
ns=name_spaces["gx"],
name_spaces=name_spaces,
kwarg="tracks",
obj_class=Track,
strict=strict,
),
)

return kwargs
27 changes: 4 additions & 23 deletions tests/gx_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,12 +186,6 @@ def test_track_from_linestring(self) -> None:
assert "when" in track.to_string()
assert "angles>" not in track.to_string()
assert "when>" not in track.to_string()
assert repr(track) == (
"Track(ns='', id='track1', target_id='track2', extrude=True, "
"tessellate=True, altitude_mode=AltitudeMode.absolute, "
"track_items=[TrackItem(when=None, coord=Point(1, 2), angle=None), "
"TrackItem(when=None, coord=Point(2, 0), angle=None)])"
)

def test_track_from_track_items(self) -> None:
time1 = datetime.datetime(2023, 1, 1, 0, 0, 0, tzinfo=datetime.timezone.utc)
Expand All @@ -209,13 +203,6 @@ def test_track_from_track_items(self) -> None:
assert ">1 2</" in track.to_string()
assert "angles>" in track.to_string()
assert ">0.0 0.0 0.0</" in track.to_string()
assert repr(track) == (
"Track(ns='', id=None, target_id=None, extrude=False, tessellate=False, "
"altitude_mode=None, "
"track_items=[TrackItem("
"when=datetime.datetime(2023, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), "
"coord=Point(1, 2), angle=Angle(heading=0.0, tilt=0.0, roll=0.0))])"
)

def test_track_from_track_items_no_coord(self) -> None:
time1 = datetime.datetime(2023, 1, 1, 0, 0, 0, tzinfo=datetime.timezone.utc)
Expand All @@ -233,13 +220,6 @@ def test_track_from_track_items_no_coord(self) -> None:
assert "coord" in track.to_string()
assert "angles>" in track.to_string()
assert ">0.0 0.0 0.0</" in track.to_string()
assert repr(track) == (
"Track(ns='', id=None, target_id=None, extrude=False, tessellate=False, "
"altitude_mode=None, "
"track_items=[TrackItem("
"when=datetime.datetime(2023, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), "
"coord=None, angle=Angle(heading=0.0, tilt=0.0, roll=0.0))])"
)

def test_track_from_str(self) -> None:
doc = """
Expand Down Expand Up @@ -346,8 +326,9 @@ def test_from_multilinestring(self) -> None:

mt = MultiTrack(geometry=lines, ns="")

assert repr(mt) == repr(
MultiTrack(
assert (
mt.to_string()
== MultiTrack(
ns="",
id=None,
target_id=None,
Expand Down Expand Up @@ -382,7 +363,7 @@ def test_from_multilinestring(self) -> None:
],
),
],
),
).to_string()
)

def test_multitrack(self) -> None:
Expand Down

0 comments on commit b0605e0

Please sign in to comment.