Conditionals do not shortcut the evaluations under them.
Currently we have a problem with enaml Conditionals where subscriptions under the Conditional are evaluating even after the condition has gone false. Effectively, we are missing the short cutting that you would need for this to behave correctly.
Here is a sample app that demonstrates the issue. Press the "Switch" button twice and an exception will be raised due to a type error.
from enaml.widgets.api import MainWindow, Container, PushButton, Label
from enaml.core.api import Conditional
enamldef Main(MainWindow): mw:
attr string_or_int = "abc"
Container:
PushButton:
text = "Switch"
clicked::
mw.string_or_int = 99 if isinstance(mw.string_or_int, str) else "abc"
Conditional:
condition << isinstance(mw.string_or_int, str)
Label:
text << mw.string_or_int[1]
Conditional:
condition << isinstance(mw.string_or_int, int)
Label:
text << str(mw.string_or_int / 3)
One possible option to fix this would be to add a "depth" property to subscriptions and processing in a depth based order, unsubscribing invalidated Conditionals' children as we go, but that seems fairly invasive. Not sure if there is an easier way to fix it.
Thanks for the report. I think this is something I have seen in the past but did not get the occasion to fix.
I agree with you that a depth based traversal would be a way to solve this. However as you say it would be a bit invasive and may require some additional C extension to remain performant. I doubt I will have time to work on such a change any time soon but I can share ideas and advice if anybody is interested.
It might be simpler to just have the Conditional dispose of its children
if the condition is false and recreate them when true. Might be a bit
slower, but would probably be "correct".
On Tue, Sep 2, 2025 at 3:20 PM Matthieu Dartiailh @.***> wrote:
MatthieuDartiailh left a comment (nucleic/enaml#581) https://github.com/nucleic/enaml/issues/581#issuecomment-3246671252
Thanks for the report. I think this is something I have seen in the past but did not get the occasion to fix.
I agree with you that a depth based traversal would be a way to solve this. However as you say it would be a bit invasive and may require some additional C extension to remain performant. I doubt I will have time to work on such a change any time soon but I can share ideas and advice if anybody is interested.
— Reply to this email directly, view it on GitHub https://github.com/nucleic/enaml/issues/581#issuecomment-3246671252, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABBQSOMBJORWCJUCOUJ53T3QX3XFAVCNFSM6AAAAACFB5QQHGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZTENBWGY3TCMRVGI . You are receiving this because you are subscribed to this thread.Message ID: @.***>
@sccolbert for this to work we would need the guarantee that the condition is always updated first. Is that a guarantee we have ?
I checked the code and the Conditional does destroy its outdated children. However the problem does stem from the fact that the label is updated before the conditional (tested using breakpoint in the conditional and such). So the root issue is indeed the order in which updates occur.