Skip to content

Commit

Permalink
refactor to use Self type annotation
Browse files Browse the repository at this point in the history
  • Loading branch information
cleder committed Apr 19, 2024
1 parent cb6754e commit 0fc438e
Show file tree
Hide file tree
Showing 8 changed files with 128 additions and 144 deletions.
6 changes: 4 additions & 2 deletions fastkml/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
from typing import Optional
from typing import cast

from typing_extensions import Self

from fastkml import config
from fastkml.enums import Verbosity
from fastkml.registry import registry
Expand Down Expand Up @@ -162,7 +164,7 @@ def class_from_element(
name_spaces: Optional[Dict[str, str]] = None,
element: Element,
strict: bool,
) -> "_XMLObject":
) -> Self:
"""Creates an XML object from an etree element."""
kwargs = cls._get_kwargs(
ns=ns,
Expand All @@ -182,7 +184,7 @@ def class_from_string(
ns: Optional[str] = None,
name_spaces: Optional[Dict[str, str]] = None,
strict: bool = True,
) -> "_XMLObject":
) -> Self:
"""
Creates a geometry object from a string.
Expand Down
10 changes: 5 additions & 5 deletions fastkml/kml.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
from typing import Union
from typing import cast

from typing_extensions import Self

from fastkml import config
from fastkml.base import _XMLObject
from fastkml.containers import Document
Expand Down Expand Up @@ -98,7 +100,7 @@ def etree_element(
Returns:
-------
Element: The Element object representing the KML element.
Element: The etree Element object representing the KML element.
"""
# self.ns may be empty, which leads to unprefixed kml elements.
Expand Down Expand Up @@ -146,7 +148,7 @@ def class_from_string(
ns: Optional[str] = None,
name_spaces: Optional[Dict[str, str]] = None,
strict: bool = True,
) -> _XMLObject:
) -> Self:
"""
Create a kml object from a string.
Expand All @@ -172,10 +174,8 @@ def class_from_string(
)
except TypeError:
element = config.etree.XML(string) # type: ignore[attr-defined]
if not element.tag.endswith("kml"):
raise TypeError
if ns is None:
ns = cast(str, element.tag.rstrip("kml"))
ns = cast(str, element.tag[:-3] if element.tag.endswith("kml") else "")
name_spaces = name_spaces or {}
name_spaces = {**config.NAME_SPACES, **name_spaces}
return cls.class_from_element(
Expand Down
49 changes: 18 additions & 31 deletions tests/geometries/linearring_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

"""Test the geometry classes."""
from typing import cast

import pygeoif.geometry as geo
import pytest
Expand Down Expand Up @@ -51,39 +50,30 @@ def test_to_string(self) -> None:

def test_from_string(self) -> None:
"""Test the from_string method."""
linear_ring = cast(
LinearRing,
LinearRing.class_from_string(
'<kml:LinearRing xmlns:kml="http://www.opengis.net/kml/2.2">'
"<kml:coordinates>0.000000,0.000000 1.000000,0.000000 1.0,1.0 "
"0.000000,0.000000</kml:coordinates>"
"</kml:LinearRing>",
),
linear_ring = LinearRing.class_from_string(
'<kml:LinearRing xmlns:kml="http://www.opengis.net/kml/2.2">'
"<kml:coordinates>0.000000,0.000000 1.000000,0.000000 1.0,1.0 "
"0.000000,0.000000</kml:coordinates>"
"</kml:LinearRing>",
)

assert linear_ring.geometry == geo.LinearRing(((0, 0), (1, 0), (1, 1), (0, 0)))

def test_empty_from_string(self) -> None:
"""Test the from_string method with an empty LinearRing."""
linear_ring = cast(
LinearRing,
LinearRing.class_from_string(
'<kml:LinearRing xmlns:kml="http://www.opengis.net/kml/2.2">'
"<kml:coordinates></kml:coordinates>"
"</kml:LinearRing>",
),
linear_ring = LinearRing.class_from_string(
'<kml:LinearRing xmlns:kml="http://www.opengis.net/kml/2.2">'
"<kml:coordinates></kml:coordinates>"
"</kml:LinearRing>",
)

assert linear_ring.geometry.is_empty

def test_no_coordinates_from_string(self) -> None:
"""Test the from_string method with an empty LinearRing."""
linear_ring = cast(
LinearRing,
LinearRing.class_from_string(
'<kml:LinearRing xmlns:kml="http://www.opengis.net/kml/2.2">'
"</kml:LinearRing>",
),
linear_ring = LinearRing.class_from_string(
'<kml:LinearRing xmlns:kml="http://www.opengis.net/kml/2.2">'
"</kml:LinearRing>",
)

assert linear_ring.geometry.is_empty
Expand All @@ -103,15 +93,12 @@ def test_from_string_invalid_coordinates_non_numerical(self) -> None:

def test_mixed_2d_3d_coordinates_from_string_relaxed(self) -> None:
"""Test the from_string method with mixed 2D and 3D coordinates."""
linear_ring = cast(
LinearRing,
LinearRing.class_from_string(
'<kml:LinearRing xmlns:kml="http://www.opengis.net/kml/2.2">'
"<kml:coordinates>0.000000,0.000000 1.000000,0.000000 1.0,1.0 "
"0.000000,0.000000 1.000000,2.000000,3.000000</kml:coordinates>"
"</kml:LinearRing>",
strict=False,
),
linear_ring = LinearRing.class_from_string(
'<kml:LinearRing xmlns:kml="http://www.opengis.net/kml/2.2">'
"<kml:coordinates>0.000000,0.000000 1.000000,0.000000 1.0,1.0 "
"0.000000,0.000000 1.000000,2.000000,3.000000</kml:coordinates>"
"</kml:LinearRing>",
strict=False,
)

assert not linear_ring
Expand Down
50 changes: 20 additions & 30 deletions tests/geometries/linestring_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

"""Test the geometry classes."""
from typing import cast

import pygeoif.geometry as geo
import pytest
Expand Down Expand Up @@ -51,17 +50,14 @@ def test_to_string(self) -> None:

def test_from_string(self) -> None:
"""Test the from_string method."""
linestring = cast(
LineString,
LineString.class_from_string(
'<LineString xmlns="http://www.opengis.net/kml/2.2">'
"<extrude>1</extrude>"
"<tessellate>1</tessellate>"
"<coordinates>"
"-122.364383,37.824664,0 -122.364152,37.824322,0"
"</coordinates>"
"</LineString>",
),
linestring = LineString.class_from_string(
'<LineString xmlns="http://www.opengis.net/kml/2.2">'
"<extrude>1</extrude>"
"<tessellate>1</tessellate>"
"<coordinates>"
"-122.364383,37.824664,0 -122.364152,37.824322,0"
"</coordinates>"
"</LineString>",
)

assert linestring.geometry == geo.LineString(
Expand Down Expand Up @@ -99,30 +95,24 @@ def test_mixed_2d_3d_coordinates_from_string_relaxed(self) -> None:

def test_empty_from_string(self) -> None:
"""Test the from_string method with an empty LineString."""
linestring = cast(
LineString,
LineString.class_from_string(
'<LineString xmlns="http://www.opengis.net/kml/2.2">'
"<extrude>1</extrude>"
"<tessellate>1</tessellate>"
"<coordinates>"
"</coordinates>"
"</LineString>",
),
linestring = LineString.class_from_string(
'<LineString xmlns="http://www.opengis.net/kml/2.2">'
"<extrude>1</extrude>"
"<tessellate>1</tessellate>"
"<coordinates>"
"</coordinates>"
"</LineString>",
)

assert linestring.geometry.is_empty

def test_no_coordinates_from_string(self) -> None:
"""Test the from_string method with no coordinates."""
linestring = cast(
LineString,
LineString.class_from_string(
'<LineString xmlns="http://www.opengis.net/kml/2.2">'
"<extrude>1</extrude>"
"<tessellate>1</tessellate>"
"</LineString>",
),
linestring = LineString.class_from_string(
'<LineString xmlns="http://www.opengis.net/kml/2.2">'
"<extrude>1</extrude>"
"<tessellate>1</tessellate>"
"</LineString>",
)

assert linestring.geometry.is_empty
Expand Down
55 changes: 21 additions & 34 deletions tests/geometries/point_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

"""Test the geometry classes."""
from typing import cast

import pygeoif.geometry as geo
import pytest
Expand Down Expand Up @@ -107,13 +106,10 @@ def test_to_string_empty_geometry(self) -> None:

def test_from_string_2d(self) -> None:
"""Test the from_string method for a 2 dimensional point."""
point = cast(
Point,
Point.class_from_string(
'<Point xmlns="http://www.opengis.net/kml/2.2">'
"<coordinates>1.000000,2.000000</coordinates>"
"</Point>",
),
point = Point.class_from_string(
'<Point xmlns="http://www.opengis.net/kml/2.2">'
"<coordinates>1.000000,2.000000</coordinates>"
"</Point>",
)

assert point.geometry == geo.Point(1, 2)
Expand All @@ -123,15 +119,12 @@ def test_from_string_2d(self) -> None:

def test_from_string_uppercase_altitude_mode_relaxed(self) -> None:
"""Test the from_string method for an uppercase altitude mode."""
point = cast(
Point,
Point.class_from_string(
'<Point xmlns="http://www.opengis.net/kml/2.2">'
"<altitudeMode>RELATIVETOGROUND</altitudeMode>"
"<coordinates>1.000000,2.000000</coordinates>"
"</Point>",
strict=False,
),
point = Point.class_from_string(
'<Point xmlns="http://www.opengis.net/kml/2.2">'
"<altitudeMode>RELATIVETOGROUND</altitudeMode>"
"<coordinates>1.000000,2.000000</coordinates>"
"</Point>",
strict=False,
)

assert point.geometry == geo.Point(1, 2)
Expand All @@ -152,16 +145,13 @@ def test_from_string_uppercase_altitude_mode_strict(self) -> None:

def test_from_string_3d(self) -> None:
"""Test the from_string method for a 3 dimensional point."""
point = cast(
Point,
Point.class_from_string(
'<Point xmlns="http://www.opengis.net/kml/2.2">'
"<extrude>1</extrude>"
"<tessellate>1</tessellate>"
"<altitudeMode>absolute</altitudeMode>"
"<coordinates>1.000000,2.000000,3.000000</coordinates>"
"</Point>",
),
point = Point.class_from_string(
'<Point xmlns="http://www.opengis.net/kml/2.2">'
"<extrude>1</extrude>"
"<tessellate>1</tessellate>"
"<altitudeMode>absolute</altitudeMode>"
"<coordinates>1.000000,2.000000,3.000000</coordinates>"
"</Point>",
)

assert point.geometry == geo.Point(1, 2, 3)
Expand All @@ -182,13 +172,10 @@ def test_empty_from_string(self) -> None:

def test_empty_from_string_relaxed(self) -> None:
"""Test that no error is raised when the geometry is empty and not strict."""
point = cast(
Point,
Point.class_from_string(
"<Point/>",
ns="",
strict=False,
),
point = Point.class_from_string(
"<Point/>",
ns="",
strict=False,
)

assert point.geometry is None
Expand Down
9 changes: 4 additions & 5 deletions tests/geometries/polygon_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

"""Test the geometry classes."""
from typing import cast

import pygeoif.geometry as geo
import pytest
Expand Down Expand Up @@ -75,7 +74,7 @@ def test_from_string_exterior_only(self) -> None:
</kml:outerBoundaryIs>
</kml:Polygon>"""

