Skip to content

Commit 8038850

Browse files
committed
PR #756/#745 add todo notes
and use more keyword arguments
1 parent a65ae21 commit 8038850

File tree

2 files changed

+25
-13
lines changed

2 files changed

+25
-13
lines changed

openeo/extra/job_management/_job_splitting.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ class JobSplittingFailure(Exception):
1515
class _BoundingBox(NamedTuple):
1616
"""Simple NamedTuple container for a bounding box"""
1717

18+
# TODO: this should be moved to more general utility module, and/or merged with existing BBoxDict
19+
1820
west: float
1921
south: float
2022
east: float
@@ -46,6 +48,8 @@ class _TileGridInterface(metaclass=abc.ABCMeta):
4648
"""Interface for tile grid classes"""
4749

4850
@abc.abstractmethod
51+
# TODO: is it intentional that this method returns a list of non-multi polygons even if the input can be multi-polygon?
52+
# TODO: typehint states that geometry can be a dict too, but that is very liberal, it's probably just about bounding box kind of dicts?
4953
def get_tiles(self, geometry: Union[Dict, MultiPolygon, Polygon]) -> List[Polygon]:
5054
"""Calculate tiles to cover given bounding box"""
5155
...
@@ -57,17 +61,21 @@ class _SizeBasedTileGrid(_TileGridInterface):
5761
The size is in m for UTM projections or degrees for WGS84.
5862
"""
5963

60-
def __init__(self, epsg: int, size: float):
64+
def __init__(self, *, epsg: int, size: float):
65+
# TODO: normalize_crs does not necessarily return an int (could also be a WKT2 string, or even None), but further logic seems to assume it's an int
6166
self.epsg = normalize_crs(epsg)
6267
self.size = size
6368

6469
@classmethod
65-
def from_size_projection(cls, size: float, projection: str) -> "_SizeBasedTileGrid":
70+
def from_size_projection(cls, *, size: float, projection: str) -> "_SizeBasedTileGrid":
6671
"""Create a tile grid from size and projection"""
67-
return cls(normalize_crs(projection), size)
72+
# TODO: the constructor also does normalize_crs, so this factory looks like overkill at the moment
73+
return cls(epsg=normalize_crs(projection), size=size)
6874

6975
def _epsg_is_meters(self) -> bool:
7076
"""Check if the projection unit is in meters. (EPSG:3857 or UTM)"""
77+
# TODO: this is a bit misleading: this code just checks some EPSG ranges (UTM and 3857) and calls all the rest to be not in meters.
78+
# It would be better to raise an exception on unknown EPSG codes than claiming they're not in meter
7179
return 32601 <= self.epsg <= 32660 or 32701 <= self.epsg <= 32760 or self.epsg == 3857
7280

7381
@staticmethod
@@ -108,9 +116,10 @@ def get_tiles(self, geometry: Union[Dict, MultiPolygon, Polygon]) -> List[Polygo
108116
else:
109117
raise JobSplittingFailure("geometry must be a dict or a shapely.geometry.Polygon or MultiPolygon")
110118

119+
# TODO: being a meter based EPSG does not imply that offset should be 500_000
111120
x_offset = 500_000 if self._epsg_is_meters() else 0
112121

113-
tiles = _SizeBasedTileGrid._split_bounding_box(bbox, x_offset, self.size)
122+
tiles = _SizeBasedTileGrid._split_bounding_box(to_cover=bbox, x_offset=x_offset, tile_size=self.size)
114123

115124
return tiles
116125

@@ -125,8 +134,10 @@ def split_area(
125134
:param tile_size: size of tiles in unit of measure of the projection
126135
:return: list of tiles (polygons).
127136
"""
137+
# TODO EPSG 3857 is probably not a good default projection. Probably better to make it a required parameter
128138
if isinstance(aoi, dict):
139+
# TODO: this possibly overwrites the given projection without the user noticing, making usage confusing
129140
projection = aoi.get("crs", projection)
130141

131-
tile_grid = _SizeBasedTileGrid.from_size_projection(tile_size, projection)
142+
tile_grid = _SizeBasedTileGrid.from_size_projection(size=tile_size, projection=projection)
132143
return tile_grid.get_tiles(aoi)

tests/extra/job_management/test_job_splitting.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
split_area,
99
)
1010

11+
# TODO: using fixtures for these simple objects is a bit overkill, makes the test harder to follow, and undermines opportunity to parameterize
1112

1213
@pytest.fixture
1314
def mock_polygon_wgs():
@@ -89,54 +90,54 @@ def test_as_polygon(self):
8990

