lockss-turtles 0.3.0.dev2__py3-none-any.whl → 0.3.0.dev4__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.
CHANGELOG.rst ADDED
@@ -0,0 +1,77 @@
1
+ =============
2
+ Release Notes
3
+ =============
4
+
5
+ -----
6
+ 0.3.0
7
+ -----
8
+
9
+ Released: FIXME
10
+
11
+ .. rubric:: Features
12
+
13
+ * Completely refactored to be in the package ``lockss.turtles``.
14
+
15
+ * Using Poetry to make uploadable to and installable from PyPI as `lockss-turtles <https://pypi.org/project/lockss-turtles>`_. Removed the requirements file.
16
+
17
+ * Validate the various YAML objects (like a ``PluginSet``) against a `JSON Schema <https://json-schema.org/>`_.
18
+
19
+ .. rubric:: Changes
20
+
21
+ * Temporarily disabled the ``analyze-registry`` command.
22
+
23
+ * ``$XDG_CONFIG_HOME/turtles`` (by default ``$HOME/.config/turtles``) is now ``$XDG_CONFIG_HOME/lockss.turtles`` (by default ``$HOME/.config/lockss.turtles``) or ``/etc/lockss.turtles`` (formerly ``turtles``).
24
+
25
+ * ``settings.yaml`` is now ``plugin-signing.yaml`` and its ``kind`` is now ``PluginSigning``. The corresponding command line option ``--settings`` is now ``--plugin-signing``.
26
+
27
+ * ``plugin-sets.yaml``, its kind ``PluginSets``, its key ``plugin-sets``, and the command line option ``--plugin-sets`` are now ``plugin-set-catalog.yaml``, ``PluginSetCatalog``, ``plugin-set-files`` and ``--plugin-set-catalog``, respectively. The builder ``options`` key is deprecated.
28
+
29
+ * ``plugin-registries.yaml``, its kind ``PluginRegistries``, its key ``plugin-registries``, and the command line option ``--plugin-registries`` are now ``plugin-registry-catalog.yaml``, ``PluginRegistryCatalog``, ``plugin-registry-files`` and ``--plugin-registry-catalog``, respectively. The ``file-naming-convention`` key is now directly under ``layout`` and the value ``full`` is now ``identifier``. The layout ``options`` key is deprecated.
30
+
31
+ -----
32
+ 0.2.0
33
+ -----
34
+
35
+ Released: 2022-10-26
36
+
37
+ .. rubric:: Features
38
+
39
+ * ``MavenPluginSet``, for Maven projects inheriting from ``org.lockss:lockss-plugins-parent-pom``.
40
+
41
+ * ``AntPluginSet``: file naming convention layout option.
42
+
43
+ * Tabular output now includes the plugin version.
44
+
45
+ .. rubric:: Bug Fixes
46
+
47
+ * ``AntPluginSet``: run ``ant load-plugins`` before building plugins.
48
+
49
+ -----
50
+ 0.1.1
51
+ -----
52
+
53
+ Released: 2022-10-23
54
+
55
+ .. rubric:: Bug Fixes
56
+
57
+ * ``RcsPluginRegistry``: Better handle incompletely managed RCS areas.
58
+
59
+ * ``DirectoryPluginRegistry``: Better file handling with ``cp``.
60
+
61
+ -----
62
+ 0.1.0
63
+ -----
64
+
65
+ Released: 2022-10-10
66
+
67
+ Initial release.
68
+
69
+ .. rubric:: Features
70
+
71
+ * ``AntPluginSet``, based on the classic ``lockss-daemon`` Ant builder.
72
+
73
+ * ``DirectoryPluginRegistry``, for a simple layout.
74
+
75
+ * ``RcsPluginRegistry``, based on the classic RCS layout.
76
+
77
+ * Tabular output by `tabulate <https://pypi.org/project/tabulate/>`_.
@@ -28,7 +28,7 @@
28
28
  # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
29
  # POSSIBILITY OF SUCH DAMAGE.
30
30
 
31
- __version__ = '0.3.0-dev2'
31
+ __version__ = '0.3.0-dev4'
32
32
 
