Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Any way to make this work with mutable data structures? #252

Open
zulrang opened this issue Jan 16, 2024 · 4 comments
Open

Any way to make this work with mutable data structures? #252

zulrang opened this issue Jan 16, 2024 · 4 comments

Comments

@zulrang
Copy link

zulrang commented Jan 16, 2024

  • psygnal version: 0.9.5
  • Python version: 3.11.6
  • Operating System: Ubuntu 22.04.3

Description

After connecting events to mutable types, I would expect that events are called when they are mutated.

What I Did

from psygnal import EventedModel


class MyModel(EventedModel):
    data: dict = {}
    values: list[int]

model = MyModel(data={'foo': 'bar'}, values=[1, 2, 3])
model.events.data.connect(lambda v: print(f"updated data: {v}"))
model.events.values.connect(lambda v: print(f"updated values: {v}"))

model.data['test'] = 'fail'
model.values.append(4)

This doesn't print anything.

@tlambert03
Copy link
Member

you would need to use an evented container like psygnal.containers.EventedList. The reason is that when you set the attribute of a field directly model.field = thing, it goes through the __setattr__ of the model. When you use model.values.append (or any other thing that calls model.values.__setitem__) then there's no way for the evented model to know about it.

You would need to do something like this:

from psygnal import EventedModel
from psygnal.containers import EventedList

class MyModel(EventedModel):
    data: dict = {}
    values: EventedList[int]

however, on a quick try, I'm noticing a couple issues at the moment with using an unmodified EventedList as a hint for a pydantic model (both v1 and v2). So, let me have a closer look tomorrow.

@tlambert03
Copy link
Member

also related... even once it does work as a field (which it should)... you'll have the issue of nested events. That is, since an evented list has many events (not just a single change event), it's not immediately clear how one should access them on the model.events field itself. This was being addressed in #169 ... but it hasn't seen action in a while. Let me know if you specifically need the nesting for your use case, or if using model.values.events... would be sufficient in this case

@ndxmrb
Copy link

ndxmrb commented Mar 8, 2024

After this has seen some work but no answer from OP so far, I thought I'd chime in:
I would love to see #169 coming back to life, because it could enable undo/redo implementations by using the memento or state-diff patterns. Then use EventedModel.update() for in-place updates from the saved states.

@tlambert03
Copy link
Member

thanks for chiming in @ndxmrb, it definitely helps to know what features people would like to see implemented! I'll look at reviving that PR, as I'm also still interested in using it myself

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants