Skip to content

Commit 0a12c60

Browse files
committed
Add EvalFuncVar binding via descriptor and drop manual rebinding
1 parent 9baf48b commit 0a12c60

File tree

2 files changed

+61
-16
lines changed

2 files changed

+61
-16
lines changed

custom_components/pyscript/eval.py

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -873,6 +873,15 @@ def get_ast_ctx(self):
873873
"""Return the ast context."""
874874
return self.ast_ctx
875875

876+
def __get__(self, obj, objtype=None):
877+
"""Support descriptor protocol so class attributes bind to instances."""
878+
if obj is None:
879+
return self
880+
# we use weak references when we bind the method calls to the instance inst;
881+
# otherwise these self references cause the object to not be deleted until
882+
# it is later garbage collected
883+
return EvalFuncVarClassInst(self.func, self.ast_ctx, weakref.ref(obj))
884+
876885
def __del__(self):
877886
"""On deletion, stop any triggers for this function."""
878887
if self.func:
@@ -1983,22 +1992,6 @@ async def call_func(self, func, func_name, *args, **kwargs):
19831992
if inspect.isclass(func) and hasattr(func, "__init__evalfunc_wrap__"):
19841993
has_init_wrapper = getattr(func, "__init__evalfunc_wrap__") is not None
19851994
inst = func(*args, **kwargs) if not has_init_wrapper else func()
1986-
#
1987-
# we use weak references when we bind the method calls to the instance inst;
1988-
# otherwise these self references cause the object to not be deleted until
1989-
# it is later garbage collected
1990-
#
1991-
inst_weak = weakref.ref(inst)
1992-
for name in dir(inst):
1993-
try:
1994-
value = getattr(inst, name)
1995-
except AttributeError:
1996-
# same effect as hasattr (which also catches AttributeError)
1997-
# dir() may list names that aren't actually accessible attributes
1998-
continue
1999-
if type(value) is not EvalFuncVar:
2000-
continue
2001-
setattr(inst, name, EvalFuncVarClassInst(value.get_func(), value.get_ast_ctx(), inst_weak))
20021995
if has_init_wrapper:
20031996
#
20041997
# since our __init__ function is async, call the renamed one

tests/test_unit_eval.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,58 @@ class Color(Enum):
181181
],
182182
[
183183
"""
184+
from enum import Enum
185+
186+
class HomeState(Enum):
187+
HOME = "home"
188+
AWAY = "away"
189+
190+
def name_and_value(self):
191+
return f"{self.name}:{self.value}"
192+
193+
[HomeState.HOME.name_and_value(), HomeState.AWAY.name_and_value()]
194+
""",
195+
["HOME:home", "AWAY:away"],
196+
],
197+
[
198+
"""
199+
class Device:
200+
def greet(self, name):
201+
return f"hi {name} from {self.__class__.__name__}"
202+
203+
d = Device()
204+
d.greet("Alice")
205+
""",
206+
"hi Alice from Device",
207+
],
208+
[
209+
"""
210+
def add(self, x, y=0):
211+
return x + y
212+
213+
class Calc:
214+
pass
215+
216+
Calc.add = add
217+
Calc().add(2, 3)
218+
""",
219+
5,
220+
],
221+
[
222+
"""
223+
class Base:
224+
def tag(self):
225+
return "base"
226+
227+
class Child(Base):
228+
pass
229+
230+
Child().tag()
231+
""",
232+
"base",
233+
],
234+
[
235+
"""
184236
from dataclasses import dataclass
185237
186238
@dataclass()

0 commit comments

Comments
 (0)