diff --git a/ocpp/routing.py b/ocpp/routing.py index 3071eb6ef..a60e7cb1e 100644 --- a/ocpp/routing.py +++ b/ocpp/routing.py @@ -1,5 +1,7 @@ import functools +routables = [] + def on(action, *, skip_schema_validation=False): """ Function decorator to mark function as handler for specific action. @@ -32,7 +34,10 @@ def inner(*args, **kwargs): inner._on_action = action inner._skip_schema_validation = skip_schema_validation + if func.__name__ not in routables: + routables.append(func.__name__) return inner + return decorator @@ -55,6 +60,8 @@ def inner(*args, **kwargs): return func(*args, **kwargs) inner._after_action = action + if func.__name__ not in routables: + routables.append(func.__name__) return inner return decorator @@ -90,10 +97,10 @@ def after_boot_notification(self, *args, **kwargs): """ routes = {} - for attr_name in dir(obj): - attr = getattr(obj, attr_name) + for attr_name in routables: for option in ['_on_action', '_after_action']: try: + attr = getattr(obj, attr_name) action = getattr(attr, option) if action not in routes: diff --git a/tests/test_charge_point.py b/tests/test_charge_point.py index e69de29bb..3ce24da3d 100644 --- a/tests/test_charge_point.py +++ b/tests/test_charge_point.py @@ -0,0 +1,35 @@ +import pytest +from ocpp.v20 import ChargePoint as cp +from ocpp.routing import on, create_route_map +from ocpp.v16.enums import Action + + +def test_getters_should_not_be_called_during_routemap_setup(): + class ChargePoint(cp): + @property + def foo(self): + raise RuntimeError("this will be raised") + + try: + ChargePoint("blah", None) + except RuntimeError as e: + assert str(e) == "this will be raised" + pytest.fail("Getter was called during ChargePoint creation") + + +def test_multiple_classes_with_same_name_for_handler(): + class ChargerA(cp): + @on(Action.Heartbeat) + def heartbeat(self, **kwargs): + pass + + class ChargerB(cp): + @on(Action.Heartbeat) + def heartbeat(self, **kwargs): + pass + + A = ChargerA("A", None) + B = ChargerB("B", None) + route_mapA = create_route_map(A) + route_mapB = create_route_map(B) + assert route_mapA["Heartbeat"] != route_mapB["Heartbeat"]