nucleic / enaml

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

LiveEditor crash if view interaction creates exception #436

Closed Tillsten closed 3 years ago

Tillsten commented 3 years ago

Using the following code in the view and pressing the button crashs the editor.

from enaml.widgets.api import *
from enaml.layout.api import *

enamldef DemoContainer(Container):
    attr model
    PushButton:
        clicked :: model.foo
frmdstryr commented 3 years ago

What is the model?

Tillsten commented 3 years ago

The default one, which does not have a foo-member.

frmdstryr commented 3 years ago

Well I don't think this is a bug, it's just how Qt works.

Since the gui made with the editor runs in the same application as the editor itself you need to catch errors in the handler(s).


from enaml.widgets.api import *
from enaml.layout.api import *

enamldef DemoContainer(Container):
    attr model
    PushButton:
        clicked ::
            try:
                model.foo
            except Exception as e:
                print(e)

Then prints out this instead of exiting:

'NoneType' object has no attribute 'foo'
Tillsten commented 3 years ago

I think I understand why it does not work currently, but it may be possible to catch expections which originates from the the view? This the current hard-crashing behavior leads to code loss.

frmdstryr commented 3 years ago

This is Qt, not enaml... I think event handlers just need to catch errors.

See https://doc.qt.io/qt-5/exceptionsafety.html

Throwing an exception from a slot invoked by Qt's signal-slot connection mechanism is considered undefined behaviour, unless it is handled within the slot

Edit: Apologies for the snark remark... didn't mean't be rude.

Tillsten commented 3 years ago

IIRC throwing an exception in qt normally does not crash the program.

(skultrafast) c:\Users\tills\Downloads>enaml-run "live_editor(1).enaml"
Traceback (most recent call last):
  File "C:\Users\tills\miniconda3\envs\skultrafast\lib\site-packages\enaml\qt\qt_abstract_button.py", line 83, in on_clicked
    self.declaration.clicked(checked)
  File "C:\Users\tills\miniconda3\envs\skultrafast\lib\site-packages\enaml\core\declarative_meta.py", line 68, in declarative_change_handler
    engine.write(owner, change['name'], change)
  File "C:\Users\tills\miniconda3\envs\skultrafast\lib\site-packages\enaml\core\expression_engine.py", line 210, in write
    pair.writer(owner, name, change)
  File "C:\Users\tills\miniconda3\envs\skultrafast\lib\site-packages\enaml\core\standard_handlers.py", line 82, in __call__
    call_func(func, (), {}, scope)
  File "demo.enaml", line 8, in f
AttributeError: 'LiveEditorModel' object has no attribute 'i'

My issue is that currently if you write wrong code you lose everything.

MatthieuDartiailh commented 3 years ago

I will try to look into it. One option for the the example would be to set a custom handler in sys.excepthook and a recommendation in the applib documentation to do so when using it.