anemoi-utils 0.4.23__tar.gz → 0.4.25__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.23 → anemoi_utils-0.4.25}/.github/CODEOWNERS +0 -1
- anemoi_utils-0.4.25/.github/pull_request_template.md +13 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/.github/workflows/downstream-ci-hpc.yml +1 -1
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/.github/workflows/pr-conventional-commit.yml +1 -1
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/.github/workflows/pr-label-conventional-commits.yml +1 -1
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/.github/workflows/pr-label-file-based.yml +1 -1
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/.github/workflows/pr-label-public.yml +1 -1
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/.github/workflows/python-pull-request.yml +1 -1
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/.github/workflows/readthedocs-pr-update.yml +1 -1
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/.gitignore +7 -1
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/.pre-commit-config.yaml +3 -2
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/.release-please-config.json +6 -1
- anemoi_utils-0.4.25/.release-please-manifest.json +3 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/CHANGELOG.md +16 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/PKG-INFO +3 -1
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/pyproject.toml +2 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi/utils/_version.py +2 -2
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi/utils/cli.py +14 -4
- anemoi_utils-0.4.25/src/anemoi/utils/commands/transfer.py +74 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi/utils/grids.py +27 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi/utils/remote/__init__.py +8 -3
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi/utils/remote/s3.py +107 -26
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi/utils/testing.py +101 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi_utils.egg-info/PKG-INFO +3 -1
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi_utils.egg-info/SOURCES.txt +1 -2
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi_utils.egg-info/requires.txt +2 -0
- anemoi_utils-0.4.23/.github/pull_request_template.md +0 -46
- anemoi_utils-0.4.23/.github/release.yml +0 -23
- anemoi_utils-0.4.23/.release-please-manifest.json +0 -3
- anemoi_utils-0.4.23/tests/test_grids.py +0 -29
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/.gitattributes +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/.github/ci-hpc-config.yml +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/.github/dependabot.yml +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/.github/labeler.yml +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/.github/workflows/python-publish.yml +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/.github/workflows/release-please.yml +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/.readthedocs.yaml +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/CONTRIBUTORS.md +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/LICENSE +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/README.md +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/docs/Makefile +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/docs/_static/logo.png +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/docs/_static/style.css +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/docs/_templates/.gitkeep +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/docs/_templates/apidoc/package.rst.jinja +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/docs/conf.py +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/docs/index.rst +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/docs/installing.rst +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/docs/modules/checkpoints.rst +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/docs/modules/config.rst +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/docs/modules/dates.rst +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/docs/modules/grib.rst +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/docs/modules/humanize.rst +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/docs/modules/provenance.rst +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/docs/modules/s3.rst +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/docs/modules/testing.rst +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/docs/modules/text.rst +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/docs/scripts/api_build.sh +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/setup.cfg +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi/utils/__init__.py +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi/utils/__main__.py +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi/utils/caching.py +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi/utils/checkpoints.py +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi/utils/commands/__init__.py +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi/utils/commands/config.py +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi/utils/commands/requests.py +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi/utils/compatibility.py +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi/utils/config.py +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi/utils/dates.py +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi/utils/devtools.py +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi/utils/grib.py +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi/utils/hindcasts.py +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi/utils/humanize.py +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi/utils/logs.py +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi/utils/mars/__init__.py +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi/utils/mars/mars.yaml +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi/utils/mars/requests.py +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi/utils/provenance.py +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi/utils/registry.py +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi/utils/remote/ssh.py +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi/utils/rules.py +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi/utils/s3.py +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi/utils/sanitise.py +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi/utils/sanitize.py +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi/utils/schemas/__init__.py +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi/utils/schemas/errors.py +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi/utils/text.py +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi/utils/timer.py +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi_utils.egg-info/dependency_links.txt +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi_utils.egg-info/entry_points.txt +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/src/anemoi_utils.egg-info/top_level.txt +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/tests/test-transfer-data/directory/b/c/x +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/tests/test-transfer-data/directory/b/y +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/tests/test-transfer-data/directory/exotic filename ;^/"'[=.,#]()/303/252/303/274/303/247/303/262/342/234/205.txt" +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/tests/test-transfer-data/directory/z +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/tests/test-transfer-data/file +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/tests/test_caching.py +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/tests/test_compatibility.py +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/tests/test_dates.py +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/tests/test_frequency.py +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/tests/test_provenance.py +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/tests/test_remote.py +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/tests/test_sanetise.py +0 -0
- {anemoi_utils-0.4.23 → anemoi_utils-0.4.25}/tests/test_utils.py +0 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
## Description
|
|
2
|
+
<!-- What issue or task does this change relate to? -->
|
|
3
|
+
|
|
4
|
+
## What problem does this change solve?
|
|
5
|
+
<!-- Describe if it's a bugfix, new feature, doc update, or breaking change -->
|
|
6
|
+
|
|
7
|
+
## What issue or task does this change relate to?
|
|
8
|
+
<!-- link to Issue Number -->
|
|
9
|
+
|
|
10
|
+
## Additional notes ##
|
|
11
|
+
<!-- Include any additional information, caveats, or considerations that the reviewer should be aware of. -->
|
|
12
|
+
|
|
13
|
+
***As a contributor to the Anemoi framework, please ensure that your changes include unit tests, updates to any affected dependencies and documentation, and have been tested in a parallel setting (i.e., with multiple GPUs). As a reviewer, you are also responsible for verifying these aspects and requesting changes if they are not adequately addressed. For guidelines about those please refer to https://anemoi.readthedocs.io/en/latest/***
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# This workflow triggers tests on dependent packages.
|
|
2
2
|
# The dependency tree itself is defined in ecmwf/downstream-ci/
|
|
3
|
-
name: Test downstream dependent packages
|
|
3
|
+
name: Test downstream dependent packages
|
|
4
4
|
|
|
5
5
|
on:
|
|
6
6
|
# Trigger the workflow on push to main or develop, except tag creation
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# This workflow assigns labels to a pull request based on the files changed in the PR.
|
|
2
2
|
# The labels are defined in the `.github/labels.yml` file.
|
|
3
|
-
name: "[
|
|
3
|
+
name: "[PR] Label File-based"
|
|
4
4
|
on:
|
|
5
5
|
pull_request_target:
|
|
6
6
|
types: [opened, synchronize]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# This workflow adds a link to the experimental documentation build to the PR.
|
|
2
2
|
# This does NOT trigger a build of the documentation, this is handled through webhooks.
|
|
3
|
-
name: Read the Docs
|
|
3
|
+
name: "[PR] Read the Docs Preview"
|
|
4
4
|
on:
|
|
5
5
|
pull_request_target:
|
|
6
6
|
types:
|
|
@@ -94,6 +94,11 @@ dmypy.json
|
|
|
94
94
|
*.csv
|
|
95
95
|
*.xlsx
|
|
96
96
|
*.xls
|
|
97
|
+
*.json
|
|
98
|
+
*.txt
|
|
99
|
+
*.zip
|
|
100
|
+
*.db
|
|
101
|
+
*.tgz
|
|
97
102
|
|
|
98
103
|
# ML artifacts
|
|
99
104
|
wandb/
|
|
@@ -120,7 +125,8 @@ tmp/
|
|
|
120
125
|
temp/
|
|
121
126
|
logs/
|
|
122
127
|
_dev/
|
|
123
|
-
|
|
128
|
+
_api/
|
|
129
|
+
./outputs
|
|
124
130
|
*tmp_data/
|
|
125
131
|
|
|
126
132
|
# Project specific
|
|
@@ -39,8 +39,9 @@ repos:
|
|
|
39
39
|
- -l 120
|
|
40
40
|
- --force-single-line-imports
|
|
41
41
|
- --profile black
|
|
42
|
+
- --project anemoi
|
|
42
43
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
43
|
-
rev: v0.11.
|
|
44
|
+
rev: v0.11.12
|
|
44
45
|
hooks:
|
|
45
46
|
- id: ruff
|
|
46
47
|
args:
|
|
@@ -64,7 +65,7 @@ repos:
|
|
|
64
65
|
- id: docconvert
|
|
65
66
|
args: ["numpy"]
|
|
66
67
|
- repo: https://github.com/tox-dev/pyproject-fmt
|
|
67
|
-
rev: "v2.
|
|
68
|
+
rev: "v2.6.0"
|
|
68
69
|
hooks:
|
|
69
70
|
- id: pyproject-fmt
|
|
70
71
|
- repo: https://github.com/jshwi/docsig # Check docstrings against function sig
|
|
@@ -10,11 +10,16 @@
|
|
|
10
10
|
"draft-pull-request": true,
|
|
11
11
|
"pull-request-title-pattern": "chore${scope}: Release${component} ${version}",
|
|
12
12
|
"pull-request-header": ":robot: Automated Release PR\n\nThis PR was created by `release-please` to prepare the next release. Once merged:\n\n1. A new version tag will be created\n2. A GitHub release will be published\n3. The changelog will be updated\n\nChanges to be included in the next release:",
|
|
13
|
-
"pull-request-footer": "> [!IMPORTANT]\n> :warning: Merging this PR will:\n> - Create a new release\n> - Trigger deployment pipelines\n> - Update package versions\n\n **Before merging:**\n - Ensure all tests pass\n - Review the changelog carefully\n - Get required approvals\n\n [Release-please documentation](https://github.com/googleapis/release-please)",
|
|
13
|
+
"pull-request-footer": "> [!IMPORTANT]\n> Please do not change the PR title, manifest file, or any other automatically generated content in this PR unless you understand the implications. Changes here can break the release process.\n> :warning: Merging this PR will:\n> - Create a new release\n> - Trigger deployment pipelines\n> - Update package versions\n\n **Before merging:**\n - Ensure all tests pass\n - Review the changelog carefully\n - Get required approvals\n\n [Release-please documentation](https://github.com/googleapis/release-please)",
|
|
14
14
|
"packages": {
|
|
15
15
|
".": {
|
|
16
16
|
"package-name": "anemoi-utils"
|
|
17
17
|
}
|
|
18
18
|
},
|
|
19
|
+
"plugins": [
|
|
20
|
+
{
|
|
21
|
+
"type": "sentence-case"
|
|
22
|
+
}
|
|
23
|
+
],
|
|
19
24
|
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json"
|
|
20
25
|
}
|
|
@@ -8,6 +8,22 @@ 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
|
+
## [0.4.25](https://github.com/ecmwf/anemoi-utils/compare/0.4.24...0.4.25) (2025-06-24)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### Features
|
|
15
|
+
|
|
16
|
+
* Add a CLI to transfer data ([#164](https://github.com/ecmwf/anemoi-utils/issues/164)) ([3a845ca](https://github.com/ecmwf/anemoi-utils/commit/3a845ca0c31d115e6b3d0496d862a3eaee5fb236))
|
|
17
|
+
* Add function to test cli ([#168](https://github.com/ecmwf/anemoi-utils/issues/168)) ([9ac9b06](https://github.com/ecmwf/anemoi-utils/commit/9ac9b06b8fd0a62cad33ea5de6a6b482f0a13656))
|
|
18
|
+
|
|
19
|
+
## [0.4.24](https://github.com/ecmwf/anemoi-utils/compare/0.4.23...0.4.24) (2025-06-06)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
### Features
|
|
23
|
+
|
|
24
|
+
* Add s3.object_exists() function ([#157](https://github.com/ecmwf/anemoi-utils/issues/157)) ([d898811](https://github.com/ecmwf/anemoi-utils/commit/d8988116320265dc6dfe467c57e0b6f29f76a2c1))
|
|
25
|
+
* Allow wildcard in config for matching s3 buckets to end points ([#160](https://github.com/ecmwf/anemoi-utils/issues/160)) ([ab20da7](https://github.com/ecmwf/anemoi-utils/commit/ab20da7e9497435a7183705b02dcbb7317d2700b))
|
|
26
|
+
|
|
11
27
|
## [0.4.23](https://github.com/ecmwf/anemoi-utils/compare/0.4.22...0.4.23) (2025-05-20)
|
|
12
28
|
|
|
13
29
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: anemoi-utils
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.25
|
|
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
|
|
@@ -225,12 +225,14 @@ Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
|
225
225
|
Requires-Python: >=3.9
|
|
226
226
|
License-File: LICENSE
|
|
227
227
|
Requires-Dist: aniso8601
|
|
228
|
+
Requires-Dist: deprecation
|
|
228
229
|
Requires-Dist: importlib-metadata; python_version < "3.10"
|
|
229
230
|
Requires-Dist: multiurl
|
|
230
231
|
Requires-Dist: numpy
|
|
231
232
|
Requires-Dist: pydantic>=2.9
|
|
232
233
|
Requires-Dist: python-dateutil
|
|
233
234
|
Requires-Dist: pyyaml
|
|
235
|
+
Requires-Dist: rich
|
|
234
236
|
Requires-Dist: tomli; python_version < "3.11"
|
|
235
237
|
Requires-Dist: tqdm
|
|
236
238
|
Provides-Extra: all
|
|
@@ -41,12 +41,14 @@ classifiers = [
|
|
|
41
41
|
dynamic = [ "version" ]
|
|
42
42
|
dependencies = [
|
|
43
43
|
"aniso8601",
|
|
44
|
+
"deprecation",
|
|
44
45
|
"importlib-metadata; python_version<'3.10'",
|
|
45
46
|
"multiurl",
|
|
46
47
|
"numpy",
|
|
47
48
|
"pydantic>=2.9",
|
|
48
49
|
"python-dateutil",
|
|
49
50
|
"pyyaml",
|
|
51
|
+
"rich",
|
|
50
52
|
"tomli; python_version<'3.11'",
|
|
51
53
|
"tqdm",
|
|
52
54
|
]
|
|
@@ -15,6 +15,7 @@ import os
|
|
|
15
15
|
import sys
|
|
16
16
|
import traceback
|
|
17
17
|
from typing import Callable
|
|
18
|
+
from typing import Optional
|
|
18
19
|
|
|
19
20
|
try:
|
|
20
21
|
import argcomplete
|
|
@@ -185,7 +186,9 @@ def register_commands(here: str, package: str, select: Callable, fail: Callable
|
|
|
185
186
|
return result
|
|
186
187
|
|
|
187
188
|
|
|
188
|
-
def cli_main(
|
|
189
|
+
def cli_main(
|
|
190
|
+
version: str, description: str, commands: dict[str, Command], test_arguments: Optional[list[str]] = None
|
|
191
|
+
) -> None:
|
|
189
192
|
"""Main entry point for the CLI.
|
|
190
193
|
|
|
191
194
|
Parameters
|
|
@@ -196,9 +199,11 @@ def cli_main(version: str, description: str, commands: dict[str, Command]) -> No
|
|
|
196
199
|
The description of the CLI
|
|
197
200
|
commands : dict[str, Command]
|
|
198
201
|
A dictionary of command names to Command instances
|
|
202
|
+
test_arguments : list[str], optional
|
|
203
|
+
The command line arguments to parse, used for testing purposes, by default None
|
|
199
204
|
"""
|
|
200
205
|
parser = make_parser(description, commands)
|
|
201
|
-
args, unknown = parser.parse_known_args()
|
|
206
|
+
args, unknown = parser.parse_known_args(test_arguments)
|
|
202
207
|
if argcomplete:
|
|
203
208
|
argcomplete.autocomplete(parser)
|
|
204
209
|
|
|
@@ -220,7 +225,7 @@ def cli_main(version: str, description: str, commands: dict[str, Command]) -> No
|
|
|
220
225
|
|
|
221
226
|
if unknown and not cmd.accept_unknown_args:
|
|
222
227
|
# This should trigger an error
|
|
223
|
-
parser.parse_args()
|
|
228
|
+
parser.parse_args(test_arguments)
|
|
224
229
|
|
|
225
230
|
try:
|
|
226
231
|
if unknown:
|
|
@@ -228,9 +233,14 @@ def cli_main(version: str, description: str, commands: dict[str, Command]) -> No
|
|
|
228
233
|
else:
|
|
229
234
|
cmd.run(args)
|
|
230
235
|
except ValueError as e:
|
|
236
|
+
|
|
237
|
+
if test_arguments:
|
|
238
|
+
raise
|
|
239
|
+
|
|
231
240
|
traceback.print_exc()
|
|
232
241
|
LOG.error("\n💣 %s", str(e).lstrip())
|
|
233
242
|
LOG.error("💣 Exiting")
|
|
234
243
|
sys.exit(1)
|
|
235
244
|
|
|
236
|
-
|
|
245
|
+
if not test_arguments:
|
|
246
|
+
sys.exit(0)
|
|
@@ -0,0 +1,74 @@
|
|
|
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
|
+
|
|
11
|
+
from argparse import ArgumentParser
|
|
12
|
+
from argparse import Namespace
|
|
13
|
+
|
|
14
|
+
from anemoi.utils.remote import transfer
|
|
15
|
+
|
|
16
|
+
from . import Command
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class Transfer(Command):
|
|
20
|
+
"""Handle configuration related commands."""
|
|
21
|
+
|
|
22
|
+
def add_arguments(self, command_parser: ArgumentParser) -> None:
|
|
23
|
+
"""Add arguments to the command parser.
|
|
24
|
+
|
|
25
|
+
Parameters
|
|
26
|
+
----------
|
|
27
|
+
command_parser : ArgumentParser
|
|
28
|
+
The argument parser to which the arguments will be added.
|
|
29
|
+
"""
|
|
30
|
+
command_parser.add_argument(
|
|
31
|
+
"--source", help="A path to a local file or folder or a URL to a file or a folder on S3."
|
|
32
|
+
)
|
|
33
|
+
command_parser.add_argument(
|
|
34
|
+
"--target", help="A path to a local file or folder or a URL to a file or a folder on S3 or a remote folder."
|
|
35
|
+
)
|
|
36
|
+
command_parser.add_argument(
|
|
37
|
+
"--overwrite",
|
|
38
|
+
action="store_true",
|
|
39
|
+
help="If the data is already on in the target location it will be overwritten..",
|
|
40
|
+
)
|
|
41
|
+
command_parser.add_argument(
|
|
42
|
+
"--resume",
|
|
43
|
+
action="store_true",
|
|
44
|
+
help="If the data is already on S3 it will not be uploaded, unless the remote file has a different size.",
|
|
45
|
+
)
|
|
46
|
+
command_parser.add_argument("--verbosity", default=1, help="The level of verbosity, by default 1.")
|
|
47
|
+
command_parser.add_argument(
|
|
48
|
+
"--progress", default=None, help="A callable that will be called with the number of files."
|
|
49
|
+
)
|
|
50
|
+
command_parser.add_argument(
|
|
51
|
+
"--threads", default=1, help="The number of threads to use when uploading a directory, by default 1."
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
def run(self, args: Namespace) -> None:
|
|
55
|
+
"""Execute the command with the provided arguments.
|
|
56
|
+
|
|
57
|
+
Parameters
|
|
58
|
+
----------
|
|
59
|
+
args : Namespace
|
|
60
|
+
The arguments passed to the command.
|
|
61
|
+
"""
|
|
62
|
+
transfer(
|
|
63
|
+
source=args.source,
|
|
64
|
+
target=args.target,
|
|
65
|
+
overwrite=args.overwrite,
|
|
66
|
+
resume=args.resume,
|
|
67
|
+
verbosity=args.verbosity,
|
|
68
|
+
progress=args.progress,
|
|
69
|
+
threads=args.threads,
|
|
70
|
+
temporary_target=False,
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
command = Transfer
|
|
@@ -17,9 +17,12 @@ from typing import List
|
|
|
17
17
|
from typing import Tuple
|
|
18
18
|
from typing import Union
|
|
19
19
|
|
|
20
|
+
import deprecation
|
|
20
21
|
import numpy as np
|
|
21
22
|
import requests
|
|
22
23
|
|
|
24
|
+
from anemoi.utils._version import __version__
|
|
25
|
+
|
|
23
26
|
from .caching import cached
|
|
24
27
|
|
|
25
28
|
LOG = logging.getLogger(__name__)
|
|
@@ -28,6 +31,12 @@ LOG = logging.getLogger(__name__)
|
|
|
28
31
|
GRIDS_URL_PATTERN = "https://get.ecmwf.int/repository/anemoi/grids/grid-{name}.npz"
|
|
29
32
|
|
|
30
33
|
|
|
34
|
+
@deprecation.deprecated(
|
|
35
|
+
deprecated_in="0.4.25",
|
|
36
|
+
removed_in="0.5.0",
|
|
37
|
+
current_version=__version__,
|
|
38
|
+
details="Use anemoi.transform.spatial.xyz_to_latlon instead.",
|
|
39
|
+
)
|
|
31
40
|
def xyz_to_latlon(x: np.ndarray, y: np.ndarray, z: np.ndarray) -> tuple[np.ndarray, np.ndarray]:
|
|
32
41
|
"""Convert Cartesian coordinates to latitude and longitude.
|
|
33
42
|
|
|
@@ -51,6 +60,12 @@ def xyz_to_latlon(x: np.ndarray, y: np.ndarray, z: np.ndarray) -> tuple[np.ndarr
|
|
|
51
60
|
)
|
|
52
61
|
|
|
53
62
|
|
|
63
|
+
@deprecation.deprecated(
|
|
64
|
+
deprecated_in="0.4.25",
|
|
65
|
+
removed_in="0.5.0",
|
|
66
|
+
current_version=__version__,
|
|
67
|
+
details="Use anemoi.transform.spatial.xyz_to_latlon instead.",
|
|
68
|
+
)
|
|
54
69
|
def latlon_to_xyz(lat: np.ndarray, lon: np.ndarray, radius: float = 1.0) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
|
|
55
70
|
"""Convert latitude and longitude to Cartesian coordinates.
|
|
56
71
|
|
|
@@ -87,6 +102,12 @@ def latlon_to_xyz(lat: np.ndarray, lon: np.ndarray, radius: float = 1.0) -> tupl
|
|
|
87
102
|
return x, y, z
|
|
88
103
|
|
|
89
104
|
|
|
105
|
+
@deprecation.deprecated(
|
|
106
|
+
deprecated_in="0.4.25",
|
|
107
|
+
removed_in="0.5.0",
|
|
108
|
+
current_version=__version__,
|
|
109
|
+
details="Use anemoi.transform.spatial.nearest_grid_points instead.",
|
|
110
|
+
)
|
|
90
111
|
def nearest_grid_points(
|
|
91
112
|
source_latitudes: np.ndarray,
|
|
92
113
|
source_longitudes: np.ndarray,
|
|
@@ -169,6 +190,12 @@ def _grids(name: Union[str, List[float], Tuple[float, ...]]) -> bytes:
|
|
|
169
190
|
return response.content
|
|
170
191
|
|
|
171
192
|
|
|
193
|
+
@deprecation.deprecated(
|
|
194
|
+
deprecated_in="0.4.25",
|
|
195
|
+
removed_in="0.5.0",
|
|
196
|
+
current_version=__version__,
|
|
197
|
+
details="Use anemoi.transform.grids.named.lookup instead.",
|
|
198
|
+
)
|
|
172
199
|
def grids(name: Union[str, List[float], Tuple[float, ...]]) -> dict:
|
|
173
200
|
"""Load grid data by name.
|
|
174
201
|
|
|
@@ -371,7 +371,12 @@ class BaseDownload(Loader):
|
|
|
371
371
|
The target path.
|
|
372
372
|
"""
|
|
373
373
|
if os.path.exists(target):
|
|
374
|
-
|
|
374
|
+
if os.path.isfile(target):
|
|
375
|
+
LOGGER.info(f"Deleting file {target}")
|
|
376
|
+
os.remove(target)
|
|
377
|
+
else:
|
|
378
|
+
LOGGER.info(f"Deleting directory {target}")
|
|
379
|
+
shutil.rmtree(target)
|
|
375
380
|
|
|
376
381
|
|
|
377
382
|
class BaseUpload(Loader):
|
|
@@ -642,10 +647,10 @@ def transfer(
|
|
|
642
647
|
A path to a local file or folder or a URL to a file or a folder on S3 or a remote folder.
|
|
643
648
|
The url should start with 's3://' or 'ssh://'.
|
|
644
649
|
overwrite : bool, optional
|
|
645
|
-
If the data is
|
|
650
|
+
If the data is already on in the target location it will be overwritten.
|
|
646
651
|
By default False
|
|
647
652
|
resume : bool, optional
|
|
648
|
-
If the data is
|
|
653
|
+
If the data is already on S3 it will not be uploaded, unless the remote file has a different size
|
|
649
654
|
Ignored if the target is an SSH remote folder (ssh://).
|
|
650
655
|
By default False
|
|
651
656
|
verbosity : int, optional
|