Skip to content

Resolve backend in rcParams.__getitem__("backend"). #11896

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 12 commits into from
Aug 28, 2018

Conversation

anntzer
Copy link
Contributor

@anntzer anntzer commented Aug 20, 2018

... to avoid leaking the non-string sentinel.

Changes to backends/__init__ and _backend_selection() were necessary
to avoid import-time cycles.

The fallback order in backend_fallback slightly changed in that the
FooCairo backends now fallback to WxAgg instead of Wx when a wx event
loop is active, but I wouldn't worry too much about it anyways given
that the Wx backend is deprecated and the correct fallback would be
WxCairo to start with.

attn @tacaswell, xref #11844.

PR Summary

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

@anntzer anntzer force-pushed the auto-backend-resolution branch from 7ca6805 to 4b2be5b Compare August 20, 2018 07:45
@anntzer
Copy link
Contributor Author

anntzer commented Aug 20, 2018

Test failure seems spurious, and I can't repro it locally.

@anntzer
Copy link
Contributor Author

anntzer commented Aug 20, 2018

@tacaswell Should be fixed now.
TLDR: now pyplot had already been imported when pytest_configure is being called (due to the resolution system), so that call to use() needed force=True.

@anntzer anntzer force-pushed the auto-backend-resolution branch 3 times, most recently from f639964 to aa25a25 Compare August 21, 2018 07:46
... to avoid leaking the non-string sentinel.

Changes to `backends/__init__` and `_backend_selection()` were necessary
to avoid import-time cycles.

The fallback order in `backend_fallback` slightly changed in that the
FooCairo backends now fallback to WxAgg instead of Wx when a wx event
loop is active, but I wouldn't worry too much about it anyways given
that the Wx backend is deprecated and the correct fallback would be
WxCairo to start with.
@anntzer anntzer force-pushed the auto-backend-resolution branch from aa25a25 to 036d788 Compare August 21, 2018 08:14
@anntzer
Copy link
Contributor Author

anntzer commented Aug 21, 2018

... or perhaps not completely fixed :/

@anntzer
Copy link
Contributor Author

anntzer commented Aug 21, 2018

Well, now I'm stuck with not being able to repro the failure locally (again) and rcParams["backend"] not matching the actual backend in the CI (per print-debugging), as feared in the API discussion of the original PR :/

@tacaswell
Copy link
Member

Let see if that fixes it. I think that some of these fixes are overlapping, but defense in depth seems like a good call here.

Turns out we were keeping state in three places we were keeping the backend state around (rcParams, rcParamsDefault, and rcParamsOrig).

This passes locally.

@tacaswell
Copy link
Member

Getting closer to the problem, it looks like the rcparam tests are re-setting back to the auto sentinal which is then resolving to qt5agg and never getting reset back to 'agg'.

@tacaswell
Copy link
Member

This behaves correctly in IPython if you let it do the 'auto' thing

16:16 $ ipython
Python 3.8.0a0 (heads/master:28853a249b, Aug 22 2018, 13:47:23) 
Type 'copyright', 'credits' or 'license' for more information
IPython 7.0.0.dev -- An enhanced Interactive Python. Type '?' for help.

In [1]: %matplotlib                                                                                                                                                                                                                                           
Using matplotlib backend: Qt5Agg

In [2]:      

and if you ask for a specific backend

16:17 $ ipython
Python 3.8.0a0 (heads/master:28853a249b, Aug 22 2018, 13:47:23) 
Type 'copyright', 'credits' or 'license' for more information
IPython 7.0.0.dev -- An enhanced Interactive Python. Type '?' for help.

In [1]: %matplotlib tk                                                                                                                                                                                                                                        

In [2]: import matplotlib                                                                                                                                                                                                                                     

In [3]: matplotlib.get_backend()                                                                                                                                                                                                                              
Out[3]: 'TkAgg'

In [4]:  

but I am now having issues with the input hooks.....

@tacaswell
Copy link
Member

ok, the inputhook issues are either an IPython master-branch or pt 2 issue (down-grading both fixed it).

@anntzer
Copy link
Contributor Author

anntzer commented Aug 23, 2018

