Skip to content

Commit

Permalink
feat: Set created/updated item properties TDE-1147
Browse files Browse the repository at this point in the history
When creating datasets, we want to set these to the current datetime.

Injects the function to get the current datetime, to allow testing the
exact values.
  • Loading branch information
l0b0 committed May 30, 2024
1 parent 3a6017c commit ba70ab9
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 15 deletions.
4 changes: 4 additions & 0 deletions scripts/datetimes.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ def format_rfc_3339_nz_midnight_datetime_string(datetime_object: datetime) -> st
return format_rfc_3339_datetime_string(datetime_utc)


def utc_now() -> datetime:
return datetime.now(tz=timezone.utc)


class NaiveDatetimeError(Exception):
def __init__(self) -> None:
super().__init__("Can't convert naive datetime to UTC")
3 changes: 2 additions & 1 deletion scripts/stac/imagery/create_stac.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from linz_logger import get_log

from scripts.datetimes import utc_now
from scripts.files.files_helper import get_file_name_from_path
from scripts.files.geotiff import get_extents
from scripts.gdal.gdal_helper import gdal_info
Expand Down Expand Up @@ -35,7 +36,7 @@ def create_item(

geometry, bbox = get_extents(gdalinfo_result)

item = ImageryItem(id_, file)
item = ImageryItem(id_, file, utc_now)
item.update_datetime(start_datetime, end_datetime)
item.update_spatial(geometry, bbox)
item.add_collection(collection_id)
Expand Down
7 changes: 5 additions & 2 deletions scripts/stac/imagery/item.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os
from typing import Any, Dict, Tuple
from datetime import datetime
from typing import Any, Callable, Dict, Tuple

from scripts.datetimes import format_rfc_3339_datetime_string
from scripts.files import fs
Expand All @@ -12,9 +13,10 @@
class ImageryItem:
stac: Dict[str, Any]

def __init__(self, id_: str, file: str) -> None:
def __init__(self, id_: str, file: str, now: Callable[[], datetime]) -> None:
file_content = fs.read(file)
file_modified_datetime = format_rfc_3339_datetime_string(modified(file))
now_string = format_rfc_3339_datetime_string(now())
self.stac = {
"type": "Feature",
"stac_version": STAC_VERSION,
Expand All @@ -32,6 +34,7 @@ def __init__(self, id_: str, file: str) -> None:
}
},
"stac_extensions": [StacExtensions.file.value],
"properties": {"created": now_string, "updated": now_string},
}

def update_datetime(self, start_datetime: str, end_datetime: str) -> None:
Expand Down
34 changes: 25 additions & 9 deletions scripts/stac/imagery/tests/collection_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
from datetime import datetime, timezone
from shutil import rmtree
from tempfile import mkdtemp
from typing import Generator
from typing import Callable, Generator

import pytest
import shapely.geometry
from pytest_subtests import SubTests

from scripts.datetimes import format_rfc_3339_datetime_string
from scripts.files.fs import read
from scripts.stac.imagery.collection import ImageryCollection
from scripts.stac.imagery.item import ImageryItem
Expand Down Expand Up @@ -113,12 +114,20 @@ def test_interval_updated_from_existing(metadata: CollectionMetadata) -> None:
assert collection.stac["extent"]["temporal"]["interval"] == [["2021-01-27T00:00:00Z", "2021-02-20T00:00:00Z"]]


def fixed_now_function(now: datetime) -> Callable[[], datetime]:
def func() -> datetime:
return now

return func


