Thanks to visit codestin.com
Credit goes to github.com

Skip to content

qt imports do not pick defaults properly #4912

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

Closed
wants to merge 1 commit into from

Conversation

jrevans
Copy link

@jrevans jrevans commented Aug 12, 2015

This fixes an error where PyQt4 would always be selected in the case where a Qt related file was imported, but not set as the current backend.

This will essentially be a bit more forgiving when a Qt related file (ie. a matplotlib file that uses 'qt_compat.py') is imported when the backend is set to something other than 'Qt5Agg' or 'Qt4Agg'.

This addresses an issue in #4897.

…where a Qt

related file was imported, but not set as the current backend.
@WeatherGod
Copy link
Member

We are going to need comments from those who use PySide to make sure all is kosher here.

I am a little weary about this change. We are, in effect, guessing the user's intent. Perhaps it makes sense to inspect sys.modules to see which Qt is already imported? Also, I don't really understand how this situation comes about. Is it a custom backend that is Qt-based? If so, perhaps it might make more sense to rethink the logic here to be more agnostic to matplotlib?

@tacaswell tacaswell added this to the next point release milestone Aug 12, 2015
@tacaswell
Copy link
Member

@WeatherGod I think you mean wary not weary 😉

I don't expect there to be a qt module imported when we enter qt_compat as it is responsible for doing said import.

I am ok with this change. Currently this is causing pain for any qt5 users who import qt_compat with out having the backend in rcparams set to qt5Agg and was working (by coincidence) for qt4 users (but they would still have to have the correct pyside vs pyqt api rcparam set). With this patch this will cause pain for users who have both pyqt5 and pyqt4/pyside installed, don't have a qt* backend set and want to use qt4 which seems like a smaller cross section.

I don't expect this to cause any problems for pyside users.

attn @mfitzp

@@ -47,8 +58,19 @@
# No ETS environment or incompatible so use rcParams.
if rcParams['backend'] == 'Qt5Agg':
Copy link
Member

Choose a reason for hiding this comment

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

By this point I think we are gaurenteed that QT_RC_MAJOR_VERSION is defined, we should switch on that instead of having the conditional import logic again.

@WeatherGod
Copy link
Member

What is the scenario where you are importing qt_compat directly, but with a backend set differently than what you want? I can only imagine two scenarios. 1) someone using qt_compat.py as a compatibility shim, completely ignoring matplotlib, or 2) someone who made a specialized backend that is Qt-based.

In both of these situations, it points to a limitation in the design of qt_compat.py, but also I would have expected other Qt modules to have been imported by then (but I admit that that isn't guaranteed). Some people have suggested that qt_compat.py get turned into its own stand-alone project, but that is obviously outside the scope here.

Sorry for rambling, I am just keeping in mind one of the tenets from PEP20: "in the face of ambiguity, resist the temptation to guess".

@tacaswell
Copy link
Member

The counter is that we are already guessing (by having the else blocks
default to qt4), this is just changing what are guess.

On Wed, Aug 12, 2015, 6:09 PM Benjamin Root [email protected]
wrote:

What is the scenario where you are importing qt_compat directly, but with
a backend set differently than what you want? I can only imagine two
scenarios. 1) someone using qt_compat.py as a compatibility shim,
completely ignoring matplotlib, or 2) someone who made a specialized
backend that is Qt-based.

In both of these situations, it points to a limitation in the design of
qt_compat.py, but also I would have expected other Qt modules to have been
imported by then (but I admit that that isn't guaranteed). Some people have
suggested that qt_compat.py get turned into its own stand-alone project,
but that is obviously outside the scope here.

Sorry for rambling, I am just keeping in mind one of the tenets from
PEP20: "in the face of ambiguity, resist the temptation to guess".


Reply to this email directly or view it on GitHub
#4912 (comment)
.

@WeatherGod
Copy link
Member

True enough. How about putting in a warning?
On Aug 12, 2015 6:25 PM, "Thomas A Caswell" [email protected]
wrote:

The counter is that we are already guessing (by having the else blocks
default to qt4), this is just changing what are guess.

On Wed, Aug 12, 2015, 6:09 PM Benjamin Root [email protected]
wrote:

What is the scenario where you are importing qt_compat directly, but with
a backend set differently than what you want? I can only imagine two
scenarios. 1) someone using qt_compat.py as a compatibility shim,
completely ignoring matplotlib, or 2) someone who made a specialized
backend that is Qt-based.

In both of these situations, it points to a limitation in the design of
qt_compat.py, but also I would have expected other Qt modules to have
been
imported by then (but I admit that that isn't guaranteed). Some people
have
suggested that qt_compat.py get turned into its own stand-alone project,
but that is obviously outside the scope here.

Sorry for rambling, I am just keeping in mind one of the tenets from
PEP20: "in the face of ambiguity, resist the temptation to guess".


Reply to this email directly or view it on GitHub
<
https://github.com/matplotlib/matplotlib/pull/4912#issuecomment-130462103>
.


Reply to this email directly or view it on GitHub
#4912 (comment)
.

@tacaswell
Copy link
Member

+1 on adding a warning

On Thu, Aug 13, 2015, 12:21 AM Benjamin Root [email protected]
wrote:

True enough. How about putting in a warning?
On Aug 12, 2015 6:25 PM, "Thomas A Caswell" [email protected]
wrote:

The counter is that we are already guessing (by having the else blocks
default to qt4), this is just changing what are guess.

On Wed, Aug 12, 2015, 6:09 PM Benjamin Root [email protected]
wrote:

What is the scenario where you are importing qt_compat directly, but
with
a backend set differently than what you want? I can only imagine two
scenarios. 1) someone using qt_compat.py as a compatibility shim,
completely ignoring matplotlib, or 2) someone who made a specialized
backend that is Qt-based.

