Skip to content

Commit

Permalink
refactoring, use more typing (yes, i come from java/kotlin)
Browse files Browse the repository at this point in the history
  • Loading branch information
lugipfupf committed May 4, 2024
1 parent 0df015e commit 2c3d14b
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 61 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

68 changes: 10 additions & 58 deletions happyMirror/__init__.py
Original file line number Diff line number Diff line change
@@ -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()
Expand All @@ -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:
Expand All @@ -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)
2 changes: 2 additions & 0 deletions happyMirror/test_widgets_loader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import unittest

7 changes: 7 additions & 0 deletions happyMirror/widget.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from happyMirror.render import BaseRenderer


class Widget:
def __init__(self, module, instance: BaseRenderer):
self.module = module
self.instance = instance
1 change: 0 additions & 1 deletion happyMirror/widgets/simple_image/simple_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
56 changes: 56 additions & 0 deletions happyMirror/widgets_loader.py
Original file line number Diff line number Diff line change
@@ -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[:]

0 comments on commit 2c3d14b

Please sign in to comment.