Skip to content

Commit b9981a3

Browse files
author
Tom Augspurger
authored
Added convenience method for getting container client / filesystem (#49)
* Added convenience method for getting filesystem
1 parent cee0aae commit b9981a3

11 files changed

Lines changed: 146 additions & 32 deletions

File tree

.github/workflows/continuous-integration.yml

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,14 @@ jobs:
1212
runs-on: ubuntu-latest
1313
strategy:
1414
matrix:
15-
python-version: ["3.7", "3.8", "3.9"]
15+
python-version: ["3.8", "3.9", "3.10", "3.11"]
1616
steps:
17-
- uses: actions/checkout@v2
17+
- uses: actions/checkout@v3
1818

1919
- name: Set up Python ${{ matrix.python-version }}
20-
uses: actions/setup-python@v2
20+
uses: actions/setup-python@v4
2121
with:
2222
python-version: ${{ matrix.python-version }}
2323

24-
- name: Cache dependencies
25-
uses: actions/cache@v2
26-
with:
27-
path: ~/.cache/pip
28-
key: pip-${{ hashFiles('requirements-dev.txt') }}
29-
restore-keys: pip-
30-
3124
- name: Execute linters and test suites
3225
run: ./scripts/cibuild

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
## New Features
44

55
* `sign` now automatically retries failed HTTP requests.
6+
* Added a convenience method `planetary_computer.get_container_client` for getting an authenticated ``azure.storage.blob.ContainerClient``.
7+
* Added a convenience method `planetary_computer.get_adlfs_filesystem` for getting an authenticated ``adlfs.AzureBlobFileSystem``.
68

79
# 0.4.7
810

README.md

Lines changed: 46 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,32 +19,31 @@ planetarycomputer configure
1919
Alternatively, a subscription key may be provided by specifying it in the `PC_SDK_SUBSCRIPTION_KEY` environment variable. A subcription key is not required for interacting with the service, however having one in place allows for less restricted rate limiting.
2020

2121

22-
## Development
23-
24-
The following steps may be followed in order to develop locally:
25-
26-
```bash
27-
## Create and activate venv
28-
python3 -m venv env
29-
source env/bin/activate
22+
## Usage
3023

31-
## Install requirements
32-
python3 -m pip install -r requirements-dev.txt
24+
This library assists with signing Azure Blob Storage URLs. The `sign` function operates directly on an HREF string, as well as several [PySTAC](https://github.com/stac-utils/pystac) objects: `Asset`, `Item`, and `ItemCollection`. In addition, the `sign` function accepts a [STAC API Client](https://pystac-client.readthedocs.io/en/stable/) `ItemSearch`, which performs a search and returns the resulting `ItemCollection` with all assets signed.
3325

34-
## Install locally
35-
pip install -e .
26+
### Automatic signing
3627

37-
## Format code
38-
./scripts/format
28+
If you're using pystac-client we recommend you use its feature to [automatically sign results](https://pystac-client.readthedocs.io/en/stable/usage.html#automatically-modifying-results) with ``planetary_computer.sign_inplace``:
3929

40-
## Run tests
41-
./scripts/test
30+
```python
31+
import planetary_computer
32+
import pystac_client
33+
34+
from pystac_client import Client
35+
import planetary_computer, requests
36+
api = Client.open(
37+
'https://planetarycomputer.microsoft.com/api/stac/v1',
38+
modifier=planetary_computer.sign_inplace,
39+
)
4240
```
4341

42+
Now all the results you get from that client will be signed.
4443

45-
## Usage
44+
### Manual signing
4645

47-
This library currently assists with signing Azure Blob Storage URLs. The `sign` function operates directly on an HREF string, as well as several [PySTAC](https://github.com/stac-utils/pystac) objects: `Asset`, `Item`, and `ItemCollection`. In addition, the `sign` function accepts a [STAC API Client](https://github.com/stac-utils/pystac-client) `ItemSearch`, which performs a search and returns the resulting `ItemCollection` with all assets signed. The following example demonstrates these use cases:
46+
Alternatively, you can manually call ``planetary_computer.sign`` on your results.
4847

4948
```python
5049
from pystac import Asset, Item, ItemCollection
@@ -80,6 +79,35 @@ search = ItemSearch(
8079
signed_item_collection = pc.sign(search)
8180
```
8281

82+
### Convenience methods
83+
84+
You'll occasionally need to interact with the Blob Storage container directly, rather than
85+
using STAC items. We include two convenience methods for this:
86+
87+
* `planetary_computer.get_container_client`: Get an [`azure.storage.blob.ContainerClient`](https://learn.microsoft.com/en-us/python/api/azure-storage-blob/azure.storage.blob.containerclient?view=azure-python)
88+
* `planetary_computer.get_adlfs_fliesystem`: Get an [`adlfs.AzureBlobFilesystem`](https://github.com/fsspec/adlfs)
89+
90+
## Development
91+
92+
The following steps may be followed in order to develop locally:
93+
94+
```bash
95+
## Create and activate venv
96+
python3 -m venv env
97+
source env/bin/activate
98+
99+
## Install requirements
100+
python3 -m pip install -r requirements-dev.txt
101+
102+
## Install locally
103+
pip install -e .
104+
105+
## Format code
106+
./scripts/format
107+
108+
## Run tests
109+
./scripts/test
110+
```
83111

84112
## Contributing
85113

planetary_computer/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,17 @@
1111
sign_item_collection,
1212
)
1313
from planetary_computer.settings import set_subscription_key
14+
from planetary_computer._adlfs import get_adlfs_filesystem, get_container_client
1415

1516
from planetary_computer.version import __version__
1617

1718
__all__ = [
19+
"get_adlfs_filesystem",
20+
"get_container_client",
1821
"set_subscription_key",
1922
"sign_asset",
2023
"sign_assets",
24+
"sign_inplace",
2125
"sign_item_collection",
2226
"sign_item",
2327
"sign_url",

planetary_computer/_adlfs.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import typing
2+
3+
import azure.storage.blob
4+
from planetary_computer.sas import get_token
5+
6+
if typing.TYPE_CHECKING:
7+
import adlfs
8+
9+
10+
def get_container_client(
11+
account_name: str, container_name: str
12+
) -> azure.storage.blob.ContainerClient:
13+
"""
14+
Get a :class:`azure.storage.blob.ContainerClient` with credentials.
15+
16+
Args:
17+
account_name (str): The storage account name.
18+
container_name (str): The storage container name.
19+
Returns:
20+
The :class:`azure.storage.blob.ContainerClient` with the short-lived SAS token
21+
set as the credential.
22+
"""
23+
token = get_token(account_name, container_name).token
24+
return azure.storage.blob.ContainerClient(
25+
f"https://{account_name}.blob.core.windows.net",
26+
container_name,
27+
credential=token,
28+
)
29+
30+
31+
def get_adlfs_filesystem(
32+
account_name: str, container_name: str
33+
) -> "adlfs.AzureBlobFileSystem":
34+
"""
35+
Get an :class:`adlfs.AzureBlobFileSystem` with credentials.
36+
37+
Args:
38+
account_name (str): The storage account name.
39+
container_name (str): The storage container name.
40+
Returns:
41+
The :class:`adlfs.AzureBlobFileSystem` with the short-lived SAS token
42+
set as the credential.
43+
"""
44+
try:
45+
import adlfs
46+
except ImportError as e:
47+
raise ImportError(
48+
"'planetary_computer.get_adlfs_filesystem' requires "
49+
"the optional dependency 'adlfs'."
50+
) from e
51+
token = get_token(account_name, container_name).token
52+
fs = adlfs.AzureBlobFileSystem(account_name, credential=token)
53+
return fs

planetary_computer/sas.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from pystac.utils import datetime_to_str
1515
from pystac.serialization.identify import identify_stac_object_type
1616
from pystac_client import ItemSearch
17+
import pystac_client
1718
import urllib3.util.retry
1819

1920
from planetary_computer.settings import Settings
@@ -336,7 +337,11 @@ def _search_and_sign(search: ItemSearch, copy: bool = True) -> ItemCollection:
336337
a "msft:expiry" property is added to the Item properties indicating the
337338
earliest expiry time for any assets that were signed.
338339
"""
339-
return sign(search.get_all_items())
340+
if pystac_client.__version__ >= "0.5.0":
341+
items = search.item_collection()
342+
else:
343+
items = search.get_all_items()
344+
return sign(items)
340345

341346

342347
@sign.register(Collection)

requirements-dev.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ flake8==4.0.1
33
ipdb==0.13.9
44
mypy==0.961
55
types-requests==2.28.1
6-
setuptools==63.1.0
6+
setuptools==63.1.0
7+
pytest

scripts/cibuild

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ if [ "${BASH_SOURCE[0]}" = "${0}" ]; then
2020
# Install/upgrade dependencies
2121
python -m pip install --upgrade pip
2222
pip install -r requirements-dev.txt
23-
pip install -e .
23+
pip install -e .[adlfs]
2424

2525
./scripts/test
2626
fi

scripts/test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,6 @@ if [ "${BASH_SOURCE[0]}" = "${0}" ]; then
2828
flake8 planetary_computer tests
2929

3030
echo "Running unit tests..."
31-
python -m unittest discover tests
31+
pytest -vs tests
3232
fi
3333
fi

setup.cfg

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ install_requires =
1919
pytz>=2020.5
2020
requests>=2.25.1
2121

22+
[options.extras_require]
23+
adlfs = adlfs
24+
2225
[options.entry_points]
2326
console_scripts =
2427
planetarycomputer = planetary_computer.scripts.cli:app

0 commit comments

Comments
 (0)