diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ad25f3d0c1684dfa55aca802085cb22c44bfa2e3..040e3c2851a3acc3b83c9cefaef8c49a5f9a63d0 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -43,6 +43,7 @@ pip_install: stage: Install script: - pip install . + - python -c "import theia_picker" # ------------------------------- Doc ------------------------------------------ diff --git a/setup.py b/setup.py index 8f92efa5ed81ecafec05398e941aedbbcdaa3829..9a3c597a8a4f036e51608f741c4850b8deec12e5 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ from setuptools import setup, find_packages -install_requires = ["requests", "pydantic==1.*", "urllib3", "tqdm"] +install_requires = ["requests", "pydantic==2.*", "urllib3", "tqdm"] setup( name="theia-picker", diff --git a/test/download_test.py b/test/download_test.py index 3065a4fcc14b60afecdb6ec19131cb9755bca461..ed67c42640c150d79ca624781e2f8d81b6386553 100644 --- a/test/download_test.py +++ b/test/download_test.py @@ -7,6 +7,8 @@ import theia_picker username = os.environ["THEIA_IDENT"] password = os.environ["THEIA_PASS"] +test_zip = False + with tempfile.TemporaryDirectory() as output_dir: # Login cat = theia_picker.TheiaCatalog( @@ -23,29 +25,36 @@ with tempfile.TemporaryDirectory() as output_dir: assert len(features) == 1 print("Search OK") -# # Download some files -# patterns = [".jpg", ".xml", "EDG_R2.tif", "FRE_B7.tif"] -# for feat in features: -# assert feat.properties.product_identifier == \ -# "SENTINEL2A_20220114-103855-001_L2A_T31TFJ_D" -# files = feat.list_files_in_archive() -# assert len(files) == 527 -# for file in files: -# if any(pattern in file for pattern in patterns): -# feat.download_single_file( -# filename=file, -# download_dir=output_dir -# ) -# out_file = os.path.join(output_dir, file) -# assert os.path.isfile(out_file) -# print("Download single file OK") -# -# # Download files batch -# feats = cat.search( -# tile_name="T31TEJ", start_date="14/01/2021", level="LEVEL2A" -# ) -# for f in feats: -# f.download_files( -# matching=["FRE_B4.tif", "FRE_B8.tif"], download_dir="/tmp" -# ) -# print("Download multiple files OK") + # Download some files + patterns = [".jpg", ".xml", "EDG_R2.tif", "FRE_B7.tif"] + for feat in features: + assert feat.properties.product_identifier == \ + "SENTINEL2A_20220114-103855-001_L2A_T31TFJ_D" + if test_zip: + files = feat.list_files_in_archive() + assert len(files) == 527 + for file in files: + if any(pattern in file for pattern in patterns): + feat.download_single_file( + filename=file, + download_dir=output_dir + ) + out_file = os.path.join(output_dir, file) + assert os.path.isfile(out_file) + print("Download single file OK") + + # Download archive + feat.download_archive("/tmp/") + print("Download archive OK") + + # Download files batch + feats = cat.search( + tile_name="T31TEJ", start_date="14/01/2021", level="LEVEL2A" + ) + if test_zip: + for f in feats: + f.download_files( + matching=["FRE_B4.tif", "FRE_B8.tif"], download_dir="/tmp" + ) + print("Download multiple files OK") + diff --git a/theia_picker/download.py b/theia_picker/download.py index 7e12294349afb8d0ef4c99c860ab4f224ca34740..60ad7557d9ad4f8015f1e11010d48752a79448c9 100644 --- a/theia_picker/download.py +++ b/theia_picker/download.py @@ -15,7 +15,7 @@ import zlib from contextlib import nullcontext from typing import Any, Dict, List, Union, Callable from urllib.parse import urlencode -from pydantic import BaseModel, Field, validator, Extra # pylint: disable = no-name-in-module, line-too-long # noqa: E501 +from pydantic import BaseModel, Field, field_validator, FieldValidationInfo, ConfigDict # pylint: disable = no-name-in-module, line-too-long # noqa: E501 from requests.adapters import HTTPAdapter, Retry import requests from tqdm.autonotebook import tqdm @@ -30,7 +30,7 @@ SECONDS_BTW_RETRIES = 2 class ProgressStub: """ TQDM stub - + """ def __init__(self, *args, **kwargs): """ @@ -518,8 +518,12 @@ class Download(BaseModel): # pylint: disable = too-few-public-methods url: str = Field(alias="url") checksum: str = Field(alias="checksum") - @validator('url', each_item=True) - def make_url(cls, url: str) -> str: # pylint: disable=no-self-argument + @field_validator("url") + def make_url( # pylint: disable=no-self-argument + cls, + url: str, + info: FieldValidationInfo # pylint: disable=unused-argument + ) -> str: """ Model validator @@ -557,14 +561,14 @@ class Properties(BaseModel): # pylint: disable = too-few-public-methods services: Services = Field(alias="services") -class Feature(BaseModel, extra=Extra.allow): +class Feature(BaseModel): """ Feature model Extended with custom functions to be helpful """ - - _requests_mgr: RequestsManager - _remote_zip: RemoteZip = None + model_config = ConfigDict(arbitrary_types_allowed=True) + requests_mgr: RequestsManager + remote_zip: RemoteZip = None id: str = Field(alias="id") properties: Properties = Field(alias="properties") @@ -588,8 +592,8 @@ class Feature(BaseModel, extra=Extra.allow): """ if renew_token: - self._requests_mgr.renew_authorization_headers() - resp = self._requests_mgr.get(self.properties.services.download.url) + self.requests_mgr.renew_authorization_headers() + resp = self.requests_mgr.get(self.properties.services.download.url) try: tot_size_in_bytes = int(resp.headers.get('content-length', 0)) block_size = 32 * 1024 # 32 Kb @@ -664,13 +668,13 @@ class Feature(BaseModel, extra=Extra.allow): """ if renew_token: - self._requests_mgr.renew_authorization_headers() - if not self._remote_zip: - self._remote_zip = RemoteZip( + self.requests_mgr.renew_authorization_headers() + if not self.remote_zip: + self.remote_zip = RemoteZip( url=self.properties.services.download.url, - requests_mgr=self._requests_mgr + requests_mgr=self.requests_mgr ) - return self._remote_zip + return self.remote_zip def list_files_in_archive(self) -> List[str]: """ @@ -680,6 +684,7 @@ class Feature(BaseModel, extra=Extra.allow): List of files in the remote archive """ + print(self.requests_mgr) return self._get_remote_zip().files_list @retry( @@ -781,7 +786,7 @@ class TheiaCatalog: # pylint: disable = too-few-public-methods # Read THEIA credentials with open(config_file_json, encoding='UTF-8') as json_file: credentials = json.load(json_file) - self._requests_mgr = RequestsManager(credentials=credentials) + self.requests_mgr = RequestsManager(credentials=credentials) self.max_records = max_records def _query(self, dict_query: dict) -> List[Feature]: @@ -813,7 +818,7 @@ class TheiaCatalog: # pylint: disable = too-few-public-methods features = search.json().get("features") log.debug("Got %s results", len(features)) return [ - Feature(_requests_mgr=self._requests_mgr, **record) + Feature(requests_mgr=self.requests_mgr, **record) for record in features ]