Skip to content

feat: Add Zarr v2 metadata access and basic auth support for OIDC-protected assets#2112

Open
cauriol wants to merge 7 commits intodevelopfrom
auth_destinee
Open

feat: Add Zarr v2 metadata access and basic auth support for OIDC-protected assets#2112
cauriol wants to merge 7 commits intodevelopfrom
auth_destinee

Conversation

@cauriol
Copy link
Copy Markdown
Collaborator

@cauriol cauriol commented Mar 25, 2026

This PR adds support for accessing Zarr v2 assets from EOProduct and extends OIDC authentication handling to support Basic authorization for protected asset access.

Changes:
-add helper methods in EOProduct to:
- extract auth headers from auth objects
- request protected assets with forwarded authentication headers
- list files from Zarr v2 metadata using .zmetadata

  • extend CodeAuthorizedAuth usage to support Basic authorization headers for protected asset access
  • protect OIDC authentication token retrieval with a lock to avoid concurrent token refresh issues

Notes
this PR currently targets Zarr v2 only through .zmetadata
Zarr v3 support can be added later if needed

@cauriol cauriol self-assigned this Mar 25, 2026
@cauriol cauriol changed the title Refactor: CodeAuthorizedAuth headers handling for header/basic auth refactor: CodeAuthorizedAuth headers handling for header/basic auth Mar 25, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 25, 2026

Test Results

    4 files  ± 0      4 suites  ±0   3m 28s ⏱️ -5s
  737 tests +13    737 ✅ +13  0 💤 ±0  0 ❌ ±0 
2 990 runs  +52  2 988 ✅ +52  2 💤 ±0  0 ❌ ±0 

Results for commit ca62273. ± Comparison against base commit e3216b6.

♻️ This comment has been updated with latest results.

@eodag-bot
Copy link
Copy Markdown
Collaborator

eodag-bot commented Mar 25, 2026

badge

Code Coverage (Ubuntu)

Details
Filename                                     Stmts    Miss  Cover    Missing
-----------------------------------------  -------  ------  -------  --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
__init__.py                                      8       0  100.00%
cli.py                                         251      11  95.62%   104-115, 377, 644
config.py                                      305      24  92.13%   70-72, 75, 78, 81, 85, 89, 93-95, 583-585, 707-709, 728, 736, 766-771, 773
crunch.py                                        2       0  100.00%
api/__init__.py                                  0       0  100.00%
api/collection.py                              151       8  94.70%   177, 213, 216, 323, 362, 365, 383, 386
api/core.py                                    787      57  92.76%   266, 552, 600, 643, 683, 703, 744-749, 774, 858-877, 891, 897, 1050, 1055, 1154, 1193-1194, 1290-1291, 1317, 1348-1349, 1375, 1388, 1449-1450, 1481-1482, 1556-1561, 1573-1576, 1688, 1921, 2075, 2197, 2285-2286
api/provider.py                                382      40  89.53%   186, 190-191, 316-337, 405, 521, 525-526, 531-534, 545, 621-631, 821-822, 870, 877, 891, 914-917, 951-958, 962-963
api/search_result.py                           181      19  89.50%   111, 123, 133, 154, 203, 220, 320, 375-378, 448, 453-454, 488, 502, 525-526, 532
api/product/__init__.py                         18       2  88.89%   57, 59
api/product/_assets.py                          54       4  92.59%   97, 191, 202-206
api/product/_product.py                        299      20  93.31%   199, 315-316, 334-335, 444, 473, 480, 519, 713, 756-759, 768-771, 825, 891, 903
api/product/metadata_mapping.py                804      58  92.79%   125-127, 221-226, 250, 308-309, 397, 418, 470-471, 508, 529-532, 555, 567-568, 609, 632, 657-660, 662-667, 732-737, 746, 752, 768, 776, 1008, 1161, 1183, 1192-1196, 1213-1218, 1351, 1374, 1383, 1405, 1410, 1462, 1534, 1555, 1581, 1595, 1620, 1666, 1735, 1810
api/product/drivers/__init__.py                 11       0  100.00%
api/product/drivers/base.py                     29       0  100.00%
api/product/drivers/generic.py                  11       0  100.00%
api/product/drivers/sentinel1.py                33       0  100.00%
api/product/drivers/sentinel2.py                33       0  100.00%
plugins/__init__.py                              0       0  100.00%
plugins/base.py                                 25       2  92.00%   48, 55
plugins/manager.py                             173      16  90.75%   102-107, 179, 201, 219-220, 232, 271-272, 372-375, 387-388
plugins/apis/__init__.py                         0       0  100.00%
plugins/apis/base.py                             4       0  100.00%
plugins/apis/ecmwf.py                          101       8  92.08%   178-180, 228-229, 255-257
plugins/apis/usgs.py                           182      25  86.26%   157, 263, 297, 339-341, 346, 374-375, 380, 410-417, 428-433, 455-461
plugins/authentication/__init__.py               6       1  83.33%   31
plugins/authentication/aws_auth.py             124      35  71.77%   52-54, 69-70, 142-149, 177-203, 226, 258-262, 279, 303, 319-320
plugins/authentication/base.py                  22       4  81.82%   45, 58, 81, 95
plugins/authentication/eoiam.py                 99       2  97.98%   171, 194
plugins/authentication/generic.py               16       3  81.25%   50, 55, 65
plugins/authentication/header.py                19       0  100.00%
plugins/authentication/keycloak.py              46       4  91.30%   154, 177-182
plugins/authentication/openid_connect.py       243      21  91.36%   101-102, 110-128, 175, 183, 197, 217, 363-366, 392, 433, 623-626
plugins/authentication/qsauth.py                34       1  97.06%   91
plugins/authentication/sas_auth.py              57       3  94.74%   68, 89, 135
plugins/authentication/token.py                128       9  92.97%   180, 217, 288-289, 339-343
plugins/authentication/token_exchange.py        36      14  61.11%   75, 93-121
plugins/crunch/__init__.py                       6       0  100.00%
plugins/crunch/base.py                          12       0  100.00%
plugins/crunch/filter_date.py                   59       0  100.00%
plugins/crunch/filter_latest_intersect.py       54       6  88.89%   92-93, 100-101, 103-107
plugins/crunch/filter_latest_tpl_name.py        35       0  100.00%
plugins/crunch/filter_overlap.py                66      10  84.85%   118-121, 137-163
plugins/crunch/filter_property.py               30       0  100.00%
plugins/download/__init__.py                     4       0  100.00%
plugins/download/aws.py                        402      76  81.09%   271, 305, 354-357, 387-388, 396-400, 480-483, 523-525, 529, 560-561, 567-571, 602, 667-675, 739-834, 846-851, 889, 915, 960-962, 1014
plugins/download/base.py                       288      24  91.67%   135, 165, 371-372, 416, 450, 527-531, 561, 596-597, 622-631, 690, 711, 733, 741
plugins/download/http.py                       574      75  86.93%   233, 275-278, 340-343, 346, 353-358, 389-391, 408, 423, 483, 518, 532, 546, 556-560, 576-581, 592, 611, 648-651, 672, 682, 689, 745, 854, 886, 916-925, 961, 1006-1011, 1020, 1035-1037, 1041, 1044, 1059-1060, 1070, 1145, 1197, 1239-1240, 1252, 1262, 1318-1319, 1349, 1369, 1397, 1477-1478
plugins/search/__init__.py                      25       0  100.00%
plugins/search/base.py                         196      18  90.82%   109, 113, 137-143, 200-203, 296, 317, 442, 492, 525-528, 537
plugins/search/build_search_result.py          505      83  83.56%   259-260, 296, 300, 320, 550-561, 576-578, 701, 725, 727, 794, 802-806, 827, 837, 863, 908, 933, 961, 979-994, 1044, 1069, 1072, 1076, 1085, 1091, 1129-1150, 1191, 1218-1219, 1228-1237, 1301, 1316, 1322, 1341-1350, 1471-1472, 1516, 1525-1527, 1584, 1632-1642
plugins/search/cop_marine.py                   273      59  78.39%   57, 65-67, 77-78, 83, 88-89, 105, 107, 110, 176-177, 220, 238, 244, 248, 252, 263, 274-275, 283, 315-318, 324, 334, 347, 351, 355, 359, 363-367, 373-376, 379-396, 413-416, 469-473, 478, 490, 504-505
plugins/search/creodias_s3.py                   29       1  96.55%   59
plugins/search/csw.py                          112      87  22.32%   99-100, 104-105, 113-170, 176-189, 197-229, 247-288
plugins/search/qssearch.py                     823      94  88.58%   415-416, 533-534, 557-558, 570-574, 789-795, 853, 919, 949, 956, 1027, 1048, 1051-1052, 1070, 1079-1080, 1107, 1179, 1188, 1193-1210, 1219, 1234, 1243, 1256, 1278, 1367, 1390, 1463-1464, 1470, 1560, 1667-1671, 1737, 1740, 1744-1745, 1766-1769, 1781, 1803-1815, 1823, 1858-1860, 1883-1889, 1896, 1950, 1973, 1978-1979, 1994, 2000, 2010, 2100, 2104, 2115, 2139, 2152, 2160-2170, 2208-2212
plugins/search/stac_list_assets.py              25      10  60.00%   44-51, 75-85
plugins/search/static_stac_search.py            84      18  78.57%   99-127, 166-169, 182, 224
resources/__init__.py                            0       0  100.00%
resources/shp/__init__.py                        0       0  100.00%
types/__init__.py                              167      43  74.25%   58, 62, 71-75, 86-98, 126-128, 135-140, 216, 219, 257, 267-283, 288, 290, 312, 317, 325, 335
types/bbox.py                                   39      19  51.28%   46-61, 72-74, 85-87, 99-101, 113-115, 123
types/download_args.py                          10       0  100.00%
types/queryables.py                            112       0  100.00%
types/search_args.py                            70      18  74.29%   60-64, 71-88, 103
types/stac_extensions.py                       114       1  99.12%   282
types/stac_metadata.py                         118      16  86.44%   95, 116-117, 150, 180-194, 203-210
utils/__init__.py                              572      39  93.18%   60, 197, 228-229, 238-264, 267, 282, 362-366, 441-445, 525, 565-566, 595, 973-976, 1027, 1046-1047, 1076, 1094-1095, 1207, 1295, 1459, 1697
utils/cache.py                                  22       0  100.00%
utils/dates.py                                 113       4  96.46%   171, 329-331
utils/env.py                                     3       0  100.00%
utils/exceptions.py                             48       0  100.00%
utils/free_text_search.py                       65       2  96.92%   83, 91
utils/import_system.py                          28      19  32.14%   64-78, 89-99
utils/logging.py                                31       1  96.77%   41
utils/notebook.py                               44      23  47.73%   25-29, 36-41, 58-62, 72-78, 83-87
utils/repr.py                                   38       0  100.00%
utils/requests.py                               55      29  47.27%   51-52, 64, 85-96, 107-124, 128
utils/s3.py                                    240      12  95.00%   200-203, 245, 263, 489, 537-538, 585, 660, 686
utils/stac_reader.py                           113      44  61.06%   63-85, 95-97, 101, 138, 154-159, 206-216, 226-256
utils/streamresponse.py                         82       7  91.46%   24-26, 63, 124, 133, 145
TOTAL                                        10360    1229  88.14%

