lockss-turtles 0.6.0.dev14__py3-none-any.whl → 0.6.0.dev15__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.
@@ -5,7 +5,7 @@ Library and command line tool to manage LOCKSS plugin sets and LOCKSS plugin
5
5
  registries.
6
6
  """
7
7
 
8
- __version__ = '0.6.0-dev14'
8
+ __version__ = '0.6.0-dev15'
9
9
 
10
10
  __copyright__ = '''
11
11
  Copyright (c) 2000-2025, Board of Trustees of Leland Stanford Jr. University
lockss/turtles/app.py CHANGED
@@ -36,10 +36,11 @@ from collections.abc import Callable, Iterable
36
36
  from pathlib import Path
37
37
  from typing import ClassVar, Literal, Optional, Union
38
38
 
39
- import yaml
39
+ from exceptiongroup import ExceptionGroup
40
40
  from lockss.pybasic.fileutil import path
41
- from pydantic import BaseModel, Field
41
+ from pydantic import Field, ValidationError
42
42
  import xdg
43
+ import yaml
43
44
 
44
45
  from .plugin import Plugin, PluginIdentifier
45
46
  from .plugin_registry import PluginRegistry, PluginRegistryCatalog, PluginRegistryCatalogKind, PluginRegistryKind, PluginRegistryLayerIdentifier
@@ -104,56 +105,115 @@ class TurtlesApp(object):
104
105
  plugin_registry_path = path(plugin_registry_path_or_str)
105
106
  if plugin_registry_path in map(lambda pr: pr.get_root(), self._plugin_registries):
106
107
  raise ValueError(f'Plugin registries already loaded from: {plugin_registry_path!s}')
108
+ errs, at_least_one = [], False
107
109
  with plugin_registry_path.open('r') as fpr:
108
110
  for yaml_obj in yaml.safe_load_all(fpr):
109
111
  if isinstance(yaml_obj, dict) and yaml_obj.get('kind') in PluginRegistryKind.__args__:
110
- plugin_registry = PluginRegistry(**yaml_obj).initialize(plugin_registry_path.parent)
111
- self._plugin_registries.append(plugin_registry)
112
+ try:
113
+ plugin_registry = PluginRegistry(**yaml_obj).initialize(plugin_registry_path.parent)
114
+ self._plugin_registries.append(plugin_registry)
115
+ at_least_one = True
116
+ except ValidationError as ve:
117
+ errs.append(ve)
118
+ if errs:
119
+ raise ExceptionGroup(f'Errors while loading plugin registries from: {plugin_registry_path!s}', errs)
120
+ if not at_least_one:
121
+ raise ValueError(f'No plugin registries found in: {plugin_registry_path!s}')
112
122
  return self
113
123
 
114
124
  def load_plugin_registry_catalogs(self, plugin_registry_catalog_path_or_str: PathOrStr) -> TurtlesApp:
115
125
  plugin_registry_catalog_path = path(plugin_registry_catalog_path_or_str)
116
126
  if plugin_registry_catalog_path in map(lambda prc: prc.get_root(), self._plugin_registry_catalogs):
117
127
  raise ValueError(f'Plugin registry catalogs already loaded from: {plugin_registry_catalog_path!s}')
128
+ errs, at_least_one = [], False
118
129
  with plugin_registry_catalog_path.open('r') as fprc:
119
130
  for yaml_obj in yaml.safe_load_all(fprc):
120
131
  if isinstance(yaml_obj, dict) and yaml_obj.get('kind') in PluginRegistryCatalogKind.__args__:
121
- plugin_registry_catalog = PluginRegistryCatalog(**yaml_obj).initialize(plugin_registry_catalog_path.parent)
122
- self._plugin_registry_catalogs.append(plugin_registry_catalog)
123
- for plugin_registry_file in plugin_registry_catalog.get_plugin_registry_files():
124
- self.load_plugin_registries(plugin_registry_catalog_path.joinpath(plugin_registry_file))
132
+ try:
133
+ plugin_registry_catalog = PluginRegistryCatalog(**yaml_obj).initialize(plugin_registry_catalog_path.parent)
134
+ self._plugin_registry_catalogs.append(plugin_registry_catalog)
135
+ at_least_one = True
136
+ for plugin_registry_file in plugin_registry_catalog.get_plugin_registry_files():
137
+ try:
138
+ self.load_plugin_registries(plugin_registry_catalog_path.joinpath(plugin_registry_file))
139
+ except ValueError as ve:
140
+ errs.append(ve)
141
+ except ExceptionGroup as eg:
142
+ errs.extend(eg.exceptions)
143
+ except ValidationError as ve:
144
+ errs.append(ve)
145
+ if errs:
146
+ raise ExceptionGroup(f'Errors while loading plugin registry catalogs from: {plugin_registry_catalog_path!s}', errs)
147
+ if not at_least_one:
148
+ raise ValueError(f'No plugin registry catalogs found in: {plugin_registry_catalog_path!s}')
125
149
  return self
126
150
 
127
151
  def load_plugin_set_catalogs(self, plugin_set_catalog_path_or_str: PathOrStr) -> TurtlesApp:
128
152
  plugin_set_catalog_path = path(plugin_set_catalog_path_or_str)
129
153
  if plugin_set_catalog_path in map(lambda psc: psc.get_root(), self._plugin_set_catalogs):
130
154
  raise ValueError(f'Plugin set catalogs already loaded from: {plugin_set_catalog_path!s}')
155
+ errs, at_least_one = [], False
131
156
  with plugin_set_catalog_path.open('r') as fpsc:
132
157
  for yaml_obj in yaml.safe_load_all(fpsc):
133
158
  if isinstance(yaml_obj, dict) and yaml_obj.get('kind') in PluginSetCatalogKind.__args__:
134
- plugin_set_catalog = PluginSetCatalog(**yaml_obj).initialize(plugin_set_catalog_path.parent)
135
- self._plugin_set_catalogs.append(plugin_set_catalog)
136
- for plugin_set_file in plugin_set_catalog.get_plugin_set_files():
137
- self.load_plugin_sets(plugin_set_catalog_path.joinpath(plugin_set_file))
159
+ try:
160
+ plugin_set_catalog = PluginSetCatalog(**yaml_obj).initialize(plugin_set_catalog_path.parent)
161
+ self._plugin_set_catalogs.append(plugin_set_catalog)
162
+ at_least_one = True
163
+ for plugin_set_file in plugin_set_catalog.get_plugin_set_files():
164
+ try:
165
+ self.load_plugin_sets(plugin_set_catalog_path.joinpath(plugin_set_file))
166
+ except ValueError as ve:
167
+ errs.append(ve)
168
+ except ExceptionGroup as eg:
169
+ errs.extend(eg.exceptions)
170
+ except ValidationError as ve:
171
+ errs.append(ve)
172
+ if errs:
173
+ raise ExceptionGroup(f'Errors while loading plugin set catalogs from: {plugin_set_catalog_path!s}', errs)
174
+ if not at_least_one:
175
+ raise ValueError(f'No plugin set catalogs found in: {plugin_set_catalog_path!s}')
138
176
  return self
139
177
 
140
178
  def load_plugin_sets(self, plugin_set_path_or_str: PathOrStr) -> TurtlesApp:
141
179
  plugin_set_path = path(plugin_set_path_or_str)
142
180
  if plugin_set_path in map(lambda ps: ps.get_root(), self._plugin_sets):
143
181
  raise ValueError(f'Plugin sets already loaded from: {plugin_set_path!s}')
182
+ errs, at_least_one = [], False
144
183
  with plugin_set_path.open('r') as fps:
145
184
  for yaml_obj in yaml.safe_load_all(fps):
146
185
  if isinstance(yaml_obj, dict) and yaml_obj.get('kind') in PluginSetKind.__args__:
147
- plugin_set = PluginSet(**yaml_obj).initialize(plugin_set_path.parent)
148
- self._plugin_sets.append(plugin_set)
186
+ try:
187
+ plugin_set = PluginSet(**yaml_obj).initialize(plugin_set_path.parent)
188
+ self._plugin_sets.append(plugin_set)
189
+ at_least_one = True
190
+ except ValidationError as ve:
191
+ errs.append(ve)
192
+ if errs:
193
+ raise ExceptionGroup(f'Errors while loading plugin sets from: {plugin_set_path!s}', errs)
194
+ if not at_least_one:
195
+ raise ValueError(f'No plugin sets found in: {plugin_set_path!s}')
149
196
  return self
150
197
 
151
198
  def load_plugin_signing_credentials(self, plugin_signing_credentials_path_or_str: PathOrStr) -> TurtlesApp:
152
199
  plugin_signing_credentials_path = path(plugin_signing_credentials_path_or_str)
153
200
  if self._plugin_signing_credentials:
154
201
  raise ValueError(f'Plugin signing credentials already loaded from: {self._plugin_signing_credentials.get_root()!s}')
202
+ found = 0
155
203
  with plugin_signing_credentials_path.open('r') as fpsc:
156
- self._plugin_signing_credentials = PluginSigningCredentials(**yaml.safe_load(fpsc)).initialize(plugin_signing_credentials_path.parent)
204
+ for yaml_obj in yaml.safe_load_all(fpsc):
205
+ if isinstance(yaml_obj, dict) and yaml_obj.get('kind') in PluginSigningCredentialsKind.__args__:
206
+ found = found + 1
207
+ if not self._plugin_signing_credentials:
208
+ try:
209
+ plugin_signing_credentials = PluginSigningCredentials(**yaml.safe_load(fpsc)).initialize(plugin_signing_credentials_path.parent)
210
+ self._plugin_signing_credentials = plugin_signing_credentials
211
+ except ValidationError as ve:
212
+ raise ExceptionGroup(f'Errors while loading plugin signing credentials from: {plugin_signing_credentials_path!s}', [ve])
213
+ if found == 0:
214
+ raise ValueError(f'No plugin signing credentials found in: {plugin_signing_credentials_path!s}')
215
+ if found > 1:
216
+ raise ValueError(f'Multiple plugin signing credentials found in: {plugin_signing_credentials_path!s}')
157
217
  return self
158
218
 
159
219
  def release_plugin(self, plugin_ids: list[PluginIdentifier], layer_ids: list[PluginRegistryLayerIdentifier], interactive: bool=False) -> dict[str, list[tuple[str, str, Path, Plugin]]]:
lockss/turtles/cli.py CHANGED
@@ -35,6 +35,7 @@ Tool for managing LOCKSS plugin sets and LOCKSS plugin registries
35
35
  from getpass import getpass
36
36
  from pathlib import Path
37
37
 
38
+ from exceptiongroup import ExceptionGroup
38
39
  from lockss.pybasic.cliutil import BaseCli, StringCommand, COPYRIGHT_DESCRIPTION, LICENSE_DESCRIPTION, VERSION_DESCRIPTION
39
40
  from lockss.pybasic.fileutil import file_lines, path
40
41
  from lockss.pybasic.outpututil import OutputFormatOptions
@@ -239,11 +240,29 @@ class TurtlesCli(BaseCli[TurtlesCommand]):
239
240
  return self._build_plugin(build_plugin_command)
240
241
 
241
242
  def _build_plugin(self, build_plugin_command: BuildPluginCommand) -> None:
243
+ errs = []
242
244
  for psc in build_plugin_command.get_plugin_set_catalogs():
243
- self._app.load_plugin_set_catalogs(psc)
245
+ try:
246
+ self._app.load_plugin_set_catalogs(psc)
247
+ except ValueError as ve:
248
+ errs.append(ve)
249
+ except ExceptionGroup as eg:
250
+ errs.extend(eg.exceptions)
244
251
  for ps in build_plugin_command.get_plugin_sets():
245
- self._app.load_plugin_sets(ps)
246
- self._app.load_plugin_signing_credentials(build_plugin_command.get_plugin_signing_credentials())
252
+ try:
253
+ self._app.load_plugin_sets(ps)
254
+ except ValueError as ve:
255
+ errs.append(ve)
256
+ except ExceptionGroup as eg:
257
+ errs.extend(eg.exceptions)
258
+ try:
259
+ self._app.load_plugin_signing_credentials(build_plugin_command.get_plugin_signing_credentials())
260
+ except ValueError as ve:
261
+ errs.append(ve)
262
+ except ExceptionGroup as eg:
263
+ errs.extend(eg.exceptions)
264
+ if errs:
265
+ raise ExceptionGroup(f'Errors while setting up the environment for building plugins', errs)
247
266
  self._obtain_password(build_plugin_command, non_interactive=build_plugin_command.non_interactive)
248
267
  # Action
249
268
  # ... plugin_id -> (set_id, jar_path, plugin)
@@ -257,10 +276,23 @@ class TurtlesCli(BaseCli[TurtlesCommand]):
257
276
  self._do_string_command(string_command)
258
277
 
259
278
  def _deploy_plugin(self, deploy_plugin_command: DeployPluginCommand) -> None:
279
+ errs = []
260
280
  for prc in deploy_plugin_command.get_plugin_registry_catalogs():
261
- self._app.load_plugin_registry_catalogs(prc)
281
+ try:
282
+ self._app.load_plugin_registry_catalogs(prc)
283
+ except ValueError as ve:
284
+ errs.append(ve)
285
+ except ExceptionGroup as eg:
286
+ errs.extend(eg.exceptions)
262
287
  for pr in deploy_plugin_command.get_plugin_registries():
263
- self._app.load_plugin_registries(pr)
288
+ try:
289
+ self._app.load_plugin_registries(pr)
290
+ except ValueError as ve:
291
+ errs.append(ve)
292
+ except ExceptionGroup as eg:
293
+ errs.extend(eg.exceptions)
294
+ if errs:
295
+ raise ExceptionGroup(f'Errors while setting up the environment for deploying plugins', errs)
264
296
  # Action
265
297
  # ... (src_path, plugin_id) -> list of (registry_id, layer_id, dst_path, plugin)
266
298
  ret = self._app.deploy_plugin(deploy_plugin_command.get_plugin_jars(),
@@ -290,15 +322,43 @@ class TurtlesCli(BaseCli[TurtlesCommand]):
290
322
  self._app.set_password(lambda: _p)
291
323
 
292
324
  def _release_plugin(self, release_plugin_command: ReleasePluginCommand) -> None:
325
+ errs = []
293
326
  for psc in release_plugin_command.get_plugin_set_catalogs():
294
- self._app.load_plugin_set_catalogs(psc)
327
+ try:
328
+ self._app.load_plugin_set_catalogs(psc)
329
+ except ValueError as ve:
330
+ errs.append(ve)
331
+ except ExceptionGroup as eg:
332
+ errs.extend(eg.exceptions)
295
333
  for ps in release_plugin_command.get_plugin_sets():
296
- self._app.load_plugin_sets(ps)
334
+ try:
335
+ self._app.load_plugin_sets(ps)
336
+ except ValueError as ve:
337
+ errs.append(ve)
338
+ except ExceptionGroup as eg:
339
+ errs.extend(eg.exceptions)
297
340
  for prc in release_plugin_command.get_plugin_registry_catalogs():
298
- self._app.load_plugin_registry_catalogs(prc)
341
+ try:
342
+ self._app.load_plugin_registry_catalogs(prc)
343
+ except ValueError as ve:
344
+ errs.append(ve)
345
+ except ExceptionGroup as eg:
346
+ errs.extend(eg.exceptions)
299
347
  for pr in release_plugin_command.get_plugin_registries():
300
- self._app.load_plugin_registries(pr)
301
- self._app.load_plugin_signing_credentials(release_plugin_command.get_plugin_signing_credentials())
348
+ try:
349
+ self._app.load_plugin_registries(pr)
350
+ except ValueError as ve:
351
+ errs.append(ve)
352
+ except ExceptionGroup as eg:
353
+ errs.extend(eg.exceptions)
354
+ try:
355
+ self._app.load_plugin_signing_credentials(release_plugin_command.get_plugin_signing_credentials())
356
+ except ValueError as ve:
357
+ errs.append(ve)
358
+ except ExceptionGroup as eg:
359
+ errs.extend(eg.exceptions)
360
+ if errs:
361
+ raise ExceptionGroup(f'Errors while setting up the environment for deploying plugins', errs)
302
362
  self._obtain_password(release_plugin_command, non_interactive=release_plugin_command.non_interactive)
303
363
  # Action
304
364
  # ... plugin_id -> list of (registry_id, layer_id, dst_path, plugin)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: lockss-turtles
3
- Version: 0.6.0.dev14
3
+ Version: 0.6.0.dev15
4
4
  Summary: Library and command line tool to manage LOCKSS plugin sets and LOCKSS plugin registries
5
5
  License: BSD-3-Clause
6
6
  Author: Thib Guicherd-Callin
@@ -18,9 +18,10 @@ Classifier: Programming Language :: Python
18
18
  Classifier: Topic :: Software Development :: Libraries
19
19
  Classifier: Topic :: System :: Archiving
20
20
  Classifier: Topic :: Utilities
21
+ Requires-Dist: exceptiongroup (>=1.3.0,<1.4.0)
21
22
  Requires-Dist: java-manifest (>=1.1.0,<1.2.0)
22
23
  Requires-Dist: lockss-pybasic (>=0.1.0,<0.2.0)
23
- Requires-Dist: pydantic (>=2.11.0,<3.0.0)
24
+ Requires-Dist: pydantic (>=2.11.0,<2.12.0)
24
25
  Requires-Dist: pyyaml (>=6.0.0,<6.1.0)
25
26
  Requires-Dist: xdg (>=6.0.0,<6.1.0)
26
27
  Project-URL: Documentation, https://docs.lockss.org/en/latest/software/turtles
@@ -1,15 +1,15 @@
1
- lockss/turtles/__init__.py,sha256=hUjYC7qFHhlnjyhcbwLh9SWARTounp6hnf3O6Lv6j8Y,1744
1
+ lockss/turtles/__init__.py,sha256=Kx9eQpAUDSr7GxWmO2xdIfEgnF_dKl5S2X1Lq9axbKU,1744
2
2
  lockss/turtles/__main__.py,sha256=825geLIwXS0LKRqxifJXlLaAZrY8nllXfHzw5ch5ysM,1624
3
- lockss/turtles/app.py,sha256=7jC9fhVxfG9RDM8_yLxWzZ2cx_9HOzFZX3aJ9Np2hbg,13410
4
- lockss/turtles/cli.py,sha256=pLZAG1hmYarCp0R4vHSJcTs3G1umk2esvaLhM5JX7rg,18435
3
+ lockss/turtles/app.py,sha256=vkaHeEGW9B3MjyfHDL6qk8NEpsK8xFVzT2QlHe4gPsk,16701
4
+ lockss/turtles/cli.py,sha256=2gDOn3Kq-opwXkQ_hMhl-imVPfzgt6UQn4i7ulMRgrU,20596
5
5
  lockss/turtles/plugin.py,sha256=re44YVlzXVU8azDshxn7oHw1GdTQLLQgYwkvZlur-60,5384
6
6
  lockss/turtles/plugin_registry.py,sha256=VmvUI6Mx6Jk7fr1L3RfJ4jB6lppCHUm-2PjzwoqxBFk,11920
7
7
  lockss/turtles/plugin_set.py,sha256=hKUXOSRyhHxxcMWE3I69Wykod32Ig871oeJsMTvbXfU,11291
8
8
  lockss/turtles/util.py,sha256=wGCrw_YySvyqaCzT0PItzXpkLHOCMMC_DQHhGU7zudI,2500
9
9
  unittest/lockss/turtles/__init__.py,sha256=hrgWx4GaP-hhPBuRlbLndJnOQmZicKCLaP-dQTCu1sQ,3162
10
10
  unittest/lockss/turtles/test_plugin_set.py,sha256=i-VM8mvrPuW2KqUlh2HPVRtgh3-F7RhmRAwcvhwpoDA,3354
11
- lockss_turtles-0.6.0.dev14.dist-info/LICENSE,sha256=O9ONND4uDxY_jucI4jZDf2liAk05ScEJaYu-Al7EOdQ,1506
12
- lockss_turtles-0.6.0.dev14.dist-info/METADATA,sha256=QERB55qsxPppMaH403Ztmx-D_9LimXphXSu4p0k0BCc,39611
13
- lockss_turtles-0.6.0.dev14.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
14
- lockss_turtles-0.6.0.dev14.dist-info/entry_points.txt,sha256=25BAVFSBRKWAWiXIGZgcr1ypt2mV7nj31Jl8WcNZZOk,51
15
- lockss_turtles-0.6.0.dev14.dist-info/RECORD,,
11
+ lockss_turtles-0.6.0.dev15.dist-info/LICENSE,sha256=O9ONND4uDxY_jucI4jZDf2liAk05ScEJaYu-Al7EOdQ,1506
12
+ lockss_turtles-0.6.0.dev15.dist-info/METADATA,sha256=h5TQdpWbu7p3zJFG4-bmofUYWvd8cmagXv4akEo3FhM,39659
13
+ lockss_turtles-0.6.0.dev15.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
14
+ lockss_turtles-0.6.0.dev15.dist-info/entry_points.txt,sha256=25BAVFSBRKWAWiXIGZgcr1ypt2mV7nj31Jl8WcNZZOk,51
15
+ lockss_turtles-0.6.0.dev15.dist-info/RECORD,,