Source code for GeoHealthCheck.plugin

from factory import Factory
import logging
import inspect
from collections.abc import Mapping
import copy
from init import App

LOGGER = logging.getLogger(__name__)


[docs]class Plugin(object): """ Abstract Base class for all GHC Plugins. Derived classes should fill in all class variables that are UPPER_CASE, unless they ar fine with default-values from superclass(es). """ # Generic attributes, subclassses override AUTHOR = 'GHC Team' """ Plugin author or team. """ NAME = 'Name missing in NAME class var' """ Short name of Plugin. TODO: i18n e.g. NAME_nl_NL ? """ DESCRIPTION = 'Description missing in DESCRIPTION class var' """ Longer description of Plugin. TODO: optional i18n e.g. DESCRIPTION_de_DE ? """ PARAM_DEFS = {} """ Plugin Parameter definitions. """ def __init__(self): self._parameters = {} def get_class_name(self): return type(self).__name__
[docs] def get_param(self, param_name): """ Get actual parameter value. `param_name` should be defined in `PARAM_DEFS`. """ if param_name not in self._parameters: return None return self._parameters[param_name]
[docs] def get_default_parameter_values(self): """ Get all default parameter values """ params = getattr(self, 'PARAM_DEFS', {}) param_values = {} for param in params: param_values[param] = '' if 'default' in params[param]: if params[param]['default']: param_values[param] = params[param]['default'] if 'value' in params[param]: param_values[param] = params[param]['value'] return param_values
[docs] def get_var_names(self): """ Get all Plugin variable names as a dict """ return ['AUTHOR', 'NAME', 'DESCRIPTION', 'PARAM_DEFS']
[docs] def get_plugin_vars(self): """ Get all (uppercase) class variables of a class as a dict """ plugin_vars = {} var_names = self.get_var_names() for var_name in var_names: plugin_vars[var_name] = getattr(self, var_name, None) return plugin_vars
[docs] def get_param_defs(self): """ Get all PARAM_DEFS as dict. """ return self.get_plugin_vars()['PARAM_DEFS']
[docs] @staticmethod def copy(obj): """ Deep copy of usually `dict` object. """ return copy.deepcopy(obj)
[docs] @staticmethod def merge(dict1, dict2): """ Recursive merge of two `dict`, mainly used for PARAM_DEFS, CHECKS_AVAIL overriding. :param dict1: base dict :param dict2: dict to merge into dict1 :return: deep copy of dict2 merged into dict1 """ def dict_merge(dct, merge_dct): """ Recursive dict merge. Inspired by :meth:``dict.update()``, instead of updating only top-level keys, dict_merge recurses down into dicts nested to an arbitrary depth, updating keys. The ``merge_dct`` is merged into ``dct``. See https://gist.github.com/angstwad/bf22d1822c38a92ec0a9 :param dct: dict onto which the merge is executed :param merge_dct: dict merged into dct :return: None """ for k, v in merge_dct.items(): if k in dct and isinstance(dct[k], dict) \ and isinstance(merge_dct[k], Mapping): dict_merge(dct[k], merge_dct[k]) else: dct[k] = merge_dct[k] result_dict = copy.deepcopy(dict1) dict_merge(result_dict, dict2) return result_dict
[docs] @staticmethod def get_plugins(baseclass='GeoHealthCheck.plugin.Plugin', filters=None): """ Class method to get list of Plugins of particular baseclass (optional), default is all Plugins. filters is a list of tuples to filter out Plugins with class var values: (class var, value), e.g. `filters=[('RESOURCE_TYPE', 'OGC:*'), ('RESOURCE_TYPE', 'OGC:WMS')]`. """ result = [] baseclass = Factory.create_class(baseclass) def add_result(plugin_name, class_obj): if not filters: result.append(plugin_name) else: vars = Factory.get_class_vars(class_obj) for filter in filters: if vars[filter[0]] == filter[1]: result.append(plugin_name) break plugins = App.get_plugins() for plugin_name in plugins: try: # Assume module first module = Factory.create_module(plugin_name) for name in dir(module): class_obj = getattr(module, name) # Must be a class object inheriting from baseclass # but not the baseclass itself if inspect.isclass(class_obj) \ and baseclass in inspect.getmro(class_obj) and \ baseclass != class_obj: add_result('%s.%s' % (plugin_name, name), class_obj) except Exception: # Try for full classname try: class_obj = Factory.create_class(plugin_name) if baseclass in inspect.getmro(class_obj) \ and baseclass != class_obj: add_result(plugin_name, class_obj) except Exception: LOGGER.warn('cannot create obj class=%s' % plugin_name) return result
def __str__(self): return "%s" % str(self.__class__)