Skip to content
  • Sponsor matplotlib/matplotlib

  • Notifications You must be signed in to change notification settings
  • Fork 7.9k

Allow args to pass through _allow_super_init #11900

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

Merged
merged 1 commit into from
Aug 21, 2018

Conversation

hmaarrfk
Copy link
Contributor

Without this, if you call FigureCanvas without any parameters, you would get the error

__init__() missing 1 required positional argument: 'figure'

But if you would try to provide the positional argument, you would get

TypeError: wrapper() takes 1 positional argument but 2 were given

because only **kwargs were passed through.

PR Checklist

  • Has Pytest style unit tests
  • Code is PEP 8 compliant
  • New features are documented, with examples if plot related
  • Documentation is sphinx and numpydoc compliant
  • Added an entry to doc/users/next_whats_new/ if major new feature (follow instructions in README.rst there)
  • Documented in doc/api/api_changes.rst if API changed in a backward-incompatible way
PHP-Proxy

PHP-Proxy

Error accessing resource: 404 - Not Found

@jklymak
Copy link
Member

jklymak commented Aug 20, 2018

Is this correct or is the first error message incorrect? If this is right it’d be nice to have a short test.

@hmaarrfk
Copy link
Contributor Author

The function signature is:

class FigureCanvasQT(QtWidgets.QWidget, FigureCanvasBase):

    # map Qt button codes to MouseEvent's ones:
    buttond = {QtCore.Qt.LeftButton: 1,
               QtCore.Qt.MidButton: 2,
               QtCore.Qt.RightButton: 3,
               # QtCore.Qt.XButton1: None,
               # QtCore.Qt.XButton2: None,
               }

    @_allow_super_init
    def __init__(self, figure):

which doesn't force kwargs

I copy pasted the error messages I got from the terminal. It definitely took me longer than I wanted to find what was wrong in my code.

Where do your tests go?

@jklymak jklymak requested a review from anntzer August 20, 2018 18:56
@jklymak
Copy link
Member

jklymak commented Aug 20, 2018

Tests go in lib/matplotlib/tests... But I'm not familiar enough with the low-level backend APIs to know exqctly where or how you should test this. However, if something this basic got through without tripping a test, then either its being called incorrectly and our documentation needs fixing, or it needs a test!

@jklymak jklymak added this to the v2.2.4 milestone Aug 20, 2018
@hmaarrfk
Copy link
Contributor Author

Yeah.... qt5agg uses a different code path that doesn't have the error. I added a test, but it doesn't cover the error since it is using the Agg backend.

@hmaarrfk hmaarrfk force-pushed the args__allow_super_init branch from 0dac93f to c51e282 Compare August 20, 2018 19:49
@anntzer
Copy link
Contributor

anntzer commented Aug 20, 2018

I think the test should really go to test_backend_qt4agg (as there's no problem with qt5)?... which is not run on CI both because we can't install pyqt4 there and because we can't import pyqt4 and pyqt5 in the same process, but that's another can of worms.

Otherwise looks good. Doesn't seem to warrant backporting though.

@anntzer anntzer modified the milestones: v2.2.4, v3.0 Aug 20, 2018
@hmaarrfk
Copy link
Contributor Author

hmaarrfk commented Aug 20, 2018

Qt5 is not the same codepath as Qt5Agg.

The problem is with Qt5 (I'm using PySide, but the code change I made is pretty clear that it would happen with PyQt5 as well Edit: I guess not, it doesn't happen on PyQt5. I may have tried it in a different environment too, not too sure).

The bug was in lib/matplotlib/backends/backend_qt5.py. I'm not sure if it happens in Qt4. I'm pretty sure Qt4 is the same code path as Qt5 these days. I'm really not a matplotlib expert, this one was just easy to fix. I felt it would have taken longer to write the "Issue"

@anntzer
Copy link
Contributor

anntzer commented Aug 20, 2018

Now I'm confused by how exactly you got the error. "qt5" is not a backend by itself, qt5agg and qt5cairo are.

@hmaarrfk
Copy link
Contributor Author

I don't see backends_qt5 importing backends_qt5Agg...

backends_qt5 has a different FigureCanvas object
https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/backends/backend_qt5.py#L214
called FigureCanvasQT

The bug is in the decorator for FigureCanvasQT.

FigureCanvasQTAgg is distinct
https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/backends/backend_qt5agg.py#L17

@hmaarrfk
Copy link
Contributor Author

But I don't see any tests for the QT backend, only the QTAgg, so I don't really have anything to base myself on. And I'm just learning how to use Qt, so I'm no expert.

@jklymak
Copy link
Member

jklymak commented Aug 20, 2018

I'm still confused; on master, v2.2.2, and v2.2.3 , without this PR, I can run

from matplotlib.backends.backend_qt4agg import FigureCanvas
from matplotlib.figure import Figure

FigureCanvas(Figure())
FigureCanvas(figure=Figure())

without the errors in your original message for either qt4 or qt5. Can you specify what code triggers the error this PR is supposed to fix?

@hmaarrfk
Copy link
Contributor Author

In [2]: from matplotlib.backends.backend_qt5 import FigureCanvas
   ...: from matplotlib.figure import Figure
   ...: 
   ...: FigureCanvas(Figure())
   ...: 
   ...: 
   ...: 
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-2-d7282e013989> in <module>()
      2 from matplotlib.figure import Figure
      3 
----> 4 FigureCanvas(Figure())
      5 

TypeError: wrapper() takes 1 positional argument but 2 were given

@jklymak
Copy link
Member

jklymak commented Aug 20, 2018

I don't know the history well enough, but I think backend_qt5 is a convenience abstraction of methods shared between the backend_qt5agg and backend_qt5cairo backends, and should not be used by itself. Why it was not made private is above my paygrade, but I don't think its meant to be used directly like this....

@jklymak
Copy link
Member

jklymak commented Aug 20, 2018

Perhaps a better explanation: https://stackoverflow.com/questions/47271291/matplotlib-backends-backend-qt5-vs-from-matplotlib-backends-backend-qt5agg

@hmaarrfk
Copy link
Contributor Author

hmm ok, maybe that is why I had to add the navbar for things to draw.

that said, it is still a bug. the decorator should also pass *args.

@anntzer
Copy link
Contributor

anntzer commented Aug 20, 2018

I can't repro your bug...

In [1]: matplotlib.backends.backend_qt5.FigureCanvas(matplotlib.figure.Figure())
Out[1]: <matplotlib.backends.backend_qt5.FigureCanvasQT at 0x7f187ee094c8>

(regardless of the fact that this class shouldn't really be instantiated as noted by @jklymak above).

In fact the super-method is called in FigureCanvasQT.__init__ as

        super().__init__(figure=figure)

not posiitionally so it's unclear how you can get positional arguments to reach the patched super-init.

@hmaarrfk
Copy link
Contributor Author

Maybe because I'm on PySide2....

PyQt5 just passes the original __init__

The bug happens because the decorator only passes the keyword args and drops the args.

@anntzer
Copy link
Contributor

anntzer commented Aug 20, 2018

Ah, I see.
The fix looks correct, but then the test is absolutely not testing the correct thing, and I would just remove it (not really worth it, the correct thing is testing instantiation of FigureCanvasQT which as stated above is not really useful anyways, etc.).

@hmaarrfk hmaarrfk force-pushed the args__allow_super_init branch from c51e282 to 6fdf2b5 Compare August 20, 2018 23:20
@hmaarrfk
Copy link
Contributor Author

Ok i removed the tests.

@jklymak jklymak merged commit 1ec1a9c into matplotlib:master Aug 21, 2018
@jklymak
Copy link
Member

jklymak commented Aug 21, 2018

Thanks for the persistence @hmaarrfk ! Sorry this was a confusing one...

@hmaarrfk
Copy link
Contributor Author

Yeah it was. I'll try to use Qt5Agg, see how that works.

@QuLogic QuLogic added this to the v3.1 milestone Aug 21, 2018
@tacaswell tacaswell modified the milestones: v3.1, v2.2.4 Aug 21, 2018
@tacaswell
Copy link
Member

@meeseeksdev backport to v2.2.x

@tacaswell
Copy link
Member

@meeseeksdev backport to v3.0.x

@lumberbot-app
Copy link

lumberbot-app bot commented Aug 21, 2018

Owee, I'm MrMeeseeks, Look at me.

There seem to be a conflict, please backport manually. Here are approximate instructions:

  1. Checkout backport branch and update it.
$ git checkout v2.2.x
$ git pull
  1. Cherry pick the first parent branch of the this PR on top of the older branch:
$ git cherry-pick -m1 1ec1a9c4f9bd50bb5a078e7327024c718318bac6
  1. You will likely have some merge/cherry-pick conflict here, fix them and commit:
$ git commit -am 'Backport PR #11900: Allow args to pass through _allow_super_init'
  1. Push to a named branch :
git push YOURFORK v2.2.x:auto-backport-of-pr-11900-on-v2.2.x
  1. Create a PR against branch v2.2.x, I would have named this PR:

"Backport PR #11900 on branch v2.2.x"

And apply the correct labels and milestones.

Congratulation you did some good work ! Hopefully your backport PR will be tested by the continuous integration and merged soon!

If these instruction are inaccurate, feel free to suggest an improvement.

meeseeksmachine pushed a commit to meeseeksmachine/matplotlib that referenced this pull request Aug 21, 2018
jklymak added a commit that referenced this pull request Aug 21, 2018
@tacaswell tacaswell modified the milestones: v2.2.4, v3.0.0 Feb 17, 2020
@tacaswell
Copy link
Member

Looks like this did not get backported to 2.2.x but did make it into 3.0.0, remilestoned to match that.

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

Successfully merging this pull request may close these issues.

None yet

5 participants