Diff against develop

Filename                                    Stmts    Miss  Cover
----------------------------------------  -------  ------  --------
api/product/_product.py                       +46       0  +1.22%
plugins/authentication/openid_connect.py       +8      +2  -0.55%
utils/exceptions.py                            +1       0  +100.00%
TOTAL                                         +55      +2  +0.05%

Results for commit: ca62273

Minimum allowed coverage is 70%

♻️ This comment has been updated with latest results

@eodag-bot
Copy link
Copy Markdown
Collaborator

eodag-bot commented Mar 25, 2026

badge

Code Coverage (Windows)

Details
Filename                                     Stmts    Miss  Cover    Missing
-----------------------------------------  -------  ------  -------  --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
__init__.py                                      8       0  100.00%
cli.py                                         251      11  95.62%   104-115, 377, 644
config.py                                      305      24  92.13%   70-72, 75, 78, 81, 85, 89, 93-95, 583-585, 707-709, 728, 736, 766-771, 773
crunch.py                                        2       0  100.00%
api/__init__.py                                  0       0  100.00%
api/collection.py                              151       8  94.70%   177, 213, 216, 323, 362, 365, 383, 386
api/core.py                                    787      57  92.76%   266, 552, 600, 643, 683, 703, 744-749, 774, 858-877, 891, 897, 1050, 1055, 1154, 1193-1194, 1290-1291, 1317, 1348-1349, 1375, 1388, 1449-1450, 1481-1482, 1556-1561, 1573-1576, 1688, 1921, 2075, 2197, 2285-2286
api/provider.py                                382      40  89.53%   186, 190-191, 316-337, 405, 521, 525-526, 531-534, 545, 621-631, 821-822, 870, 877, 891, 914-917, 951-958, 962-963
api/search_result.py                           181      19  89.50%   111, 123, 133, 154, 203, 220, 320, 375-378, 448, 453-454, 488, 502, 525-526, 532
api/product/__init__.py                         18       2  88.89%   57, 59
api/product/_assets.py                          54       4  92.59%   97, 191, 202-206
api/product/_product.py                        299      20  93.31%   199, 315-316, 334-335, 444, 473, 480, 519, 713, 756-759, 768-771, 825, 891, 903
api/product/metadata_mapping.py                804      58  92.79%   125-127, 221-226, 250, 308-309, 397, 418, 470-471, 508, 529-532, 555, 567-568, 609, 632, 657-660, 662-667, 732-737, 746, 752, 768, 776, 1008, 1161, 1183, 1192-1196, 1213-1218, 1351, 1374, 1383, 1405, 1410, 1462, 1534, 1555, 1581, 1595, 1620, 1666, 1735, 1810
api/product/drivers/__init__.py                 11       0  100.00%
api/product/drivers/base.py                     29       0  100.00%
api/product/drivers/generic.py                  11       0  100.00%
api/product/drivers/sentinel1.py                33       0  100.00%
api/product/drivers/sentinel2.py                33       0  100.00%
plugins/__init__.py                              0       0  100.00%
plugins/base.py                                 25       2  92.00%   48, 55
plugins/manager.py                             173      16  90.75%   102-107, 179, 201, 219-220, 232, 271-272, 372-375, 387-388
plugins/apis/__init__.py                         0       0  100.00%
plugins/apis/base.py                             4       0  100.00%
plugins/apis/ecmwf.py                          101       8  92.08%   178-180, 228-229, 255-257
plugins/apis/usgs.py                           182      25  86.26%   157, 263, 297, 339-341, 346, 374-375, 380, 410-417, 428-433, 455-461
plugins/authentication/__init__.py               6       1  83.33%   31
plugins/authentication/aws_auth.py             124      35  71.77%   52-54, 69-70, 142-149, 177-203, 226, 258-262, 279, 303, 319-320
plugins/authentication/base.py                  22       4  81.82%   45, 58, 81, 95
plugins/authentication/eoiam.py                 99       2  97.98%   171, 194
plugins/authentication/generic.py               16       3  81.25%   50, 55, 65
plugins/authentication/header.py                19       0  100.00%
plugins/authentication/keycloak.py              46       4  91.30%   154, 177-182
plugins/authentication/openid_connect.py       243      21  91.36%   101-102, 110-128, 175, 183, 197, 217, 363-366, 392, 433, 623-626
plugins/authentication/qsauth.py                34       1  97.06%   91
plugins/authentication/sas_auth.py              57       3  94.74%   68, 89, 135
plugins/authentication/token.py                128       9  92.97%   180, 217, 288-289, 339-343
plugins/authentication/token_exchange.py        36      14  61.11%   75, 93-121
plugins/crunch/__init__.py                       6       0  100.00%
plugins/crunch/base.py                          12       0  100.00%
plugins/crunch/filter_date.py                   59       0  100.00%
plugins/crunch/filter_latest_intersect.py       54       6  88.89%   92-93, 100-101, 103-107
plugins/crunch/filter_latest_tpl_name.py        35       0  100.00%
plugins/crunch/filter_overlap.py                66      10  84.85%   118-121, 137-163
plugins/crunch/filter_property.py               30       0  100.00%
plugins/download/__init__.py                     4       0  100.00%
plugins/download/aws.py                        402      76  81.09%   271, 305, 354-357, 387-388, 396-400, 480-483, 523-525, 529, 560-561, 567-571, 602, 667-675, 739-834, 846-851, 889, 915, 960-962, 1014
plugins/download/base.py                       288      26  90.97%   135, 165, 232-234, 371-372, 416, 450, 527-531, 561, 596-597, 622-631, 690, 711, 733, 741
plugins/download/http.py                       574      75  86.93%   233, 275-278, 340-343, 346, 353-358, 389-391, 408, 423, 483, 518, 532, 546, 556-560, 576-581, 592, 611, 648-651, 672, 682, 689, 745, 854, 886, 916-925, 961, 1006-1011, 1020, 1035-1037, 1041, 1044, 1059-1060, 1070, 1145, 1197, 1239-1240, 1252, 1262, 1318-1319, 1349, 1369, 1397, 1477-1478
plugins/search/__init__.py                      25       0  100.00%
plugins/search/base.py                         196      18  90.82%   109, 113, 137-143, 200-203, 296, 317, 442, 492, 525-528, 537
plugins/search/build_search_result.py          505      83  83.56%   259-260, 296, 300, 320, 550-561, 576-578, 701, 725, 727, 794, 802-806, 827, 837, 863, 908, 933, 961, 979-994, 1044, 1069, 1072, 1076, 1085, 1091, 1129-1150, 1191, 1218-1219, 1228-1237, 1301, 1316, 1322, 1341-1350, 1471-1472, 1516, 1525-1527, 1584, 1632-1642
plugins/search/cop_marine.py                   273      59  78.39%   57, 65-67, 77-78, 83, 88-89, 105, 107, 110, 176-177, 220, 238, 244, 248, 252, 263, 274-275, 283, 315-318, 324, 334, 347, 351, 355, 359, 363-367, 373-376, 379-396, 413-416, 469-473, 478, 490, 504-505
plugins/search/creodias_s3.py                   29       1  96.55%   59
plugins/search/csw.py                          112      87  22.32%   99-100, 104-105, 113-170, 176-189, 197-229, 247-288
plugins/search/qssearch.py                     823      94  88.58%   415-416, 533-534, 557-558, 570-574, 789-795, 853, 919, 949, 956, 1027, 1048, 1051-1052, 1070, 1079-1080, 1107, 1179, 1188, 1193-1210, 1219, 1234, 1243, 1256, 1278, 1367, 1390, 1463-1464, 1470, 1560, 1667-1671, 1737, 1740, 1744-1745, 1766-1769, 1781, 1803-1815, 1823, 1858-1860, 1883-1889, 1896, 1950, 1973, 1978-1979, 1994, 2000, 2010, 2100, 2104, 2115, 2139, 2152, 2160-2170, 2208-2212
plugins/search/stac_list_assets.py              25      10  60.00%   44-51, 75-85
plugins/search/static_stac_search.py            84      18  78.57%   99-127, 166-169, 182, 224
resources/__init__.py                            0       0  100.00%
resources/shp/__init__.py                        0       0  100.00%
types/__init__.py                              167      43  74.25%   58, 62, 71-75, 86-98, 126-128, 135-140, 216, 219, 257, 267-283, 288, 290, 312, 317, 325, 335
types/bbox.py                                   39      19  51.28%   46-61, 72-74, 85-87, 99-101, 113-115, 123
types/download_args.py                          10       0  100.00%
types/queryables.py                            112       0  100.00%
types/search_args.py                            70      18  74.29%   60-64, 71-88, 103
types/stac_extensions.py                       114       1  99.12%   282
types/stac_metadata.py                         118      16  86.44%   95, 116-117, 150, 180-194, 203-210
utils/__init__.py                              572      39  93.18%   60, 197, 228-229, 238-264, 267, 282, 362-366, 441-445, 525, 565-566, 595, 973-976, 1027, 1046-1047, 1076, 1094-1095, 1207, 1295, 1459, 1697
utils/cache.py                                  22       0  100.00%
utils/dates.py                                 113       4  96.46%   171, 329-331
utils/env.py                                     3       0  100.00%
utils/exceptions.py                             48       0  100.00%
utils/free_text_search.py                       65       2  96.92%   83, 91
utils/import_system.py                          28      19  32.14%   64-78, 89-99
utils/logging.py                                31       1  96.77%   41
utils/notebook.py                               44      23  47.73%   25-29, 36-41, 58-62, 72-78, 83-87
utils/repr.py                                   38       0  100.00%
utils/requests.py                               55      29  47.27%   51-52, 64, 85-96, 107-124, 128
utils/s3.py                                    240      12  95.00%   200-203, 245, 263, 489, 537-538, 585, 660, 686
utils/stac_reader.py                           113      44  61.06%   63-85, 95-97, 101, 138, 154-159, 206-216, 226-256
utils/streamresponse.py                         82       7  91.46%   24-26, 63, 124, 133, 145
TOTAL                                        10360    1231  88.12%

