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

View File

@ -524,7 +524,7 @@ class ActionMenu:
wrapped = m[it][0]
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):
global _rule_component_clipboard
@ -545,7 +545,7 @@ class ActionMenu:
c = _rule_component_clipboard
_rule_component_clipboard = None
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._on_update()

View File

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