9091
class TestSizeBasedTileGrid:
9192
def test_from_size_projection(self):
92-
splitter = _SizeBasedTileGrid.from_size_projection(0.1, "EPSG:4326")
93+
splitter = _SizeBasedTileGrid.from_size_projection(size=0.1, projection="EPSG:4326")
9394
assert splitter.epsg == 4326
9495
assert splitter.size == 0.1
9596

9697
def test_get_tiles_raises_exception(self):
9798
"""test get_tiles when the input geometry is not a dict or shapely.geometry.Polygon"""
98-
tile_grid = _SizeBasedTileGrid.from_size_projection(0.1, "EPSG:4326")
99+
tile_grid = _SizeBasedTileGrid.from_size_projection(size=0.1, projection="EPSG:4326")
99100
with pytest.raises(JobSplittingFailure):
100101
tile_grid.get_tiles("invalid_geometry")
101102

102103
def test_simple_get_tiles_dict(self, mock_dict_with_crs_utm, mock_polygon_utm):
103104
"""test get_tiles when the the tile grid size is equal to the size of the input geometry. The original geometry should be returned as polygon."""
104-
tile_grid = _SizeBasedTileGrid.from_size_projection(100_000, "EPSG:3857")
105+
tile_grid = _SizeBasedTileGrid.from_size_projection(size=100_000, projection="EPSG:3857")
105106
tiles = tile_grid.get_tiles(mock_dict_with_crs_utm)
106107
assert len(tiles) == 1
107108
assert tiles[0] == mock_polygon_utm
108109

109110
def test_multiple_get_tile_dict(self, mock_dict_with_crs_utm):
110111
"""test get_tiles when the the tile grid size is smaller than the size of the input geometry. The input geometry should be split into multiple tiles."""
111-
tile_grid = _SizeBasedTileGrid.from_size_projection(20_000, "EPSG:3857")
112+
tile_grid = _SizeBasedTileGrid.from_size_projection(size=20_000, projection="EPSG:3857")
112113
tiles = tile_grid.get_tiles(mock_dict_with_crs_utm)
113114
assert len(tiles) == 25
114115
assert tiles[0] == shapely.geometry.box(0.0, 0.0, 20_000.0, 20_000.0)
115116

116117
def test_larger_get_tile_dict(self, mock_dict_with_crs_utm, mock_polygon_utm):
117118
"""test get_tiles when the the tile grid size is larger than the size of the input geometry. The original geometry should be returned."""
118-
tile_grid = _SizeBasedTileGrid.from_size_projection(200_000, "EPSG:3857")
119+
tile_grid = _SizeBasedTileGrid.from_size_projection(size=200_000, projection="EPSG:3857")
119120
tiles = tile_grid.get_tiles(mock_dict_with_crs_utm)
120121
assert len(tiles) == 1
121122
assert tiles[0] == mock_polygon_utm
122123

123124
def test_get_tiles_polygon_wgs(self, mock_polygon_wgs):
124125
"""test get_tiles when the input geometry is a polygon in wgs and the tile grid is in wgs"""
125-
tile_grid = _SizeBasedTileGrid.from_size_projection(0.1, "EPSG:4326")
126+
tile_grid = _SizeBasedTileGrid.from_size_projection(size=0.1, projection="EPSG:4326")
126127
tiles = tile_grid.get_tiles(mock_polygon_wgs)
127128
assert len(tiles) == 100
128129
assert tiles[0] == shapely.geometry.box(0.0, 0.0, 0.1, 0.1)
129130

130131
def test_simple_get_tiles_polygon(self, mock_polygon_utm):
131132
"""test get_tiles when the the tile grid size is equal to the size of the input geometry. The original geometry should be returned."""
132-
tile_grid = _SizeBasedTileGrid.from_size_projection(100_000.0, "EPSG:3857")
133+
tile_grid = _SizeBasedTileGrid.from_size_projection(size=100_000.0, projection="EPSG:3857")
133134
tiles = tile_grid.get_tiles(mock_polygon_utm)
134135
assert len(tiles) == 1
135136
assert tiles[0] == mock_polygon_utm
136137

137138
def test_larger_get_tiles_polygon(self, mock_polygon_utm):
138139
"""test get_tiles when the the tile grid size is larger than the size of the input geometry. The original geometry should be returned."""
139-
tile_grid = _SizeBasedTileGrid.from_size_projection(200_000.0, "EPSG:3857")
140+
tile_grid = _SizeBasedTileGrid.from_size_projection(size=200_000.0, projection="EPSG:3857")
140141
tiles = tile_grid.get_tiles(mock_polygon_utm)
141142
assert len(tiles) == 1
142143
assert tiles[0] == mock_polygon_utm

0 commit comments

Comments
 (0)