lockss-turtles 0.6.0.dev23__py3-none-any.whl → 0.6.0.dev25__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.
lockss/turtles/cli.py CHANGED
@@ -29,76 +29,186 @@
29
29
  # POSSIBILITY OF SUCH DAMAGE.
30
30
 
31
31
  """
32
- Tool for managing LOCKSS plugin sets and LOCKSS plugin registries
32
+ Command line tool for managing LOCKSS plugin sets and LOCKSS plugin registries.
33
33
  """
34
34
 
35
+ # Remove in Python 3.11; see https://docs.python.org/3.11/library/exceptions.html#exception-groups
36
+ from exceptiongroup import ExceptionGroup
37
+
35
38
  from getpass import getpass
36
39
  from itertools import chain
37
40
  from pathlib import Path
38
41
 
39
- from exceptiongroup import ExceptionGroup
40
42
  from lockss.pybasic.cliutil import BaseCli, StringCommand, COPYRIGHT_DESCRIPTION, LICENSE_DESCRIPTION, VERSION_DESCRIPTION
41
43
  from lockss.pybasic.fileutil import file_lines, path
42
44
  from lockss.pybasic.outpututil import OutputFormatOptions
43
45
  from pydantic.v1 import BaseModel, Field, FilePath
44
- from pydantic.v1.class_validators import validator
45
46
  import tabulate
46
47
  from typing import Optional
47
48
 
48
49
  from . import __copyright__, __license__, __version__
49
- from .app import TurtlesApp
50
+ from .app import Turtles
51
+ from .plugin import PluginIdentifier
50
52
  from .plugin_registry import PluginRegistryLayerIdentifier
51
53
  from .util import file_or
52
54
 
53
55
 
54
56
  class PluginBuildingOptions(BaseModel):
55
- plugin_set: Optional[list[FilePath]] = Field(aliases=['-s'], title='Plugin Sets', description=f'(plugin sets) add one or more plugin set definition files to the loaded plugin sets')
56
- plugin_set_catalog: Optional[list[FilePath]] = Field(aliases=['-S'], title='Plugin Set Catalogs', description=f'(plugin sets) add one or more plugin set catalogs to the loaded plugin set catalogs; if no plugin set catalogs or plugin sets are specified, load {file_or(TurtlesApp.default_plugin_set_catalog_choices())}')
57
- plugin_signing_credentials: Optional[FilePath] = Field(aliases=['-c'], title='Plugin Signing Credentials', description=f'(plugin signing credentials) load the plugin signing credentials from the given file, or if none, from {file_or(TurtlesApp.default_plugin_signing_credentials_choices())}')
58
- plugin_signing_password: Optional[str] = Field(title='Plugin Signing Password', description='(plugin signing credentials) set the plugin signing password, or if none, prompt interactively')
57
+ """
58
+ Pydantic-Argparse (Pydantic v1) model for the ``--plugin-set``/``-s``,
59
+ ``--plugin-set-catalog``/``-S``, ``--plugin-signing-credentials``/``-c``,
60
+ ``--plugin-signing-password`` options.
61
+ """
62
+
63
+ #: The ``--plugin-set``/``-s`` option.
64
+ plugin_set: Optional[list[FilePath]] = Field(aliases=['-s'],
65
+ title='Plugin Sets',
66
+ description=f'(plugin sets) add one or more plugin set definition files to the loaded plugin sets')
67
+
68
+ #: The ``--plugin-set-catalog``/``-S`` option.
69
+ plugin_set_catalog: Optional[list[FilePath]] = Field(aliases=['-S'],
70
+ title='Plugin Set Catalogs',
71
+ description=f'(plugin sets) add one or more plugin set catalogs to the loaded plugin set catalogs; if no plugin set catalogs or plugin sets are specified, load {file_or(Turtles.default_plugin_set_catalog_choices())}')
72
+
73
+ #: The ``--plugin-signing-credentials``/``-c`` option.
74
+ plugin_signing_credentials: Optional[FilePath] = Field(aliases=['-c'],
75
+ title='Plugin Signing Credentials',
76
+ description=f'(plugin signing credentials) load the plugin signing credentials from the given file, or if none, from {file_or(Turtles.default_plugin_signing_credentials_choices())}')
77
+
78
+ #: The ``--plugin-signing-password`` option.
79
+ plugin_signing_password: Optional[str] = Field(title='Plugin Signing Password',
80
+ description='(plugin signing credentials) set the plugin signing password, or if none, prompt interactively')
59
81
 
60
82
  def get_plugin_sets(self) -> list[Path]:
