Skip to content

Commit 1af1fd8

Browse files
finetjuljourdain
authored andcommitted
feat(TrameApp): avoid intermediate class
1 parent 7e7b9ff commit 1af1fd8

File tree

2 files changed

+80
-62
lines changed

2 files changed

+80
-62
lines changed

tests/test_decorators.py

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,39 @@ def test_TrameApp():
55

66
@TrameApp()
77
class A:
8-
def __init__(self, server):
8+
def __init__(self, server, e):
9+
"""doc string"""
910
self.server = server
10-
self.server.state.change("c")(self.c_changed)
11-
12-
class B(A):
13-
def __init__(self, server):
14-
super().__init__(server)
11+
self.e = e
1512

1613
@change("c")
1714
def c_changed(self, c, **kwargs):
1815
self.c = c
1916

17+
class B(A):
18+
def __init__(self, server, e):
19+
super().__init__(server, e)
20+
21+
@change("d")
22+
def d_changed(self, d, **kwargs):
23+
self.d = d
24+
2025
@controller.set("on_server_ready")
2126
def on_server_ready(self, **kwargs):
2227
assert self.c == 10
28+
assert self.d == 15
2329
asyncio.create_task(self.server.stop())
2430

25-
b = B(get_server())
31+
server = get_server()
32+
33+
a = A(server, 1)
34+
assert type(a) is A
35+
assert a.__init__.__doc__ is not None
36+
37+
b = B(server, 2)
38+
assert type(b) is B
39+
assert b.e == 2
40+
2641
b.server.state.c = 10
42+
b.server.state.d = 15
2743
b.server.start()

trame/decorators/klass.py

Lines changed: 57 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -42,61 +42,63 @@ def __init__(self, server="server", namespace=""):
4242
self.namespace_prefix = namespace
4343

4444
def __call__(self, klass):
45-
class TrameWrapper(klass):
46-
@functools.wraps(klass, updated=())
47-
def __init__(instance, *args, **kwargs):
48-
logger.debug("Create instance")
49-
super(TrameWrapper, instance).__init__(*args, **kwargs)
50-
51-
logger.debug("Instance created")
52-
53-
server = getattr(instance, self.server_name)
54-
prefix = (
55-
getattr(instance, self.namespace_prefix)
56-
if self.namespace_prefix
57-
else ""
58-
)
59-
60-
logger.debug(f"{server=} {prefix=}")
61-
62-
# Look for method decorator
63-
for k in inspect.getmembers(instance.__class__, can_be_decorated):
64-
fn = getattr(instance, k[0])
65-
66-
# Handle @state.change
67-
if "_trame_state_change" in fn.__dict__:
68-
state_change_names = fn.__dict__["_trame_state_change"]
69-
logger.debug(
70-
f"state.change({[f'{prefix}{v}' for v in state_change_names]})({k[0]})"
71-
)
72-
server.state.change(
73-
*[f"{prefix}{v}" for v in state_change_names]
74-
)(fn)
75-
76-
# Handle @trigger
77-
if "_trame_trigger_names" in fn.__dict__:
78-
trigger_names = fn.__dict__["_trame_trigger_names"]
79-
for trigger_name in trigger_names:
80-
logger.debug(f"trigger({trigger_name})({k[0]})")
81-
server.trigger(f"{trigger_name}")(fn)
82-
if prefix:
83-
logger.debug(f"trigger({prefix}{trigger_name})({k[0]})")
84-
server.trigger(f"{prefix}{trigger_name}")(fn)
85-
86-
# Handle @ctrl.[add, once, add_task, set]
87-
if "_trame_controller" in fn.__dict__:
88-
actions = fn.__dict__["_trame_controller"]
89-
for action in actions:
90-
name = action.get("name")
91-
method = action.get("method")
92-
decorate = getattr(server.controller, method)
93-
logger.debug(f"ctrl.{method}({name})({k[0]})")
94-
decorate(name)(fn)
95-
if prefix:
96-
logger.debug(f"ctrl.{method}({prefix}{name})({k[0]})")
97-
decorate(f"{prefix}{name}")(fn)
98-
99-
return TrameWrapper
45+
self.klass_init = klass.__init__
46+
47+
@functools.wraps(klass.__init__, updated=())
48+
def wrapped_init(instance, *args, **kwargs):
49+
logger.debug("Create instance")
50+
self.klass_init(instance, *args, **kwargs)
51+
52+
logger.debug("Instance created")
53+
54+
server = getattr(instance, self.server_name)
55+
prefix = (
56+
getattr(instance, self.namespace_prefix)
57+
if self.namespace_prefix
58+
else ""
59+
)
60+
61+
logger.debug(f"{server=} {prefix=}")
62+
63+
# Look for method decorator
64+
for k in inspect.getmembers(instance.__class__, can_be_decorated):
65+
fn = getattr(instance, k[0])
66+
67+
# Handle @state.change
68+
if "_trame_state_change" in fn.__dict__:
69+
state_change_names = fn.__dict__["_trame_state_change"]
70+
logger.debug(
71+
f"state.change({[f'{prefix}{v}' for v in state_change_names]})({k[0]})"
72+
)
73+
server.state.change(*[f"{prefix}{v}" for v in state_change_names])(
74+
fn
75+
)
76+
77+
# Handle @trigger
78+
if "_trame_trigger_names" in fn.__dict__:
79+
trigger_names = fn.__dict__["_trame_trigger_names"]
80+
for trigger_name in trigger_names:
81+
logger.debug(f"trigger({trigger_name})({k[0]})")
82+
server.trigger(f"{trigger_name}")(fn)
83+
if prefix:
84+
logger.debug(f"trigger({prefix}{trigger_name})({k[0]})")
85+
server.trigger(f"{prefix}{trigger_name}")(fn)
86+
87+
# Handle @ctrl.[add, once, add_task, set]
88+
if "_trame_controller" in fn.__dict__:
89+
actions = fn.__dict__["_trame_controller"]
90+
for action in actions:
91+
name = action.get("name")
92+
method = action.get("method")
93+
decorate = getattr(server.controller, method)
94+
logger.debug(f"ctrl.{method}({name})({k[0]})")
95+
decorate(name)(fn)
96+
if prefix:
97+
logger.debug(f"ctrl.{method}({prefix}{name})({k[0]})")
98+
decorate(f"{prefix}{name}")(fn)
99+
100+
klass.__init__ = wrapped_init
101+
return klass
100102

101103

102104
def change(*args):

0 commit comments

Comments
 (0)