11import datetime
22import re
3- from typing import Any , Dict
3+ from typing import Any , Dict , Optional , Union
44from unittest import mock
55from unittest .mock import MagicMock , patch
66
@@ -150,68 +150,44 @@ def normalized_dummy_geodataframe() -> pd.DataFrame:
150150 )
151151
152152
153- FAKE_NOW = datetime .datetime (2020 , 5 , 22 )
153+ def _pystac_item (
154+ * ,
155+ id : str ,
156+ properties : Optional [dict ] = None ,
157+ geometry : Optional = None ,
158+ bbox : Optional = None ,
159+ datetime_ : Union [None , str , datetime .date , datetime .date ] = "2025-06-07" ,
160+ ) -> pystac .Item :
161+ """Helper to easily construct a dummy but valid pystac.Item"""
162+ if isinstance (datetime_ , str ):
163+ datetime_ = pystac .utils .str_to_datetime (datetime_ )
164+ elif isinstance (datetime_ , datetime .date ):
165+ datetime_ = datetime .datetime .combine (datetime_ , datetime .time .min , tzinfo = datetime .timezone .utc )
154166
155-
156- @pytest .fixture
157- def dummy_stac_item () -> pystac .Item :
158- properties = {
159- "datetime" : pystac .utils .datetime_to_str (FAKE_NOW ),
160- "some_property" : "value" ,
161- }
162-
163- return pystac .Item (id = "test" , geometry = None , bbox = None , properties = properties , datetime = FAKE_NOW )
167+ return pystac .Item (
168+ id = id ,
169+ geometry = geometry ,
170+ bbox = bbox ,
171+ properties = properties or {},
172+ datetime = datetime_ ,
173+ )
164174
165175
166176@pytest .fixture
167- def dummy_stac_item_geometry () -> pystac .Item :
177+ def dummy_stac_item () -> pystac .Item :
168178 properties = {
169- "datetime" : pystac . utils . datetime_to_str ( FAKE_NOW ) ,
179+ "datetime" : "2020-05-22T00:00:00Z" ,
170180 "some_property" : "value" ,
171- "geometry" : {"type" : "Polygon" , "coordinates" : (((0.0 , 0.0 ), (1.0 , 0.0 ), (1.0 , 1.0 ), (0.0 , 1.0 ), (0.0 , 0.0 )),)},
172181 }
173-
174182 return pystac .Item (
175- id = "test" ,
176- geometry = {"type" : "Polygon" , "coordinates" : (((0.0 , 0.0 ), (1.0 , 0.0 ), (1.0 , 1.0 ), (0.0 , 1.0 ), (0.0 , 0.0 )),)},
177- bbox = (0.0 , 0.0 , 1.0 , 1.0 ),
178- properties = properties ,
179- datetime = FAKE_NOW ,
180- )
181-
182-
183- @pytest .fixture
184- def dummy_series () -> pd .Series :
185- return pd .Series (
186- {"item_id" : "test" , "datetime" : pystac .utils .datetime_to_str (FAKE_NOW ), "some_property" : "value" }, name = "test"
183+ id = "test" , geometry = None , bbox = None , properties = properties , datetime = datetime .datetime (2020 , 5 , 22 )
187184 )
188185
189186
190187@pytest .fixture
191188def dummy_series_no_item_id () -> pd .Series :
192- return pd .Series ({"datetime" : pystac . utils . datetime_to_str ( FAKE_NOW ) , "some_property" : "value" }, name = "test" )
189+ return pd .Series ({"datetime" : "2020-05-22T00:00:00Z" , "some_property" : "value" }, name = "test" )
193190
194- @pytest .fixture
195- def dummy_series_geometry () -> pd .Series :
196- return pd .Series (
197- {
198- "item_id" : "test" ,
199- "datetime" : pystac .utils .datetime_to_str (FAKE_NOW ),
200- "some_property" : "value" ,
201- "geometry" : {
202- "type" : "Polygon" ,
203- "coordinates" : (((0.0 , 0.0 ), (1.0 , 0.0 ), (1.0 , 1.0 ), (0.0 , 1.0 ), (0.0 , 0.0 )),),
204- },
205- },
206- name = "test" ,
207- )
208-
209-
210- @pytest .fixture
211- def patch_datetime_now ():
212- with patch ("datetime.datetime" ) as mock_datetime :
213- mock_datetime .now .return_value = FAKE_NOW
214- yield mock_datetime
215191
216192
217193@pytest .fixture
@@ -220,6 +196,7 @@ def bulk_dataframe():
220196 {
221197 "item_id" : [f"test-{ i } " for i in range (10 )],
222198 "some_property" : [f"value-{ i } " for i in range (10 )],
199+ "datetime" : [f"2020-{ i + 1 :02d} -01" for i in range (10 )],
223200 },
224201 index = [i for i in range (10 )],
225202 )
@@ -278,16 +255,80 @@ def test_initialize_from_df_with_geometry(
278255 def test_series_from (self , job_db_exists , dummy_series_no_item_id , dummy_stac_item ):
279256 pdt .assert_series_equal (job_db_exists .series_from (dummy_stac_item ), dummy_series_no_item_id )
280257
281- def test_item_from (self , patch_datetime_now , job_db_exists , dummy_series , dummy_stac_item ):
282- item = job_db_exists .item_from (dummy_series )
283- assert item .to_dict () == dummy_stac_item .to_dict ()
284-
285- def test_item_from_geometry (
286- self , patch_datetime_now , job_db_exists , dummy_series_geometry , dummy_stac_item_geometry
287- ):
258+ @pytest .mark .parametrize (
259+ ["series" , "expected" ],
260+ [
261+ # Minimal (using current time as datetime)
262+ (
263+ pd .Series ({"item_id" : "item-123" }),
264+ _pystac_item (id = "item-123" , datetime_ = "2022-02-02" ),
265+ ),
266+ # With explicit datetime, and some other properties
267+ (
268+ pd .Series (
269+ {
270+ "item_id" : "item-123" ,
271+ "datetime" : "2023-04-05" ,
272+ "hello" : "world" ,
273+ }
274+ ),
275+ _pystac_item (
276+ id = "item-123" ,
277+ properties = {"hello" : "world" },
278+ datetime_ = "2023-04-05" ,
279+ ),
280+ ),
281+ (
282+ pd .Series (
283+ {
284+ "item_id" : "item-123" ,
285+ "datetime" : datetime .datetime (2023 , 4 , 5 , 12 , 34 ),
286+ "hello" : "world" ,
287+ }
288+ ),
289+ _pystac_item (
290+ id = "item-123" ,
291+ properties = {"hello" : "world" },
292+ datetime_ = "2023-04-05T12:34:00Z" ,
293+ ),
294+ ),
295+ ],
296+ )
297+ def test_item_from (self , job_db_exists , series , expected , time_machine ):
298+ time_machine .move_to ("2022-02-02T00:00:00Z" )
299+ item = job_db_exists .item_from (series )
300+ assert isinstance (item , pystac .Item )
301+ assert item .to_dict () == expected .to_dict ()
302+
303+ @pytest .mark .parametrize (
304+ ["series" , "expected" ],
305+ [
306+ (
307+ pd .Series (
308+ {
309+ "item_id" : "item-123" ,
310+ "datetime" : "2023-04-05" ,
311+ "geometry" : {"type" : "Polygon" , "coordinates" : (((1 , 2 ), (3 , 4 ), (0 , 5 ), (1 , 2 )),)},
312+ },
313+ ),
314+ _pystac_item (
315+ id = "item-123" ,
316+ datetime_ = "2023-04-05" ,
317+ geometry = {"type" : "Polygon" , "coordinates" : (((1 , 2 ), (3 , 4 ), (0 , 5 ), (1 , 2 )),)},
318+ bbox = (0.0 , 2.0 , 3.0 , 5.0 ),
319+ properties = {
320+ "geometry" : {"type" : "Polygon" , "coordinates" : (((1 , 2 ), (3 , 4 ), (0 , 5 ), (1 , 2 )),)},
321+ },
322+ ),
323+ ),
324+ ],
325+ )
326+ def test_item_from_geometry (self , job_db_exists , series , expected ):
327+ # TODO avoid this `has_geometry` hack?
288328 job_db_exists .has_geometry = True
289- item = job_db_exists .item_from (dummy_series_geometry )
290- assert item .to_dict () == dummy_stac_item_geometry .to_dict ()
329+ item = job_db_exists .item_from (series )
330+ assert isinstance (item , pystac .Item )
331+ assert item .to_dict () == expected .to_dict ()
291332
292333 @patch ("openeo.extra.job_management.stac_job_db.STACAPIJobDatabase.get_by_status" )
293334 def test_count_by_status (self , mock_get_by_status , normalized_dummy_dataframe , job_db_exists ):
@@ -315,15 +356,15 @@ def test_get_by_status_result(self, job_db_exists):
315356 pd .DataFrame (
316357 {
317358 "item_id" : ["test" ],
318- "datetime" : [pystac . utils . datetime_to_str ( FAKE_NOW ) ],
359+ "datetime" : ["2020-05-22T00:00:00Z" ],
319360 "some_property" : ["value" ],
320361 },
321362 index = [0 ],
322363 ),
323364 )
324365
325366 @patch ("requests.post" )
326- def test_persist_single_chunk (self , mock_requests_post , bulk_dataframe , job_db_exists , patch_datetime_now ):
367+ def test_persist_single_chunk (self , mock_requests_post , bulk_dataframe , job_db_exists ):
327368 def bulk_items (df ):
328369 all_items = []
329370 if not df .empty :
0 commit comments