Diff against develop

Filename                                    Stmts    Miss  Cover
----------------------------------------  -------  ------  --------
api/product/_product.py                       +46       0  +1.22%
plugins/authentication/openid_connect.py       +8      +2  -0.55%
utils/exceptions.py                            +1       0  +100.00%
TOTAL                                         +55      +2  +0.05%

Results for commit: ca62273

Minimum allowed coverage is 70%

♻️ This comment has been updated with latest results

@cauriol cauriol marked this pull request as ready for review March 26, 2026 09:37
@cauriol cauriol requested a review from jlahovnik March 26, 2026 09:37
@cauriol cauriol marked this pull request as draft April 1, 2026 09:27
@cauriol cauriol removed the request for review from jlahovnik April 1, 2026 09:27
@cauriol cauriol changed the title refactor: CodeAuthorizedAuth headers handling for header/basic auth feat: Add Zarr v2 metadata access and basic auth support for OIDC-protected assets Apr 1, 2026
@alambare
Copy link
Copy Markdown
Collaborator

alambare commented Apr 1, 2026

@cauriol, instead of introducing a new method get_auth_headers in plugin configs, we should leverage the product._get_storage_options from EODAG cube: https://github.com/CS-SI/eodag-cube/blob/develop/eodag_cube/api/product/_product.py#L121.
This method should probably be refactored to not activate order and become a public interface.

