From 8670dc9a78185b087c948e0c319c007146c1466c Mon Sep 17 00:00:00 2001 From: Megan Davidson Date: Fri, 9 Sep 2022 14:53:26 +1200 Subject: [PATCH 01/14] feat: initialise collection object and stac --- scripts/initialise_stac_collection.py | 38 +++++++++++++++++++++++++++ scripts/stac/imagery/collection.py | 20 ++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 scripts/initialise_stac_collection.py create mode 100644 scripts/stac/imagery/collection.py diff --git a/scripts/initialise_stac_collection.py b/scripts/initialise_stac_collection.py new file mode 100644 index 000000000..a3999feac --- /dev/null +++ b/scripts/initialise_stac_collection.py @@ -0,0 +1,38 @@ +import argparse +import json +import os + +from linz_logger import get_log + +from scripts.files.fs import write +from scripts.logging.time_helper import time_in_ms +from scripts.stac.imagery.collection import ImageryCollection + + +def initialise_imagery_collection(title: str, description: str) -> None: + start_time = time_in_ms() + get_log().info("finalise_stac_collection_imagery_start", title=title, description=description) + + collection = ImageryCollection(title=title, description=description) + + tmp_file_path = os.path.join("/tmp/", "collection.json") + write(tmp_file_path, json.dumps(collection.stac).encode("utf-8")) + + get_log().info("create_stac_collection_imagery_complete", title=title, duration=time_in_ms() - start_time) + + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument("--title", dest="title", required=True) + parser.add_argument("--description", dest="description", required=True) + + arguments = parser.parse_args() + + title = arguments.title + description = arguments.description + + initialise_imagery_collection(title, description) + + +if __name__ == "__main__": + main() diff --git a/scripts/stac/imagery/collection.py b/scripts/stac/imagery/collection.py new file mode 100644 index 000000000..3cbe6b605 --- /dev/null +++ b/scripts/stac/imagery/collection.py @@ -0,0 +1,20 @@ +from typing import Any, Dict, Optional + +import ulid + +PYSTAC_VERSION = "1.0.0" + + +class ImageryCollection: + stac: Dict[str, Any] + + def __init__(self, title: Optional[str] = None, description: Optional[str] = None) -> None: + self.stac = { + "type": "Collection", + "stac_version": PYSTAC_VERSION, + "id": str(ulid.ULID()), + "title": title, + "description": description, + "license": "CC-BY-4.0", + "links": [{"rel": "self", "href": "./collection.json", "type": "application/json"}], + } From c24408657dbb05045988bc2562ca5ddc1f8fe88e Mon Sep 17 00:00:00 2001 From: Megan Davidson Date: Fri, 9 Sep 2022 14:53:34 +1200 Subject: [PATCH 02/14] test: collection test --- scripts/stac/tests/collection_test.py | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 scripts/stac/tests/collection_test.py diff --git a/scripts/stac/tests/collection_test.py b/scripts/stac/tests/collection_test.py new file mode 100644 index 000000000..50ca500c8 --- /dev/null +++ b/scripts/stac/tests/collection_test.py @@ -0,0 +1,10 @@ +from scripts.stac.imagery.collection import ImageryCollection + + +def test_imagery_stac_collection_initialise() -> None: + title = "Test Urban Imagery" + description = "Test Urban Imagery Description" + collection = ImageryCollection(title, description) + + assert collection.stac["title"] == title + assert collection.stac["description"] == description From 3aebf908e0e0a4813dc7056cfe562fd326308138 Mon Sep 17 00:00:00 2001 From: Megan Davidson Date: Fri, 9 Sep 2022 15:29:12 +1200 Subject: [PATCH 03/14] fix: appease mypy --- scripts/stac/imagery/collection.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/scripts/stac/imagery/collection.py b/scripts/stac/imagery/collection.py index 3cbe6b605..ae029df45 100644 --- a/scripts/stac/imagery/collection.py +++ b/scripts/stac/imagery/collection.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, Optional +from typing import Any, Dict, List, Optional import ulid @@ -18,3 +18,19 @@ def __init__(self, title: Optional[str] = None, description: Optional[str] = Non "license": "CC-BY-4.0", "links": [{"rel": "self", "href": "./collection.json", "type": "application/json"}], } + + def add_link(self, href: str, rel: str = "item", file_type: str = "application/json") -> None: + # Will be implemented in Future PR + pass + + def update_spatial_extent(self, item_bbox: List[float]) -> None: + # Will be implemented in Future PR + pass + + def update_temporal_extent(self, item_start_datetime: str, item_end_datetime: str) -> None: + # Will be implemented in Future PR + pass + + def update_extent(self, bbox: Optional[List[float]] = None, interval: Optional[List[str]] = None) -> None: + # Will be implemented in Future PR + pass From a039c60abb64b9b5b3d53f6d4a25392c2d1c2c80 Mon Sep 17 00:00:00 2001 From: Megan Davidson Date: Mon, 19 Sep 2022 14:25:05 +1200 Subject: [PATCH 04/14] fix: move stac version to its own file for reuse --- scripts/stac/imagery/collection.py | 4 +++- scripts/stac/util/STAC_VERSION.py | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 scripts/stac/util/STAC_VERSION.py diff --git a/scripts/stac/imagery/collection.py b/scripts/stac/imagery/collection.py index ae029df45..2af74aa1e 100644 --- a/scripts/stac/imagery/collection.py +++ b/scripts/stac/imagery/collection.py @@ -2,6 +2,8 @@ import ulid +from scripts.stac.util.STAC_VERSION import STAC_VERSION + PYSTAC_VERSION = "1.0.0" @@ -11,7 +13,7 @@ class ImageryCollection: def __init__(self, title: Optional[str] = None, description: Optional[str] = None) -> None: self.stac = { "type": "Collection", - "stac_version": PYSTAC_VERSION, + "stac_version": STAC_VERSION, "id": str(ulid.ULID()), "title": title, "description": description, diff --git a/scripts/stac/util/STAC_VERSION.py b/scripts/stac/util/STAC_VERSION.py new file mode 100644 index 000000000..da99fa74c --- /dev/null +++ b/scripts/stac/util/STAC_VERSION.py @@ -0,0 +1 @@ +STAC_VERSION = "1.0.0" From b01d18cc5cf1c1ebcc1c49e46d1e80e7829187bc Mon Sep 17 00:00:00 2001 From: Megan Davidson Date: Fri, 9 Sep 2022 15:44:39 +1200 Subject: [PATCH 05/14] feat: create items --- scripts/cli/cli_helper.py | 41 +++++++++++++++-- scripts/create_stac_items.py | 66 ++++++++++++++++++++++++++++ scripts/gdal/gdalinfo.py | 25 +++++++++++ scripts/stac/imagery/collection.py | 25 +++++++---- scripts/stac/imagery/item.py | 52 ++++++++++++++++++++++ scripts/stac/tests/item_test.py | 27 ++++++++++++ scripts/stac/util/checksum.py | 17 +++++++ scripts/stac/util/geotiff.py | 16 +++++++ scripts/stac/util/stac_extensions.py | 5 +++ 9 files changed, 262 insertions(+), 12 deletions(-) create mode 100644 scripts/create_stac_items.py create mode 100644 scripts/gdal/gdalinfo.py create mode 100644 scripts/stac/imagery/item.py create mode 100644 scripts/stac/tests/item_test.py create mode 100644 scripts/stac/util/checksum.py create mode 100644 scripts/stac/util/geotiff.py create mode 100644 scripts/stac/util/stac_extensions.py diff --git a/scripts/cli/cli_helper.py b/scripts/cli/cli_helper.py index 6f9e85219..993e41753 100644 --- a/scripts/cli/cli_helper.py +++ b/scripts/cli/cli_helper.py @@ -1,8 +1,10 @@ import argparse import json +from datetime import datetime from os import environ from typing import List +from dateutil import parser, tz from linz_logger import get_log @@ -26,12 +28,45 @@ def parse_source() -> List[str]: Returns: List[str]: A list of paths. """ - parser = argparse.ArgumentParser() - parser.add_argument("--source", dest="source", nargs="+", required=True) - arguments = parser.parse_args() + parser_args = argparse.ArgumentParser() + parser_args.add_argument("--source", dest="source", nargs="+", required=True) + arguments = parser_args.parse_args() return format_source(arguments.source) def is_argo() -> bool: return bool(environ.get("ARGO_TEMPLATE")) + + +def format_date(date: datetime) -> str: + """Parse the CLI argument '--date' and format it to UTC. + Args: + date: datetime + Returns: + str: date and time in UTC + """ + date_string_nz = f"{date.strftime('%Y-%m-%d')}T00:00:00.000" + datetime_utc = nzt_datetime_to_utc_datetime(date_string_nz) + return datetime_utc.strftime("%Y-%m-%dT%H:%M:%S") + "Z" + + +def nzt_datetime_to_utc_datetime(date: str) -> datetime: + utc_tz = tz.gettz("UTC") + nz_tz = tz.gettz("Pacific/Auckland") + + try: + nz_time = parser.parse(date).replace(tzinfo=nz_tz) + except parser.ParserError as err: + raise Exception(f"Not a valid date: {err}") from err + + utc_time: datetime = nz_time.astimezone(utc_tz) + return utc_time + + +def valid_date(s: str) -> datetime: + try: + return datetime.strptime(s, "%Y-%m-%d") + except ValueError as e: + msg = f"not a valid date: {s}" + raise argparse.ArgumentTypeError(msg) from e diff --git a/scripts/create_stac_items.py b/scripts/create_stac_items.py new file mode 100644 index 000000000..8eaf8c48f --- /dev/null +++ b/scripts/create_stac_items.py @@ -0,0 +1,66 @@ +import argparse +import json +import os +from typing import List + +from linz_logger import get_log + +from scripts.cli.cli_helper import format_date, format_source, valid_date +from scripts.files.files_helper import get_file_name_from_path, is_tiff +from scripts.files.fs import read, write +from scripts.logging.time_helper import time_in_ms +from scripts.stac.imagery.collection import ImageryCollection +from scripts.stac.imagery.item import ImageryItem +from scripts.stac.util.geotiff import get_extents + + +def create_imagery_items(files: List[str], start_datetime: str, end_datetime: str, collection_path: str) -> None: + start_time = time_in_ms() + + get_log().info("read collection object", source=collection_path) + collection = ImageryCollection(stac=json.loads(read(collection_path))) + + get_log().info("create_stac_items_imagery_start", source=files) + + for file in files: + if not is_tiff(file): + get_log().trace("create_stac_file_not_tiff_skipped", file=file) + continue + + id_ = get_file_name_from_path(file) + geometry, bbox = get_extents(file) + + item = ImageryItem(id_, file) + item.update_datetime(start_datetime, end_datetime) + item.update_spatail(geometry, bbox) + item.add_collection(collection.stac["title"], collection_path) + + tmp_file_path = os.path.join("/tmp/", f"{id_}.json") + write(tmp_file_path, json.dumps(item.stac).encode("utf-8")) + get_log().info("imagery_stac_item_created", file=file) + + get_log().info("create_stac_items_imagery_complete", source=files, duration=time_in_ms() - start_time) + + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument("--source", dest="source", nargs="+", required=True) + parser.add_argument( + "--start_datetime", dest="start_datetime", help="start datetime in format YYYY-MM-DD", type=valid_date, required=True + ) + parser.add_argument( + "--end_datetime", dest="end_datetime", help="end datetime in format YYYY-MM-DD", type=valid_date, required=True + ) + parser.add_argument("--collection", dest="collection", help="path to collection.json", required=True) + arguments = parser.parse_args() + + source = format_source(arguments.source) + start_datetime = format_date(arguments.start_datetime) + end_datetime = format_date(arguments.end_datetime) + collection_path = arguments.collection + + create_imagery_items(source, start_datetime, end_datetime, collection_path) + + +if __name__ == "__main__": + main() diff --git a/scripts/gdal/gdalinfo.py b/scripts/gdal/gdalinfo.py new file mode 100644 index 000000000..7c4f51914 --- /dev/null +++ b/scripts/gdal/gdalinfo.py @@ -0,0 +1,25 @@ +import json +from typing import Any, Dict + +from linz_logger import get_log + +from scripts.gdal.gdal_helper import GDALExecutionException, run_gdal + + +def gdal_info(path: str) -> Dict[Any, Any]: + gdalinfo_command = ["gdalinfo", "-stats", "-json", "--config", "GDAL_PAM_ENABLED", "NO"] + try: + gdalinfo_process = run_gdal(gdalinfo_command, path) + gdalinfo_result = {} + try: + gdalinfo_result = json.loads(gdalinfo_process.stdout) + except json.JSONDecodeError as e: + get_log().error("load_gdalinfo_result_error", file=path, error=e) + raise e + if gdalinfo_process.stderr: + get_log().error("Gdalinfo_error", file=path, error=str(gdalinfo_process.stderr)) + raise Exception(f"Gdalinfo Error {str(gdalinfo_process.stderr)}") + return gdalinfo_result + except GDALExecutionException as gee: + get_log().error("gdalinfo_failed", file=path, error=str(gee)) + raise gee diff --git a/scripts/stac/imagery/collection.py b/scripts/stac/imagery/collection.py index 2af74aa1e..292123025 100644 --- a/scripts/stac/imagery/collection.py +++ b/scripts/stac/imagery/collection.py @@ -10,16 +10,23 @@ class ImageryCollection: stac: Dict[str, Any] - def __init__(self, title: Optional[str] = None, description: Optional[str] = None) -> None: - self.stac = { - "type": "Collection", + def __init__( + self, title: Optional[str] = None, description: Optional[str] = None, stac: Optional[Dict[str, Any]] = None + ) -> None: + if stac: + self.stac = stac + elif title and description: + self.stac = { + "type": "Collection", "stac_version": STAC_VERSION, - "id": str(ulid.ULID()), - "title": title, - "description": description, - "license": "CC-BY-4.0", - "links": [{"rel": "self", "href": "./collection.json", "type": "application/json"}], - } + "id": str(ulid.ULID()), + "title": title, + "description": description, + "license": "CC-BY-4.0", + "links": [{"rel": "self", "href": "./collection.json", "type": "application/json"}], + } + else: + raise Exception("incorrect initialising parameters must have 'stac' or 'title and description'") def add_link(self, href: str, rel: str = "item", file_type: str = "application/json") -> None: # Will be implemented in Future PR diff --git a/scripts/stac/imagery/item.py b/scripts/stac/imagery/item.py new file mode 100644 index 000000000..22f313f88 --- /dev/null +++ b/scripts/stac/imagery/item.py @@ -0,0 +1,52 @@ +from typing import Any, Dict, List, Optional + +from scripts.stac.util import checksum +from scripts.stac.util.stac_extensions import StacExtensions + +PYSTAC_VERSION = "1.0.0" + + +class ImageryItem: + stac: Dict[str, Any] + + def __init__(self, id_: Optional[str] = None, path: Optional[str] = None, stac: Optional[Dict[str, Any]] = None) -> None: + if stac: + self.stac = stac + elif id_ and path: + self.stac = { + "type": "Feature", + "stac_version": PYSTAC_VERSION, + "id": id_, + "links": [ + {"rel": "self", "href": f"./{id_}.json", "type": "application/json"}, + ], + "assets": { + "visual": { + "href": path, + "type": "image/tiff; application:geotiff; profile:cloud-optimized", + "file:checksum": checksum.multihash_as_hex(path), + } + }, + "stac_extensions": [StacExtensions.file.value], + } + else: + raise Exception("incorrect initialising parameters must have 'stac' or 'id_ and path'") + + def update_datetime(self, start_datetime: str, end_datetime: str) -> None: + self.stac["properties"] = { + "start_datetime": start_datetime, + "end_datetime": end_datetime, + "datetime": None, + } + + def update_spatail(self, geometry: List[List[float]], bbox: List[float]) -> None: + self.stac["geometry"] = {"type": "Polygon", "coordinates": [geometry]} + self.stac["bbox"] = bbox + + def add_collection(self, title: str, path: str) -> None: + self.stac["collection"] = title + self.add_link(rel="collection", href=path) + self.add_link(rel="parent", href=path) + + def add_link(self, rel: str, href: str, file_type: str = "application/json") -> None: + self.stac["links"].append({"rel": rel, "href": href, "type": file_type}) diff --git a/scripts/stac/tests/item_test.py b/scripts/stac/tests/item_test.py new file mode 100644 index 000000000..2234a5682 --- /dev/null +++ b/scripts/stac/tests/item_test.py @@ -0,0 +1,27 @@ +from scripts.files.files_helper import get_file_name_from_path +from scripts.stac.imagery.item import ImageryItem + + +def test_imagery_stac_item(mocker) -> None: # type: ignore + # mock functions that interact with files + geometry = [[1799667.5, 5815977.0], [1800422.5, 5815977.0], [1800422.5, 5814986.0], [1799667.5, 5814986.0]] + bbox = [1799667.5, 5815977.0, 1800422.5, 5814986.0] + checksum = "1220cdef68d62fb912110b810e62edc53de07f7a44fb2b310db700e9d9dd58baa6b4" + mocker.patch("scripts.stac.util.checksum.multihash_as_hex", return_value=checksum) + + path = "./test/BR34_5000_0302.tiff" + id_ = get_file_name_from_path(path) + start_datetime = "2021-01-27 00:00:00Z" + end_datetime = "2021-01-27 00:00:00Z" + + item = ImageryItem(id_, path) + item.update_spatail(geometry, bbox) + item.update_datetime(start_datetime, end_datetime) + # checks + assert item.stac["id"] == id_ + assert item.stac["properties"]["start_datetime"] == start_datetime + assert item.stac["properties"]["end_datetime"] == end_datetime + assert item.stac["properties"]["datetime"] is None + assert item.stac["geometry"]["coordinates"] == [geometry] + assert item.stac["bbox"] == bbox + assert item.stac["assets"]["visual"]["file:checksum"] == checksum diff --git a/scripts/stac/util/checksum.py b/scripts/stac/util/checksum.py new file mode 100644 index 000000000..5386c4f7c --- /dev/null +++ b/scripts/stac/util/checksum.py @@ -0,0 +1,17 @@ +import hashlib +import io + +import multihash + +from scripts.files import fs + +CHUNK_SIZE = 1024 * 1024 # 1MB + + +def multihash_as_hex(path: str) -> str: + file_hash = hashlib.sha256() + file = io.BytesIO(fs.read(path)) + while chunk := file.read(CHUNK_SIZE): + file_hash.update(chunk) + result: str = multihash.to_hex_string(multihash.encode(file_hash.digest(), "sha2-256")) + return result diff --git a/scripts/stac/util/geotiff.py b/scripts/stac/util/geotiff.py new file mode 100644 index 000000000..8fd0ab968 --- /dev/null +++ b/scripts/stac/util/geotiff.py @@ -0,0 +1,16 @@ +from typing import List, Tuple + +from scripts.gdal.gdalinfo import gdal_info + + +def get_extents(path: str) -> Tuple[List[List[float]], List[float]]: + corner_coordinates = gdal_info(path)["cornerCoordinates"] + + upper_left = [corner_coordinates["upperLeft"][0], corner_coordinates["upperLeft"][1]] + upper_right = [corner_coordinates["upperRight"][0], corner_coordinates["upperRight"][1]] + lower_left = [corner_coordinates["lowerLeft"][0], corner_coordinates["lowerLeft"][1]] + lower_right = [corner_coordinates["lowerRight"][0], corner_coordinates["lowerRight"][1]] + + geometry = [upper_left, upper_right, lower_right, lower_left] + bbox = [upper_left[0], upper_left[1], lower_right[0], lower_right[1]] + return geometry, bbox diff --git a/scripts/stac/util/stac_extensions.py b/scripts/stac/util/stac_extensions.py new file mode 100644 index 000000000..4567f0c69 --- /dev/null +++ b/scripts/stac/util/stac_extensions.py @@ -0,0 +1,5 @@ +from enum import Enum + + +class StacExtensions(str, Enum): + file = "https://stac-extensions.github.io/file/v2.0.0/schema.json" From 925533187e30e98b140505959539e1ae58beaa81 Mon Sep 17 00:00:00 2001 From: Megan Davidson Date: Fri, 9 Sep 2022 15:50:53 +1200 Subject: [PATCH 06/14] fix: add dependencies --- poetry.lock | 491 ++++++++++++++++++++++++++++++++++++++++++------- pyproject.toml | 2 + 2 files changed, 427 insertions(+), 66 deletions(-) diff --git a/poetry.lock b/poetry.lock index 68ef0f443..e42e6cf8f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -39,10 +39,21 @@ optional = false python-versions = ">=3.5" [package.extras] -dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "mypy (>=0.900,!=0.940)", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"] -docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] -tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "mypy (>=0.900,!=0.940)", "pytest-mypy-plugins", "zope.interface", "cloudpickle"] -tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "mypy (>=0.900,!=0.940)", "pytest-mypy-plugins", "cloudpickle"] +tests_no_zope = ["cloudpickle", "pytest-mypy-plugins", "mypy (>=0.900,!=0.940)", "pytest (>=4.3.0)", "pympler", "hypothesis", "coverage[toml] (>=5.0.2)"] +tests = ["cloudpickle", "zope.interface", "pytest-mypy-plugins", "mypy (>=0.900,!=0.940)", "pytest (>=4.3.0)", "pympler", "hypothesis", "coverage[toml] (>=5.0.2)"] +docs = ["sphinx-notfound-page", "zope.interface", "sphinx", "furo"] +dev = ["cloudpickle", "pre-commit", "sphinx-notfound-page", "sphinx", "furo", "zope.interface", "pytest-mypy-plugins", "mypy (>=0.900,!=0.940)", "pytest (>=4.3.0)", "pympler", "hypothesis", "coverage[toml] (>=5.0.2)"] + +[[package]] +name = "base58" +version = "2.1.1" +description = "Base58 and Base58Check implementation." +category = "main" +optional = false +python-versions = ">=3.5" + +[package.extras] +tests = ["mypy", "PyHamcrest (>=2.0.2)", "pytest (>=4.6)", "pytest-benchmark", "pytest-cov", "pytest-flake8"] [[package]] name = "black" @@ -102,7 +113,7 @@ crt = ["awscrt (==0.13.8)"] name = "certifi" version = "2022.6.15" description = "Python package for providing Mozilla's CA Bundle." -category = "dev" +category = "main" optional = false python-versions = ">=3.6" @@ -340,6 +351,14 @@ category = "dev" optional = false python-versions = ">=3.6" +[[package]] +name = "morphys" +version = "1.0" +description = "Smart conversions between unicode and bytes types for common cases" +category = "main" +optional = false +python-versions = "*" + [[package]] name = "moto" version = "3.1.17" @@ -362,28 +381,28 @@ werkzeug = ">=0.5,<2.2.0" xmltodict = "*" [package.extras] -all = ["PyYAML (>=5.1)", "python-jose[cryptography] (>=3.1.0,<4.0.0)", "ecdsa (!=0.15)", "docker (>=2.5.1)", "graphql-core", "jsondiff (>=1.1.2)", "aws-xray-sdk (>=0.93,!=0.96)", "idna (>=2.5,<4)", "cfn-lint (>=0.4.0)", "sshpubkeys (>=3.1.0)", "pyparsing (>=3.0.7)", "openapi-spec-validator (>=0.2.8)", "setuptools"] -apigateway = ["PyYAML (>=5.1)", "python-jose[cryptography] (>=3.1.0,<4.0.0)", "ecdsa (!=0.15)", "openapi-spec-validator (>=0.2.8)"] -apigatewayv2 = ["PyYAML (>=5.1)"] -appsync = ["graphql-core"] -awslambda = ["docker (>=2.5.1)"] -batch = ["docker (>=2.5.1)"] -cloudformation = ["PyYAML (>=5.1)", "python-jose[cryptography] (>=3.1.0,<4.0.0)", "ecdsa (!=0.15)", "docker (>=2.5.1)", "graphql-core", "jsondiff (>=1.1.2)", "aws-xray-sdk (>=0.93,!=0.96)", "idna (>=2.5,<4)", "cfn-lint (>=0.4.0)", "sshpubkeys (>=3.1.0)", "pyparsing (>=3.0.7)", "openapi-spec-validator (>=0.2.8)", "setuptools"] -cognitoidp = ["python-jose[cryptography] (>=3.1.0,<4.0.0)", "ecdsa (!=0.15)"] -ds = ["sshpubkeys (>=3.1.0)"] -dynamodb = ["docker (>=2.5.1)"] -dynamodb2 = ["docker (>=2.5.1)"] -dynamodbstreams = ["docker (>=2.5.1)"] -ebs = ["sshpubkeys (>=3.1.0)"] -ec2 = ["sshpubkeys (>=3.1.0)"] -efs = ["sshpubkeys (>=3.1.0)"] -glue = ["pyparsing (>=3.0.7)"] -iotdata = ["jsondiff (>=1.1.2)"] -route53resolver = ["sshpubkeys (>=3.1.0)"] +xray = ["setuptools", "aws-xray-sdk (>=0.93,!=0.96)"] +ssm = ["dataclasses", "PyYAML (>=5.1)"] +server = ["flask-cors", "flask", "setuptools", "openapi-spec-validator (>=0.2.8)", "pyparsing (>=3.0.7)", "sshpubkeys (>=3.1.0)", "cfn-lint (>=0.4.0)", "idna (>=2.5,<4)", "aws-xray-sdk (>=0.93,!=0.96)", "jsondiff (>=1.1.2)", "graphql-core", "docker (>=2.5.1)", "ecdsa (!=0.15)", "python-jose[cryptography] (>=3.1.0,<4.0.0)", "PyYAML (>=5.1)"] s3 = ["PyYAML (>=5.1)"] -server = ["PyYAML (>=5.1)", "python-jose[cryptography] (>=3.1.0,<4.0.0)", "ecdsa (!=0.15)", "docker (>=2.5.1)", "graphql-core", "jsondiff (>=1.1.2)", "aws-xray-sdk (>=0.93,!=0.96)", "idna (>=2.5,<4)", "cfn-lint (>=0.4.0)", "sshpubkeys (>=3.1.0)", "pyparsing (>=3.0.7)", "openapi-spec-validator (>=0.2.8)", "setuptools", "flask", "flask-cors"] -ssm = ["PyYAML (>=5.1)", "dataclasses"] -xray = ["aws-xray-sdk (>=0.93,!=0.96)", "setuptools"] +route53resolver = ["sshpubkeys (>=3.1.0)"] +iotdata = ["jsondiff (>=1.1.2)"] +glue = ["pyparsing (>=3.0.7)"] +efs = ["sshpubkeys (>=3.1.0)"] +ec2 = ["sshpubkeys (>=3.1.0)"] +ebs = ["sshpubkeys (>=3.1.0)"] +dynamodbstreams = ["docker (>=2.5.1)"] +dynamodb2 = ["docker (>=2.5.1)"] +dynamodb = ["docker (>=2.5.1)"] +ds = ["sshpubkeys (>=3.1.0)"] +cognitoidp = ["ecdsa (!=0.15)", "python-jose[cryptography] (>=3.1.0,<4.0.0)"] +cloudformation = ["setuptools", "openapi-spec-validator (>=0.2.8)", "pyparsing (>=3.0.7)", "sshpubkeys (>=3.1.0)", "cfn-lint (>=0.4.0)", "idna (>=2.5,<4)", "aws-xray-sdk (>=0.93,!=0.96)", "jsondiff (>=1.1.2)", "graphql-core", "docker (>=2.5.1)", "ecdsa (!=0.15)", "python-jose[cryptography] (>=3.1.0,<4.0.0)", "PyYAML (>=5.1)"] +batch = ["docker (>=2.5.1)"] +awslambda = ["docker (>=2.5.1)"] +appsync = ["graphql-core"] +apigatewayv2 = ["PyYAML (>=5.1)"] +apigateway = ["openapi-spec-validator (>=0.2.8)", "ecdsa (!=0.15)", "python-jose[cryptography] (>=3.1.0,<4.0.0)", "PyYAML (>=5.1)"] +all = ["setuptools", "openapi-spec-validator (>=0.2.8)", "pyparsing (>=3.0.7)", "sshpubkeys (>=3.1.0)", "cfn-lint (>=0.4.0)", "idna (>=2.5,<4)", "aws-xray-sdk (>=0.93,!=0.96)", "jsondiff (>=1.1.2)", "graphql-core", "docker (>=2.5.1)", "ecdsa (!=0.15)", "python-jose[cryptography] (>=3.1.0,<4.0.0)", "PyYAML (>=5.1)"] [[package]] name = "mypy" @@ -470,8 +489,8 @@ optional = false python-versions = ">=3.6" [package.extras] -testing = ["pytest-benchmark", "pytest"] -dev = ["tox", "pre-commit"] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] [[package]] name = "pre-commit" @@ -497,6 +516,20 @@ category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +[[package]] +name = "py-multihash" +version = "2.0.1" +description = "Multihash implementation in Python" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +base58 = ">=1.0.2,<3.0" +morphys = ">=1.0,<2.0" +six = ">=1.10.0,<2.0" +varint = ">=1.0.2,<2.0" + [[package]] name = "pycparser" version = "2.21" @@ -571,6 +604,20 @@ python-versions = "*" [package.dependencies] pytest = ">=3.6.0" +[[package]] +name = "pytest-mock" +version = "3.8.2" +description = "Thin-wrapper around the mock package for easier use with pytest" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +pytest = ">=5.0" + +[package.extras] +dev = ["pre-commit", "tox", "pytest-asyncio"] + [[package]] name = "python-dateutil" version = "2.8.2" @@ -621,8 +668,8 @@ idna = ">=2.5,<4" urllib3 = ">=1.21.1,<1.27" [package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)"] use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] [[package]] name = "responses" @@ -723,9 +770,17 @@ optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, <4" [package.extras] -brotli = ["brotlicffi (>=0.8.0)", "brotli (>=1.0.9)", "brotlipy (>=0.6.0)"] -secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] +secure = ["ipaddress", "certifi", "idna (>=2.0.0)", "cryptography (>=1.3.4)", "pyOpenSSL (>=0.14)"] +brotli = ["brotlipy (>=0.6.0)", "brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] + +[[package]] +name = "varint" +version = "1.0.2" +description = "Simple python varint implementation" +category = "main" +optional = false +python-versions = "*" [[package]] name = "virtualenv" @@ -774,70 +829,374 @@ python-versions = ">=3.4" [metadata] lock-version = "1.1" python-versions = "^3.8.10" -content-hash = "f0c00002fe66be4bb7b0a32b63e8e06969466a44723ad8f62ed242ac7841bee4" +content-hash = "92790112add43f439f5c50a33df90ae966f3bf27a2a8077cc6f9208a9b62af2e" [metadata.files] -arrow = [] +arrow = [ + {file = "arrow-1.2.1-py3-none-any.whl", hash = "sha256:6b2914ef3997d1fd7b37a71ce9dd61a6e329d09e1c7b44f4d3099ca4a5c0933e"}, + {file = "arrow-1.2.1.tar.gz", hash = "sha256:c2dde3c382d9f7e6922ce636bf0b318a7a853df40ecb383b29192e6c5cc82840"}, +] astroid = [] atomicwrites = [] attrs = [] +base58 = [ + {file = "base58-2.1.1-py3-none-any.whl", hash = "sha256:11a36f4d3ce51dfc1043f3218591ac4eb1ceb172919cebe05b52a5bcc8d245c2"}, + {file = "base58-2.1.1.tar.gz", hash = "sha256:c5d0cb3f5b6e81e8e35da5754388ddcc6d0d14b6c6a132cb93d69ed580a7278c"}, +] black = [] boto3 = [] botocore = [] -certifi = [] +certifi = [ + {file = "certifi-2022.6.15-py3-none-any.whl", hash = "sha256:fe86415d55e84719d75f8b69414f6438ac3547d2078ab91b67e779ef69378412"}, + {file = "certifi-2022.6.15.tar.gz", hash = "sha256:84c85a9078b11105f04f3036a9482ae10e4621616db313fe045dd24743a0820d"}, +] cffi = [] -cfgv = [] +cfgv = [ + {file = "cfgv-3.3.1-py2.py3-none-any.whl", hash = "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426"}, + {file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"}, +] charset-normalizer = [] -click = [] -colorama = [] +click = [ + {file = "click-8.0.3-py3-none-any.whl", hash = "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3"}, + {file = "click-8.0.3.tar.gz", hash = "sha256:410e932b050f5eed773c4cda94de75971c89cdb3155a72a0831139a79e5ecb5b"}, +] +colorama = [ + {file = "colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"}, + {file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"}, +] cryptography = [] -dill = [] +dill = [ + {file = "dill-0.3.5.1-py2.py3-none-any.whl", hash = "sha256:33501d03270bbe410c72639b350e941882a8b0fd55357580fbc873fba0c59302"}, + {file = "dill-0.3.5.1.tar.gz", hash = "sha256:d75e41f3eff1eee599d738e76ba8f4ad98ea229db8b085318aa2b3333a208c86"}, +] distlib = [] filelock = [] -gitlint = [] -gitlint-core = [] +gitlint = [ + {file = "gitlint-0.17.0-py2.py3-none-any.whl", hash = "sha256:46469d5db3f3bca72fa946c159d0733dc8c75211309477676295cf2d80d177b4"}, + {file = "gitlint-0.17.0.tar.gz", hash = "sha256:8c10c6b404d255b43ddc4a2f5f13bcb10284bc162adfb2c03b10708309009189"}, +] +gitlint-core = [ + {file = "gitlint-core-0.17.0.tar.gz", hash = "sha256:772dfd33effaa8515ca73e901466aa938c19ced894bec6783d19691f57429691"}, + {file = "gitlint_core-0.17.0-py2.py3-none-any.whl", hash = "sha256:cb99ccd736a698b910385211203bda94bf4ce29086d0c08f8f58a18c40a98377"}, +] identify = [] -idna = [] -iniconfig = [] -isort = [] +idna = [ + {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, + {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, +] +iniconfig = [ + {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, + {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, +] +isort = [ + {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"}, + {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"}, +] jinja2 = [] -jmespath = [] -lazy-object-proxy = [] +jmespath = [ + {file = "jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980"}, + {file = "jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"}, +] +lazy-object-proxy = [ + {file = "lazy-object-proxy-1.7.1.tar.gz", hash = "sha256:d609c75b986def706743cdebe5e47553f4a5a1da9c5ff66d76013ef396b5a8a4"}, + {file = "lazy_object_proxy-1.7.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bb8c5fd1684d60a9902c60ebe276da1f2281a318ca16c1d0a96db28f62e9166b"}, + {file = "lazy_object_proxy-1.7.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a57d51ed2997e97f3b8e3500c984db50a554bb5db56c50b5dab1b41339b37e36"}, + {file = "lazy_object_proxy-1.7.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd45683c3caddf83abbb1249b653a266e7069a09f486daa8863fb0e7496a9fdb"}, + {file = "lazy_object_proxy-1.7.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:8561da8b3dd22d696244d6d0d5330618c993a215070f473b699e00cf1f3f6443"}, + {file = "lazy_object_proxy-1.7.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fccdf7c2c5821a8cbd0a9440a456f5050492f2270bd54e94360cac663398739b"}, + {file = "lazy_object_proxy-1.7.1-cp310-cp310-win32.whl", hash = "sha256:898322f8d078f2654d275124a8dd19b079080ae977033b713f677afcfc88e2b9"}, + {file = "lazy_object_proxy-1.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:85b232e791f2229a4f55840ed54706110c80c0a210d076eee093f2b2e33e1bfd"}, + {file = "lazy_object_proxy-1.7.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:46ff647e76f106bb444b4533bb4153c7370cdf52efc62ccfc1a28bdb3cc95442"}, + {file = "lazy_object_proxy-1.7.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:12f3bb77efe1367b2515f8cb4790a11cffae889148ad33adad07b9b55e0ab22c"}, + {file = "lazy_object_proxy-1.7.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c19814163728941bb871240d45c4c30d33b8a2e85972c44d4e63dd7107faba44"}, + {file = "lazy_object_proxy-1.7.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:e40f2013d96d30217a51eeb1db28c9ac41e9d0ee915ef9d00da639c5b63f01a1"}, + {file = "lazy_object_proxy-1.7.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:2052837718516a94940867e16b1bb10edb069ab475c3ad84fd1e1a6dd2c0fcfc"}, + {file = "lazy_object_proxy-1.7.1-cp36-cp36m-win32.whl", hash = "sha256:6a24357267aa976abab660b1d47a34aaf07259a0c3859a34e536f1ee6e76b5bb"}, + {file = "lazy_object_proxy-1.7.1-cp36-cp36m-win_amd64.whl", hash = "sha256:6aff3fe5de0831867092e017cf67e2750c6a1c7d88d84d2481bd84a2e019ec35"}, + {file = "lazy_object_proxy-1.7.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6a6e94c7b02641d1311228a102607ecd576f70734dc3d5e22610111aeacba8a0"}, + {file = "lazy_object_proxy-1.7.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4ce15276a1a14549d7e81c243b887293904ad2d94ad767f42df91e75fd7b5b6"}, + {file = "lazy_object_proxy-1.7.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e368b7f7eac182a59ff1f81d5f3802161932a41dc1b1cc45c1f757dc876b5d2c"}, + {file = "lazy_object_proxy-1.7.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6ecbb350991d6434e1388bee761ece3260e5228952b1f0c46ffc800eb313ff42"}, + {file = "lazy_object_proxy-1.7.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:553b0f0d8dbf21890dd66edd771f9b1b5f51bd912fa5f26de4449bfc5af5e029"}, + {file = "lazy_object_proxy-1.7.1-cp37-cp37m-win32.whl", hash = "sha256:c7a683c37a8a24f6428c28c561c80d5f4fd316ddcf0c7cab999b15ab3f5c5c69"}, + {file = "lazy_object_proxy-1.7.1-cp37-cp37m-win_amd64.whl", hash = "sha256:df2631f9d67259dc9620d831384ed7732a198eb434eadf69aea95ad18c587a28"}, + {file = "lazy_object_proxy-1.7.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:07fa44286cda977bd4803b656ffc1c9b7e3bc7dff7d34263446aec8f8c96f88a"}, + {file = "lazy_object_proxy-1.7.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4dca6244e4121c74cc20542c2ca39e5c4a5027c81d112bfb893cf0790f96f57e"}, + {file = "lazy_object_proxy-1.7.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91ba172fc5b03978764d1df5144b4ba4ab13290d7bab7a50f12d8117f8630c38"}, + {file = "lazy_object_proxy-1.7.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:043651b6cb706eee4f91854da4a089816a6606c1428fd391573ef8cb642ae4f7"}, + {file = "lazy_object_proxy-1.7.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b9e89b87c707dd769c4ea91f7a31538888aad05c116a59820f28d59b3ebfe25a"}, + {file = "lazy_object_proxy-1.7.1-cp38-cp38-win32.whl", hash = "sha256:9d166602b525bf54ac994cf833c385bfcc341b364e3ee71e3bf5a1336e677b55"}, + {file = "lazy_object_proxy-1.7.1-cp38-cp38-win_amd64.whl", hash = "sha256:8f3953eb575b45480db6568306893f0bd9d8dfeeebd46812aa09ca9579595148"}, + {file = "lazy_object_proxy-1.7.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dd7ed7429dbb6c494aa9bc4e09d94b778a3579be699f9d67da7e6804c422d3de"}, + {file = "lazy_object_proxy-1.7.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70ed0c2b380eb6248abdef3cd425fc52f0abd92d2b07ce26359fcbc399f636ad"}, + {file = "lazy_object_proxy-1.7.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7096a5e0c1115ec82641afbdd70451a144558ea5cf564a896294e346eb611be1"}, + {file = "lazy_object_proxy-1.7.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f769457a639403073968d118bc70110e7dce294688009f5c24ab78800ae56dc8"}, + {file = "lazy_object_proxy-1.7.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:39b0e26725c5023757fc1ab2a89ef9d7ab23b84f9251e28f9cc114d5b59c1b09"}, + {file = "lazy_object_proxy-1.7.1-cp39-cp39-win32.whl", hash = "sha256:2130db8ed69a48a3440103d4a520b89d8a9405f1b06e2cc81640509e8bf6548f"}, + {file = "lazy_object_proxy-1.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:677ea950bef409b47e51e733283544ac3d660b709cfce7b187f5ace137960d61"}, + {file = "lazy_object_proxy-1.7.1-pp37.pp38-none-any.whl", hash = "sha256:d66906d5785da8e0be7360912e99c9188b70f52c422f9fc18223347235691a84"}, +] linz-logger = [] -markupsafe = [] -mccabe = [] +markupsafe = [ + {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-win32.whl", hash = "sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-win32.whl", hash = "sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-win32.whl", hash = "sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-win32.whl", hash = "sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247"}, + {file = "MarkupSafe-2.1.1.tar.gz", hash = "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b"}, +] +mccabe = [ + {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, + {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, +] +morphys = [ + {file = "morphys-1.0-py2.py3-none-any.whl", hash = "sha256:76d6dbaa4d65f597e59d332c81da786d83e4669387b9b2a750cfec74e7beec20"}, +] moto = [] -mypy = [] +mypy = [ + {file = "mypy-0.961-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:697540876638ce349b01b6786bc6094ccdaba88af446a9abb967293ce6eaa2b0"}, + {file = "mypy-0.961-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b117650592e1782819829605a193360a08aa99f1fc23d1d71e1a75a142dc7e15"}, + {file = "mypy-0.961-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:bdd5ca340beffb8c44cb9dc26697628d1b88c6bddf5c2f6eb308c46f269bb6f3"}, + {file = "mypy-0.961-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3e09f1f983a71d0672bbc97ae33ee3709d10c779beb613febc36805a6e28bb4e"}, + {file = "mypy-0.961-cp310-cp310-win_amd64.whl", hash = "sha256:e999229b9f3198c0c880d5e269f9f8129c8862451ce53a011326cad38b9ccd24"}, + {file = "mypy-0.961-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b24be97351084b11582fef18d79004b3e4db572219deee0212078f7cf6352723"}, + {file = "mypy-0.961-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f4a21d01fc0ba4e31d82f0fff195682e29f9401a8bdb7173891070eb260aeb3b"}, + {file = "mypy-0.961-cp36-cp36m-win_amd64.whl", hash = "sha256:439c726a3b3da7ca84a0199a8ab444cd8896d95012c4a6c4a0d808e3147abf5d"}, + {file = "mypy-0.961-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5a0b53747f713f490affdceef835d8f0cb7285187a6a44c33821b6d1f46ed813"}, + {file = "mypy-0.961-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0e9f70df36405c25cc530a86eeda1e0867863d9471fe76d1273c783df3d35c2e"}, + {file = "mypy-0.961-cp37-cp37m-win_amd64.whl", hash = "sha256:b88f784e9e35dcaa075519096dc947a388319cb86811b6af621e3523980f1c8a"}, + {file = "mypy-0.961-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:d5aaf1edaa7692490f72bdb9fbd941fbf2e201713523bdb3f4038be0af8846c6"}, + {file = "mypy-0.961-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9f5f5a74085d9a81a1f9c78081d60a0040c3efb3f28e5c9912b900adf59a16e6"}, + {file = "mypy-0.961-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f4b794db44168a4fc886e3450201365c9526a522c46ba089b55e1f11c163750d"}, + {file = "mypy-0.961-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:64759a273d590040a592e0f4186539858c948302c653c2eac840c7a3cd29e51b"}, + {file = "mypy-0.961-cp38-cp38-win_amd64.whl", hash = "sha256:63e85a03770ebf403291ec50097954cc5caf2a9205c888ce3a61bd3f82e17569"}, + {file = "mypy-0.961-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5f1332964963d4832a94bebc10f13d3279be3ce8f6c64da563d6ee6e2eeda932"}, + {file = "mypy-0.961-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:006be38474216b833eca29ff6b73e143386f352e10e9c2fbe76aa8549e5554f5"}, + {file = "mypy-0.961-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9940e6916ed9371809b35b2154baf1f684acba935cd09928952310fbddaba648"}, + {file = "mypy-0.961-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a5ea0875a049de1b63b972456542f04643daf320d27dc592d7c3d9cd5d9bf950"}, + {file = "mypy-0.961-cp39-cp39-win_amd64.whl", hash = "sha256:1ece702f29270ec6af25db8cf6185c04c02311c6bb21a69f423d40e527b75c56"}, + {file = "mypy-0.961-py3-none-any.whl", hash = "sha256:03c6cc893e7563e7b2949b969e63f02c000b32502a1b4d1314cabe391aa87d66"}, + {file = "mypy-0.961.tar.gz", hash = "sha256:f730d56cb924d371c26b8eaddeea3cc07d78ff51c521c6d04899ac6904b75492"}, +] mypy-boto3-s3 = [] -mypy-extensions = [] +mypy-extensions = [ + {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, + {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, +] nodeenv = [] -packaging = [] -pathspec = [] -platformdirs = [] -pluggy = [] +packaging = [ + {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, + {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, +] +pathspec = [ + {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"}, + {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, +] +platformdirs = [ + {file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"}, + {file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"}, +] +pluggy = [ + {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, + {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, +] pre-commit = [] -py = [] -pycparser = [] +py = [ + {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, + {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, +] +py-multihash = [ + {file = "py-multihash-2.0.1.tar.gz", hash = "sha256:b97511a87b7091f8b37a3d74ccb4a898e133529e7c5e431f9a27f78248a75e60"}, + {file = "py_multihash-2.0.1-py2.py3-none-any.whl", hash = "sha256:c388728b3456d35cd6668b42a3d9ba32dd640493c8e93b992979668dcf2c0676"}, +] +pycparser = [ + {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, + {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, +] pylint = [] -pyparsing = [] -pytest = [] +pyparsing = [ + {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, + {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, +] +pytest = [ + {file = "pytest-7.1.2-py3-none-any.whl", hash = "sha256:13d0e3ccfc2b6e26be000cb6568c832ba67ba32e719443bfe725814d3c42433c"}, + {file = "pytest-7.1.2.tar.gz", hash = "sha256:a06a0425453864a270bc45e71f783330a7428defb4230fb5e6a731fde06ecd45"}, +] pytest-dependency = [] -python-dateutil = [] +pytest-mock = [] +python-dateutil = [ + {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, + {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, +] python-ulid = [] -pytz = [] -pyyaml = [] +pytz = [ + {file = "pytz-2022.1-py2.py3-none-any.whl", hash = "sha256:e68985985296d9a66a881eb3193b0906246245294a881e7c8afe623866ac6a5c"}, + {file = "pytz-2022.1.tar.gz", hash = "sha256:1e760e2fe6a8163bc0b3d9a19c4f84342afa0a2affebfaa84b01b978a02ecaa7"}, +] +pyyaml = [ + {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, + {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, + {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, + {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, + {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, + {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, + {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, + {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, + {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, + {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, + {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, + {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, + {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, + {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, + {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, + {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, + {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, + {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, +] requests = [] responses = [] -s3transfer = [] -sh = [] -six = [] +s3transfer = [ + {file = "s3transfer-0.6.0-py3-none-any.whl", hash = "sha256:06176b74f3a15f61f1b4f25a1fc29a4429040b7647133a463da8fa5bd28d5ecd"}, + {file = "s3transfer-0.6.0.tar.gz", hash = "sha256:2ed07d3866f523cc561bf4a00fc5535827981b117dd7876f036b0c1aca42c947"}, +] +sh = [ + {file = "sh-1.14.2-py2.py3-none-any.whl", hash = "sha256:4921ac9c1a77ec8084bdfaf152fe14138e2b3557cc740002c1a97076321fce8a"}, + {file = "sh-1.14.2.tar.gz", hash = "sha256:9d7bd0334d494b2a4609fe521b2107438cdb21c0e469ffeeb191489883d6fe0d"}, +] +six = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] structlog = [] -toml = [] -tomli = [] +toml = [ + {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, + {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, +] +tomli = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] tomlkit = [] typing-extensions = [] urllib3 = [] +varint = [ + {file = "varint-1.0.2.tar.gz", hash = "sha256:a6ecc02377ac5ee9d65a6a8ad45c9ff1dac8ccee19400a5950fb51d594214ca5"}, +] virtualenv = [] werkzeug = [] -wrapt = [] +wrapt = [ + {file = "wrapt-1.14.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1b376b3f4896e7930f1f772ac4b064ac12598d1c38d04907e696cc4d794b43d3"}, + {file = "wrapt-1.14.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:903500616422a40a98a5a3c4ff4ed9d0066f3b4c951fa286018ecdf0750194ef"}, + {file = "wrapt-1.14.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5a9a0d155deafd9448baff28c08e150d9b24ff010e899311ddd63c45c2445e28"}, + {file = "wrapt-1.14.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ddaea91abf8b0d13443f6dac52e89051a5063c7d014710dcb4d4abb2ff811a59"}, + {file = "wrapt-1.14.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:36f582d0c6bc99d5f39cd3ac2a9062e57f3cf606ade29a0a0d6b323462f4dd87"}, + {file = "wrapt-1.14.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:7ef58fb89674095bfc57c4069e95d7a31cfdc0939e2a579882ac7d55aadfd2a1"}, + {file = "wrapt-1.14.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:e2f83e18fe2f4c9e7db597e988f72712c0c3676d337d8b101f6758107c42425b"}, + {file = "wrapt-1.14.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:ee2b1b1769f6707a8a445162ea16dddf74285c3964f605877a20e38545c3c462"}, + {file = "wrapt-1.14.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:833b58d5d0b7e5b9832869f039203389ac7cbf01765639c7309fd50ef619e0b1"}, + {file = "wrapt-1.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:80bb5c256f1415f747011dc3604b59bc1f91c6e7150bd7db03b19170ee06b320"}, + {file = "wrapt-1.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:07f7a7d0f388028b2df1d916e94bbb40624c59b48ecc6cbc232546706fac74c2"}, + {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:02b41b633c6261feff8ddd8d11c711df6842aba629fdd3da10249a53211a72c4"}, + {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2fe803deacd09a233e4762a1adcea5db5d31e6be577a43352936179d14d90069"}, + {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:257fd78c513e0fb5cdbe058c27a0624c9884e735bbd131935fd49e9fe719d310"}, + {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4fcc4649dc762cddacd193e6b55bc02edca674067f5f98166d7713b193932b7f"}, + {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:11871514607b15cfeb87c547a49bca19fde402f32e2b1c24a632506c0a756656"}, + {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8ad85f7f4e20964db4daadcab70b47ab05c7c1cf2a7c1e51087bfaa83831854c"}, + {file = "wrapt-1.14.1-cp310-cp310-win32.whl", hash = "sha256:a9a52172be0b5aae932bef82a79ec0a0ce87288c7d132946d645eba03f0ad8a8"}, + {file = "wrapt-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:6d323e1554b3d22cfc03cd3243b5bb815a51f5249fdcbb86fda4bf62bab9e164"}, + {file = "wrapt-1.14.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:43ca3bbbe97af00f49efb06e352eae40434ca9d915906f77def219b88e85d907"}, + {file = "wrapt-1.14.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:6b1a564e6cb69922c7fe3a678b9f9a3c54e72b469875aa8018f18b4d1dd1adf3"}, + {file = "wrapt-1.14.1-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3"}, + {file = "wrapt-1.14.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:a85d2b46be66a71bedde836d9e41859879cc54a2a04fad1191eb50c2066f6e9d"}, + {file = "wrapt-1.14.1-cp35-cp35m-win32.whl", hash = "sha256:dbcda74c67263139358f4d188ae5faae95c30929281bc6866d00573783c422b7"}, + {file = "wrapt-1.14.1-cp35-cp35m-win_amd64.whl", hash = "sha256:b21bb4c09ffabfa0e85e3a6b623e19b80e7acd709b9f91452b8297ace2a8ab00"}, + {file = "wrapt-1.14.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:9e0fd32e0148dd5dea6af5fee42beb949098564cc23211a88d799e434255a1f4"}, + {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9736af4641846491aedb3c3f56b9bc5568d92b0692303b5a305301a95dfd38b1"}, + {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b02d65b9ccf0ef6c34cba6cf5bf2aab1bb2f49c6090bafeecc9cd81ad4ea1c1"}, + {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21ac0156c4b089b330b7666db40feee30a5d52634cc4560e1905d6529a3897ff"}, + {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:9f3e6f9e05148ff90002b884fbc2a86bd303ae847e472f44ecc06c2cd2fcdb2d"}, + {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:6e743de5e9c3d1b7185870f480587b75b1cb604832e380d64f9504a0535912d1"}, + {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:d79d7d5dc8a32b7093e81e97dad755127ff77bcc899e845f41bf71747af0c569"}, + {file = "wrapt-1.14.1-cp36-cp36m-win32.whl", hash = "sha256:81b19725065dcb43df02b37e03278c011a09e49757287dca60c5aecdd5a0b8ed"}, + {file = "wrapt-1.14.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b014c23646a467558be7da3d6b9fa409b2c567d2110599b7cf9a0c5992b3b471"}, + {file = "wrapt-1.14.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:88bd7b6bd70a5b6803c1abf6bca012f7ed963e58c68d76ee20b9d751c74a3248"}, + {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5901a312f4d14c59918c221323068fad0540e34324925c8475263841dbdfe68"}, + {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d77c85fedff92cf788face9bfa3ebaa364448ebb1d765302e9af11bf449ca36d"}, + {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d649d616e5c6a678b26d15ece345354f7c2286acd6db868e65fcc5ff7c24a77"}, + {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7d2872609603cb35ca513d7404a94d6d608fc13211563571117046c9d2bcc3d7"}, + {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015"}, + {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2b39d38039a1fdad98c87279b48bc5dce2c0ca0d73483b12cb72aa9609278e8a"}, + {file = "wrapt-1.14.1-cp37-cp37m-win32.whl", hash = "sha256:60db23fa423575eeb65ea430cee741acb7c26a1365d103f7b0f6ec412b893853"}, + {file = "wrapt-1.14.1-cp37-cp37m-win_amd64.whl", hash = "sha256:709fe01086a55cf79d20f741f39325018f4df051ef39fe921b1ebe780a66184c"}, + {file = "wrapt-1.14.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8c0ce1e99116d5ab21355d8ebe53d9460366704ea38ae4d9f6933188f327b456"}, + {file = "wrapt-1.14.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e3fb1677c720409d5f671e39bac6c9e0e422584e5f518bfd50aa4cbbea02433f"}, + {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:642c2e7a804fcf18c222e1060df25fc210b9c58db7c91416fb055897fc27e8cc"}, + {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b7c050ae976e286906dd3f26009e117eb000fb2cf3533398c5ad9ccc86867b1"}, + {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af"}, + {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:01c205616a89d09827986bc4e859bcabd64f5a0662a7fe95e0d359424e0e071b"}, + {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5a0f54ce2c092aaf439813735584b9537cad479575a09892b8352fea5e988dc0"}, + {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2cf71233a0ed05ccdabe209c606fe0bac7379fdcf687f39b944420d2a09fdb57"}, + {file = "wrapt-1.14.1-cp38-cp38-win32.whl", hash = "sha256:aa31fdcc33fef9eb2552cbcbfee7773d5a6792c137b359e82879c101e98584c5"}, + {file = "wrapt-1.14.1-cp38-cp38-win_amd64.whl", hash = "sha256:d1967f46ea8f2db647c786e78d8cc7e4313dbd1b0aca360592d8027b8508e24d"}, + {file = "wrapt-1.14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3232822c7d98d23895ccc443bbdf57c7412c5a65996c30442ebe6ed3df335383"}, + {file = "wrapt-1.14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:988635d122aaf2bdcef9e795435662bcd65b02f4f4c1ae37fbee7401c440b3a7"}, + {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cca3c2cdadb362116235fdbd411735de4328c61425b0aa9f872fd76d02c4e86"}, + {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d52a25136894c63de15a35bc0bdc5adb4b0e173b9c0d07a2be9d3ca64a332735"}, + {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40e7bc81c9e2b2734ea4bc1aceb8a8f0ceaac7c5299bc5d69e37c44d9081d43b"}, + {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b9b7a708dd92306328117d8c4b62e2194d00c365f18eff11a9b53c6f923b01e3"}, + {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6a9a25751acb379b466ff6be78a315e2b439d4c94c1e99cb7266d40a537995d3"}, + {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:34aa51c45f28ba7f12accd624225e2b1e5a3a45206aa191f6f9aac931d9d56fe"}, + {file = "wrapt-1.14.1-cp39-cp39-win32.whl", hash = "sha256:dee0ce50c6a2dd9056c20db781e9c1cfd33e77d2d569f5d1d9321c641bb903d5"}, + {file = "wrapt-1.14.1-cp39-cp39-win_amd64.whl", hash = "sha256:dee60e1de1898bde3b238f18340eec6148986da0455d8ba7848d50470a7a32fb"}, + {file = "wrapt-1.14.1.tar.gz", hash = "sha256:380a85cf89e0e69b7cfbe2ea9f765f004ff419f34194018a6827ac0e3edfed4d"}, +] xmltodict = [] diff --git a/pyproject.toml b/pyproject.toml index 9a5c1efb6..b06bd52f1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,6 +40,7 @@ python = "^3.8.10" boto3 = "^1.24.12" linz-logger = "^0.9.0" certifi = "^2022.6.15" +py-multihash = "^2.0.1" [tool.poetry.dev-dependencies] black = "^22.3.0" @@ -52,3 +53,4 @@ mypy-boto3-s3 = "^1.24.0" pytest = "^7.1.2" pytest-dependency = "^0.5.1" moto = "^3.1.16" +pytest-mock = "^3.8.2" From bb87eeabde563810140a6981f2da8997e8990df8 Mon Sep 17 00:00:00 2001 From: Megan Davidson Date: Tue, 20 Sep 2022 11:10:17 +1200 Subject: [PATCH 07/14] fix: minor code tidy and add test --- scripts/create_stac_items.py | 4 ++-- scripts/stac/imagery/collection.py | 4 +--- scripts/stac/imagery/item.py | 12 ++++++------ scripts/stac/tests/item_test.py | 21 +++++++++++++++++++-- 4 files changed, 28 insertions(+), 13 deletions(-) diff --git a/scripts/create_stac_items.py b/scripts/create_stac_items.py index 8eaf8c48f..e30adab9b 100644 --- a/scripts/create_stac_items.py +++ b/scripts/create_stac_items.py @@ -32,8 +32,8 @@ def create_imagery_items(files: List[str], start_datetime: str, end_datetime: st item = ImageryItem(id_, file) item.update_datetime(start_datetime, end_datetime) - item.update_spatail(geometry, bbox) - item.add_collection(collection.stac["title"], collection_path) + item.update_spatial(geometry, bbox) + item.add_collection(collection, collection_path) tmp_file_path = os.path.join("/tmp/", f"{id_}.json") write(tmp_file_path, json.dumps(item.stac).encode("utf-8")) diff --git a/scripts/stac/imagery/collection.py b/scripts/stac/imagery/collection.py index 292123025..7549456db 100644 --- a/scripts/stac/imagery/collection.py +++ b/scripts/stac/imagery/collection.py @@ -4,8 +4,6 @@ from scripts.stac.util.STAC_VERSION import STAC_VERSION -PYSTAC_VERSION = "1.0.0" - class ImageryCollection: stac: Dict[str, Any] @@ -18,7 +16,7 @@ def __init__( elif title and description: self.stac = { "type": "Collection", - "stac_version": STAC_VERSION, + "stac_version": STAC_VERSION, "id": str(ulid.ULID()), "title": title, "description": description, diff --git a/scripts/stac/imagery/item.py b/scripts/stac/imagery/item.py index 22f313f88..413bf9b0c 100644 --- a/scripts/stac/imagery/item.py +++ b/scripts/stac/imagery/item.py @@ -1,10 +1,10 @@ from typing import Any, Dict, List, Optional +from scripts.stac.imagery.collection import ImageryCollection from scripts.stac.util import checksum +from scripts.stac.util.STAC_VERSION import STAC_VERSION from scripts.stac.util.stac_extensions import StacExtensions -PYSTAC_VERSION = "1.0.0" - class ImageryItem: stac: Dict[str, Any] @@ -15,7 +15,7 @@ def __init__(self, id_: Optional[str] = None, path: Optional[str] = None, stac: elif id_ and path: self.stac = { "type": "Feature", - "stac_version": PYSTAC_VERSION, + "stac_version": STAC_VERSION, "id": id_, "links": [ {"rel": "self", "href": f"./{id_}.json", "type": "application/json"}, @@ -39,12 +39,12 @@ def update_datetime(self, start_datetime: str, end_datetime: str) -> None: "datetime": None, } - def update_spatail(self, geometry: List[List[float]], bbox: List[float]) -> None: + def update_spatial(self, geometry: List[List[float]], bbox: List[float]) -> None: self.stac["geometry"] = {"type": "Polygon", "coordinates": [geometry]} self.stac["bbox"] = bbox - def add_collection(self, title: str, path: str) -> None: - self.stac["collection"] = title + def add_collection(self, collection: ImageryCollection, path: str) -> None: + self.stac["collection"] = collection.stac["title"] self.add_link(rel="collection", href=path) self.add_link(rel="parent", href=path) diff --git a/scripts/stac/tests/item_test.py b/scripts/stac/tests/item_test.py index 2234a5682..920910c71 100644 --- a/scripts/stac/tests/item_test.py +++ b/scripts/stac/tests/item_test.py @@ -1,5 +1,5 @@ from scripts.files.files_helper import get_file_name_from_path -from scripts.stac.imagery.item import ImageryItem +from scripts.stac.imagery.item import ImageryCollection, ImageryItem def test_imagery_stac_item(mocker) -> None: # type: ignore @@ -15,7 +15,7 @@ def test_imagery_stac_item(mocker) -> None: # type: ignore end_datetime = "2021-01-27 00:00:00Z" item = ImageryItem(id_, path) - item.update_spatail(geometry, bbox) + item.update_spatial(geometry, bbox) item.update_datetime(start_datetime, end_datetime) # checks assert item.stac["id"] == id_ @@ -25,3 +25,20 @@ def test_imagery_stac_item(mocker) -> None: # type: ignore assert item.stac["geometry"]["coordinates"] == [geometry] assert item.stac["bbox"] == bbox assert item.stac["assets"]["visual"]["file:checksum"] == checksum + + +def test_imagery_add_collection(mocker) -> None: # type: ignore + title = "Collection" + description = "Collection Description" + collection = ImageryCollection(title=title, description=description) + + path = "./test/BR34_5000_0302.tiff" + id_ = get_file_name_from_path(path) + checksum = "1220cdef68d62fb912110b810e62edc53de07f7a44fb2b310db700e9d9dd58baa6b4" + mocker.patch("scripts.stac.util.checksum.multihash_as_hex", return_value=checksum) + item = ImageryItem(id_, path) + + item.add_collection(collection, "fake/path.json") + + assert item.stac["collection"] == "Collection" + assert {"rel": "collection", "href": "fake/path.json", "type": "application/json"} in item.stac["links"] From 9a6ae29174382e7304644fff682cf88a91315fb4 Mon Sep 17 00:00:00 2001 From: Megan Davidson Date: Fri, 9 Sep 2022 15:58:58 +1200 Subject: [PATCH 08/14] feat: implement update collection --- scripts/files/files_helper.py | 4 ++ scripts/stac/imagery/collection.py | 80 ++++++++++++++++++++++++--- scripts/stac/tests/collection_test.py | 12 ++++ scripts/update_stac_collection.py | 49 ++++++++++++++++ 4 files changed, 137 insertions(+), 8 deletions(-) create mode 100644 scripts/update_stac_collection.py diff --git a/scripts/files/files_helper.py b/scripts/files/files_helper.py index 8756eee27..9dd9ac754 100644 --- a/scripts/files/files_helper.py +++ b/scripts/files/files_helper.py @@ -8,3 +8,7 @@ def get_file_name_from_path(path: str) -> str: def is_tiff(path: str) -> bool: return path.lower().endswith((".tiff", ".tif")) + + +def is_json(path: str) -> bool: + return path.lower().endswith(".json") diff --git a/scripts/stac/imagery/collection.py b/scripts/stac/imagery/collection.py index 7549456db..77ccd7a81 100644 --- a/scripts/stac/imagery/collection.py +++ b/scripts/stac/imagery/collection.py @@ -1,3 +1,4 @@ +from datetime import datetime from typing import Any, Dict, List, Optional import ulid @@ -27,17 +28,80 @@ def __init__( raise Exception("incorrect initialising parameters must have 'stac' or 'title and description'") def add_link(self, href: str, rel: str = "item", file_type: str = "application/json") -> None: - # Will be implemented in Future PR - pass + self.stac["links"].append({"rel": rel, "href": href, "type": file_type}) def update_spatial_extent(self, item_bbox: List[float]) -> None: - # Will be implemented in Future PR - pass + if "extent" not in self.stac: + self.update_extent(bbox=item_bbox) + return + if not self.stac["extent"]["spatial"]["bbox"]: + self.update_extent(bbox=item_bbox) + return + + bbox = self.stac["extent"]["spatial"]["bbox"] + min_x = min(bbox[0], bbox[2]) + max_x = max(bbox[0], bbox[2]) + min_y = min(bbox[1], bbox[3]) + max_y = max(bbox[1], bbox[3]) + + item_min_x = min(item_bbox[0], item_bbox[2]) + item_max_x = max(item_bbox[0], item_bbox[2]) + item_min_y = min(item_bbox[1], item_bbox[3]) + item_max_y = max(item_bbox[1], item_bbox[3]) + + if item_min_x < min_x: + min_x = item_min_x + if item_min_y < min_y: + min_y = item_min_y + if item_max_x > max_x: + max_x = item_max_x + if item_max_y > max_y: + max_y = item_max_y + + self.update_extent(bbox=[min_x, min_y, max_x, max_y]) def update_temporal_extent(self, item_start_datetime: str, item_end_datetime: str) -> None: - # Will be implemented in Future PR - pass + if "extent" not in self.stac: + self.update_extent(interval=[item_start_datetime, item_end_datetime]) + return + if not self.stac["extent"]["temporal"]["interval"]: + self.update_extent(interval=[item_start_datetime, item_end_datetime]) + return + + interval = self.stac["extent"]["temporal"]["interval"] + + item_start = datetime.strptime(item_start_datetime, "%Y-%m-%dT%H:%M:%SZ") + item_end = datetime.strptime(item_end_datetime, "%Y-%m-%dT%H:%M:%SZ") + + collection_datetimes = [] + for date in interval: + collection_datetimes.append(datetime.strptime(date, "%Y-%m-%dT%H:%M:%SZ")) + + start_datetime = min(collection_datetimes[0], collection_datetimes[1]) + end_datetime = max(collection_datetimes[0], collection_datetimes[1]) + + if item_start < start_datetime: + start_datetime = item_start + if item_end > end_datetime: + end_datetime = item_end + + self.update_extent( + interval=[ + start_datetime.strftime("%Y-%m-%dT%H:%M:%SZ"), + end_datetime.strftime("%Y-%m-%dT%H:%M:%SZ"), + ] + ) def update_extent(self, bbox: Optional[List[float]] = None, interval: Optional[List[str]] = None) -> None: - # Will be implemented in Future PR - pass + if "extent" not in self.stac: + self.stac["extent"] = { + "spatial": { + "bbox": bbox, + }, + "temporal": {"interval": interval}, + } + return + if bbox: + self.stac["extent"]["spatial"]["bbox"] = bbox + if interval: + self.stac["extent"]["temporal"]["interval"] = interval diff --git a/scripts/stac/tests/collection_test.py b/scripts/stac/tests/collection_test.py index 50ca500c8..2c98ecd28 100644 --- a/scripts/stac/tests/collection_test.py +++ b/scripts/stac/tests/collection_test.py @@ -8,3 +8,15 @@ def test_imagery_stac_collection_initialise() -> None: assert collection.stac["title"] == title assert collection.stac["description"] == description + + +def test_imagery_stac_collection_update() -> None: + title = "Test Urban Imagery" + description = "Test Urban Imagery Description" + bbox = [1799667.5, 5815977.0, 1800422.5, 5814986.0] + start_datetime = "2021-01-27T00:00:00Z" + end_datetime = "2021-01-27T00:00:00Z" + collection = ImageryCollection(title, description) + collection.update_spatial_extent(bbox) + collection.update_temporal_extent(start_datetime, end_datetime) + assert collection.stac["extent"]["temporal"]["interval"] == [start_datetime, end_datetime] diff --git a/scripts/update_stac_collection.py b/scripts/update_stac_collection.py new file mode 100644 index 000000000..03ad72ae6 --- /dev/null +++ b/scripts/update_stac_collection.py @@ -0,0 +1,49 @@ +import argparse +import json +from typing import List + +from linz_logger import get_log + +from scripts.cli.cli_helper import format_source +from scripts.files.files_helper import is_json +from scripts.files.fs import read, write +from scripts.logging.time_helper import time_in_ms +from scripts.stac.imagery.collection import ImageryCollection +from scripts.stac.imagery.item import ImageryItem + + +def update_imagery_collection(files: List[str], collection_path: str) -> None: + start_time = time_in_ms() + get_log().info("finalise_stac_collection_imagery_start", collection=collection_path) + + collection = ImageryCollection(stac=json.loads(read(collection_path))) + + for file in files: + if not is_json(file): + get_log().trace("create_stac_file_not_tiff_skipped", file=file) + item = ImageryItem(stac=json.loads(read(file))) + collection.add_link(href=file) + collection.update_temporal_extent(item.stac["properties"]["start_datetime"], item.stac["properties"]["end_datetime"]) + collection.update_spatial_extent(item.stac["bbox"]) + + write(collection_path, json.dumps(collection.stac).encode("utf-8")) + + get_log().info( + "update_stac_collection_imagery_complete", collection=collection.stac, source=files, duration=time_in_ms() - start_time + ) + + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument("--source", dest="source", nargs="+", required=True) + parser.add_argument("--collection", dest="collection", help="path to collection.json", required=True) + arguments = parser.parse_args() + + files = format_source(arguments.source) + collection_path = arguments.collection + + update_imagery_collection(files, collection_path) + + +if __name__ == "__main__": + main() From 5e398daf02dbd10273f354e951254548ffe07cd3 Mon Sep 17 00:00:00 2001 From: Megan Davidson Date: Fri, 9 Sep 2022 16:03:46 +1200 Subject: [PATCH 09/14] fix: appease pylint will be reverted in next PR --- scripts/standardise_validate.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/standardise_validate.py b/scripts/standardise_validate.py index d2da2a4b6..90b94f311 100644 --- a/scripts/standardise_validate.py +++ b/scripts/standardise_validate.py @@ -10,10 +10,10 @@ def main() -> None: concurrency: int = 1 - parser = argparse.ArgumentParser() - parser.add_argument("--preset", dest="preset", required=True) - parser.add_argument("--source", dest="source", nargs="+", required=True) - arguments = parser.parse_args() + parse_args = argparse.ArgumentParser() + parse_args.add_argument("--preset", dest="preset", required=True) + parse_args.add_argument("--source", dest="source", nargs="+", required=True) + arguments = parse_args.parse_args() source = format_source(arguments.source) From bc924554fca09a7e551dcc29d48eb973d64d88c8 Mon Sep 17 00:00:00 2001 From: Megan Davidson Date: Wed, 21 Sep 2022 11:28:59 +1200 Subject: [PATCH 10/14] test: add more tests --- scripts/stac/tests/collection_test.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/scripts/stac/tests/collection_test.py b/scripts/stac/tests/collection_test.py index 2c98ecd28..e8bbd3966 100644 --- a/scripts/stac/tests/collection_test.py +++ b/scripts/stac/tests/collection_test.py @@ -20,3 +20,24 @@ def test_imagery_stac_collection_update() -> None: collection.update_spatial_extent(bbox) collection.update_temporal_extent(start_datetime, end_datetime) assert collection.stac["extent"]["temporal"]["interval"] == [start_datetime, end_datetime] + + +def test_imagery_stac_collction_update_twice() -> None: + title = "Test Urban Imagery" + description = "Test Urban Imagery Description" + collection = ImageryCollection(title, description) + + bbox_one = [174.889641, -41.217532, 174.902344, -41.203521] + start_datetime_one = "2021-01-27T00:00:00Z" + end_datetime_one = "2021-01-27T00:00:00Z" + collection.update_spatial_extent(bbox_one) + collection.update_temporal_extent(start_datetime_one, end_datetime_one) + + bbox_two = [174.917643, -41.211157, 174.922965, -41.205490] + start_datetime_two = "2021-02-01T00:00:00Z" + end_datetime_two = "2021-02-20T00:00:00Z" + collection.update_spatial_extent(bbox_two) + collection.update_temporal_extent(start_datetime_two, end_datetime_two) + + assert collection.stac["extent"]["temporal"]["interval"] == [start_datetime_one, end_datetime_two] + assert collection.stac["extent"]["spatial"]["bbox"] == [174.889641, -41.217532, 174.922965, -41.203521] From 6e040b0037bf2ec24761dba303ac306184c87839 Mon Sep 17 00:00:00 2001 From: Alice Fage Date: Fri, 23 Sep 2022 13:05:57 +1200 Subject: [PATCH 11/14] fix: formatting --- scripts/stac/imagery/collection.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/stac/imagery/collection.py b/scripts/stac/imagery/collection.py index 8868e4b81..81b6947f9 100644 --- a/scripts/stac/imagery/collection.py +++ b/scripts/stac/imagery/collection.py @@ -104,4 +104,5 @@ def update_extent(self, bbox: Optional[List[float]] = None, interval: Optional[L if bbox: self.stac["extent"]["spatial"]["bbox"] = bbox if interval: - self.stac["extent"]["temporal"]["interval"] = interval \ No newline at end of file + self.stac["extent"]["temporal"]["interval"] = interval + \ No newline at end of file From e95d97243337d2e439abbdba5cb0e9693456ebd6 Mon Sep 17 00:00:00 2001 From: Alice Fage Date: Fri, 23 Sep 2022 13:12:05 +1200 Subject: [PATCH 12/14] fix: all formatting --- scripts/stac/collection.py | 43 +++++++++++++++++++++++++++ scripts/stac/imagery/collection.py | 1 - scripts/stac/tests/collection_test.py | 2 +- 3 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 scripts/stac/collection.py diff --git a/scripts/stac/collection.py b/scripts/stac/collection.py new file mode 100644 index 000000000..7549456db --- /dev/null +++ b/scripts/stac/collection.py @@ -0,0 +1,43 @@ +from typing import Any, Dict, List, Optional + +import ulid + +from scripts.stac.util.STAC_VERSION import STAC_VERSION + + +class ImageryCollection: + stac: Dict[str, Any] + + def __init__( + self, title: Optional[str] = None, description: Optional[str] = None, stac: Optional[Dict[str, Any]] = None + ) -> None: + if stac: + self.stac = stac + elif title and description: + self.stac = { + "type": "Collection", + "stac_version": STAC_VERSION, + "id": str(ulid.ULID()), + "title": title, + "description": description, + "license": "CC-BY-4.0", + "links": [{"rel": "self", "href": "./collection.json", "type": "application/json"}], + } + else: + raise Exception("incorrect initialising parameters must have 'stac' or 'title and description'") + + def add_link(self, href: str, rel: str = "item", file_type: str = "application/json") -> None: + # Will be implemented in Future PR + pass + + def update_spatial_extent(self, item_bbox: List[float]) -> None: + # Will be implemented in Future PR + pass + + def update_temporal_extent(self, item_start_datetime: str, item_end_datetime: str) -> None: + # Will be implemented in Future PR + pass + + def update_extent(self, bbox: Optional[List[float]] = None, interval: Optional[List[str]] = None) -> None: + # Will be implemented in Future PR + pass diff --git a/scripts/stac/imagery/collection.py b/scripts/stac/imagery/collection.py index 81b6947f9..77ccd7a81 100644 --- a/scripts/stac/imagery/collection.py +++ b/scripts/stac/imagery/collection.py @@ -105,4 +105,3 @@ def update_extent(self, bbox: Optional[List[float]] = None, interval: Optional[L self.stac["extent"]["spatial"]["bbox"] = bbox if interval: self.stac["extent"]["temporal"]["interval"] = interval - \ No newline at end of file diff --git a/scripts/stac/tests/collection_test.py b/scripts/stac/tests/collection_test.py index f8052fa69..e8bbd3966 100644 --- a/scripts/stac/tests/collection_test.py +++ b/scripts/stac/tests/collection_test.py @@ -40,4 +40,4 @@ def test_imagery_stac_collction_update_twice() -> None: collection.update_temporal_extent(start_datetime_two, end_datetime_two) assert collection.stac["extent"]["temporal"]["interval"] == [start_datetime_one, end_datetime_two] - assert collection.stac["extent"]["spatial"]["bbox"] == [174.889641, -41.217532, 174.922965, -41.203521] \ No newline at end of file + assert collection.stac["extent"]["spatial"]["bbox"] == [174.889641, -41.217532, 174.922965, -41.203521] From 12ca5aaab78f885315fcde57e26c7e514bb471cb Mon Sep 17 00:00:00 2001 From: Alice Fage Date: Fri, 23 Sep 2022 13:14:11 +1200 Subject: [PATCH 13/14] fix: remove additional file --- scripts/stac/collection.py | 43 -------------------------------------- 1 file changed, 43 deletions(-) delete mode 100644 scripts/stac/collection.py diff --git a/scripts/stac/collection.py b/scripts/stac/collection.py deleted file mode 100644 index 7549456db..000000000 --- a/scripts/stac/collection.py +++ /dev/null @@ -1,43 +0,0 @@ -from typing import Any, Dict, List, Optional - -import ulid - -from scripts.stac.util.STAC_VERSION import STAC_VERSION - - -class ImageryCollection: - stac: Dict[str, Any] - - def __init__( - self, title: Optional[str] = None, description: Optional[str] = None, stac: Optional[Dict[str, Any]] = None - ) -> None: - if stac: - self.stac = stac - elif title and description: - self.stac = { - "type": "Collection", - "stac_version": STAC_VERSION, - "id": str(ulid.ULID()), - "title": title, - "description": description, - "license": "CC-BY-4.0", - "links": [{"rel": "self", "href": "./collection.json", "type": "application/json"}], - } - else: - raise Exception("incorrect initialising parameters must have 'stac' or 'title and description'") - - def add_link(self, href: str, rel: str = "item", file_type: str = "application/json") -> None: - # Will be implemented in Future PR - pass - - def update_spatial_extent(self, item_bbox: List[float]) -> None: - # Will be implemented in Future PR - pass - - def update_temporal_extent(self, item_start_datetime: str, item_end_datetime: str) -> None: - # Will be implemented in Future PR - pass - - def update_extent(self, bbox: Optional[List[float]] = None, interval: Optional[List[str]] = None) -> None: - # Will be implemented in Future PR - pass From 1eb7473cb064833e57f46775c8c556f60e9b43ba Mon Sep 17 00:00:00 2001 From: Megan Davidson Date: Fri, 23 Sep 2022 13:20:48 +1200 Subject: [PATCH 14/14] fix: typo --- scripts/stac/tests/collection_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/stac/tests/collection_test.py b/scripts/stac/tests/collection_test.py index e8bbd3966..caedabb28 100644 --- a/scripts/stac/tests/collection_test.py +++ b/scripts/stac/tests/collection_test.py @@ -22,7 +22,7 @@ def test_imagery_stac_collection_update() -> None: assert collection.stac["extent"]["temporal"]["interval"] == [start_datetime, end_datetime] -def test_imagery_stac_collction_update_twice() -> None: +def test_imagery_stac_collection_update_twice() -> None: title = "Test Urban Imagery" description = "Test Urban Imagery Description" collection = ImageryCollection(title, description)