esgpull 0.9.3__py3-none-any.whl → 0.9.5__py3-none-any.whl
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/context.py +45 -12
- esgpull/esgpull.py +10 -5
- esgpull/migrations/versions/0.9.4_update_tables.py +28 -0
- esgpull/migrations/versions/0.9.5_update_tables.py +28 -0
- esgpull/tui.py +11 -0
- {esgpull-0.9.3.dist-info → esgpull-0.9.5.dist-info}/METADATA +3 -3
- {esgpull-0.9.3.dist-info → esgpull-0.9.5.dist-info}/RECORD +10 -8
- {esgpull-0.9.3.dist-info → esgpull-0.9.5.dist-info}/WHEEL +1 -1
- {esgpull-0.9.3.dist-info → esgpull-0.9.5.dist-info}/entry_points.txt +0 -0
- {esgpull-0.9.3.dist-info → esgpull-0.9.5.dist-info}/licenses/LICENSE +0 -0
esgpull/context.py
CHANGED
|
@@ -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(
|
esgpull/esgpull.py
CHANGED
|
@@ -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 ###
|
esgpull/tui.py
CHANGED
|
@@ -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)
|
|
@@ -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,10 +1,10 @@
|
|
|
1
1
|
esgpull/__init__.py,sha256=XItFDIMNmFUNNcKtUgXdfmGwUIWt4AAv0a4mZkfj5P8,240
|
|
2
2
|
esgpull/config.py,sha256=APA3IqYyz_TY2FAm_TNSLsFIkOxmdGnbFLnd2H2YXIs,12042
|
|
3
3
|
esgpull/constants.py,sha256=VlgRJDth5aDjyTopJ2W2JU83353XcRf18RIFAZt7yck,1263
|
|
4
|
-
esgpull/context.py,sha256=
|
|
4
|
+
esgpull/context.py,sha256=nF0ihtfLRw1mm6gIZHYLO_vK-Ga3vgr1I4Qy42Wi2Yo,26819
|
|
5
5
|
esgpull/database.py,sha256=1wGeNbJp0gOLo5Q1N53JfiwVbZ8nfvZVkKlvEaJwOpU,6716
|
|
6
6
|
esgpull/download.py,sha256=aR2c_SOuZtgX7tI2a9_N4Mn86ABq1k7Mxq_BdojFrP4,5600
|
|
7
|
-
esgpull/esgpull.py,sha256=
|
|
7
|
+
esgpull/esgpull.py,sha256=2rBUuKuTBau8fpOA0mRwsFvmVrFAjXX42KKIyfMvpsM,19631
|
|
8
8
|
esgpull/exceptions.py,sha256=wgLyhyIITdusNucPjnnURJX1Jxv1VVIr9PzJV_77qhg,3275
|
|
9
9
|
esgpull/fs.py,sha256=sc7Af2E3yh3V9KVuSPSXFBuFtlQ3L99UZmS1ZJuiBeM,7280
|
|
10
10
|
esgpull/graph.py,sha256=Yl2VuF8PNn0R5xRyEK58Q1Xlx8B1PfhbTwt1JftFDro,15929
|
|
@@ -13,7 +13,7 @@ esgpull/plugin.py,sha256=t6iejis65UREQ71gnj1-gVFhlrGt1z1n3SpJ6KiP57E,18904
|
|
|
13
13
|
esgpull/processor.py,sha256=ubhlKMMOY_ieZEcN9zcDPlmZxQDXqb2QVmeCwWo7zOE,5376
|
|
14
14
|
esgpull/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
15
|
esgpull/result.py,sha256=f64l9gPFpFWgctmHVYrNWJvuXXB1sxpxXzJEIssLXxc,1020
|
|
16
|
-
esgpull/tui.py,sha256=
|
|
16
|
+
esgpull/tui.py,sha256=7V3Qam7jOdB2CEI-j-ioMbWb28yvFEzqwexUGhZgolo,11639
|
|
17
17
|
esgpull/utils.py,sha256=pLMQfY0p2oNIFyCZhHBD74BOAJtmt9QV6dTJ79VsfF8,1213
|
|
18
18
|
esgpull/version.py,sha256=IHT4mKrIr8eV-C3HtmIVD85iGVH25n2ohoff31kaJ1A,93
|
|
19
19
|
esgpull/cli/__init__.py,sha256=W0q_eyhvtPgyX5cXKSDDLUUrskGLzgNoJ9VCY9fJ6pY,1701
|
|
@@ -71,6 +71,8 @@ esgpull/migrations/versions/0.9.0_update_tables.py,sha256=nXfPiyuseD5BXvu59zkeST
|
|
|
71
71
|
esgpull/migrations/versions/0.9.1_update_tables.py,sha256=ITewU2qgdCwhorsl2d_t7ENt_6KecG3z5xfRr_LwrtY,541
|
|
72
72
|
esgpull/migrations/versions/0.9.2_update_tables.py,sha256=aux--HPA_jUtvk7Zb2ZRXRhnRLT-whqZ0lLWt8Apyac,541
|
|
73
73
|
esgpull/migrations/versions/0.9.3_update_tables.py,sha256=-k1CneOa7OTO6xPZ8uR0ccy-4B8TU3kM12-oYKFEOlA,541
|
|
74
|
+
esgpull/migrations/versions/0.9.4_update_tables.py,sha256=tvvXvov7ggXO9A8B5399bixCuM9fSni1SHkJXa5f5II,541
|
|
75
|
+
esgpull/migrations/versions/0.9.5_update_tables.py,sha256=pmLJeJus9-Dmj0geKCpHqrFxlEMLMhPZ_zB7oBLm5rQ,541
|
|
74
76
|
esgpull/migrations/versions/14c72daea083_query_add_column_updated_at.py,sha256=MKqz0tfwGwRkgP4QDd-cpUmXCVr4tM_wlC2BfxqJ1_w,1031
|
|
75
77
|
esgpull/migrations/versions/c7c8541fa741_query_add_column_added_at.py,sha256=Al_o7fDmoRqc9vBCQgtgrNbSPIOBxdMZ5T-ztakqVeY,1033
|
|
76
78
|
esgpull/migrations/versions/d14f179e553c_file_add_composite_index_dataset_id_.py,sha256=0vJvttugWmgKns4g-K4i3EU6eid2Z_K2e3H6Ktevf7c,860
|
|
@@ -87,8 +89,8 @@ esgpull/models/sql.py,sha256=K8Nre5HKFPjkRzUUW6p6Qk7aG8upbw8C3pnmCFlg7d8,8942
|
|
|
87
89
|
esgpull/models/synda_file.py,sha256=6o5unPhzVJGnbpA2MxcS0r-hrBwocHYVnLrqjSGtmuk,2387
|
|
88
90
|
esgpull/models/tag.py,sha256=5CQDB9rAeCqog63ec9LPFN46HOFNkHPy-maY4gkBQ3E,461
|
|
89
91
|
esgpull/models/utils.py,sha256=exwlIlIKYjhhfUE82w1kU_HeSQOSY97PTvpkhW0udMA,1631
|
|
90
|
-
esgpull-0.9.
|
|
91
|
-
esgpull-0.9.
|
|
92
|
-
esgpull-0.9.
|
|
93
|
-
esgpull-0.9.
|
|
94
|
-
esgpull-0.9.
|
|
92
|
+
esgpull-0.9.5.dist-info/METADATA,sha256=KHIghvsCaNoJXZNOj6-MXNDZeQiGnLfI_-WesaZ8I7c,3833
|
|
93
|
+
esgpull-0.9.5.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
94
|
+
esgpull-0.9.5.dist-info/entry_points.txt,sha256=vyh7HvFrCp4iyMrTkDoSF3weaYrlNj2OJe0Fq5q4QB4,45
|
|
95
|
+
esgpull-0.9.5.dist-info/licenses/LICENSE,sha256=lUqGPGWDHHxjkUDuYgjLLY2XQXXn_EHU7fnrQWHGugc,1540
|
|
96
|
+
esgpull-0.9.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|