2016-12-04 08:37:01 +01:00
|
|
|
"""Core application engine"""
|
|
|
|
|
2016-12-09 07:27:01 +01:00
|
|
|
import os
|
2016-12-04 16:23:44 +01:00
|
|
|
import time
|
2016-12-09 07:27:01 +01:00
|
|
|
import pkgutil
|
2016-12-04 11:09:10 +01:00
|
|
|
import importlib
|
2016-12-04 16:23:44 +01:00
|
|
|
import bumblebee.error
|
2016-12-09 07:27:01 +01:00
|
|
|
import bumblebee.modules
|
|
|
|
|
2016-12-09 08:43:14 +01:00
|
|
|
def all_modules():
|
2016-12-09 07:27:01 +01:00
|
|
|
"""Return a list of available modules"""
|
|
|
|
result = []
|
|
|
|
path = os.path.dirname(bumblebee.modules.__file__)
|
|
|
|
for mod in [name for _, name, _ in pkgutil.iter_modules([path])]:
|
|
|
|
result.append({
|
|
|
|
"name": mod
|
|
|
|
})
|
|
|
|
return result
|
2016-12-04 11:09:10 +01:00
|
|
|
|
|
|
|
class Module(object):
|
|
|
|
"""Module instance base class
|
|
|
|
|
|
|
|
Objects of this type represent the modules that
|
|
|
|
the user configures. Concrete module implementations
|
|
|
|
(e.g. CPU utilization, disk usage, etc.) derive from
|
|
|
|
this base class.
|
|
|
|
"""
|
2016-12-09 08:23:53 +01:00
|
|
|
def __init__(self, engine, config={}, widgets=[]):
|
2016-12-08 12:44:52 +01:00
|
|
|
self.name = self.__module__.split(".")[-1]
|
2016-12-09 08:23:53 +01:00
|
|
|
self._config = config
|
2016-12-09 08:43:14 +01:00
|
|
|
if "name" not in self._config:
|
2016-12-09 08:23:53 +01:00
|
|
|
self._config["name"] = self.name
|
2016-12-09 19:29:16 +01:00
|
|
|
self.id = self._config["name"]
|
2016-12-08 08:44:54 +01:00
|
|
|
self._widgets = []
|
|
|
|
if widgets:
|
|
|
|
self._widgets = widgets if isinstance(widgets, list) else [widgets]
|
|
|
|
|
|
|
|
def widgets(self):
|
|
|
|
"""Return the widgets to draw for this module"""
|
|
|
|
return self._widgets
|
2016-12-04 11:09:10 +01:00
|
|
|
|
2016-12-10 08:37:04 +01:00
|
|
|
def widget(self, name):
|
|
|
|
for widget in self._widgets:
|
|
|
|
if widget.name == name:
|
|
|
|
return widget
|
|
|
|
|
2016-12-09 07:11:23 +01:00
|
|
|
def update(self, widgets):
|
|
|
|
"""By default, update() is a NOP"""
|
|
|
|
pass
|
|
|
|
|
2016-12-09 07:57:21 +01:00
|
|
|
def parameter(self, name, default=None):
|
|
|
|
"""Return the config parameter 'name' for this module"""
|
2016-12-09 08:23:53 +01:00
|
|
|
name = "{}.{}".format(self._config["name"], name)
|
|
|
|
return self._config["config"].get(name, default)
|
2016-12-09 07:57:21 +01:00
|
|
|
|
2016-12-04 08:37:01 +01:00
|
|
|
class Engine(object):
|
|
|
|
"""Engine for driving the application
|
|
|
|
|
|
|
|
This class connects input/output, instantiates all
|
|
|
|
required modules and drives the "event loop"
|
|
|
|
"""
|
2016-12-09 19:29:16 +01:00
|
|
|
def __init__(self, config, output=None, inp=None):
|
2016-12-04 12:26:20 +01:00
|
|
|
self._output = output
|
2016-12-09 07:57:21 +01:00
|
|
|
self._config = config
|
2016-12-04 08:37:01 +01:00
|
|
|
self._running = True
|
2016-12-04 11:09:10 +01:00
|
|
|
self._modules = []
|
2016-12-09 19:29:16 +01:00
|
|
|
self.input = inp
|
2016-12-04 11:09:10 +01:00
|
|
|
self.load_modules(config.modules())
|
2016-12-09 19:29:16 +01:00
|
|
|
self.input.start()
|
2016-12-04 11:09:10 +01:00
|
|
|
|
|
|
|
def load_modules(self, modules):
|
|
|
|
"""Load specified modules and return them as list"""
|
|
|
|
for module in modules:
|
2016-12-09 11:49:59 +01:00
|
|
|
self._modules.append(self._load_module(module["module"], module["name"]))
|
2016-12-04 11:09:10 +01:00
|
|
|
return self._modules
|
|
|
|
|
2016-12-09 11:49:59 +01:00
|
|
|
def _load_module(self, module_name, config_name=None):
|
2016-12-04 11:09:10 +01:00
|
|
|
"""Load specified module and return it as object"""
|
2016-12-09 08:43:14 +01:00
|
|
|
if config_name is None:
|
2016-12-09 07:57:21 +01:00
|
|
|
config_name = module_name
|
2016-12-04 16:23:44 +01:00
|
|
|
try:
|
|
|
|
module = importlib.import_module("bumblebee.modules.{}".format(module_name))
|
|
|
|
except ImportError as error:
|
|
|
|
raise bumblebee.error.ModuleLoadError(error)
|
2016-12-09 08:23:53 +01:00
|
|
|
return getattr(module, "Module")(self, {
|
|
|
|
"name": config_name,
|
|
|
|
"config": self._config
|
|
|
|
})
|
2016-12-04 08:37:01 +01:00
|
|
|
|
|
|
|
def running(self):
|
|
|
|
"""Check whether the event loop is running"""
|
|
|
|
return self._running
|
|
|
|
|
|
|
|
def stop(self):
|
|
|
|
"""Stop the event loop"""
|
|
|
|
self._running = False
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
"""Start the event loop"""
|
2016-12-04 12:26:20 +01:00
|
|
|
self._output.start()
|
2016-12-04 08:37:01 +01:00
|
|
|
while self.running():
|
2016-12-08 12:44:52 +01:00
|
|
|
self._output.begin()
|
2016-12-04 12:53:18 +01:00
|
|
|
for module in self._modules:
|
2016-12-08 08:44:54 +01:00
|
|
|
module.update(module.widgets())
|
2016-12-08 12:44:52 +01:00
|
|
|
for widget in module.widgets():
|
2016-12-09 11:49:59 +01:00
|
|
|
widget.link_module(module)
|
2016-12-09 19:29:16 +01:00
|
|
|
self._output.draw(widget=widget, module=module, engine=self)
|
2016-12-04 16:14:43 +01:00
|
|
|
self._output.flush()
|
2016-12-08 12:44:52 +01:00
|
|
|
self._output.end()
|
2016-12-04 17:45:42 +01:00
|
|
|
if self.running():
|
|
|
|
time.sleep(1)
|
2016-12-04 08:37:01 +01:00
|
|
|
|
2016-12-04 12:26:20 +01:00
|
|
|
self._output.stop()
|
2016-12-09 19:29:16 +01:00
|
|
|
self.input.stop()
|
2016-12-04 12:26:20 +01:00
|
|
|
|
2016-12-04 08:37:01 +01:00
|
|
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|