cloudnet-api-client 0.12.7__tar.gz → 0.12.9__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {cloudnet_api_client-0.12.7 → cloudnet_api_client-0.12.9}/.github/dataportal.env +2 -2
- {cloudnet_api_client-0.12.7 → cloudnet_api_client-0.12.9}/.github/docker-compose.yml +1 -1
- {cloudnet_api_client-0.12.7 → cloudnet_api_client-0.12.9}/.github/workflows/publish.yml +3 -3
- {cloudnet_api_client-0.12.7 → cloudnet_api_client-0.12.9}/.github/workflows/test.yml +10 -6
- {cloudnet_api_client-0.12.7 → cloudnet_api_client-0.12.9}/CHANGELOG.md +9 -0
- {cloudnet_api_client-0.12.7 → cloudnet_api_client-0.12.9}/PKG-INFO +9 -9
- {cloudnet_api_client-0.12.7 → cloudnet_api_client-0.12.9}/README.md +8 -8
- {cloudnet_api_client-0.12.7 → cloudnet_api_client-0.12.9}/cloudnet_api_client/client.py +2 -2
- {cloudnet_api_client-0.12.7 → cloudnet_api_client-0.12.9}/cloudnet_api_client/containers.py +1 -0
- {cloudnet_api_client-0.12.7 → cloudnet_api_client-0.12.9}/cloudnet_api_client/dl.py +16 -7
- cloudnet_api_client-0.12.9/cloudnet_api_client/version.py +1 -0
- {cloudnet_api_client-0.12.7 → cloudnet_api_client-0.12.9}/tests/test_client.py +14 -0
- cloudnet_api_client-0.12.7/cloudnet_api_client/version.py +0 -1
- {cloudnet_api_client-0.12.7 → cloudnet_api_client-0.12.9}/.github/db.env +0 -0
- {cloudnet_api_client-0.12.7 → cloudnet_api_client-0.12.9}/.github/initdb.d/init-dbs.sh +0 -0
- {cloudnet_api_client-0.12.7 → cloudnet_api_client-0.12.9}/.github/ss.env +0 -0
- {cloudnet_api_client-0.12.7 → cloudnet_api_client-0.12.9}/.gitignore +0 -0
- {cloudnet_api_client-0.12.7 → cloudnet_api_client-0.12.9}/.pre-commit-config.yaml +0 -0
- {cloudnet_api_client-0.12.7 → cloudnet_api_client-0.12.9}/LICENSE +0 -0
- {cloudnet_api_client-0.12.7 → cloudnet_api_client-0.12.9}/cloudnet_api_client/__init__.py +0 -0
- {cloudnet_api_client-0.12.7 → cloudnet_api_client-0.12.9}/cloudnet_api_client/py.typed +0 -0
- {cloudnet_api_client-0.12.7 → cloudnet_api_client-0.12.9}/cloudnet_api_client/utils.py +0 -0
- {cloudnet_api_client-0.12.7 → cloudnet_api_client-0.12.9}/pyproject.toml +0 -0
- {cloudnet_api_client-0.12.7 → cloudnet_api_client-0.12.9}/tests/data/20140205_hyytiala_classification.nc +0 -0
- {cloudnet_api_client-0.12.7 → cloudnet_api_client-0.12.9}/tests/data/20250801_Magurele_CHM170137_000.nc +0 -0
- {cloudnet_api_client-0.12.7 → cloudnet_api_client-0.12.9}/tests/data/20250803_JOYCE_WST_01m.dat +0 -0
- {cloudnet_api_client-0.12.7 → cloudnet_api_client-0.12.9}/tests/data/20250808_Granada_CHM170119_0045_000.nc +0 -0
- {cloudnet_api_client-0.12.7 → cloudnet_api_client-0.12.9}/tests/data/20250808_hyytiala_iwc-Z-T-method.nc +0 -0
- {cloudnet_api_client-0.12.7 → cloudnet_api_client-0.12.9}/tests/data/20250814_bucharest_classification.nc +0 -0
- {cloudnet_api_client-0.12.7 → cloudnet_api_client-0.12.9}/tests/data/20250821_limassol_parsivel_41582c49.nc +0 -0
- {cloudnet_api_client-0.12.7 → cloudnet_api_client-0.12.9}/tests/data/20250822_leipzig-lim_ecmwf-open.nc +0 -0
|
@@ -8,8 +8,8 @@ TYPEORM_PORT=5432
|
|
|
8
8
|
TYPEORM_SYNCHRONIZE=false
|
|
9
9
|
TYPEORM_MIGRATIONS_RUN=true
|
|
10
10
|
TYPEORM_LOGGING=false
|
|
11
|
-
TYPEORM_ENTITIES=build/entity/*.js
|
|
12
|
-
TYPEORM_MIGRATIONS=build/migration/*.js
|
|
11
|
+
TYPEORM_ENTITIES=build/app/src/entity/*.js
|
|
12
|
+
TYPEORM_MIGRATIONS=build/app/src/migration/*.js
|
|
13
13
|
DP_SS_URL=http://storage-service:5900
|
|
14
14
|
DP_SS_USER=test
|
|
15
15
|
DP_SS_PASSWORD=test
|
|
@@ -15,7 +15,7 @@ services:
|
|
|
15
15
|
[
|
|
16
16
|
"sh",
|
|
17
17
|
"-c",
|
|
18
|
-
"node build/fixtures.js /backend-fixtures/backend/fixtures TRUNCATE && node build/fixtures.js /dataportal-fixtures APPEND && npm run start",
|
|
18
|
+
"node build/app/src/fixtures.js /backend-fixtures/backend/fixtures TRUNCATE && node build/app/src/fixtures.js /dataportal-fixtures APPEND && npm run start",
|
|
19
19
|
]
|
|
20
20
|
db:
|
|
21
21
|
image: "postgres:16"
|
|
@@ -12,9 +12,9 @@ jobs:
|
|
|
12
12
|
contents: write
|
|
13
13
|
id-token: write
|
|
14
14
|
steps:
|
|
15
|
-
- uses: actions/checkout@
|
|
15
|
+
- uses: actions/checkout@v6
|
|
16
16
|
- name: Set up Python
|
|
17
|
-
uses: actions/setup-python@
|
|
17
|
+
uses: actions/setup-python@v6
|
|
18
18
|
with:
|
|
19
19
|
python-version: "3.10"
|
|
20
20
|
- name: Install dependencies
|
|
@@ -30,7 +30,7 @@ jobs:
|
|
|
30
30
|
echo "name=cloudnet-api-client $version" >> $GITHUB_OUTPUT
|
|
31
31
|
id: changelog
|
|
32
32
|
- name: Create release
|
|
33
|
-
uses: softprops/action-gh-release@
|
|
33
|
+
uses: softprops/action-gh-release@v2
|
|
34
34
|
with:
|
|
35
35
|
name: ${{ steps.changelog.outputs.name }}
|
|
36
36
|
body_path: ${{ github.workspace }}-CHANGELOG.txt
|
|
@@ -11,15 +11,15 @@ jobs:
|
|
|
11
11
|
runs-on: ubuntu-latest
|
|
12
12
|
steps:
|
|
13
13
|
- name: Set up Python
|
|
14
|
-
uses: actions/setup-python@
|
|
14
|
+
uses: actions/setup-python@v6
|
|
15
15
|
with:
|
|
16
16
|
python-version: ${{ matrix.python-version }}
|
|
17
17
|
|
|
18
18
|
- name: Checkout code
|
|
19
|
-
uses: actions/checkout@
|
|
19
|
+
uses: actions/checkout@v6
|
|
20
20
|
|
|
21
21
|
- name: Cache Python dependencies
|
|
22
|
-
uses: actions/cache@
|
|
22
|
+
uses: actions/cache@v5
|
|
23
23
|
with:
|
|
24
24
|
path: ~/.cache/pip
|
|
25
25
|
key: ${{ runner.os }}-pip-${{ matrix.python-version }}-${{ hashFiles('**/pyproject.toml') }}
|
|
@@ -28,7 +28,7 @@ jobs:
|
|
|
28
28
|
${{ runner.os }}-pip-
|
|
29
29
|
|
|
30
30
|
- name: Checkout fixtures
|
|
31
|
-
uses: actions/checkout@
|
|
31
|
+
uses: actions/checkout@v6
|
|
32
32
|
with:
|
|
33
33
|
repository: actris-cloudnet/dataportal
|
|
34
34
|
sparse-checkout: backend/fixtures/
|
|
@@ -36,13 +36,13 @@ jobs:
|
|
|
36
36
|
path: backend-fixtures
|
|
37
37
|
|
|
38
38
|
- name: Checkout production fixtures
|
|
39
|
-
uses: actions/checkout@
|
|
39
|
+
uses: actions/checkout@v6
|
|
40
40
|
with:
|
|
41
41
|
repository: actris-cloudnet/dataportal-fixtures
|
|
42
42
|
path: dataportal-fixtures
|
|
43
43
|
|
|
44
44
|
- name: Set up Docker Buildx
|
|
45
|
-
uses: docker/setup-buildx-action@
|
|
45
|
+
uses: docker/setup-buildx-action@v4
|
|
46
46
|
|
|
47
47
|
- name: Start dataportal
|
|
48
48
|
run: docker compose -f .github/docker-compose.yml up -d --wait
|
|
@@ -62,3 +62,7 @@ jobs:
|
|
|
62
62
|
- name: Shutdown backend
|
|
63
63
|
if: always()
|
|
64
64
|
run: docker compose -f .github/docker-compose.yml down
|
|
65
|
+
|
|
66
|
+
- name: Print logs
|
|
67
|
+
if: always()
|
|
68
|
+
run: docker compose -f .github/docker-compose.yml logs
|
|
@@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## 0.12.9 – 2026-04-14
|
|
9
|
+
|
|
10
|
+
- Add s3key to file metadata
|
|
11
|
+
|
|
12
|
+
## 0.12.8 – 2026-03-24
|
|
13
|
+
|
|
14
|
+
- Support downloading of single metadata objects
|
|
15
|
+
- Hide total progress bar when downloading a single file
|
|
16
|
+
|
|
8
17
|
## 0.12.7 – 2025-12-18
|
|
9
18
|
|
|
10
19
|
- Adjust progress bars
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cloudnet-api-client
|
|
3
|
-
Version: 0.12.
|
|
3
|
+
Version: 0.12.9
|
|
4
4
|
Summary: Cloudnet API client
|
|
5
5
|
Author-email: Simo Tukiainen <simo.tukiainen@fmi.fi>
|
|
6
6
|
License-File: LICENSE
|
|
@@ -51,7 +51,7 @@ sites = client.sites()
|
|
|
51
51
|
site = client.site("hyytiala")
|
|
52
52
|
|
|
53
53
|
products = client.products()
|
|
54
|
-
product = client.
|
|
54
|
+
product = client.product("classification")
|
|
55
55
|
|
|
56
56
|
models = client.models()
|
|
57
57
|
model = client.model("ecmwf-open")
|
|
@@ -239,13 +239,13 @@ Download files from the fetched metadata.
|
|
|
239
239
|
|
|
240
240
|
Parameters:
|
|
241
241
|
|
|
242
|
-
| name | type
|
|
243
|
-
| ----------------- |
|
|
244
|
-
| metadata | `
|
|
245
|
-
| output_directory | `PathLike` or `str`
|
|
246
|
-
| concurrency_limit | `int`
|
|
247
|
-
| progress | `bool` or `None`
|
|
248
|
-
| validate_checksum | `bool`
|
|
242
|
+
| name | type | default |
|
|
243
|
+
| ----------------- | ----------------------------------------------- | ----------------- |
|
|
244
|
+
| metadata | `RawMetadata`, `ProductMetadata` or `list[...]` | |
|
|
245
|
+
| output_directory | `PathLike` or `str` | Current directory |
|
|
246
|
+
| concurrency_limit | `int` | 5 |
|
|
247
|
+
| progress | `bool` or `None` | `None` |
|
|
248
|
+
| validate_checksum | `bool` | `False` |
|
|
249
249
|
|
|
250
250
|
There's also an asynchronous version of this function:
|
|
251
251
|
`cloudnet_api_client.adownload`. It's useful for usage inside Jupyter notebook.
|
|
@@ -22,7 +22,7 @@ sites = client.sites()
|
|
|
22
22
|
site = client.site("hyytiala")
|
|
23
23
|
|
|
24
24
|
products = client.products()
|
|
25
|
-
product = client.
|
|
25
|
+
product = client.product("classification")
|
|
26
26
|
|
|
27
27
|
models = client.models()
|
|
28
28
|
model = client.model("ecmwf-open")
|
|
@@ -210,13 +210,13 @@ Download files from the fetched metadata.
|
|
|
210
210
|
|
|
211
211
|
Parameters:
|
|
212
212
|
|
|
213
|
-
| name | type
|
|
214
|
-
| ----------------- |
|
|
215
|
-
| metadata | `
|
|
216
|
-
| output_directory | `PathLike` or `str`
|
|
217
|
-
| concurrency_limit | `int`
|
|
218
|
-
| progress | `bool` or `None`
|
|
219
|
-
| validate_checksum | `bool`
|
|
213
|
+
| name | type | default |
|
|
214
|
+
| ----------------- | ----------------------------------------------- | ----------------- |
|
|
215
|
+
| metadata | `RawMetadata`, `ProductMetadata` or `list[...]` | |
|
|
216
|
+
| output_directory | `PathLike` or `str` | Current directory |
|
|
217
|
+
| concurrency_limit | `int` | 5 |
|
|
218
|
+
| progress | `bool` or `None` | `None` |
|
|
219
|
+
| validate_checksum | `bool` | `False` |
|
|
220
220
|
|
|
221
221
|
There's also an asynchronous version of this function:
|
|
222
222
|
`cloudnet_api_client.adownload`. It's useful for usage inside Jupyter notebook.
|
|
@@ -322,7 +322,7 @@ class APIClient:
|
|
|
322
322
|
|
|
323
323
|
def download(
|
|
324
324
|
self,
|
|
325
|
-
metadata: MetadataList,
|
|
325
|
+
metadata: MetadataList | TMetadata,
|
|
326
326
|
output_directory: str | PathLike = ".",
|
|
327
327
|
concurrency_limit: int = 5,
|
|
328
328
|
progress: bool | None = None,
|
|
@@ -340,7 +340,7 @@ class APIClient:
|
|
|
340
340
|
|
|
341
341
|
async def adownload(
|
|
342
342
|
self,
|
|
343
|
-
metadata: MetadataList,
|
|
343
|
+
metadata: MetadataList | TMetadata,
|
|
344
344
|
output_directory: str | PathLike = ".",
|
|
345
345
|
concurrency_limit: int = 5,
|
|
346
346
|
progress: bool | None = None,
|
|
@@ -8,14 +8,22 @@ import aiohttp
|
|
|
8
8
|
from tqdm import tqdm
|
|
9
9
|
|
|
10
10
|
from cloudnet_api_client import utils
|
|
11
|
-
from cloudnet_api_client.containers import
|
|
11
|
+
from cloudnet_api_client.containers import (
|
|
12
|
+
Metadata,
|
|
13
|
+
ProductMetadata,
|
|
14
|
+
)
|
|
12
15
|
|
|
13
16
|
|
|
14
17
|
class BarConfig:
|
|
15
18
|
def __init__(
|
|
16
|
-
self,
|
|
19
|
+
self,
|
|
20
|
+
disable: bool | None,
|
|
21
|
+
max_workers: int,
|
|
22
|
+
total_bytes: int,
|
|
23
|
+
n_files: int,
|
|
17
24
|
) -> None:
|
|
18
25
|
self.disable = disable
|
|
26
|
+
self.single_file = n_files <= 1
|
|
19
27
|
self.position_queue = self._init_position_queue(max_workers)
|
|
20
28
|
self.total_amount = tqdm(
|
|
21
29
|
total=total_bytes,
|
|
@@ -23,7 +31,7 @@ class BarConfig:
|
|
|
23
31
|
unit="iB",
|
|
24
32
|
unit_scale=True,
|
|
25
33
|
unit_divisor=1024,
|
|
26
|
-
disable=self.disable,
|
|
34
|
+
disable=self.disable if not self.single_file else True,
|
|
27
35
|
position=0,
|
|
28
36
|
leave=False,
|
|
29
37
|
colour="green",
|
|
@@ -32,7 +40,8 @@ class BarConfig:
|
|
|
32
40
|
|
|
33
41
|
def _init_position_queue(self, max_workers: int) -> asyncio.Queue:
|
|
34
42
|
queue: asyncio.Queue = asyncio.Queue()
|
|
35
|
-
|
|
43
|
+
start = 0 if self.single_file else 1
|
|
44
|
+
for i in range(start, start + max_workers):
|
|
36
45
|
queue.put_nowait(i)
|
|
37
46
|
return queue
|
|
38
47
|
|
|
@@ -49,17 +58,17 @@ class DlParams:
|
|
|
49
58
|
|
|
50
59
|
async def download_files(
|
|
51
60
|
base_url: str,
|
|
52
|
-
metadata: Iterable[Metadata],
|
|
61
|
+
metadata: Iterable[Metadata] | Metadata,
|
|
53
62
|
output_path: Path,
|
|
54
63
|
concurrency_limit: int,
|
|
55
64
|
disable_progress: bool | None,
|
|
56
65
|
validate_checksum: bool = False,
|
|
57
66
|
) -> list[Path]:
|
|
58
|
-
metas = list(metadata)
|
|
67
|
+
metas = list(metadata) if isinstance(metadata, Iterable) else [metadata]
|
|
59
68
|
file_exists = _checksum_matches if validate_checksum else _size_and_name_matches
|
|
60
69
|
semaphore = asyncio.Semaphore(concurrency_limit)
|
|
61
70
|
total_bytes = sum(meta.size for meta in metas)
|
|
62
|
-
bar_config = BarConfig(disable_progress, concurrency_limit, total_bytes)
|
|
71
|
+
bar_config = BarConfig(disable_progress, concurrency_limit, total_bytes, len(metas))
|
|
63
72
|
full_paths = []
|
|
64
73
|
async with aiohttp.ClientSession() as session:
|
|
65
74
|
tasks = []
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.12.9"
|
|
@@ -462,6 +462,19 @@ class TestDownloadingFunctionality:
|
|
|
462
462
|
assert paths1 == paths2
|
|
463
463
|
assert paths2[0].stat().st_size == original_size
|
|
464
464
|
|
|
465
|
+
def test_downloading_single_metadata(self, client: APIClient, tmp_path: Path):
|
|
466
|
+
uuid = "ab872770-9136-4e61-8958-31e62abdfb1b"
|
|
467
|
+
meta = client.file(uuid)
|
|
468
|
+
paths = client.download(meta, output_directory=tmp_path, progress=False)
|
|
469
|
+
assert len(paths) == 1
|
|
470
|
+
assert paths[0].exists()
|
|
471
|
+
|
|
472
|
+
def test_downloading_single_metadata_II(self, client: APIClient, tmp_path: Path):
|
|
473
|
+
meta = client.raw_files(date_from="2025-08-01")
|
|
474
|
+
assert len(meta) == 3
|
|
475
|
+
paths = client.download(meta[0], output_directory=tmp_path, progress=False)
|
|
476
|
+
assert len(paths) == 1
|
|
477
|
+
|
|
465
478
|
async def test_async_download(self, client: APIClient, tmp_path: Path):
|
|
466
479
|
meta = client.raw_files(date_from="2025-08-01")
|
|
467
480
|
assert len(meta) == 3
|
|
@@ -523,6 +536,7 @@ def _submit_product_file(backend_url: str, data_path: Path, meta: File):
|
|
|
523
536
|
"uuid": str(UUID(nc.file_uuid)),
|
|
524
537
|
"pid": nc.pid,
|
|
525
538
|
"instrumentPid": getattr(nc, "instrument_pid", None),
|
|
539
|
+
"s3key": None,
|
|
526
540
|
**file_info,
|
|
527
541
|
}
|
|
528
542
|
payload["model"] = product if payload["product"] == "model" else None
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.12.7"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cloudnet_api_client-0.12.7 → cloudnet_api_client-0.12.9}/tests/data/20250803_JOYCE_WST_01m.dat
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|