esgpull 0.9.3__tar.gz → 0.9.5__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.
- {esgpull-0.9.3 → esgpull-0.9.5}/.github/workflows/ci.yml +4 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/PKG-INFO +3 -3
- {esgpull-0.9.3 → esgpull-0.9.5}/README.md +1 -1
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/context.py +45 -12
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/esgpull.py +10 -5
- esgpull-0.9.5/esgpull/migrations/versions/0.9.4_update_tables.py +28 -0
- esgpull-0.9.5/esgpull/migrations/versions/0.9.5_update_tables.py +28 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/tui.py +11 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/pyproject.toml +2 -2
- {esgpull-0.9.3 → esgpull-0.9.5}/requirements-dev.lock +36 -36
- {esgpull-0.9.3 → esgpull-0.9.5}/requirements.lock +17 -19
- {esgpull-0.9.3 → esgpull-0.9.5}/tests/cli/test_dataset.py +1 -1
- esgpull-0.9.5/tests/cli/test_download.py +50 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/tests/cli/test_remove.py +2 -2
- {esgpull-0.9.3 → esgpull-0.9.5}/tests/cli/test_update.py +1 -1
- {esgpull-0.9.3 → esgpull-0.9.5}/tests/test_context.py +189 -1
- {esgpull-0.9.3 → esgpull-0.9.5}/uv.lock +2 -7
- {esgpull-0.9.3 → esgpull-0.9.5}/.github/workflows/doc.yml +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/.github/workflows/pypi-publish.yml +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/.gitignore +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/.pre-commit-config.yaml +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/CITATION.cff +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/LICENSE +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/alembic.ini +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/docs/docs/configuration.md +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/docs/docs/download.md +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/docs/docs/glossary.md +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/docs/docs/images/download_1.svg +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/docs/docs/images/download_2.svg +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/docs/docs/images/download_3.svg +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/docs/docs/images/download_4.svg +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/docs/docs/images/download_5.svg +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/docs/docs/images/download_6.svg +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/docs/docs/images/intro_1.svg +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/docs/docs/images/intro_2.svg +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/docs/docs/images/intro_3.svg +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/docs/docs/images/intro_4.svg +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/docs/docs/images/intro_5.svg +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/docs/docs/images/intro_6.svg +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/docs/docs/images/quickstart_1.svg +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/docs/docs/images/search_1.svg +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/docs/docs/images/search_2.svg +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/docs/docs/images/search_3.svg +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/docs/docs/images/search_4.svg +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/docs/docs/images/search_5.svg +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/docs/docs/images/search_6.svg +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/docs/docs/images/search_7.svg +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/docs/docs/images/search_ignore.svg +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/docs/docs/index.md +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/docs/docs/installation.md +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/docs/docs/plugins.md +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/docs/docs/queries.md +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/docs/docs/quickstart.md +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/docs/docs/search.md +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/docs/docs/stylesheets/extra.css +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/docs/includes/abbreviations.md +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/docs/mkdocs.yml +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/__init__.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/cli/__init__.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/cli/add.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/cli/autoremove.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/cli/config.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/cli/convert.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/cli/decorators.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/cli/download.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/cli/facet.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/cli/get.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/cli/index_nodes.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/cli/install.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/cli/plugins.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/cli/remove.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/cli/retry.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/cli/search.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/cli/self.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/cli/show.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/cli/status.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/cli/track.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/cli/update.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/cli/utils.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/config.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/constants.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/database.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/download.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/exceptions.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/fs.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/graph.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/install_config.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/migrations/README +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/migrations/env.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/migrations/script.py.mako +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/migrations/versions/0.3.0_update_tables.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/migrations/versions/0.3.1_update_tables.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/migrations/versions/0.3.2_update_tables.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/migrations/versions/0.3.3_update_tables.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/migrations/versions/0.3.4_update_tables.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/migrations/versions/0.3.5_update_tables.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/migrations/versions/0.3.6_update_tables.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/migrations/versions/0.3.7_update_tables.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/migrations/versions/0.3.8_update_tables.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/migrations/versions/0.4.0_update_tables.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/migrations/versions/0.5.0_update_tables.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/migrations/versions/0.5.1_update_tables.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/migrations/versions/0.5.2_update_tables.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/migrations/versions/0.5.3_update_tables.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/migrations/versions/0.5.4_update_tables.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/migrations/versions/0.5.5_update_tables.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/migrations/versions/0.6.0_update_tables.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/migrations/versions/0.6.1_update_tables.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/migrations/versions/0.6.2_update_tables.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/migrations/versions/0.6.3_update_tables.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/migrations/versions/0.6.4_update_tables.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/migrations/versions/0.6.5_update_tables.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/migrations/versions/0.7.0_update_tables.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/migrations/versions/0.7.1_update_tables.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/migrations/versions/0.7.2_update_tables.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/migrations/versions/0.7.3_update_tables.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/migrations/versions/0.8.0_update_tables.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/migrations/versions/0.9.0_update_tables.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/migrations/versions/0.9.1_update_tables.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/migrations/versions/0.9.2_update_tables.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/migrations/versions/0.9.3_update_tables.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/migrations/versions/14c72daea083_query_add_column_updated_at.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/migrations/versions/c7c8541fa741_query_add_column_added_at.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/migrations/versions/d14f179e553c_file_add_composite_index_dataset_id_.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/migrations/versions/e7edab5d4e4b_add_dataset_tracking.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/models/__init__.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/models/base.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/models/dataset.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/models/facet.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/models/file.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/models/options.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/models/query.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/models/selection.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/models/sql.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/models/synda_file.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/models/tag.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/models/utils.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/plugin.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/processor.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/py.typed +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/result.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/utils.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/esgpull/version.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/pdm.lock +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/tests/__init__.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/tests/assets/error_plugin.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/tests/assets/incompatible_plugin.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/tests/assets/priority_test_plugin.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/tests/assets/sample_plugin.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/tests/cli/__init__.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/tests/cli/test_parse.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/tests/cli/test_plugin_cli.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/tests/cli/test_show_dates.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/tests/conftest.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/tests/test_config.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/tests/test_dataset.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/tests/test_db.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/tests/test_esgpull.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/tests/test_fs.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/tests/test_graph.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/tests/test_plugin.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/tests/test_processor.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/tests/test_query.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/tests/test_selection.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/tests/test_synda.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/tests/test_utils.py +0 -0
- {esgpull-0.9.3 → esgpull-0.9.5}/tests/utils.py +0 -0
|
@@ -9,6 +9,8 @@ on:
|
|
|
9
9
|
- esgpull/**
|
|
10
10
|
- tests/**
|
|
11
11
|
- .github/workflows/ci.yml
|
|
12
|
+
- pyproject.toml
|
|
13
|
+
- uv.lock
|
|
12
14
|
pull_request:
|
|
13
15
|
branches:
|
|
14
16
|
- main
|
|
@@ -17,6 +19,8 @@ on:
|
|
|
17
19
|
- esgpull/**
|
|
18
20
|
- tests/**
|
|
19
21
|
- .github/workflows/ci.yml
|
|
22
|
+
- pyproject.toml
|
|
23
|
+
- uv.lock
|
|
20
24
|
|
|
21
25
|
jobs:
|
|
22
26
|
tests:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: esgpull
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.5
|
|
4
4
|
Summary: ESGF data discovery, download, replication tool
|
|
5
5
|
Project-URL: Repository, https://github.com/ESGF/esgf-download
|
|
6
6
|
Project-URL: Documentation, https://esgf.github.io/esgf-download/
|
|
@@ -31,13 +31,13 @@ Requires-Dist: pyparsing>=3.0.9
|
|
|
31
31
|
Requires-Dist: pyyaml>=6.0
|
|
32
32
|
Requires-Dist: rich>=12.6.0
|
|
33
33
|
Requires-Dist: setuptools>=65.4.1
|
|
34
|
-
Requires-Dist: sqlalchemy
|
|
34
|
+
Requires-Dist: sqlalchemy<2.1,>=2.0.0b2
|
|
35
35
|
Requires-Dist: tomlkit>=0.11.5
|
|
36
36
|
Description-Content-Type: text/markdown
|
|
37
37
|
|
|
38
38
|
# esgpull - ESGF data management utility
|
|
39
39
|
|
|
40
|
-
[](https://github.com/astral-sh/uv)
|
|
41
41
|
|
|
42
42
|
`esgpull` is a tool that simplifies usage of the [ESGF Search API](https://esgf.github.io/esg-search/ESGF_Search_RESTful_API.html) for data discovery, and manages procedures related to downloading and storing files from ESGF.
|
|
43
43
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# esgpull - ESGF data management utility
|
|
2
2
|
|
|
3
|
-
[](https://github.com/astral-sh/uv)
|
|
4
4
|
|
|
5
5
|
`esgpull` is a tool that simplifies usage of the [ESGF Search API](https://esgf.github.io/esg-search/ESGF_Search_RESTful_API.html) for data discovery, and manages procedures related to downloading and storing files from ESGF.
|
|
6
6
|
|
|
@@ -134,18 +134,46 @@ class Result:
|
|
|
134
134
|
solr_terms: list[str] = []
|
|
135
135
|
for name, values in self.query.selection.items():
|
|
136
136
|
if index.is_bridge():
|
|
137
|
-
|
|
137
|
+
if name == "query":
|
|
138
|
+
solr_terms.append(" ".join(values))
|
|
139
|
+
elif name.startswith("!"):
|
|
140
|
+
value_term = " ".join(quote_str(v) for v in values)
|
|
141
|
+
if len(values) > 1:
|
|
142
|
+
value_term = f"({value_term})"
|
|
143
|
+
solr_terms.append(f"NOT ({name[1:]}:{value_term})")
|
|
144
|
+
else:
|
|
145
|
+
has_wildcard = any("*" in v for v in values)
|
|
146
|
+
no_wildcard = any("*" not in v for v in values)
|
|
147
|
+
|
|
148
|
+
if has_wildcard and no_wildcard:
|
|
149
|
+
logger.warning(
|
|
150
|
+
(
|
|
151
|
+
f"Facet {name} has mixed wildcard/non-wildcard values. "
|
|
152
|
+
"Non-wildcard values may match partially."
|
|
153
|
+
)
|
|
154
|
+
)
|
|
155
|
+
value_term = " ".join(quote_str(v) for v in values)
|
|
156
|
+
if len(values) > 1:
|
|
157
|
+
value_term = f"({value_term})"
|
|
158
|
+
solr_terms.append(f"{name}:{value_term}")
|
|
159
|
+
elif has_wildcard:
|
|
160
|
+
value_term = " ".join(quote_str(v) for v in values)
|
|
161
|
+
if len(values) > 1:
|
|
162
|
+
value_term = f"({value_term})"
|
|
163
|
+
solr_terms.append(f"{name}:{value_term}")
|
|
164
|
+
else:
|
|
165
|
+
params[name] = ",".join(values)
|
|
138
166
|
else:
|
|
139
167
|
value_term = " ".join(values)
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
else:
|
|
143
|
-
if len(values) > 1:
|
|
144
|
-
value_term = f"({value_term})"
|
|
145
|
-
if name.startswith("!"):
|
|
146
|
-
solr_terms.append(f"NOT ({name[1:]}:{value_term})")
|
|
168
|
+
if name == "query":
|
|
169
|
+
solr_terms.append(value_term)
|
|
147
170
|
else:
|
|
148
|
-
|
|
171
|
+
if len(values) > 1:
|
|
172
|
+
value_term = f"({value_term})"
|
|
173
|
+
if name.startswith("!"):
|
|
174
|
+
solr_terms.append(f"NOT ({name[1:]}:{value_term})")
|
|
175
|
+
else:
|
|
176
|
+
solr_terms.append(f"{name}:{value_term}")
|
|
149
177
|
if solr_terms:
|
|
150
178
|
params["query"] = " AND ".join(solr_terms)
|
|
151
179
|
for name, option in self.query.options.items(use_default=True):
|
|
@@ -562,6 +590,7 @@ class Context:
|
|
|
562
590
|
) -> list[File]:
|
|
563
591
|
files: list[File] = []
|
|
564
592
|
shas: set[str] = set()
|
|
593
|
+
file_ids: set[str] = set()
|
|
565
594
|
async for result in self._fetch(*results):
|
|
566
595
|
files_result = result.to(ResultFiles)
|
|
567
596
|
files_result.process()
|
|
@@ -569,9 +598,13 @@ class Context:
|
|
|
569
598
|
for file in files_result.data:
|
|
570
599
|
if not keep_duplicates and file.sha in shas:
|
|
571
600
|
logger.debug(f"Duplicate file {file.file_id}")
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
601
|
+
continue
|
|
602
|
+
if not keep_duplicates and file.file_id in file_ids:
|
|
603
|
+
logger.debug(f"Duplicate file_id {file.file_id}")
|
|
604
|
+
continue
|
|
605
|
+
files.append(file)
|
|
606
|
+
shas.add(file.sha)
|
|
607
|
+
file_ids.add(file.file_id)
|
|
575
608
|
return files
|
|
576
609
|
|
|
577
610
|
async def _search_as_queries(
|
|
@@ -54,7 +54,7 @@ from esgpull.plugin import (
|
|
|
54
54
|
)
|
|
55
55
|
from esgpull.processor import Processor
|
|
56
56
|
from esgpull.result import Err, Ok, Result
|
|
57
|
-
from esgpull.tui import UI, DummyLive, Verbosity, logger
|
|
57
|
+
from esgpull.tui import UI, DummyLive, ErrorCountColumn, Verbosity, logger
|
|
58
58
|
from esgpull.utils import format_size
|
|
59
59
|
|
|
60
60
|
|
|
@@ -387,6 +387,7 @@ class Esgpull:
|
|
|
387
387
|
SpinnerColumn(),
|
|
388
388
|
MofNCompleteColumn(),
|
|
389
389
|
TimeRemainingColumn(compact=True, elapsed_when_finished=True),
|
|
390
|
+
ErrorCountColumn(),
|
|
390
391
|
)
|
|
391
392
|
file_columns: list[str | ProgressColumn] = [
|
|
392
393
|
TextColumn("[cyan][{task.id}] [b blue]{task.fields[sha]}"),
|
|
@@ -434,7 +435,9 @@ class Esgpull:
|
|
|
434
435
|
if use_db:
|
|
435
436
|
self.db.add(*processor.files)
|
|
436
437
|
queue_size = len(processor.tasks)
|
|
437
|
-
main_task_id = main_progress.add_task(
|
|
438
|
+
main_task_id = main_progress.add_task(
|
|
439
|
+
"", total=queue_size, nb_errors=0
|
|
440
|
+
)
|
|
438
441
|
# TODO: rename ? installed/downloaded/completed/...
|
|
439
442
|
files: list[File] = []
|
|
440
443
|
errors: list[Err] = []
|
|
@@ -475,11 +478,13 @@ class Esgpull:
|
|
|
475
478
|
)
|
|
476
479
|
case Err(_, err):
|
|
477
480
|
queue_size -= 1
|
|
478
|
-
main_progress.update(
|
|
479
|
-
main_task_id, total=queue_size
|
|
480
|
-
)
|
|
481
481
|
result.data.file.status = FileStatus.Error
|
|
482
482
|
errors.append(result)
|
|
483
|
+
main_progress.update(
|
|
484
|
+
main_task_id,
|
|
485
|
+
total=queue_size,
|
|
486
|
+
nb_errors=len(errors),
|
|
487
|
+
)
|
|
483
488
|
emit(
|
|
484
489
|
Event.file_error,
|
|
485
490
|
file=result.data.file,
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""update tables
|
|
2
|
+
|
|
3
|
+
Revision ID: 0.9.4
|
|
4
|
+
Revises: 0.9.3
|
|
5
|
+
Create Date: 2026-01-14 10:49:04.536961
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
from alembic import op
|
|
9
|
+
import sqlalchemy as sa
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# revision identifiers, used by Alembic.
|
|
13
|
+
revision = '0.9.4'
|
|
14
|
+
down_revision = '0.9.3'
|
|
15
|
+
branch_labels = None
|
|
16
|
+
depends_on = None
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def upgrade() -> None:
|
|
20
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
|
21
|
+
pass
|
|
22
|
+
# ### end Alembic commands ###
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def downgrade() -> None:
|
|
26
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
|
27
|
+
pass
|
|
28
|
+
# ### end Alembic commands ###
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""update tables
|
|
2
|
+
|
|
3
|
+
Revision ID: 0.9.5
|
|
4
|
+
Revises: 0.9.4
|
|
5
|
+
Create Date: 2026-02-04 15:52:02.010431
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
from alembic import op
|
|
9
|
+
import sqlalchemy as sa
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# revision identifiers, used by Alembic.
|
|
13
|
+
revision = '0.9.5'
|
|
14
|
+
down_revision = '0.9.4'
|
|
15
|
+
branch_labels = None
|
|
16
|
+
depends_on = None
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def upgrade() -> None:
|
|
20
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
|
21
|
+
pass
|
|
22
|
+
# ### end Alembic commands ###
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def downgrade() -> None:
|
|
26
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
|
27
|
+
pass
|
|
28
|
+
# ### end Alembic commands ###
|
|
@@ -101,6 +101,17 @@ class ExceptionToDebugFilter(logging.Filter):
|
|
|
101
101
|
return True
|
|
102
102
|
|
|
103
103
|
|
|
104
|
+
class ErrorCountColumn(ProgressColumn):
|
|
105
|
+
def render(self, task):
|
|
106
|
+
nb_errors = task.fields.get("nb_errors", 0)
|
|
107
|
+
|
|
108
|
+
if nb_errors == 0:
|
|
109
|
+
return Text("")
|
|
110
|
+
|
|
111
|
+
suffix = "" if nb_errors == 1 else "s"
|
|
112
|
+
return Text(f"({nb_errors} download{suffix} failed)", style="red")
|
|
113
|
+
|
|
114
|
+
|
|
104
115
|
@define
|
|
105
116
|
class UI:
|
|
106
117
|
path: Path = field(converter=Path)
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "esgpull"
|
|
7
|
-
version = "0.9.
|
|
7
|
+
version = "0.9.5"
|
|
8
8
|
classifiers = [
|
|
9
9
|
"License :: OSI Approved :: BSD License",
|
|
10
10
|
"Programming Language :: Python :: 3",
|
|
@@ -27,7 +27,7 @@ dependencies = [
|
|
|
27
27
|
"pyyaml>=6.0",
|
|
28
28
|
"tomlkit>=0.11.5",
|
|
29
29
|
"rich>=12.6.0",
|
|
30
|
-
"sqlalchemy>=2.0.0b2",
|
|
30
|
+
"sqlalchemy>=2.0.0b2,<2.1",
|
|
31
31
|
"setuptools>=65.4.1",
|
|
32
32
|
"aiostream>=0.4.5",
|
|
33
33
|
"attrs>=22.1.0",
|
|
@@ -14,24 +14,24 @@ aiofiles==25.1.0
|
|
|
14
14
|
# via esgpull
|
|
15
15
|
aiostream==0.7.1
|
|
16
16
|
# via esgpull
|
|
17
|
-
alembic==1.
|
|
17
|
+
alembic==1.18.3
|
|
18
18
|
# via esgpull
|
|
19
19
|
annotated-types==0.7.0
|
|
20
20
|
# via pydantic
|
|
21
|
-
anyio==4.
|
|
21
|
+
anyio==4.12.1
|
|
22
22
|
# via httpx
|
|
23
23
|
asttokens==3.0.1
|
|
24
24
|
# via stack-data
|
|
25
25
|
attrs==25.4.0
|
|
26
26
|
# via cattrs
|
|
27
27
|
# via esgpull
|
|
28
|
-
babel==2.
|
|
28
|
+
babel==2.18.0
|
|
29
29
|
# via mkdocs-material
|
|
30
30
|
backrefs==6.1
|
|
31
31
|
# via mkdocs-material
|
|
32
32
|
cattrs==25.3.0
|
|
33
33
|
# via esgpull
|
|
34
|
-
certifi==
|
|
34
|
+
certifi==2026.1.4
|
|
35
35
|
# via httpcore
|
|
36
36
|
# via httpx
|
|
37
37
|
# via requests
|
|
@@ -49,18 +49,18 @@ colorama==0.4.6
|
|
|
49
49
|
# via mkdocs-material
|
|
50
50
|
comm==0.2.3
|
|
51
51
|
# via ipykernel
|
|
52
|
-
coverage==7.
|
|
52
|
+
coverage==7.13.3
|
|
53
53
|
# via pytest-cov
|
|
54
|
-
cryptography==46.0.
|
|
54
|
+
cryptography==46.0.4
|
|
55
55
|
# via pyopenssl
|
|
56
|
-
debugpy==1.8.
|
|
56
|
+
debugpy==1.8.20
|
|
57
57
|
# via ipykernel
|
|
58
58
|
decorator==5.2.1
|
|
59
59
|
# via ipdb
|
|
60
60
|
# via ipython
|
|
61
61
|
deprecated==1.3.1
|
|
62
62
|
# via click-params
|
|
63
|
-
exceptiongroup==1.3.
|
|
63
|
+
exceptiongroup==1.3.1
|
|
64
64
|
# via anyio
|
|
65
65
|
# via cattrs
|
|
66
66
|
# via ipython
|
|
@@ -69,11 +69,11 @@ execnet==2.1.2
|
|
|
69
69
|
# via pytest-xdist
|
|
70
70
|
executing==2.2.1
|
|
71
71
|
# via stack-data
|
|
72
|
-
filelock==3.20.
|
|
72
|
+
filelock==3.20.3
|
|
73
73
|
# via pytest-mypy
|
|
74
74
|
ghp-import==2.1.0
|
|
75
75
|
# via mkdocs
|
|
76
|
-
greenlet==3.
|
|
76
|
+
greenlet==3.3.1
|
|
77
77
|
# via sqlalchemy
|
|
78
78
|
h11==0.16.0
|
|
79
79
|
# via httpcore
|
|
@@ -90,7 +90,7 @@ iniconfig==2.3.0
|
|
|
90
90
|
ipdb==0.13.13
|
|
91
91
|
ipykernel==7.1.0
|
|
92
92
|
# via jupyter-console
|
|
93
|
-
ipython==8.
|
|
93
|
+
ipython==8.38.0
|
|
94
94
|
# via ipdb
|
|
95
95
|
# via ipykernel
|
|
96
96
|
# via jupyter-console
|
|
@@ -99,7 +99,7 @@ jedi==0.19.2
|
|
|
99
99
|
jinja2==3.1.6
|
|
100
100
|
# via mkdocs
|
|
101
101
|
# via mkdocs-material
|
|
102
|
-
jupyter-client==8.
|
|
102
|
+
jupyter-client==8.8.0
|
|
103
103
|
# via ipykernel
|
|
104
104
|
# via jupyter-console
|
|
105
105
|
jupyter-console==6.6.3
|
|
@@ -107,9 +107,11 @@ jupyter-core==5.9.1
|
|
|
107
107
|
# via ipykernel
|
|
108
108
|
# via jupyter-client
|
|
109
109
|
# via jupyter-console
|
|
110
|
+
librt==0.7.8
|
|
111
|
+
# via mypy
|
|
110
112
|
mako==1.3.10
|
|
111
113
|
# via alembic
|
|
112
|
-
markdown==3.10
|
|
114
|
+
markdown==3.10.1
|
|
113
115
|
# via mkdocs
|
|
114
116
|
# via mkdocs-material
|
|
115
117
|
# via pymdown-extensions
|
|
@@ -131,18 +133,18 @@ mkdocs==1.6.1
|
|
|
131
133
|
# via mkdocs-material
|
|
132
134
|
mkdocs-get-deps==0.2.0
|
|
133
135
|
# via mkdocs
|
|
134
|
-
mkdocs-material==9.7.
|
|
136
|
+
mkdocs-material==9.7.1
|
|
135
137
|
mkdocs-material-extensions==1.3.1
|
|
136
138
|
# via mkdocs-material
|
|
137
|
-
mypy==1.
|
|
139
|
+
mypy==1.19.1
|
|
138
140
|
# via pytest-mypy
|
|
139
141
|
mypy-extensions==1.1.0
|
|
140
142
|
# via mypy
|
|
141
143
|
nest-asyncio==1.6.0
|
|
142
144
|
# via esgpull
|
|
143
145
|
# via ipykernel
|
|
144
|
-
orjson==3.11.
|
|
145
|
-
packaging==
|
|
146
|
+
orjson==3.11.7
|
|
147
|
+
packaging==26.0
|
|
146
148
|
# via esgpull
|
|
147
149
|
# via ipykernel
|
|
148
150
|
# via mkdocs
|
|
@@ -151,12 +153,12 @@ paginate==0.5.7
|
|
|
151
153
|
# via mkdocs-material
|
|
152
154
|
parso==0.8.5
|
|
153
155
|
# via jedi
|
|
154
|
-
pathspec==0.
|
|
156
|
+
pathspec==1.0.4
|
|
155
157
|
# via mkdocs
|
|
156
158
|
# via mypy
|
|
157
159
|
pexpect==4.9.0
|
|
158
160
|
# via ipython
|
|
159
|
-
platformdirs==4.5.
|
|
161
|
+
platformdirs==4.5.1
|
|
160
162
|
# via esgpull
|
|
161
163
|
# via jupyter-core
|
|
162
164
|
# via mkdocs-get-deps
|
|
@@ -166,15 +168,15 @@ pluggy==1.6.0
|
|
|
166
168
|
prompt-toolkit==3.0.52
|
|
167
169
|
# via ipython
|
|
168
170
|
# via jupyter-console
|
|
169
|
-
psutil==7.
|
|
171
|
+
psutil==7.2.2
|
|
170
172
|
# via ipykernel
|
|
171
173
|
ptyprocess==0.7.0
|
|
172
174
|
# via pexpect
|
|
173
175
|
pure-eval==0.2.3
|
|
174
176
|
# via stack-data
|
|
175
|
-
pycparser==
|
|
177
|
+
pycparser==3.0
|
|
176
178
|
# via cffi
|
|
177
|
-
pydantic==2.12.
|
|
179
|
+
pydantic==2.12.5
|
|
178
180
|
# via esgpull
|
|
179
181
|
# via pydantic-settings
|
|
180
182
|
pydantic-core==2.41.5
|
|
@@ -187,13 +189,13 @@ pygments==2.19.2
|
|
|
187
189
|
# via mkdocs-material
|
|
188
190
|
# via pytest
|
|
189
191
|
# via rich
|
|
190
|
-
pymdown-extensions==10.
|
|
192
|
+
pymdown-extensions==10.20.1
|
|
191
193
|
# via mkdocs-material
|
|
192
194
|
pyopenssl==25.3.0
|
|
193
195
|
# via esgpull
|
|
194
|
-
pyparsing==3.2
|
|
196
|
+
pyparsing==3.3.2
|
|
195
197
|
# via esgpull
|
|
196
|
-
pytest==9.0.
|
|
198
|
+
pytest==9.0.2
|
|
197
199
|
# via pytest-cov
|
|
198
200
|
# via pytest-mypy
|
|
199
201
|
# via pytest-xdist
|
|
@@ -219,28 +221,26 @@ pyzmq==27.1.0
|
|
|
219
221
|
# via jupyter-console
|
|
220
222
|
requests==2.32.5
|
|
221
223
|
# via mkdocs-material
|
|
222
|
-
rich==14.2
|
|
224
|
+
rich==14.3.2
|
|
223
225
|
# via esgpull
|
|
224
|
-
setuptools==80.
|
|
226
|
+
setuptools==80.10.2
|
|
225
227
|
# via esgpull
|
|
226
228
|
six==1.17.0
|
|
227
229
|
# via python-dateutil
|
|
228
|
-
|
|
229
|
-
# via anyio
|
|
230
|
-
sqlalchemy==2.0.44
|
|
230
|
+
sqlalchemy==2.0.46
|
|
231
231
|
# via alembic
|
|
232
232
|
# via esgpull
|
|
233
233
|
stack-data==0.6.3
|
|
234
234
|
# via ipython
|
|
235
|
-
tomli==2.
|
|
235
|
+
tomli==2.4.0
|
|
236
236
|
# via alembic
|
|
237
237
|
# via coverage
|
|
238
238
|
# via ipdb
|
|
239
239
|
# via mypy
|
|
240
240
|
# via pytest
|
|
241
|
-
tomlkit==0.
|
|
241
|
+
tomlkit==0.14.0
|
|
242
242
|
# via esgpull
|
|
243
|
-
tornado==6.5.
|
|
243
|
+
tornado==6.5.4
|
|
244
244
|
# via ipykernel
|
|
245
245
|
# via jupyter-client
|
|
246
246
|
traitlets==5.14.3
|
|
@@ -269,13 +269,13 @@ typing-extensions==4.15.0
|
|
|
269
269
|
typing-inspection==0.4.2
|
|
270
270
|
# via pydantic
|
|
271
271
|
# via pydantic-settings
|
|
272
|
-
urllib3==2.
|
|
272
|
+
urllib3==2.6.3
|
|
273
273
|
# via requests
|
|
274
274
|
validators==0.22.0
|
|
275
275
|
# via click-params
|
|
276
276
|
watchdog==6.0.0
|
|
277
277
|
# via mkdocs
|
|
278
|
-
wcwidth==0.
|
|
278
|
+
wcwidth==0.5.3
|
|
279
279
|
# via prompt-toolkit
|
|
280
|
-
wrapt==2.
|
|
280
|
+
wrapt==2.1.1
|
|
281
281
|
# via deprecated
|
|
@@ -14,18 +14,18 @@ aiofiles==25.1.0
|
|
|
14
14
|
# via esgpull
|
|
15
15
|
aiostream==0.7.1
|
|
16
16
|
# via esgpull
|
|
17
|
-
alembic==1.
|
|
17
|
+
alembic==1.18.3
|
|
18
18
|
# via esgpull
|
|
19
19
|
annotated-types==0.7.0
|
|
20
20
|
# via pydantic
|
|
21
|
-
anyio==4.
|
|
21
|
+
anyio==4.12.1
|
|
22
22
|
# via httpx
|
|
23
23
|
attrs==25.4.0
|
|
24
24
|
# via cattrs
|
|
25
25
|
# via esgpull
|
|
26
26
|
cattrs==25.3.0
|
|
27
27
|
# via esgpull
|
|
28
|
-
certifi==
|
|
28
|
+
certifi==2026.1.4
|
|
29
29
|
# via httpcore
|
|
30
30
|
# via httpx
|
|
31
31
|
cffi==2.0.0
|
|
@@ -35,14 +35,14 @@ click==8.3.1
|
|
|
35
35
|
# via esgpull
|
|
36
36
|
click-params==0.5.0
|
|
37
37
|
# via esgpull
|
|
38
|
-
cryptography==46.0.
|
|
38
|
+
cryptography==46.0.4
|
|
39
39
|
# via pyopenssl
|
|
40
40
|
deprecated==1.3.1
|
|
41
41
|
# via click-params
|
|
42
|
-
exceptiongroup==1.3.
|
|
42
|
+
exceptiongroup==1.3.1
|
|
43
43
|
# via anyio
|
|
44
44
|
# via cattrs
|
|
45
|
-
greenlet==3.
|
|
45
|
+
greenlet==3.3.1
|
|
46
46
|
# via sqlalchemy
|
|
47
47
|
h11==0.16.0
|
|
48
48
|
# via httpcore
|
|
@@ -63,13 +63,13 @@ mdurl==0.1.2
|
|
|
63
63
|
# via markdown-it-py
|
|
64
64
|
nest-asyncio==1.6.0
|
|
65
65
|
# via esgpull
|
|
66
|
-
packaging==
|
|
66
|
+
packaging==26.0
|
|
67
67
|
# via esgpull
|
|
68
|
-
platformdirs==4.5.
|
|
68
|
+
platformdirs==4.5.1
|
|
69
69
|
# via esgpull
|
|
70
|
-
pycparser==
|
|
70
|
+
pycparser==3.0
|
|
71
71
|
# via cffi
|
|
72
|
-
pydantic==2.12.
|
|
72
|
+
pydantic==2.12.5
|
|
73
73
|
# via esgpull
|
|
74
74
|
# via pydantic-settings
|
|
75
75
|
pydantic-core==2.41.5
|
|
@@ -80,24 +80,22 @@ pygments==2.19.2
|
|
|
80
80
|
# via rich
|
|
81
81
|
pyopenssl==25.3.0
|
|
82
82
|
# via esgpull
|
|
83
|
-
pyparsing==3.2
|
|
83
|
+
pyparsing==3.3.2
|
|
84
84
|
# via esgpull
|
|
85
85
|
python-dotenv==1.2.1
|
|
86
86
|
# via pydantic-settings
|
|
87
87
|
pyyaml==6.0.3
|
|
88
88
|
# via esgpull
|
|
89
|
-
rich==14.2
|
|
89
|
+
rich==14.3.2
|
|
90
90
|
# via esgpull
|
|
91
|
-
setuptools==80.
|
|
91
|
+
setuptools==80.10.2
|
|
92
92
|
# via esgpull
|
|
93
|
-
|
|
94
|
-
# via anyio
|
|
95
|
-
sqlalchemy==2.0.44
|
|
93
|
+
sqlalchemy==2.0.46
|
|
96
94
|
# via alembic
|
|
97
95
|
# via esgpull
|
|
98
|
-
tomli==2.
|
|
96
|
+
tomli==2.4.0
|
|
99
97
|
# via alembic
|
|
100
|
-
tomlkit==0.
|
|
98
|
+
tomlkit==0.14.0
|
|
101
99
|
# via esgpull
|
|
102
100
|
typing-extensions==4.15.0
|
|
103
101
|
# via aiostream
|
|
@@ -116,5 +114,5 @@ typing-inspection==0.4.2
|
|
|
116
114
|
# via pydantic-settings
|
|
117
115
|
validators==0.22.0
|
|
118
116
|
# via click-params
|
|
119
|
-
wrapt==2.
|
|
117
|
+
wrapt==2.1.1
|
|
120
118
|
# via deprecated
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from click.testing import CliRunner
|
|
4
|
+
|
|
5
|
+
from esgpull import Esgpull
|
|
6
|
+
from esgpull.cli.download import download
|
|
7
|
+
from esgpull.config import Config
|
|
8
|
+
from esgpull.models import File, FileStatus, Query
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def test_download_errors_in_progress(root: Path, config: Config):
|
|
12
|
+
# Configure the environment
|
|
13
|
+
config.generate(overwrite=True)
|
|
14
|
+
runner = CliRunner()
|
|
15
|
+
esg = Esgpull(root)
|
|
16
|
+
|
|
17
|
+
# Create a query without updating (no datasets will be created)
|
|
18
|
+
query = Query()
|
|
19
|
+
query.compute_sha()
|
|
20
|
+
query.track(query.options.default())
|
|
21
|
+
|
|
22
|
+
# Manually create files
|
|
23
|
+
failing_file = File(
|
|
24
|
+
file_id="failing_file",
|
|
25
|
+
dataset_id="test_dataset_id",
|
|
26
|
+
master_id="test_master_id",
|
|
27
|
+
url="https://nonexistent.path/to/file.nc",
|
|
28
|
+
version="1.0",
|
|
29
|
+
filename="failing.nc",
|
|
30
|
+
local_path="test/failing",
|
|
31
|
+
data_node="test_node",
|
|
32
|
+
checksum="12345",
|
|
33
|
+
checksum_type="SHA256",
|
|
34
|
+
size=1000,
|
|
35
|
+
status=FileStatus.Queued,
|
|
36
|
+
)
|
|
37
|
+
failing_file.compute_sha()
|
|
38
|
+
|
|
39
|
+
# Add files to query
|
|
40
|
+
query.files.append(failing_file)
|
|
41
|
+
|
|
42
|
+
# Add query to database
|
|
43
|
+
esg.db.add(query)
|
|
44
|
+
|
|
45
|
+
# Run the download instruction in the CLI
|
|
46
|
+
result_download = runner.invoke(download)
|
|
47
|
+
|
|
48
|
+
# Parse the output to extract
|
|
49
|
+
output = result_download.output
|
|
50
|
+
assert "download failed" in output
|
|
@@ -22,7 +22,7 @@ def test_update_after_remove(root: Path, config: Config):
|
|
|
22
22
|
"experiment_id:1pctCO2",
|
|
23
23
|
"source_id:CNRM-ESM2-1",
|
|
24
24
|
"--distrib",
|
|
25
|
-
"
|
|
25
|
+
"true",
|
|
26
26
|
"--track",
|
|
27
27
|
],
|
|
28
28
|
)
|
|
@@ -47,7 +47,7 @@ def test_update_after_remove(root: Path, config: Config):
|
|
|
47
47
|
"experiment_id:1pctCO2",
|
|
48
48
|
"source_id:CNRM-ESM2-1",
|
|
49
49
|
"--distrib",
|
|
50
|
-
"
|
|
50
|
+
"true",
|
|
51
51
|
"--track",
|
|
52
52
|
],
|
|
53
53
|
)
|