def test_add_item(metadata: CollectionMetadata, subtests: SubTests) -> None:
collection = ImageryCollection(metadata)
item_file_path = "./scripts/tests/data/empty.tiff"
modified_datetime = datetime(2001, 2, 3, hour=4, minute=5, second=6, tzinfo=timezone.utc)
os.utime(item_file_path, times=(any_epoch_datetime().timestamp(), modified_datetime.timestamp()))
item = ImageryItem("BR34_5000_0304", item_file_path)
now = any_epoch_datetime()
item = ImageryItem("BR34_5000_0304", item_file_path, fixed_now_function(now))
geometry = {
"type": "Polygon",
"coordinates": [[1799667.5, 5815977.0], [1800422.5, 5815977.0], [1800422.5, 5814986.0], [1799667.5, 5814986.0]],
Expand All @@ -131,13 +140,17 @@ def test_add_item(metadata: CollectionMetadata, subtests: SubTests) -> None:

collection.add_item(item.stac)

with subtests.test():
assert {
"file:checksum": "122097b5d2b049c6ffdf608af28c4ba2744fad7f03046d1f58b2523402f30577f618",
"rel": "item",
"href": "./BR34_5000_0304.json",
"type": "application/json",
} in collection.stac["links"]
links = collection.stac["links"].copy()

with subtests.test(msg="File checksum heuristic"):
# The checksum changes based on the contents
assert links[1].pop("file:checksum").startswith("1220")

with subtests.test(msg="Main links content"):
assert [
{"href": "./collection.json", "rel": "self", "type": "application/json"},
{"rel": "item", "href": "./BR34_5000_0304.json", "type": "application/json"},
] == links

with subtests.test():
assert collection.stac["extent"]["temporal"]["interval"] == [[start_datetime, end_datetime]]
Expand All @@ -146,6 +159,9 @@ def test_add_item(metadata: CollectionMetadata, subtests: SubTests) -> None:
assert collection.stac["extent"]["spatial"]["bbox"] == [bbox]

for property_name in ["created", "updated"]:
with subtests.test(msg=f"item properties.{property_name}"):
assert item.stac["properties"][property_name] == format_rfc_3339_datetime_string(now)

with subtests.test(msg=f"item assets.visual.{property_name}"):
assert item.stac["assets"]["visual"][property_name] == "2001-02-03T04:05:06Z"

Expand Down
5 changes: 3 additions & 2 deletions scripts/stac/imagery/tests/item_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from scripts.stac.imagery.collection import ImageryCollection
from scripts.stac.imagery.item import ImageryItem
from scripts.stac.imagery.metadata_constants import CollectionMetadata
from scripts.tests.datetimes_test import any_epoch_datetime


def test_imagery_stac_item(mocker: MockerFixture, subtests: SubTests) -> None:
Expand All @@ -23,7 +24,7 @@ def test_imagery_stac_item(mocker: MockerFixture, subtests: SubTests) -> None:
start_datetime = "2021-01-27T00:00:00Z"
end_datetime = "2021-01-27T00:00:00Z"

item = ImageryItem(id_, path)
item = ImageryItem(id_, path, any_epoch_datetime)
item.update_spatial(geometry, bbox)
item.update_datetime(start_datetime, end_datetime)
# checks
Expand Down Expand Up @@ -77,7 +78,7 @@ def test_imagery_add_collection(mocker: MockerFixture, subtests: SubTests) -> No
path = "./scripts/tests/data/empty.tiff"
id_ = get_file_name_from_path(path)
mocker.patch("scripts.files.fs.read", return_value=b"")
item = ImageryItem(id_, path)
item = ImageryItem(id_, path, any_epoch_datetime)

item.add_collection(collection.stac["id"])

Expand Down
12 changes: 11 additions & 1 deletion scripts/tests/datetimes_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from random import randint

from dateutil.tz import tz
from pytest import raises
from pytest import approx, raises
from pytest_subtests import SubTests

from scripts.datetimes import (
Expand All @@ -11,6 +11,7 @@
format_rfc_3339_nz_midnight_datetime_string,
parse_rfc_3339_date,
parse_rfc_3339_datetime,
utc_now,
)


Expand Down Expand Up @@ -49,6 +50,15 @@ def test_should_format_rfc_3339_nz_midnight_datetime_string() -> None:
assert format_rfc_3339_nz_midnight_datetime_string(datetime_object) == "2001-02-02T11:00:00Z"


def test_system_clock_should_return_current_time() -> None:
# At most five second difference
assert utc_now().timestamp() == approx(datetime.now().timestamp(), abs=5)


def test_system_clock_should_return_utc_datetime() -> None:
assert utc_now().tzinfo == timezone.utc


def any_epoch_datetime() -> datetime:
"""
Get arbitrary datetime
Expand Down

0 comments on commit ba70ab9

Please sign in to comment.