npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@monudj/monu-callback

v0.0.2

Published

DO NOT USE: see ipycallback instead. This is for testing purposes. Use this widget to allow client side (javascript) to trigger event on the server side (python)

Downloads

7

Readme

ipycallback

Build Status codecov

A widget that allows javascript (client) and python (server) communicate with each other.

Installation

You can install using pip:

pip install ipycallback

Or if you use jupyterlab:

pip install ipycallback
jupyter labextension install @jupyter-widgets/jupyterlab-manager

If you are using Jupyter Notebook 5.2 or earlier, you may also need to enable the nbextension:

jupyter nbextension enable --py [--sys-prefix|--user|--system] ipycallback

Examples

  1. Create a widget (server)
from ipycallback import SlowTunnelWidget

tunnel = SlowTunnelWidget()
display(tunnel)
  1. Send messages from python to javascript (server)
tunnel.send_msg(ujson.dumps({"msg": "hello world"}))
  1. Listen to messages from javascript (server). This will override any previous listeners.
def handle_msg(version: int, msg: str):
    print('receive message', version, msg)

tunnel.on_receive(handle_msg)
  1. Listen to messages from python (client). This will override any previous listeners.
window.IPyCallback.get("<tunnel.model_id>").on_receive((version, msg) => {
    console.log('receive message', version, msg);
});
  1. Send messages from javascript to python (client).
let version = window.IPyCallback.get("<tunnel.model_id>").send_msg(JSON.stringify({"msg": "hello world"}));
  1. Implement a "synchronous" call-and-wait
// (client)
// send a message to the server, this function returns a version of this message, which is just the previous
// version + 1
let version = tunnel.send_msg("message");
tunnel.on_receive((resp_version, response) => {
    // ignore the response if it is old
    if (resp_version < version) return;

    // put your code to handle the response in here
});
# (server)
def on_receive(version: int, msg: str):
    # handle the message
    resp_msg = msg

    # generate a response with a specific version to ensure the order
    tunnel.send_msg_with_version(version, resp_msg)

See examples for more.

How does this work

Low-level ipywidgets documentation: https://ipywidgets.readthedocs.io/en/latest/examples/Widget%20Low%20Level.html

It contains two endpoints (or queue):

  1. py_endpoint for the client to "send" messages to the server. Specifically, when the value is changed in the client, Jupyter notebook comms fires a message to the python kernel. The python code that listens to the change event of this endpoint will pick it up and the on_receive_handler function will be called with two parameters: the version of this message, and the message.
  2. js_endpoint for the server to "send" messages to the client. The mechanic is similar to the py_endpoint.

Note that each message is associated with a "version". Normally, you won't need to handle message's version if your applications don't need to have a synchronous "call-and-receive" mechanism. An example of an application that need synchronous "call-and-receive" is fulltext search where users type some keyword, the request is send to the server, while the response is generated, users may modify their query, which create another request to the server. Even though you may try to cancel the previous request, you still may end up receiving two responses in which the later response is from the former request. A solution to this problem is to associate each request with a value (version) that represent the order of the requests. On the server side, a message with older version will be discard and won't be send to the client, while on the client side, when they receive a message, they can discard the message if they have made a newer message. In this scenario, we should have the message's version in py_endpoint will always be equal to the message's version in the js_endpoint or be the js_endpoint message's version plus 1 (when there is a request that server is handling). Below is a snippet showing how this works:

// (client)
// send a message to the server, this function returns a version of this message, which is just the previous
// version + 1
let version = tunnel.send_msg("message");
tunnel.on_receive((resp_version, response) => {
    // ignore the response if it is old
    if (resp_version < version) return;

    // put your code to handle the response in here
});
# (server)
def on_receive(version: int, msg: str):
    # handle the message
    resp_msg = msg

    # generate a response with a specific version to ensure the order
    tunnel.send_msg_with_version(version, resp_msg)

In case your applications only need to sync the state of the client and server models (may be because you don't want to write an extension for that), then you can use just one endpoint: js_endpoint if you want to push the server's state to the client (use the send_msg function in python), or py_endpoint if you want to push the client's state to the server (use the send_msg function in javascript).

Development

Release the package (original):

  1. Update the version in package.json, ipycallback/_frontend.py and ipycallback/_version.py.
  2. Relase the npm packages:
    npm login
    npm publish
  3. Bundle the python package: python setup.py sdist bdist_wheel
  4. Publish the package to PyPI: twine upload -u <username> -p <password> dist/ipycallback*