Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix TimeStamp and TimeSpan class to use class_from_element method #266

Merged
merged 3 commits into from
Nov 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions examples/UsageExamples.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@


def print_child_features(element):
"""Prints the name of every child node of the given element, recursively"""
"""Prints the name of every child node of the given element, recursively."""
if not getattr(element, "features", None):
return
for feature in element.features():
Expand All @@ -17,7 +17,7 @@ def print_child_features(element):

k = kml.KML()

with open(fname) as kml_file: # noqa: ENC001
with open(fname, encoding="utf-8") as kml_file:
k.from_string(kml_file.read().encode("utf-8"))

print_child_features(k)
8 changes: 7 additions & 1 deletion fastkml/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,12 @@ def class_from_element(
strict: bool,
) -> "_XMLObject":
"""Creates an XML object from an etree element."""
kwargs = cls._get_kwargs(ns=ns, element=element, strict=strict)
kwargs = cls._get_kwargs(
ns=ns,
name_spaces=name_spaces,
element=element,
strict=strict,
)
return cls(
**kwargs,
)
Expand Down Expand Up @@ -186,6 +191,7 @@ def class_from_string(
ns = cls._get_ns(ns)
return cls.class_from_element(
ns=ns,
name_spaces=name_spaces,
strict=strict,
element=cast(
Element,
Expand Down
18 changes: 12 additions & 6 deletions fastkml/kml.py
Original file line number Diff line number Diff line change
Expand Up @@ -458,14 +458,20 @@ def from_element(self, element: Element, strict: bool = False) -> None:
self.snippet = _snippet
timespan = element.find(f"{self.ns}TimeSpan")
if timespan is not None:
s = TimeSpan(self.ns)
s.from_element(timespan)
self._timespan = s
self._timespan = TimeSpan.class_from_element(
ns=self.ns,
name_spaces=self.name_spaces,
element=timespan,
strict=strict,
)
timestamp = element.find(f"{self.ns}TimeStamp")
if timestamp is not None:
s = TimeStamp(self.ns)
s.from_element(timestamp)
self._timestamp = s
self._timestamp = TimeStamp.class_from_element(
ns=self.ns,
name_spaces=self.name_spaces,
element=timestamp,
strict=strict,
)
atom_link = element.find(f"{atom.NS}link")
if atom_link is not None:
s = atom.Link()
Expand Down
62 changes: 47 additions & 15 deletions fastkml/times.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import re
from datetime import date
from datetime import datetime
from typing import Any
from typing import Dict
from typing import Optional
from typing import Union

Expand Down Expand Up @@ -157,11 +159,12 @@ class TimeStamp(_TimePrimitive):
def __init__(
self,
ns: Optional[str] = None,
name_spaces: Optional[Dict[str, str]] = None,
id: Optional[str] = None,
target_id: Optional[str] = None,
timestamp: Optional[KmlDateTime] = None,
) -> None:
super().__init__(ns=ns, id=id, target_id=target_id)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file contains at least one console log. Please remove any present.

super().__init__(ns=ns, name_spaces=name_spaces, id=id, target_id=target_id)
self.timestamp = timestamp

def etree_element(
Expand All @@ -177,11 +180,25 @@ def etree_element(
when.text = str(self.timestamp)
return element

def from_element(self, element: Element) -> None:
super().from_element(element)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file contains at least one console log. Please remove any present.

when = element.find(f"{self.ns}when")
@classmethod
def _get_kwargs(
cls,
*,
ns: str,
name_spaces: Optional[Dict[str, str]] = None,
element: Element,
strict: bool,
) -> Dict[str, Any]:
kwargs = super()._get_kwargs(
ns=ns,
name_spaces=name_spaces,
element=element,
strict=strict,
)
when = element.find(f"{ns}when")
if when is not None:
self.timestamp = KmlDateTime.parse(when.text)
kwargs["timestamp"] = KmlDateTime.parse(when.text)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file contains at least one console log. Please remove any present.

return kwargs


class TimeSpan(_TimePrimitive):
Expand All @@ -192,24 +209,16 @@ class TimeSpan(_TimePrimitive):
def __init__(
self,
ns: Optional[str] = None,
name_spaces: Optional[Dict[str, str]] = None,
id: Optional[str] = None,
target_id: Optional[str] = None,
begin: Optional[KmlDateTime] = None,
end: Optional[KmlDateTime] = None,
) -> None:
super().__init__(ns=ns, id=id, target_id=target_id)
super().__init__(ns=ns, name_spaces=name_spaces, id=id, target_id=target_id)
self.begin = begin
self.end = end

def from_element(self, element: Element) -> None:
super().from_element(element)
begin = element.find(f"{self.ns}begin")
if begin is not None:
self.begin = KmlDateTime.parse(begin.text)
end = element.find(f"{self.ns}end")
if end is not None:
self.end = KmlDateTime.parse(end.text)

def etree_element(
self,
precision: Optional[int] = None,
Expand Down Expand Up @@ -237,3 +246,26 @@ def etree_element(
raise ValueError(msg)
# TODO test if end > begin
return element

@classmethod
def _get_kwargs(
cls,
*,
ns: str,
name_spaces: Optional[Dict[str, str]] = None,
element: Element,
strict: bool,
) -> Dict[str, Any]:
kwargs = super()._get_kwargs(
ns=ns,
name_spaces=name_spaces,
element=element,
strict=strict,
)
begin = element.find(f"{ns}begin")
if begin is not None:
kwargs["begin"] = KmlDateTime.parse(begin.text)
end = element.find(f"{ns}end")
if end is not None:
kwargs["end"] = KmlDateTime.parse(end.text)
return kwargs
25 changes: 19 additions & 6 deletions fastkml/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from typing import Optional
from typing import SupportsFloat
from typing import Union
from typing import cast

from fastkml import config
from fastkml.base import _BaseObject
Expand Down Expand Up @@ -185,14 +186,26 @@ def from_element(self, element: Element) -> None:
self.altitude_mode = AltitudeMode(altitude_mode.text)
timespan = element.find(f"{self.ns}TimeSpan")
if timespan is not None:
span = TimeSpan(self.ns)
span.from_element(timespan)
self._timespan = span
self._timespan = cast(
TimeSpan,
TimeSpan.class_from_element(
ns=self.ns,
name_spaces=self.name_spaces,
element=timespan,
strict=False,
),
)
timestamp = element.find(f"{self.ns}TimeStamp")
if timestamp is not None:
stamp = TimeStamp(self.ns)
stamp.from_element(timestamp)
self._timestamp = stamp
self._timestamp = cast(
TimeStamp,
TimeStamp.class_from_element(
ns=self.ns,
name_spaces=self.name_spaces,
element=timestamp,
strict=False,
),
)

def etree_element(
self,
Expand Down
4 changes: 3 additions & 1 deletion tests/atom_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,9 @@ def test_atom_person_ns(self) -> None:

def test_atom_author(self) -> None:
a = atom.Author(
name="Nobody", uri="http://localhost", email="[email protected]",
name="Nobody",
uri="http://localhost",
email="[email protected]",
)

serialized = a.to_string()
Expand Down
3 changes: 2 additions & 1 deletion tests/base_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ def test_to_str_empty_ns(self) -> None:
obj.__name__ = "test"

assert obj.to_string().replace(" ", "").replace(
"\n", "",
"\n",
"",
) == '<test id="id-0" targetId="target-id-0" />'.replace(" ", "")

def test_from_string(self) -> None:
Expand Down
3 changes: 2 additions & 1 deletion tests/geometries/point_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ def test_to_string_empty_geometry(self) -> None:
point = Point(geometry=geo.Point(None, None)) # type: ignore[arg-type]

with pytest.raises(
KMLWriteError, match=r"Invalid dimensions in coordinates '\(\(\),\)'",
KMLWriteError,
match=r"Invalid dimensions in coordinates '\(\(\),\)'",
):
point.to_string()

Expand Down
44 changes: 38 additions & 6 deletions tests/gx_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,24 @@ def test_multitrack(self) -> None:
track_items=[
TrackItem(
when=datetime.datetime(
2020, 1, 1, 0, 0, tzinfo=tzutc(),
2020,
1,
1,
0,
0,
tzinfo=tzutc(),
),
coord=geo.Point(0.0, 0.0),
angle=None,
),
TrackItem(
when=datetime.datetime(
2020, 1, 1, 0, 10, tzinfo=tzutc(),
2020,
1,
1,
0,
10,
tzinfo=tzutc(),
),
coord=geo.Point(1.0, 0.0),
angle=None,
Expand All @@ -119,14 +129,24 @@ def test_multitrack(self) -> None:
track_items=[
TrackItem(
when=datetime.datetime(
2020, 1, 1, 0, 10, tzinfo=tzutc(),
2020,
1,
1,
0,
10,
tzinfo=tzutc(),
),
coord=geo.Point(0.0, 1.0),
angle=None,
),
TrackItem(
when=datetime.datetime(
2020, 1, 1, 0, 20, tzinfo=tzutc(),
2020,
1,
1,
0,
20,
tzinfo=tzutc(),
),
coord=geo.Point(1.0, 1.0),
angle=None,
Expand Down Expand Up @@ -384,14 +404,26 @@ def test_multitrack(self) -> None:
track_items=[
TrackItem(
when=datetime.datetime(
2010, 5, 28, 2, 2, 55, tzinfo=tzutc(),
2010,
5,
28,
2,
2,
55,
tzinfo=tzutc(),
),
coord=geo.Point(-122.203451, 37.374706, 141.800003),
angle=Angle(heading=1.0, tilt=2.0, roll=3.0),
),
TrackItem(
when=datetime.datetime(
2010, 5, 28, 2, 2, 56, tzinfo=tzutc(),
2010,
5,
28,
2,
2,
56,
tzinfo=tzutc(),
),
coord=geo.Point(-122.203329, 37.37478, 141.199997),
angle=Angle(heading=1.0, tilt=2.0, roll=3.0),
Expand Down
Loading
Loading