lockss-turtles 0.5.0.dev4__tar.gz → 0.6.0.dev1__tar.gz
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-0.5.0.dev4 → lockss_turtles-0.6.0.dev1}/CHANGELOG.rst +35 -1
- {lockss_turtles-0.5.0.dev4 → lockss_turtles-0.6.0.dev1}/LICENSE +1 -1
- {lockss_turtles-0.5.0.dev4 → lockss_turtles-0.6.0.dev1}/PKG-INFO +17 -19
- {lockss_turtles-0.5.0.dev4 → lockss_turtles-0.6.0.dev1}/README.rst +1 -1
- lockss_turtles-0.6.0.dev1/pyproject.toml +81 -0
- lockss_turtles-0.6.0.dev1/src/lockss/turtles/__init__.py +40 -0
- {lockss_turtles-0.5.0.dev4 → lockss_turtles-0.6.0.dev1}/src/lockss/turtles/__main__.py +3 -3
- {lockss_turtles-0.5.0.dev4 → lockss_turtles-0.6.0.dev1}/src/lockss/turtles/app.py +82 -75
- lockss_turtles-0.6.0.dev1/src/lockss/turtles/cli.py +285 -0
- {lockss_turtles-0.5.0.dev4 → lockss_turtles-0.6.0.dev1}/src/lockss/turtles/plugin.py +64 -55
- {lockss_turtles-0.5.0.dev4 → lockss_turtles-0.6.0.dev1}/src/lockss/turtles/plugin_registry.py +90 -79
- {lockss_turtles-0.5.0.dev4 → lockss_turtles-0.6.0.dev1}/src/lockss/turtles/plugin_set.py +95 -87
- {lockss_turtles-0.5.0.dev4 → lockss_turtles-0.6.0.dev1}/src/lockss/turtles/resources/__init__.py +1 -1
- {lockss_turtles-0.5.0.dev4 → lockss_turtles-0.6.0.dev1}/src/lockss/turtles/util.py +8 -10
- lockss_turtles-0.5.0.dev4/pyproject.toml +0 -41
- lockss_turtles-0.5.0.dev4/src/lockss/turtles/__init__.py +0 -63
- lockss_turtles-0.5.0.dev4/src/lockss/turtles/cli.py +0 -446
- {lockss_turtles-0.5.0.dev4 → lockss_turtles-0.6.0.dev1}/src/lockss/turtles/resources/plugin-registry-catalog-schema.json +0 -0
- {lockss_turtles-0.5.0.dev4 → lockss_turtles-0.6.0.dev1}/src/lockss/turtles/resources/plugin-registry-schema.json +0 -0
- {lockss_turtles-0.5.0.dev4 → lockss_turtles-0.6.0.dev1}/src/lockss/turtles/resources/plugin-set-catalog-schema.json +0 -0
- {lockss_turtles-0.5.0.dev4 → lockss_turtles-0.6.0.dev1}/src/lockss/turtles/resources/plugin-set-schema.json +0 -0
- {lockss_turtles-0.5.0.dev4 → lockss_turtles-0.6.0.dev1}/src/lockss/turtles/resources/plugin-signing-credentials-schema.json +0 -0
|
@@ -3,13 +3,47 @@ Release Notes
|
|
|
3
3
|
=============
|
|
4
4
|
|
|
5
5
|
-----
|
|
6
|
-
0.
|
|
6
|
+
0.6.0
|
|
7
7
|
-----
|
|
8
8
|
|
|
9
9
|
Released: ?
|
|
10
10
|
|
|
11
11
|
* **Features**
|
|
12
12
|
|
|
13
|
+
* Now using type hinting throughout.
|
|
14
|
+
|
|
15
|
+
* Now using *lockss-pybasic* and *pydantic-argparse* internally.
|
|
16
|
+
|
|
17
|
+
* **Changes**
|
|
18
|
+
|
|
19
|
+
* Some long options have been renamed (the short options remain unchanged):
|
|
20
|
+
|
|
21
|
+
============ ================= =============
|
|
22
|
+
Short option Version 0.5.0 Version 0.6.0
|
|
23
|
+
============ ================= =============
|
|
24
|
+
``-i`` ``--identifier`` ``--plugin-identifier``
|
|
25
|
+
``-I`` ``--identifiers`` ``--plugin-identifiers``
|
|
26
|
+
``-j`` ``--jar`` ``--plugin-jar``
|
|
27
|
+
``-J`` ``--jars`` ``--plugin-jars``
|
|
28
|
+
``-l`` ``--layer`` ``--plugin-registry-layer``
|
|
29
|
+
``-L`` ``--layers`` ``--plugin-registry-layers``
|
|
30
|
+
n/a ``--password`` ``--plugin-signing-password``
|
|
31
|
+
============ ================= =============
|
|
32
|
+
|
|
33
|
+
* Bare arguments are no longer allowed and treated as plugin identifiers or plugin JARs; all plugin identifiers must be specified via ``--plugin-identifier/-i`` or ``--plugin-identifiers/-I`` options and all plugin JARS via ``--plugin-jar/-j`` or ``--plugin-jars/-J`` options.
|
|
34
|
+
|
|
35
|
+
* The ``usage`` command has been removed.
|
|
36
|
+
|
|
37
|
+
-----
|
|
38
|
+
0.5.0
|
|
39
|
+
-----
|
|
40
|
+
|
|
41
|
+
Released: 2024-09-04
|
|
42
|
+
|
|
43
|
+
* **Features**
|
|
44
|
+
|
|
45
|
+
* ``AntPluginSet``: also include plugin auxiliary packages (``plugin_aux_packages``).
|
|
46
|
+
|
|
13
47
|
-----
|
|
14
48
|
0.4.0
|
|
15
49
|
-----
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Copyright (c) 2000-
|
|
1
|
+
Copyright (c) 2000-2025, 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:
|
|
@@ -1,31 +1,29 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
2
|
Name: lockss-turtles
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary:
|
|
5
|
-
Home-page: https://www.lockss.org/
|
|
3
|
+
Version: 0.6.0.dev1
|
|
4
|
+
Summary: Library and command line tool to manage LOCKSS plugin sets and LOCKSS plugin registries
|
|
6
5
|
License: BSD-3-Clause
|
|
7
6
|
Author: Thib Guicherd-Callin
|
|
8
7
|
Author-email: thib@cs.stanford.edu
|
|
9
|
-
|
|
8
|
+
Maintainer: Thib Guicherd-Callin
|
|
9
|
+
Maintainer-email: thib@cs.stanford.edu
|
|
10
|
+
Requires-Python: >=3.9,<4.0
|
|
10
11
|
Classifier: Development Status :: 5 - Production/Stable
|
|
11
12
|
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Framework :: Pydantic :: 2
|
|
12
14
|
Classifier: Intended Audience :: Developers
|
|
13
15
|
Classifier: Intended Audience :: System Administrators
|
|
14
16
|
Classifier: License :: OSI Approved :: BSD License
|
|
15
|
-
Classifier:
|
|
16
|
-
Classifier:
|
|
17
|
-
Classifier:
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python
|
|
18
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
19
|
+
Classifier: Topic :: System :: Archiving
|
|
22
20
|
Classifier: Topic :: Utilities
|
|
23
|
-
Requires-Dist: java-manifest (>=1.1.0,<2.0
|
|
24
|
-
Requires-Dist: jsonschema (>=4.
|
|
25
|
-
Requires-Dist:
|
|
26
|
-
Requires-Dist:
|
|
27
|
-
Requires-Dist:
|
|
28
|
-
Requires-Dist: xdg (>=6.0.0,<
|
|
21
|
+
Requires-Dist: java-manifest (>=1.1.0,<1.2.0)
|
|
22
|
+
Requires-Dist: jsonschema (>=4.24.0,<4.25.0)
|
|
23
|
+
Requires-Dist: lockss-pybasic (>=0.1.0,<0.2.0)
|
|
24
|
+
Requires-Dist: pydantic (>=2.11.7,<3.0.0)
|
|
25
|
+
Requires-Dist: pyyaml (>=6.0.0,<6.1.0)
|
|
26
|
+
Requires-Dist: xdg (>=6.0.0,<6.1.0)
|
|
29
27
|
Project-URL: Repository, https://github.com/lockss/lockss-turtles
|
|
30
28
|
Description-Content-Type: text/x-rst
|
|
31
29
|
|
|
@@ -33,7 +31,7 @@ Description-Content-Type: text/x-rst
|
|
|
33
31
|
Turtles
|
|
34
32
|
=======
|
|
35
33
|
|
|
36
|
-
.. |RELEASE| replace:: 0.
|
|
34
|
+
.. |RELEASE| replace:: 0.6.0-dev1
|
|
37
35
|
.. |RELEASE_DATE| replace:: ?
|
|
38
36
|
|
|
39
37
|
.. |HELP| replace:: ``--help/-h``
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Copyright (c) 2000-2025, Board of Trustees of Leland Stanford Jr. University
|
|
2
|
+
#
|
|
3
|
+
# Redistribution and use in source and binary forms, with or without
|
|
4
|
+
# modification, are permitted provided that the following conditions are met:
|
|
5
|
+
#
|
|
6
|
+
# 1. Redistributions of source code must retain the above copyright notice,
|
|
7
|
+
# this list of conditions and the following disclaimer.
|
|
8
|
+
#
|
|
9
|
+
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
10
|
+
# this list of conditions and the following disclaimer in the documentation
|
|
11
|
+
# and/or other materials provided with the distribution.
|
|
12
|
+
#
|
|
13
|
+
# 3. Neither the name of the copyright holder nor the names of its contributors
|
|
14
|
+
# may be used to endorse or promote products derived from this software without
|
|
15
|
+
# specific prior written permission.
|
|
16
|
+
#
|
|
17
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
18
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
19
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
20
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
21
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
22
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
23
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
24
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
25
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
26
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
27
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
|
28
|
+
|
|
29
|
+
[project]
|
|
30
|
+
name = "lockss-turtles"
|
|
31
|
+
version = "0.6.0-dev1" # Always change in __init__.py, and at release time in README.rst and CHANGELOG.rst
|
|
32
|
+
description = "Library and command line tool to manage LOCKSS plugin sets and LOCKSS plugin registries"
|
|
33
|
+
license = { text = "BSD-3-Clause" }
|
|
34
|
+
readme = "README.rst"
|
|
35
|
+
requires-python = ">=3.9,<4.0"
|
|
36
|
+
authors = [
|
|
37
|
+
{ name = "Thib Guicherd-Callin", email = "thib@cs.stanford.edu" },
|
|
38
|
+
]
|
|
39
|
+
maintainers = [
|
|
40
|
+
{ name = "Thib Guicherd-Callin", email = "thib@cs.stanford.edu" }
|
|
41
|
+
]
|
|
42
|
+
dependencies = [
|
|
43
|
+
"java-manifest (>=1.1.0,<1.2.0)",
|
|
44
|
+
"jsonschema (>=4.24.0,<4.25.0)",
|
|
45
|
+
"lockss-pybasic (>=0.1.0,<0.2.0)",
|
|
46
|
+
"pyyaml (>=6.0.0,<6.1.0)",
|
|
47
|
+
"xdg (>=6.0.0,<6.1.0)",
|
|
48
|
+
"pydantic (>=2.11.7,<3.0.0)",
|
|
49
|
+
]
|
|
50
|
+
classifiers = [
|
|
51
|
+
"Development Status :: 5 - Production/Stable",
|
|
52
|
+
"Environment :: Console",
|
|
53
|
+
"Framework :: Pydantic :: 2",
|
|
54
|
+
"Intended Audience :: Developers",
|
|
55
|
+
"Intended Audience :: System Administrators",
|
|
56
|
+
"License :: OSI Approved :: BSD License",
|
|
57
|
+
"Programming Language :: Python",
|
|
58
|
+
"Topic :: Software Development :: Libraries",
|
|
59
|
+
"Topic :: System :: Archiving",
|
|
60
|
+
"Topic :: Utilities",
|
|
61
|
+
]
|
|
62
|
+
|
|
63
|
+
[project.urls]
|
|
64
|
+
repository = "https://github.com/lockss/lockss-turtles"
|
|
65
|
+
|
|
66
|
+
[tool.poetry]
|
|
67
|
+
include = [
|
|
68
|
+
"CHANGELOG.rst",
|
|
69
|
+
"LICENSE",
|
|
70
|
+
"README.rst",
|
|
71
|
+
]
|
|
72
|
+
packages = [
|
|
73
|
+
{ include = "lockss", from = "src" }
|
|
74
|
+
]
|
|
75
|
+
|
|
76
|
+
[tool.poetry.scripts]
|
|
77
|
+
turtles = 'lockss.turtles.cli:main'
|
|
78
|
+
|
|
79
|
+
[build-system]
|
|
80
|
+
requires = ["poetry-core>=2.0.0,<3.0.0"]
|
|
81
|
+
build-backend = "poetry.core.masonry.api"
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Library and command line tool to manage LOCKSS plugin sets and LOCKSS plugin
|
|
5
|
+
registries.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
__version__ = '0.6.0-dev1'
|
|
9
|
+
|
|
10
|
+
__copyright__ = '''
|
|
11
|
+
Copyright (c) 2000-2025, Board of Trustees of Leland Stanford Jr. University
|
|
12
|
+
'''.strip()
|
|
13
|
+
|
|
14
|
+
__license__ = __copyright__ + '\n\n' + '''
|
|
15
|
+
Redistribution and use in source and binary forms, with or without
|
|
16
|
+
modification, are permitted provided that the following conditions are met:
|
|
17
|
+
|
|
18
|
+
1. Redistributions of source code must retain the above copyright notice,
|
|
19
|
+
this list of conditions and the following disclaimer.
|
|
20
|
+
|
|
21
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
22
|
+
this list of conditions and the following disclaimer in the documentation
|
|
23
|
+
and/or other materials provided with the distribution.
|
|
24
|
+
|
|
25
|
+
3. Neither the name of the copyright holder nor the names of its contributors
|
|
26
|
+
may be used to endorse or promote products derived from this software without
|
|
27
|
+
specific prior written permission.
|
|
28
|
+
|
|
29
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
30
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
31
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
32
|
+
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
33
|
+
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
34
|
+
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
35
|
+
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
36
|
+
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
37
|
+
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
38
|
+
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
39
|
+
POSSIBILITY OF SUCH DAMAGE.
|
|
40
|
+
'''.strip()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
|
|
3
|
-
# Copyright (c) 2000-
|
|
3
|
+
# Copyright (c) 2000-2025, Board of Trustees of Leland Stanford Jr. University
|
|
4
4
|
#
|
|
5
5
|
# Redistribution and use in source and binary forms, with or without
|
|
6
6
|
# modification, are permitted provided that the following conditions are met:
|
|
@@ -28,6 +28,6 @@
|
|
|
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
|
-
|
|
31
|
+
from lockss.turtles.cli import main
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
main()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
|
|
3
|
-
# Copyright (c) 2000-
|
|
3
|
+
# Copyright (c) 2000-2025, Board of Trustees of Leland Stanford Jr. University
|
|
4
4
|
#
|
|
5
5
|
# Redistribution and use in source and binary forms, with or without
|
|
6
6
|
# modification, are permitted provided that the following conditions are met:
|
|
@@ -28,103 +28,79 @@
|
|
|
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
|
-
import
|
|
31
|
+
from collections.abc import Callable
|
|
32
|
+
import importlib.resources as IR
|
|
32
33
|
from pathlib import Path
|
|
34
|
+
from typing import Dict, List, Optional, Tuple, Union
|
|
33
35
|
|
|
36
|
+
from lockss.pybasic.fileutil import path
|
|
34
37
|
import xdg
|
|
35
38
|
|
|
36
|
-
from
|
|
37
|
-
from
|
|
38
|
-
from
|
|
39
|
-
import
|
|
40
|
-
from
|
|
39
|
+
from . import resources as __resources__
|
|
40
|
+
from .plugin import Plugin
|
|
41
|
+
from .plugin_registry import PluginRegistry, PluginRegistryCatalog
|
|
42
|
+
from .plugin_set import PluginSet, PluginSetCatalog
|
|
43
|
+
from .util import YamlT, load_and_validate
|
|
41
44
|
|
|
42
45
|
|
|
43
46
|
class TurtlesApp(object):
|
|
44
47
|
|
|
45
|
-
XDG_CONFIG_DIR = xdg.xdg_config_home().joinpath(__package__)
|
|
48
|
+
XDG_CONFIG_DIR: Path = xdg.xdg_config_home().joinpath(__package__)
|
|
46
49
|
|
|
47
|
-
USR_CONFIG_DIR = Path('/usr/local/share', __package__)
|
|
50
|
+
USR_CONFIG_DIR: Path = Path('/usr/local/share', __package__)
|
|
48
51
|
|
|
49
|
-
ETC_CONFIG_DIR = Path('/etc', __package__)
|
|
52
|
+
ETC_CONFIG_DIR: Path = Path('/etc', __package__)
|
|
50
53
|
|
|
51
|
-
CONFIG_DIRS = [XDG_CONFIG_DIR, USR_CONFIG_DIR, ETC_CONFIG_DIR]
|
|
54
|
+
CONFIG_DIRS: List[Path] = [XDG_CONFIG_DIR, USR_CONFIG_DIR, ETC_CONFIG_DIR]
|
|
52
55
|
|
|
53
|
-
PLUGIN_REGISTRY_CATALOG = 'plugin-registry-catalog.yaml'
|
|
56
|
+
PLUGIN_REGISTRY_CATALOG: str = 'plugin-registry-catalog.yaml'
|
|
54
57
|
|
|
55
|
-
PLUGIN_SET_CATALOG = 'plugin-set-catalog.yaml'
|
|
58
|
+
PLUGIN_SET_CATALOG: str = 'plugin-set-catalog.yaml'
|
|
56
59
|
|
|
57
|
-
PLUGIN_SIGNING_CREDENTIALS = 'plugin-signing-credentials.yaml'
|
|
60
|
+
PLUGIN_SIGNING_CREDENTIALS: str = 'plugin-signing-credentials.yaml'
|
|
58
61
|
|
|
59
|
-
PLUGIN_SIGNING_CREDENTIALS_SCHEMA = 'plugin-signing-credentials-schema.json'
|
|
62
|
+
PLUGIN_SIGNING_CREDENTIALS_SCHEMA: str = 'plugin-signing-credentials-schema.json'
|
|
60
63
|
|
|
61
|
-
|
|
62
|
-
def _default_files(file_str):
|
|
63
|
-
return [dir_path.joinpath(file_str) for dir_path in TurtlesApp.CONFIG_DIRS]
|
|
64
|
-
|
|
65
|
-
@staticmethod
|
|
66
|
-
def _select_file(file_str, preselected=None):
|
|
67
|
-
if preselected:
|
|
68
|
-
preselected = _path(preselected)
|
|
69
|
-
if not preselected.is_file():
|
|
70
|
-
raise FileNotFoundError(str(preselected))
|
|
71
|
-
return preselected
|
|
72
|
-
choices = TurtlesApp._default_files(file_str)
|
|
73
|
-
ret = next(filter(Path.is_file, choices), None)
|
|
74
|
-
if ret is None:
|
|
75
|
-
raise FileNotFoundError(' or '.join(map(str, choices)))
|
|
76
|
-
return ret
|
|
77
|
-
|
|
78
|
-
def __init__(self):
|
|
64
|
+
def __init__(self) -> None:
|
|
79
65
|
super().__init__()
|
|
80
|
-
self._password = None
|
|
81
|
-
self._plugin_registries = None
|
|
82
|
-
self._plugin_sets = None
|
|
83
|
-
self._plugin_signing_credentials = None
|
|
66
|
+
self._password: Optional[Callable[[], str]] = None
|
|
67
|
+
self._plugin_registries: Optional[List[PluginRegistry]] = None
|
|
68
|
+
self._plugin_sets: Optional[List[PluginSet]] = None
|
|
69
|
+
self._plugin_signing_credentials: YamlT = None
|
|
84
70
|
|
|
85
|
-
|
|
86
|
-
def build_plugin(self, plugin_ids):
|
|
71
|
+
def build_plugin(self, plugin_ids: List[str]) -> Dict[str, Tuple[str, Path, Plugin]]:
|
|
87
72
|
return {plugin_id: self._build_one_plugin(plugin_id) for plugin_id in plugin_ids}
|
|
88
73
|
|
|
89
|
-
def default_plugin_registry_catalogs(self):
|
|
90
|
-
return TurtlesApp._default_files(TurtlesApp.PLUGIN_REGISTRY_CATALOG)
|
|
91
|
-
|
|
92
|
-
def default_plugin_set_catalogs(self):
|
|
93
|
-
return TurtlesApp._default_files(TurtlesApp.PLUGIN_SET_CATALOG)
|
|
94
|
-
|
|
95
|
-
def default_plugin_signing_credentials(self):
|
|
96
|
-
return TurtlesApp._default_files(TurtlesApp.PLUGIN_SIGNING_CREDENTIALS)
|
|
97
|
-
|
|
98
74
|
# Returns (src_path, plugin_id) -> list of (registry_id, layer_id, dst_path, plugin)
|
|
99
|
-
def deploy_plugin(self, src_paths, layer_ids, interactive=False):
|
|
75
|
+
def deploy_plugin(self, src_paths: List[Path], layer_ids: List[str], interactive: bool=False) -> Dict[Tuple[Path, str], List[Tuple[str, str, Optional[Path], Optional[Plugin]]]]:
|
|
100
76
|
plugin_ids = [Plugin.id_from_jar(src_path) for src_path in src_paths]
|
|
101
77
|
return {(src_path, plugin_id): self._deploy_one_plugin(src_path,
|
|
102
78
|
plugin_id,
|
|
103
79
|
layer_ids,
|
|
104
80
|
interactive=interactive) for src_path, plugin_id in zip(src_paths, plugin_ids)}
|
|
105
81
|
|
|
106
|
-
def load_plugin_registries(self, plugin_registry_catalog_path=None):
|
|
82
|
+
def load_plugin_registries(self, plugin_registry_catalog_path: Optional[Union[Path, str]]=None) -> None:
|
|
107
83
|
if self._plugin_registries is None:
|
|
108
84
|
plugin_registry_catalog = PluginRegistryCatalog.from_path(self.select_plugin_registry_catalog(plugin_registry_catalog_path))
|
|
109
85
|
self._plugin_registries = list()
|
|
110
86
|
for plugin_registry_file in plugin_registry_catalog.get_plugin_registry_files():
|
|
111
87
|
self._plugin_registries.extend(PluginRegistry.from_path(plugin_registry_file))
|
|
112
88
|
|
|
113
|
-
def load_plugin_sets(self, plugin_set_catalog_path=None):
|
|
89
|
+
def load_plugin_sets(self, plugin_set_catalog_path: Optional[Union[Path, str]]=None) -> None:
|
|
114
90
|
if self._plugin_sets is None:
|
|
115
91
|
plugin_set_catalog = PluginSetCatalog.from_path(self.select_plugin_set_catalog(plugin_set_catalog_path))
|
|
116
92
|
self._plugin_sets = list()
|
|
117
93
|
for plugin_set_file in plugin_set_catalog.get_plugin_set_files():
|
|
118
94
|
self._plugin_sets.extend(PluginSet.from_path(plugin_set_file))
|
|
119
95
|
|
|
120
|
-
def load_plugin_signing_credentials(self, plugin_signing_credentials_path=None):
|
|
96
|
+
def load_plugin_signing_credentials(self, plugin_signing_credentials_path: Optional[Union[Path, str]]=None) -> None:
|
|
121
97
|
if self._plugin_signing_credentials is None:
|
|
122
|
-
plugin_signing_credentials_path =
|
|
123
|
-
with
|
|
124
|
-
self._plugin_signing_credentials =
|
|
98
|
+
plugin_signing_credentials_path = path(plugin_signing_credentials_path) if plugin_signing_credentials_path else self._select_file(TurtlesApp.PLUGIN_SIGNING_CREDENTIALS)
|
|
99
|
+
with IR.path(__resources__, TurtlesApp.PLUGIN_SIGNING_CREDENTIALS_SCHEMA) as plugin_signing_credentials_schema_path:
|
|
100
|
+
self._plugin_signing_credentials = load_and_validate(plugin_signing_credentials_schema_path, plugin_signing_credentials_path)
|
|
125
101
|
|
|
126
102
|
# Returns plugin_id -> list of (registry_id, layer_id, dst_path, plugin)
|
|
127
|
-
def release_plugin(self, plugin_ids, layer_ids, interactive=False):
|
|
103
|
+
def release_plugin(self, plugin_ids: List[str], layer_ids: List[str], interactive: bool=False) -> Dict[str, List[Tuple[str, str, Path, Plugin]]]:
|
|
128
104
|
# ... plugin_id -> (set_id, jar_path, plugin)
|
|
129
105
|
ret1 = self.build_plugin(plugin_ids)
|
|
130
106
|
jar_paths = [jar_path for set_id, jar_path, plugin in ret1.values()]
|
|
@@ -134,54 +110,85 @@ class TurtlesApp(object):
|
|
|
134
110
|
interactive=interactive)
|
|
135
111
|
return {plugin_id: val for (jar_path, plugin_id), val in ret2.items()}
|
|
136
112
|
|
|
137
|
-
def select_plugin_registry_catalog(self, preselected=None):
|
|
113
|
+
def select_plugin_registry_catalog(self, preselected: Optional[Union[Path, str]]=None) -> Path:
|
|
138
114
|
return TurtlesApp._select_file(TurtlesApp.PLUGIN_REGISTRY_CATALOG, preselected)
|
|
139
115
|
|
|
140
|
-
def select_plugin_set_catalog(self, preselected=None):
|
|
116
|
+
def select_plugin_set_catalog(self, preselected: Optional[Union[Path, str]]=None) -> Path:
|
|
141
117
|
return TurtlesApp._select_file(TurtlesApp.PLUGIN_SET_CATALOG, preselected)
|
|
142
118
|
|
|
143
|
-
def select_plugin_signing_credentials(self, preselected=None):
|
|
119
|
+
def select_plugin_signing_credentials(self, preselected: Optional[Union[Path, str]]=None) -> Path:
|
|
144
120
|
return TurtlesApp._select_file(TurtlesApp.PLUGIN_SIGNING_CREDENTIALS, preselected)
|
|
145
121
|
|
|
146
|
-
def set_password(self, pw):
|
|
147
|
-
self._password = pw if callable(pw) else lambda
|
|
122
|
+
def set_password(self, pw: Union[Callable[[], str], str]) -> None:
|
|
123
|
+
self._password = pw if callable(pw) else lambda: pw
|
|
148
124
|
|
|
149
125
|
# Returns (set_id, jar_path, plugin)
|
|
150
|
-
def _build_one_plugin(self, plugin_id):
|
|
126
|
+
def _build_one_plugin(self, plugin_id: str) -> Tuple[str, Optional[Path], Optional[Plugin]]:
|
|
151
127
|
for plugin_set in self._plugin_sets:
|
|
152
128
|
if plugin_set.has_plugin(plugin_id):
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
129
|
+
bp = plugin_set.build_plugin(plugin_id,
|
|
130
|
+
self._get_plugin_signing_keystore(),
|
|
131
|
+
self._get_plugin_signing_alias(),
|
|
132
|
+
self._get_plugin_signing_password())
|
|
133
|
+
return plugin_set.get_id(), bp[0] if bp else None, bp[1] if bp else None
|
|
158
134
|
raise Exception(f'{plugin_id}: not found in any plugin set')
|
|
159
135
|
|
|
160
136
|
# Returns list of (registry_id, layer_id, dst_path, plugin)
|
|
161
|
-
def _deploy_one_plugin(self, src_jar, plugin_id, layer_ids, interactive=False):
|
|
137
|
+
def _deploy_one_plugin(self, src_jar: Path, plugin_id: str, layer_ids: List[str], interactive: bool=False) -> List[Tuple[str, str, Optional[Path], Optional[Plugin]]]:
|
|
162
138
|
ret = list()
|
|
163
139
|
for plugin_registry in self._plugin_registries:
|
|
164
140
|
if plugin_registry.has_plugin(plugin_id):
|
|
165
141
|
for layer_id in layer_ids:
|
|
166
142
|
layer = plugin_registry.get_layer(layer_id)
|
|
167
143
|
if layer is not None:
|
|
144
|
+
dp = layer.deploy_plugin(plugin_id,
|
|
145
|
+
src_jar,
|
|
146
|
+
interactive=interactive)
|
|
168
147
|
ret.append((plugin_registry.get_id(),
|
|
169
148
|
layer.get_id(),
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
interactive=interactive)))
|
|
149
|
+
dp[0] if dp else None,
|
|
150
|
+
dp[1] if dp else None))
|
|
173
151
|
if len(ret) == 0:
|
|
174
152
|
raise Exception(f'{src_jar}: {plugin_id} not declared in any plugin registry')
|
|
175
153
|
return ret
|
|
176
154
|
|
|
177
|
-
def _get_password(self):
|
|
155
|
+
def _get_password(self) -> Optional[str]:
|
|
178
156
|
return self._password() if self._password else None
|
|
179
157
|
|
|
180
|
-
def _get_plugin_signing_alias(self):
|
|
158
|
+
def _get_plugin_signing_alias(self) -> str:
|
|
181
159
|
return self._plugin_signing_credentials['plugin-signing-alias']
|
|
182
160
|
|
|
183
|
-
def _get_plugin_signing_keystore(self):
|
|
161
|
+
def _get_plugin_signing_keystore(self) -> str:
|
|
184
162
|
return self._plugin_signing_credentials['plugin-signing-keystore']
|
|
185
163
|
|
|
186
|
-
def _get_plugin_signing_password(self):
|
|
164
|
+
def _get_plugin_signing_password(self) -> str:
|
|
187
165
|
return self._get_password()
|
|
166
|
+
|
|
167
|
+
@staticmethod
|
|
168
|
+
def default_plugin_registry_catalogs() -> List[Path]:
|
|
169
|
+
return TurtlesApp._default_files(TurtlesApp.PLUGIN_REGISTRY_CATALOG)
|
|
170
|
+
|
|
171
|
+
@staticmethod
|
|
172
|
+
def default_plugin_set_catalogs() -> List[Path]:
|
|
173
|
+
return TurtlesApp._default_files(TurtlesApp.PLUGIN_SET_CATALOG)
|
|
174
|
+
|
|
175
|
+
@staticmethod
|
|
176
|
+
def default_plugin_signing_credentials() -> List[Path]:
|
|
177
|
+
return TurtlesApp._default_files(TurtlesApp.PLUGIN_SIGNING_CREDENTIALS)
|
|
178
|
+
|
|
179
|
+
@staticmethod
|
|
180
|
+
def _default_files(file_str) -> List[Path]:
|
|
181
|
+
return [dir_path.joinpath(file_str) for dir_path in TurtlesApp.CONFIG_DIRS]
|
|
182
|
+
|
|
183
|
+
@staticmethod
|
|
184
|
+
def _select_file(file_str, preselected: Optional[Union[Path, str]]=None) -> Path:
|
|
185
|
+
if preselected:
|
|
186
|
+
preselected = path(preselected)
|
|
187
|
+
if not preselected.is_file():
|
|
188
|
+
raise FileNotFoundError(str(preselected))
|
|
189
|
+
return preselected
|
|
190
|
+
choices = TurtlesApp._default_files(file_str)
|
|
191
|
+
ret = next(filter(lambda f: f.is_file(), choices), None)
|
|
192
|
+
if ret is None:
|
|
193
|
+
raise FileNotFoundError(' or '.join(map(str, choices)))
|
|
194
|
+
return ret
|