Added a simple plugin validator

This commit is contained in:
Gnarwhal 2024-09-14 17:56:10 +00:00
parent 552146551c
commit 1a9001e956
Signed by: Gnarwhal
GPG key ID: 0989A73D8C421174
3 changed files with 152 additions and 8 deletions

View file

@ -25,6 +25,7 @@ Issues = "https://forge.monodon.me/Gnarwhal/sshare/issues"
[project.scripts] [project.scripts]
sshare = "sshare.main:main" sshare = "sshare.main:main"
sshare-validate = "sshare.validator:main"
[tool.setuptools_scm] [tool.setuptools_scm]
version_file = "src/sshare/version.py" version_file = "src/sshare/version.py"

View file

@ -21,11 +21,11 @@ from sshare import config_directory
class PluginLoader: class PluginLoader:
@staticmethod @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) return PluginLoader.internal(command_line, logger, config, flags) + PluginLoader.external(logger, config, flags)
@staticmethod @staticmethod
def internal(command_line=False, logger=None, config=None, flags=None): def internal(command_line=False, logger=None, config=dict(), flags=dict()):
return [ return [
Plugin.internal(plugin, logger, config, flags) Plugin.internal(plugin, logger, config, flags)
for plugin for plugin
@ -41,7 +41,7 @@ class PluginLoader:
] ]
@staticmethod @staticmethod
def external(logger=None, config=None, flags=None): def external(logger=None, config=dict(), flags=dict()):
return [ return [
Plugin.external(plugin, logger, config, flags) Plugin.external(plugin, logger, config, flags)
for plugin for plugin
@ -49,7 +49,7 @@ class PluginLoader:
] ]
@staticmethod @staticmethod
def at(logger=None, config=None, flags=None, *args): def at(logger=None, config=dict(), flags=dict(), *args):
return [ return [
Plugin.external(plugin, logger, config, flags) Plugin.external(plugin, logger, config, flags)
for plugin for plugin
@ -91,8 +91,19 @@ class PluginManager:
class Plugin: class Plugin:
@staticmethod @staticmethod
def types(): def types(methods=False):
return [ "logger", "source", "name", "upload", "location", "feedback" ] 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): def __init__(self, name, module, logger, external_config, external_flags):
self.__dict__ = module.__dict__ self.__dict__ = module.__dict__
@ -169,11 +180,11 @@ class Plugin:
return activate return activate
@staticmethod @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())) return Plugin(name, importlib.import_module(f"sshare.plugins.{name}"), logger, config.get(name, dict()), flags.get(name, dict()))
@staticmethod @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( module_spec = importlib.util.spec_from_file_location(
path.stem, path.stem,
path.as_posix(), path.as_posix(),

132
src/sshare/validator.py Normal file
View 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)