Skip to content

Correct typo of "buttons" to "button" in webagg backend #30337

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

T-Wainwright
Copy link

@T-Wainwright T-Wainwright commented Jul 21, 2025

PR summary

cd37b73 introduces a typo which breaks visualisation in various interactive forms, mentioned in #29337, #29654

This is required for functionality of anything using interactive plots with the webagg backend

Discussion of this issue in other PR's/ issues imply upgrading ipympl to >0.9.5, this issue is persisting as I'm running matplotlib 3.10.3 and ipympl 0.9.7. Think this therefore needs to be fixed on matplotlibs side.

PR checklist

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for opening your first PR into Matplotlib!

If you have not heard from us in a week or so, please leave a new comment below and that should bring it to our attention. Most of our reviewers are volunteers and sometimes things fall through the cracks.

You can also join us on gitter for real-time discussion.

For details on testing, writing docs, and our review process, please see the developer guide

We strive to be a welcoming and open project. Please follow our Code of Conduct.

@story645
Copy link
Member

Is there any test that can be added in mpl (maybe a mock of some sort) for this?

@T-Wainwright
Copy link
Author

working on a minimal example to reproduce atm

@ianthomas23
Copy link
Member

It is not a typo, both button and buttons are valid.

@T-Wainwright
Copy link
Author

Still trying to wrap my head around a minimal working example, getting differing behaviour in a reduced case vs my application...

But if button and buttons are both valid, and one works, any reason not to change it?

@ianthomas23
Copy link
Member

But if button and buttons are both valid, and one works, any reason not to change it?

They do different things. See #28453.

@T-Wainwright
Copy link
Author

T-Wainwright commented Jul 22, 2025

Still working at an example, it's pretty finicky to reproduce so makes me wonder if there is something else going on under the hood, but forcing an error output in that block of code yields:

287 button = event['button'] + 1  # JS numbers off by 1 compared to mpl.
    288 print("event:")
--> [289] raise Exception(repr(event))
    290 buttons = {  # JS ordering different compared to mpl.
    291     button for button, mask in [
    292         (MouseButton.LEFT, 1),
   (...)    297     ] if event['buttons'] & mask  # State *after* press/release.
    298 }
    299 modifiers = event['modifiers']

Exception: {'x': 441, 'y': 185, 'button': 0, 'step': 1, 'modifiers': [], 'guiEvent': {'isTrusted': True, 'data': 'scroll', 'step': 1}, 'type': 'scroll'}

Which at least shows for some reason 'buttons' is not in the event.

I'm happy to move this over to an issue for more discussion on ipympl or here, but I believe there is something still not right.

@ianthomas23
Copy link
Member

I'm happy to move this over to an issue for more discussion on ipympl or here, but I believe there is something still not right.

There is something wrong in the sense that this is fixed in ipympl at these lines
https://github.com/matplotlib/ipympl/blob/5e068ed222427919cc20c406e34d02ba9be55cc3/src/mpl_widget.ts#L760-L761

but some people using ipympl 0.9.7 are still seeing problems.

Personally I am not able to reproduce the problem. I use ipympl and matplotlib in jupyterlab frequently, using all 3 major OSses and different versions of python, and installing from PyPI and conda-forge. To make progress what is needed is a reliable reproducer, i.e. the steps needed to get a system into the state that ipympl 0.9.7 does not work.

@T-Wainwright
Copy link
Author

Minimal expample on my machine:

import matplotlib
matplotlib.use('module://ipympl.backend_nbagg')  # Set the backend programmatically

import matplotlib.pyplot as plt
import numpy as np

# Data
x = np.linspace(0, 2 * np.pi, 100)
y = np.sin(x)

fig, ax = plt.subplots()

ax.plot(x, y, label='Sine Wave')

plt.show()

I'm looking to interactively view on vscode server, via remote ssh. I've blown away .vscode-server to ensure a clean environment server side, with a fresh venv of python 3.12.11 pip freeze yields:

asttokens==3.0.0
comm==0.2.2
contourpy==1.3.2
cycler==0.12.1
debugpy==1.8.15
decorator==5.2.1
executing==2.2.0
fonttools==4.59.0
ipykernel==6.30.0
ipympl==0.9.7
ipython==9.4.0
ipython_pygments_lexers==1.1.1
ipywidgets==8.1.7
jedi==0.19.2
jupyter_client==8.6.3
jupyter_core==5.8.1
jupyterlab_widgets==3.0.15
kiwisolver==1.4.8
matplotlib==3.10.3
matplotlib-inline==0.1.7
nest-asyncio==1.6.0
numpy==2.3.1
packaging==25.0
parso==0.8.4
pexpect==4.9.0
pillow==11.3.0
platformdirs==4.3.8
prompt_toolkit==3.0.51
psutil==7.0.0
ptyprocess==0.7.0
pure_eval==0.2.3
Pygments==2.19.2
pyparsing==3.2.3
python-dateutil==2.9.0.post0
pyzmq==27.0.0
six==1.17.0
stack-data==0.6.3
tornado==6.5.1
traitlets==5.14.3
wcwidth==0.2.13
widgetsnbextension==4.0.14

Hope this might help?

@T-Wainwright
Copy link
Author

T-Wainwright commented Jul 22, 2025

Full steps for me to reproduce reliably:

  1. mv/ delete .vscode-server directory
  2. check ps aux | grep jupyter and kill any lingering <pid>
  3. fully close down vscode
  4. killall -u <username> on remote machine, forcing a disconnect
  5. ssh connect to remote, create test directory, cd in
  6. python3 -m venv testEnv
  7. source testEnv/bin/activate
  8. pip install ipykernel matplotlib ipympl numpy
  9. Connect to ssh host on vscode
  10. Open test directory in vscode
  11. Create test.ipynb with above code, and save
  12. Select kernel -> install recommended extensions [jupyter + python]
  13. Reload window
  14. Select kernel -> testEnv
  15. Run all

Returns:

286 e_type = event['type']
    287 button = event['button'] + 1  # JS numbers off by 1 compared to mpl.
    288 buttons = {  # JS ordering different compared to mpl.
    289     button for button, mask in [
    290         (MouseButton.LEFT, 1),
    291         (MouseButton.RIGHT, 2),
    292         (MouseButton.MIDDLE, 4),
    293         (MouseButton.BACK, 8),
    294         (MouseButton.FORWARD, 16),
--> [295] if event['buttons'] & mask  # State *after* press/release.
    296 }
    297 modifiers = event['modifiers']
    298 guiEvent = event.get('guiEvent')

@ianthomas23
Copy link
Member

Can you try using JupyterLab instead of VSCode?

@T-Wainwright
Copy link
Author

That doesn't throw any errors, so could be in the generation of the javascript sent to vscode?

@ianthomas23
Copy link
Member

It seems likely that vscode is the key factor here, given my observation that I've never experienced a problem and I always use JupyterLab rather than vscode.

I don't know what vscode does in these situations. My understanding is that it (and others such as PyCharm) reuse the Jupyter machinery but modify it for their own purposes. So it is quite possible that whatever they do has not been upgraded to work with ipympl 0.9.7 correctly.

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

Successfully merging this pull request may close these issues.

3 participants