diff --git a/docs/working_with_kml.rst b/docs/working_with_kml.rst
index 0150953c..8cda819a 100644
--- a/docs/working_with_kml.rst
+++ b/docs/working_with_kml.rst
@@ -230,8 +230,8 @@ CascadingStyle element into a supported Style element.
13.96486261382906
0.0
0.0
- absolute
632.584179697442
+ absolute
#__managed_style_0D301BCC0014827EFCCB
diff --git a/fastkml/times.py b/fastkml/times.py
index 62b06fd9..e33c71b3 100644
--- a/fastkml/times.py
+++ b/fastkml/times.py
@@ -88,15 +88,30 @@ def __init__(
resolution: Optional[DateTimeResolution] = None,
) -> None:
"""Initialize a KmlDateTime object."""
- self.dt = dt
- self.resolution = resolution
if resolution is None:
# sourcery skip: swap-if-expression
- self.resolution = (
+ resolution = (
DateTimeResolution.date
if not isinstance(dt, datetime)
else DateTimeResolution.datetime
)
+ dt = (
+ dt.date()
+ if isinstance(dt, datetime) and resolution != DateTimeResolution.datetime
+ else dt
+ )
+ if resolution == DateTimeResolution.year:
+ self.dt = date(dt.year, 1, 1)
+ elif resolution == DateTimeResolution.year_month:
+ self.dt = date(dt.year, dt.month, 1)
+ else:
+ self.dt = dt
+ self.resolution = (
+ DateTimeResolution.date
+ if not isinstance(self.dt, datetime)
+ and resolution == DateTimeResolution.datetime
+ else resolution
+ )
def __repr__(self) -> str:
"""Create a string (c)representation for KmlDateTime."""
@@ -142,7 +157,7 @@ def parse(cls, datestr: str) -> Optional["KmlDateTime"]:
year = int(year_month_day_match.group("year"))
month = int(year_month_day_match.group("month") or 1)
day = int(year_month_day_match.group("day") or 1)
- dt = arrow.get(year, month, day).datetime
+ dt = date(year, month, day)
resolution = DateTimeResolution.date
if year_month_day_match.group("day") is None:
resolution = DateTimeResolution.year_month
diff --git a/fastkml/views.py b/fastkml/views.py
index 5e56d545..97b3ea66 100644
--- a/fastkml/views.py
+++ b/fastkml/views.py
@@ -18,7 +18,6 @@
from typing import Any
from typing import Dict
from typing import Optional
-from typing import Union
from fastkml import config
from fastkml.base import _XMLObject
@@ -35,8 +34,8 @@
from fastkml.mixins import TimeMixin
from fastkml.registry import RegistryItem
from fastkml.registry import registry
-from fastkml.times import TimeSpan
-from fastkml.times import TimeStamp
+
+__all__ = ["Camera", "LatLonAltBox", "Lod", "LookAt", "Region"]
logger = logging.getLogger(__name__)
@@ -100,7 +99,6 @@ def __init__(
heading: Optional[float] = None,
tilt: Optional[float] = None,
altitude_mode: Optional[AltitudeMode] = None,
- time_primitive: Union[TimeSpan, TimeStamp, None] = None,
**kwargs: Any,
) -> None:
"""
@@ -128,8 +126,6 @@ def __init__(
The tilt angle of the view.
altitude_mode : Optional[AltitudeMode]
The altitude mode of the view.
- time_primitive : Union[TimeSpan, TimeStamp, None]
- The time primitive associated with the view.
kwargs : Any
Additional keyword arguments.
@@ -151,7 +147,6 @@ def __init__(
self.heading = heading
self.tilt = tilt
self.altitude_mode = altitude_mode
- self.times = time_primitive
def __repr__(self) -> str:
"""Create a string (c)representation for _AbstractView."""
@@ -167,7 +162,6 @@ def __repr__(self) -> str:
f"heading={self.heading!r}, "
f"tilt={self.tilt!r}, "
f"altitude_mode={self.altitude_mode}, "
- f"time_primitive={self.times!r}, "
f"**{self._get_splat()!r},"
")"
)
@@ -233,29 +227,6 @@ def __repr__(self) -> str:
default=0.0,
),
)
-registry.register(
- _AbstractView,
- RegistryItem(
- ns_ids=("kml",),
- attr_name="altitude_mode",
- node_name="altitudeMode",
- classes=(AltitudeMode,),
- get_kwarg=subelement_enum_kwarg,
- set_element=enum_subelement,
- default=AltitudeMode.clamp_to_ground,
- ),
-)
-registry.register(
- _AbstractView,
- RegistryItem(
- ns_ids=("kml",),
- attr_name="time_primitive",
- node_name="TimeStamp",
- classes=(TimeSpan, TimeStamp),
- get_kwarg=xml_subelement_kwarg,
- set_element=xml_subelement,
- ),
-)
class Camera(_AbstractView):
@@ -300,7 +271,6 @@ def __init__(
tilt: Optional[float] = None,
roll: Optional[float] = None,
altitude_mode: Optional[AltitudeMode] = None,
- time_primitive: Union[TimeSpan, TimeStamp, None] = None,
**kwargs: Any,
) -> None:
"""
@@ -319,8 +289,6 @@ def __init__(
tilt (Optional[float]): The tilt of the view.
roll (Optional[float]): The roll of the view.
altitude_mode (AltitudeMode): The altitude mode of the view.
- time_primitive (Union[TimeSpan, TimeStamp, None]): The time primitive of the
- view.
**kwargs (Any): Additional keyword arguments.
Returns:
@@ -339,7 +307,6 @@ def __init__(
heading=heading,
tilt=tilt,
altitude_mode=altitude_mode,
- time_primitive=time_primitive,
**kwargs,
)
self.roll = roll
@@ -359,7 +326,6 @@ def __repr__(self) -> str:
f"tilt={self.tilt!r}, "
f"roll={self.roll!r}, "
f"altitude_mode={self.altitude_mode}, "
- f"time_primitive={self.times!r}, "
f"**{self._get_splat()!r},"
")"
)
@@ -377,6 +343,18 @@ def __repr__(self) -> str:
default=0.0,
),
)
+registry.register(
+ Camera,
+ RegistryItem(
+ ns_ids=("kml", "gx", ""),
+ attr_name="altitude_mode",
+ node_name="altitudeMode",
+ classes=(AltitudeMode,),
+ get_kwarg=subelement_enum_kwarg,
+ set_element=enum_subelement,
+ default=AltitudeMode.clamp_to_ground,
+ ),
+)
class LookAt(_AbstractView):
@@ -407,7 +385,6 @@ def __init__(
tilt: Optional[float] = None,
range: Optional[float] = None,
altitude_mode: Optional[AltitudeMode] = None,
- time_primitive: Union[TimeSpan, TimeStamp, None] = None,
**kwargs: Any,
) -> None:
"""
@@ -427,7 +404,6 @@ def __init__(
range (Optional[float]): The range value.
altitude_mode (AltitudeMode): The altitude mode. Defaults to
AltitudeMode.relative_to_ground.
- time_primitive (Union[TimeSpan, TimeStamp, None]): The time primitive.
**kwargs (Any): Additional keyword arguments.
Returns:
@@ -446,7 +422,6 @@ def __init__(
heading=heading,
tilt=tilt,
altitude_mode=altitude_mode,
- time_primitive=time_primitive,
**kwargs,
)
self.range = range
@@ -466,7 +441,6 @@ def __repr__(self) -> str:
f"tilt={self.tilt!r}, "
f"range={self.range!r}, "
f"altitude_mode={self.altitude_mode}, "
- f"time_primitive={self.times!r}, "
f"**{self._get_splat()!r},"
")"
)
@@ -483,6 +457,18 @@ def __repr__(self) -> str:
set_element=float_subelement,
),
)
+registry.register(
+ LookAt,
+ RegistryItem(
+ ns_ids=("kml", "gx", ""),
+ attr_name="altitude_mode",
+ node_name="altitudeMode",
+ classes=(AltitudeMode,),
+ get_kwarg=subelement_enum_kwarg,
+ set_element=enum_subelement,
+ default=AltitudeMode.clamp_to_ground,
+ ),
+)
class LatLonAltBox(_XMLObject):
@@ -653,7 +639,7 @@ def __bool__(self) -> bool:
registry.register(
LatLonAltBox,
RegistryItem(
- ns_ids=("kml",),
+ ns_ids=("kml", "gx", ""),
attr_name="altitude_mode",
node_name="altitudeMode",
classes=(AltitudeMode,),
@@ -701,10 +687,10 @@ def __init__(
ns (Optional[str]): The namespace for the view.
name_spaces (Optional[Dict[str, str]]): The dictionary of namespace prefixes
and URIs.
- min_lod_pixels (Optional[float]): The minimum level of detail in pixels.
- max_lod_pixels (Optional[float]): The maximum level of detail in pixels.
- min_fade_extent (Optional[float]): The minimum fade extent in pixels.
- max_fade_extent (Optional[float]): The maximum fade extent in pixels.
+ min_lod_pixels (Optional[int]): The minimum level of detail in pixels.
+ max_lod_pixels (Optional[int]): The maximum level of detail in pixels.
+ min_fade_extent (Optional[int]): The minimum fade extent in pixels.
+ max_fade_extent (Optional[int]): The maximum fade extent in pixels.
**kwargs (Any): Additional keyword arguments.
Returns:
@@ -775,8 +761,8 @@ def __bool__(self) -> bool:
attr_name="min_fade_extent",
node_name="minFadeExtent",
classes=(float,),
- get_kwarg=subelement_float_kwarg,
- set_element=float_subelement,
+ get_kwarg=subelement_int_kwarg,
+ set_element=int_subelement,
default=0,
),
)
@@ -787,8 +773,8 @@ def __bool__(self) -> bool:
attr_name="max_fade_extent",
node_name="maxFadeExtent",
classes=(float,),
- get_kwarg=subelement_float_kwarg,
- set_element=float_subelement,
+ get_kwarg=subelement_int_kwarg,
+ set_element=int_subelement,
default=0,
),
)
@@ -902,10 +888,3 @@ def __bool__(self) -> bool:
set_element=xml_subelement,
),
)
-
-
-__all__ = [
- "Camera",
- "LookAt",
- "Region",
-]
diff --git a/tests/hypothesis/geometry_test.py b/tests/hypothesis/geometry_test.py
index 0e85323d..22dd8d65 100644
--- a/tests/hypothesis/geometry_test.py
+++ b/tests/hypothesis/geometry_test.py
@@ -69,11 +69,7 @@
altitude_mode=st.one_of(
st.none(),
st.sampled_from(
- (
- AltitudeMode.absolute,
- AltitudeMode.clamp_to_ground,
- AltitudeMode.relative_to_ground,
- ),
+ AltitudeMode,
),
),
)
diff --git a/tests/hypothesis/gx_test.py b/tests/hypothesis/gx_test.py
index a9c184cd..823aae4e 100644
--- a/tests/hypothesis/gx_test.py
+++ b/tests/hypothesis/gx_test.py
@@ -14,12 +14,10 @@
# along with this library; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
"""Test gx Track and MultiTrack."""
-import datetime
import typing
from hypothesis import given
from hypothesis import strategies as st
-from hypothesis.extra.dateutil import timezones
from pygeoif.hypothesis.strategies import epsg4326
from pygeoif.hypothesis.strategies import points
@@ -29,12 +27,12 @@
import fastkml.types
from fastkml.gx import Angle
from fastkml.gx import TrackItem
-from fastkml.times import KmlDateTime
from tests.base import Lxml
from tests.hypothesis.common import assert_repr_roundtrip
from tests.hypothesis.common import assert_str_roundtrip
from tests.hypothesis.common import assert_str_roundtrip_terse
from tests.hypothesis.common import assert_str_roundtrip_verbose
+from tests.hypothesis.strategies import kml_datetimes
from tests.hypothesis.strategies import nc_name
track_items = st.builds(
@@ -51,15 +49,7 @@
),
),
coord=points(srs=epsg4326),
- when=st.builds(
- KmlDateTime,
- dt=st.datetimes(
- allow_imaginary=False,
- timezones=timezones(),
- min_value=datetime.datetime(2000, 1, 1), # noqa: DTZ001
- max_value=datetime.datetime(2050, 1, 1), # noqa: DTZ001
- ),
- ),
+ when=kml_datetimes(),
)
diff --git a/tests/hypothesis/multi_geometry_test.py b/tests/hypothesis/multi_geometry_test.py
index f54a56f6..e20950f3 100644
--- a/tests/hypothesis/multi_geometry_test.py
+++ b/tests/hypothesis/multi_geometry_test.py
@@ -65,13 +65,7 @@
tessellate=st.one_of(st.none(), st.booleans()),
altitude_mode=st.one_of(
st.none(),
- st.sampled_from(
- (
- AltitudeMode.absolute,
- AltitudeMode.clamp_to_ground,
- AltitudeMode.relative_to_ground,
- ),
- ),
+ st.sampled_from(AltitudeMode),
),
)
diff --git a/tests/hypothesis/strategies.py b/tests/hypothesis/strategies.py
index 3e154cea..8f6cd19c 100644
--- a/tests/hypothesis/strategies.py
+++ b/tests/hypothesis/strategies.py
@@ -15,6 +15,7 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
"""Custom hypothesis strategies for testing."""
+import datetime
import re
import string
from functools import partial
@@ -22,6 +23,10 @@
from urllib.parse import urlencode
from hypothesis import strategies as st
+from hypothesis.extra.dateutil import timezones
+
+import fastkml.enums
+from fastkml.times import KmlDateTime
ID_TEXT: Final = string.ascii_letters + string.digits + ".-_"
nc_name = partial(
@@ -48,6 +53,27 @@
alphabet=st.characters(min_codepoint=1, blacklist_categories=("Cc", "Cs")),
)
+kml_datetimes = partial(
+ st.builds,
+ KmlDateTime,
+ dt=st.one_of(
+ st.dates(
+ min_value=datetime.date(2000, 1, 1),
+ max_value=datetime.date(2050, 1, 1),
+ ),
+ st.datetimes(
+ allow_imaginary=False,
+ timezones=timezones(),
+ min_value=datetime.datetime(2000, 1, 1), # noqa: DTZ001
+ max_value=datetime.datetime(2050, 1, 1), # noqa: DTZ001
+ ),
+ ),
+ resolution=st.one_of(
+ st.none(),
+ st.one_of(st.none(), st.sampled_from(fastkml.enums.DateTimeResolution)),
+ ),
+)
+
@st.composite
def query_strings(draw: st.DrawFn) -> str:
diff --git a/tests/hypothesis/times_test.py b/tests/hypothesis/times_test.py
new file mode 100644
index 00000000..b7b1ab71
--- /dev/null
+++ b/tests/hypothesis/times_test.py
@@ -0,0 +1,76 @@
+# Copyright (C) 2024 Christian Ledermann
+#
+# This library is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by the Free
+# Software Foundation; either version 2.1 of the License, or (at your option)
+# any later version.
+#
+# This library is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this library; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+"""
+Property-based tests for the times module.
+
+These tests use the hypothesis library to generate random input for the
+functions under test. The tests are run with pytest.
+"""
+import typing
+
+from hypothesis import given
+from hypothesis import strategies as st
+
+import fastkml
+import fastkml.enums
+import fastkml.times
+from tests.base import Lxml
+from tests.hypothesis.common import assert_repr_roundtrip
+from tests.hypothesis.common import assert_str_roundtrip
+from tests.hypothesis.common import assert_str_roundtrip_terse
+from tests.hypothesis.common import assert_str_roundtrip_verbose
+from tests.hypothesis.strategies import kml_datetimes
+from tests.hypothesis.strategies import nc_name
+
+
+class TestTimes(Lxml):
+ @given(
+ id=st.one_of(st.none(), nc_name()),
+ target_id=st.one_of(st.none(), nc_name()),
+ timestamp=st.one_of(st.none(), kml_datetimes()),
+ )
+ def test_fuzz_time_stamp(
+ self,
+ id: typing.Optional[str],
+ target_id: typing.Optional[str],
+ timestamp: typing.Optional[fastkml.times.KmlDateTime],
+ ) -> None:
+ time_stamp = fastkml.TimeStamp(id=id, target_id=target_id, timestamp=timestamp)
+
+ assert_repr_roundtrip(time_stamp)
+ assert_str_roundtrip(time_stamp)
+ assert_str_roundtrip_terse(time_stamp)
+ assert_str_roundtrip_verbose(time_stamp)
+
+ @given(
+ id=st.one_of(st.none(), nc_name()),
+ target_id=st.one_of(st.none(), nc_name()),
+ begin=st.one_of(st.none(), kml_datetimes()),
+ end=st.one_of(st.none(), kml_datetimes()),
+ )
+ def test_fuzz_time_span(
+ self,
+ id: typing.Optional[str],
+ target_id: typing.Optional[str],
+ begin: typing.Optional[fastkml.times.KmlDateTime],
+ end: typing.Optional[fastkml.times.KmlDateTime],
+ ) -> None:
+ time_span = fastkml.TimeSpan(id=id, target_id=target_id, begin=begin, end=end)
+
+ assert_repr_roundtrip(time_span)
+ assert_str_roundtrip(time_span)
+ assert_str_roundtrip_terse(time_span)
+ assert_str_roundtrip_verbose(time_span)
diff --git a/tests/hypothesis/views_test.py b/tests/hypothesis/views_test.py
new file mode 100644
index 00000000..bfdc8f8a
--- /dev/null
+++ b/tests/hypothesis/views_test.py
@@ -0,0 +1,285 @@
+# Copyright (C) 2024 Christian Ledermann
+#
+# This library is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by the Free
+# Software Foundation; either version 2.1 of the License, or (at your option)
+# any later version.
+#
+# This library is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this library; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+"""Property-based tests for the views module."""
+import typing
+from functools import partial
+
+from hypothesis import given
+from hypothesis import strategies as st
+
+import fastkml
+import fastkml.enums
+import fastkml.views
+from fastkml.views import LatLonAltBox
+from fastkml.views import Lod
+from tests.base import Lxml
+from tests.hypothesis.common import assert_repr_roundtrip
+from tests.hypothesis.common import assert_str_roundtrip
+from tests.hypothesis.common import assert_str_roundtrip_terse
+from tests.hypothesis.common import assert_str_roundtrip_verbose
+from tests.hypothesis.strategies import nc_name
+
+lods = partial(
+ st.builds,
+ Lod,
+ min_lod_pixels=st.integers(),
+ max_lod_pixels=st.integers(),
+ min_fade_extent=st.integers(),
+ max_fade_extent=st.integers(),
+)
+
+lat_lon_alt_boxes = partial(
+ st.builds,
+ LatLonAltBox,
+ north=st.floats(allow_nan=False, allow_infinity=False, min_value=0, max_value=90),
+ south=st.floats(allow_nan=False, allow_infinity=False, min_value=0, max_value=90),
+ east=st.floats(allow_nan=False, allow_infinity=False, min_value=0, max_value=180),
+ west=st.floats(allow_nan=False, allow_infinity=False, min_value=0, max_value=180),
+ min_altitude=st.floats(allow_nan=False, allow_infinity=False).filter(
+ lambda x: x != 0,
+ ),
+ max_altitude=st.floats(allow_nan=False, allow_infinity=False).filter(
+ lambda x: x != 0,
+ ),
+ altitude_mode=st.sampled_from(fastkml.enums.AltitudeMode),
+)
+
+common_view = partial(
+ given,
+ id=st.one_of(st.none(), nc_name()),
+ target_id=st.one_of(st.none(), nc_name()),
+ longitude=st.one_of(
+ st.none(),
+ st.floats(
+ allow_nan=False,
+ allow_infinity=False,
+ min_value=-180,
+ max_value=180,
+ ).filter(lambda x: x != 0),
+ ),
+ latitude=st.one_of(
+ st.none(),
+ st.floats(
+ allow_nan=False,
+ allow_infinity=False,
+ min_value=-90,
+ max_value=90,
+ ).filter(lambda x: x != 0),
+ ),
+ altitude=st.one_of(
+ st.none(),
+ st.floats(allow_nan=False, allow_infinity=False).filter(lambda x: x != 0),
+ ),
+ heading=st.one_of(
+ st.none(),
+ st.floats(allow_nan=False, allow_infinity=False, min_value=0, max_value=360),
+ ),
+ tilt=st.one_of(
+ st.none(),
+ st.floats(allow_nan=False, allow_infinity=False, min_value=0, max_value=180),
+ ),
+ altitude_mode=st.one_of(st.none(), st.sampled_from(fastkml.enums.AltitudeMode)),
+)
+
+
+class TestLxml(Lxml):
+
+ @given(
+ min_lod_pixels=st.one_of(st.none(), st.integers()),
+ max_lod_pixels=st.one_of(st.none(), st.integers()),
+ min_fade_extent=st.one_of(st.none(), st.integers()),
+ max_fade_extent=st.one_of(st.none(), st.integers()),
+ )
+ def test_fuzz_lod(
+ self,
+ min_lod_pixels: typing.Optional[int],
+ max_lod_pixels: typing.Optional[int],
+ min_fade_extent: typing.Optional[int],
+ max_fade_extent: typing.Optional[int],
+ ) -> None:
+ lod = fastkml.views.Lod(
+ min_lod_pixels=min_lod_pixels,
+ max_lod_pixels=max_lod_pixels,
+ min_fade_extent=min_fade_extent,
+ max_fade_extent=max_fade_extent,
+ )
+
+ assert_repr_roundtrip(lod)
+ assert_str_roundtrip(lod)
+ assert_str_roundtrip_terse(lod)
+ assert_str_roundtrip_verbose(lod)
+
+ @given(
+ north=st.one_of(
+ st.none(),
+ st.floats(allow_nan=False, allow_infinity=False, min_value=0, max_value=90),
+ ),
+ south=st.one_of(
+ st.none(),
+ st.floats(allow_nan=False, allow_infinity=False, min_value=0, max_value=90),
+ ),
+ east=st.one_of(
+ st.none(),
+ st.floats(
+ allow_nan=False,
+ allow_infinity=False,
+ min_value=0,
+ max_value=180,
+ ),
+ ),
+ west=st.one_of(
+ st.none(),
+ st.floats(
+ allow_nan=False,
+ allow_infinity=False,
+ min_value=0,
+ max_value=180,
+ ),
+ ),
+ min_altitude=st.one_of(
+ st.none(),
+ st.floats(allow_nan=False, allow_infinity=False).filter(lambda x: x != 0),
+ ),
+ max_altitude=st.one_of(
+ st.none(),
+ st.floats(allow_nan=False, allow_infinity=False).filter(lambda x: x != 0),
+ ),
+ altitude_mode=st.one_of(st.none(), st.sampled_from(fastkml.enums.AltitudeMode)),
+ )
+ def test_fuzz_lat_lon_alt_box(
+ self,
+ north: typing.Optional[float],
+ south: typing.Optional[float],
+ east: typing.Optional[float],
+ west: typing.Optional[float],
+ min_altitude: typing.Optional[float],
+ max_altitude: typing.Optional[float],
+ altitude_mode: typing.Optional[fastkml.enums.AltitudeMode],
+ ) -> None:
+ lat_lon_alt_box = fastkml.views.LatLonAltBox(
+ north=north,
+ south=south,
+ east=east,
+ west=west,
+ min_altitude=min_altitude,
+ max_altitude=max_altitude,
+ altitude_mode=altitude_mode,
+ )
+
+ assert_repr_roundtrip(lat_lon_alt_box)
+ assert_str_roundtrip(lat_lon_alt_box)
+ assert_str_roundtrip_terse(lat_lon_alt_box)
+ assert_str_roundtrip_verbose(lat_lon_alt_box)
+
+ @given(
+ id=st.one_of(st.none(), nc_name()),
+ target_id=st.one_of(st.none(), nc_name()),
+ lat_lon_alt_box=st.one_of(st.none(), lat_lon_alt_boxes()),
+ lod=st.one_of(st.none(), lods()),
+ )
+ def test_fuzz_region(
+ self,
+ id: typing.Optional[str],
+ target_id: typing.Optional[str],
+ lat_lon_alt_box: typing.Optional[fastkml.views.LatLonAltBox],
+ lod: typing.Optional[fastkml.views.Lod],
+ ) -> None:
+ region = fastkml.views.Region(
+ id=id,
+ target_id=target_id,
+ lat_lon_alt_box=lat_lon_alt_box,
+ lod=lod,
+ )
+
+ assert_repr_roundtrip(region)
+ assert_str_roundtrip(region)
+ assert_str_roundtrip_terse(region)
+ assert_str_roundtrip_verbose(region)
+
+ @common_view(
+ roll=st.one_of(
+ st.none(),
+ st.floats(
+ allow_nan=False,
+ allow_infinity=False,
+ min_value=-180,
+ max_value=180,
+ ).filter(lambda x: x != 0),
+ ),
+ )
+ def test_fuzz_camera(
+ self,
+ id: typing.Optional[str],
+ target_id: typing.Optional[str],
+ longitude: typing.Optional[float],
+ latitude: typing.Optional[float],
+ altitude: typing.Optional[float],
+ heading: typing.Optional[float],
+ tilt: typing.Optional[float],
+ altitude_mode: typing.Optional[fastkml.enums.AltitudeMode],
+ roll: typing.Optional[float],
+ ) -> None:
+ camera = fastkml.Camera(
+ id=id,
+ target_id=target_id,
+ longitude=longitude,
+ latitude=latitude,
+ altitude=altitude,
+ heading=heading,
+ tilt=tilt,
+ roll=roll,
+ altitude_mode=altitude_mode,
+ )
+
+ assert_repr_roundtrip(camera)
+ assert_str_roundtrip(camera)
+ assert_str_roundtrip_terse(camera)
+ assert_str_roundtrip_verbose(camera)
+
+ @common_view(
+ range=st.one_of(
+ st.none(),
+ st.floats(allow_nan=False, allow_infinity=False).filter(lambda x: x != 0),
+ ),
+ )
+ def test_fuzz_look_at(
+ self,
+ id: typing.Optional[str],
+ target_id: typing.Optional[str],
+ longitude: typing.Optional[float],
+ latitude: typing.Optional[float],
+ altitude: typing.Optional[float],
+ heading: typing.Optional[float],
+ tilt: typing.Optional[float],
+ altitude_mode: typing.Optional[fastkml.enums.AltitudeMode],
+ range: typing.Optional[float],
+ ) -> None:
+ look_at = fastkml.LookAt(
+ id=id,
+ target_id=target_id,
+ longitude=longitude,
+ latitude=latitude,
+ altitude=altitude,
+ heading=heading,
+ tilt=tilt,
+ range=range,
+ altitude_mode=altitude_mode,
+ )
+
+ assert_repr_roundtrip(look_at)
+ assert_str_roundtrip(look_at)
+ assert_str_roundtrip_terse(look_at)
+ assert_str_roundtrip_verbose(look_at)
diff --git a/tests/repr_eq_test.py b/tests/repr_eq_test.py
index 65d827bf..2023f4d7 100644
--- a/tests/repr_eq_test.py
+++ b/tests/repr_eq_test.py
@@ -340,7 +340,6 @@ class TestRepr(StdLibrary):
tilt=61.61116895973212,
range=359.3753895394523,
altitude_mode=AltitudeMode.relative_to_ground,
- time_primitive=None,
),
times=None,
style_url=None,
@@ -1485,7 +1484,6 @@ class TestRepr(StdLibrary):
tilt=51.96,
range=301.9568,
altitude_mode=AltitudeMode.relative_to_ground,
- time_primitive=None,
),
times=None,
style_url=None,
diff --git a/tests/times_test.py b/tests/times_test.py
index 1876a003..201ba02d 100644
--- a/tests/times_test.py
+++ b/tests/times_test.py
@@ -102,7 +102,7 @@ def test_parse_year(self) -> None:
assert dt
assert dt.resolution == DateTimeResolution.year
- assert dt.dt == datetime.datetime(2000, 1, 1, tzinfo=tzutc())
+ assert dt.dt == datetime.date(2000, 1, 1)
def test_parse_year_0(self) -> None:
with pytest.raises(
@@ -116,14 +116,14 @@ def test_parse_year_month(self) -> None:
assert dt
assert dt.resolution == DateTimeResolution.year_month
- assert dt.dt == datetime.datetime(2000, 3, 1, tzinfo=tzutc())
+ assert dt.dt == datetime.date(2000, 3, 1)
def test_parse_year_month_no_dash(self) -> None:
dt = KmlDateTime.parse("200004")
assert dt
assert dt.resolution == DateTimeResolution.year_month
- assert dt.dt == datetime.datetime(2000, 4, 1, tzinfo=tzutc())
+ assert dt.dt == datetime.date(2000, 4, 1)
def test_parse_year_month_0(self) -> None:
with pytest.raises(ValueError, match="month must be in 1..12"):
@@ -138,14 +138,14 @@ def test_parse_year_month_day(self) -> None:
assert dt
assert dt.resolution == DateTimeResolution.date
- assert dt.dt == datetime.datetime(2000, 3, 1, tzinfo=tzutc())
+ assert dt.dt == datetime.date(2000, 3, 1)
def test_parse_year_month_day_no_dash(self) -> None:
dt = KmlDateTime.parse("20000401")
assert dt
assert dt.resolution == DateTimeResolution.date
- assert dt.dt == datetime.datetime(2000, 4, 1, tzinfo=tzutc())
+ assert dt.dt == datetime.date(2000, 4, 1)
def test_parse_year_month_day_0(self) -> None:
with pytest.raises(
@@ -295,7 +295,7 @@ def test_read_timestamp_year(self) -> None:
assert ts.timestamp
assert ts.timestamp.resolution == DateTimeResolution.year
- assert ts.timestamp.dt == datetime.datetime(1997, 1, 1, 0, 0, tzinfo=tzutc())
+ assert ts.timestamp.dt == datetime.date(1997, 1, 1)
def test_read_timestamp_year_month(self) -> None:
doc = """
@@ -308,7 +308,7 @@ def test_read_timestamp_year_month(self) -> None:
assert ts.timestamp
assert ts.timestamp.resolution == DateTimeResolution.year_month
- assert ts.timestamp.dt == datetime.datetime(1997, 7, 1, 0, 0, tzinfo=tzutc())
+ assert ts.timestamp.dt == datetime.date(1997, 7, 1)
def test_read_timestamp_ym_no_hyphen(self) -> None:
doc = """
@@ -321,7 +321,7 @@ def test_read_timestamp_ym_no_hyphen(self) -> None:
assert ts.timestamp
assert ts.timestamp.resolution == DateTimeResolution.year_month
- assert ts.timestamp.dt == datetime.datetime(1998, 8, 1, 0, 0, tzinfo=tzutc())
+ assert ts.timestamp.dt == datetime.date(1998, 8, 1)
def test_read_timestamp_ymd(self) -> None:
doc = """
@@ -334,7 +334,7 @@ def test_read_timestamp_ymd(self) -> None:
assert ts.timestamp
assert ts.timestamp.resolution == DateTimeResolution.date
- assert ts.timestamp.dt == datetime.datetime(1997, 7, 16, 0, 0, tzinfo=tzutc())
+ assert ts.timestamp.dt == datetime.date(1997, 7, 16)
def test_read_timestamp_utc(self) -> None:
# dateTime (YYYY-MM-DDThh:mm:ssZ)
@@ -393,7 +393,7 @@ def test_read_timespan(self) -> None:
assert ts.begin
assert ts.begin.resolution == DateTimeResolution.date
- assert ts.begin.dt == datetime.datetime(1876, 8, 1, 0, 0, tzinfo=tzutc())
+ assert ts.begin.dt == datetime.date(1876, 8, 1)
assert ts.end
assert ts.end.resolution == DateTimeResolution.datetime
assert ts.end.dt == datetime.datetime(1997, 7, 16, 7, 30, 15, tzinfo=tzutc())
@@ -415,7 +415,7 @@ def test_feature_fromstring(self) -> None:
assert d.time_stamp is None
assert d.begin
- assert d.begin.dt == datetime.datetime(1876, 8, 1, 0, 0, tzinfo=tzutc())
+ assert d.begin.dt == datetime.date(1876, 8, 1)
assert d.end
assert d.end.dt == datetime.datetime(1997, 7, 16, 7, 30, 15, tzinfo=tzutc())
diff --git a/tests/views_test.py b/tests/views_test.py
index 097dfaae..68231f15 100644
--- a/tests/views_test.py
+++ b/tests/views_test.py
@@ -16,11 +16,7 @@
"""Test the (Abstract)Views classes."""
-import datetime
-from dateutil.tz import tzutc
-
-from fastkml import times
from fastkml import views
from fastkml.enums import AltitudeMode
from tests.base import Lxml
@@ -32,12 +28,6 @@ class TestStdLibrary(StdLibrary):
def test_create_camera(self) -> None:
"""Test the creation of a camera."""
- time_span = times.TimeSpan(
- id="time-span-id",
- begin=times.KmlDateTime(datetime.datetime(2019, 1, 1, tzinfo=tzutc())),
- end=times.KmlDateTime(datetime.datetime(2019, 1, 2, tzinfo=tzutc())),
- )
-
camera = views.Camera(
id="cam-id",
target_id="target-cam-id",
@@ -48,7 +38,6 @@ def test_create_camera(self) -> None:
altitude_mode=AltitudeMode("relativeToGround"),
latitude=50,
longitude=60,
- time_primitive=time_span,
)
assert camera.heading == 10
@@ -60,12 +49,6 @@ def test_create_camera(self) -> None:
assert camera.longitude == 60
assert camera.id == "cam-id"
assert camera.target_id == "target-cam-id"
- assert camera.begin == times.KmlDateTime(
- datetime.datetime(2019, 1, 1, tzinfo=tzutc()),
- )
- assert camera.end == times.KmlDateTime(
- datetime.datetime(2019, 1, 2, tzinfo=tzutc()),
- )
assert camera.to_string()
def test_camera_read(self) -> None:
@@ -73,10 +56,6 @@ def test_camera_read(self) -> None:
camera_xml = (
''
- ''
- "2019-01-01T00:00:00"
- "2019-01-02T00:00:00"
- ""
"60"
"50"
"40"
@@ -98,18 +77,8 @@ def test_camera_read(self) -> None:
assert camera.longitude == 60
assert camera.id == "cam-id"
assert camera.target_id == "target-cam-id"
- assert camera.begin == times.KmlDateTime(
- datetime.datetime(2019, 1, 1, tzinfo=tzutc()),
- )
- assert camera.end == times.KmlDateTime(
- datetime.datetime(2019, 1, 2, tzinfo=tzutc()),
- )
def test_create_look_at(self) -> None:
- time_stamp = times.TimeStamp(
- id="time-span-id",
- timestamp=times.KmlDateTime(datetime.datetime(2019, 1, 1, tzinfo=tzutc())),
- )
look_at = views.LookAt(
id="look-at-id",
@@ -120,7 +89,6 @@ def test_create_look_at(self) -> None:
altitude_mode=AltitudeMode("relativeToGround"),
latitude=50,
longitude=60,
- time_primitive=time_stamp,
)
assert look_at.heading == 10
@@ -131,14 +99,6 @@ def test_create_look_at(self) -> None:
assert look_at.longitude == 60
assert look_at.id == "look-at-id"
assert look_at.target_id == "target-look-at-id"
- assert look_at.times.timestamp.dt == datetime.datetime(
- 2019,
- 1,
- 1,
- tzinfo=tzutc(),
- )
- assert look_at.begin is None
- assert look_at.end is None
assert look_at.to_string()
def test_look_at_read(self) -> None:
@@ -150,9 +110,6 @@ def test_look_at_read(self) -> None:
"10"
"20"
"relativeToGround"
- ''
- "2019-01-01T00:00:00"
- ""
"30"
""
)
@@ -166,14 +123,6 @@ def test_look_at_read(self) -> None:
assert look_at.longitude == 60
assert look_at.id == "look-at-id"
assert look_at.target_id == "target-look-at-id"
- assert look_at.times.timestamp.dt == datetime.datetime(
- 2019,
- 1,
- 1,
- tzinfo=tzutc(),
- )
- assert look_at.begin is None
- assert look_at.end is None
def test_region_with_all_optional_parameters(self) -> None:
"""Region object can be initialized with all optional parameters."""