-
Notifications
You must be signed in to change notification settings - Fork 47
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鈥檒l occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use psygnal instead of EventEmitter
(callbacks receive value directly). Add deprecation strategy
#253
Conversation
Codecov Report
@@ Coverage Diff @@
## main #253 +/- ##
==========================================
- Coverage 89.96% 89.96% -0.01%
==========================================
Files 29 29
Lines 3258 3257 -1
==========================================
- Hits 2931 2930 -1
Misses 327 327
Continue to review full report at Codecov.
|
EventEmitter
(callbacks receive value directly). Add deprecation strategy
Hi, @tlambert03 . I think I can do without |
looks like you've already updated |
ok, we should probably figure out why that's happening on the napari side then. This code works for me (you too?): from magicgui import magicgui
@magicgui
def f(x: int):
print(locals())
f.called.connect(lambda e: f.close())
f.show() # clicking the run button prints locals before closing edit: hmm... it seems to work for me on napari too. Can you make an issue either here or at napari with a minimal example showing the problem? |
Thank you, @tlambert03 , the
OK, I'll open a issue in napari. |
thanks! |
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.
Nice work here. I think we should go with the change and then make the new 0.4.0
magicgui release. i looked through some of the deprecation approach - i looks good to me.
My next big question is - should we switch over the main napari repo to use pysgnal too? I'd be curious what @goanpeca thinks about that. I can't remember if we've discussed. I'd probably be in favour of it, but curious what he and others think too
I'd like to eventually ... with the notable exception of mouse events and keyboard events. Those make a lot of sense as a single (possibly complicated) event object, and I can see why vispy used them (since it's almost all mouse/keyboard events). Basically, everything that has some sort of |
@tlambert03 before I look at the code, I'll say I generally like the API, but since we are overhauling a lot of big things, should we rethink a few things?
|
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.
does this still have the block() context manager? (probably reading the code will clarify but wanted to write down all my thoughts)
Yup, except it's "blocked". I would suggest renaming to "block"?
Anyway, I very much like the PR! See my comments above, they are very small, and I would consider none of them blockers.
One more thought, could be dumb: it's kinda nice to have a decorator that shows you when an event is going to trigger a function. Could we also make a decorator for emitting when a function/method is called? e.g.:
|
oh if you really want it i suppose there's no harm :)
yes, the signature is up to the emitter... so you can add as many or as few positional params: class T:
changed = Signal(str, str) # new, previous
t = T()
t.changed.emit('new', 'old') the receiver, however, can accept as many (or as few) of the params as it wants: @t.changed.connect
def i_take_them_all(new_val: str, old_val: str): ...
@t.changed.connect
def but_this_is_fine(): ...
@t.changed.connect
def so_is_this(new_val: str): ...
I'm not sure either... just observing that Qt seems to reserve mouse and keyboard events for non signals. I don't know that it's just related to complexity. need to ponder that.
I dunno... I kind of favor past tense "blocked" in context managers cause it reads like a sentence: with signal.blocked():
do_something()
# this feels a little less "englishy" 馃お
with signal.block():
do_something() besides,
interesting! I do kinda like it. two things to note though:
could be handy! |
lovely.
Interesting, I guess
I guess that makes it pretty final 馃槀
Yeah, I guess I was hoping that some kind of magic could be done so that it would apply to the instance. But perhaps it's too hard/magicky to bother.
Yes, that was my idea. Currently most/all of our in-place modifiers don't return anything, so I don't think that's a big ask! |
Co-authored-by: Juan Nunez-Iglesias <juan.nunez-iglesias@monash.edu>
This PR removes events.py and uses psygnal instead... In general, I dislike the event object that gets passed around in callbacks (it makes sense for mouse events and stuff, but not so much for single value callbacks). This was originally raised by @berl in https://github.com/napari/magicgui/issues/173, and I agree with the sentiment there that requiring a user to make a callback that uses
event.value
is stranger than just usingvalue
directly. This supersedes and closes #182This is still WIP, as I need to add deprecation warningsupdate:
I believe this is now ready for some input! The major changes are described below (and will be added to https://github.com/napari/magicgui/issues/255, which is linked directly in the warning message).
馃憞
The big change here is that callbacks connected to
widget.changed
(and other event emitters) now receive the value(s) directly, instead of an event object:the change
for the few packages who were manually emitting change events:
deprecation strategy
def my_callback(param):
) will receive theEvent
object as they currently do, but will now see aFutureWarning
explaining the upcoming change. (note, theEvent object
is now just a simplenamedtuple
that matches the API of the oldEvent
object.)magicgui.events.Event
. e.g.def my_callback(param: str):
will receive the value directly, not a Event.Event
objects (they too would have broken before)widget.changed(value='whatever')
will get aFutureWarning
explaining that they should usewidget.changed.emit('whatever')
instead.breaking:
connect(..., position=...)
)... @hanjinliu, I see you're using that a bit inmagic-class
), so would be curious to hear how troublesome losing that will be.I tested this PR with stardist-napari, (which I believe might be the package using the largest "surface" of the current events API), and it works (though of course emits a lot of warnings now). @uschmidt83, @maweigert, I can help with those updates as well.
@sofroniewn and @jni ... i know we've discussed this before, but just wanted to give you another heads up