Skip to content

Commit a16335d

Browse files
authored
Merge pull request #1084 from xcube-dev/konstntokas-xxx-small_adjustments_https_datastore_for_xcube_zenodo
Bug fix in `has_data` method for `"https"` data store
2 parents 765d0aa + 2fd4010 commit a16335d

File tree

3 files changed

+55
-4
lines changed

3 files changed

+55
-4
lines changed

CHANGES.md

+8-3
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,21 @@
99
* The behaviour of the function `xcube.core.resample.resample_in_space()` has
1010
been changed if no `tile_size` is specified for the target grid mapping. It now
1111
defaults to the `tile_size` of the source grid mapping, improving the
12-
user-friendliness of resampling and reprojection.
12+
user-friendliness of resampling and reprojection. (#1082)
1313
* The `"https"` data store (`store = new_data_store("https", ...)`) now allows
1414
for lazily accessing NetCDF files.
1515
Implementation note: For this to work, the `DatasetNetcdfFsDataAccessor`
16-
class has been adjusted.
16+
class has been adjusted. (#1083)
1717

1818
### Fixes
1919

2020
* The function `xcube.core.resample.resample_in_space()` now always operates
21-
lazily and therefore supports chunk-wise, parallel processing. (#1
21+
lazily and therefore supports chunk-wise, parallel processing. (#1082)
22+
* Bux fix in the `has_data` method of the `"https"` data store
23+
(`store = new_data_store("https", ...)`). (#1084)
24+
* Bux fix in the `has_data` method of all filesystem-based data store
25+
(`"file", "s3", "https"`). `data_type` can be any of the supported data types,
26+
e.g. for `.tif` file, `data_type` can be either `dataset` or `mldataset`. (#1084)
2227
* The explaination of the parameter `xy_scale` in the method
2328
`xcube.core.gridmapping.GridMapping.scale` has been corrected. (#1086)
2429

test/core/store/test_store.py

+32
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@
22
# Permissions are hereby granted under the terms of the MIT License:
33
# https://opensource.org/licenses/MIT.
44
import unittest
5+
from unittest.mock import patch
6+
from unittest.mock import MagicMock
57

68
from fsspec.registry import register_implementation
79

810
from xcube.core.store import DataStoreError
911
from xcube.core.store import list_data_store_ids
1012
from xcube.core.store import new_data_store
13+
1114
import pytest
1215

1316

@@ -57,6 +60,35 @@ def test_get_data_opener_ids(self):
5760
store.get_data_opener_ids(data_id="test.geotiff", data_type="mldataset"),
5861
)
5962

63+
@patch("fsspec.filesystem")
64+
def test_has_data(self, mock_filesystem):
65+
# Mock the HTTPFileSystem instance and its `exists` method
66+
mock_http_fs = MagicMock()
67+
mock_filesystem.return_value = mock_http_fs
68+
mock_http_fs.exists.return_value = True
69+
mock_http_fs.sep = "/"
70+
71+
store = new_data_store("https", root="test.org")
72+
73+
res = store.has_data(data_id="test.tif")
74+
self.assertEqual(mock_filesystem.call_count, 1)
75+
mock_http_fs.exists.assert_called_once_with("https://test.org/test.tif")
76+
self.assertTrue(res)
77+
78+
res = store.has_data(data_id="test.tif", data_type="dataset")
79+
mock_http_fs.exists.assert_called_with("https://test.org/test.tif")
80+
self.assertEqual(mock_http_fs.exists.call_count, 2)
81+
self.assertTrue(res)
82+
83+
res = store.has_data(data_id="test.tif", data_type="mldataset")
84+
mock_http_fs.exists.assert_called_with("https://test.org/test.tif")
85+
self.assertEqual(mock_http_fs.exists.call_count, 3)
86+
self.assertTrue(res)
87+
88+
res = store.has_data(data_id="test.tif", data_type="geodataframe")
89+
self.assertEqual(mock_http_fs.exists.call_count, 3)
90+
self.assertFalse(res)
91+
6092

6193
def test_fsspec_instantiation_error():
6294
error_string = "deliberate instantiation error for testing"

xcube/core/store/fs/store.py

+15-1
Original file line numberDiff line numberDiff line change
@@ -275,8 +275,10 @@ def get_data_ids(
275275

276276
def has_data(self, data_id: str, data_type: DataTypeLike = None) -> bool:
277277
assert_given(data_id, "data_id")
278-
if self._is_data_specified(data_id, data_type):
278+
if self._is_data_type_available(data_id, data_type):
279279
fs_path = self._convert_data_id_into_fs_path(data_id)
280+
if self.protocol == "https":
281+
fs_path = f"{self.protocol}://{fs_path}"
280282
return self.fs.exists(fs_path)
281283
return False
282284

@@ -509,6 +511,18 @@ def _is_data_specified(
509511
return False
510512
return True
511513

514+
def _is_data_type_available(self, data_id: str, data_type: DataTypeLike) -> bool:
515+
ext = self._get_filename_ext(data_id)
516+
format_id = _FILENAME_EXT_TO_FORMAT.get(ext.lower())
517+
if format_id is None:
518+
return False
519+
avail_data_types = _FORMAT_TO_DATA_TYPE_ALIASES.get(format_id)
520+
data_type = DataType.normalize(data_type)
521+
return any(
522+
data_type.is_super_type_of(avail_data_type)
523+
for avail_data_type in avail_data_types
524+
)
525+
512526
def _assert_data_specified(self, data_id, data_type: DataTypeLike):
513527
self._is_data_specified(data_id, data_type, require=True)
514528

0 commit comments

Comments
 (0)