8000 [Bug]: "Unhashable type" when event callback is a method of a `dict` subclass · Issue #26012 · matplotlib/matplotlib · GitHub
[go: up one dir, main page]

Skip to content
[Bug]: "Unhashable type" when event callback is a method of a dict subclass #26012
Closed
@charwick

Description

@charwick

Bug summary

I've got a class Charts that uses self.fig.canvas.mpl_connect('key_press_event', self.sendEvent) to handle keypresses, which works fine. But recently I tried changing my class to subclass dict, and – oddly – this seems to confuse Matplotlib. I get the error:

  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/helipad/visualize.py", line 72, in launch
    self.fig.canvas.mpl_connect('key_press_event', self.sendEvent)
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/matplotlib/backend_bases.py", line 2476, in mpl_connect
    return self.callbacks.connect(s, func)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/matplotlib/cbook/__init__.py", line 228, in connect
    if proxy in self._func_cid_map[signal]:
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: unhashable type: 'Charts'

Which is weird because I'm not passing Charts at all.
Looking at MPL's code, it looks like the _weak_or_strong_ref function is getting a reference to Charts back out of the method I passed as a callback, putting it in the proxy variable, and hashing it, which subclassing dict prevents it from doing.

Code for reproduction

import matplotlib.pyplot as plt

class ThisWorks:
	def __init__(self):
		self.fig, plots = plt.subplots(1)
		self.fig.canvas.mpl_connect('key_press_event', self.sendEvent)
		self.keyListeners = {}

	def sendEvent(self, event):
		if event.name=='key_press_event' and event.key in self.keyListeners:
			for f in self.keyListeners[event.key]: f(self.model, event)

class ThisDoesntWork(ThisWorks, dict): pass

x = ThisDoesntWork()

Actual outcome

Traceback (most recent call last):
  File "/Users/charwick/Desktop/example.py", line 15, in <module>
    x = ThisDoesntWork()
        ^^^^^^^^^^^^^^^^
  File "example.py", line 6, in __init__
    self.fig.canvas.mpl_connect('key_press_event', self.sendEvent)
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/matplotlib/backend_bases.py", line 2476, in mpl_connect
    return self.callbacks.connect(s, func)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/matplotlib/cbook/__init__.py", line 227, in connect
    if proxy in self._func_cid_map[signal]:
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: unhashable type: 'ThisDoesntWork'

Expected outcome

Code above doesn't actually do anything, but it shouldn't generate an error.

Additional information

No response

Operating system

MacOS 13.3.1

Matplotlib Version

3.7.1

Matplotlib Backend

No response

Python version

3.11.3

Jupyter version

No response

Installation

pip

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0