nucleic / enaml

Declarative User Interfaces for Python
http://enaml.readthedocs.io/en/latest/
Other
1.53k stars 130 forks source link

An async func isn't correctly determined to be a coroutine function #431

Closed frmdstryr closed 3 years ago

frmdstryr commented 3 years ago

Minor issue... but 'async func' methods on enamldefs currently don't seem to properly have "async-ness".

Eg:

import asyncio
from enaml.core.api import Looper
from enaml.widgets.api import Window, Container, Form, Label, PushButton

async def foo():
    pass # Good

class Method:
    async def foo():
        pass # Good

enamldef Main(Window): window:

    async func bar():
        pass

    func check_async():
        assert asyncio.iscoroutinefunction(foo)
        assert asyncio.iscoroutinefunction(Method.foo)
        assert asyncio.iscoroutinefunction(self.bar)

    Container:
        PushButton:
            text = "Check"
            clicked :: check_async()
Traceback (most recent call last):
  File "/home/user/Workspace/enaml/enaml/qt/qt_abstract_button.py", line 83, in on_clicked
    self.declaration.clicked(checked)
  File "/home/user/Workspace/enaml/enaml/core/declarative_meta.py", line 68, in declarative_change_handler
    engine.write(owner, change['name'], change)
  File "/home/user/Workspace/enaml/enaml/core/expression_engine.py", line 210, in write
    pair.writer(owner, name, change)
  File "/home/user/Workspace/enaml/enaml/core/standard_handlers.py", line 82, in __call__
    call_func(func, (), {}, scope)
  File "tests/example.enaml", line 27, in f
    clicked :: check_async()
  File "tests/example.enaml", line 21, in check_async
    assert asyncio.iscoroutinefunction(self.bar)
AssertionError

inspect.iscorourtinefunction checks for the CO_COROUTINE flag.

I don't remember if this worked before or not but it doesn't on 0.12.0.

frmdstryr commented 3 years ago

I guess this is because a dfunc isn't a method or function, so it's not worth messing with this.

MatthieuDartiailh commented 3 years ago

I will try to have a look nonetheless, it should work.

MatthieuDartiailh commented 3 years ago

Indeed declarative functions and methods do not inherit from FunctionType and MethodType meaning that the inspect functions do not know how to handle them. Running them on the __func__ attribute should give meaningful results. We could try to clean up the inheritance but we would have to mirror all the actual function attribute on the dfunc. I am not sure it is worth it. Let me know what you think

frmdstryr commented 3 years ago

Running them on the __func__ attribute should give meaningful results.

That's good to know if it's ever needed in the future.

I ended up re-writing the part of code using this so it didn't need to check async'ness anymore so i'd say just leave it as is.