83
+ """
84
+ Returns the cumulative plugin set files.
85
+
86
+ :return: The cumulative plugin set files (possibly an empty list).
87
+ :rtype: list[Path]
88
+ """
61
89
  return [path(p) for p in self.plugin_set or []]
62
90
 
63
91
  def get_plugin_set_catalogs(self) -> list[Path]:
92
+ """
93
+ Returns the cumulative plugin set catalog files.
94
+
95
+ :return: The cumulative plugin set catalog files if any plugin set files
96
+ or plugin set catalog files are specified (possibly an empty
97
+ list), or the first default plugin set catalog file if no
98
+ plugin set files nor plugin set catalog files are specified.
99
+ :rtype: list[Path]
100
+ :raise FileNotFoundError: If no plugin set files nor plugin set catalog
101
+ files are specified, and none of the default
102
+ plugin set catalog file choices exist.
103
+ """
64
104
  if self.plugin_set or self.plugin_set_catalog:
65
105
  return [path(p) for p in self.plugin_set_catalog or []]
66
- if single := TurtlesApp.select_default_plugin_set_catalog():
106
+ if single := Turtles.select_default_plugin_set_catalog():
67
107
  return [single]
68
- raise FileNotFoundError(file_or(TurtlesApp.default_plugin_set_catalog_choices()))
108
+ raise FileNotFoundError(file_or(Turtles.default_plugin_set_catalog_choices()))
69
109
 
70
110
  def get_plugin_signing_credentials(self) -> Path:
111
+ """
112
+ Returns the plugin signing credentials file.
113
+
114
+ :return: The plugin signing credentials file, or the first default
115
+ plugin signing credentials file if not specified.
116
+ :rtype: Path
117
+ :raise FileNotFoundError: If no plugin signing credentials file is
118
+ specified, and none of the default
119
+ plugin signing credentials file choices exist.
120
+ """
71
121
  if self.plugin_signing_credentials:
72
122
  return path(self.plugin_signing_credentials)
73
- if ret := TurtlesApp.select_default_plugin_signing_credentials():
123
+ if ret := Turtles.select_default_plugin_signing_credentials():
74
124
  return ret
75
- raise FileNotFoundError(file_or(TurtlesApp.default_plugin_signing_credentials_choices()))
125
+ raise FileNotFoundError(file_or(Turtles.default_plugin_signing_credentials_choices()))
76
126
 
77
127
 
78
128
  class PluginDeploymentOptions(BaseModel):
79
- plugin_registry: Optional[list[FilePath]] = Field(aliases=['-r'], description=f'(plugin registry) add one or more plugin registries to the loaded plugin registries')
80
- plugin_registry_catalog: Optional[list[FilePath]] = Field(aliases=['-R'], description=f'(plugin registry) add one or more plugin registry catalogs to the loaded plugin registry catalogs; if no plugin registry catalogs or plugin registries are specified, load {file_or(TurtlesApp.default_plugin_registry_catalog_choices())}')
81
- plugin_registry_layer: Optional[list[str]] = Field(aliases=['-l'], description='(plugin registry layers) add one or more plugin registry layers to the set of plugin registry layers to process')
82
- plugin_registry_layers: Optional[list[FilePath]] = Field(aliases=['-L'], description='(plugin registry layers) add the plugin registry layers listed in one or more files to the set of plugin registry layers to process')
83
- testing: Optional[bool] = Field(False, aliases=['-t'], description='(plugin registry layers) synonym for --plugin-registry-layer testing (i.e. add "testing" to the list of plugin registry layers to process)')
84
- production: Optional[bool] = Field(False, aliases=['-p'], description='(plugin registry layers) synonym for --plugin-registry-layer production (i.e. add "production" to the list of plugin registry layers to process)')
129
+ """
130
+ Pydantic-Argparse (Pydantic v1) model for the ``--plugin-registry``/``-r``,
131
+ ``--plugin-registry-catalog``/``-R``, ``--plugin-registry-layer``/``-l``,
132
+ ``--plugin-registry-layers``/``-L``, ``--testing``/``-t``,
133
+ ``--production``/``-P`` options.
134
+ """
85
135
 
86
- @validator('plugin_registry_layers', each_item=True, pre=True)
87
- def _expand_each_plugin_registry_layers_path(cls, v: Path) -> Path:
88
- return path(v)
136
+ #: The ``--plugin-registry``/``-r`` option.
137
+ plugin_registry: Optional[list[FilePath]] = Field(aliases=['-r'],
138
+ title='Plugin Registries',
139
+ description=f'(plugin registry) add one or more plugin registries to the loaded plugin registries')
140
+
141
+ #: The ``--plugin-registry-catalog``/``-R`` option.
142
+ plugin_registry_catalog: Optional[list[FilePath]] = Field(aliases=['-R'],
143
+ title='Plugin Registry Catalogs',
144
+ description=f'(plugin registry) add one or more plugin registry catalogs to the loaded plugin registry catalogs; if no plugin registry catalogs or plugin registries are specified, load {file_or(Turtles.default_plugin_registry_catalog_choices())}')
145
+
146
+ #: The ``--plugin-registry-layer``/``-l`` option.
147
+ plugin_registry_layer: Optional[list[str]] = Field(aliases=['-l'],
148
+ title='Plugin Registry Layer Identifiers',
149
+ description='(plugin registry layers) add one or more plugin registry layers to the set of plugin registry layers to process')
150
+
151
+ #: The ``--plugin-registry-layers``/``-L`` option.
152
+ plugin_registry_layers: Optional[list[FilePath]] = Field(aliases=['-L'],
153
+ title='Files of Plugin Registry Layer Identifiers',
154
+ description='(plugin registry layers) add the plugin registry layers listed in one or more files to the set of plugin registry layers to process')
155
+
156
+ #: The ``--testing``/``-t`` option.
157
+ testing: Optional[bool] = Field(False,
158
+ aliases=['-t'],
159
+ title='Testing Layer',
160
+ description='(plugin registry layers) synonym for --plugin-registry-layer testing (i.e. add "testing" to the list of plugin registry layers to process)')
161
+
162
+ #: The ``--production``/``-P`` option.
163
+ production: Optional[bool] = Field(False,
164
+ aliases=['-p'],
165
+ title='Production Layer',
166
+ description='(plugin registry layers) synonym for --plugin-registry-layer production (i.e. add "production" to the list of plugin registry layers to process)')
89
167
 
90
168
  def get_plugin_registries(self) -> list[Path]:
169
+ """
170
+ Returns the cumulative plugin registry files.
171
+
172
+ :return: The cumulative plugin registry files (possibly an empty list).
173
+ :rtype: list[Path]
174
+ """
91
175
  return [path(p) for p in self.plugin_registry or []]
92
176
 
93
177
  def get_plugin_registry_catalogs(self) -> list[Path]:
178
+ """
179
+ Returns the cumulative plugin registry catalog files.
180
+
181
+ :return: The cumulative plugin registry catalog files if any plugin set
182
+ files or plugin registry catalog files are specified (possibly
183
+ an empty list), or the first default plugin registry catalog
184
+ file if no plugin registry files nor plugin registry catalog
185
+ files are specified.
186
+ :rtype: list[Path]
187
+ :raise FileNotFoundError: If no plugin registry files nor plugin
188
+ registry catalog files are specified, and none
189
+ of the default plugin registry catalog file
190
+ choices exist.
191
+ """
94
192
  if self.plugin_registry or self.plugin_registry_catalog:
95
193
  return [path(p) for p in self.plugin_registry_catalog or []]
96
- if single := TurtlesApp.select_default_plugin_registry_catalog():
194
+ if single := Turtles.select_default_plugin_registry_catalog():
97
195
  return [single]
98
- raise FileNotFoundError(file_or(TurtlesApp.default_plugin_set_catalog_choices()))
196
+ raise FileNotFoundError(file_or(Turtles.default_plugin_set_catalog_choices()))
99
197
 
100
198
  def get_plugin_registry_layers(self) -> list[PluginRegistryLayerIdentifier]:
101
- ret = [*(self.plugin_registry_layer or []), *chain.from_iterable(file_lines(file_path) for file_path in self.plugin_registry_layers or [])]
199
+ """
200
+ Returns the cumulative list of plugin registry layer identifiers, from
201
+ ``plugin_registry_layer`` and the identifiers in
202
+ ``plugin_registry_layers`` files.
203
+
204
+ :return: The cumulative list of plugin registry layer identifiers, from
205
+ ``plugin_registry_layer`` and the identifiers in
206
+ ``plugin_registry_layers`` files.
207
+ :rtype: list[PluginRegistryLayerIdentifier]
208
+ :raise ValueError: If the list of plugin registry layer identifiers is
209
+ empty.
210
+ """
211
+ ret = [*(self.plugin_registry_layer or []), *chain.from_iterable(file_lines(path(file_path)) for file_path in self.plugin_registry_layers or [])]
102
212
  for layer in reversed(['testing', 'production']):
103
213
  if getattr(self, layer, False) and layer not in ret:
104
214
  ret.insert(0, layer)
@@ -109,17 +219,33 @@ class PluginDeploymentOptions(BaseModel):
109
219
 
110
220
  class PluginIdentifierOptions(BaseModel):
111
221
  """
112
- The --identifier/-i and --identifiers/-I options.
222
+ Pydantic-Argparse (Pydantic v1) models for the
223
+ ``--plugin-identifier``/``-i``, ``--plugin-identifiers``/``-I`` options.
113
224
  """
114
- plugin_identifier: Optional[list[str]] = Field(aliases=['-i'], description='(plugin identifiers) add one or more plugin identifiers to the set of plugin identifiers to process')
115
- plugin_identifiers: Optional[list[FilePath]] = Field(aliases=['-I'], description='(plugin identifiers) add the plugin identifiers listed in one or more files to the set of plugin identifiers to process')
116
-
117
- @validator('plugin_identifiers', each_item=True, pre=True)
118
- def _expand_each_plugin_identifiers_path(cls, v: Path) -> Path:
119
- return path(v)
120
225
 
121
- def get_plugin_identifiers(self) -> list[str]:
122
- ret = [*(self.plugin_identifier or []), *chain.from_iterable(file_lines(file_path) for file_path in self.plugin_identifiers or [])]
226
+ #: The ``--plugin-identifier``/``-i`` option.
227
+ plugin_identifier: Optional[list[str]] = Field(aliases=['-i'],
228
+ title='Plugin Identifiers',
229
+ description='(plugin identifiers) add one or more plugin identifiers to the set of plugin identifiers to process')
230
+
231
+ #: The ``--plugin-identifiers``/``-I`` option.
232
+ plugin_identifiers: Optional[list[FilePath]] = Field(aliases=['-I'],
233
+ title='Files of Plugin Identifiers',
234
+ description='(plugin identifiers) add the plugin identifiers listed in one or more files to the set of plugin identifiers to process')
235
+
236
+ def get_plugin_identifiers(self) -> list[PluginIdentifier]:
237
+ """
238
+ Returns the cumulative list of plugin identifiers, from
239
+ ``plugin_identifier`` and the identifiers in ``plugin_identifiers``
240
+ files.
241
+
242
+ :return: The cumulative list of plugin identifiers, from
243
+ ``plugin_identifier`` and the identifiers in
244
+ ``plugin_identifiers`` files.
245
+ :rtype: list[PluginIdentifier]
246
+ :raise ValueError: If the list of plugin identifiers is empty.
247
+ """
248
+ ret = [*(self.plugin_identifier or []), *chain.from_iterable(file_lines(path(file_path)) for file_path in self.plugin_identifiers or [])]
123
249
  if ret:
124
250
  return ret
125
251
  raise ValueError('Empty list of plugin identifiers')
@@ -127,53 +253,116 @@ class PluginIdentifierOptions(BaseModel):
127
253
 
128
254
  class PluginJarOptions(BaseModel):
129
255
  """
130
- The --plugin-jar/-j and --plugin-jars/-J options.
256
+ Pydantic-Argparse (Pydantic v1) model for the ``--plugin-jar``/``-j``,
257
+ ``--plugin-jars``/``-J`` options.
131
258
  """
132
- plugin_jar: Optional[list[FilePath]] = Field(aliases=['-j'], description='(plugin JARs) add one or more plugin JARs to the set of plugin JARs to process')
133
- plugin_jars: Optional[list[FilePath]] = Field(aliases=['-J'], description='(plugin JARs) add the plugin JARs listed in one or more files to the set of plugin JARs to process')
134
259
 
135
- @validator('plugin_jar', 'plugin_jars', each_item=True, pre=True)
136
- def _expand_each_plugin_jars_path(cls, v: Path) -> Path:
137
- return path(v)
138
-
139
- def get_plugin_jars(self):
140
- ret = [*(self.plugin_jar or []), *chain.from_iterable(file_lines(file_path) for file_path in self.plugin_jars or [])]
260
+ #: The ``--plugin-jar``/``-j`` option.
261
+ plugin_jar: Optional[list[FilePath]] = Field(aliases=['-j'],
262
+ title='Plugin JARs',
263
+ description='(plugin JARs) add one or more plugin JARs to the set of plugin JARs to process')
264
+
265
+ #: The ``--plugin-jars``/``-J`` option.
266
+ plugin_jars: Optional[list[FilePath]] = Field(aliases=['-J'],
267
+ title='Files of Plugin JARs',
268
+ description='(plugin JARs) add the plugin JARs listed in one or more files to the set of plugin JARs to process')
269
+
270
+ def get_plugin_jars(self) -> list[Path]:
271
+ """
272
+ Returns the cumulative list of plugin JARs, from ``plugin_jar`` and the
273
+ plugin JARs in ``plugin_jars``
274
+ files.
275
+
276
+ :return: The cumulative list of plugin JARs, from ``plugin_jar`` and the
277
+ plugin JARs in ``plugin_jars`` files.
278
+ :rtype: list[Path]
279
+ :raise ValueError: If the list of plugin JARs is empty.
280
+ """
281
+ ret = [*(self.plugin_jar or []), *chain.from_iterable(file_lines(path(file_path)) for file_path in self.plugin_jars or [])]
141
282
  if len(ret):
142
283
  return ret
143
284
  raise ValueError('Empty list of plugin JARs')
144
285
 
145
286
 
146
287
  class NonInteractiveOptions(BaseModel):
288
+ """
289
+ Pydantic-Argparse (Pydantic v1) model for the ``--non-interactive`` option.
290
+ """
291
+
292
+ #: The ``--non-interactive`` option.
147
293
  non_interactive: Optional[bool] = Field(False,
294
+ title='Non-Interactive',
148
295
  description='(plugin signing credentials) disallow interactive prompts')
149
296
 
150
297
 
151
298
  class TurtlesCommand(BaseModel):
299
+ """
300
+ Pydantic-Argparse (Pydantic v1) model for the ``turtles`` command.
301
+ """
152
302
 
153
- class BuildPluginCommand(OutputFormatOptions, NonInteractiveOptions, PluginBuildingOptions, PluginIdentifierOptions): pass
154
-
155
- class DeployPluginCommand(OutputFormatOptions, NonInteractiveOptions, PluginDeploymentOptions, PluginJarOptions): pass
303
+ class BuildPluginCommand(OutputFormatOptions, NonInteractiveOptions, PluginBuildingOptions, PluginIdentifierOptions):
304
+ """
305
+ Pydantic-Argparse (Pydantic v1) model for the ``build-plugin`` command.
306
+ """
307
+ pass
308
+
309
+ class DeployPluginCommand(OutputFormatOptions, NonInteractiveOptions, PluginDeploymentOptions, PluginJarOptions):
310
+ """
311
+ Pydantic-Argparse (Pydantic v1) model for the ``deploy-plugin`` command.
312
+ """
313
+ pass
314
+
315
+ class ReleasePluginCommand(OutputFormatOptions, NonInteractiveOptions, PluginDeploymentOptions, PluginBuildingOptions, PluginIdentifierOptions):
316
+ """
317
+ Pydantic-Argparse (Pydantic v1) model for the ``release-plugin``
318
+ command.
319
+ """
320
+ pass
321
+
322
+ #: The ``bp`` synonym for the ``build-plugin`` command.
323
+ bp: Optional[BuildPluginCommand] = Field(description='synonym for: build-plugin')
156
324
 
157
- class ReleasePluginCommand(OutputFormatOptions, NonInteractiveOptions, PluginDeploymentOptions, PluginBuildingOptions, PluginIdentifierOptions): pass
325
+ #: The ``build-plugin`` command.
326
+ build_plugin: Optional[BuildPluginCommand] = Field(alias='build-plugin',
327
+ description='build plugins')
158
328
 
159
- bp: Optional[BuildPluginCommand] = Field(description='synonym for: build-plugin')
160
- build_plugin: Optional[BuildPluginCommand] = Field(description='build plugins', alias='build-plugin')
329
+ #: The ``copyright`` command.
161
330
  copyright: Optional[StringCommand.type(__copyright__)] = Field(description=COPYRIGHT_DESCRIPTION)
162
- deploy_plugin: Optional[DeployPluginCommand] = Field(description='deploy plugins', alias='deploy-plugin')
331
+
332
+ #: The ``deploy-plugin`` command.
333
+ deploy_plugin: Optional[DeployPluginCommand] = Field(alias='deploy-plugin',
334
+ description='deploy plugins')
335
+
336
+ #: The ``dp`` synonym for the ``deploy-plugin`` command.
163
337
  dp: Optional[DeployPluginCommand] = Field(description='synonym for: deploy-plugin')
338
+
339
+ #: The ``license`` command.
164
340
  license: Optional[StringCommand.type(__license__)] = Field(description=LICENSE_DESCRIPTION)
165
- release_plugin: Optional[ReleasePluginCommand] = Field(description='release (build and deploy) plugins', alias='release-plugin')
341
+
342
+ #: The ``release-plugin`` command.
343
+ release_plugin: Optional[ReleasePluginCommand] = Field(alias='release-plugin',
344
+ description='release (build and deploy) plugins')
345
+
346
+ #: The ``rp`` synonym for the ``release-plugin`` command.
166
347
  rp: Optional[ReleasePluginCommand] = Field(description='synonym for: release-plugin')
348
+
349
+ #: The ``version`` command.
167
350
  version: Optional[StringCommand.type(__version__)] = Field(description=VERSION_DESCRIPTION)
168
351
 
169
352
 
170
353
  class TurtlesCli(BaseCli[TurtlesCommand]):
354
+ """
355
+ Command line tool for Turtles.
356
+ """
171
357
 
172
358
  def __init__(self):
359
+ """
360
+ Constructor.
361
+ """
173
362
  super().__init__(model=TurtlesCommand,
174
363
  prog='turtles',
175
364
  description='Tool for managing LOCKSS plugin sets and LOCKSS plugin registries')
176
- self._app: TurtlesApp = TurtlesApp()
365
+ self._app: Turtles = Turtles()
177
366
 
178
367
  # def _analyze_registry(self):
179
368
  # # Prerequisites
@@ -233,19 +422,33 @@ class TurtlesCli(BaseCli[TurtlesCommand]):
233
422
  # if len(result) > 0:
234
423
  # self._tabulate(title, result, headers)
235
424
 
236
- def _bp(self, build_plugin_command: TurtlesCommand.BuildPluginCommand) -> None:
237
- return self._build_plugin(build_plugin_command)
425
+ def _bp(self,
426
+ command: TurtlesCommand.BuildPluginCommand) -> None:
427
+ """
428
+ Implementation of the ``bp`` command.
429
+
430
+ :param command: The command object.
431
+ :type command: TurtlesCommand.BuildPluginCommand
432
+ """
433
+ return self._build_plugin(command)
434
+
435
+ def _build_plugin(self,
436
+ command: TurtlesCommand.BuildPluginCommand) -> None:
437
+ """
438
+ Implementation of the ``build-plugin`` command.
238
439
 
239
- def _build_plugin(self, build_plugin_command: TurtlesCommand.BuildPluginCommand) -> None:
440
+ :param command: The command object.
441
+ :type command: TurtlesCommand.BuildPluginCommand
442
+ """
240
443
  errs = []
241
- for psc in build_plugin_command.get_plugin_set_catalogs():
444
+ for psc in command.get_plugin_set_catalogs():
242
445
  try:
243
446
  self._app.load_plugin_set_catalogs(psc)
244
447
  except ValueError as ve:
245
448
  errs.append(ve)
246
449
  except ExceptionGroup as eg:
247
450
  errs.extend(eg.exceptions)
248
- for ps in build_plugin_command.get_plugin_sets():
451
+ for ps in command.get_plugin_sets():
249
452
  try:
250
453
  self._app.load_plugin_sets(ps)
251
454
  except ValueError as ve:
@@ -253,35 +456,49 @@ class TurtlesCli(BaseCli[TurtlesCommand]):
253
456
  except ExceptionGroup as eg:
254
457
  errs.extend(eg.exceptions)
255
458
  try:
256
- self._app.load_plugin_signing_credentials(build_plugin_command.get_plugin_signing_credentials())
459
+ self._app.load_plugin_signing_credentials(command.get_plugin_signing_credentials())
257
460
  except ValueError as ve:
258
461
  errs.append(ve)
259
462
  except ExceptionGroup as eg:
260
463
  errs.extend(eg.exceptions)
261
464
  if errs:
262
465
  raise ExceptionGroup(f'Errors while setting up the environment for building plugins', errs)
263
- self._obtain_password(build_plugin_command, non_interactive=build_plugin_command.non_interactive)
466
+ self._obtain_plugin_signing_password(command, non_interactive=command.non_interactive)
264
467
  # Action
265
468
  # ... plugin_id -> (set_id, jar_path, plugin)
266
- ret = self._app.build_plugin(build_plugin_command.get_plugin_identifiers())
469
+ ret = self._app.build_plugin(command.get_plugin_identifiers())
267
470
  # Output
268
471
  print(tabulate.tabulate([[plugin_id, plugin.get_version(), set_id, jar_path] for plugin_id, (set_id, jar_path, plugin) in ret.items()],
269
472
  headers=['Plugin identifier', 'Plugin version', 'Plugin set', 'Plugin JAR'],
270
- tablefmt=build_plugin_command.output_format))
271
-
272
- def _copyright(self, string_command: StringCommand) -> None:
273
- self._do_string_command(string_command)
274
-
275
- def _deploy_plugin(self, deploy_plugin_command: TurtlesCommand.DeployPluginCommand) -> None:
473
+ tablefmt=command.output_format))
474
+
475
+ def _copyright(self,
476
+ command: StringCommand) -> None:
477
+ """
478
+ Implementation of the ``copyright`` command.
479
+
480
+ :param command: The command object.
481
+ :type command: StringCommand
482
+ """
483
+ self._do_string_command(command)
484
+
485
+ def _deploy_plugin(self,
486
+ command: TurtlesCommand.DeployPluginCommand) -> None:
487
+ """
488
+ Implementation of the ``deploy_plugin`` command.
489
+
490
+ :param command: The command object.
491
+ :type command: TurtlesCommand.DeployPluginCommand
492
+ """
276
493
  errs = []
