From ceb39e0e769701923c4125c3d80827e77e4bb327 Mon Sep 17 00:00:00 2001 From: Victor Engmark Date: Fri, 14 Jun 2024 09:14:43 +1200 Subject: [PATCH 1/3] refactor: Sort Python packages alphabetically --- pyproject.toml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 08cf0eae9..842bb2e3a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,16 +45,16 @@ tifffile = "^2023.12.9" [tool.poetry.dev-dependencies] black = "^23.11.0" -isort = "^5.12.0" gitlint = "^0.19.1" +isort = "^5.12.0" +moto = "^5.0.5" mypy = "^1.6" -pylint = "^3.1.0" -pre-commit = "^3.5.0" mypy-boto3-s3 = "^1.28.55" +pre-commit = "^3.5.0" +pylint = "^3.1.0" pytest = "^7.4.3" pytest-dependency = "^0.5.1" -pytest-subtests = "*" -moto = "^5.0.5" pytest-mock = "^3.12.0" +pytest-subtests = "*" shellcheck-py = "*" vulture = "^2.10" From f959bfd23bba7725bdda35da96d74c5d9f57bec7 Mon Sep 17 00:00:00 2001 From: Victor Engmark Date: Fri, 14 Jun 2024 09:16:49 +1200 Subject: [PATCH 2/3] refactor: Use new Poetry group syntax --- poetry.lock | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/poetry.lock b/poetry.lock index bfec333b8..fc0c4954e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1448,4 +1448,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.10.6" -content-hash = "8c8c59af190cc96258a80a91d1fd86818be03ba7982e2e8a54b31397a9c3a567" +content-hash = "a482c92d5024f799c35ed339545ed8b28b3c3ee0a0c97ff0c30b017cfc0311a1" diff --git a/pyproject.toml b/pyproject.toml index 842bb2e3a..ae3b27ce6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,7 +43,7 @@ py-multihash = "^2.0.1" shapely = "^2.0.4" tifffile = "^2023.12.9" -[tool.poetry.dev-dependencies] +[tool.poetry.group.dev.dependencies] black = "^23.11.0" gitlint = "^0.19.1" isort = "^5.12.0" From 3600c01c75a6b892d4cb015d442657b4fca5c433 Mon Sep 17 00:00:00 2001 From: Victor Engmark Date: Fri, 14 Jun 2024 09:16:20 +1200 Subject: [PATCH 3/3] feat: Add Shapely type library For IDE recognition. --- poetry.lock | 16 +++++++++++++++- pyproject.toml | 1 + scripts/files/geotiff.py | 4 +--- scripts/gdal/gdalinfo.py | 2 +- scripts/stac/imagery/capture_area.py | 20 ++++++++++---------- scripts/stac/imagery/collection.py | 6 +++--- 6 files changed, 31 insertions(+), 18 deletions(-) diff --git a/poetry.lock b/poetry.lock index fc0c4954e..923e95609 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1346,6 +1346,20 @@ files = [ {file = "types_PyYAML-6.0.12.9-py3-none-any.whl", hash = "sha256:5aed5aa66bd2d2e158f75dda22b059570ede988559f030cf294871d3b647e3e8"}, ] +[[package]] +name = "types-shapely" +version = "2.0.0.20240613" +description = "Typing stubs for shapely" +optional = false +python-versions = ">=3.8" +files = [ + {file = "types-shapely-2.0.0.20240613.tar.gz", hash = "sha256:d5ee564554274b11f8ee267e27b2640c1b165f8b49cea4723010fd24fc111ff2"}, + {file = "types_shapely-2.0.0.20240613-py3-none-any.whl", hash = "sha256:ce8e9fc6e030a00e2fb1120864b0ff564dceb15be09374633f9050911683bde3"}, +] + +[package.dependencies] +numpy = ">=1.20" + [[package]] name = "typing-extensions" version = "4.5.0" @@ -1448,4 +1462,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.10.6" -content-hash = "a482c92d5024f799c35ed339545ed8b28b3c3ee0a0c97ff0c30b017cfc0311a1" +content-hash = "f17e9994ecadf3206afb6c21f89fc5e1a6126b27d5df66754b64c5d1dd953527" diff --git a/pyproject.toml b/pyproject.toml index ae3b27ce6..cc05cde42 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -57,4 +57,5 @@ pytest-dependency = "^0.5.1" pytest-mock = "^3.12.0" pytest-subtests = "*" shellcheck-py = "*" +types-shapely = "*" vulture = "^2.10" diff --git a/scripts/files/geotiff.py b/scripts/files/geotiff.py index 26ed7d611..ee41ff66f 100644 --- a/scripts/files/geotiff.py +++ b/scripts/files/geotiff.py @@ -1,11 +1,9 @@ -from typing import Dict, List, Tuple - from shapely.geometry import Polygon from scripts.gdal.gdalinfo import GdalInfo -def get_extents(gdalinfo_result: GdalInfo) -> Tuple[Dict[str, List[float]], Tuple[float]]: +def get_extents(gdalinfo_result: GdalInfo) -> tuple[dict[str, list[list[list[float]]]], tuple[float, float, float, float]]: """Get the geometry and bounding box from the `gdalinfo`. Args: diff --git a/scripts/gdal/gdalinfo.py b/scripts/gdal/gdalinfo.py index a997d6cb0..e39fd8b0d 100644 --- a/scripts/gdal/gdalinfo.py +++ b/scripts/gdal/gdalinfo.py @@ -68,7 +68,7 @@ class GdalInfo(TypedDict): metadata: Dict[Any, Any] cornerCoordinates: Dict[Any, Any] extent: Dict[Any, Any] - wgs84Extent: Optional[Dict[str, List[float]]] + wgs84Extent: Optional[Dict[str, List[List[List[float]]]]] bands: List[GdalInfoBand] """Coordinate system description""" coordinateSystem: Dict[Any, Any] diff --git a/scripts/stac/imagery/capture_area.py b/scripts/stac/imagery/capture_area.py index a9e6e5253..3ca75640b 100644 --- a/scripts/stac/imagery/capture_area.py +++ b/scripts/stac/imagery/capture_area.py @@ -1,9 +1,9 @@ import json -from typing import Any, Dict, List +from typing import Any, Dict, Sequence from linz_logger import get_log -from shapely import BufferCapStyle, BufferJoinStyle, Geometry, to_geojson, union_all -from shapely.geometry import Polygon +from shapely import BufferCapStyle, BufferJoinStyle, to_geojson, union_all +from shapely.geometry.base import BaseGeometry from scripts.logging.time_helper import time_in_ms @@ -43,11 +43,11 @@ def get_buffer_distance(gsd: float) -> float: return gsd * 2 * DECIMAL_DEGREES_1M -def to_feature(geometry: Geometry) -> Dict[str, Any]: - """Transform a Geometry to a GeoJSON feature. +def to_feature(geometry: BaseGeometry) -> Dict[str, Any]: + """Transform a BaseGeometry to a GeoJSON feature. Args: - geometry: a Geometry + geometry: a BaseGeometry Returns: a GeoJSON document. @@ -55,7 +55,7 @@ def to_feature(geometry: Geometry) -> Dict[str, Any]: return {"geometry": json.loads(to_geojson(geometry)), "type": "Feature", "properties": {}} -def merge_polygons(polygons: List[Polygon], buffer_distance: float) -> Geometry: +def merge_polygons(polygons: Sequence[BaseGeometry], buffer_distance: float) -> BaseGeometry: """Merge a list of polygons by converting them to a single geometry that covers the same area. A buffer distance is used to buffer out the polygons before dissolving them together and then negative buffer them back in. The merged geometry is simplify (rounded) to the decimal used for the buffer. @@ -80,8 +80,8 @@ def merge_polygons(polygons: List[Polygon], buffer_distance: float) -> Geometry: return union_simplified -def generate_capture_area(polygons: List[Polygon], gsd: float) -> Dict[str, Any]: - """Generate the capture area from a list of polygons. +def generate_capture_area(polygons: Sequence[BaseGeometry], gsd: float) -> Dict[str, Any]: + """Generate the capture area from a list of BaseGeometries. Providing the `gsd` allows to round the geometry as we've seen some tiffs geometry being slightly off, sometimes due to rounding issue in their creation process (before delivery). @@ -92,7 +92,7 @@ def generate_capture_area(polygons: List[Polygon], gsd: float) -> Dict[str, Any] but < buffer_factor*2 will be closed. Args: - polygons: list of polygons of the area + polygons: list of BaseGeometries of the area gsd: Ground Sample Distance in meters Returns: diff --git a/scripts/stac/imagery/collection.py b/scripts/stac/imagery/collection.py index 2e892f556..c6408eaa5 100644 --- a/scripts/stac/imagery/collection.py +++ b/scripts/stac/imagery/collection.py @@ -2,8 +2,8 @@ from datetime import datetime from typing import Any, Callable, Dict, List, Optional -import shapely.ops import ulid +from shapely.geometry.base import BaseGeometry from scripts.datetimes import format_rfc_3339_datetime_string, parse_rfc_3339_datetime from scripts.files.files_helper import ContentType @@ -87,12 +87,12 @@ def __init__( self.add_providers(providers) - def add_capture_area(self, polygons: List[shapely.geometry.shape], target: str, artifact_target: str = "/tmp") -> None: + def add_capture_area(self, polygons: List[BaseGeometry], target: str, artifact_target: str = "/tmp") -> None: """Add the capture area of the Collection. The `href` or path of the capture-area.geojson is always set as the relative `./capture-area.geojson` Args: - polygons: list of geometries + polygons: list of BaseGeometries target: location where the capture-area.geojson file will be saved artifact_target: location where the capture-area.geojson artifact file will be saved. This is useful for Argo Workflow in order to expose the file to the user for testing/validation purpose.