Added a simple plugin validator
This commit is contained in:
parent
552146551c
commit
1a9001e956
3 changed files with 152 additions and 8 deletions
|
@ -25,6 +25,7 @@ Issues = "https://forge.monodon.me/Gnarwhal/sshare/issues"
|
|||
|
||||
[project.scripts]
|
||||
sshare = "sshare.main:main"
|
||||
sshare-validate = "sshare.validator:main"
|
||||
|
||||
[tool.setuptools_scm]
|
||||
version_file = "src/sshare/version.py"
|
||||
|
|
|
@ -21,11 +21,11 @@ from sshare import config_directory
|
|||
|
||||
class PluginLoader:
|
||||
@staticmethod
|
||||
def all(command_line=False, logger=None, config=None, flags=None):
|
||||
def all(command_line=False, logger=None, config=dict(), flags=dict()):
|
||||
return PluginLoader.internal(command_line, logger, config, flags) + PluginLoader.external(logger, config, flags)
|
||||
|
||||
@staticmethod
|
||||
def internal(command_line=False, logger=None, config=None, flags=None):
|
||||
def internal(command_line=False, logger=None, config=dict(), flags=dict()):
|
||||
return [
|
||||
Plugin.internal(plugin, logger, config, flags)
|
||||
for plugin
|
||||
|
@ -41,7 +41,7 @@ class PluginLoader:
|
|||
]
|
||||
|
||||
@staticmethod
|
||||
def external(logger=None, config=None, flags=None):
|
||||
def external(logger=None, config=dict(), flags=dict()):
|
||||
return [
|
||||
Plugin.external(plugin, logger, config, flags)
|
||||
for plugin
|
||||
|
@ -49,7 +49,7 @@ class PluginLoader:
|
|||
]
|
||||
|
||||
@staticmethod
|
||||
def at(logger=None, config=None, flags=None, *args):
|
||||
def at(logger=None, config=dict(), flags=dict(), *args):
|
||||
return [
|
||||
Plugin.external(plugin, logger, config, flags)
|
||||
for plugin
|
||||
|
@ -91,8 +91,19 @@ class PluginManager:
|
|||
|
||||
class Plugin:
|
||||
@staticmethod
|
||||
def types():
|
||||
return [ "logger", "source", "name", "upload", "location", "feedback" ]
|
||||
def types(methods=False):
|
||||
types = {
|
||||
"logger": { "info", "warn", "error" },
|
||||
"source": { "get_source" },
|
||||
"name": { "get_name" },
|
||||
"upload": { "upload" },
|
||||
"location": { "get_location" },
|
||||
"feedback": { "give_feedback"},
|
||||
}
|
||||
if methods:
|
||||
return types
|
||||
else:
|
||||
return types.keys()
|
||||
|
||||
def __init__(self, name, module, logger, external_config, external_flags):
|
||||
self.__dict__ = module.__dict__
|
||||
|
@ -169,11 +180,11 @@ class Plugin:
|
|||
return activate
|
||||
|
||||
@staticmethod
|
||||
def internal(name=None, logger=None, config=None, flags=None):
|
||||
def internal(name=None, logger=None, config=dict(), flags=dict()):
|
||||
return Plugin(name, importlib.import_module(f"sshare.plugins.{name}"), logger, config.get(name, dict()), flags.get(name, dict()))
|
||||
|
||||
@staticmethod
|
||||
def external(path, logger=None, config=None, flags=None):
|
||||
def external(path, logger=None, config=dict(), flags=dict()):
|
||||
module_spec = importlib.util.spec_from_file_location(
|
||||
path.stem,
|
||||
path.as_posix(),
|
||||
|
|
132
src/sshare/validator.py
Normal file
132
src/sshare/validator.py
Normal file
|
@ -0,0 +1,132 @@
|
|||
# This file is part of SSHare.
|
||||
#
|
||||
# SSHare is free software: you can redistribute it and/or modify it under the terms of
|
||||
# the GNU General Public License as published by the Free Software Foundation,
|
||||
# either version 3 of the License, or (at your option) any later version.
|
||||
#
|
||||
# SSHare is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# SSHare. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import argparse
|
||||
|
||||
from sshare import config_directory
|
||||
from sshare.plugin import Plugin
|
||||
from sshare.plugin import PluginLoader
|
||||
from sshare.version import version
|
||||
|
||||
def validate(plugin, quiet=False):
|
||||
def log(message):
|
||||
if not quiet:
|
||||
print(message)
|
||||
|
||||
error_count = 0
|
||||
def error(message, end=False):
|
||||
nonlocal error_count
|
||||
nonlocal log
|
||||
|
||||
if error_count == 0:
|
||||
log("[\033[91mFAILED\033[0m]")
|
||||
error_count = error_count + 1
|
||||
log(f"\033[91m => {message}\033[0m")
|
||||
|
||||
def success():
|
||||
nonlocal log
|
||||
|
||||
log(f"[\033[92mOK\033[0m]")
|
||||
|
||||
mandatory_keys = dict()
|
||||
def validate_type_and_add_keys(type):
|
||||
nonlocal mandatory_keys
|
||||
|
||||
types = Plugin.types(methods=True)
|
||||
if type in types:
|
||||
mandatory_keys[type] = types[type]
|
||||
|
||||
else:
|
||||
error(f"plugin_type '{type}' is not a valid plugin type")
|
||||
if not hasattr(plugin, "plugin_type"):
|
||||
error("must define plugin_type")
|
||||
else:
|
||||
if isinstance(plugin.plugin_type, set):
|
||||
for index, type in enumerate(plugin.plugin_type):
|
||||
validate_type_and_add_keys(type)
|
||||
elif isinstance(plugin.plugin_type, str):
|
||||
validate_type_and_add_keys(plugin.plugin_type)
|
||||
else:
|
||||
error("plugin_type must be either a string or a set of strings")
|
||||
|
||||
for type, keys in mandatory_keys.items():
|
||||
for key in keys:
|
||||
if not hasattr(plugin, key):
|
||||
error(f"plugin type '{type}' requires definition of '{key}' ")
|
||||
|
||||
if hasattr(plugin, "activate"):
|
||||
def validate_activate(args, type=None):
|
||||
def validate_activate_arg(arg):
|
||||
nonlocal plugin
|
||||
nonlocal type
|
||||
|
||||
if hasattr(plugin, "args"):
|
||||
if arg in plugin.args.keys():
|
||||
return
|
||||
error(f"activate arg '{arg}' does not exist in 'args'")
|
||||
if isinstance(args, set):
|
||||
for arg in args:
|
||||
validate_activate_arg(arg)
|
||||
else:
|
||||
validate_activate_arg(arg)
|
||||
|
||||
if isinstance(plugin.activate, dict):
|
||||
for type, args in plugin.activate.items():
|
||||
if not type in Plugin.types():
|
||||
error(f"activate specified for unrecognized plugin type '{type}'")
|
||||
validate_activate(args, type)
|
||||
else:
|
||||
validate_activate(plugin.activate)
|
||||
|
||||
if error_count == 0:
|
||||
success()
|
||||
return error_count
|
||||
|
||||
def main():
|
||||
arg_parser = argparse.ArgumentParser(
|
||||
prog="sshare-validate",
|
||||
description="Validate sshare plugins",
|
||||
)
|
||||
arg_parser.add_argument(
|
||||
"-v",
|
||||
"--version",
|
||||
action="version",
|
||||
version=f"%(prog)s version {version}",
|
||||
)
|
||||
arg_parser.add_argument(
|
||||
"--dev",
|
||||
action="store_const",
|
||||
const=True,
|
||||
help="Validate all internal and external plugins"
|
||||
)
|
||||
arg_parser.add_argument(
|
||||
"plugins",
|
||||
nargs="*",
|
||||
help="plugin(s) to be validated",
|
||||
)
|
||||
arguments = arg_parser.parse_args()
|
||||
if arguments.dev:
|
||||
to_be_validated = PluginLoader.all(command_line=True)
|
||||
elif len(arguments.plugins) > 0:
|
||||
to_be_validated = PluginLoader.at(*arguments.plugins)
|
||||
else:
|
||||
to_be_validated = PluginLoader.external()
|
||||
|
||||
longest = 0
|
||||
for plugin in to_be_validated:
|
||||
if len(plugin.name) > longest:
|
||||
longest = len(plugin.name)
|
||||
for plugin in to_be_validated:
|
||||
print(f"{plugin.name}{"".join([ " " for _ in range(0, longest-len(plugin.name))])} ", end="")
|
||||
validate(plugin)
|
Loading…
Reference in a new issue