#!/usr/bin/env python # vim: textwidth=0 wrapmargin=0 tabstop=4 shiftwidth=4 softtabstop=4 smartindent smarttab """Plugin that tests that modules we bundle for plugins are present and working.""" import logging import os import shutil import sqlite3 import zipfile import semantic_version from SubA import SubA from config import appname, appversion, config # For compatibility with pre-5.0.0 if not hasattr(config, 'get_int'): config.get_int = config.getint if not hasattr(config, 'get_str'): config.get_str = config.get if not hasattr(config, 'get_bool'): config.get_bool = lambda key: bool(config.getint(key)) if not hasattr(config, 'get_list'): config.get_list = config.get # This could also be returned from plugin_start3() plugin_name = os.path.basename(os.path.dirname(__file__)) # Logger per found plugin, so the folder name is included in # the logging format. logger = logging.getLogger(f'{appname}.{plugin_name}') if not logger.hasHandlers(): level = logging.INFO # So logger.info(...) is equivalent to print() logger.setLevel(level) logger_channel = logging.StreamHandler() logger_channel.setLevel(level) logger_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(module)s:%(lineno)d:%(funcName)s: %(message)s') # noqa: E501 logger_formatter.default_time_format = '%Y-%m-%d %H:%M:%S' logger_formatter.default_msec_format = '%s.%03d' logger_channel.setFormatter(logger_formatter) logger.addHandler(logger_channel) class This: """Module global variables.""" def __init__(self): self.DBFILE = 'plugintest.db' self.plugin_test: PluginTest self.suba: SubA this = This() class PluginTest(object): """Class that performs actual tests on bundled modules.""" def __init__(self, directory: str): logger.debug(f'directory = "{directory}') dbfile = os.path.join(directory, this.DBFILE) # Test 'import zipfile' with zipfile.ZipFile(dbfile + '.zip', 'w') as zip: if os.path.exists(dbfile): zip.write(dbfile) zip.close() # Testing 'import shutil' if os.path.exists(dbfile): shutil.copyfile(dbfile, dbfile + '.bak') # Testing 'import sqlite3' self.sqlconn = sqlite3.connect(dbfile) self.sqlc = self.sqlconn.cursor() try: self.sqlc.execute('CREATE TABLE entries (timestamp TEXT, cmdrname TEXT, system TEXT, station TEXT, eventtype TEXT)') # noqa: E501 except sqlite3.OperationalError: logger.exception('sqlite3.OperationalError when CREATE TABLE entries:') def store(self, timestamp: str, cmdrname: str, system: str, station: str, event: str) -> None: """ Store the provided data in sqlite database. :param timestamp: :param cmdrname: :param system: :param station: :param event: :return: None """ logger.debug(f'timestamp = "{timestamp}", cmdr = "{cmdrname}", system = "{system}", station = "{station}", event = "{event}"') # noqa: E501 self.sqlc.execute('INSERT INTO entries VALUES(?, ?, ?, ?, ?)', (timestamp, cmdrname, system, station, event)) self.sqlconn.commit() return None def plugin_start3(plugin_dir: str) -> str: """ Plugin startup method. :param plugin_dir: :return: 'Pretty' name of this plugin. """ # Up until 5.0.0-beta1 config.appversion is a string if isinstance(appversion, str): core_version = semantic_version.Version(appversion) elif callable(appversion): # From 5.0.0-beta1 it's a function, returning semantic_version.Version core_version = appversion() config.set('plugintest_bool', True) somebool = config.get_bool('plugintest_bool') logger.debug(f'Stored bool: {somebool=} ({type(somebool)})') config.set('plugintest_str', 'Test String') somestr = config.get_str('plugintest_str') logger.debug(f'Stored str: {somestr=} ({type(somestr)})') config.set('plugintest_int', 42) someint = config.get_int('plugintest_int') logger.debug(f'Stored int: {someint=} ({type(someint)})') config.set('plugintest_list', ['test', 'one', 'two']) somelist = config.get_list('plugintest_list') logger.debug(f'Stored list: {somelist=} ({type(somelist)})') logger.info(f'Core EDMC version: {core_version}') # And then compare like this if core_version < semantic_version.Version('5.0.0-beta1'): logger.info('EDMC core version is before 5.0.0-beta1') else: logger.info('EDMC core version is at least 5.0.0-beta1') # Yes, just blow up if config.appverison is neither str or callable logger.info(f'Folder is {plugin_dir}') this.plugin_test = PluginTest(plugin_dir) this.suba = SubA(logger) this.suba.ping() return plugin_name def plugin_stop() -> None: """ Plugin stop method. :return: """ logger.info('Stopping') def journal_entry(cmdrname: str, is_beta: bool, system: str, station: str, entry: dict, state: dict) -> None: """ Handle the given journal entry. :param cmdrname: :param is_beta: :param system: :param station: :param entry: :param state: :return: None """ logger.debug( f'cmdr = "{cmdrname}", is_beta = "{is_beta}"' f', system = "{system}", station = "{station}"' f', event = "{entry["event"]}"' ) this.plugin_test.store(entry['timestamp'], cmdrname, system, station, entry['event'])