@sbrunato can we get your opinion here ?

@sbrunato
Copy link
Copy Markdown
Collaborator

sbrunato commented Apr 2, 2026

@cauriol, instead of introducing a new method get_auth_headers in plugin configs, we should leverage the product._get_storage_options from EODAG cube: https://github.com/CS-SI/eodag-cube/blob/develop/eodag_cube/api/product/_product.py#L121. This method should probably be refactored to not activate order and become a public interface.

@sbrunato can we get your opinion here ?

@alambare I agree. EOProduct._get_storage_options can be moved from eodag-cube to eodag and publicly exposed

@cauriol cauriol marked this pull request as ready for review April 2, 2026 13:36
@cauriol cauriol requested a review from alambare April 2, 2026 13:36
Comment on lines +589 to +595
def request_asset(
self,
url: str,
) -> requests.Response:
"""Perform a GET request to the given URL using product's authentication headers."""
headers = self.get_storage_options().get("headers", {})
return requests.get(url, headers=headers, stream=True)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should use the stream download method from EODAG download plugins instead of creating a new method.

)

if ".zmetadata" in mapper:
meta = json.loads(mapper[".zmetadata"])
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use orjson instead of json.

Comment on lines +614 to +618
# TODO: Support Zarr v3 when test data becomes available.
# Zarr v2 uses `.zmetadata`, while Zarr v3 exposes `zarr.json`.
# The implementation should be straightforward once we can validate it
# against real examples.
raise ValueError(f"No Zarr metadata file found at {base_url}")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With Destination Earth, we do have a zarr v3 store: DanubeHis data. I don't understand what is blocking here.