The whole thing turned out to be more complicated than expected (hehe), but the additional fixes by @tacaswell look good, so I'm "approving" them (well, can't do this on my own PR). Of course that should need at least one external reviewer...

@tacaswell
Copy link
Member

The complexity we hit is what @timhoffm (correctly) predicted would be a problem, however I think we have no choice but to absorb this complexity as we can not break compatibility with older versions of IPython.

@anntzer
Copy link
Contributor Author

anntzer commented Aug 24, 2018

Now that I think of it I think the previous approach (resolve when writing to the rcParams, not when reading from it) was still simpler (even if using the sentinel object rather than a list, because that object essentially never exists in the rcParams, this being the source of the issues). After all the tests did pass on the old PR IIRC. Of course there were the other issue pointed out by @timhoffm re: whether "active" rcParams would be a good API.

In any case things appear to work as they are (thanks for figuring it out).

Copy link
Member

@efiring efiring left a comment

Choose a reason for hiding this comment

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

Seems OK.
In addition to considering the minor comments, you might want to use this PR to update the list of valid backends in matplotlibrc.template while you are in the neighborhood.

if k not in STYLE_BLACKLIST})
rcParams.update({k: rcParamsOrig[k] for k in rcParamsOrig
if k not in STYLE_BLACKLIST and k != 'backend'})
rcParams['backend'] = dict.__getitem__(rcParamsOrig, 'backend')
Copy link
Member

Choose a reason for hiding this comment

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

I think this is contrary to what the docstring says; if so, the docstring needs an update, and either there or in a comment it would be good to say why this exception is being made.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@tacaswell you made this change I think?

Copy link
Member

Choose a reason for hiding this comment

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

I think this block can be dropped.

@@ -36,7 +36,7 @@ def setup():
"Could not set locale to English/United States. "
"Some date-related tests may fail.")

mpl.use('Agg', warn=False) # use Agg backend for these tests
mpl.use('Agg', force=True, warn=False) # use Agg backend for these tests
Copy link
Member

Choose a reason for hiding this comment

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

The docstring for mpl.use says the use of plt.switch_backend is preferred over force=True; so why is the discouraged form being used in the tests?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The docstring should be updated (really there is no (actual) difference between use and switch_backend anymore after this PR (other than whether we silently or loudly fail or emit a warning) so I'd rather not point to switch_backend, but I know @tacaswell did add some pointers to it at some point so I'll let him decide.

Copy link
Member

Choose a reason for hiding this comment

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

Removing that note from the docstring is something on my to-do list that I did not get to.

print(dict.__getitem__(plt.rcParams, "backend"))
print(plt.rcParams["backend"])
print(plt._backend_mod)
print(fig.canvas)
Copy link
Member

Choose a reason for hiding this comment

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

We don't usually include print calls in the tests, do we? Are these left over from debugging, or are they intentional? If the latter, given that they are unusual, do they merit a comment?

Copy link
Contributor Author

@anntzer anntzer Aug 26, 2018

Choose a reason for hiding this comment

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

that was for debugging the failure on travis, removing it (rebased it out).

This is to ensure that when IPython get the backend in
IPython.core.pylabtools.find_gui_and_backend the backend resolution is
triggered.
In either case (resolved or not) pass the backend value through.  This
maintains the behavior prior to changing the type of rcParamsOrig to RcParams.
If the context block triggers the auto-resolution of the backend
keep than information around.
This is to prevent the auto resolution of the backend from being
reverted.
@anntzer anntzer force-pushed the auto-backend-resolution branch from 571fd0b to aaab933 Compare August 26, 2018 21:00
@tacaswell tacaswell force-pushed the auto-backend-resolution branch from 7bd83e8 to ad91933 Compare August 27, 2018 23:20
@tacaswell
Copy link
Member

@anntzer I force pushed an ammended last commit.

@tacaswell
Copy link
Member

I plan to merge this when CI passes.

@tacaswell tacaswell merged commit 32ad86f into matplotlib:master Aug 28, 2018
meeseeksmachine pushed a commit to meeseeksmachine/matplotlib that referenced this pull request Aug 28, 2018
tacaswell added a commit that referenced this pull request Aug 28, 2018
@anntzer anntzer deleted the auto-backend-resolution branch August 28, 2018 06:17
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.

3 participants