[core] Pass configuration parameters to modules

User can now use -p <key>=<value> to pass configuration parameters to
modules. For this, the module gets a "parameter()" method. Parameter
keys are in the format <name>.<key> where <name> is the name of the
loaded module. This is either the name of the module itself (e.g. "cpu")
or its alias, if the user specified it, for example:

bumblebee-status -m cpu -p cpu.warning=90

vs.

bumblebee-status -m cpu:test -p test.warning=90

see #23
This commit is contained in:
Tobi-wan Kenobi 2016-12-09 07:57:21 +01:00
parent c8a51b416f
commit f33711f49f
4 changed files with 52 additions and 5 deletions

View file

@ -5,9 +5,11 @@ module parameters, etc.) to all other components
""" """
import argparse import argparse
import bumblebee.store
MODULE_HELP = "" MODULE_HELP = ""
THEME_HELP = "" THEME_HELP = ""
PARAMETER_HELP = ""
def create_parser(): def create_parser():
"""Create the argument parser""" """Create the argument parser"""
@ -15,18 +17,25 @@ def create_parser():
parser.add_argument("-m", "--modules", nargs="+", default=[], parser.add_argument("-m", "--modules", nargs="+", default=[],
help=MODULE_HELP) help=MODULE_HELP)
parser.add_argument("-t", "--theme", default="default", help=THEME_HELP) parser.add_argument("-t", "--theme", default="default", help=THEME_HELP)
parser.add_argument("-p", "--parameters", nargs="+", default=[],
help=PARAMETER_HELP)
return parser return parser
class Config(object): class Config(bumblebee.store.Store):
"""Top-level configuration class """Top-level configuration class
Parses commandline arguments and provides non-module Parses commandline arguments and provides non-module
specific configuration information. specific configuration information.
""" """
def __init__(self, args=None): def __init__(self, args=None):
super(Config, self).__init__()
parser = create_parser() parser = create_parser()
self._args = parser.parse_args(args if args else []) self._args = parser.parse_args(args if args else [])
for param in self._args.parameters:
key, value = param.split("=")
self.set(key, value)
def modules(self): def modules(self):
"""Return a list of all activated modules""" """Return a list of all activated modules"""
return [{ return [{

View file

@ -39,6 +39,16 @@ class Module(object):
"""By default, update() is a NOP""" """By default, update() is a NOP"""
pass pass
def parameter(self, name, default=None):
"""Return the config parameter 'name' for this module"""
name = "{}.{}".format(self._config_name, name)
return self._config.get(name, default)
def set_config(self, config, name):
"""Set the config for this module"""
self._config = config
self._config_name = name
class Engine(object): class Engine(object):
"""Engine for driving the application """Engine for driving the application
@ -47,6 +57,7 @@ class Engine(object):
""" """
def __init__(self, config, output=None): def __init__(self, config, output=None):
self._output = output self._output = output
self._config = config
self._running = True self._running = True
self._modules = [] self._modules = []
self.load_modules(config.modules()) self.load_modules(config.modules())
@ -54,16 +65,20 @@ class Engine(object):
def load_modules(self, modules): def load_modules(self, modules):
"""Load specified modules and return them as list""" """Load specified modules and return them as list"""
for module in modules: for module in modules:
self._modules.append(self.load_module(module["module"])) self._modules.append(self.load_module(module["module"], module["name"]))
return self._modules return self._modules
def load_module(self, module_name): def load_module(self, module_name, config_name=None):
"""Load specified module and return it as object""" """Load specified module and return it as object"""
if config_name == None:
config_name = module_name
try: try:
module = importlib.import_module("bumblebee.modules.{}".format(module_name)) module = importlib.import_module("bumblebee.modules.{}".format(module_name))
except ImportError as error: except ImportError as error:
raise bumblebee.error.ModuleLoadError(error) raise bumblebee.error.ModuleLoadError(error)
return getattr(module, "Module")(self) res = getattr(module, "Module")(self)
res.set_config(self._config, config_name)
return res
def running(self): def running(self):
"""Check whether the event loop is running""" """Check whether the event loop is running"""

View file

@ -11,7 +11,7 @@ from tests.util import MockOutput
class TestEngine(unittest.TestCase): class TestEngine(unittest.TestCase):
def setUp(self): def setUp(self):
self.engine = Engine(config=Config(), output=MockOutput()) self.engine = Engine(config=Config(), output=MockOutput())
self.singleWidgetModule = [{"module": "test"}] self.singleWidgetModule = [{"module": "test", "name": "a"}]
self.testModule = "test" self.testModule = "test"
self.invalidModule = "no-such-module" self.invalidModule = "no-such-module"
self.testModuleSpec = "bumblebee.modules.{}".format(self.testModule) self.testModuleSpec = "bumblebee.modules.{}".format(self.testModule)

View file

@ -3,17 +3,32 @@
import unittest import unittest
from bumblebee.engine import Module from bumblebee.engine import Module
from bumblebee.config import Config
from tests.util import MockWidget from tests.util import MockWidget
class TestModule(unittest.TestCase): class TestModule(unittest.TestCase):
def setUp(self): def setUp(self):
self.widget = MockWidget("foo") self.widget = MockWidget("foo")
self.config = Config()
self.moduleWithoutWidgets = Module(engine=None, widgets=None) self.moduleWithoutWidgets = Module(engine=None, widgets=None)
self.moduleWithOneWidget = Module(engine=None, widgets=self.widget) self.moduleWithOneWidget = Module(engine=None, widgets=self.widget)
self.moduleWithMultipleWidgets = Module(engine=None, self.moduleWithMultipleWidgets = Module(engine=None,
widgets=[self.widget, self.widget, self.widget] widgets=[self.widget, self.widget, self.widget]
) )
self.anyModule = Module(engine=None, widgets = self.widget)
self.anotherModule = Module(engine=None, widgets = self.widget)
self.anyConfigName = "cfg"
self.anotherConfigName = "cfg2"
self.anyKey = "some-parameter"
self.anyValue = "value"
self.anotherValue = "another-value"
self.emptyKey = "i-do-not-exist"
self.config.set("{}.{}".format(self.anyConfigName, self.anyKey), self.anyValue)
self.config.set("{}.{}".format(self.anotherConfigName, self.anyKey), self.anotherValue)
self.anyModule.set_config(self.config, self.anyConfigName)
self.anotherModule.set_config(self.config, self.anotherConfigName)
def test_empty_widgets(self): def test_empty_widgets(self):
self.assertEquals(self.moduleWithoutWidgets.widgets(), []) self.assertEquals(self.moduleWithoutWidgets.widgets(), [])
@ -23,3 +38,11 @@ class TestModule(unittest.TestCase):
def test_multiple_widgets(self): def test_multiple_widgets(self):
for widget in self.moduleWithMultipleWidgets.widgets(): for widget in self.moduleWithMultipleWidgets.widgets():
self.assertEquals(widget, self.widget) self.assertEquals(widget, self.widget)
def test_parameters(self):
self.assertEquals(self.anyModule.parameter(self.anyKey), self.anyValue)
self.assertEquals(self.anotherModule.parameter(self.anyKey), self.anotherValue)
def test_default_parameters(self):
self.assertEquals(self.anyModule.parameter(self.emptyKey), None)
self.assertEquals(self.anyModule.parameter(self.emptyKey, self.anyValue), self.anyValue)