In both of these situations, it points to a limitation in the design of
qt_compat.py, but also I would have expected other Qt modules to have
been
imported by then (but I admit that that isn't guaranteed). Some people
have
suggested that qt_compat.py get turned into its own stand-alone
project,
but that is obviously outside the scope here.

Sorry for rambling, I am just keeping in mind one of the tenets from
PEP20: "in the face of ambiguity, resist the temptation to guess".


Reply to this email directly or view it on GitHub
<

https://github.com/matplotlib/matplotlib/pull/4912#issuecomment-130462103>

.


Reply to this email directly or view it on GitHub
<
https://github.com/matplotlib/matplotlib/pull/4912#issuecomment-130465573>
.


Reply to this email directly or view it on GitHub
#4912 (comment)
.

@jrevans
Copy link
Author

jrevans commented Aug 17, 2015

I ran into this scenario with two separate cases, the first is in implementing a pure-Qt backend (no Agg!) and the second (more important to us) is more complicated...

We have a module that when imported by our users will initialize matplotlib to recognize our data types. If we are operating in a headless (no display) environment, then we also set the backend to Agg (we have users that will run scripts both interactively and in batches and they requested this feature in our setup and it makes our nightly tests happier). Additionally we have some plot widgets that derive from the Qt matplotlib FigureCanvas. We also generate our documentation by explicitly introspecting the user API (this allows us to make sure the entire API is documented). The simple process of introspection imports both of these files. Importing one sets the backend to Agg, the other imports a widget (which isn't used), but in doing so it causes 'qt_compat' to be imported, which wants to ultimately import a non-existant PyQt4.

@tacaswell
Copy link
Member

I am convinced this should be merged once the comments are addressed.

@mfitzp
Copy link
Member

mfitzp commented Aug 19, 2015

Apologies for the slow response (in the last stages of writing up my thesis) but I agree with the merge once the duplicate logic is removed.

I think the move towards Qt5 by default is sensible since that is now the base API.

The following block (not touched by this commit) means that the environment variable is only used when the major version number of the API from the environment matches that of the rcParam. In practise this means the environment variable only works to switch Qt4 versions (since Qt4 is the only one with >1 API). Otherwise it will silently be ignored:

if (QT_API_ENV is not None):
    try:
        QT_ENV_MAJOR_VERSION = ETS[QT_API_ENV][1]
    except KeyError:
        raise RuntimeError(
            ('Unrecognized environment variable %r, valid values are:'
             ' %r, %r or %r' % (QT_API_ENV, 'pyqt', 'pyside', 'pyqt5')))
    if QT_ENV_MAJOR_VERSION == QT_RC_MAJOR_VERSION:
        # Only if backend and env qt major version are
        # compatible use the env variable.
        QT_API = ETS[QT_API_ENV][0]           

I suggest we add another warning at the bottom of this?

@tacaswell
Copy link
Member

Marked as not a blocker as this as I am comfortable putting out RC1 without this fixed but it should done before the final release.

@tacaswell
Copy link
Member

@jrevans Ping, any update on this?

@JGoutin
Copy link
Contributor

JGoutin commented Sep 17, 2015

Just a little change proposition from the jrevans commit :
Check what PyQt version is actually used rather than try to force the use of PyQt5

I have PyQt5 and PyQt4 installed at the same time, and both are used by different applications with matplotlib. With this change, all applications should work correctly if rcParams is not set.

Line 31:

else:
    # A different backend was specified, but we still got here because a Qt
    # related file was imported. This is allowed, so lets try and guess
    # what we should be using.
    if "PyQt5" in sys.modules:
        # PyQt5 is actually used.
        QT_RC_MAJOR_VERSION = 5
    else:
        # This is a fallback
        QT_RC_MAJOR_VERSION = 4

Line 63:

else:
    # A different backend was specified, but we still got here because a Qt
    # related file was imported. This is allowed, so lets try and guess
    # what we should be using.
    if "PyQt5" in sys.modules:
        # PyQt5 is actually used.
        QT_API = rcParams['backend.qt5']
    else:
        # This is a fallback
        QT_API = rcParams['backend.qt4']

@tacaswell
Copy link
Member

@JGoutin Can you put in a PR based on @jrevans branch with those changes on top as an additional commit?

@JGoutin
Copy link
Contributor

JGoutin commented Sep 17, 2015

It's done. Here is the commit : jrevans@2a23a63

I don't find how adding it on the actual pull request.

@tacaswell
Copy link
Member

Please make a new pr, it is the easiest way.

On Thu, Sep 17, 2015, 10:06 JGoutin [email protected] wrote:

It's done. Here is the commit : jrevans/matplotlib@2a23a63
jrevans@2a23a63

I don't show how adding it at the actual pull request.


Reply to this email directly or view it on GitHub
#4912 (comment)
.

@JGoutin
Copy link
Contributor

JGoutin commented Sep 17, 2015

The pr : https://github.com/JGoutin/matplotlib

@tacaswell
Copy link
Member

@JGoutin Which branch from your fork should I be looking at?

@JGoutin
Copy link
Contributor

JGoutin commented Sep 24, 2015

master branch

@tacaswell
Copy link
Member

Can you move that to a feature branch and open a pull request against mpl
master?

On Thu, Sep 24, 2015, 02:37 JGoutin [email protected] wrote:

master branch


Reply to this email directly or view it on GitHub
#4912 (comment)
.

@JGoutin JGoutin mentioned this pull request Sep 24, 2015
@JGoutin
Copy link
Contributor

JGoutin commented Sep 24, 2015

You can find the pull request here : #5134

@tacaswell
Copy link
Member

Replaced by #5134

@tacaswell tacaswell closed this Sep 26, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants