lockss-turtles 0.6.0.dev19__py3-none-any.whl → 0.6.0.dev21__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/__init__.py +4 -1
- lockss/turtles/app.py +1 -1
- lockss/turtles/cli.py +7 -7
- lockss/turtles/plugin.py +154 -10
- lockss/turtles/plugin_registry.py +6 -7
- lockss/turtles/plugin_set.py +9 -9
- {lockss_turtles-0.6.0.dev19.dist-info → lockss_turtles-0.6.0.dev21.dist-info}/METADATA +2 -2
- lockss_turtles-0.6.0.dev21.dist-info/RECORD +15 -0
- lockss_turtles-0.6.0.dev19.dist-info/RECORD +0 -15
- {lockss_turtles-0.6.0.dev19.dist-info → lockss_turtles-0.6.0.dev21.dist-info}/LICENSE +0 -0
- {lockss_turtles-0.6.0.dev19.dist-info → lockss_turtles-0.6.0.dev21.dist-info}/WHEEL +0 -0
- {lockss_turtles-0.6.0.dev19.dist-info → lockss_turtles-0.6.0.dev21.dist-info}/entry_points.txt +0 -0
lockss/turtles/__init__.py
CHANGED
|
@@ -5,12 +5,15 @@ Library and command line tool to manage LOCKSS plugin sets and LOCKSS plugin
|
|
|
5
5
|
registries.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
#: This package's version.
|
|
9
|
+
__version__ = '0.6.0-dev21'
|
|
9
10
|
|
|
11
|
+
#: This package's copyright.
|
|
10
12
|
__copyright__ = '''
|
|
11
13
|
Copyright (c) 2000-2025, Board of Trustees of Leland Stanford Jr. University
|
|
12
14
|
'''.strip()
|
|
13
15
|
|
|
16
|
+
#: This package's license.
|
|
14
17
|
__license__ = __copyright__ + '\n\n' + '''
|
|
15
18
|
Redistribution and use in source and binary forms, with or without
|
|
16
19
|
modification, are permitted provided that the following conditions are met:
|
lockss/turtles/app.py
CHANGED
|
@@ -74,7 +74,7 @@ class TurtlesApp(object):
|
|
|
74
74
|
|
|
75
75
|
ETC_CONFIG_DIR: ClassVar[Path] = Path('/etc', CONFIG_DIR_NAME)
|
|
76
76
|
|
|
77
|
-
CONFIG_DIRS: ClassVar[tuple[Path, ...]] = (XDG_CONFIG_DIR,
|
|
77
|
+
CONFIG_DIRS: ClassVar[tuple[Path, ...]] = (XDG_CONFIG_DIR, ETC_CONFIG_DIR, USR_CONFIG_DIR)
|
|
78
78
|
|
|
79
79
|
PLUGIN_REGISTRY_CATALOG: ClassVar[str] = 'plugin-registry-catalog.yaml'
|
|
80
80
|
|
lockss/turtles/cli.py
CHANGED
|
@@ -52,10 +52,10 @@ from .util import file_or
|
|
|
52
52
|
|
|
53
53
|
|
|
54
54
|
class PluginBuildingOptions(BaseModel):
|
|
55
|
-
plugin_set: Optional[list[FilePath]] = Field(aliases=['-s'], 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'], 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'], 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(description='(plugin signing credentials) set the plugin signing password, or if none, prompt interactively')
|
|
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')
|
|
59
59
|
|
|
60
60
|
def get_plugin_sets(self) -> list[Path]:
|
|
61
61
|
return [path(p) for p in self.plugin_set or []]
|
|
@@ -119,7 +119,7 @@ class PluginIdentifierOptions(BaseModel):
|
|
|
119
119
|
return path(v)
|
|
120
120
|
|
|
121
121
|
def get_plugin_identifiers(self) -> list[str]:
|
|
122
|
-
ret = [*(self.plugin_identifier or []), *
|
|
122
|
+
ret = [*(self.plugin_identifier or []), *chain.from_iterable(file_lines(file_path) for file_path in self.plugin_identifiers or [])]
|
|
123
123
|
if ret:
|
|
124
124
|
return ret
|
|
125
125
|
raise ValueError('Empty list of plugin identifiers')
|
|
@@ -137,7 +137,7 @@ class PluginJarOptions(BaseModel):
|
|
|
137
137
|
return path(v)
|
|
138
138
|
|
|
139
139
|
def get_plugin_jars(self):
|
|
140
|
-
ret = [*(self.plugin_jar or []), *
|
|
140
|
+
ret = [*(self.plugin_jar or []), *chain.from_iterable(file_lines(file_path) for file_path in self.plugin_jars or [])]
|
|
141
141
|
if len(ret):
|
|
142
142
|
return ret
|
|
143
143
|
raise ValueError('Empty list of plugin JARs')
|
|
@@ -161,7 +161,7 @@ class ReleasePluginCommand(OutputFormatOptions, NonInteractiveOptions, PluginDep
|
|
|
161
161
|
|
|
162
162
|
class TurtlesCommand(BaseModel):
|
|
163
163
|
bp: Optional[BuildPluginCommand] = Field(description='synonym for: build-plugin')
|
|
164
|
-
build_plugin: Optional[BuildPluginCommand] = Field(description='build
|
|
164
|
+
build_plugin: Optional[BuildPluginCommand] = Field(description='build plugins', alias='build-plugin')
|
|
165
165
|
copyright: Optional[StringCommand.type(__copyright__)] = Field(description=COPYRIGHT_DESCRIPTION)
|
|
166
166
|
deploy_plugin: Optional[DeployPluginCommand] = Field(description='deploy plugins', alias='deploy-plugin')
|
|
167
167
|
dp: Optional[DeployPluginCommand] = Field(description='synonym for: deploy-plugin')
|
lockss/turtles/plugin.py
CHANGED
|
@@ -38,7 +38,7 @@ from __future__ import annotations
|
|
|
38
38
|
|
|
39
39
|
from collections.abc import Callable
|
|
40
40
|
from pathlib import Path
|
|
41
|
-
from typing import Any, Optional
|
|
41
|
+
from typing import Any, AnyStr, IO, Optional
|
|
42
42
|
import xml.etree.ElementTree as ET
|
|
43
43
|
from zipfile import ZipFile
|
|
44
44
|
|
|
@@ -48,12 +48,32 @@ from lockss.pybasic.fileutil import path
|
|
|
48
48
|
from .util import PathOrStr
|
|
49
49
|
|
|
50
50
|
|
|
51
|
+
#: A type alias for plugin identifiers.
|
|
51
52
|
PluginIdentifier = str
|
|
52
53
|
|
|
53
54
|
|
|
54
55
|
class Plugin(object):
|
|
56
|
+
"""
|
|
57
|
+
An object to represent a LOCKSS plugin.
|
|
58
|
+
"""
|
|
55
59
|
|
|
56
|
-
def __init__(self, plugin_file, plugin_path) -> None:
|
|
60
|
+
def __init__(self, plugin_file: IO[AnyStr], plugin_path: PathOrStr) -> None:
|
|
61
|
+
"""
|
|
62
|
+
Constructor.
|
|
63
|
+
|
|
64
|
+
Other exceptions than ``RuntimeError`` may be raised if the plugin
|
|
65
|
+
definition file cannot be parsed by ``xml.etree.ElementTree``.
|
|
66
|
+
|
|
67
|
+
:param plugin_file: An open file-like object that can read the plugin
|
|
68
|
+
definition file.
|
|
69
|
+
:type plugin_file: IO[AnyStr]
|
|
70
|
+
:param plugin_path: A string (or Path) representing the hierarchical
|
|
71
|
+
path of the plugin definition file (as a real file,
|
|
72
|
+
or as a file entry in a JAR file).
|
|
73
|
+
:type plugin_path: PathOrStr
|
|
74
|
+
:raises RuntimeError: If the plugin definition file parses as XML but
|
|
75
|
+
the top-level element is not <map>.
|
|
76
|
+
"""
|
|
57
77
|
super().__init__()
|
|
58
78
|
self._path = plugin_path
|
|
59
79
|
self._parsed = ET.parse(plugin_file).getroot()
|
|
@@ -62,6 +82,14 @@ class Plugin(object):
|
|
|
62
82
|
raise RuntimeError(f'{plugin_path!s}: invalid root element: {tag}')
|
|
63
83
|
|
|
64
84
|
def get_aux_packages(self) -> list[str]:
|
|
85
|
+
"""
|
|
86
|
+
Returns the (possibly empty) list of auxiliary code packages declared by
|
|
87
|
+
the plugin (``plugin_aux_packages``).
|
|
88
|
+
|
|
89
|
+
:return: A non-null list of strings representing auxiliary code
|
|
90
|
+
packages.
|
|
91
|
+
:rtype: list[str]
|
|
92
|
+
"""
|
|
65
93
|
key = 'plugin_aux_packages'
|
|
66
94
|
lst = [x[1] for x in self._parsed.findall('entry') if x[0].tag == 'string' and x[0].text == key]
|
|
67
95
|
if lst is None or len(lst) < 1:
|
|
@@ -71,21 +99,76 @@ class Plugin(object):
|
|
|
71
99
|
return [x.text for x in lst[0].findall('string')]
|
|
72
100
|
|
|
73
101
|
def get_identifier(self) -> Optional[PluginIdentifier]:
|
|
102
|
+
"""
|
|
103
|
+
Get this plugin's identifier (``plugin_identifier``).
|
|
104
|
+
|
|
105
|
+
:return: A plugin identifier, or None if missing.
|
|
106
|
+
:rtype: Optional[PluginIdentifier]
|
|
107
|
+
:raises ValueError: If the plugin definition contains more than one.
|
|
108
|
+
"""
|
|
74
109
|
return self._only_one('plugin_identifier')
|
|
75
110
|
|
|
76
111
|
def get_name(self) -> Optional[str]:
|
|
112
|
+
"""
|
|
113
|
+
Get this plugin's name (``plugin_name``).
|
|
114
|
+
|
|
115
|
+
:return: A plugin name, or None if missing.
|
|
116
|
+
:rtype: Optional[str]
|
|
117
|
+
:raises ValueError: If the plugin definition contains more than one.
|
|
118
|
+
"""
|
|
77
119
|
return self._only_one('plugin_name')
|
|
78
120
|
|
|
79
121
|
def get_parent_identifier(self) -> Optional[PluginIdentifier]:
|
|
122
|
+
"""
|
|
123
|
+
Get this plugin's parent identifier (``plugin_parent``).
|
|
124
|
+
|
|
125
|
+
:return: A parent plugin identifier, or None if this plugin has no
|
|
126
|
+
parent.
|
|
127
|
+
:rtype: Optional[PluginIdentifier]
|
|
128
|
+
:raises ValueError: If the plugin definition contains more than one.
|
|
129
|
+
"""
|
|
80
130
|
return self._only_one('plugin_parent')
|
|
81
131
|
|
|
82
132
|
def get_parent_version(self) -> Optional[int]:
|
|
133
|
+
"""
|
|
134
|
+
Get this plugin's parent version (``plugin_parent_version``).
|
|
135
|
+
|
|
136
|
+
:return: A parent plugin version, or None if this plugin has no
|
|
137
|
+
parent.
|
|
138
|
+
:rtype: Optional[int]
|
|
139
|
+
:raises ValueError: If the plugin definition contains more than one.
|
|
140
|
+
"""
|
|
83
141
|
return self._only_one('plugin_parent_version', int)
|
|
84
142
|
|
|
85
143
|
def get_version(self) -> Optional[int]:
|
|
144
|
+
"""
|
|
145
|
+
Get this plugin's version (``plugin_version``).
|
|
146
|
+
|
|
147
|
+
:return: A plugin version, or None if missing.
|
|
148
|
+
:rtype: Optional[int]
|
|
149
|
+
:raises ValueError: If the plugin definition contains more than one.
|
|
150
|
+
"""
|
|
86
151
|
return self._only_one('plugin_version', int)
|
|
87
152
|
|
|
88
|
-
def _only_one(self, key: str, result: Callable=str) -> Optional[Any]:
|
|
153
|
+
def _only_one(self, key: str, result: Callable[[str], Any]=str) -> Optional[Any]:
|
|
154
|
+
"""
|
|
155
|
+
Retrieves the value of a given key in the plugin definition, optionally
|
|
156
|
+
coerced into a representation (by default simply a string).
|
|
157
|
+
|
|
158
|
+
:param key: A plugin key.
|
|
159
|
+
:param key: str
|
|
160
|
+
:param result: A functor that takes a string and returns the desired
|
|
161
|
+
representation; by default this is the string constructor
|
|
162
|
+
``str``, meaning by default the string values are
|
|
163
|
+
returned unchanged.
|
|
164
|
+
:param result: Callable[[str], Any]
|
|
165
|
+
:return: The value for the given key, coerced through the given functor,
|
|
166
|
+
or None if the plugin definition does not contain any entry
|
|
167
|
+
with the given key.
|
|
168
|
+
:rtype: Optional[Any]
|
|
169
|
+
:raises ValueError: If the plugin definition contains more than one
|
|
170
|
+
entry with the given key.
|
|
171
|
+
"""
|
|
89
172
|
lst = [x[1].text for x in self._parsed.findall('entry') if x[0].tag == 'string' and x[0].text == key]
|
|
90
173
|
if lst is None or len(lst) < 1:
|
|
91
174
|
return None
|
|
@@ -94,8 +177,16 @@ class Plugin(object):
|
|
|
94
177
|
return result(lst[0])
|
|
95
178
|
|
|
96
179
|
@staticmethod
|
|
97
|
-
def from_jar(
|
|
98
|
-
|
|
180
|
+
def from_jar(jar_path_or_str: PathOrStr) -> Plugin:
|
|
181
|
+
"""
|
|
182
|
+
Instantiates a Plugin object from the given plugin JAR file.
|
|
183
|
+
|
|
184
|
+
:param jar_path_or_str: The path to a plugin JAR.
|
|
185
|
+
:type jar_path_or_str: PathOrStr
|
|
186
|
+
:return: A Plugin object.
|
|
187
|
+
:rtype: Plugin
|
|
188
|
+
"""
|
|
189
|
+
jar_path = path(jar_path_or_str)
|
|
99
190
|
plugin_id = Plugin.id_from_jar(jar_path)
|
|
100
191
|
plugin_fstr = str(Plugin.id_to_file(plugin_id))
|
|
101
192
|
with ZipFile(jar_path, 'r') as zip_file:
|
|
@@ -103,18 +194,50 @@ class Plugin(object):
|
|
|
103
194
|
return Plugin(plugin_file, plugin_fstr)
|
|
104
195
|
|
|
105
196
|
@staticmethod
|
|
106
|
-
def from_path(
|
|
107
|
-
|
|
108
|
-
|
|
197
|
+
def from_path(path_or_str: PathOrStr) -> Plugin:
|
|
198
|
+
"""
|
|
199
|
+
Instantiates a Plugin object from the given plugin file.
|
|
200
|
+
|
|
201
|
+
:param path_or_str: The path to a plugin file.
|
|
202
|
+
:type path_or_str: PathOrStr
|
|
203
|
+
:return: A Plugin object.
|
|
204
|
+
:rtype: Plugin
|
|
205
|
+
"""
|
|
206
|
+
fpath = path(path_or_str)
|
|
207
|
+
with fpath.open('r') as input_file:
|
|
109
208
|
return Plugin(input_file, fpath)
|
|
110
209
|
|
|
111
210
|
@staticmethod
|
|
112
211
|
def file_to_id(plugin_fstr: str) -> PluginIdentifier:
|
|
212
|
+
"""
|
|
213
|
+
Converts a plugin file path (ending in ``.xml``) to the implied plugin
|
|
214
|
+
identifier (e.g. ``org/myproject/plugin/MyPlugin.xml`` implies
|
|
215
|
+
``org.myproject.plugin.MyPlugin``).
|
|
216
|
+
|
|
217
|
+
See also ``id_to_file``.
|
|
218
|
+
|
|
219
|
+
:param plugin_fstr: A string file path.
|
|
220
|
+
:type plugin_fstr: str
|
|
221
|
+
:return: A plugin identifier.
|
|
222
|
+
:rtype: PluginIdentifier
|
|
223
|
+
"""
|
|
113
224
|
return plugin_fstr.replace('/', '.')[:-4] # 4 is len('.xml')
|
|
114
225
|
|
|
115
226
|
@staticmethod
|
|
116
|
-
def id_from_jar(
|
|
117
|
-
|
|
227
|
+
def id_from_jar(jar_path_or_str: PathOrStr) -> PluginIdentifier:
|
|
228
|
+
"""
|
|
229
|
+
Extracts the plugin identifier from a plugin JAR's manifest file.
|
|
230
|
+
|
|
231
|
+
:param jar_path_or_str: The path to a plugin JAR.
|
|
232
|
+
:type jar_path_or_str: PathOrStr
|
|
233
|
+
:return: The plugin identifier extracted from the given plugin JAR's
|
|
234
|
+
manifest file.
|
|
235
|
+
:rtype: PluginIdentifier
|
|
236
|
+
:raises Exception: If the JAR's manifest file has no entry with
|
|
237
|
+
``Lockss-Plugin`` equal to ``true`` and ``Name``
|
|
238
|
+
equal to the packaged plugin's identifier.
|
|
239
|
+
"""
|
|
240
|
+
jar_path = path(jar_path_or_str)
|
|
118
241
|
manifest = java_manifest.from_jar(jar_path)
|
|
119
242
|
for entry in manifest:
|
|
120
243
|
if entry.get('Lockss-Plugin') == 'true':
|
|
@@ -127,8 +250,29 @@ class Plugin(object):
|
|
|
127
250
|
|
|
128
251
|
@staticmethod
|
|
129
252
|
def id_to_dir(plugin_id: PluginIdentifier) -> Path:
|
|
253
|
+
"""
|
|
254
|
+
Returns the path of the directory containing the given plugin identifier
|
|
255
|
+
(for example ``org/myproject/plugin`` for
|
|
256
|
+
``org.myproject.plugin.MyPlugin``).
|
|
257
|
+
|
|
258
|
+
:param plugin_id: A plugin identifier.
|
|
259
|
+
:type plugin_id: PluginIdentifier
|
|
260
|
+
:return: The directory path containing the given plugin identifier.
|
|
261
|
+
:rtype: Path
|
|
262
|
+
"""
|
|
130
263
|
return Plugin.id_to_file(plugin_id).parent
|
|
131
264
|
|
|
132
265
|
@staticmethod
|
|
133
266
|
def id_to_file(plugin_id: PluginIdentifier) -> Path:
|
|
267
|
+
"""
|
|
268
|
+
Returns the path of the definition file corresponding to the given
|
|
269
|
+
plugin identifier (for example ``org/myproject/plugin/MyPlugin.xml`` for
|
|
270
|
+
``org.myproject.plugin.MyPlugin``).
|
|
271
|
+
|
|
272
|
+
:param plugin_id: A plugin identifier.
|
|
273
|
+
:type plugin_id: PluginIdentifier
|
|
274
|
+
:return: The path of the definition file corresponding to the given
|
|
275
|
+
plugin identifier.
|
|
276
|
+
:rtype: Path
|
|
277
|
+
"""
|
|
134
278
|
return Path(f'{plugin_id.replace(".", "/")}.xml')
|
|
@@ -45,13 +45,12 @@ from .plugin import Plugin, PluginIdentifier
|
|
|
45
45
|
from .util import BaseModelWithRoot
|
|
46
46
|
|
|
47
47
|
|
|
48
|
-
|
|
49
48
|
PluginRegistryCatalogKind = Literal['PluginRegistryCatalog']
|
|
50
49
|
|
|
51
50
|
|
|
52
51
|
class PluginRegistryCatalog(BaseModelWithRoot):
|
|
53
|
-
kind: PluginRegistryCatalogKind = Field(description="This object's kind")
|
|
54
|
-
plugin_registry_files: list[str] = Field(min_length=1, description="A non-empty list of plugin registry files"
|
|
52
|
+
kind: PluginRegistryCatalogKind = Field(title='Kind', description="This object's kind")
|
|
53
|
+
plugin_registry_files: list[str] = Field(alias='plugin-registry-files', min_length=1, title='Plugin Registry Files', description="A non-empty list of plugin registry files")
|
|
55
54
|
|
|
56
55
|
def get_plugin_registry_files(self) -> list[Path]:
|
|
57
56
|
return [self.get_root().joinpath(pstr) for pstr in self.plugin_registry_files]
|
|
@@ -66,7 +65,7 @@ PluginRegistryLayoutFileNamingConvention = Literal['abbreviated', 'identifier',
|
|
|
66
65
|
class BasePluginRegistryLayout(BaseModel, ABC):
|
|
67
66
|
TYPE_FIELD: ClassVar[dict[str, str]] = dict(title='Plugin Registry Layout Type', description='A plugin registry layout type')
|
|
68
67
|
FILE_NAMING_CONVENTION_DEFAULT: ClassVar[PluginRegistryLayoutFileNamingConvention] = 'identifier'
|
|
69
|
-
FILE_NAMING_CONVENTION_FIELD: ClassVar[dict[str, str]] = dict(title='Plugin Registry Layout File Naming Convention', description='A file naming convention for the plugin registry layout'
|
|
68
|
+
FILE_NAMING_CONVENTION_FIELD: ClassVar[dict[str, str]] = dict(alias='file-naming-convention', title='Plugin Registry Layout File Naming Convention', description='A file naming convention for the plugin registry layout')
|
|
70
69
|
|
|
71
70
|
_plugin_registry: Optional[PluginRegistry]
|
|
72
71
|
|
|
@@ -213,13 +212,13 @@ PluginRegistryIdentifier = str
|
|
|
213
212
|
|
|
214
213
|
|
|
215
214
|
class PluginRegistry(BaseModelWithRoot):
|
|
216
|
-
kind: PluginRegistryKind = Field(description="This object's kind")
|
|
215
|
+
kind: PluginRegistryKind = Field(title='Kind', description="This object's kind")
|
|
217
216
|
id: PluginRegistryIdentifier = Field(title='Plugin Registry Identifier', description='An identifier for the plugin set')
|
|
218
217
|
name: str = Field(title='Plugin Registry Name', description='A name for the plugin set')
|
|
219
218
|
layout: PluginRegistryLayout = Field(title='Plugin Registry Layout', description='A layout for the plugin registry')
|
|
220
219
|
layers: list[PluginRegistryLayer] = Field(min_length=1, title='Plugin Registry Layers', description="A non-empty list of plugin registry layers")
|
|
221
|
-
plugin_identifiers: list[PluginIdentifier] = Field(min_length=1, title='Plugin Identifiers', description="A non-empty list of plugin identifiers"
|
|
222
|
-
suppressed_plugin_identifiers: list[PluginIdentifier] = Field([], title='Suppressed Plugin Identifiers', description="A list of suppressed plugin identifiers"
|
|
220
|
+
plugin_identifiers: list[PluginIdentifier] = Field(alias='plugin-identifiers', min_length=1, title='Plugin Identifiers', description="A non-empty list of plugin identifiers")
|
|
221
|
+
suppressed_plugin_identifiers: list[PluginIdentifier] = Field([], alias='suppressed-plugin-identifiers', title='Suppressed Plugin Identifiers', description="A list of suppressed plugin identifiers")
|
|
223
222
|
|
|
224
223
|
def get_id(self) -> PluginRegistryIdentifier:
|
|
225
224
|
return self.id
|
lockss/turtles/plugin_set.py
CHANGED
|
@@ -59,9 +59,9 @@ class PluginSetCatalog(BaseModelWithRoot):
|
|
|
59
59
|
plugin set catalog.
|
|
60
60
|
"""
|
|
61
61
|
#: This object's kind.
|
|
62
|
-
kind: PluginSetCatalogKind = Field(description="This object's kind")
|
|
62
|
+
kind: PluginSetCatalogKind = Field(title='Kind', description="This object's kind")
|
|
63
63
|
#: A non-empty list of plugin set files.
|
|
64
|
-
plugin_set_files: list[str] = Field(min_length=1, description="A non-empty list of plugin set files"
|
|
64
|
+
plugin_set_files: list[str] = Field(alias='plugin-set-files', min_length=1, title='Plugin Set Files', description="A non-empty list of plugin set files")
|
|
65
65
|
|
|
66
66
|
def get_plugin_set_files(self) -> list[Path]:
|
|
67
67
|
"""
|
|
@@ -86,11 +86,11 @@ class BasePluginSetBuilder(BaseModelWithRoot, ABC):
|
|
|
86
86
|
"""
|
|
87
87
|
|
|
88
88
|
#: Pydantic definition of the ``type`` field.
|
|
89
|
-
TYPE_FIELD: ClassVar[dict[str, str]] = dict(
|
|
89
|
+
TYPE_FIELD: ClassVar[dict[str, str]] = dict(title='Plugin Builder Type', description='A plugin builder type')
|
|
90
90
|
#: Pydantic definition of the ``main`` field.
|
|
91
|
-
MAIN_FIELD: ClassVar[dict[str, str]] = dict(description="The path to the plugins' source code, relative to the root of the project"
|
|
91
|
+
MAIN_FIELD: ClassVar[dict[str, str]] = dict(title='Main Code Path', description="The path to the plugins' source code, relative to the root of the project")
|
|
92
92
|
#: Pydantic definition of the ``test`` field.
|
|
93
|
-
TEST_FIELD: ClassVar[dict[str, str]] = dict(description="The path to the plugins' unit tests, relative to the root of the project"
|
|
93
|
+
TEST_FIELD: ClassVar[dict[str, str]] = dict(title='Test Code Path', description="The path to the plugins' unit tests, relative to the root of the project")
|
|
94
94
|
|
|
95
95
|
@abstractmethod
|
|
96
96
|
def build_plugin(self, plugin_id: PluginIdentifier, keystore_path: Path, keystore_alias: str, keystore_password=None) -> tuple[Path, Plugin]:
|
|
@@ -361,10 +361,10 @@ PluginSetIdentifier = str
|
|
|
361
361
|
|
|
362
362
|
|
|
363
363
|
class PluginSet(BaseModel):
|
|
364
|
-
kind: PluginSetKind = Field(description="This object's kind")
|
|
365
|
-
id: PluginSetIdentifier = Field(description='An identifier for the plugin set')
|
|
366
|
-
name: str = Field(description='A name for the plugin set')
|
|
367
|
-
builder: PluginSetBuilder = Field(description='A builder for the plugin set'
|
|
364
|
+
kind: PluginSetKind = Field(title='Kind', description="This object's kind")
|
|
365
|
+
id: PluginSetIdentifier = Field(title='Plugin Set Identifier', description='An identifier for the plugin set')
|
|
366
|
+
name: str = Field(title='Plugin Set Name', description='A name for the plugin set')
|
|
367
|
+
builder: PluginSetBuilder = Field(title='Plugin Set Builder', description='A builder for the plugin set')
|
|
368
368
|
|
|
369
369
|
def build_plugin(self, plugin_id: PluginIdentifier, keystore_path: Path, keystore_alias: str, keystore_password=None) -> tuple[Path, Plugin]:
|
|
370
370
|
return self.builder.build_plugin(plugin_id, keystore_path, keystore_alias, keystore_password)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: lockss-turtles
|
|
3
|
-
Version: 0.6.0.
|
|
3
|
+
Version: 0.6.0.dev21
|
|
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
|
|
@@ -34,7 +34,7 @@ Description-Content-Type: text/x-rst
|
|
|
34
34
|
Turtles
|
|
35
35
|
=======
|
|
36
36
|
|
|
37
|
-
.. |RELEASE| replace:: 0.6.0-
|
|
37
|
+
.. |RELEASE| replace:: 0.6.0-dev20
|
|
38
38
|
.. |RELEASE_DATE| replace:: ?
|
|
39
39
|
|
|
40
40
|
.. |HELP| replace:: ``--help/-h``
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
lockss/turtles/__init__.py,sha256=9arhPOwCemb5EemdFE4gisbpLEE6bPqOBGi1yOXJmIA,1827
|
|
2
|
+
lockss/turtles/__main__.py,sha256=BqRTG3dejCgLh87UJ1Os9DD9unxnQkOdUQM6eqWS3Sg,1680
|
|
3
|
+
lockss/turtles/app.py,sha256=Rxbsq10A830D1r99a5tqLVYWM3bJZ2Org-JKjXD-2Mk,16689
|
|
4
|
+
lockss/turtles/cli.py,sha256=ZijrjwW1VXtmRvTDpfLnLvq9aL0CfK-F6mglk04RihI,20887
|
|
5
|
+
lockss/turtles/plugin.py,sha256=HT01Er9-odvJ4lF8DNC7TV4uxSqTw44UBe02Jgj5xMs,11065
|
|
6
|
+
lockss/turtles/plugin_registry.py,sha256=ZGlVnhP831hmqLQ9cJueUAXlZWQ67rm0cs6U91F7STc,11943
|
|
7
|
+
lockss/turtles/plugin_set.py,sha256=Q-d-UfZM8I6f-z4TeYe8jdBbhPv0r4ro2H24oNd8Syc,15898
|
|
8
|
+
lockss/turtles/util.py,sha256=8EyWvzTLNycQM_ZKCtWm8FpKJSrwaCSWh8006UYq6vU,2498
|
|
9
|
+
unittest/lockss/turtles/__init__.py,sha256=hrgWx4GaP-hhPBuRlbLndJnOQmZicKCLaP-dQTCu1sQ,3162
|
|
10
|
+
unittest/lockss/turtles/test_plugin_set.py,sha256=q6JmooDR-wijAQ8x9DWKTNB6Of4EOr3Dgq8oaX0LTpQ,4179
|
|
11
|
+
lockss_turtles-0.6.0.dev21.dist-info/LICENSE,sha256=O9ONND4uDxY_jucI4jZDf2liAk05ScEJaYu-Al7EOdQ,1506
|
|
12
|
+
lockss_turtles-0.6.0.dev21.dist-info/METADATA,sha256=2HRA5jwOYJaTyU4wXqaIBzQg4aKlxdjTdl9lqL3aT9w,39692
|
|
13
|
+
lockss_turtles-0.6.0.dev21.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
14
|
+
lockss_turtles-0.6.0.dev21.dist-info/entry_points.txt,sha256=25BAVFSBRKWAWiXIGZgcr1ypt2mV7nj31Jl8WcNZZOk,51
|
|
15
|
+
lockss_turtles-0.6.0.dev21.dist-info/RECORD,,
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
lockss/turtles/__init__.py,sha256=cBj5LqZHvI7BaYdTG5wtlImMX8zdhImZFc0uXc_CIq0,1744
|
|
2
|
-
lockss/turtles/__main__.py,sha256=BqRTG3dejCgLh87UJ1Os9DD9unxnQkOdUQM6eqWS3Sg,1680
|
|
3
|
-
lockss/turtles/app.py,sha256=SAmd_k_2viX_SY2aiXNgQq0k1oPYMUwNBicsnzAo9e4,16689
|
|
4
|
-
lockss/turtles/cli.py,sha256=lNdRVP8RkY80lRNZny9v2VXL8lPt0jNOhOEdzCUd-XU,20749
|
|
5
|
-
lockss/turtles/plugin.py,sha256=re44YVlzXVU8azDshxn7oHw1GdTQLLQgYwkvZlur-60,5384
|
|
6
|
-
lockss/turtles/plugin_registry.py,sha256=G_CwTFgDV4om1W0-QY7Ww_7mneCbckXuEWMk7ZFOPW4,11916
|
|
7
|
-
lockss/turtles/plugin_set.py,sha256=XCIGmSKHZlSk-L0hhvzE38OU3JmWYgWFTI3V8Uaq1x0,15814
|
|
8
|
-
lockss/turtles/util.py,sha256=8EyWvzTLNycQM_ZKCtWm8FpKJSrwaCSWh8006UYq6vU,2498
|
|
9
|
-
unittest/lockss/turtles/__init__.py,sha256=hrgWx4GaP-hhPBuRlbLndJnOQmZicKCLaP-dQTCu1sQ,3162
|
|
10
|
-
unittest/lockss/turtles/test_plugin_set.py,sha256=q6JmooDR-wijAQ8x9DWKTNB6Of4EOr3Dgq8oaX0LTpQ,4179
|
|
11
|
-
lockss_turtles-0.6.0.dev19.dist-info/LICENSE,sha256=O9ONND4uDxY_jucI4jZDf2liAk05ScEJaYu-Al7EOdQ,1506
|
|
12
|
-
lockss_turtles-0.6.0.dev19.dist-info/METADATA,sha256=LAGhBiXHtJ_Ure1XKjdlVN8DOrFQvbSKjLXFym4CtG4,39692
|
|
13
|
-
lockss_turtles-0.6.0.dev19.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
14
|
-
lockss_turtles-0.6.0.dev19.dist-info/entry_points.txt,sha256=25BAVFSBRKWAWiXIGZgcr1ypt2mV7nj31Jl8WcNZZOk,51
|
|
15
|
-
lockss_turtles-0.6.0.dev19.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
{lockss_turtles-0.6.0.dev19.dist-info → lockss_turtles-0.6.0.dev21.dist-info}/entry_points.txt
RENAMED
|
File without changes
|