lockss-turtles 0.6.0.dev25__py3-none-any.whl → 0.6.0.dev27__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 +1 -1
- lockss/turtles/plugin_set.py +2 -2
- lockss/turtles/plugin_signing_credentials.py +8 -4
- {lockss_turtles-0.6.0.dev25.dist-info → lockss_turtles-0.6.0.dev27.dist-info}/METADATA +2 -2
- lockss_turtles-0.6.0.dev27.dist-info/RECORD +18 -0
- unittest/lockss/turtles/test_plugin_registry.py +6 -0
- unittest/lockss/turtles/test_plugin_set.py +6 -4
- unittest/lockss/turtles/test_plugin_signing_credentials.py +102 -0
- lockss_turtles-0.6.0.dev25.dist-info/RECORD +0 -17
- {lockss_turtles-0.6.0.dev25.dist-info → lockss_turtles-0.6.0.dev27.dist-info}/WHEEL +0 -0
- {lockss_turtles-0.6.0.dev25.dist-info → lockss_turtles-0.6.0.dev27.dist-info}/entry_points.txt +0 -0
- {lockss_turtles-0.6.0.dev25.dist-info → lockss_turtles-0.6.0.dev27.dist-info}/licenses/LICENSE +0 -0
lockss/turtles/__init__.py
CHANGED
lockss/turtles/plugin_set.py
CHANGED
|
@@ -293,7 +293,7 @@ class MavenPluginSetBuilder(BasePluginSetBuilder):
|
|
|
293
293
|
:param keystore_alias: The alias to use in the plugin signing keystore.
|
|
294
294
|
:type keystore_alias: str
|
|
295
295
|
:param keystore_password: The plugin signing password.
|
|
296
|
-
:type keystore_password:
|
|
296
|
+
:type keystore_password: Optional[Callable[[], str]]
|
|
297
297
|
:raises subprocess.CalledProcessError: If a subprocess fails.
|
|
298
298
|
"""
|
|
299
299
|
if not self._built:
|
|
@@ -302,7 +302,7 @@ class MavenPluginSetBuilder(BasePluginSetBuilder):
|
|
|
302
302
|
f'-Dkeystore.file={keystore_path!s}',
|
|
303
303
|
f'-Dkeystore.alias={keystore_alias}']
|
|
304
304
|
if keystore_password:
|
|
305
|
-
cmd.
|
|
305
|
+
cmd.append(f'-Dkeystore.password={keystore_password()}')
|
|
306
306
|
try:
|
|
307
307
|
subprocess.run(cmd, cwd=self.get_root(), check=True, stdout=sys.stdout, stderr=sys.stderr)
|
|
308
308
|
except subprocess.CalledProcessError as cpe:
|
|
@@ -35,7 +35,7 @@ Module to represent plugin signing credentials.
|
|
|
35
35
|
from pathlib import Path
|
|
36
36
|
from typing import Literal
|
|
37
37
|
|
|
38
|
-
from pydantic
|
|
38
|
+
from pydantic import Field
|
|
39
39
|
|
|
40
40
|
from .util import BaseModelWithRoot
|
|
41
41
|
|
|
@@ -52,13 +52,17 @@ class PluginSigningCredentials(BaseModelWithRoot):
|
|
|
52
52
|
|
|
53
53
|
#: This object's kind.
|
|
54
54
|
kind: PluginSigningCredentialsKind = Field(title='Kind',
|
|
55
|
-
|
|
55
|
+
description="This object's kind")
|
|
56
56
|
|
|
57
57
|
#: Path to the plugin signing keystore.
|
|
58
|
-
plugin_signing_keystore: str = Field(
|
|
58
|
+
plugin_signing_keystore: str = Field(alias='plugin-signing-keystore',
|
|
59
|
+
title='Plugin Signing Keystore',
|
|
60
|
+
description='A path to the plugin signing keystore')
|
|
59
61
|
|
|
60
62
|
#: Alias to use from the plugin signing keystore.
|
|
61
|
-
plugin_signing_alias: str = Field(
|
|
63
|
+
plugin_signing_alias: str = Field(alias='plugin-signing-alias',
|
|
64
|
+
title='Plugin Signing Alias',
|
|
65
|
+
description='The plugin signing alias to use')
|
|
62
66
|
|
|
63
67
|
def get_plugin_signing_alias(self) -> str:
|
|
64
68
|
"""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lockss-turtles
|
|
3
|
-
Version: 0.6.0.
|
|
3
|
+
Version: 0.6.0.dev27
|
|
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
|
License-File: LICENSE
|
|
@@ -35,7 +35,7 @@ Description-Content-Type: text/x-rst
|
|
|
35
35
|
Turtles
|
|
36
36
|
=======
|
|
37
37
|
|
|
38
|
-
.. |RELEASE| replace:: 0.6.0-
|
|
38
|
+
.. |RELEASE| replace:: 0.6.0-dev27 NOT YET RELEASED
|
|
39
39
|
.. |RELEASE_DATE| replace:: NOT YET RELEASED
|
|
40
40
|
.. |TURTLES| replace:: **Turtles**
|
|
41
41
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
lockss/turtles/__init__.py,sha256=P1XcKk4CYzKllNxexHpDFA3wntLuU2VsZNeaw2yBhkE,1827
|
|
2
|
+
lockss/turtles/__main__.py,sha256=BqRTG3dejCgLh87UJ1Os9DD9unxnQkOdUQM6eqWS3Sg,1680
|
|
3
|
+
lockss/turtles/app.py,sha256=XnBF91r-D3YGSfgIP0v9C064fH8Rc6y4I5y1arEweCQ,30520
|
|
4
|
+
lockss/turtles/cli.py,sha256=x4Ciba5fcDSNeYAhhauOeCP1FcMy5ptOts32CWG3la4,30546
|
|
5
|
+
lockss/turtles/plugin.py,sha256=fxIAaSL06uv9sjYCz2wTQjn_92qPK3EvGNnbkpeSZcA,10972
|
|
6
|
+
lockss/turtles/plugin_registry.py,sha256=8BR6CrqY8hh4zpy13B8gZ9qpCMASlOxvX6g8VmpWeMc,26864
|
|
7
|
+
lockss/turtles/plugin_set.py,sha256=QCUWh56NV5YMQmZIz3-9DYHZI42BC3Aain5mxax7x9o,24668
|
|
8
|
+
lockss/turtles/plugin_signing_credentials.py,sha256=EekUJeXvbfRcrVHCsvvbGBO07bSBzEgVL1Ck4TUbe8k,3415
|
|
9
|
+
lockss/turtles/util.py,sha256=sBvB96BBED_yVZOybcf-sIwldNm9wstgWssnhugpww0,3536
|
|
10
|
+
unittest/lockss/turtles/__init__.py,sha256=ude-nT_uHF0lCD9qKrzedm8QvwqTiNjogpyz8SJudOQ,5598
|
|
11
|
+
unittest/lockss/turtles/test_plugin_registry.py,sha256=NXQyvvV3u1Pk3h5e-W7F93NIL6rYrv3bN_N4TFuZ0_U,18644
|
|
12
|
+
unittest/lockss/turtles/test_plugin_set.py,sha256=SJ2IO3sVOkm1zRr4a9SbyMhKpyKZAzoDV1oVfya3eEU,10949
|
|
13
|
+
unittest/lockss/turtles/test_plugin_signing_credentials.py,sha256=oxAKxeIEATNu3dIajcAFy-gEChMDCHSSDjZotuAB49o,5269
|
|
14
|
+
lockss_turtles-0.6.0.dev27.dist-info/METADATA,sha256=LqVEn6pJGDdsyD7xxTX5tCkAhKcZZU5xKnL3_cLXV1k,2362
|
|
15
|
+
lockss_turtles-0.6.0.dev27.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
16
|
+
lockss_turtles-0.6.0.dev27.dist-info/entry_points.txt,sha256=25BAVFSBRKWAWiXIGZgcr1ypt2mV7nj31Jl8WcNZZOk,51
|
|
17
|
+
lockss_turtles-0.6.0.dev27.dist-info/licenses/LICENSE,sha256=O9ONND4uDxY_jucI4jZDf2liAk05ScEJaYu-Al7EOdQ,1506
|
|
18
|
+
lockss_turtles-0.6.0.dev27.dist-info/RECORD,,
|
|
@@ -259,6 +259,12 @@ class TestPluginRegistryLayer(PydanticTestCase):
|
|
|
259
259
|
for valid in self.valid:
|
|
260
260
|
self.assertEqual(valid.get_plugin_registry(), self.fake_plugin_registry)
|
|
261
261
|
|
|
262
|
+
def test_path_dot_works(self) -> None:
|
|
263
|
+
prl = PluginRegistryLayer(id='mylayer',
|
|
264
|
+
name='My Layer',
|
|
265
|
+
path='.').initialize(self.fake_plugin_registry)
|
|
266
|
+
self.assertEqual(prl.get_path(), ROOT)
|
|
267
|
+
|
|
262
268
|
|
|
263
269
|
class TestPluginRegistry(PydanticTestCase):
|
|
264
270
|
|
|
@@ -51,6 +51,7 @@ class TestPluginSetCatalog(PydanticTestCase):
|
|
|
51
51
|
'plugin-set-files': [
|
|
52
52
|
'one.yaml'
|
|
53
53
|
]}).initialize(ROOT)
|
|
54
|
+
self.valid = [self.valid_absolute, self.valid_relative]
|
|
54
55
|
|
|
55
56
|
def test_missing_kind(self) -> None:
|
|
56
57
|
self.assertPydanticMissing(lambda: PluginSetCatalog(),
|
|
@@ -85,8 +86,8 @@ class TestPluginSetCatalog(PydanticTestCase):
|
|
|
85
86
|
self.assertRaises(ValueError, lambda: psc.get_plugin_set_files())
|
|
86
87
|
|
|
87
88
|
def test_kind(self) -> None:
|
|
88
|
-
self.
|
|
89
|
-
|
|
89
|
+
for valid in self.valid:
|
|
90
|
+
self.assertEqual(valid.kind, 'PluginSetCatalog')
|
|
90
91
|
|
|
91
92
|
def test_get_plugin_set_files(self) -> None:
|
|
92
93
|
self.assertListEqual(self.valid_absolute.get_plugin_set_files(),
|
|
@@ -106,6 +107,7 @@ class _BasePluginSetBuilderTestCase(ABC, PydanticTestCase):
|
|
|
106
107
|
self.valid_relative = self.instance(type=self.type(),
|
|
107
108
|
main='maindir',
|
|
108
109
|
test='testdir').initialize(ROOT)
|
|
110
|
+
self.valid = [self.valid_absolute, self.valid_relative]
|
|
109
111
|
|
|
110
112
|
@abstractmethod
|
|
111
113
|
def instance(self, **kwargs) -> BasePluginSetBuilder:
|
|
@@ -157,8 +159,8 @@ class _BasePluginSetBuilderTestCase(ABC, PydanticTestCase):
|
|
|
157
159
|
self.assertRaises(ValueError, lambda: psb.get_test())
|
|
158
160
|
|
|
159
161
|
def test_get_type(self) -> None:
|
|
160
|
-
|
|
161
|
-
|
|
162
|
+
for valid in self.valid:
|
|
163
|
+
self.assertEqual(valid.get_type(), self.type())
|
|
162
164
|
|
|
163
165
|
def test_get_main(self) -> None:
|
|
164
166
|
self.assertEqual(self.valid_absolute.get_main(), Path('/tmp/maindir'))
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
# Copyright (c) 2000-2025, Board of Trustees of Leland Stanford Jr. University
|
|
4
|
+
#
|
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
|
7
|
+
#
|
|
8
|
+
# 1. Redistributions of source code must retain the above copyright notice,
|
|
9
|
+
# this list of conditions and the following disclaimer.
|
|
10
|
+
#
|
|
11
|
+
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
# this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
# and/or other materials provided with the distribution.
|
|
14
|
+
#
|
|
15
|
+
# 3. Neither the name of the copyright holder nor the names of its contributors
|
|
16
|
+
# may be used to endorse or promote products derived from this software without
|
|
17
|
+
# specific prior written permission.
|
|
18
|
+
#
|
|
19
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
20
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
21
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
22
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
23
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
24
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
25
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
26
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
27
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
28
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
29
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
|
30
|
+
|
|
31
|
+
# Remove in Python 3.14
|
|
32
|
+
# See https://stackoverflow.com/questions/33533148/how-do-i-type-hint-a-method-with-the-type-of-the-enclosing-class/33533514#33533514
|
|
33
|
+
from __future__ import annotations
|
|
34
|
+
|
|
35
|
+
from abc import ABC, abstractmethod
|
|
36
|
+
from pathlib import Path
|
|
37
|
+
|
|
38
|
+
from . import PydanticTestCase, ROOT
|
|
39
|
+
from lockss.turtles.plugin_signing_credentials import PluginSigningCredentials
|
|
40
|
+
|
|
41
|
+
class TestPluginSigningCredentials(PydanticTestCase):
|
|
42
|
+
|
|
43
|
+
def setUp(self) -> None:
|
|
44
|
+
super().setUp()
|
|
45
|
+
self.valid_absolute = PluginSigningCredentials(**{'kind': 'PluginSigningCredentials',
|
|
46
|
+
'plugin-signing-keystore': '/tmp/keystore.txt',
|
|
47
|
+
'plugin-signing-alias': 'myalias'}).initialize(ROOT)
|
|
48
|
+
self.valid_relative = PluginSigningCredentials(**{'kind': 'PluginSigningCredentials',
|
|
49
|
+
'plugin-signing-keystore': 'keystore.txt',
|
|
50
|
+
'plugin-signing-alias': 'myalias'}).initialize(ROOT)
|
|
51
|
+
self.valid = [self.valid_absolute, self.valid_relative]
|
|
52
|
+
|
|
53
|
+
def test_missing_kind(self) -> None:
|
|
54
|
+
self.assertPydanticMissing(lambda: PluginSigningCredentials(),
|
|
55
|
+
'kind')
|
|
56
|
+
|
|
57
|
+
def test_null_kind(self) -> None:
|
|
58
|
+
self.assertPydanticLiteralError(lambda: PluginSigningCredentials(kind=None),
|
|
59
|
+
'kind',
|
|
60
|
+
'PluginSigningCredentials')
|
|
61
|
+
|
|
62
|
+
def test_wrong_kind(self) -> None:
|
|
63
|
+
self.assertPydanticLiteralError(lambda: PluginSigningCredentials(kind='WrongKind'),
|
|
64
|
+
'kind',
|
|
65
|
+
'PluginSigningCredentials')
|
|
66
|
+
|
|
67
|
+
def test_missing_plugin_signing_alias(self) -> None:
|
|
68
|
+
self.assertPydanticMissing(lambda: PluginSigningCredentials(),
|
|
69
|
+
'plugin-signing-alias')
|
|
70
|
+
|
|
71
|
+
def test_null_plugin_signing_alias(self) -> None:
|
|
72
|
+
self.assertPydanticStringType(lambda: PluginSigningCredentials(**{'plugin-signing-alias': None}),
|
|
73
|
+
'plugin-signing-alias')
|
|
74
|
+
|
|
75
|
+
def test_missing_plugin_signing_keystore(self) -> None:
|
|
76
|
+
self.assertPydanticMissing(lambda: PluginSigningCredentials(),
|
|
77
|
+
'plugin-signing-keystore')
|
|
78
|
+
|
|
79
|
+
def test_null_plugin_signing_keystore(self) -> None:
|
|
80
|
+
self.assertPydanticStringType(lambda: PluginSigningCredentials(**{'plugin-signing-keystore': None}),
|
|
81
|
+
'plugin-signing-keystore')
|
|
82
|
+
|
|
83
|
+
def test_uninitialized(self) -> None:
|
|
84
|
+
psc = PluginSigningCredentials(**{'kind': 'PluginSigningCredentials',
|
|
85
|
+
'plugin-signing-keystore': '/tmp/keystore.txt',
|
|
86
|
+
'plugin-signing-alias': 'myalias'})
|
|
87
|
+
self.assertRaises(ValueError, lambda: psc.get_root())
|
|
88
|
+
self.assertRaises(ValueError, lambda: psc.get_plugin_signing_keystore())
|
|
89
|
+
|
|
90
|
+
def test_kind(self) -> None:
|
|
91
|
+
for valid in self.valid:
|
|
92
|
+
self.assertEqual(valid.kind, 'PluginSigningCredentials')
|
|
93
|
+
|
|
94
|
+
def test_get_plugin_signing_alias(self) -> None:
|
|
95
|
+
for valid in self.valid:
|
|
96
|
+
self.assertEqual(valid.get_plugin_signing_alias(), 'myalias')
|
|
97
|
+
|
|
98
|
+
def test_get_plugin_signing_keystore(self) -> None:
|
|
99
|
+
self.assertEqual(self.valid_absolute.get_plugin_signing_keystore(),
|
|
100
|
+
Path('/tmp/keystore.txt'))
|
|
101
|
+
self.assertEqual(self.valid_relative.get_plugin_signing_keystore(),
|
|
102
|
+
ROOT.joinpath('keystore.txt'))
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
lockss/turtles/__init__.py,sha256=6HUyqmH9_7cfWBkAGl3hejHhz3eXkpNtw3ndfcS5044,1827
|
|
2
|
-
lockss/turtles/__main__.py,sha256=BqRTG3dejCgLh87UJ1Os9DD9unxnQkOdUQM6eqWS3Sg,1680
|
|
3
|
-
lockss/turtles/app.py,sha256=XnBF91r-D3YGSfgIP0v9C064fH8Rc6y4I5y1arEweCQ,30520
|
|
4
|
-
lockss/turtles/cli.py,sha256=x4Ciba5fcDSNeYAhhauOeCP1FcMy5ptOts32CWG3la4,30546
|
|
5
|
-
lockss/turtles/plugin.py,sha256=fxIAaSL06uv9sjYCz2wTQjn_92qPK3EvGNnbkpeSZcA,10972
|
|
6
|
-
lockss/turtles/plugin_registry.py,sha256=8BR6CrqY8hh4zpy13B8gZ9qpCMASlOxvX6g8VmpWeMc,26864
|
|
7
|
-
lockss/turtles/plugin_set.py,sha256=4fUmpp_GF_WY06gyhm9tVofYINoTXYUqAvKik3Z4bE4,24640
|
|
8
|
-
lockss/turtles/plugin_signing_credentials.py,sha256=1ktGascqT2UM6o4ipMS_M80haWA8IzUXFYqzuWUNUJU,3254
|
|
9
|
-
lockss/turtles/util.py,sha256=sBvB96BBED_yVZOybcf-sIwldNm9wstgWssnhugpww0,3536
|
|
10
|
-
unittest/lockss/turtles/__init__.py,sha256=ude-nT_uHF0lCD9qKrzedm8QvwqTiNjogpyz8SJudOQ,5598
|
|
11
|
-
unittest/lockss/turtles/test_plugin_registry.py,sha256=PIBeAKoDudInJOGhwTSug_b4AugGtK5yFmapUtQYTNw,18372
|
|
12
|
-
unittest/lockss/turtles/test_plugin_set.py,sha256=I1GNKlFcG_b906vsk12xOq0Y2Jer-vdF7VH9qszlw2w,10916
|
|
13
|
-
lockss_turtles-0.6.0.dev25.dist-info/METADATA,sha256=jDXEkuRovEbrWYawuPRSrqc6igOYJ9l2hJHTFfCuqy4,2362
|
|
14
|
-
lockss_turtles-0.6.0.dev25.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
15
|
-
lockss_turtles-0.6.0.dev25.dist-info/entry_points.txt,sha256=25BAVFSBRKWAWiXIGZgcr1ypt2mV7nj31Jl8WcNZZOk,51
|
|
16
|
-
lockss_turtles-0.6.0.dev25.dist-info/licenses/LICENSE,sha256=O9ONND4uDxY_jucI4jZDf2liAk05ScEJaYu-Al7EOdQ,1506
|
|
17
|
-
lockss_turtles-0.6.0.dev25.dist-info/RECORD,,
|
|
File without changes
|
{lockss_turtles-0.6.0.dev25.dist-info → lockss_turtles-0.6.0.dev27.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
{lockss_turtles-0.6.0.dev25.dist-info → lockss_turtles-0.6.0.dev27.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|