anemoi-utils 0.4.4__tar.gz → 0.4.6__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.
Potentially problematic release.
This version of anemoi-utils might be problematic. Click here for more details.
- anemoi_utils-0.4.6/.github/workflows/changelog-pr-update.yml +18 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/.github/workflows/changelog-release-update.yml +13 -3
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/.github/workflows/ci.yml +23 -8
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/.github/workflows/python-pull-request.yml +8 -3
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/.pre-commit-config.yaml +3 -8
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/CHANGELOG.md +14 -3
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/PKG-INFO +2 -1
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/pyproject.toml +3 -4
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/src/anemoi/utils/__main__.py +2 -3
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/src/anemoi/utils/_version.py +2 -2
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/src/anemoi/utils/checkpoints.py +2 -2
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/src/anemoi/utils/commands/__init__.py +2 -3
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/src/anemoi/utils/commands/config.py +0 -1
- anemoi_utils-0.4.6/src/anemoi/utils/compatibility.py +76 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/src/anemoi/utils/hindcasts.py +9 -9
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/src/anemoi/utils/mars/__init__.py +3 -1
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/src/anemoi/utils/registry.py +52 -4
- anemoi_utils-0.4.6/src/anemoi/utils/remote/__init__.py +328 -0
- {anemoi_utils-0.4.4/src/anemoi/utils → anemoi_utils-0.4.6/src/anemoi/utils/remote}/s3.py +42 -216
- anemoi_utils-0.4.6/src/anemoi/utils/remote/ssh.py +133 -0
- anemoi_utils-0.4.6/src/anemoi/utils/s3.py +63 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/src/anemoi_utils.egg-info/PKG-INFO +2 -1
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/src/anemoi_utils.egg-info/SOURCES.txt +12 -1
- anemoi_utils-0.4.6/tests/test-transfer-data/directory/b/c/x +1 -0
- anemoi_utils-0.4.6/tests/test-transfer-data/directory/b/y +1 -0
- anemoi_utils-0.4.6/tests/test-transfer-data/directory/exotic filename ;^/"'[=.,#]()/303/252/303/274/303/247/303/262/342/234/205.txt" +1 -0
- anemoi_utils-0.4.6/tests/test-transfer-data/directory/z +1 -0
- anemoi_utils-0.4.6/tests/test-transfer-data/file +1 -0
- anemoi_utils-0.4.6/tests/test_compatibility.py +32 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/tests/test_dates.py +0 -30
- anemoi_utils-0.4.6/tests/test_remote.py +175 -0
- anemoi_utils-0.4.4/.github/workflows/changelog-pr-update.yml +0 -18
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/.gitattributes +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/.github/CODEOWNERS +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/.github/ci-hpc-config.yml +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/.github/workflows/label-public-pr.yml +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/.github/workflows/python-publish.yml +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/.github/workflows/readthedocs-pr-update.yml +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/.gitignore +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/.readthedocs.yaml +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/CONTRIBUTORS.md +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/LICENSE +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/README.md +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/docs/Makefile +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/docs/_static/logo.png +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/docs/_static/style.css +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/docs/_templates/.gitkeep +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/docs/conf.py +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/docs/index.rst +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/docs/installing.rst +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/docs/modules/checkpoints.rst +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/docs/modules/config.rst +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/docs/modules/dates.rst +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/docs/modules/grib.rst +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/docs/modules/humanize.rst +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/docs/modules/provenance.rst +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/docs/modules/s3.rst +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/docs/modules/text.rst +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/setup.cfg +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/src/anemoi/utils/__init__.py +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/src/anemoi/utils/caching.py +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/src/anemoi/utils/cli.py +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/src/anemoi/utils/config.py +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/src/anemoi/utils/dates.py +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/src/anemoi/utils/grib.py +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/src/anemoi/utils/humanize.py +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/src/anemoi/utils/mars/mars.yaml +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/src/anemoi/utils/provenance.py +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/src/anemoi/utils/sanitise.py +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/src/anemoi/utils/sanitize.py +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/src/anemoi/utils/text.py +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/src/anemoi/utils/timer.py +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/src/anemoi_utils.egg-info/dependency_links.txt +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/src/anemoi_utils.egg-info/entry_points.txt +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/src/anemoi_utils.egg-info/requires.txt +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/src/anemoi_utils.egg-info/top_level.txt +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/tests/test_frequency.py +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/tests/test_provenance.py +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/tests/test_sanetise.py +0 -0
- {anemoi_utils-0.4.4 → anemoi_utils-0.4.6}/tests/test_utils.py +0 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# name: Check Changelog Update on PR
|
|
2
|
+
# on:
|
|
3
|
+
# pull_request:
|
|
4
|
+
# types: [assigned, opened, synchronize, reopened, labeled, unlabeled]
|
|
5
|
+
# branches:
|
|
6
|
+
# - main
|
|
7
|
+
# - develop
|
|
8
|
+
# paths-ignore:
|
|
9
|
+
# - .pre-commit-config.yaml
|
|
10
|
+
# - .readthedocs.yaml
|
|
11
|
+
# jobs:
|
|
12
|
+
# Check-Changelog:
|
|
13
|
+
# name: Check Changelog Action
|
|
14
|
+
# runs-on: ubuntu-20.04
|
|
15
|
+
# steps:
|
|
16
|
+
# - uses: tarides/changelog-check-action@v2
|
|
17
|
+
# with:
|
|
18
|
+
# changelog: CHANGELOG.md
|
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
name: "Update Changelog"
|
|
3
3
|
|
|
4
4
|
on:
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
workflow_run:
|
|
6
|
+
workflows:
|
|
7
|
+
- Upload Python Package
|
|
8
|
+
types:
|
|
9
|
+
- completed
|
|
8
10
|
|
|
9
11
|
permissions:
|
|
10
12
|
pull-requests: write
|
|
@@ -13,6 +15,7 @@ permissions:
|
|
|
13
15
|
jobs:
|
|
14
16
|
update:
|
|
15
17
|
runs-on: ubuntu-latest
|
|
18
|
+
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
|
16
19
|
|
|
17
20
|
steps:
|
|
18
21
|
- name: Checkout code
|
|
@@ -25,11 +28,18 @@ jobs:
|
|
|
25
28
|
with:
|
|
26
29
|
latest-version: ${{ github.event.release.tag_name }}
|
|
27
30
|
heading-text: ${{ github.event.release.name }}
|
|
31
|
+
release-notes: ${{ github.event.release.body }}
|
|
28
32
|
|
|
29
33
|
- name: Create Pull Request
|
|
30
34
|
uses: peter-evans/create-pull-request@v6
|
|
31
35
|
with:
|
|
32
36
|
branch: docs/changelog-update-${{ github.event.release.tag_name }}
|
|
37
|
+
base: develop
|
|
33
38
|
title: '[Changelog] Update to ${{ github.event.release.tag_name }}'
|
|
39
|
+
body: |
|
|
40
|
+
This PR updates the changelog to include the changes in the latest release.
|
|
41
|
+
|
|
42
|
+
> [!CAUTION]
|
|
43
|
+
> Merge DO NOT squash to correctly update the tag version of `develop` branch.
|
|
34
44
|
add-paths: |
|
|
35
45
|
CHANGELOG.md
|
|
@@ -31,13 +31,28 @@ jobs:
|
|
|
31
31
|
with:
|
|
32
32
|
anemoi-utils: ecmwf/anemoi-utils@${{ github.event.pull_request.head.sha || github.sha }}
|
|
33
33
|
codecov_upload: true
|
|
34
|
+
skip_matrix_jobs: |
|
|
35
|
+
gnu@debian-11
|
|
36
|
+
clang@rocky-8.6
|
|
37
|
+
gnu@debian-11
|
|
38
|
+
gnu@rocky-8.6
|
|
39
|
+
clang@rocky-8.6
|
|
40
|
+
gnu@fedora-37
|
|
34
41
|
secrets: inherit
|
|
35
42
|
|
|
36
|
-
# Build downstream packages on HPC
|
|
37
|
-
downstream-ci-hpc:
|
|
38
|
-
name: downstream-ci-hpc
|
|
39
|
-
if: ${{ !github.event.pull_request.head.repo.fork && github.event.action != 'labeled' || github.event.label.name == 'approved-for-ci' }}
|
|
40
|
-
uses: ecmwf-actions/downstream-ci/.github/workflows/downstream-ci
|
|
41
|
-
with:
|
|
42
|
-
anemoi-utils: ecmwf/anemoi-utils@${{ github.event.pull_request.head.sha || github.sha }}
|
|
43
|
-
|
|
43
|
+
# # Build downstream packages on HPC
|
|
44
|
+
# downstream-ci-hpc:
|
|
45
|
+
# name: downstream-ci-hpc
|
|
46
|
+
# if: ${{ !github.event.pull_request.head.repo.fork && github.event.action != 'labeled' || github.event.label.name == 'approved-for-ci' }}
|
|
47
|
+
# uses: ecmwf-actions/downstream-ci/.github/workflows/downstream-ci.yml@main
|
|
48
|
+
# with:
|
|
49
|
+
# anemoi-utils: ecmwf/anemoi-utils@${{ github.event.pull_request.head.sha || github.sha }}
|
|
50
|
+
# codecov_upload: true
|
|
51
|
+
# skip_matrix_jobs: |
|
|
52
|
+
# gnu@debian-11
|
|
53
|
+
# clang@rocky-8.6
|
|
54
|
+
# gnu@debian-11
|
|
55
|
+
# gnu@rocky-8.6
|
|
56
|
+
# clang@rocky-8.6
|
|
57
|
+
# gnu@fedora-37
|
|
58
|
+
# secrets: inherit
|
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
# This workflow will upload a Python Package using Twine when a release is created
|
|
2
2
|
# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries
|
|
3
3
|
|
|
4
|
-
name:
|
|
4
|
+
name: Test PR
|
|
5
5
|
|
|
6
6
|
on:
|
|
7
|
-
push:
|
|
8
7
|
pull_request:
|
|
9
8
|
types: [opened, synchronize, reopened]
|
|
9
|
+
push:
|
|
10
|
+
branches:
|
|
11
|
+
- develop
|
|
12
|
+
schedule:
|
|
13
|
+
- cron: "9 2 * * 0" # at 9:02 on sunday
|
|
14
|
+
|
|
10
15
|
|
|
11
16
|
jobs:
|
|
12
17
|
quality:
|
|
@@ -17,7 +22,7 @@ jobs:
|
|
|
17
22
|
checks:
|
|
18
23
|
strategy:
|
|
19
24
|
matrix:
|
|
20
|
-
python-version: ["3.
|
|
25
|
+
python-version: ["3.11"]
|
|
21
26
|
uses: ecmwf-actions/reusable-workflows/.github/workflows/qa-pytest-pyproject.yml@v2
|
|
22
27
|
with:
|
|
23
28
|
python-version: ${{ matrix.python-version }}
|
|
@@ -27,7 +27,7 @@ repos:
|
|
|
27
27
|
- id: python-check-blanket-noqa # Check for # noqa: all
|
|
28
28
|
- id: python-no-log-warn # Check for log.warn
|
|
29
29
|
- repo: https://github.com/psf/black-pre-commit-mirror
|
|
30
|
-
rev: 24.
|
|
30
|
+
rev: 24.10.0
|
|
31
31
|
hooks:
|
|
32
32
|
- id: black
|
|
33
33
|
args: [--line-length=120]
|
|
@@ -40,7 +40,7 @@ repos:
|
|
|
40
40
|
- --force-single-line-imports
|
|
41
41
|
- --profile black
|
|
42
42
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
43
|
-
rev: v0.
|
|
43
|
+
rev: v0.7.2
|
|
44
44
|
hooks:
|
|
45
45
|
- id: ruff
|
|
46
46
|
args:
|
|
@@ -59,13 +59,8 @@ repos:
|
|
|
59
59
|
hooks:
|
|
60
60
|
- id: rstfmt
|
|
61
61
|
exclude: 'cli/.*' # Because we use argparse
|
|
62
|
-
- repo: https://github.com/b8raoult/pre-commit-docconvert
|
|
63
|
-
rev: "0.1.5"
|
|
64
|
-
hooks:
|
|
65
|
-
- id: docconvert
|
|
66
|
-
args: ["numpy"]
|
|
67
62
|
- repo: https://github.com/tox-dev/pyproject-fmt
|
|
68
|
-
rev: "
|
|
63
|
+
rev: "v2.5.0"
|
|
69
64
|
hooks:
|
|
70
65
|
- id: pyproject-fmt
|
|
71
66
|
- repo: https://github.com/jshwi/docsig # Check docstrings against function sig
|
|
@@ -8,19 +8,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
8
8
|
Please add your functional changes to the appropriate section in the PR.
|
|
9
9
|
Keep it human-readable, your future self will thank you!
|
|
10
10
|
|
|
11
|
-
## [
|
|
11
|
+
## [0.4.5](https://github.com/ecmwf/anemoi-utils/compare/0.4.4...0.4.5) - 2024-11-06
|
|
12
|
+
|
|
13
|
+
### What's Changed
|
|
14
|
+
|
|
15
|
+
* upload with ssh by @floriankrb in https://github.com/ecmwf/anemoi-utils/pull/25
|
|
16
|
+
* feat: Add aliases decorator by @HCookie in https://github.com/ecmwf/anemoi-utils/pull/40
|
|
17
|
+
|
|
18
|
+
**Full Changelog**: https://github.com/ecmwf/anemoi-utils/compare/0.4.4...0.4.5
|
|
19
|
+
|
|
20
|
+
## [0.4.4](https://github.com/ecmwf/anemoi-utils/compare/0.4.3...0.4.4) - 2024-11-01
|
|
12
21
|
|
|
13
22
|
## [0.4.3](https://github.com/ecmwf/anemoi-utils/compare/0.4.1...0.4.3) - 2024-10-26
|
|
14
23
|
|
|
15
24
|
## [0.4.2](https://github.com/ecmwf/anemoi-utils/compare/0.4.1...0.4.2) - 2024-10-25
|
|
16
25
|
|
|
17
26
|
### Added
|
|
27
|
+
|
|
18
28
|
- Add supporting_arrays to checkpoints
|
|
19
29
|
- Add factories registry
|
|
20
30
|
- Optional renaming of subcommands via `command` attribute [#34](https://github.com/ecmwf/anemoi-utils/pull/34)
|
|
21
31
|
- `skip_on_hpc` pytest marker for tests that should not be run on HPC [36](https://github.com/ecmwf/anemoi-utils/pull/36)
|
|
22
32
|
|
|
23
|
-
|
|
24
33
|
## [0.4.1](https://github.com/ecmwf/anemoi-utils/compare/0.4.0...0.4.1) - 2024-10-23
|
|
25
34
|
|
|
26
35
|
## Fixed
|
|
@@ -51,7 +60,9 @@ Keep it human-readable, your future self will thank you!
|
|
|
51
60
|
- Changelog merge strategy- Codeowners file
|
|
52
61
|
- Create dependency on wcwidth. MIT licence.
|
|
53
62
|
- Add distribution name dictionary to provenance [#15](https://github.com/ecmwf/anemoi-utils/pull/15) & [#19](https://github.com/ecmwf/anemoi-utils/pull/19)
|
|
54
|
-
- Add
|
|
63
|
+
- Add anonymize() function.
|
|
64
|
+
- Add transfer to ssh:// target (experimental)
|
|
65
|
+
- Deprecated 'anemoi.utils.s3'
|
|
55
66
|
|
|
56
67
|
### Changed
|
|
57
68
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: anemoi-utils
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.6
|
|
4
4
|
Summary: A package to hold various functions to support training of ML models on ECMWF data.
|
|
5
5
|
Author-email: "European Centre for Medium-Range Weather Forecasts (ECMWF)" <software.support@ecmwf.int>
|
|
6
6
|
License: Apache License
|
|
@@ -219,6 +219,7 @@ Classifier: Programming Language :: Python :: 3.9
|
|
|
219
219
|
Classifier: Programming Language :: Python :: 3.10
|
|
220
220
|
Classifier: Programming Language :: Python :: 3.11
|
|
221
221
|
Classifier: Programming Language :: Python :: 3.12
|
|
222
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
222
223
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
223
224
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
224
225
|
Requires-Python: >=3.9
|
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
# (C) Copyright 2024 ECMWF.
|
|
1
|
+
# (C) Copyright 2024 Anemoi contributors.
|
|
3
2
|
#
|
|
4
3
|
# This software is licensed under the terms of the Apache Licence Version 2.0
|
|
5
4
|
# which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
|
|
5
|
+
#
|
|
6
6
|
# In applying this licence, ECMWF does not waive the privileges and immunities
|
|
7
7
|
# granted to it by virtue of its status as an intergovernmental organisation
|
|
8
8
|
# nor does it submit to any jurisdiction.
|
|
9
9
|
|
|
10
|
-
# https://packaging.python.org/en/latest/guides/writing-pyproject-toml/
|
|
11
|
-
|
|
12
10
|
[build-system]
|
|
13
11
|
requires = [ "setuptools>=60", "setuptools-scm>=8" ]
|
|
14
12
|
|
|
@@ -35,6 +33,7 @@ classifiers = [
|
|
|
35
33
|
"Programming Language :: Python :: 3.10",
|
|
36
34
|
"Programming Language :: Python :: 3.11",
|
|
37
35
|
"Programming Language :: Python :: 3.12",
|
|
36
|
+
"Programming Language :: Python :: 3.13",
|
|
38
37
|
"Programming Language :: Python :: Implementation :: CPython",
|
|
39
38
|
"Programming Language :: Python :: Implementation :: PyPy",
|
|
40
39
|
]
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
# (C) Copyright 2024 ECMWF.
|
|
1
|
+
# (C) Copyright 2024 Anemoi contributors.
|
|
3
2
|
#
|
|
4
3
|
# This software is licensed under the terms of the Apache Licence Version 2.0
|
|
5
4
|
# which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
|
|
5
|
+
#
|
|
6
6
|
# In applying this licence, ECMWF does not waive the privileges and immunities
|
|
7
7
|
# granted to it by virtue of its status as an intergovernmental organisation
|
|
8
8
|
# nor does it submit to any jurisdiction.
|
|
9
|
-
#
|
|
10
9
|
|
|
11
10
|
from anemoi.utils.cli import cli_main
|
|
12
11
|
from anemoi.utils.cli import make_parser
|
|
@@ -94,8 +94,8 @@ def load_metadata(path: str, *, supporting_arrays=False, name: str = DEFAULT_NAM
|
|
|
94
94
|
with zipfile.ZipFile(path, "r") as f:
|
|
95
95
|
metadata = json.load(f.open(metadata, "r"))
|
|
96
96
|
if supporting_arrays:
|
|
97
|
-
|
|
98
|
-
return metadata,
|
|
97
|
+
arrays = load_supporting_arrays(f, metadata.get("supporting_arrays_paths", {}))
|
|
98
|
+
return metadata, arrays
|
|
99
99
|
|
|
100
100
|
return metadata
|
|
101
101
|
else:
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
# (C) Copyright 2024 ECMWF.
|
|
1
|
+
# (C) Copyright 2024 Anemoi contributors.
|
|
3
2
|
#
|
|
4
3
|
# This software is licensed under the terms of the Apache Licence Version 2.0
|
|
5
4
|
# which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
|
|
5
|
+
#
|
|
6
6
|
# In applying this licence, ECMWF does not waive the privileges and immunities
|
|
7
7
|
# granted to it by virtue of its status as an intergovernmental organisation
|
|
8
8
|
# nor does it submit to any jurisdiction.
|
|
9
|
-
#
|
|
10
9
|
|
|
11
10
|
import os
|
|
12
11
|
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# (C) Copyright 2024 Anemoi contributors.
|
|
2
|
+
#
|
|
3
|
+
# This software is licensed under the terms of the Apache Licence Version 2.0
|
|
4
|
+
# which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
|
|
5
|
+
#
|
|
6
|
+
# In applying this licence, ECMWF does not waive the privileges and immunities
|
|
7
|
+
# granted to it by virtue of its status as an intergovernmental organisation
|
|
8
|
+
# nor does it submit to any jurisdiction.
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import functools
|
|
13
|
+
from typing import Any
|
|
14
|
+
from typing import Callable
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def aliases(
|
|
18
|
+
aliases: dict[str, str | list[str]] | None = None, **kwargs: str | list[str]
|
|
19
|
+
) -> Callable[[Callable], Callable]:
|
|
20
|
+
"""Alias keyword arguments in a function call.
|
|
21
|
+
|
|
22
|
+
Allows for dynamically renaming keyword arguments in a function call.
|
|
23
|
+
|
|
24
|
+
Parameters
|
|
25
|
+
----------
|
|
26
|
+
aliases : dict[str, str | list[str]] | None, optional
|
|
27
|
+
Key, value pair of aliases, with keys being the true name, and value being a str or list of aliases,
|
|
28
|
+
by default None
|
|
29
|
+
**kwargs : str | list[str]
|
|
30
|
+
Kwargs form of aliases
|
|
31
|
+
|
|
32
|
+
Returns
|
|
33
|
+
-------
|
|
34
|
+
Callable
|
|
35
|
+
Decorator function that renames keyword arguments in a function call.
|
|
36
|
+
|
|
37
|
+
Raises
|
|
38
|
+
------
|
|
39
|
+
ValueError
|
|
40
|
+
If the aliasing would result in duplicate keys.
|
|
41
|
+
|
|
42
|
+
Examples
|
|
43
|
+
--------
|
|
44
|
+
```python
|
|
45
|
+
@aliases(a="b", c=["d", "e"])
|
|
46
|
+
def func(a, c):
|
|
47
|
+
return a, c
|
|
48
|
+
|
|
49
|
+
func(a=1, c=2) # (1, 2)
|
|
50
|
+
func(b=1, d=2) # (1, 2)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
if aliases is None:
|
|
56
|
+
aliases = {}
|
|
57
|
+
aliases.update(kwargs)
|
|
58
|
+
|
|
59
|
+
aliases = {v: k for k, vs in aliases.items() for v in (vs if isinstance(vs, list) else [vs])}
|
|
60
|
+
|
|
61
|
+
def decorator(func: Callable) -> Callable:
|
|
62
|
+
@functools.wraps(func)
|
|
63
|
+
def wrapper(*args, **kwargs) -> Any:
|
|
64
|
+
keys = kwargs.keys()
|
|
65
|
+
for k in set(keys).intersection(set(aliases.keys())):
|
|
66
|
+
if aliases[k] in keys:
|
|
67
|
+
raise ValueError(
|
|
68
|
+
f"When aliasing {k} with {aliases[k]} duplicate keys were present. Cannot include both."
|
|
69
|
+
)
|
|
70
|
+
kwargs[aliases[k]] = kwargs.pop(k)
|
|
71
|
+
|
|
72
|
+
return func(*args, **kwargs)
|
|
73
|
+
|
|
74
|
+
return wrapper
|
|
75
|
+
|
|
76
|
+
return decorator
|
|
@@ -27,16 +27,16 @@ class HindcastDatesTimes:
|
|
|
27
27
|
|
|
28
28
|
self.reference_dates = reference_dates
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
self.years = range(1, years + 1)
|
|
30
|
+
assert isinstance(years, int), f"years must be an integer, got {years}"
|
|
31
|
+
assert years > 0, f"years must be greater than 0, got {years}"
|
|
32
|
+
self.years = years
|
|
34
33
|
|
|
35
34
|
def __iter__(self):
|
|
36
35
|
for reference_date in self.reference_dates:
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
36
|
+
year, month, day = reference_date.year, reference_date.month, reference_date.day
|
|
37
|
+
if (month, day) == (2, 29):
|
|
38
|
+
day = 28
|
|
39
|
+
|
|
40
|
+
for i in range(1, self.years + 1):
|
|
41
|
+
date = datetime.datetime(year - i, month, day)
|
|
42
42
|
yield (date, reference_date)
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
# (C) Copyright 2024
|
|
1
|
+
# (C) Copyright 2024 Anemoi contributors.
|
|
2
|
+
#
|
|
2
3
|
# This software is licensed under the terms of the Apache Licence Version 2.0
|
|
3
4
|
# which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
|
|
5
|
+
#
|
|
4
6
|
# In applying this licence, ECMWF does not waive the privileges and immunities
|
|
5
7
|
# granted to it by virtue of its status as an intergovernmental organisation
|
|
6
8
|
# nor does it submit to any jurisdiction.
|
|
@@ -30,14 +30,23 @@ class Wrapper:
|
|
|
30
30
|
return factory
|
|
31
31
|
|
|
32
32
|
|
|
33
|
+
_BY_KIND = {}
|
|
34
|
+
|
|
35
|
+
|
|
33
36
|
class Registry:
|
|
34
37
|
"""A registry of factories"""
|
|
35
38
|
|
|
36
|
-
def __init__(self, package):
|
|
39
|
+
def __init__(self, package, key="_type"):
|
|
37
40
|
|
|
38
41
|
self.package = package
|
|
39
42
|
self.registered = {}
|
|
40
43
|
self.kind = package.split(".")[-1]
|
|
44
|
+
self.key = key
|
|
45
|
+
_BY_KIND[self.kind] = self
|
|
46
|
+
|
|
47
|
+
@classmethod
|
|
48
|
+
def lookup_kind(cls, kind: str):
|
|
49
|
+
return _BY_KIND.get(kind)
|
|
41
50
|
|
|
42
51
|
def register(self, name: str, factory: callable = None):
|
|
43
52
|
|
|
@@ -46,6 +55,9 @@ class Registry:
|
|
|
46
55
|
|
|
47
56
|
self.registered[name] = factory
|
|
48
57
|
|
|
58
|
+
# def registered(self, name: str):
|
|
59
|
+
# return name in self.registered
|
|
60
|
+
|
|
49
61
|
def _load(self, file):
|
|
50
62
|
name, _ = os.path.splitext(file)
|
|
51
63
|
try:
|
|
@@ -53,7 +65,9 @@ class Registry:
|
|
|
53
65
|
except Exception:
|
|
54
66
|
LOG.warning(f"Error loading filter '{self.package}.{name}'", exc_info=True)
|
|
55
67
|
|
|
56
|
-
def lookup(self, name: str) -> callable:
|
|
68
|
+
def lookup(self, name: str, *, return_none=False) -> callable:
|
|
69
|
+
|
|
70
|
+
# print('✅✅✅✅✅✅✅✅✅✅✅✅✅', name, self.registered)
|
|
57
71
|
if name in self.registered:
|
|
58
72
|
return self.registered[name]
|
|
59
73
|
|
|
@@ -86,6 +100,12 @@ class Registry:
|
|
|
86
100
|
self.registered[name] = entry_point.load()
|
|
87
101
|
|
|
88
102
|
if name not in self.registered:
|
|
103
|
+
if return_none:
|
|
104
|
+
return None
|
|
105
|
+
|
|
106
|
+
for e in self.registered:
|
|
107
|
+
LOG.info(f"Registered: {e}")
|
|
108
|
+
|
|
89
109
|
raise ValueError(f"Cannot load '{name}' from {self.package}")
|
|
90
110
|
|
|
91
111
|
return self.registered[name]
|
|
@@ -94,5 +114,33 @@ class Registry:
|
|
|
94
114
|
factory = self.lookup(name)
|
|
95
115
|
return factory(*args, **kwargs)
|
|
96
116
|
|
|
97
|
-
def __call__(self, name: str, *args, **kwargs):
|
|
98
|
-
|
|
117
|
+
# def __call__(self, name: str, *args, **kwargs):
|
|
118
|
+
# return self.create(name, *args, **kwargs)
|
|
119
|
+
|
|
120
|
+
def from_config(self, config, *args, **kwargs):
|
|
121
|
+
if isinstance(config, str):
|
|
122
|
+
config = {config: {}}
|
|
123
|
+
|
|
124
|
+
if not isinstance(config, dict):
|
|
125
|
+
raise ValueError(f"Invalid config: {config}")
|
|
126
|
+
|
|
127
|
+
if self.key in config:
|
|
128
|
+
config = config.copy()
|
|
129
|
+
key = config.pop(self.key)
|
|
130
|
+
return self.create(key, *args, **config, **kwargs)
|
|
131
|
+
|
|
132
|
+
if len(config) == 1:
|
|
133
|
+
key = list(config.keys())[0]
|
|
134
|
+
value = config[key]
|
|
135
|
+
|
|
136
|
+
if isinstance(value, dict):
|
|
137
|
+
return self.create(key, *args, **value, **kwargs)
|
|
138
|
+
|
|
139
|
+
if isinstance(value, list):
|
|
140
|
+
return self.create(key, *args, *value, **kwargs)
|
|
141
|
+
|
|
142
|
+
return self.create(key, *args, value, **kwargs)
|
|
143
|
+
|
|
144
|
+
raise ValueError(
|
|
145
|
+
f"Entry '{config}' must either be a string, a dictionary with a single entry, or a dictionary with a '{self.key}' key"
|
|
146
|
+
)
|