Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix route map generation for classes using @property #140

Merged
merged 8 commits into from
Oct 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions ocpp/routing.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import functools

routables = []


def on(action, *, skip_schema_validation=False):
""" Function decorator to mark function as handler for specific action.
Expand Down Expand Up @@ -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


Expand All @@ -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

Expand Down Expand Up @@ -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:
Expand Down
35 changes: 35 additions & 0 deletions tests/test_charge_point.py
Original file line number Diff line number Diff line change
@@ -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"]