Repository navigation
Description
Bug report
Bug summary
In NeXpy, a PyQt application that subclasses NavigationToolbar2QT in backends/backend_qt5.py, a call to _init_toolbar fails because of a TypeError, which is generated by an internal conflict between positional and keyword arguments within the Matplotlib code. This affects Matplotlib v3.2.0, but not v3.1.2.
The issue is caused by a call to _icon in _init_toolbar, i.e., self._icon(image_file + '.png', icon_color), which has the color defined as a positional argument. However, the _icon function is defined as def _icon(self, name, color=None):
I don't understand why this is a problem. I thought that Python is tolerant of keyword arguments being defined as positional arguments when there is no ambiguity. I also have no idea why it doesn't appear to affect the toolbar initialization when opening a PyQt window in pyplot, e.g., within a Jupyter qtconsole client, which presumably calls the same function. I would be grateful if anyone else does understand it and can suggest a work-around. Nevertheless, I presume that the Matplotlib code should respect the use of keyword arguments.
Traceback
~/miniconda3/lib/python3.7/site-packages/nexpy/gui/plotview.py in _init_toolbar(self)
3385 ('Add', 'Add plot data to tree', 'hand', 'add_data')
3386 )
-> 3387 super(NXNavigationToolbar, self)._init_toolbar()
3388 self._actions['set_aspect'].setCheckable(True)
3389 for action in self.findChildren(QtWidgets.QAction):
~/miniconda3/lib/python3.7/site-packages/matplotlib/backends/backend_qt5.py in _init_toolbar(self)
698 self.addSeparator()
699 else:
--> 700 a = self.addAction(self._icon(image_file + '.png', icon_color),
701 text, getattr(self, callback))
702 self._actions[callback] = a
TypeError: _icon() takes 2 positional arguments but 3 were given
Matplotlib version
- Operating system: Mac OS X
- Matplotlib version: 3.2.0
- Matplotlib backend: Qt5Agg
- Python version: 3.7 and 3.8
I tested this with Matplotlib v3.2.0 installed by pip and conda.
Activity
tacaswell commentedon Mar 18, 2020
What I think happened is that in #14810 we added an (optional) keyword argument to
NavigationToolbar2QT._iconand make use of of the keyword internally.However, in nexpy you are over-loading
_icon(https://github.com/nexpy/nexpy/blob/1b0adabbdabe0ace5cd9131577e3ba8c2b96c3f5/src/nexpy/gui/plotview.py#L3367-L3369) matching the old signature so when initializing nexpy's custom toolbar theself._iconcall (in Matplotlib's code) finds the_icondefinition from nexpy's code that then complains about there being too many positional arguments.Given that this is a private method I think the best fix is for nexpy to add the colors param to he signature of
_icon(or add*args, **kwargs) and ignore it which should get nexpy working with all versions of Matplotlib again.rayosborn commentedon Mar 18, 2020
Thanks for the quick response. That's embarrassing. I had forgotten that I had overridden the
_iconfunction as well. I was thrown off by assuming it was a positional vs keyword issue. I agree then that this is not really a Matplotlib issue. Unless you think there are other ramifications, please feel free to close this.anntzer commentedon Mar 18, 2020
I'll close, as I don't think there's anything to change on our side? Except perhaps "let's try to avoid APIs where third parties may want to subclass private methods".