Introduce hooks support

This commit is contained in:
norohind 2022-04-10 23:08:31 +03:00
parent afdecb4cd8
commit 76ea80b178
Signed by: norohind
GPG Key ID: 01C3BECC26FB59E1
4 changed files with 85 additions and 0 deletions

View File

@ -1,5 +1,8 @@
from . import Queries
import DB
import HookSystem
hook_system = HookSystem.HookSystem()
def update_squad(squad_id: int, suppress_absence=False) -> None | int:
@ -15,10 +18,12 @@ def update_squad(squad_id: int, suppress_absence=False) -> None | int:
# Squad not found FDEV
if not suppress_absence:
operation_id = DB.delete_squadron(squad_id)
hook_system.notify_deleted(operation_id)
else:
# Then we got valid squad_info dict
news_info = Queries.get_squad_news(squad_id)
operation_id = DB.insert_info_news(news_info, squad_info)
hook_system.notify_inserted(operation_id)
return operation_id

11
Hook.py Normal file
View File

@ -0,0 +1,11 @@
from abc import ABC, abstractmethod
class Hook(ABC): # See at Hook class as to observer in observer pattern
"""
In order to implement hook, subclass this class and pass instance to HookSystem.add_hook
"""
@abstractmethod
def update(self, operation_id: int) -> None:
raise NotImplemented

58
HookSystem.py Normal file
View File

@ -0,0 +1,58 @@
import os
import functools
import threading
from Hook import Hook
import importlib.machinery
def check_int(func: callable) -> callable:
@functools.wraps(func)
def decorated(self, operation_id: int | None) -> None:
if type(operation_id) == int:
return func(self, operation_id)
return decorated
class HookSystem:
hooks_inserted: list[Hook] = list()
hooks_deleted: list[Hook] = list()
def __init__(self):
# hooks load
for file_name in sorted(os.listdir('hooks')):
if file_name.endswith('.py') and not file_name[0] in ['.', '_']:
path = os.path.join('hooks', file_name)
hook_name = file_name[:-3]
module = importlib.machinery.SourceFileLoader(hook_name, path).load_module()
setup_func = getattr(module, 'setup', None)
if setup_func is not None:
setup_func(self)
else:
raise AttributeError(f'No setup method in {file_name} hook')
def add_on_insert_hook(self, hook: Hook) -> None:
self.hooks_inserted.append(hook)
def remove_on_insert_hook(self, hook: Hook) -> None:
self.hooks_inserted.remove(hook)
def add_on_delete_hook(self, hook: Hook) -> None:
self.hooks_deleted.append(hook)
def remove_on_delete_hook(self, hook: Hook) -> None:
self.hooks_deleted.remove(hook)
@check_int
def notify_inserted(self, operation_id: int | None) -> None:
self._notify(operation_id, self.hooks_inserted)
@check_int
def notify_deleted(self, operation_id: int) -> None:
self._notify(operation_id, self.hooks_deleted)
@staticmethod
def _notify(operation_id, hooks: list[Hook]) -> None:
for hook in hooks:
threading.Thread(target=hook.update, args=(operation_id,)).start()

11
hooks/testHook.py Normal file
View File

@ -0,0 +1,11 @@
from HookSystem import HookSystem
from Hook import Hook
class testHook(Hook):
def update(self, operation_id: int) -> None:
print('update')
def setup(hook_system: HookSystem) -> None:
hook_system.add_on_insert_hook(testHook())