Sign kerchunk-style reference mappings (#35)

This commit is contained in:
Tom Augspurger 2022-01-10 16:47:22 -06:00 коммит произвёл GitHub
Родитель 3d67a64fba
Коммит 27037bcb9a
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
6 изменённых файлов: 79 добавлений и 5 удалений

Просмотреть файл

@ -1,3 +1,9 @@
# 0.4.5
## New Features
* `sign` will now sign [Kerchunk](kerchunk)-style dictionaries of references.
# 0.4.4
## New Features
@ -49,3 +55,4 @@
[gh-25]: https://github.com/microsoft/planetary-computer-sdk-for-python/issues/25
[gh-30]: https://github.com/microsoft/planetary-computer-sdk-for-python/pull/30
[xarray-assets]: https://github.com/stac-extensions/xarray-assets
[kerchunk]: https://fsspec.github.io/kerchunk/

Просмотреть файл

@ -1,6 +1,8 @@
import re
from datetime import datetime, timezone
from typing import Any, Dict, Optional
from typing import Any, Dict, Optional, Mapping
import collections.abc
import copy
import warnings
from functools import singledispatch
@ -70,12 +72,13 @@ def sign(obj: Any) -> Any:
Args:
obj (Any): The object to sign. Must be one of:
str (URL), Asset, Item, ItemCollection, or ItemSearch
str (URL), Asset, Item, ItemCollection, or ItemSearch, or a mapping.
Returns:
Any: A copy of the object where all relevant URLs have been signed
"""
raise TypeError(
"Invalid type, must be one of: str, Asset, Item, ItemCollection, or ItemSearch"
"Invalid type, must be one of: str, Asset, Item, ItemCollection, "
"ItemSearch, or mapping"
)
@ -277,6 +280,38 @@ def _search_and_sign(search: ItemSearch) -> ItemCollection:
return sign(search.get_all_items())
@sign.register(collections.abc.Mapping)
def sign_reference_file(references: Mapping) -> Mapping:
"""
Sign a Kerchunk-style dictionary of references.
Args:
references (Mapping): The dictionary containing the references.
Returns:
references (Mapping): The dictionary, now with signed URLs.
This method will sign all of the URLs under the ``"templates"`` key. Mappings
with other keys will be returned unchanged. See https://fsspec.github.io/kerchunk/
for more.
"""
# TODO(python3.8): Use TypedDict instead of Mapping to limit the kinds we accept.
# If we accept other mapping types in the future, we'll need to dispatch within
# the function.
if set(references) == {"version", "templates", "refs"}:
references = copy.deepcopy(references)
for k, v in references["templates"].items():
references["templates"][k] = sign_url(v)
else:
raise TypeError(
"When providing a mapping, the keys should be 'version', 'templates', "
"and 'refs'."
)
return references
def get_token(account_name: str, container_name: str) -> SASToken:
"""
Get a token for a container in a storage account.

Просмотреть файл

@ -1,3 +1,3 @@
"""Library version"""
__version__ = "0.4.4"
__version__ = "0.4.5"

Просмотреть файл

@ -1,6 +1,6 @@
[metadata]
name = planetary-computer
version = 0.4.4
version = 0.4.5
license_file = LICENSE
author = microsoft
author_email = planetarycomputer@microsoft.com

Просмотреть файл

@ -0,0 +1,9 @@
{
"version": 1,
"templates": {
"a": "https://nasagddp.blob.core.windows.net/nex-gddp-cmip6/NEX/GDDP-CMIP6/ACCESS-CM2/historical/r1i1p1f1/hurs/hurs_day_ACCESS-CM2_historical_r1i1p1f1_gn_1950.nc",
"b": "https://nasagddp.blob.core.windows.net/nex-gddp-cmip6/NEX/GDDP-CMIP6/ACCESS-CM2/historical/r1i1p1f1/hurs/hurs_day_ACCESS-CM2_historical_r1i1p1f1_gn_1951.nc"
},
"refs": {
}
}

Просмотреть файл

@ -1,4 +1,5 @@
import os
import json
import unittest
from urllib.parse import parse_qs, urlparse
from pathlib import Path
@ -57,6 +58,12 @@ def get_sample_item_collection() -> ItemCollection:
return ItemCollection([get_sample_item()])
def get_sample_references() -> dict:
with open(os.fspath(HERE.joinpath("data-files/sample-reference-file.json"))) as f:
references = json.load(f)
return references
class TestSigning(unittest.TestCase):
def assertRootResolved(self, item: Item) -> None:
root_link = item.get_root_link()
@ -180,6 +187,22 @@ class TestSigning(unittest.TestCase):
result = pc.sign(vrt_string)
self.assertGreater(result.count("?st"), 0)
def test_sign_references_file(self) -> None:
references = get_sample_references()
result = pc.sign(references)
for v in result["templates"].values():
self.assertSigned(v)
def test_sign_other_mapping_raises(self) -> None:
with self.assertRaisesRegex(TypeError, "When providing a mapping"):
pc.sign({"version": None})
with self.assertRaisesRegex(TypeError, "When providing a mapping"):
pc.sign({})
with self.assertRaisesRegex(TypeError, "When providing a mapping"):
pc.sign({"version": None, "templates": None, "refs": None, "extra": None})
class TestUtils(unittest.TestCase):
def test_parse_adlfs_url(self) -> None: