esgpull 0.9.4__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 CHANGED
@@ -590,6 +590,7 @@ class Context:
590
590
  ) -> list[File]:
591
591
  files: list[File] = []
592
592
  shas: set[str] = set()
593
+ file_ids: set[str] = set()
593
594
  async for result in self._fetch(*results):
594
595
  files_result = result.to(ResultFiles)
595
596
  files_result.process()
@@ -597,9 +598,13 @@ class Context:
597
598
  for file in files_result.data:
598
599
  if not keep_duplicates and file.sha in shas:
599
600
  logger.debug(f"Duplicate file {file.file_id}")
600
- else:
601
- files.append(file)
602
- shas.add(file.sha)
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)
603
608
  return files
604
609
 
605
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("", total=queue_size)
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.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.4
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>=2.0.0b2
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
- [![Rye](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/rye/main/artwork/badge.json)](https://rye.astral.sh)
40
+ [![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](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=LGGnWnKuk9xkUvf5EX3NLbKKRlGvtRe9blps7C-dkTo,26558
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=mqvrXnyCzTSU3j_u5pYidpLs2j86TEFDPX6MhCnNfMs,19458
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=XJs8AUm28YLWl3ephpxY8jHFvG7HrIr08u3RdYvABdE,11338
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
@@ -72,6 +72,7 @@ esgpull/migrations/versions/0.9.1_update_tables.py,sha256=ITewU2qgdCwhorsl2d_t7E
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
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
75
76
  esgpull/migrations/versions/14c72daea083_query_add_column_updated_at.py,sha256=MKqz0tfwGwRkgP4QDd-cpUmXCVr4tM_wlC2BfxqJ1_w,1031
76
77
  esgpull/migrations/versions/c7c8541fa741_query_add_column_added_at.py,sha256=Al_o7fDmoRqc9vBCQgtgrNbSPIOBxdMZ5T-ztakqVeY,1033
77
78
  esgpull/migrations/versions/d14f179e553c_file_add_composite_index_dataset_id_.py,sha256=0vJvttugWmgKns4g-K4i3EU6eid2Z_K2e3H6Ktevf7c,860
@@ -88,8 +89,8 @@ esgpull/models/sql.py,sha256=K8Nre5HKFPjkRzUUW6p6Qk7aG8upbw8C3pnmCFlg7d8,8942
88
89
  esgpull/models/synda_file.py,sha256=6o5unPhzVJGnbpA2MxcS0r-hrBwocHYVnLrqjSGtmuk,2387
89
90
  esgpull/models/tag.py,sha256=5CQDB9rAeCqog63ec9LPFN46HOFNkHPy-maY4gkBQ3E,461
90
91
  esgpull/models/utils.py,sha256=exwlIlIKYjhhfUE82w1kU_HeSQOSY97PTvpkhW0udMA,1631
91
- esgpull-0.9.4.dist-info/METADATA,sha256=MKviUWHQuaz6SVYBYuWPky-4BZ3LBRyWaET0A3i4JaA,3818
92
- esgpull-0.9.4.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
93
- esgpull-0.9.4.dist-info/entry_points.txt,sha256=vyh7HvFrCp4iyMrTkDoSF3weaYrlNj2OJe0Fq5q4QB4,45
94
- esgpull-0.9.4.dist-info/licenses/LICENSE,sha256=lUqGPGWDHHxjkUDuYgjLLY2XQXXn_EHU7fnrQWHGugc,1540
95
- esgpull-0.9.4.dist-info/RECORD,,
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,,