277
- for prc in deploy_plugin_command.get_plugin_registry_catalogs():
494
+ for prc in command.get_plugin_registry_catalogs():
278
495
  try:
279
496
  self._app.load_plugin_registry_catalogs(prc)
280
497
  except ValueError as ve:
281
498
  errs.append(ve)
282
499
  except ExceptionGroup as eg:
283
500
  errs.extend(eg.exceptions)
284
- for pr in deploy_plugin_command.get_plugin_registries():
501
+ for pr in command.get_plugin_registries():
285
502
  try:
286
503
  self._app.load_plugin_registries(pr)
287
504
  except ValueError as ve:
@@ -292,56 +509,94 @@ class TurtlesCli(BaseCli[TurtlesCommand]):
292
509
  raise ExceptionGroup(f'Errors while setting up the environment for deploying plugins', errs)
293
510
  # Action
294
511
  # ... (src_path, plugin_id) -> list of (registry_id, layer_id, dst_path, plugin)
295
- ret = self._app.deploy_plugin(deploy_plugin_command.get_plugin_jars(),
296
- deploy_plugin_command.get_plugin_registry_layers(),
297
- interactive=not deploy_plugin_command.non_interactive)
512
+ ret = self._app.deploy_plugin(command.get_plugin_jars(),
513
+ command.get_plugin_registry_layers(),
514
+ interactive=not command.non_interactive)
298
515
  # Output
299
516
  print(tabulate.tabulate([[src_path, plugin_id, plugin.get_version(), registry_id, layer_id, dst_path] for (src_path, plugin_id), val in ret.items() for registry_id, layer_id, dst_path, plugin in val],
300
517
  headers=['Plugin JAR', 'Plugin identifier', 'Plugin version', 'Plugin registry', 'Plugin registry layer', 'Deployed JAR'],
301
- tablefmt=deploy_plugin_command.output_format))
302
-
303
- def _do_string_command(self, string_command: StringCommand) -> None:
304
- string_command()
305
-
306
- def _dp(self, deploy_plugin_command: TurtlesCommand.DeployPluginCommand) -> None:
307
- return self._deploy_plugin(deploy_plugin_command)
308
-
309
- def _license(self, string_command: StringCommand) -> None:
310
- self._do_string_command(string_command)
311
-
312
- def _obtain_password(self, plugin_building_options: PluginBuildingOptions, non_interactive: bool=False) -> None:
518
+ tablefmt=command.output_format))
519
+
520
+ def _do_string_command(self,
521
+ command: StringCommand) -> None:
522
+ """
523
+ Implementation of string commands.
524
+
525
+ :param command: The command object.
526
+ :type command: StringCommand
527
+ """
528
+ command()
529
+
530
+ def _dp(self,
531
+ command: TurtlesCommand.DeployPluginCommand) -> None:
532
+ """
533
+ Implementation of the ``dp`` command.
534
+
535
+ :param command: The command object.
536
+ :type command: TurtlesCommand.DeployPluginCommand
537
+ """
538
+ return self._deploy_plugin(command)
539
+
540
+ def _license(self,
541
+ command: StringCommand) -> None:
542
+ """
543
+ Implementation of the ``license`` command.
544
+
545
+ :param command: The command object.
546
+ :type command: StringCommand
547
+ """
548
+ self._do_string_command(command)
549
+
550
+ def _obtain_plugin_signing_password(self,
551
+ plugin_building_options: PluginBuildingOptions,
552
+ non_interactive: bool=False) -> None:
553
+ """
554
+ Ensures the plugin signing password is specified.
555
+
556
+ :param plugin_building_options:
557
+ :type plugin_building_options: PluginBuildingOptions
558
+ :param non_interactive:
559
+ :type non_interactive: bool
560
+ """
313
561
  if plugin_building_options.plugin_signing_password:
314
562
  _p = plugin_building_options.plugin_signing_password
315
563
  elif not non_interactive:
316
564
  _p = getpass('Plugin signing password: ')
317
565
  else:
318
566
  self._parser.error('no plugin signing password specified while in non-interactive mode')
319
- self._app.set_password(lambda: _p)
567
+ self._app.set_plugin_signing_password(lambda: _p)
320
568
 
321
- def _release_plugin(self, release_plugin_command: TurtlesCommand.ReleasePluginCommand) -> None:
569
+ def _release_plugin(self,
570
+ command: TurtlesCommand.ReleasePluginCommand) -> None:
571
+ """
572
+ Implementation of the ``release-plugin`` command.
573
+
574
+ :param command: The command object.
575
+ :type command: TurtlesCommand.ReleasePluginCommand
576
+ """
322
577
  errs = []
