From 4372e39819bc5a2f374da05c91d3047409b41aa0 Mon Sep 17 00:00:00 2001 From: Christian Ledermann Date: Fri, 13 Oct 2023 11:17:13 +0100 Subject: [PATCH] improve typing and tests --- pygeoif/factories.py | 2 +- pygeoif/geometry.py | 4 +++- tests/test_base.py | 2 +- tests/test_factories.py | 38 ++++++++++++++++++++++++++++++++++++-- tests/test_line.py | 3 +++ tests/test_linear_ring.py | 1 + tests/test_point.py | 1 + 7 files changed, 46 insertions(+), 5 deletions(-) diff --git a/pygeoif/factories.py b/pygeoif/factories.py index 582464e4..e5c2fa35 100644 --- a/pygeoif/factories.py +++ b/pygeoif/factories.py @@ -154,7 +154,7 @@ def shape( geometries = [ shape(fi) for fi in geometry["geometries"] # type: ignore [typeddict-item] ] - return GeometryCollection(geometries) # type: ignore [arg-type] + return GeometryCollection(geometries) raise NotImplementedError(f"[{geometry['type']} is not implemented") diff --git a/pygeoif/geometry.py b/pygeoif/geometry.py index 669bac14..28d2f70d 100644 --- a/pygeoif/geometry.py +++ b/pygeoif/geometry.py @@ -1000,7 +1000,9 @@ class isn't generally supported by ordinary GIS sw (viewers and so on). So {'type': 'Point', 'coordinates': (1.0, -1.0)}]} """ - def __init__(self, geometries: Iterable[Geometry]) -> None: + def __init__( + self, geometries: Iterable[Union[Geometry, "GeometryCollection"]] + ) -> None: """ Initialize the MultiGeometry with Geometries. diff --git a/tests/test_base.py b/tests/test_base.py index 2e6f1839..615a56e0 100644 --- a/tests/test_base.py +++ b/tests/test_base.py @@ -49,7 +49,7 @@ def test_wkt_coordinates() -> None: def test_from_dict() -> None: base_geo = geometry._Geometry() with pytest.raises(NotImplementedError, match="^Must be implemented by subclass$"): - assert base_geo._from_dict({"type": "_Geometry"}) + assert base_geo._from_dict({"type": "_Geometry"}) # type: ignore def test_has_z() -> None: diff --git a/tests/test_factories.py b/tests/test_factories.py index d0410f93..5c714b95 100644 --- a/tests/test_factories.py +++ b/tests/test_factories.py @@ -87,7 +87,7 @@ def test_box_cw() -> None: def test_shell_holes_from_wkt_coords() -> None: shell, holes = factories._shell_holes_from_wkt_coords( [ - ["0 0", "10 20", "30 40", "0 0"], + ["0 0", "10 20", "30 40", "0 0"], # type: ignore ], ) assert holes is None @@ -139,15 +139,17 @@ def test_linestring(self) -> None: "LINESTRING(-72.991 46.177,-73.079 46.16," "-73.146 46.124,-73.177 46.071,-73.164 46.044)", ) + + assert isinstance(line, geometry.LineString) assert ( line.wkt == "LINESTRING (-72.991 46.177, " "-73.079 46.16, -73.146 46.124, " "-73.177 46.071, -73.164 46.044)" ) - assert isinstance(line, geometry.LineString) def test_linearring(self) -> None: r = factories.from_wkt("LINEARRING (0 0,0 1,1 0,0 0)") + assert isinstance(r, geometry.LinearRing) assert r.wkt == "LINEARRING (0 0, 0 1, 1 0, 0 0)" @@ -159,12 +161,18 @@ def test_polygon(self) -> None: "-91.638 76.202,-91.647 76.211,-91.648 76.218," "-91.643 76.221,-91.636 76.222,-91.611 76.227))", ) + + assert isinstance(p, geometry.Polygon) assert p.exterior.coords[0][0] == -91.611 assert p.exterior.coords[0] == p.exterior.coords[-1] assert len(p.exterior.coords) == 14 + + def test_polygon_1(self) -> None: p = factories.from_wkt( "POLYGON((1 1,5 1,5 5,1 5,1 1),(2 2, 3 2, 3 3, 2 3,2 2))", ) + + assert isinstance(p, geometry.Polygon) assert p.exterior.coords[0] == p.exterior.coords[-1] assert p.exterior.coords[0] == (1.0, 1.0) assert len(list(p.interiors)) == 1 @@ -180,12 +188,20 @@ def test_polygon(self) -> None: "1 5, 1 1),(2 2, 3 2, " "3 3, 2 3, 2 2))" ) + + def test_polygon_2(self) -> None: p = factories.from_wkt("POLYGON ((30 10, 10 20, 20 40, 40 40, 30 10))") + + assert isinstance(p, geometry.Polygon) assert p.exterior.coords[0] == p.exterior.coords[-1] + + def test_polygon_3(self) -> None: p = factories.from_wkt( """POLYGON ((35 10, 10 20, 15 40, 45 45, 35 10), (20 30, 35 35, 30 20, 20 30))""", ) + + assert isinstance(p, geometry.Polygon) assert p.exterior.coords[0] == p.exterior.coords[-1] def test_multipoint(self) -> None: @@ -207,6 +223,8 @@ def test_multilinestring(self) -> None: p = factories.from_wkt( "MULTILINESTRING((3 4,10 50,20 25),(-5 -8,-10 -8,-15 -4))", ) + + assert isinstance(p, geometry.MultiLineString) assert list(p.geoms)[0].coords == (((3, 4), (10, 50), (20, 25))) assert list(p.geoms)[1].coords == (((-5, -8), (-10, -8), (-15, -4))) assert ( @@ -214,10 +232,14 @@ def test_multilinestring(self) -> None: "20 25),(-5 -8, " "-10 -8, -15 -4))" ) + + def test_multilinestring_1(self) -> None: p = factories.from_wkt( """MULTILINESTRING ((10 10, 20 20, 10 40), (40 40, 30 30, 40 20, 30 10))""", ) + + assert isinstance(p, geometry.MultiLineString) assert p.wkt == ( "MULTILINESTRING((10 10, 20 20, 10 40),(40 40, 30 30, 40 20, 30 10))" ) @@ -228,6 +250,8 @@ def test_multipolygon(self) -> None: "(1 1,2 2,3 3,1 1))," "((100 100,110 110,120 120,100 100)))", ) + + assert isinstance(p, geometry.MultiPolygon) # two polygons: the first one has an interior ring assert len(list(p.geoms)) == 2 assert list(p.geoms)[0].exterior.coords == ( @@ -255,15 +279,23 @@ def test_multipolygon(self) -> None: "((100 100, 110 110," " 120 120, 100 100)))" ) + + def test_multipolygon_1(self) -> None: p = factories.from_wkt( "MULTIPOLYGON(((1 1,5 1,5 5,1 5,1 1)," "(2 2, 3 2, 3 3, 2 3,2 2)),((3 3,6 2,6 4,3 3)))", ) + + assert isinstance(p, geometry.MultiPolygon) assert len(list(p.geoms)) == 2 + + def test_multipolygon_2(self) -> None: p = factories.from_wkt( "MULTIPOLYGON (((30 20, 10 40, 45 40, 30 20))," "((15 5, 40 10, 10 20, 5 10, 15 5)))", ) + + assert isinstance(p, geometry.MultiPolygon) assert p.__geo_interface__ == { "type": "MultiPolygon", "bbox": (5.0, 5.0, 45.0, 40.0), @@ -285,6 +317,8 @@ def test_geometrycollection(self) -> None: gc = factories.from_wkt( "GEOMETRYCOLLECTION(POINT(4 6), LINESTRING(4 6,7 10))", ) + + assert isinstance(gc, geometry.GeometryCollection) assert len(list(gc.geoms)) == 2 assert isinstance(list(gc.geoms)[0], geometry.Point) assert isinstance(list(gc.geoms)[1], geometry.LineString) diff --git a/tests/test_line.py b/tests/test_line.py index 089c9768..b0b4df8a 100644 --- a/tests/test_line.py +++ b/tests/test_line.py @@ -82,7 +82,10 @@ def test_from_compatible() -> None: "coordinates": ((0.0, 0.0, 1.0), (1.0, 1.0, 2.0)), }, ) + line = geometry.LineString._from_interface(not_a_geometry) + + assert isinstance(line, geometry.LineString) assert line.coords == ((0.0, 0.0, 1.0), (1.0, 1.0, 2.0)) diff --git a/tests/test_linear_ring.py b/tests/test_linear_ring.py index 5fe4cbe9..529d705c 100644 --- a/tests/test_linear_ring.py +++ b/tests/test_linear_ring.py @@ -86,6 +86,7 @@ def test_from_compatible() -> None: ring = geometry.LinearRing._from_interface(not_a_geometry) + assert isinstance(ring, geometry.LinearRing) assert ring.coords == ((0.0, 0.0, 1.0), (1.0, 1.0, 2.0), (0, 4, 3), (0, 0, 1)) diff --git a/tests/test_point.py b/tests/test_point.py index 9a82b282..96e9a709 100644 --- a/tests/test_point.py +++ b/tests/test_point.py @@ -170,6 +170,7 @@ def test_from_compatible() -> None: point = geometry.Point._from_interface(not_a_geometry) + assert isinstance(point, geometry.Point) assert point.coords == ((0, 1, 2),)