From 71b3cc5afd7690a417420e1b048b99ced220c663 Mon Sep 17 00:00:00 2001 From: Antsalacia Date: Thu, 28 Nov 2024 15:40:45 +0100 Subject: [PATCH 01/32] adding compression option --- earthspy/earthspy.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/earthspy/earthspy.py b/earthspy/earthspy.py index de6581d..66fcfe6 100644 --- a/earthspy/earthspy.py +++ b/earthspy/earthspy.py @@ -85,6 +85,7 @@ def set_query_parameters( download_mode: str = "SM", remove_splitboxes: bool = True, verbose: bool = True, + compression: str = None ) -> None: """Define a set of parameters used for the API request. @@ -171,6 +172,10 @@ def set_query_parameters( # set and correct resolution self.set_correct_resolution() + + # set compress mode + + self.compress_mode = compression # set post-processing attributes self.get_evaluation_script(evaluation_script) @@ -188,6 +193,14 @@ def set_query_parameters( return None + def get_raster_compression(self) -> None: + + try: + assert self.compress_mode in ['DEFLATE','LZW','PACKBITS','JPEG', + 'WEBP','LZMA','ZSTD'] + except: + print("Not a valid compression keyword") + def get_data_collection(self) -> shb.DataCollection: """Get Sentinel Hub DataCollection object from data collection name. @@ -1059,6 +1072,7 @@ def merge_rasters(self) -> None: "height": mosaic.shape[1], "width": mosaic.shape[2], "transform": output_transform, + "compress": self.compress_mode } ) From c7dbb65952c52238d9ef6c6a97bb8ef191f98503 Mon Sep 17 00:00:00 2001 From: Antsalacia Date: Fri, 29 Nov 2024 11:33:35 +0100 Subject: [PATCH 02/32] Adding modification and verification in method --- earthspy/earthspy.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/earthspy/earthspy.py b/earthspy/earthspy.py index 66fcfe6..b242513 100644 --- a/earthspy/earthspy.py +++ b/earthspy/earthspy.py @@ -174,8 +174,7 @@ def set_query_parameters( self.set_correct_resolution() # set compress mode - - self.compress_mode = compression + self.get_raster_compression() # set post-processing attributes self.get_evaluation_script(evaluation_script) @@ -193,13 +192,18 @@ def set_query_parameters( return None - def get_raster_compression(self) -> None: + def get_raster_compression(self) -> str: + """Verify valid keyword for raster compression - try: - assert self.compress_mode in ['DEFLATE','LZW','PACKBITS','JPEG', - 'WEBP','LZMA','ZSTD'] - except: - print("Not a valid compression keyword") + :return: Compression mode + """ + + if compress_mode in ['DEFLATE','LZW','PACKBITS','JPEG', 'WEBP','LZMA','ZSTD']: + self.compress_mode = compress_mode + else: + raise KeyError("Compression mode not found") + + return self.compress_mode def get_data_collection(self) -> shb.DataCollection: """Get Sentinel Hub DataCollection object from data collection name. From 7ac2f6c60e08c52e94c2552c323a293aee0ed8f6 Mon Sep 17 00:00:00 2001 From: Antsalacia Date: Fri, 29 Nov 2024 12:06:10 +0100 Subject: [PATCH 03/32] Add argument in method --- earthspy/earthspy.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/earthspy/earthspy.py b/earthspy/earthspy.py index b242513..1379a32 100644 --- a/earthspy/earthspy.py +++ b/earthspy/earthspy.py @@ -174,7 +174,7 @@ def set_query_parameters( self.set_correct_resolution() # set compress mode - self.get_raster_compression() + self.get_raster_compression(compression) # set post-processing attributes self.get_evaluation_script(evaluation_script) @@ -192,7 +192,7 @@ def set_query_parameters( return None - def get_raster_compression(self) -> str: + def get_raster_compression(self, compress_mode) -> str: """Verify valid keyword for raster compression :return: Compression mode From ba57e0cdac38532b1c5f6226b25defc33641d916 Mon Sep 17 00:00:00 2001 From: Antsalacia Date: Fri, 29 Nov 2024 12:14:24 +0100 Subject: [PATCH 04/32] rename and add docstring --- earthspy/earthspy.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/earthspy/earthspy.py b/earthspy/earthspy.py index 1379a32..128a7d6 100644 --- a/earthspy/earthspy.py +++ b/earthspy/earthspy.py @@ -85,7 +85,7 @@ def set_query_parameters( download_mode: str = "SM", remove_splitboxes: bool = True, verbose: bool = True, - compression: str = None + raster_compression: str = None ) -> None: """Define a set of parameters used for the API request. @@ -146,6 +146,8 @@ def set_query_parameters( :param verbose: Whether to print processing status or not, defaults to True. :type verbose: bool, optional + + :param raster_compression: Which raster compression mode to use or not """ # set processing attributes From a3ae236c1867f9e70aea796eb03e686f39776e9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20Wehrl=C3=A9?= Date: Fri, 29 Nov 2024 15:52:34 +0100 Subject: [PATCH 05/32] Add `raster_compression` type in docstring --- earthspy/earthspy.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/earthspy/earthspy.py b/earthspy/earthspy.py index 128a7d6..000f57c 100644 --- a/earthspy/earthspy.py +++ b/earthspy/earthspy.py @@ -147,7 +147,9 @@ def set_query_parameters( to True. :type verbose: bool, optional - :param raster_compression: Which raster compression mode to use or not + :param raster_compression: Raster compression to apply following methods + available in rasterio, defaults to None. + :type raster_compression: Union[None, str], optional """ # set processing attributes From 5bbc9d53b02f3cf0ff1dcab9c563a0fd54f73aa6 Mon Sep 17 00:00:00 2001 From: Antsalacia Date: Fri, 29 Nov 2024 16:34:09 +0100 Subject: [PATCH 06/32] fix None bug and rename --- earthspy/earthspy.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/earthspy/earthspy.py b/earthspy/earthspy.py index 128a7d6..805f3b8 100644 --- a/earthspy/earthspy.py +++ b/earthspy/earthspy.py @@ -176,7 +176,7 @@ def set_query_parameters( self.set_correct_resolution() # set compress mode - self.get_raster_compression(compression) + self.get_raster_compression(raster_compression) # set post-processing attributes self.get_evaluation_script(evaluation_script) @@ -194,18 +194,20 @@ def set_query_parameters( return None - def get_raster_compression(self, compress_mode) -> str: + def get_raster_compression(self, raster_compression) -> str: """Verify valid keyword for raster compression :return: Compression mode """ - if compress_mode in ['DEFLATE','LZW','PACKBITS','JPEG', 'WEBP','LZMA','ZSTD']: - self.compress_mode = compress_mode + if raster_compression in ['DEFLATE','LZW','PACKBITS','JPEG', 'WEBP','LZMA','ZSTD']: + self.raster_compression = raster_compression + elif raster_compression == None: + self.raster_compression = None else: raise KeyError("Compression mode not found") - return self.compress_mode + return self.raster_compression def get_data_collection(self) -> shb.DataCollection: """Get Sentinel Hub DataCollection object from data collection name. @@ -1078,7 +1080,7 @@ def merge_rasters(self) -> None: "height": mosaic.shape[1], "width": mosaic.shape[2], "transform": output_transform, - "compress": self.compress_mode + "compress": self.raster_compression } ) From f584b99f92010a9f28754afa56c8edc292703a84 Mon Sep 17 00:00:00 2001 From: Antsalacia Date: Fri, 29 Nov 2024 17:37:31 +0100 Subject: [PATCH 07/32] change argument --- earthspy/earthspy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/earthspy/earthspy.py b/earthspy/earthspy.py index cbb2ce0..82a792f 100644 --- a/earthspy/earthspy.py +++ b/earthspy/earthspy.py @@ -196,7 +196,7 @@ def set_query_parameters( return None - def get_raster_compression(self, raster_compression) -> str: + def get_raster_compression(self, raster_compression: Union[None, str]) -> str: """Verify valid keyword for raster compression :return: Compression mode From 40366a13224ef9fab1c13a8e2609d1f6dccb0f21 Mon Sep 17 00:00:00 2001 From: Antsalacia Date: Mon, 2 Dec 2024 10:33:39 +0100 Subject: [PATCH 08/32] CodeQL issue --- earthspy/earthspy.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/earthspy/earthspy.py b/earthspy/earthspy.py index 82a792f..8679d65 100644 --- a/earthspy/earthspy.py +++ b/earthspy/earthspy.py @@ -202,7 +202,8 @@ def get_raster_compression(self, raster_compression: Union[None, str]) -> str: :return: Compression mode """ - if raster_compression in ['DEFLATE','LZW','PACKBITS','JPEG', 'WEBP','LZMA','ZSTD']: + if raster_compression in ['DEFLATE','LZW','PACKBITS','JPEG', + 'WEBP','LZMA','ZSTD']: self.raster_compression = raster_compression elif raster_compression == None: self.raster_compression = None From 2c8c68897406ea0e4585c47f2e5d7b57a3cbb629 Mon Sep 17 00:00:00 2001 From: Antsalacia Date: Mon, 2 Dec 2024 10:41:54 +0100 Subject: [PATCH 09/32] pre-commit issues --- earthspy/earthspy.py | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/earthspy/earthspy.py b/earthspy/earthspy.py index 8679d65..ed16c3c 100644 --- a/earthspy/earthspy.py +++ b/earthspy/earthspy.py @@ -85,7 +85,7 @@ def set_query_parameters( download_mode: str = "SM", remove_splitboxes: bool = True, verbose: bool = True, - raster_compression: str = None + raster_compression: str = None, ) -> None: """Define a set of parameters used for the API request. @@ -147,6 +147,7 @@ def set_query_parameters( to True. :type verbose: bool, optional + :param raster_compression: Raster compression to apply following methods available in rasterio, defaults to None. :type raster_compression: Union[None, str], optional @@ -177,6 +178,7 @@ def set_query_parameters( # set and correct resolution self.set_correct_resolution() + # set compress mode self.get_raster_compression(raster_compression) @@ -199,16 +201,25 @@ def set_query_parameters( def get_raster_compression(self, raster_compression: Union[None, str]) -> str: """Verify valid keyword for raster compression + :return: Compression mode """ - if raster_compression in ['DEFLATE','LZW','PACKBITS','JPEG', - 'WEBP','LZMA','ZSTD']: - self.raster_compression = raster_compression + if raster_compression in [ + 'DEFLATE', + 'LZW', + 'PACKBITS', + 'JPEG', + 'WEBP', + 'LZMA', + 'ZSTD' + ]: + + self.raster_compression = raster_compression elif raster_compression == None: self.raster_compression = None else: - raise KeyError("Compression mode not found") + raise KeyError("Compression mode not found") return self.raster_compression @@ -1083,7 +1094,7 @@ def merge_rasters(self) -> None: "height": mosaic.shape[1], "width": mosaic.shape[2], "transform": output_transform, - "compress": self.raster_compression + "compress": self.raster_compression, } ) From 37f57657b868507a720950606dc785dec196dce6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20Wehrl=C3=A9?= Date: Mon, 2 Dec 2024 20:55:07 +0100 Subject: [PATCH 10/32] Address CodeQL alert --- earthspy/earthspy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/earthspy/earthspy.py b/earthspy/earthspy.py index ed16c3c..a9f7e70 100644 --- a/earthspy/earthspy.py +++ b/earthspy/earthspy.py @@ -216,7 +216,7 @@ def get_raster_compression(self, raster_compression: Union[None, str]) -> str: ]: self.raster_compression = raster_compression - elif raster_compression == None: + elif raster_compression is None: self.raster_compression = None else: raise KeyError("Compression mode not found") From 372711887bde27bf2ba086b00a21e14dc7090edb Mon Sep 17 00:00:00 2001 From: Antsalacia Date: Tue, 3 Dec 2024 10:24:49 +0100 Subject: [PATCH 11/32] test with pre-commit --- earthspy/earthspy.py | 67 ++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/earthspy/earthspy.py b/earthspy/earthspy.py index ed16c3c..600e9a8 100644 --- a/earthspy/earthspy.py +++ b/earthspy/earthspy.py @@ -1,29 +1,29 @@ -# -*- coding: utf-8 -*- """ @author: Adrien Wehrlé, EO-IO, University of Zurich, Switzerland """ -from collections import Counter -from datetime import datetime, timedelta import glob import json +import os +import shutil +import tarfile +import time +from collections import Counter +from datetime import datetime, timedelta from multiprocessing import cpu_count +from pathlib import Path +from typing import Tuple, Union + import numpy as np import objectpath -import os import pandas as pd -from pathlib import Path import rasterio -from rasterio.merge import merge import requests import sentinelhub as shb -import shutil -import tarfile -import time -from typing import Union, Tuple import validators +from rasterio.merge import merge class EarthSpy: @@ -34,12 +34,12 @@ class EarthSpy: def __init__(self, CLIENT_credentials_file: str) -> None: """ :param CLIENT_credentials_file: full path to file containing credentials - with User's OAuth client ID (1st row) secrect (2nd row). + with User's OAuth client ID (1st row) secret (2nd row). :type CLIENT_credentials_file: str """ # read credentials stored in text file - with open(CLIENT_credentials_file, "r") as file: + with open(CLIENT_credentials_file) as file: credentials = file.read().splitlines() # extract credentials from lines @@ -146,8 +146,8 @@ def set_query_parameters( :param verbose: Whether to print processing status or not, defaults to True. :type verbose: bool, optional - - + + :param raster_compression: Raster compression to apply following methods available in rasterio, defaults to None. :type raster_compression: Union[None, str], optional @@ -177,8 +177,7 @@ def set_query_parameters( # set and correct resolution self.set_correct_resolution() - - + # set compress mode self.get_raster_compression(raster_compression) @@ -200,27 +199,27 @@ def set_query_parameters( def get_raster_compression(self, raster_compression: Union[None, str]) -> str: """Verify valid keyword for raster compression - - + + :return: Compression mode """ - + if raster_compression in [ - 'DEFLATE', - 'LZW', - 'PACKBITS', - 'JPEG', - 'WEBP', - 'LZMA', - 'ZSTD' + "DEFLATE", + "LZW", + "PACKBITS", + "JPEG", + "WEBP", + "LZMA", + "ZSTD", ]: - + self.raster_compression = raster_compression elif raster_compression == None: self.raster_compression = None else: raise KeyError("Compression mode not found") - + return self.raster_compression def get_data_collection(self) -> shb.DataCollection: @@ -260,7 +259,7 @@ def get_available_data(self) -> list: ] # some data sets require a difference service_url, test search_iterator - # and update service_url if dowload failed + # and update service_url if download failed try: # store metadata of available scenes self.metadata = [list(iterator) for iterator in search_iterator] @@ -428,12 +427,12 @@ def get_bounding_box(self, bounding_box: Union[list, str]) -> shb.geometry.BBox: :rtype: sentinelhub.geometry.BBox """ - # if a list, set Sentinel Hub BBox wit bounding_box + # if a list, set Sentinel Hub BBox with bounding_box if isinstance(bounding_box, list): # create Sentinel Hub BBox self.bounding_box = shb.BBox(bbox=bounding_box, crs=shb.CRS.WGS84) - # cant guess name, so set to None + # can't guess name, so set to None self.bounding_box_name = None # if a string, extract bounding box from corresponding GEOJSON file @@ -497,7 +496,7 @@ def get_store_folder(self, store_folder: Union[str, None]) -> str: if self.algorithm: store_folder += f"{os.sep}{self.algorithm}" - # create subfolder if doesnt exist + # create subfolder if doesn't exist if not os.path.exists(store_folder): os.makedirs(store_folder) @@ -507,7 +506,7 @@ def get_store_folder(self, store_folder: Union[str, None]) -> str: return self.store_folder def convert_bounding_box_coordinates(self) -> Tuple[shb.geometry.BBox, list]: - """Convert bounding boxe coordinates to a Geodetic Parameter Dataset (EPSG) in + """Convert bounding boxes coordinates to a Geodetic Parameter Dataset (EPSG) in meter unit, default to EPSG:3413 (NSIDC Sea Ice Polar Stereographic North). @@ -593,7 +592,7 @@ def set_correct_resolution(self) -> int: elif not self.resolution and self.download_mode == "SM": self.resolution = self.raw_data_collection_resolution - # resolution cant be higher than max resolution in D download mode + # resolution can't be higher than max resolution in D download mode if self.download_mode == "D" and self.resolution < max_resolution: self.resolution = max_resolution if self.verbose: From e9c5cf297d067514e69cc65fde85500cdbb7f2e7 Mon Sep 17 00:00:00 2001 From: Antsalacia Date: Tue, 3 Dec 2024 10:32:16 +0100 Subject: [PATCH 12/32] change in metadata --- earthspy/earthspy.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/earthspy/earthspy.py b/earthspy/earthspy.py index 47e96f7..e1e1b5b 100644 --- a/earthspy/earthspy.py +++ b/earthspy/earthspy.py @@ -1093,10 +1093,16 @@ def merge_rasters(self) -> None: "height": mosaic.shape[1], "width": mosaic.shape[2], "transform": output_transform, - "compress": self.raster_compression, } ) - + + if self.raster_compression is not None: + output_meta.update( + { + "compress":self.raster_compression + } + ) + # write mosaic with rasterio.open(date_output_filename, "w", **output_meta) as dst: dst.write(mosaic) From 0a9d2cc85313f73ea6597fa1de824e3215122fac Mon Sep 17 00:00:00 2001 From: Antsalacia Date: Tue, 3 Dec 2024 10:36:55 +0100 Subject: [PATCH 13/32] add pre-commit --- .pre-commit-config.yaml | 112 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 .pre-commit-config.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..4848f16 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,112 @@ +# based on Glaciohack pre-commit config +ci: + autofix_prs: false + autoupdate_schedule: quarterly +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: check-yaml + - id: end-of-file-fixer + exclude: \.txt$ + - id: trailing-whitespace # Remove trailing + # whitespaces + - id: check-merge-conflict + # Fix common spelling mistakes + - repo: https://github.com/codespell-project/codespell + rev: v2.3.0 + hooks: + - id: codespell + args: [ + '--ignore-words-list', 'alos,inout,vor', + '--ignore-regex', '\bnin\b', + '--' + ] + types_or: [python, rst, markdown] + files: ^(earthspy|docs|tests)/ + + # Replace relative imports + - repo: https://github.com/MarcoGorelli/absolufy-imports + rev: v0.3.1 + hooks: + - id: absolufy-imports + + # Format the code aggressively using black + - repo: https://github.com/psf/black + rev: 24.10.0 + hooks: + - id: black + args: [--line-length=88] + + # Lint the code using flake8 + - repo: https://github.com/pycqa/flake8 + rev: 7.1.1 + hooks: + - id: flake8 + args: [ + '--max-line-length', '122', + '--extend-ignore', 'E203,B028', # flake8 + # disagrees + # with + # black, so + # this + # should be + # ignored. + '--' + ] + additional_dependencies: + - flake8-comprehensions + - flake8-bugbear + files: ^(earthspy|tests) + + # Sort imports using isort + - repo: https://github.com/PyCQA/isort + rev: 5.13.2 + hooks: + - id: isort + args: [ "--profile", "black" ] + + # Automatically upgrade syntax to a minimum version + - repo: https://github.com/asottile/pyupgrade + rev: v3.19.0 + hooks: + - id: pyupgrade + args: [--py37-plus] + + # Various formattings + - repo: https://github.com/pre-commit/pygrep-hooks + rev: v1.10.0 + hooks: + # Detect common mistake of using single backticks when + # writing rst + - id: rst-backticks + # Detect mistake of rst directive not ending with + # double colon or space before the double colon + - id: rst-directive-colons + types: [text] + types_or: [python, rst] + # Detect mistake of inline code touching normal text + # in rst + - id: rst-inline-touching-normal + types: [text] + types_or: [python, rst] + # Eval should never be used (can do arbitrary code + # execution) + - id: python-no-eval + # Enforce the use of type annotations instead of + # docstring type comments + - id: python-use-type-annotations + + + - repo: local + hooks: + # Generate pip's dev-requirements.txt from conda's + # dev-environment.yml to run snyk (snyk doesn't currently + # support conda) + - id: pip-to-conda + name: Generate pip dependency from conda + language: python + entry: .github/scripts/generate_pip_deps_from_conda.py + files: ^(dev-environment.yml|requirements-dev.txt)$ + pass_filenames: false + additional_dependencies: [tomli, pyyaml] From e34429cd0a3b16661e1200f16fe06c02142e3730 Mon Sep 17 00:00:00 2001 From: Antsalacia Date: Tue, 3 Dec 2024 10:51:18 +0100 Subject: [PATCH 14/32] pre-commit change --- earthspy/earthspy.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/earthspy/earthspy.py b/earthspy/earthspy.py index 8da0556..434f82d 100644 --- a/earthspy/earthspy.py +++ b/earthspy/earthspy.py @@ -1106,23 +1106,19 @@ def merge_rasters(self) -> None: "transform": output_transform, } ) - + # update dictionary if compression set if self.raster_compression is not None: - output_meta.update( - { - "compress":self.raster_compression - } - ) + output_meta.update({"compress": self.raster_compression}) # extract scene id id_dict = {k: self.metadata[date][0][k] for k in ["id"]} - + # write mosaic with rasterio.open(date_output_filename, "w", **output_meta) as dst: dst.write(mosaic) dst.update_tags(**id_dict) - + # save file name of merged raster self.output_filenames_renamed.append(date_output_filename) From f65d35a1a1e67106b69eefdf2b0ea4ec35448d31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20Wehrl=C3=A9?= Date: Tue, 3 Dec 2024 11:21:36 +0100 Subject: [PATCH 15/32] modify `get_raster_compression` docstring --- earthspy/earthspy.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/earthspy/earthspy.py b/earthspy/earthspy.py index 434f82d..8b36cac 100644 --- a/earthspy/earthspy.py +++ b/earthspy/earthspy.py @@ -197,10 +197,11 @@ def set_query_parameters( return None def get_raster_compression(self, raster_compression: Union[None, str]) -> str: - """Verify valid keyword for raster compression - - - :return: Compression mode + """Get raster compression based on rasterio's + available methods + + :return: Raster compression method + :rtype: Union[None, str] """ if raster_compression in [ @@ -328,7 +329,6 @@ def get_raw_data_collection_resolution(self) -> int: :return: Data collection resolution. :rtype: int - """ # set default satellite resolution From 468020ceecbb8a559d465612ded697d697cd54ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20Wehrl=C3=A9?= Date: Tue, 3 Dec 2024 11:22:43 +0100 Subject: [PATCH 16/32] modify line length on docstring --- earthspy/earthspy.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/earthspy/earthspy.py b/earthspy/earthspy.py index 8b36cac..76ff54b 100644 --- a/earthspy/earthspy.py +++ b/earthspy/earthspy.py @@ -197,8 +197,7 @@ def set_query_parameters( return None def get_raster_compression(self, raster_compression: Union[None, str]) -> str: - """Get raster compression based on rasterio's - available methods + """Get raster compression based on rasterio's available methods :return: Raster compression method :rtype: Union[None, str] From d8512b1bb7c161f8b87829d26035e88a326f5d1f Mon Sep 17 00:00:00 2001 From: Antsalacia Date: Fri, 6 Dec 2024 10:30:02 +0100 Subject: [PATCH 17/32] Problem with self and variables env --- tests/test_earthspy.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/test_earthspy.py b/tests/test_earthspy.py index f0d3da6..8a6ed76 100644 --- a/tests/test_earthspy.py +++ b/tests/test_earthspy.py @@ -358,3 +358,15 @@ def test_merge_rasters(self) -> None: # assert all(isinstance(item, str) for item in self.t3.output_filenames_renamed) # # check that one output per split box was created # assert len(self.t3.outputs) == len(self.t3.split_boxes) + + def test_get_raster_compression(self) -> None: + """""" + #%% + comp_def = self.t1.raster_compression + assert comp_def == None + + + + + + From d8cb87f94564ee942363a01e593eb0bb5f794eba Mon Sep 17 00:00:00 2001 From: Antsalacia Date: Thu, 12 Dec 2024 11:56:20 +0100 Subject: [PATCH 18/32] Adding conftest and test --- earthspy/earthspy.py | 2 +- tests/conftest.py | 181 ++++++++++++ tests/test_earthspy.py | 645 ++++++++++++++++++----------------------- 3 files changed, 467 insertions(+), 361 deletions(-) create mode 100644 tests/conftest.py diff --git a/earthspy/earthspy.py b/earthspy/earthspy.py index 76ff54b..cab0fd9 100644 --- a/earthspy/earthspy.py +++ b/earthspy/earthspy.py @@ -198,7 +198,7 @@ def set_query_parameters( def get_raster_compression(self, raster_compression: Union[None, str]) -> str: """Get raster compression based on rasterio's available methods - + :return: Raster compression method :rtype: Union[None, str] """ diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..3172816 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,181 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" + +@author: Adrien Wehrlé, University of Zurich, Switzerland + +""" + +import earthspy.earthspy as es +import pytest +import os + +def pytest_addoption(parser): + parser.addoption("--filepath", action="store", default="test") + + +if os.getenv("CI") is not None: + # create local variables from environment secrets for convenience + SH_CLIENT_ID = os.environ["SH_CLIENT_ID"] + SH_CLIENT_SECRET = os.environ["SH_CLIENT_SECRET"] + + # path to credential file to be created + filepath = "auth.txt" + + # create file containing credentials for testing + with open(filepath, "w") as out: + out.write(f"{SH_CLIENT_ID}\n{SH_CLIENT_SECRET}") +else: + @pytest.fixture(scope="session") + def filepath(pytestconfig): + return pytestconfig.getoption("filepath") + + @pytest.fixture(scope="session") + def credentials(filepath): + # read credentials stored in text file + with open(filepath) as file: + credentials = file.read().splitlines() + return credentials + + @pytest.fixture(scope="session") + def SH_CLIENT_ID(credentials) -> None: + # extract credentials from lines + SH_CLIENT_ID = credentials[0] + return SH_CLIENT_ID + + @pytest.fixture(scope="session") + def SH_CLIENT_SECRET(credentials) -> None: + SH_CLIENT_SECRET = credentials[1] + return SH_CLIENT_SECRET + + + +@pytest.fixture(scope="session") +def test_evalscript(): + test_evalscript = """ + //VERSION=3 + function setup(){ + return{ + input: ["B02", "B03", "B04", "dataMask"], + output: {bands: 4} + } + } + function evaluatePixel(sample){ + // Set gain for visualisation + let gain = 2.5; + // Return RGB + return [sample.B04 * gain, sample.B03 * gain, sample.B02 * gain, + sample.dataMask]; + } + """ + return test_evalscript + +@pytest.fixture(scope="session") +def test_url(): + test_url = ( + "https://custom-scripts.sentinel-hub.com/custom-scripts/" + + "sentinel-2/true_color/script.js" + ) + return test_url + +@pytest.fixture(scope="session") +def test_collection(): + # an example of data collection + test_collection = "SENTINEL2_L2A" + return test_collection + +@pytest.fixture(scope="session") +def test_bounding_box(): + # an example of footprint area + test_bounding_box = [-51.13, 69.204, -51.06, 69.225] + return test_bounding_box + +@pytest.fixture(scope="session") +def test_area_name(): + # an example of area available as GEOJSON file + test_area_name = "Ilulissat" + return test_area_name + +@pytest.fixture(scope="session") +def t1(filepath, test_evalscript, test_collection, test_bounding_box): + # example of query with default parameters + t1 = es.EarthSpy(filepath) + t1.set_query_parameters( + bounding_box=test_bounding_box, + time_interval=["2019-08-23"], + evaluation_script=test_evalscript, + data_collection=test_collection, + download_mode="SM", + ) + return t1 + +@pytest.fixture(scope="session") +def t2(filepath, test_evalscript, test_collection, test_area_name): + # example of query with direct area name + t2 = es.EarthSpy(filepath) + t2.set_query_parameters( + bounding_box=test_area_name, + time_interval=["2019-08-23"], + evaluation_script=test_evalscript, + data_collection=test_collection, + download_mode="SM", + ) + return t2 + +@pytest.fixture(scope="session") +def t3(filepath, test_evalscript, test_collection, test_bounding_box): + # example of query with direct mode + t3 = es.EarthSpy(filepath) + t3.set_query_parameters( + bounding_box=test_bounding_box, + time_interval=["2019-08-23"], + evaluation_script=test_evalscript, + data_collection=test_collection, + download_mode="D", + ) + return t3 + +@pytest.fixture(scope="session") +def t4(filepath, test_evalscript, test_collection, test_bounding_box): + # example of query with direct mode + t4 = es.EarthSpy(filepath) + t4.set_query_parameters( + bounding_box=test_bounding_box, + time_interval=["2019-08-23"], + evaluation_script=test_evalscript, + data_collection=test_collection, + download_mode="SM", + raster_compression="LZW", + ) + return t4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/test_earthspy.py b/tests/test_earthspy.py index 8a6ed76..d237ee1 100644 --- a/tests/test_earthspy.py +++ b/tests/test_earthspy.py @@ -5,368 +5,293 @@ """ -import os - import numpy as np import pandas as pd import requests import sentinelhub as shb -import earthspy.earthspy as es - - -class TestEarthspy: - # create local variables from environment secrets for convenience - SH_CLIENT_ID = os.environ["SH_CLIENT_ID"] - SH_CLIENT_SECRET = os.environ["SH_CLIENT_SECRET"] - - # create file containing credentials for testing - with open("auth.txt", "w") as out: - out.write(f"{SH_CLIENT_ID}\n{SH_CLIENT_SECRET}") - - # an example of custom script - test_evalscript = """ - //VERSION=3 - function setup(){ - return{ - input: ["B02", "B03", "B04", "dataMask"], - output: {bands: 4} - } - } - function evaluatePixel(sample){ - // Set gain for visualisation - let gain = 2.5; - // Return RGB - return [sample.B04 * gain, sample.B03 * gain, sample.B02 * gain, - sample.dataMask]; - } - """ - - # an example of custom script URL - test_url = ( - "https://custom-scripts.sentinel-hub.com/custom-scripts/" - + "sentinel-2/true_color/script.js" - ) - - # an example of data collection - test_collection = "SENTINEL2_L2A" - - # an example of footprint area - test_bounding_box = [-51.13, 69.204, -51.06, 69.225] - - # an example of area available as GEOJSON file - test_area_name = "Ilulissat" - - print(os.getcwd()) - - # example of query with default parameters - t1 = es.EarthSpy("auth.txt") - t1.set_query_parameters( - bounding_box=test_bounding_box, - time_interval=["2019-08-23"], - evaluation_script=test_evalscript, - data_collection=test_collection, - download_mode="SM", - ) - - # example of query with direct area name - t2 = es.EarthSpy("auth.txt") - t2.set_query_parameters( - bounding_box=test_area_name, - time_interval=["2019-08-23"], - evaluation_script=test_evalscript, - data_collection=test_collection, - download_mode="SM", - ) - - # example of query with direct mode - t3 = es.EarthSpy("auth.txt") - t3.set_query_parameters( - bounding_box=test_bounding_box, - time_interval=["2019-08-23"], - evaluation_script=test_evalscript, - data_collection=test_collection, - download_mode="D", - ) - - def test_init(self) -> None: - """Test auth.txt parsing and connection configuration.""" - - # check for credentials - assert self.t1.CLIENT_ID == os.environ["SH_CLIENT_ID"] - assert self.t1.CLIENT_SECRET == os.environ["SH_CLIENT_SECRET"] - - # check if connection was properly setup - assert isinstance(self.t1.config, shb.config.SHConfig) - assert self.t1.config.sh_client_id == os.environ["SH_CLIENT_ID"] - assert self.t1.config.sh_client_secret == os.environ["SH_CLIENT_SECRET"] - - def test_set_query_parameters(self) -> None: - """Test direct attribute assignment.""" - - # check if attributes were set accordingly - assert self.t1.download_mode is not None - assert self.t1.download_mode == "SM" - assert self.t1.verbose - assert self.t1.data_collection_str == self.test_collection - assert isinstance( - self.t1.user_date_range, pd.core.indexes.datetimes.DatetimeIndex - ) - assert isinstance(self.t1.evaluation_script, str) - - def test_get_data_collection(self) -> None: - """Test data collection selection.""" - - # check if data collection was set properly - assert self.t1.data_collection == shb.DataCollection[self.test_collection] - assert isinstance(self.t1.data_collection, shb.DataCollection) - - def test_get_satellite_name(self) -> None: - """Test satellite name extraction""" - - # check if satellite name was set properly - assert isinstance(self.t1.satellite, str) - assert self.t1.satellite == "SENTINEL2" - - def test_get_raw_data_collection_resolution(self) -> None: - """Test resolution selection""" - - # check if data resolution was set correctly - assert self.t1.raw_data_collection_resolution == 10 - assert self.t2.raw_data_collection_resolution == 10 - assert self.t3.raw_data_collection_resolution == 10 - - def test_set_number_of_cores(self) -> None: - """Test selection of number of cores for multiprocessing""" - - # check if number of cores was set correctly - assert isinstance(self.t1.nb_cores, int) - assert isinstance(self.t2.nb_cores, int) - assert isinstance(self.t3.nb_cores, int) - - def test_get_date_range(self) -> None: - """Test datetime object creation""" - - d1 = self.t1.get_date_range(time_interval=3) - # check if date from present was set accordingly - assert isinstance(d1, pd.DatetimeIndex) - - d2a = self.t1.get_date_range(time_interval="2019-08-01") - d2b = self.t2.get_date_range(time_interval="2019-08-01") - d2c = self.t3.get_date_range(time_interval="2019-08-01") - # check if single date (str) was set accordingly - assert d2a == pd.date_range("2019-08-01", "2019-08-01") - assert d2b == pd.date_range("2019-08-01", "2019-08-01") - assert d2c == pd.date_range("2019-08-01", "2019-08-01") - - d3a = self.t1.get_date_range(time_interval=["2019-08-01"]) - d3b = self.t2.get_date_range(time_interval=["2019-08-01"]) - d3c = self.t3.get_date_range(time_interval=["2019-08-01"]) - # check if single date (list) was set accordingly - assert d3a == pd.date_range("2019-08-01", "2019-08-01") - assert d3b == pd.date_range("2019-08-01", "2019-08-01") - assert d3c == pd.date_range("2019-08-01", "2019-08-01") - - d4a = self.t1.get_date_range( - time_interval=["2019-08-01", "2019-08-02", "2019-08-03"] - ) - d4b = self.t2.get_date_range( - time_interval=["2019-08-01", "2019-08-02", "2019-08-03"] - ) - d4c = self.t3.get_date_range( - time_interval=["2019-08-01", "2019-08-02", "2019-08-03"] - ) - # check if a list of dates was set accordingly - pd.testing.assert_index_equal(d4a, pd.date_range("2019-08-01", "2019-08-03")) - pd.testing.assert_index_equal(d4b, pd.date_range("2019-08-01", "2019-08-03")) - pd.testing.assert_index_equal(d4c, pd.date_range("2019-08-01", "2019-08-03")) - - def test_get_bounding_box(self) -> None: - """Test bounding box creation""" - - bb1 = self.t1.get_bounding_box(bounding_box=self.test_bounding_box) - # check if a Sentinel Hub bounding box was created - assert isinstance(bb1, shb.geometry.BBox) - - bb2 = self.t2.get_bounding_box(bounding_box=self.test_area_name) - # check if a Sentinel Hub bounding box was created - assert isinstance(bb2, shb.geometry.BBox) - area_coordinates = np.array(bb2.geojson["coordinates"][0]) - area_bounding_box = [ - np.nanmin(area_coordinates[:, 0]), - np.nanmin(area_coordinates[:, 1]), - np.nanmax(area_coordinates[:, 0]), - np.nanmax(area_coordinates[:, 1]), - ] - # check if setting Ilulissat bounding_box with coordinates gives - # the same bounding_box just like calling its area name - assert area_bounding_box == self.test_bounding_box - - def test_get_store_folder(self) -> None: - """Test store folder selection""" - - sf1 = self.t1.get_store_folder(None) - # # check if default store folder was set accordingly - assert isinstance(sf1, str) - - sf2 = self.t1.get_store_folder(store_folder="./test/path") - # # check if passed store folder was set accordingly - assert isinstance(sf2, str) - # # check the actual string - assert sf2 == "./test/path" - - def test_convert_bounding_box_coordinates(self) -> None: - """Test bounding box conversion""" - - self.t1.convert_bounding_box_coordinates() - # check if a new Sentinel Hub bounding box was created - assert isinstance(self.t1.bounding_box_UTM, shb.geometry.BBox) - # check if the right CRS was assigned - assert self.t1.bounding_box_UTM.crs == shb.CRS("32622") - # check if the right CRS was assigned - assert self.t1.bounding_box.crs == shb.CRS("4326") - # check if a bounding box list was created - assert isinstance(self.t1.bounding_box_UTM_list, list) - # check that all items of the list are floats - assert all(isinstance(item, float) for item in self.t1.bounding_box_UTM_list) - # check that all coordinates were included - assert len(self.t1.bounding_box_UTM_list) == 4 - - def test_get_max_resolution(self) -> None: - """Test maximum resolution computation""" - - mr1 = self.t1.get_max_resolution() - # check that maximum resolution was set correctly - assert isinstance(mr1, np.int64) - assert mr1 == 11 - - def test_set_correct_resolution(self) -> None: - """Test resolution refinement""" - - r1 = self.t1.set_correct_resolution() - # check that query resolution was set correctly - assert r1 == 10 - # check that download mode was set correctly - assert isinstance(self.t1.download_mode, str) - - r2 = self.t3.set_correct_resolution() - # check that query resolution was set correctly - assert r2 == 11 - # check that download mode was set correctly - assert isinstance(self.t3.download_mode, str) - - def test_list_requests(self) -> None: - """Test request listing""" - - lr1 = self.t1.list_requests() - # check that a list was created accordingly - assert isinstance(lr1, list) - assert len(lr1) == 4 - assert len(lr1) == len(self.t1.split_boxes) - # check that a list of Sentinel Hub requests was created - assert all(isinstance(item, shb.SentinelHubRequest) for item in lr1) - - lr2 = self.t3.list_requests() - # check that a list was created accordingly - assert isinstance(lr2, list) - assert len(lr2) == 1 - assert len(lr2) == len(self.t3.split_boxes) - # check that a list of Sentinel Hub requests was created - assert isinstance(lr2[0], shb.SentinelHubRequest) - - def test_get_split_boxes(self) -> None: - """Test split box creation""" - - sb1 = self.t1.get_split_boxes() - # check that a list of split boxes was created - assert isinstance(sb1, list) - # check that each split box is a Sentinel Hub bounding box - assert all(isinstance(item, shb.geometry.BBox) for item in sb1) - # check that each split box is in the correct projection - assert all(item.crs == shb.CRS("32622") for item in sb1) - - # check that only one box has been created - assert len(self.t3.split_boxes) == 1 - # check that the split box is in the right projection - assert self.t3.split_boxes[0].crs == shb.CRS("4326") - - def test_get_evaluation_script_from_link(self) -> None: - """Test custom script extraction from URL""" - - es1 = self.t1.get_evaluation_script_from_link(self.test_url) - # check that evalscript was set accordingly - assert es1 == requests.get(self.test_url).text - - def test_set_split_boxes_ids(self) -> None: - """Test split box ID generation""" - - sbi1 = self.t1.set_split_boxes_ids() - # check that split box ids were saved in dictionary - assert isinstance(sbi1, dict) - # check that dictionary has the right shape - assert len(sbi1) == 4 - - def test_get_evaluation_script(self) -> None: - """Test evaluation script extraction""" - - es1 = self.t1.get_evaluation_script(None) - # check that default evalscript was set accordingly - assert es1 == requests.get(self.test_url).text - - es2 = self.t1.get_evaluation_script(self.test_evalscript) - # check that passed evalscript was set correctly - assert isinstance(es2, str) - - def test_sentinelhub_request(self) -> None: - """Test API request generation""" - - sr1 = self.t1.sentinelhub_request( - self.t1.user_date_range[0], self.t1.split_boxes[0] - ) - # # check that a Sentinel Hub request was created - assert isinstance(sr1, shb.SentinelHubRequest) - - sr2 = self.t3.sentinelhub_request( - self.t3.user_date_range[0], self.t3.split_boxes[0] - ) - # # check that a Sentinel Hub request was created - assert isinstance(sr2, shb.SentinelHubRequest) - - def test_rename_output_files(self) -> None: - """Test output renaming""" - - # self.t4.send_sentinelhub_requests() - # # check that a list of file names was created - # assert all(isinstance(item, str) for item in self.t4.output_filenames) - # # check that one file name per split box was created - # assert len(self.t4.output_filenames) == len(self.t4.split_boxes) - - def test_send_sentinelhub_requests(self) -> None: - """Test API outputs""" - - # self.t5.send_sentinelhub_requests() - # # check that a list of raw file names was created - # assert all(isinstance(item, str) for item in self.t5.raw_filenames) - # # check that one raw file name per split box was created - # assert len(self.t5.raw_filenames) == len(self.t5.split_boxes) - - def test_merge_rasters(self) -> None: - """Test raster merge""" - - # self.t3.send_sentinelhub_requests() - # # check that a list of renamed file names was created - # assert all(isinstance(item, str) for item in self.t3.output_filenames_renamed) - # # check that one output per split box was created - # assert len(self.t3.outputs) == len(self.t3.split_boxes) - - def test_get_raster_compression(self) -> None: - """""" - #%% - comp_def = self.t1.raster_compression - assert comp_def == None - - - - - - + +def test_init(t1, SH_CLIENT_ID, SH_CLIENT_SECRET) -> None: + """Test auth.txt parsing and connection configuration.""" + + # check for credentials + assert t1.CLIENT_ID == SH_CLIENT_ID + assert t1.CLIENT_SECRET == SH_CLIENT_SECRET + + # check if connection was properly setup + assert isinstance(t1.config, shb.config.SHConfig) + assert t1.config.sh_client_id == SH_CLIENT_ID + assert t1.config.sh_client_secret == SH_CLIENT_SECRET + + +def test_set_query_parameters(t1, test_collection) -> None: + """Test direct attribute assignment.""" + + # check if attributes were set accordingly + assert t1.download_mode is not None + assert t1.download_mode == "SM" + assert t1.verbose + assert t1.data_collection_str == test_collection + assert isinstance(t1.user_date_range, pd.core.indexes.datetimes.DatetimeIndex) + assert isinstance(t1.evaluation_script, str) + + +def test_get_data_collection(t1, test_collection) -> None: + """Test data collection selection.""" + + # check if data collection was set properly + assert t1.data_collection == shb.DataCollection[test_collection] + assert isinstance(t1.data_collection, shb.DataCollection) + + +def test_get_satellite_name(t1) -> None: + """Test satellite name extraction""" + + # check if satellite name was set properly + assert isinstance(t1.satellite, str) + assert t1.satellite == "SENTINEL2" + + +def test_get_raw_data_collection_resolution(t1, t2, t3) -> None: + """Test resolution selection""" + + # check if data resolution was set correctly + assert t1.raw_data_collection_resolution == 10 + assert t2.raw_data_collection_resolution == 10 + assert t3.raw_data_collection_resolution == 10 + + +def test_set_number_of_cores(t1, t2, t3) -> None: + """Test selection of number of cores for multiprocessing""" + + # check if number of cores was set correctly + assert isinstance(t1.nb_cores, int) + assert isinstance(t2.nb_cores, int) + assert isinstance(t3.nb_cores, int) + + +def test_get_date_range(t1, t2, t3) -> None: + """Test datetime object creation""" + + d1 = t1.get_date_range(time_interval=3) + # check if date from present was set accordingly + assert isinstance(d1, pd.DatetimeIndex) + + d2a = t1.get_date_range(time_interval="2019-08-01") + d2b = t2.get_date_range(time_interval="2019-08-01") + d2c = t3.get_date_range(time_interval="2019-08-01") + # check if single date (str) was set accordingly + assert d2a == pd.date_range("2019-08-01", "2019-08-01") + assert d2b == pd.date_range("2019-08-01", "2019-08-01") + assert d2c == pd.date_range("2019-08-01", "2019-08-01") + + d3a = t1.get_date_range(time_interval=["2019-08-01"]) + d3b = t2.get_date_range(time_interval=["2019-08-01"]) + d3c = t3.get_date_range(time_interval=["2019-08-01"]) + # check if single date (list) was set accordingly + assert d3a == pd.date_range("2019-08-01", "2019-08-01") + assert d3b == pd.date_range("2019-08-01", "2019-08-01") + assert d3c == pd.date_range("2019-08-01", "2019-08-01") + + d4a = t1.get_date_range(time_interval=["2019-08-01", "2019-08-02", "2019-08-03"]) + d4b = t2.get_date_range(time_interval=["2019-08-01", "2019-08-02", "2019-08-03"]) + d4c = t3.get_date_range(time_interval=["2019-08-01", "2019-08-02", "2019-08-03"]) + # check if a list of dates was set accordingly + pd.testing.assert_index_equal(d4a, pd.date_range("2019-08-01", "2019-08-03")) + pd.testing.assert_index_equal(d4b, pd.date_range("2019-08-01", "2019-08-03")) + pd.testing.assert_index_equal(d4c, pd.date_range("2019-08-01", "2019-08-03")) + + +def test_get_bounding_box(t1, t2, test_bounding_box, test_area_name) -> None: + """Test bounding box creation""" + + bb1 = t1.get_bounding_box(bounding_box=test_bounding_box) + # check if a Sentinel Hub bounding box was created + assert isinstance(bb1, shb.geometry.BBox) + + bb2 = t2.get_bounding_box(bounding_box=test_area_name) + # check if a Sentinel Hub bounding box was created + assert isinstance(bb2, shb.geometry.BBox) + area_coordinates = np.array(bb2.geojson["coordinates"][0]) + area_bounding_box = [ + np.nanmin(area_coordinates[:, 0]), + np.nanmin(area_coordinates[:, 1]), + np.nanmax(area_coordinates[:, 0]), + np.nanmax(area_coordinates[:, 1]), + ] + # check if setting Ilulissat bounding_box with coordinates gives + # the same bounding_box just like calling its area name + assert area_bounding_box == test_bounding_box + + +def test_get_store_folder(t1) -> None: + """Test store folder selection""" + + sf1 = t1.get_store_folder(None) + # # check if default store folder was set accordingly + assert isinstance(sf1, str) + + sf2 = t1.get_store_folder(store_folder="./test/path") + # # check if passed store folder was set accordingly + assert isinstance(sf2, str) + # # check the actual string + assert sf2 == "./test/path" + + +def test_convert_bounding_box_coordinates(t1) -> None: + """Test bounding box conversion""" + + t1.convert_bounding_box_coordinates() + # check if a new Sentinel Hub bounding box was created + assert isinstance(t1.bounding_box_UTM, shb.geometry.BBox) + # check if the right CRS was assigned + assert t1.bounding_box_UTM.crs == shb.CRS("32622") + # check if the right CRS was assigned + assert t1.bounding_box.crs == shb.CRS("4326") + # check if a bounding box list was created + assert isinstance(t1.bounding_box_UTM_list, list) + # check that all items of the list are floats + assert all(isinstance(item, float) for item in t1.bounding_box_UTM_list) + # check that all coordinates were included + assert len(t1.bounding_box_UTM_list) == 4 + + +def test_get_max_resolution(t1) -> None: + """Test maximum resolution computation""" + + mr1 = t1.get_max_resolution() + # check that maximum resolution was set correctly + assert isinstance(mr1, np.int64) + assert mr1 == 11 + + +def test_set_correct_resolution(t1, t3) -> None: + """Test resolution refinement""" + + r1 = t1.set_correct_resolution() + # check that query resolution was set correctly + assert r1 == 10 + # check that download mode was set correctly + assert isinstance(t1.download_mode, str) + + r2 = t3.set_correct_resolution() + # check that query resolution was set correctly + assert r2 == 11 + # check that download mode was set correctly + assert isinstance(t3.download_mode, str) + + +def test_list_requests(t1, t3) -> None: + """Test request listing""" + + lr1 = t1.list_requests() + # check that a list was created accordingly + assert isinstance(lr1, list) + assert len(lr1) == 4 + assert len(lr1) == len(t1.split_boxes) + # check that a list of Sentinel Hub requests was created + assert all(isinstance(item, shb.SentinelHubRequest) for item in lr1) + + lr2 = t3.list_requests() + # check that a list was created accordingly + assert isinstance(lr2, list) + assert len(lr2) == 1 + assert len(lr2) == len(t3.split_boxes) + # check that a list of Sentinel Hub requests was created + assert isinstance(lr2[0], shb.SentinelHubRequest) + + +def test_get_split_boxes(t1, t3) -> None: + """Test split box creation""" + + sb1 = t1.get_split_boxes() + # check that a list of split boxes was created + assert isinstance(sb1, list) + # check that each split box is a Sentinel Hub bounding box + assert all(isinstance(item, shb.geometry.BBox) for item in sb1) + # check that each split box is in the correct projection + assert all(item.crs == shb.CRS("32622") for item in sb1) + + # check that only one box has been created + assert len(t3.split_boxes) == 1 + # check that the split box is in the right projection + assert t3.split_boxes[0].crs == shb.CRS("4326") + + +def test_get_evaluation_script_from_link(t1, test_url) -> None: + """Test custom script extraction from URL""" + + es1 = t1.get_evaluation_script_from_link(test_url) + # check that evalscript was set accordingly + assert es1 == requests.get(test_url).text + + +def test_set_split_boxes_ids(t1) -> None: + """Test split box ID generation""" + + sbi1 = t1.set_split_boxes_ids() + # check that split box ids were saved in dictionary + assert isinstance(sbi1, dict) + # check that dictionary has the right shape + assert len(sbi1) == 4 + + +def test_get_evaluation_script(t1, test_url, test_evalscript) -> None: + """Test evaluation script extraction""" + + es1 = t1.get_evaluation_script(None) + # check that default evalscript was set accordingly + assert es1 == requests.get(test_url).text + + es2 = t1.get_evaluation_script(test_evalscript) + # check that passed evalscript was set correctly + assert isinstance(es2, str) + + +def test_sentinelhub_request(t1, t3) -> None: + """Test API request generation""" + + sr1 = t1.sentinelhub_request(t1.user_date_range[0], t1.split_boxes[0]) + # # check that a Sentinel Hub request was created + assert isinstance(sr1, shb.SentinelHubRequest) + + sr2 = t3.sentinelhub_request(t3.user_date_range[0], t3.split_boxes[0]) + # # check that a Sentinel Hub request was created + assert isinstance(sr2, shb.SentinelHubRequest) + + +def test_rename_output_files() -> None: + """Test output renaming""" + + # t4.send_sentinelhub_requests() + # # check that a list of file names was created + # assert all(isinstance(item, str) for item in t4.output_filenames) + # # check that one file name per split box was created + # assert len(t4.output_filenames) == len(t4.split_boxes) + + +def test_send_sentinelhub_requests() -> None: + """Test API outputs""" + + # t5.send_sentinelhub_requests() + # # check that a list of raw file names was created + # assert all(isinstance(item, str) for item in t5.raw_filenames) + # # check that one raw file name per split box was created + # assert len(t5.raw_filenames) == len(t5.split_boxes) + + +def test_merge_rasters() -> None: + """Test raster merge""" + + # t3.send_sentinelhub_requests() + # # check that a list of renamed file names was created + # assert all(isinstance(item, str) for item in t3.output_filenames_renamed) + # # check that one output per split box was created + # assert len(t3.outputs) == len(t3.split_boxes) + + +# def test_get_raster_compression(t4) -> None: +# """""" + +# comp_def = t4.raster_compression() +# assert comp_def == None From 74cb8b07d057568e45884c1484b3ee052beb2a66 Mon Sep 17 00:00:00 2001 From: AdrienWehrle Date: Thu, 12 Dec 2024 21:10:24 +0100 Subject: [PATCH 19/32] rename filepath for authfile --- tests/conftest.py | 109 +++++++++++++++++------------------------ tests/test_earthspy.py | 5 +- 2 files changed, 45 insertions(+), 69 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 3172816..ccf1cfa 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,55 +1,57 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- """ @author: Adrien Wehrlé, University of Zurich, Switzerland """ -import earthspy.earthspy as es -import pytest import os +import pytest + +import earthspy.earthspy as es + + def pytest_addoption(parser): - parser.addoption("--filepath", action="store", default="test") - + parser.addoption("--authfile", action="store", default="test") -if os.getenv("CI") is not None: + +if os.getenv("CI") is not None: # create local variables from environment secrets for convenience SH_CLIENT_ID = os.environ["SH_CLIENT_ID"] SH_CLIENT_SECRET = os.environ["SH_CLIENT_SECRET"] - + # path to credential file to be created - filepath = "auth.txt" - + authfile = "auth.txt" + # create file containing credentials for testing - with open(filepath, "w") as out: + with open(authfile, "w") as out: out.write(f"{SH_CLIENT_ID}\n{SH_CLIENT_SECRET}") else: + @pytest.fixture(scope="session") - def filepath(pytestconfig): - return pytestconfig.getoption("filepath") - + def authfile(pytestconfig): + return pytestconfig.getoption("authfile") + @pytest.fixture(scope="session") - def credentials(filepath): + def credentials(authfile): # read credentials stored in text file - with open(filepath) as file: + with open(authfile) as file: credentials = file.read().splitlines() return credentials - + @pytest.fixture(scope="session") - def SH_CLIENT_ID(credentials) -> None: + def SH_CLIENT_ID(credentials) -> None: # extract credentials from lines SH_CLIENT_ID = credentials[0] return SH_CLIENT_ID - + @pytest.fixture(scope="session") def SH_CLIENT_SECRET(credentials) -> None: SH_CLIENT_SECRET = credentials[1] return SH_CLIENT_SECRET - @pytest.fixture(scope="session") def test_evalscript(): test_evalscript = """ @@ -69,37 +71,42 @@ def test_evalscript(): } """ return test_evalscript - + + @pytest.fixture(scope="session") -def test_url(): +def test_url(): test_url = ( "https://custom-scripts.sentinel-hub.com/custom-scripts/" + "sentinel-2/true_color/script.js" ) return test_url + @pytest.fixture(scope="session") -def test_collection(): +def test_collection(): # an example of data collection test_collection = "SENTINEL2_L2A" return test_collection - + + @pytest.fixture(scope="session") -def test_bounding_box(): +def test_bounding_box(): # an example of footprint area test_bounding_box = [-51.13, 69.204, -51.06, 69.225] return test_bounding_box - + + @pytest.fixture(scope="session") -def test_area_name(): +def test_area_name(): # an example of area available as GEOJSON file test_area_name = "Ilulissat" return test_area_name + @pytest.fixture(scope="session") -def t1(filepath, test_evalscript, test_collection, test_bounding_box): +def t1(authfile, test_evalscript, test_collection, test_bounding_box): # example of query with default parameters - t1 = es.EarthSpy(filepath) + t1 = es.EarthSpy(authfile) t1.set_query_parameters( bounding_box=test_bounding_box, time_interval=["2019-08-23"], @@ -109,10 +116,11 @@ def t1(filepath, test_evalscript, test_collection, test_bounding_box): ) return t1 + @pytest.fixture(scope="session") -def t2(filepath, test_evalscript, test_collection, test_area_name): +def t2(authfile, test_evalscript, test_collection, test_area_name): # example of query with direct area name - t2 = es.EarthSpy(filepath) + t2 = es.EarthSpy(authfile) t2.set_query_parameters( bounding_box=test_area_name, time_interval=["2019-08-23"], @@ -122,10 +130,11 @@ def t2(filepath, test_evalscript, test_collection, test_area_name): ) return t2 + @pytest.fixture(scope="session") -def t3(filepath, test_evalscript, test_collection, test_bounding_box): +def t3(authfile, test_evalscript, test_collection, test_bounding_box): # example of query with direct mode - t3 = es.EarthSpy(filepath) + t3 = es.EarthSpy(authfile) t3.set_query_parameters( bounding_box=test_bounding_box, time_interval=["2019-08-23"], @@ -135,10 +144,11 @@ def t3(filepath, test_evalscript, test_collection, test_bounding_box): ) return t3 + @pytest.fixture(scope="session") -def t4(filepath, test_evalscript, test_collection, test_bounding_box): +def t4(authfile, test_evalscript, test_collection, test_bounding_box): # example of query with direct mode - t4 = es.EarthSpy(filepath) + t4 = es.EarthSpy(authfile) t4.set_query_parameters( bounding_box=test_bounding_box, time_interval=["2019-08-23"], @@ -148,34 +158,3 @@ def t4(filepath, test_evalscript, test_collection, test_bounding_box): raster_compression="LZW", ) return t4 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tests/test_earthspy.py b/tests/test_earthspy.py index 2e2be60..d237ee1 100644 --- a/tests/test_earthspy.py +++ b/tests/test_earthspy.py @@ -5,15 +5,12 @@ """ -import glob -import json -import os - import numpy as np import pandas as pd import requests import sentinelhub as shb + def test_init(t1, SH_CLIENT_ID, SH_CLIENT_SECRET) -> None: """Test auth.txt parsing and connection configuration.""" From bf94c1aa36d72a040211aed04af4c102f78362c8 Mon Sep 17 00:00:00 2001 From: AdrienWehrle Date: Thu, 12 Dec 2024 21:33:03 +0100 Subject: [PATCH 20/32] fix authfile fixture --- tests/conftest.py | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index ccf1cfa..f08b797 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -13,47 +13,65 @@ def pytest_addoption(parser): - parser.addoption("--authfile", action="store", default="test") + """Add option to pass local path to authentication file""" + parser.addoption( + "--authfile", + action="store", + default="./auth.txt", + help="Full path to Sentinel Hub credential file containing ID and password", + ) +# if running in Github action if os.getenv("CI") is not None: + # create local variables from environment secrets for convenience SH_CLIENT_ID = os.environ["SH_CLIENT_ID"] SH_CLIENT_SECRET = os.environ["SH_CLIENT_SECRET"] # path to credential file to be created - authfile = "auth.txt" + @pytest.fixture(scope="session") + def authfile(pytestconfig): + """Set credential file name""" + authfile = "auth.txt" + return authfile # create file containing credentials for testing with open(authfile, "w") as out: out.write(f"{SH_CLIENT_ID}\n{SH_CLIENT_SECRET}") + +# if running locally else: @pytest.fixture(scope="session") def authfile(pytestconfig): + """Get option from command line call""" return pytestconfig.getoption("authfile") @pytest.fixture(scope="session") def credentials(authfile): - # read credentials stored in text file + """Read credentials stored in text file""" + with open(authfile) as file: credentials = file.read().splitlines() return credentials @pytest.fixture(scope="session") def SH_CLIENT_ID(credentials) -> None: - # extract credentials from lines + """Extract client id from line""" SH_CLIENT_ID = credentials[0] return SH_CLIENT_ID @pytest.fixture(scope="session") def SH_CLIENT_SECRET(credentials) -> None: + """Extract client secret from line""" SH_CLIENT_SECRET = credentials[1] return SH_CLIENT_SECRET @pytest.fixture(scope="session") def test_evalscript(): + """Set a test evalscript for Sentinel-2""" test_evalscript = """ //VERSION=3 function setup(){ @@ -75,6 +93,7 @@ def test_evalscript(): @pytest.fixture(scope="session") def test_url(): + """Set a test evalscript pointing to Sentinel-2 True Color""" test_url = ( "https://custom-scripts.sentinel-hub.com/custom-scripts/" + "sentinel-2/true_color/script.js" @@ -84,28 +103,28 @@ def test_url(): @pytest.fixture(scope="session") def test_collection(): - # an example of data collection + """Set a test data collection""" test_collection = "SENTINEL2_L2A" return test_collection @pytest.fixture(scope="session") def test_bounding_box(): - # an example of footprint area + """Set a test footprint area (bounding box)""" test_bounding_box = [-51.13, 69.204, -51.06, 69.225] return test_bounding_box @pytest.fixture(scope="session") def test_area_name(): - # an example of area available as GEOJSON file + """Set a test area available as geojson file""" test_area_name = "Ilulissat" return test_area_name @pytest.fixture(scope="session") def t1(authfile, test_evalscript, test_collection, test_bounding_box): - # example of query with default parameters + """Set a test query with default parameters""" t1 = es.EarthSpy(authfile) t1.set_query_parameters( bounding_box=test_bounding_box, @@ -119,7 +138,7 @@ def t1(authfile, test_evalscript, test_collection, test_bounding_box): @pytest.fixture(scope="session") def t2(authfile, test_evalscript, test_collection, test_area_name): - # example of query with direct area name + """Set a test query with area name""" t2 = es.EarthSpy(authfile) t2.set_query_parameters( bounding_box=test_area_name, @@ -133,7 +152,7 @@ def t2(authfile, test_evalscript, test_collection, test_area_name): @pytest.fixture(scope="session") def t3(authfile, test_evalscript, test_collection, test_bounding_box): - # example of query with direct mode + """Set a test query with direct download mode""" t3 = es.EarthSpy(authfile) t3.set_query_parameters( bounding_box=test_bounding_box, @@ -147,7 +166,7 @@ def t3(authfile, test_evalscript, test_collection, test_bounding_box): @pytest.fixture(scope="session") def t4(authfile, test_evalscript, test_collection, test_bounding_box): - # example of query with direct mode + """Set a test query with LZW raster compression""" t4 = es.EarthSpy(authfile) t4.set_query_parameters( bounding_box=test_bounding_box, From 3f242d8a8fc5967b8c5ea79c89acbbb72bfc65e5 Mon Sep 17 00:00:00 2001 From: AdrienWehrle Date: Thu, 12 Dec 2024 21:51:05 +0100 Subject: [PATCH 21/32] try and fix authfile writing in Github action --- tests/conftest.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index f08b797..aded3b6 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -31,14 +31,20 @@ def pytest_addoption(parser): # path to credential file to be created @pytest.fixture(scope="session") - def authfile(pytestconfig): + def authfile(): """Set credential file name""" authfile = "auth.txt" return authfile - # create file containing credentials for testing - with open(authfile, "w") as out: - out.write(f"{SH_CLIENT_ID}\n{SH_CLIENT_SECRET}") + # path to credential file to be created + @pytest.fixture(scope="session") + def write_authfile(authfile): + """Create file containing credentials for testing""" + with open(authfile, "w") as out: + out.write(f"{SH_CLIENT_ID}\n{SH_CLIENT_SECRET}") + + return None + # if running locally else: From b6bc46977b23b2112cd1d44fbd02f909a1b5dc0f Mon Sep 17 00:00:00 2001 From: AdrienWehrle Date: Thu, 12 Dec 2024 22:00:24 +0100 Subject: [PATCH 22/32] modify compression methods --- earthspy/earthspy.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/earthspy/earthspy.py b/earthspy/earthspy.py index cab0fd9..d0b4bc5 100644 --- a/earthspy/earthspy.py +++ b/earthspy/earthspy.py @@ -203,21 +203,18 @@ def get_raster_compression(self, raster_compression: Union[None, str]) -> str: :rtype: Union[None, str] """ - if raster_compression in [ - "DEFLATE", - "LZW", - "PACKBITS", - "JPEG", - "WEBP", - "LZMA", - "ZSTD", - ]: + # list rasterio compression algorithm and exclude dunders + rasterio_compression_algorithms = [ + m for m in dir(rasterio.enums.Compression) if not m.startswith("__") + ] + # use rasterio compression method as is + if raster_compression.lower() in rasterio_compression_algorithms: self.raster_compression = raster_compression elif raster_compression is None: self.raster_compression = None else: - raise KeyError("Compression mode not found") + raise KeyError("Compression algorithm not found") return self.raster_compression From f6acfc7f5de66da9e33963ba7ebc738b94e7322a Mon Sep 17 00:00:00 2001 From: AdrienWehrle Date: Thu, 12 Dec 2024 22:02:50 +0100 Subject: [PATCH 23/32] fix authfile --- tests/conftest.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index aded3b6..aa312a8 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -32,18 +32,12 @@ def pytest_addoption(parser): # path to credential file to be created @pytest.fixture(scope="session") def authfile(): - """Set credential file name""" + """Set credential file name and create credential file + for testing""" authfile = "auth.txt" - return authfile - - # path to credential file to be created - @pytest.fixture(scope="session") - def write_authfile(authfile): - """Create file containing credentials for testing""" with open(authfile, "w") as out: out.write(f"{SH_CLIENT_ID}\n{SH_CLIENT_SECRET}") - - return None + return authfile # if running locally From 9d722c2d21fc22a493666040511ba8ac1cb287ab Mon Sep 17 00:00:00 2001 From: AdrienWehrle Date: Thu, 12 Dec 2024 22:10:57 +0100 Subject: [PATCH 24/32] fix authfile --- tests/conftest.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index aa312a8..844bfc9 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -25,13 +25,21 @@ def pytest_addoption(parser): # if running in Github action if os.getenv("CI") is not None: - # create local variables from environment secrets for convenience - SH_CLIENT_ID = os.environ["SH_CLIENT_ID"] - SH_CLIENT_SECRET = os.environ["SH_CLIENT_SECRET"] + @pytest.fixture(scope="session") + def SH_CLIENT_ID() -> None: + """Create local client id from environment variable""" + SH_CLIENT_ID = os.environ["SH_CLIENT_ID"] + return SH_CLIENT_ID + + @pytest.fixture(scope="session") + def SH_CLIENT_SECRET() -> None: + """Create local client secret from environment variable""" + SH_CLIENT_SECRET = os.environ["SH_CLIENT_SECRET"] + return SH_CLIENT_SECRET # path to credential file to be created @pytest.fixture(scope="session") - def authfile(): + def authfile(SH_CLIENT_ID, SH_CLIENT_SECRET): """Set credential file name and create credential file for testing""" authfile = "auth.txt" From 7ec7f3d3c57a48582ac247e4a3fa8189837df9e5 Mon Sep 17 00:00:00 2001 From: AdrienWehrle Date: Thu, 12 Dec 2024 22:14:30 +0100 Subject: [PATCH 25/32] add assert for authentification --- tests/conftest.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/conftest.py b/tests/conftest.py index 844bfc9..1177b51 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -28,12 +28,16 @@ def pytest_addoption(parser): @pytest.fixture(scope="session") def SH_CLIENT_ID() -> None: """Create local client id from environment variable""" + # check if variable in environment variables + assert "SH_CLIENT_ID" in os.environ SH_CLIENT_ID = os.environ["SH_CLIENT_ID"] return SH_CLIENT_ID @pytest.fixture(scope="session") def SH_CLIENT_SECRET() -> None: """Create local client secret from environment variable""" + # check if variable in environment variables + assert "SH_CLIENT_SECRET" in os.environ SH_CLIENT_SECRET = os.environ["SH_CLIENT_SECRET"] return SH_CLIENT_SECRET From 2dd7d8a71a72f5a79f8edb9746618ede5613829e Mon Sep 17 00:00:00 2001 From: AdrienWehrle Date: Thu, 12 Dec 2024 22:18:37 +0100 Subject: [PATCH 26/32] remove assert --- tests/conftest.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 1177b51..802c506 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -29,7 +29,6 @@ def pytest_addoption(parser): def SH_CLIENT_ID() -> None: """Create local client id from environment variable""" # check if variable in environment variables - assert "SH_CLIENT_ID" in os.environ SH_CLIENT_ID = os.environ["SH_CLIENT_ID"] return SH_CLIENT_ID @@ -37,7 +36,6 @@ def SH_CLIENT_ID() -> None: def SH_CLIENT_SECRET() -> None: """Create local client secret from environment variable""" # check if variable in environment variables - assert "SH_CLIENT_SECRET" in os.environ SH_CLIENT_SECRET = os.environ["SH_CLIENT_SECRET"] return SH_CLIENT_SECRET From 533c2f9c3b6befcfb2efd8950ca14004715fa84d Mon Sep 17 00:00:00 2001 From: Antsalacia Date: Mon, 16 Dec 2024 11:02:46 +0100 Subject: [PATCH 27/32] change None check and add test for comp --- earthspy/earthspy.py | 6 +++--- tests/test_earthspy.py | 13 ++++++++----- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/earthspy/earthspy.py b/earthspy/earthspy.py index d0b4bc5..1f4a719 100644 --- a/earthspy/earthspy.py +++ b/earthspy/earthspy.py @@ -209,10 +209,10 @@ def get_raster_compression(self, raster_compression: Union[None, str]) -> str: ] # use rasterio compression method as is - if raster_compression.lower() in rasterio_compression_algorithms: - self.raster_compression = raster_compression - elif raster_compression is None: + if raster_compression is None: self.raster_compression = None + elif raster_compression.lower() in rasterio_compression_algorithms: + self.raster_compression = raster_compression else: raise KeyError("Compression algorithm not found") diff --git a/tests/test_earthspy.py b/tests/test_earthspy.py index d237ee1..7e0aaf3 100644 --- a/tests/test_earthspy.py +++ b/tests/test_earthspy.py @@ -290,8 +290,11 @@ def test_merge_rasters() -> None: # assert len(t3.outputs) == len(t3.split_boxes) -# def test_get_raster_compression(t4) -> None: -# """""" - -# comp_def = t4.raster_compression() -# assert comp_def == None +def test_get_raster_compression(t3, t4) -> None: + """""" + + comp_def = t3.raster_compression + assert comp_def == None + + comp_cust = t4.raster_compression + assert comp_cust == "LZW" \ No newline at end of file From 239bfb25a470ea4b6586ffb51e0d5709ebfeea1d Mon Sep 17 00:00:00 2001 From: Antsalacia Date: Mon, 16 Dec 2024 11:05:43 +0100 Subject: [PATCH 28/32] Add comments --- tests/test_earthspy.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/test_earthspy.py b/tests/test_earthspy.py index 7e0aaf3..3860f46 100644 --- a/tests/test_earthspy.py +++ b/tests/test_earthspy.py @@ -291,10 +291,11 @@ def test_merge_rasters() -> None: def test_get_raster_compression(t3, t4) -> None: - """""" - + """Test raster compression""" + # check default raster compression comp_def = t3.raster_compression assert comp_def == None + # check raster compression sith mode specified comp_cust = t4.raster_compression assert comp_cust == "LZW" \ No newline at end of file From 92c6479a8417313f41f62043940327c128626787 Mon Sep 17 00:00:00 2001 From: Antsalacia Date: Mon, 16 Dec 2024 11:17:38 +0100 Subject: [PATCH 29/32] comply with github_adv_sec --- tests/test_earthspy.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_earthspy.py b/tests/test_earthspy.py index 3860f46..fe98887 100644 --- a/tests/test_earthspy.py +++ b/tests/test_earthspy.py @@ -294,8 +294,8 @@ def test_get_raster_compression(t3, t4) -> None: """Test raster compression""" # check default raster compression comp_def = t3.raster_compression - assert comp_def == None - + assert comp_def is None + # check raster compression sith mode specified comp_cust = t4.raster_compression - assert comp_cust == "LZW" \ No newline at end of file + assert comp_cust == "LZW" From 0ebfcc6b4ee1d401b299d7b7072514cf64386821 Mon Sep 17 00:00:00 2001 From: Antsalacia Date: Mon, 16 Dec 2024 11:30:23 +0100 Subject: [PATCH 30/32] fix typo --- tests/test_earthspy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_earthspy.py b/tests/test_earthspy.py index fe98887..33254c3 100644 --- a/tests/test_earthspy.py +++ b/tests/test_earthspy.py @@ -296,6 +296,6 @@ def test_get_raster_compression(t3, t4) -> None: comp_def = t3.raster_compression assert comp_def is None - # check raster compression sith mode specified + # check raster compression with mode specified comp_cust = t4.raster_compression assert comp_cust == "LZW" From 7ade2d3d51dc3406bdc2fb9910f5b648fb1f4fd2 Mon Sep 17 00:00:00 2001 From: AdrienWehrle Date: Tue, 17 Dec 2024 16:26:46 +0100 Subject: [PATCH 31/32] forgot pre-commit --- earthspy/earthspy.py | 2 +- tests/test_earthspy.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/earthspy/earthspy.py b/earthspy/earthspy.py index 1f4a719..28330eb 100644 --- a/earthspy/earthspy.py +++ b/earthspy/earthspy.py @@ -177,7 +177,7 @@ def set_query_parameters( # set and correct resolution self.set_correct_resolution() - # set compress mode + # set compression method self.get_raster_compression(raster_compression) # set post-processing attributes diff --git a/tests/test_earthspy.py b/tests/test_earthspy.py index 33254c3..336b80c 100644 --- a/tests/test_earthspy.py +++ b/tests/test_earthspy.py @@ -296,6 +296,6 @@ def test_get_raster_compression(t3, t4) -> None: comp_def = t3.raster_compression assert comp_def is None - # check raster compression with mode specified + # check raster compression when LZW compression is specified comp_cust = t4.raster_compression assert comp_cust == "LZW" From 80b174b27239c3eef094abf16ddea1dd5f97c172 Mon Sep 17 00:00:00 2001 From: AdrienWehrle Date: Tue, 17 Dec 2024 16:31:37 +0100 Subject: [PATCH 32/32] add Antsalacia in author list --- earthspy/earthspy.py | 2 +- tests/conftest.py | 2 +- tests/test_earthspy.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/earthspy/earthspy.py b/earthspy/earthspy.py index 28330eb..67328b3 100644 --- a/earthspy/earthspy.py +++ b/earthspy/earthspy.py @@ -1,6 +1,6 @@ """ -@author: Adrien Wehrlé, EO-IO, University of Zurich, Switzerland +@authors: Adrien Wehrlé (EO-IO), Antsalacia """ diff --git a/tests/conftest.py b/tests/conftest.py index 802c506..a30424f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 """ -@author: Adrien Wehrlé, University of Zurich, Switzerland +@authors: Adrien Wehrlé (EO-IO), Antsalacia """ diff --git a/tests/test_earthspy.py b/tests/test_earthspy.py index 336b80c..8f0398c 100644 --- a/tests/test_earthspy.py +++ b/tests/test_earthspy.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 """ -@author: Adrien Wehrlé, EO-IO, University of Zurich, Switzerland +@authors: Adrien Wehrlé (EO-IO), Antsalacia """