diversion: Remove RuleComponent class to avoid coupling of classes

Replace tight coupling of Action and Condition classes by removing their
common base class and converting it into a function.

The RuleComponent was a base class solely holding a compile function and
passing it to its children. There is no need for tight coupling with
inheritance for that purpose.

Related #2659
This commit is contained in:
MattHag 2024-12-31 17:50:08 +01:00
parent e9a58fb3e0
commit 9af34b33e8
3 changed files with 21 additions and 26 deletions

View File

@ -511,19 +511,17 @@ MOUSE_GESTURE_TESTS = {
"mouse-noop": [], "mouse-noop": [],
} }
# COMPONENTS = {}
def compile_component(c):
class RuleComponent: if isinstance(c, Rule) or isinstance(c, Condition) or isinstance(c, Action):
def compile(self, c): return c
if isinstance(c, RuleComponent): elif isinstance(c, dict) and len(c) == 1:
return c k, v = next(iter(c.items()))
elif isinstance(c, dict) and len(c) == 1: if k in COMPONENTS:
k, v = next(iter(c.items())) cls = COMPONENTS[k]
if k in COMPONENTS: return cls(v)
return COMPONENTS[k](v) logger.warning("illegal component in rule: %s", c)
logger.warning("illegal component in rule: %s", c) return FalllbackCondition()
return Condition()
def _evaluate(components, feature, notification: HIDPPNotification, device, result) -> Any: def _evaluate(components, feature, notification: HIDPPNotification, device, result) -> Any:
@ -537,9 +535,9 @@ def _evaluate(components, feature, notification: HIDPPNotification, device, resu
return res return res
class Rule(RuleComponent): class Rule:
def __init__(self, args, source=None, warn=True): def __init__(self, args, source=None, warn=True):
self.components = [self.compile(a) for a in args] self.components = [compile_component(a) for a in args]
self.source = source self.source = source
def __str__(self): def __str__(self):
@ -559,7 +557,7 @@ class Rule(RuleComponent):
return {"Rule": [c.data() for c in self.components]} return {"Rule": [c.data() for c in self.components]}
class Condition(RuleComponent): class Condition:
def __init__(self, *args): def __init__(self, *args):
pass pass
@ -577,7 +575,7 @@ class Not(Condition):
if isinstance(op, list) and len(op) == 1: if isinstance(op, list) and len(op) == 1:
op = op[0] op = op[0]
self.op = op self.op = op
self.component = self.compile(op) self.component = compile_component(op)
def __str__(self): def __str__(self):
return "Not: " + str(self.component) return "Not: " + str(self.component)
@ -594,7 +592,7 @@ class Not(Condition):
class Or(Condition): class Or(Condition):
def __init__(self, args, warn=True): def __init__(self, args, warn=True):
self.components = [self.compile(a) for a in args] self.components = [compile_component(a) for a in args]
def __str__(self): def __str__(self):
return "Or: [" + ", ".join(str(c) for c in self.components) + "]" return "Or: [" + ", ".join(str(c) for c in self.components) + "]"
@ -617,7 +615,7 @@ class Or(Condition):
class And(Condition): class And(Condition):
def __init__(self, args, warn=True): def __init__(self, args, warn=True):
self.components = [self.compile(a) for a in args] self.components = [compile_component(a) for a in args]
def __str__(self): def __str__(self):
return "And: [" + ", ".join(str(c) for c in self.components) + "]" return "And: [" + ", ".join(str(c) for c in self.components) + "]"
@ -1145,7 +1143,7 @@ class Host(Condition):
return {"Host": self.host} return {"Host": self.host}
class Action(RuleComponent): class Action:
def __init__(self, *args): def __init__(self, *args):
pass pass

View File

@ -524,7 +524,7 @@ class ActionMenu:
wrapped = m[it][0] wrapped = m[it][0]
c = wrapped.component c = wrapped.component
_rule_component_clipboard = diversion.RuleComponent().compile(c.data()) _rule_component_clipboard = diversion.compile_component(c.data())
def menu_do_cut(self, _mitem, m, it): def menu_do_cut(self, _mitem, m, it):
global _rule_component_clipboard global _rule_component_clipboard
@ -545,7 +545,7 @@ class ActionMenu:
c = _rule_component_clipboard c = _rule_component_clipboard
_rule_component_clipboard = None _rule_component_clipboard = None
if c: if c:
_rule_component_clipboard = diversion.RuleComponent().compile(c.data()) _rule_component_clipboard = diversion.compile_component(c.data())
self._menu_do_insert(_mitem, m, it, new_c=c, below=below) self._menu_do_insert(_mitem, m, it, new_c=c, below=below)
self._on_update() self._on_update()

View File

@ -20,7 +20,6 @@ from typing import Any
from typing import Callable from typing import Callable
from gi.repository import Gtk from gi.repository import Gtk
from logitech_receiver import diversion
def norm(s): def norm(s):
@ -50,8 +49,6 @@ class CompletionEntry(Gtk.Entry):
class RuleComponentUI(abc.ABC): class RuleComponentUI(abc.ABC):
CLASS = diversion.RuleComponent
def __init__(self, panel, on_update: Callable = None): def __init__(self, panel, on_update: Callable = None):
self.panel = panel self.panel = panel
self.widgets = {} # widget -> coord. in grid self.widgets = {} # widget -> coord. in grid
@ -109,5 +106,5 @@ class RuleComponentUI(abc.ABC):
for c in self.panel.get_children(): for c in self.panel.get_children():
self.panel.remove(c) self.panel.remove(c)
def update_devices(self): # noqa: B027 def update_devices(self) -> None:
pass return None