feat(displayhook): add register_hook/unregister_hook to ZMQShellDisplayHook#1522
Open
rgbkrk wants to merge 2 commits into
Open
feat(displayhook): add register_hook/unregister_hook to ZMQShellDisplayHook#1522rgbkrk wants to merge 2 commits into
rgbkrk wants to merge 2 commits into
Conversation
…ayHook Mirrors the hook chain on ZMQDisplayPublisher so the same transform function can register on both display_data and execute_result. Lets extensions attach ZMQ buffers (or otherwise mutate/suppress) the bare-last-expression execute_result message without subclassing ZMQShellDisplayHook and reimplementing finish_displayhook. Hook contract matches ZMQDisplayPublisher.register_hook: hook(msg) -> msg continue chain hook(msg) -> None suppress send
…playHook Mirrors the ZMQDisplayPublisher hook tests (NoReturnHook / ReturnHook, thread-local isolation, unregister) and adds: - a mutation test that attaches buffers to the outbound message — the motivating use case for execute_result hooks - short-circuit semantics in a multi-hook chain - threading semantics: each hook receives the previous hook's return value - the existing empty-data guard still suppresses both hooks and send
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Mirrors the
register_hook/unregister_hook/_hookschain thatZMQDisplayPublisheralready has, but onZMQShellDisplayHook— the displayhook used for the bare-last-expressionexecute_resultpath.finish_displayhooknow runs the chain beforesession.send, with the same contract asZMQDisplayPublisher.publish:hook(msg) -> msg— pass through, continue the chain, eventuallysession.send.hook(msg) -> None— hook handled the send itself; suppress the default send.The hook list lives on a
threading.local()so registrations don't leak across threads, matching the existing implementation onZMQDisplayPublisher.Motivation
DisplayFormatteris the documented extension point for mime formatting, but inside ipykerneldisplay_dataandexecute_resulttake different paths after formatting:ZMQDisplayPublisher.publish(used bydisplay()/display_data) builds the message and walksself._hooksbefore callingsession.send. That's where buffer-attaching transforms, redirectors, and similar extensions live today.ZMQShellDisplayHook.finish_displayhook(used for the bare-last-expressionexecute_resultpath) callssession.senddirectly with no hook chain.So an extension that wants identical behavior on both paths — for example, attaching ZMQ
buffersto the outbound message — has to subclassZMQShellDisplayHookand reimplementfinish_displayhookfrom scratch. This PR makes the two paths symmetric so a single hook function canregister_hookon both seats.Concrete use case
Streaming Arrow IPC bytes alongside a small JSON envelope on
display_data/execute_result, without going through comms or widgets. The kernel emits a normal display message whosedatacarries a structured payload (mimetype + ref) and attaches the Arrow bytes as ZMQbuffers; the frontend reassembles. This pattern composes naturally with__arrow_c_stream__, so any dataframe library that implements the protocol gets a high-fidelity representation without per-library shims.Doing this on
display_dataworks today viaZMQDisplayPublisher.register_hook. Doing it onexecute_result(the baredfon the last line of a cell) requires the same hook to fire onZMQShellDisplayHook, which it can't today. nteract currently carries a subclass to bridge the gap; with this PR upstream, the subclass goes away.Compatibility
self.msg,content.datanon-empty,self.sessionconfigured) are preserved, andsession.sendis called exactly as before.ZMQDisplayPublisher's, so a hook authored againstdisplay_dataworks unchanged onexecute_result.ZMQDisplayPublisheralready provides.