33
33
  __copyright__ = '''\
34
34
  Copyright (c) 2000-2023, Board of Trustees of Leland Stanford Jr. University
lockss/turtles/app.py CHANGED
@@ -44,17 +44,19 @@ class TurtlesApp(object):
44
44
 
45
45
  XDG_CONFIG_DIR = xdg.xdg_config_home().joinpath(__package__)
46
46
 
47
- GLOBAL_CONFIG_DIR = Path('/etc', __package__)
47
+ USR_CONFIG_DIR = Path('/usr/local/share', __package__)
48
48
 
49
- CONFIG_DIRS = [XDG_CONFIG_DIR, GLOBAL_CONFIG_DIR]
49
+ ETC_CONFIG_DIR = Path('/etc', __package__)
50
+
51
+ CONFIG_DIRS = [XDG_CONFIG_DIR, USR_CONFIG_DIR, ETC_CONFIG_DIR]
50
52
 
51
53
  PLUGIN_REGISTRY_CATALOG = 'plugin-registry-catalog.yaml'
52
54
 
53
55
  PLUGIN_SET_CATALOG = 'plugin-set-catalog.yaml'
54
56
 
55
- PLUGIN_SIGNING = 'plugin-signing.yaml'
57
+ PLUGIN_SIGNING_CREDENTIALS = 'plugin-signing-credentials.yaml'
56
58
 
57
- PLUGIN_SIGNING_SCHEMA = 'plugin-signing-schema.json'
59
+ PLUGIN_SIGNING_CREDENTIALS_SCHEMA = 'plugin-signing-credentials-schema.json'
58
60
 
59
61
  @staticmethod
60
62
  def _default_files(file_str):
@@ -78,7 +80,7 @@ class TurtlesApp(object):
78
80
  self._password = None
79
81
  self._plugin_registries = None
80
82
  self._plugin_sets = None
81
- self._plugin_signing = None
83
+ self._plugin_signing_credentials = None
82
84
 
83
85
  # Returns plugin_id -> (set_id, jar_path, plugin)
84
86
  def build_plugin(self, plugin_ids):
@@ -90,8 +92,8 @@ class TurtlesApp(object):
90
92
  def default_plugin_set_catalogs(self):
91
93
  return TurtlesApp._default_files(TurtlesApp.PLUGIN_SET_CATALOG)
92
94
 
93
- def default_plugin_signing(self):
94
- return TurtlesApp._default_files(TurtlesApp.PLUGIN_SIGNING)
95
+ def default_plugin_signing_credentials(self):
96
+ return TurtlesApp._default_files(TurtlesApp.PLUGIN_SIGNING_CREDENTIALS)
95
97
 
96
98
  # Returns (src_path, plugin_id) -> list of (registry_id, layer_id, dst_path, plugin)
97
99
  def deploy_plugin(self, src_paths, layer_ids, interactive=False):
@@ -115,11 +117,11 @@ class TurtlesApp(object):
115
117
  for plugin_set_file in plugin_set_catalog.plugin_set_files():
116
118
  self._plugin_sets.extend(PluginSet.from_path(plugin_set_file))
117
119
 
118
- def load_plugin_signing(self, plugin_signing_path=None):
119
- if self._plugin_signing is None:
120
- plugin_signing_path = _path(plugin_signing_path) if plugin_signing_path else self._select_file(TurtlesApp.PLUGIN_SIGNING)
121
- plugin_signing_schema_path = importlib.resources.path(lockss.turtles.resources, TurtlesApp.PLUGIN_SIGNING_SCHEMA)
122
- self._plugin_signing = _load_and_validate(plugin_signing_schema_path, plugin_signing_path)
120
+ def load_plugin_signing_credentials(self, plugin_signing_credentials_path=None):
121
+ if self._plugin_signing_credentials is None:
122
+ plugin_signing_credentials_path = _path(plugin_signing_credentials_path) if plugin_signing_credentials_path else self._select_file(TurtlesApp.PLUGIN_SIGNING_CREDENTIALS)
123
+ plugin_signing_credentials_schema_path = importlib.resources.path(lockss.turtles.resources, TurtlesApp.PLUGIN_SIGNING_SCHEMA)
124
+ self._plugin_signing_credentials = _load_and_validate(plugin_signing_credentials_schema_path, plugin_signing_credentials_path)
123
125
 
124
126
  # Returns plugin_id -> list of (registry_id, layer_id, dst_path, plugin)
125
127
  def release_plugin(self, plugin_ids, layer_ids, interactive=False):
@@ -138,8 +140,8 @@ class TurtlesApp(object):
138
140
  def select_plugin_set_catalog(self, preselected=None):
139
141
  return TurtlesApp._select_file(TurtlesApp.PLUGIN_SET_CATALOG, preselected)
140
142
 
141
- def select_plugin_signing(self, preselected=None):
142
- return TurtlesApp._select_file(TurtlesApp.PLUGIN_SIGNING, preselected)
143
+ def select_plugin_signing_credentials(self, preselected=None):
144
+ return TurtlesApp._select_file(TurtlesApp.PLUGIN_SIGNING_CREDENTIALS, preselected)
143
145
 
144
146
  def set_password(self, pw):
145
147
  self._password = pw if callable(pw) else lambda x: pw
@@ -176,10 +178,10 @@ class TurtlesApp(object):
176
178
  return self._password() if self._password else None
177
179
 
178
180
  def _get_plugin_signing_alias(self):
179
- return self._plugin_signing['plugin-signing-alias']
181
+ return self._plugin_signing_credentials['plugin-signing-alias']
180
182
 
181
183
  def _get_plugin_signing_keystore(self):
182
- return self._plugin_signing['plugin-signing-keystore']
184
+ return self._plugin_signing_credentials['plugin-signing-keystore']
183
185
 
184
186
  def _get_plugin_signing_password(self):
185
187
  return self._get_password()
lockss/turtles/cli.py CHANGED
@@ -52,6 +52,8 @@ def _file_lines(path):
52
52
 
53
53
  class TurtlesCli(object):
54
54
 
55
+ PROG = 'turtles'
56
+
55
57
  def __init__(self):
56
58
  super().__init__()
57
59
  self._app = TurtlesApp()
@@ -130,7 +132,7 @@ class TurtlesCli(object):
130
132
  def _build_plugin(self):
131
133
  # Prerequisites
132
134
  self._app.load_plugin_sets(self._args.plugin_set_catalog)
133
- self._app.load_plugin_signing(self._args.plugin_signing)
135
+ self._app.load_plugin_signing_credentials(self._args.plugin_signing_credentials)
134
136
  self._obtain_password()
135
137
  # Action
136
138
  # ... plugin_id -> (set_id, jar_path, plugin)
@@ -215,22 +217,22 @@ class TurtlesCli(object):
215
217
  help='set the plugin signing password')
216
218
 
217
219
  def _make_option_plugin_registry_catalog(self, container):
218
- container.add_argument('--plugin-registry-catalog',
220
+ container.add_argument('--plugin-registry-catalog', '-r',
219
221
  metavar='FILE',
220
222
  type=Path,
221
223
  help=f'load plugin registry catalog from %(metavar)s (default: {" or ".join(map(str, self._app.default_plugin_registry_catalogs()))})')
222
224
 
223
225
  def _make_option_plugin_set_catalog(self, container):
224
- container.add_argument('--plugin-set-catalog',
226
+ container.add_argument('--plugin-set-catalog', '-s',
225
227
  metavar='FILE',
226
228
  type=Path,
227
229
  help=f'load plugin set catalog from %(metavar)s (default: {" or ".join(map(str, self._app.default_plugin_set_catalogs()))})')
228
230
 
229
- def _make_option_plugin_signing(self, container):
230
- container.add_argument('--plugin-signing',
231
+ def _make_option_plugin_signing_credentials(self, container):
232
+ container.add_argument('--plugin-signing-credentials', '-c',
231
233
  metavar='FILE',
232
234
  type=Path,
233
- help=f'load plugin signing settings from %(metavar)s (default: {" or ".join(map(str, self._app.default_plugin_signing()))})')
235
+ help=f'load plugin signing credentials from %(metavar)s (default: {" or ".join(map(str, self._app.default_plugin_signing_credentials()))})')
234
236
 
235
237
  def _make_option_production(self, container):
236
238
  container.add_argument('--production', '-p',
@@ -292,7 +294,7 @@ class TurtlesCli(object):
292
294
  help='add the layers in %(metavar)s to the list of plugin registry layers to process')
293
295
 
294
296
  def _make_parser(self):
295
- self._parser = argparse.ArgumentParser(prog=__package__)
297
+ self._parser = argparse.ArgumentParser(prog=TurtlesCli.PROG)
296
298
  self._subparsers = self._parser.add_subparsers(title='commands',
297
299
  description="Add --help to see the command's own help message",
298
300
  # With subparsers, metavar is also used as the heading of the column of subcommands
@@ -328,7 +330,7 @@ class TurtlesCli(object):
328
330
  self._make_options_identifiers(parser)
329
331
  self._make_option_password(parser)
330
332
  self._make_option_plugin_set_catalog(parser)
331
- self._make_option_plugin_signing(parser)
333
+ self._make_option_plugin_signing_credentials(parser)
332
334
 
333
335
  def _make_parser_copyright(self, container):
334
336
  parser = container.add_parser('copyright',
@@ -363,7 +365,7 @@ class TurtlesCli(object):
363
365
  self._make_option_password(parser)
364
366
  self._make_option_plugin_registry_catalog(parser)
365
367
  self._make_option_plugin_set_catalog(parser)
366
- self._make_option_plugin_signing(parser)
368
+ self._make_option_plugin_signing_credentials(parser)
367
369
  self._make_option_production(parser)
368
370
  self._make_option_testing(parser)
369
371
 
@@ -392,7 +394,7 @@ class TurtlesCli(object):
392
394
  # Prerequisites
393
395
  self._app.load_plugin_sets(self._args.plugin_set_catalog)
394
396
  self._app.load_plugin_registries(self._args.plugin_registries)
395
- self._app.load_plugin_signing(self._args.plugin_signing)
397
+ self._app.load_plugin_signing_credentials(self._args.plugin_signing_credentials)
396
398
  self._obtain_password()
397
399
  # Action
398
400
  # ... plugin_id -> list of (registry_id, layer_id, dst_path, plugin)
@@ -102,9 +102,6 @@ class PluginRegistry(object):
102
102
  def layout_type(self):
103
103
  return self._parsed['layout']['type']
104
104
 
105
- def layout_options(self):
106
- return self._parsed['layout'].get('options', dict())
107
-
108
105
  def name(self):
109
106
  return self._parsed['name']
110
107
 
@@ -221,6 +218,9 @@ class RcsPluginRegistryLayer(DirectoryPluginRegistryLayer):
221
218
  def __init__(self, plugin_registry, parsed):
222
219
  super().__init__(plugin_registry, parsed)
223
220
 
221
+ def get_file_naming_convention(self):
222
+ return self.plugin_registry()._parsed['layout'].get('file-naming-convention', RcsPluginRegistry.IDENTIFIER)
223
+
224
224
  def _copy_jar(self, src_path, dst_path, interactive=False):
225
225
  basename = dst_path.name
226
226
  plugin = Plugin.from_jar(src_path)
@@ -239,11 +239,10 @@ class RcsPluginRegistryLayer(DirectoryPluginRegistryLayer):
239
239
  subprocess.run(cmd, check=True, cwd=self.path())
240
240
 
241
241
  def _get_dstfile(self, plugid):
242
- conv = self.plugin_registry().layout_options().get('file-naming-convention')
243
- if conv == RcsPluginRegistry.ABBREVIATED:
244
- return f'{plugid.split(".")[-1]}.jar'
245
- elif conv == RcsPluginRegistry.IDENTIFIER or conv is None:
242
+ conv = self.get_file_naming_convention()
243
+ if conv == RcsPluginRegistry.IDENTIFIER:
246
244
  return super()._get_dstfile(plugid)
245
+ elif conv == RcsPluginRegistry.ABBREVIATED:
246
+ return f'{plugid.split(".")[-1]}.jar'
247
247
  else:
248
- raise RuntimeError(
249
- f'{self.plugin_registry().id()}: unknown file naming convention in layout options: {conv}')
248
+ raise RuntimeError(f'{self.plugin_registry().id()}: unknown file naming convention: {conv}')
@@ -98,6 +98,13 @@
98
98
  "items": {
99
99
  "type":"string"
100
100
  }
101
+ },
102
+ "suppressed-plugin-identifiers": {
103
+ "description": "A list of plugin identifiers excluded from the plugin registry",
104
+ "type": "array",
105
+ "items": {
106
+ "type":"string"
107
+ }
101
108
  }
102
109
  }
103
110
  }
@@ -4,6 +4,12 @@
4
4
  "title": "Plugin Set",
5
5
  "description": "LOCKSS plugin set",
6
6
  "type": "object",
7
+ "required": [
8
+ "kind",
9
+ "id",
10
+ "name",
11
+ "builder"
12
+ ],
7
13
  "properties": {
8
14
  "kind": {
9
15
  "description": "This object's kind",
@@ -21,6 +27,9 @@
21
27
  "builder": {
22
28
  "description": "A plugin builder",
23
29
  "type": "object",
30
+ "required": [
31
+ "type"
32
+ ],
24
33
  "properties": {
25
34
  "type": {
26
35
  "description": "A plugin builder type",
@@ -30,10 +39,7 @@
30
39
  ]
31
40
  }
32
41
  },
33
- "required": [
34
- "type"
35
- ],
36
- "anyOf": [
42
+ "allOf": [
37
43
  {
38
44
  "if": {
39
45
  "properties": {
@@ -45,12 +51,14 @@
45
51
  "then": {
46
52
  "properties": {
47
53
  "main": {
48
- "description": "The plugin set's main tree path",
49
- "type": "string"
54
+ "description": "The path (relative to the root of the project) to the plugins' source code",
55
+ "type": "string",
56
+ "default": "plugins/src"
50
57
  },
51
58
  "test": {
52
- "description": "The plugin set's test tree path",
53
- "type": "string"
59
+ "description": "The path (relative to the root of the project) to the plugins' unit tests",
60
+ "type": "string",
61
+ "default": "plugins/test/src"
54
62
  }
55
63
  }
56
64
  }
@@ -66,23 +74,19 @@
66
74
  "then": {
67
75
  "properties": {
68
76
  "main": {
69
- "description": "The plugin set's main tree path",
70
- "type": "string"
77
+ "description": "The path (relative to the root of the project) to the plugins' source code",
78
+ "type": "string",
79
+ "default": "src/main/java"
71
80
  },
72
81
  "test": {
73
- "description": "The plugin set's test tree path",
74
- "type": "string"
82
+ "description": "The path (relative to the root of the project) to the plugins' unit tests",
83
+ "type": "string",
84
+ "default": "src/test/java"
75
85
  }
76
86
  }
77
87
  }
78
88
  }
79
89
  ]
80
90
  }
81
- },
82
- "required": [
83
- "kind",
84
- "id",
85
- "name",
86
- "builder"
87
- ]
91
+ }
88
92
  }
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "https://assets.lockss.org/schemas/json/plugin-signing-schema.json",
4
- "title": "Plugin Signing",
5
- "description": "LOCKSS plugin signing settings",
3
+ "$id": "https://assets.lockss.org/schemas/json/plugin-signing-credentials-schema.json",
4
+ "title": "Plugin Signing Credentials",
5
+ "description": "LOCKSS plugin signing credentials",
6
6
  "type": "object",
7
7
  "properties": {
8
8
  "kind": {
9
9
  "description": "This object's kind",
10
10
  "type": "string",
11
- "const": "PluginSigning"
11
+ "const": "PluginSigningCredentials"
12
12
  },
13
13
  "plugin-signing-keystore": {
14
14
  "description": "A path to the plugin signing keystore",
@@ -1,4 +1,4 @@
1
- Copyright (c) 2000-2022, Board of Trustees of Leland Stanford Jr. University
1
+ Copyright (c) 2000-2023, Board of Trustees of Leland Stanford Jr. University
2
2
 
3
3
  Redistribution and use in source and binary forms, with or without
4
4
  modification, are permitted provided that the following conditions are met: