-
Notifications
You must be signed in to change notification settings - Fork 81
fix(timer): BlynkTimer Broken on Low Memory Ports #6
Conversation
On low memory ports MICROPY_PY_FUNCTION_ATTRS is disabled, leading BlynkTimer to raise an AttributeError when trying to get a name for a new timer. This fixes it by naming each timer 'X_timer' (where X is the # of timer) if the __name__ attribute does not exist. Fixes blynkkk#5
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot for your findings . All looks good. I have only one small proposal for code modification
getattr should capture AttributeError if default value was provided.
|
Okay, I pushed a cleaner version that should work for all cases. def _get_func_name(self, obj):
if getattr(obj, 'func', None) is None:
return 'timer'
elif getattr(obj, 'name', None) is None:
return self._get_func_name(obj.func)
return obj.name would also be problematic. Also To be honest, I just don't understand why |
I ok with hasattr - maybe previously I just get used to getattrs )).
|
Well haha, see my co 8000 mment This will still always return 'timer' for any |
With: def _get_func_name(self, obj):
if hasattr(obj, 'func'):
return self._get_func_name(obj.func)
return getattr(obj, '__name__', 'timer') The flow can go three ways: 1.)
2.)
3.)
Is there another usage case that I am missing? |
Okay, final comment for the night haha. main.py def _get_func_name(obj):
if hasattr(obj, 'func'):
print(obj.func)
return _get_func_name(obj.func)
return getattr(obj, '__name__', 'timer')
def test():
pass
class FakeFuncAttr:
func = test
def __init__():
pass
def test_func_name():
print("GET FUNC NAME")
x = test
print(_get_func_name(x))
def test_with_func_attr():
print("TEST WITH FUNC ATTR (forced for test)")
x = FakeFuncAttr
# setattr(x, 'func', y) - doesnt work on micropython :(
print(_get_func_name(x)) Results on ESP8266 (no function attrs enabled): MicroPython v1.11 on 2019-06-03; ESP module with ESP8266
Type "help()" for more information.
>>>
>>> import main
>>> main.test_func_name()
GET FUNC NAME
timer
>>> main.test_with_func_attr()
TEST WITH FUNC ATTR (forced for test)
<function test at 0x3ffefff0>
timer
>>> Results on ESP32 (function attrs enabled): MicroPython v1.11-47-g1a51fc9dd on 2019-06-18; ESP32 module with ESP32Type "help()" for more information.
>>>
>>> import main
>>> main.test_
test_func_name test_with_func_attr
>>> main.test_func_name()
GET FUNC NAME
test
>>> main.test_with_func_attr()
TEST WITH FUNC ATTR (forced for test)
<function test at 0x3ffc3b00>
test
>>> Is this not what we are trying to achieve? Hope we come to a conclusion here haha, but I am gonna catch some sleep. Its been fun haha. |
Finally I have remebered purpose of obj.func ))
Initially I on quick view I was thinking that this is something internal ) So here you are right and you solution will cover expected cases.
|
Haha! Wow, thats it, I never thought about that possibility. But yeah your definitely right about adding some comments. Went ahead and updated it. |
Thx! |
Fixes #5
Notes
On most low memory ports (such as the esp8266) the config variable
MICROPY_PY_FUNCTION_ATTRS
is disabled, effectively meaningfunc.__name__
doesn't exist. (See micropython/micropython#614 for more details)Because
Timer
relies onfunc.__name__
to name its timers, its effectively broken on any port withoutMICROPY_PY_FUNCTION_ATTRS
enabled.Changes
This PR fixes this issue by doing the following:
Checks if
func.__name__
existsIf yes, continues as normal
If not:
obj.func
exists and reattempt with that (original fallback)Also adds a note in
TIMERS.md
referring to this change.This essentially means that on ports without
MICROPY_PY_FUNCTION_ATTRS
, timers are namedX_timer
, with X as the original number of timer.