diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index bcc9c0e..9df12a1 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -15,10 +15,10 @@ jobs: - name: Checkout source uses: actions/checkout@v2 - - name: Set up Python 3.7 + - name: Set up Python 3.8 uses: actions/setup-python@v2 with: - python-version: "3.7" + python-version: "3.8" - name: Check that the current version isn't already on PyPi run: | diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 10a1ef3..e2a37fb 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,10 +16,10 @@ jobs: steps: - name: Checkout the repo uses: actions/checkout@v2 - - name: Set up Python 3.7 + - name: Set up Python 3.8 uses: actions/setup-python@v2 with: - python-version: "3.7" + python-version: "3.8" - name: Run pre-commit action uses: pre-commit/action@v2.0.0 @@ -28,7 +28,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: [3.7, 3.11] + python-version: [3.8, 3.12] os: [ubuntu-latest] steps: - name: Checkout the repo @@ -65,10 +65,10 @@ jobs: steps: - name: Checkout the repo uses: actions/checkout@v2 - - name: Set up Python 3.7 + - name: Set up Python 3.8 uses: actions/setup-python@v2 with: - python-version: "3.7" + python-version: "3.8" - name: Update pip run: python -m pip install --upgrade pip - name: Get pip cache dir diff --git a/CHANGES.rst b/CHANGES.rst index 3a2ba6a..0d3ee93 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,6 +1,13 @@ Release history --------------- +0.3.1 (2023-11-14) +++++++++++++++++++ + +- Allows regex in band selection through `StacAssets` driver (#38) +- Removes support for `python3.7`` and adds support for `python3.12` (#39) +- Various minor fixes and improvements (#37) + 0.3.0 (2023-03-17) ++++++++++++++++++ diff --git a/README.rst b/README.rst index 8c60fed..39e38b8 100644 --- a/README.rst +++ b/README.rst @@ -72,7 +72,7 @@ Example usage for interacting with the api in your Python code: Contribute ========== -If you intend to contribute to eodag-sentinelsat source code:: +If you intend to contribute to eodag-cube source code:: git clone https://github.com/CS-SI/eodag-cube.git cd eodag-cube diff --git a/eodag_cube/__init__.py b/eodag_cube/__init__.py index b780744..6aac0c1 100644 --- a/eodag_cube/__init__.py +++ b/eodag_cube/__init__.py @@ -19,7 +19,7 @@ __title__ = "eodag-cube" __description__ = "Data access for EODAG" -__version__ = "0.3.0" +__version__ = "0.3.1" __author__ = "CS GROUP - France (CSSI)" __author_email__ = "eodag@csgroup.space" __url__ = "https://github.com/CS-SI/eodag-cube" diff --git a/eodag_cube/api/product/drivers/stac_assets.py b/eodag_cube/api/product/drivers/stac_assets.py index 48dead4..2d32a20 100644 --- a/eodag_cube/api/product/drivers/stac_assets.py +++ b/eodag_cube/api/product/drivers/stac_assets.py @@ -15,6 +15,8 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +import re + from eodag.api.product.drivers.base import DatasetDriver from eodag.utils.exceptions import AddressNotFound @@ -28,11 +30,47 @@ def get_data_address(self, eo_product, band): See :func:`~eodag.api.product.drivers.base.DatasetDriver.get_data_address` to get help on the formal parameters. """ - if band in eo_product.assets: - return eo_product.assets[band]["href"] - elif band.upper() in [b.upper() for b in eo_product.assets.keys()]: - for k, v in eo_product.assets.items(): - if k.upper() == band.upper(): - return v["href"] + error_message = "" + + # try using exact + p = re.compile(rf"^{band}$", re.IGNORECASE) + matching_keys = [ + s + for s in eo_product.assets.keys() + if ( + ( + "roles" in eo_product.assets[s] + and "data" in eo_product.assets[s]["roles"] + ) + or ("roles" not in eo_product.assets[s]) + ) + and p.match(s) + ] + if len(matching_keys) == 1: + return eo_product.assets[matching_keys[0]]["href"] + else: + error_message += ( + rf"{len(matching_keys)} assets keys found matching {p} AND " + ) - raise AddressNotFound + # try to find keys containing given band + p = re.compile(rf"^.*{band}.*$", re.IGNORECASE) + matching_keys = [ + s + for s in eo_product.assets.keys() + if ( + ( + "roles" in eo_product.assets[s] + and "data" in eo_product.assets[s]["roles"] + ) + or ("roles" not in eo_product.assets[s]) + ) + and p.match(s) + ] + if len(matching_keys) == 1: + return eo_product.assets[matching_keys[0]]["href"] + else: + raise AddressNotFound( + rf"Please adapt given band parameter ('{band}') to match only one asset: {error_message}" + rf"{len(matching_keys)} assets keys found matching {p}" + ) diff --git a/setup.py b/setup.py index e05def1..a974a29 100644 --- a/setup.py +++ b/setup.py @@ -57,11 +57,11 @@ "License :: OSI Approved :: Apache Software License", "Programming Language :: Python", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", "Programming Language :: Python :: Implementation :: CPython", "Topic :: Scientific/Engineering :: GIS", ], diff --git a/tests/units/test_eoproduct_driver_stac_assets.py b/tests/units/test_eoproduct_driver_stac_assets.py index 8678704..6e33119 100644 --- a/tests/units/test_eoproduct_driver_stac_assets.py +++ b/tests/units/test_eoproduct_driver_stac_assets.py @@ -35,16 +35,39 @@ def setUp(self): "S2A_MSIL1C_20180101T105441_N0206_R051_T31TDH_20180101T124911.SAFE", ) self.product.assets = { - "B01": { - "title": "Band 1 (coastal)", + "T31TDH_20180101T124911_B01.jp2": { + "title": "Band 1", "type": "image/jp2", + "roles": ["data"], "href": os.path.join( TEST_RESOURCES_PATH, "products", "S2A_MSIL1C_20180101T105441_N0206_R051_T31TDH_20180101T124911.SAFE/" + "GRANULE/L1C_T31TDH_A013204_20180101T105435/IMG_DATA/T31TDH_20180101T105441_B01.jp2", ), - } + }, + "T31TDH_20180101T124911_B03.jp2": { + "title": "Band 3", + "type": "image/jp2", + "roles": ["data"], + "href": os.path.join( + TEST_RESOURCES_PATH, + "products", + "S2A_MSIL1C_20180101T105441_N0206_R051_T31TDH_20180101T124911.SAFE/" + + "GRANULE/L1C_T31TDH_A013204_20180101T105435/IMG_DATA/T31TDH_20180101T105441_B03.jp2", + ), + }, + "T31TDH_20180101T124911_B01.json": { + "title": "Band 1 metadata", + "type": "image/jp2", + "roles": ["metadata"], + "href": os.path.join( + TEST_RESOURCES_PATH, + "products", + "S2A_MSIL1C_20180101T105441_N0206_R051_T31TDH_20180101T124911.SAFE/" + + "GRANULE/L1C_T31TDH_A013204_20180101T105435/IMG_DATA/T31TDH_20180101T105441_B01.json", + ), + }, } self.stac_assets_driver = StacAssets() @@ -54,11 +77,22 @@ def test_driver_get_local_dataset_address_bad_band(self): driver = StacAssets() band = "B02" self.assertRaises(AddressNotFound, driver.get_data_address, product, band) + band = "B0" + self.assertRaises(AddressNotFound, driver.get_data_address, product, band) def test_driver_get_local_dataset_address_ok(self): """Driver returns a good address for an existing band""" with self._filesystem_product() as product: - band = "B01" + band = "b01" + address = self.stac_assets_driver.get_data_address(product, band) + self.assertEqual(address, self.local_band_file) + band = "t31tdh_20180101t124911_b01" + address = self.stac_assets_driver.get_data_address(product, band) + self.assertEqual(address, self.local_band_file) + band = "T31TDH_20180101T124911_B01.jp2" + address = self.stac_assets_driver.get_data_address(product, band) + self.assertEqual(address, self.local_band_file) + band = "T31TDH.*B01.*" address = self.stac_assets_driver.get_data_address(product, band) self.assertEqual(address, self.local_band_file) diff --git a/tox.ini b/tox.ini index de8f2cf..f7f5028 100644 --- a/tox.ini +++ b/tox.ini @@ -1,15 +1,15 @@ [tox] -envlist = py37, py38, py39, py10, py311, pypi, linters +envlist = py38, py39, py10, py311, py312, pypi, linters skipsdist = True # Mapping required by tox-gh-actions, only used in CI [gh-actions] python = - 3.7: py37 3.8: py38 3.9: py39 3.10: py310 3.11: py311 + 3.12: py312 [testenv] deps =