headers = self.get_storage_options().get("headers", {})
return requests.get(url, headers=headers, stream=True)

def list_zarr_files_from_metadata(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In zarr, we have keys and not files. I suppose you can rename the method to something like list_zarr_keys ?

try:
url = self.assets[asset_key]["href"] if asset_key else self.location
except KeyError as e:
raise DatasetCreationError(f"{asset_key} not found in {self} assets") from e
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are not creating a xarray here. The exception class is not accurate.

"zipstream-ng",
"fsspec",
"aiohttp",
"requests"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

requests is already a dependency in EODAG.

Comment on lines +605 to +608
mapper = fsspec.get_mapper(
base_url,
client_kwargs={"headers": headers, "trust_env": False},
)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about introducing fsspec in EODAG library.
The library is a wrapper above multiple backends. To use it, you need to bring backends to support all the filesystems: s3fs for S3, gcsfs for google cloud storage and adlfs for azure blob storage.
Most of the times, users will store zarr files on a S3 compatible store but some may store them on google or azure stores.
Maybe we don't want to support google / azure stores ? or in an optional dependencies branch ?

My opinion:

  1. we do not support google and azure yet. Maybe once if we replace boto3 by obstore.
  2. we do not bring fsspec in EODAG but instead call boto3 to get the list of zarr keys. If a dedicated function is needed to get the list of keys with boto3, it should live in eodag/utils/s3.py.

@sbrunato what do you think?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants