diff --git a/README.md b/README.md index 470627e..24f10af 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ class Renderer(BaseRenderer): ``` ## Custom Routes -If your widget uses custom routes, eg. to display an image, you can do so by implementing `render.BaseRenderer.register_custom_routes` +If your widget uses custom routes, e.g. to display an image, you can do so by implementing `render.BaseRenderer.register_custom_routes` An example of how to do that can be found in the example widget 'simple_image'. - +This method will be called automatically. diff --git a/happyMirror/__init__.py b/happyMirror/__init__.py index 65a8d94..73ff531 100644 --- a/happyMirror/__init__.py +++ b/happyMirror/__init__.py @@ -1,20 +1,13 @@ import os -import importlib -import sys from flask import Flask, render_template -try: - import config -except ImportError: - from . import config +import config +from happyMirror.widgets_loader import WidgetsLoader -def create_app(widgets=None, test_config=None): - if widgets is None: - widgets = [] - - widgets = list(filter(lambda w: w is not None, widgets)) +def start(widgets_loader: WidgetsLoader, test_config=None): + widgets = widgets_loader.load(config.enabled_widgets) app = Flask(__name__, instance_relative_config=True) app.config.from_mapping() @@ -25,21 +18,21 @@ def create_app(widgets=None, test_config=None): app.config.from_mapping(test_config) for widget in widgets: - widget['instance'] = widget['module'].Renderer() - widget['instance'].register_custom_routes(app) + widget.instance.register_custom_routes(app) try: os.makedirs(app.instance_path) except OSError: pass + @app.route('/') def root(): data = [] for cur_widget in widgets: try: - data.append(cur_widget['instance'].render()) + data.append(cur_widget.instance.render()) except KeyError as e: print(f"KeyError for: '{cur_widget}'", e) except AttributeError: @@ -48,50 +41,9 @@ def root(): print(f"Exception for: '{cur_widget}'", e) return render_template('base.html', data=data) - return app - - -def load_widgets(enabled_widgets=None): - loaded_widgets = [] - if enabled_widgets is None: - enabled_widgets = [] - - for root, dirs, files in walk_level(os.curdir + '/widgets'): - for dir_name in dirs: - single_widget = load_single_widget(dir_name, enabled_widgets, root) - loaded_widgets.append(single_widget) - - return loaded_widgets - - -def load_single_widget(dir_name, enabled_widgets, root): - if dir_name in enabled_widgets: - try: - sys.path.append(f"{root}/{dir_name}") - print(f"Importing widget '{dir_name}'") - widget_renderer = importlib.import_module(dir_name) - print(f"Widget '{dir_name}' loaded") - - return {'module': widget_renderer, 'instance': None} - except ModuleNotFoundError: - print("Module not found") - except AttributeError: - print("The module does not have the specified class or function.") - except Exception as e: - print(f"An error occurred while loading widget '{dir_name}': {e}") - - -def walk_level(some_dir, level=1): - some_dir = some_dir.rstrip(os.path.sep) - assert os.path.isdir(some_dir) - num_sep = some_dir.count(os.path.sep) - for root, dirs, files in os.walk(some_dir): - yield root, dirs, files - num_sep_this = root.count(os.path.sep) - if num_sep + level <= num_sep_this: - del dirs[:] + app.run() if __name__ == '__main__': - my_widgets = load_widgets(config.enabled_widgets) - create_app(my_widgets).run() + loader = WidgetsLoader() + start(widgets_loader=loader) diff --git a/happyMirror/test_widgets_loader.py b/happyMirror/test_widgets_loader.py new file mode 100644 index 0000000..c5c2eee --- /dev/null +++ b/happyMirror/test_widgets_loader.py @@ -0,0 +1,2 @@ +import unittest + diff --git a/happyMirror/widget.py b/happyMirror/widget.py new file mode 100644 index 0000000..028be8e --- /dev/null +++ b/happyMirror/widget.py @@ -0,0 +1,7 @@ +from happyMirror.render import BaseRenderer + + +class Widget: + def __init__(self, module, instance: BaseRenderer): + self.module = module + self.instance = instance \ No newline at end of file diff --git a/happyMirror/widgets/simple_image/simple_image.py b/happyMirror/widgets/simple_image/simple_image.py index d175d50..7b2cca2 100644 --- a/happyMirror/widgets/simple_image/simple_image.py +++ b/happyMirror/widgets/simple_image/simple_image.py @@ -6,7 +6,6 @@ class Renderer(BaseRenderer): - def register_custom_routes(self, app: Flask): print(f"Widget '{__name__}' is registering custom routes...") app.add_url_rule( diff --git a/happyMirror/widgets_loader.py b/happyMirror/widgets_loader.py new file mode 100644 index 0000000..d4f5d23 --- /dev/null +++ b/happyMirror/widgets_loader.py @@ -0,0 +1,56 @@ +import os +import sys +import importlib + +from happyMirror.widget import Widget + + +class WidgetsLoader: + def __init__(self): + self.__loaded_widgets = [] + + def load(self, enabled_widgets=None) -> list[Widget]: + loaded_widgets = [] + + if enabled_widgets is None: + enabled_widgets = [] + + for root, dirs, files in self.__walk_level(os.curdir + '/widgets'): + for dir_name in dirs: + single_widget = self.__load_single_widget(dir_name, enabled_widgets, root) + loaded_widgets.append(single_widget) + + + self.__loaded_widgets = self.__sanitize(loaded_widgets) + return self.__loaded_widgets + + def __sanitize(self, loaded_widgets) -> list: + return list(filter(lambda w: w is not None, loaded_widgets)) + + def __load_single_widget(self, dir_name, enabled_widgets, root) -> Widget: + if dir_name in enabled_widgets: + try: + sys.path.append(f"{root}/{dir_name}") + print(f"Importing widget '{dir_name}'") + widget_renderer = importlib.import_module(dir_name) + print(f"Widget '{dir_name}' loaded") + + return Widget(module=widget_renderer, instance=widget_renderer.Renderer()) + except ModuleNotFoundError: + print("Module not found") + except AttributeError: + print("The module does not have the specified class or function.") + except Exception as e: + print(f"An error occurred while loading widget '{dir_name}': {e}") + + + def __walk_level(self, some_dir, level=1): + some_dir = some_dir.rstrip(os.path.sep) + assert os.path.isdir(some_dir) + num_sep = some_dir.count(os.path.sep) + for root, dirs, files in os.walk(some_dir): + yield root, dirs, files + num_sep_this = root.count(os.path.sep) + if num_sep + level <= num_sep_this: + del dirs[:] +