323
- for psc in release_plugin_command.get_plugin_set_catalogs():
578
+ for psc in command.get_plugin_set_catalogs():
324
579
  try:
325
580
  self._app.load_plugin_set_catalogs(psc)
326
581
  except ValueError as ve:
327
582
  errs.append(ve)
328
583
  except ExceptionGroup as eg:
329
584
  errs.extend(eg.exceptions)
330
- for ps in release_plugin_command.get_plugin_sets():
585
+ for ps in command.get_plugin_sets():
331
586
  try:
332
587
  self._app.load_plugin_sets(ps)
333
588
  except ValueError as ve:
334
589
  errs.append(ve)
335
590
  except ExceptionGroup as eg:
336
591
  errs.extend(eg.exceptions)
337
- for prc in release_plugin_command.get_plugin_registry_catalogs():
592
+ for prc in command.get_plugin_registry_catalogs():
338
593
  try:
339
594
  self._app.load_plugin_registry_catalogs(prc)
340
595
  except ValueError as ve:
341
596
  errs.append(ve)
342
597
  except ExceptionGroup as eg:
343
598
  errs.extend(eg.exceptions)
344
- for pr in release_plugin_command.get_plugin_registries():
599
+ for pr in command.get_plugin_registries():
345
600
  try:
346
601
  self._app.load_plugin_registries(pr)
347
602
  except ValueError as ve:
@@ -349,34 +604,50 @@ class TurtlesCli(BaseCli[TurtlesCommand]):
349
604
  except ExceptionGroup as eg:
350
605
  errs.extend(eg.exceptions)
351
606
  try:
352
- self._app.load_plugin_signing_credentials(release_plugin_command.get_plugin_signing_credentials())
607
+ self._app.load_plugin_signing_credentials(command.get_plugin_signing_credentials())
353
608
  except ValueError as ve:
354
609
  errs.append(ve)
355
610
  except ExceptionGroup as eg:
356
611
  errs.extend(eg.exceptions)
357
612
  if errs:
358
613
  raise ExceptionGroup(f'Errors while setting up the environment for deploying plugins', errs)
359
- self._obtain_password(release_plugin_command, non_interactive=release_plugin_command.non_interactive)
614
+ self._obtain_plugin_signing_password(command, non_interactive=command.non_interactive)
360
615
  # Action
361
616
  # ... plugin_id -> list of (registry_id, layer_id, dst_path, plugin)
362
- ret = self._app.release_plugin(release_plugin_command.get_plugin_identifiers(),
363
- release_plugin_command.get_plugin_registry_layers(),
364
- interactive=not release_plugin_command.non_interactive)
617
+ ret = self._app.release_plugin(command.get_plugin_identifiers(),
618
+ command.get_plugin_registry_layers(),
619
+ interactive=not command.non_interactive)
365
620
  # Output
366
621
  print(tabulate.tabulate([[plugin_id, plugin.get_version(), registry_id, layer_id, dst_path] for plugin_id, val in ret.items() for registry_id, layer_id, dst_path, plugin in val],
367
622
  headers=['Plugin identifier', 'Plugin version', 'Plugin registry', 'Plugin registry layer', 'Deployed JAR'],
368
- tablefmt=release_plugin_command.output_format))
623
+ tablefmt=command.output_format))
624
+
625
+ def _rp(self, command: TurtlesCommand.ReleasePluginCommand) -> None:
626
+ """
627
+ Implementation of the ``rp`` command.
628
+
629
+ :param command: The command object.
630
+ :type command: TurtlesCommand.ReleasePluginCommand
631
+ """
632
+ self._release_plugin(command)
369
633
 
370
- def _rp(self, release_plugin_command: TurtlesCommand.ReleasePluginCommand) -> None:
371
- self._release_plugin(release_plugin_command)
634
+ def _version(self, command: StringCommand) -> None:
635
+ """
636
+ Implementation of the ``version`` command.
372
637
 
373
- def _version(self, string_command: StringCommand) -> None:
374
- self._do_string_command(string_command)
638
+ :param command: The command object.
639
+ :type command: StringCommand
640
+ """
641
+ self._do_string_command(command)
375
642
 
376
643
 
377
- def main():
644
+ def main() -> None:
645
+ """
646
+ Main entry point of the module.
647
+ """
378
648
  TurtlesCli().run()
379
649
 
380
650
 
651
+ # Main entry point of the module.
381
652
  if __name__ == '__main__':
382
653
  main()