polygon2 = cast(Polygon, Polygon.class_from_string(doc))
polygon2 = Polygon.class_from_string(doc)

assert polygon2.geometry == geo.Polygon([(0, 0), (1, 0), (1, 1), (0, 0)])

Expand Down Expand Up @@ -140,7 +139,7 @@ def test_from_string_exterior_interior(self) -> None:
</kml:Polygon>
"""

polygon = cast(Polygon, Polygon.class_from_string(doc))
polygon = Polygon.class_from_string(doc)

assert polygon.geometry == geo.Polygon(
[(-1, -1), (2, -1), (2, 2), (-1, -1)],
Expand All @@ -164,7 +163,7 @@ def test_from_string_exterior_mixed_interior_relaxed(self) -> None:
</kml:Polygon>
"""

polygon = cast(Polygon, Polygon.class_from_string(doc, strict=False))
polygon = Polygon.class_from_string(doc, strict=False)

assert polygon.geometry == geo.Polygon(
((-1.0, -1.0), (2.0, -1.0), (2.0, 2.0), (-1.0, -1.0)),
Expand All @@ -177,7 +176,7 @@ def test_empty_polygon(self) -> None:
"<LinearRing><coordinates/></LinearRing></outerBoundaryIs></Polygon>"
)

polygon = cast(Polygon, Polygon.class_from_string(doc, ns=""))
polygon = Polygon.class_from_string(doc, ns="")

assert not polygon.geometry
assert polygon.to_string()
Expand Down

0 comments on commit 0fc438e

Please sign in to comment.