Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

FIX: pyplot auto-backend detection case-sensitivity fixup#29721

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Conversation

jayaddison
Copy link
Contributor

@jayaddisonjayaddison commentedMar 9, 2025
edited
Loading

PR summary

There seems to be a case-sensitivity bug in thematplotlib.pyplot module code that decides whether to configure backend autodetection, and I think that this is the cause of the bug reported in#29713.

The bug means that a current interactive environment value ofTkAgg is not detected as one of the possible values from a set that includes the stringtkagg -- and so an auto-backend isnot configured, as it would have been previously in v3.8.3 of this library.

A minimal repro example is provided below, for use in a container environment with no graphical/GUI environment available:

>>>importmatplotlib.pyplot>>>matplotlib.pyplot.new_figure_manager()Traceback (mostrecentcalllast):File"<python-input-1>",line1,in<module>matplotlib.pyplot.new_figure_manager()~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^File"/usr/lib/python3/dist-packages/matplotlib/pyplot.py",line551,innew_figure_manager_warn_if_gui_out_of_main_thread()~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^File"/usr/lib/python3/dist-packages/matplotlib/pyplot.py",line528,in_warn_if_gui_out_of_main_threadcanvas_class=cast(type[FigureCanvasBase],_get_backend_mod().FigureCanvas)~~~~~~~~~~~~~~~~^^File"/usr/lib/python3/dist-packages/matplotlib/pyplot.py",line369,in_get_backend_modswitch_backend(rcParams._get("backend"))~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^File"/usr/lib/python3/dist-packages/matplotlib/pyplot.py",line433,inswitch_backendraiseImportError(    ...<2lines>...newbackend,required_framework,current_framework))ImportError:Cannotloadbackend'TkAgg'whichrequiresthe'tk'interactiveframework,as'headless'iscurrentlyrunning

PR checklist

Closes#29713.

@jayaddison
Copy link
ContributorAuthor

Thinking about how to add test coverage here: I think that modifying/extending thetest_backend_fallback_headless andtest_backend_fallback_headful test cases might be a reasonable way to demonstrate the problem and/or fix:

@pytest.mark.skipif(sys.platform!="linux",reason="Linux only")
deftest_backend_fallback_headless(tmp_path):
env= {**os.environ,
"DISPLAY":"","WAYLAND_DISPLAY":"",
"MPLBACKEND":"","MPLCONFIGDIR":str(tmp_path)}
withpytest.raises(subprocess.CalledProcessError):
subprocess_run_for_testing(
[sys.executable,"-c",
"import matplotlib;"
"matplotlib.use('tkagg');"
"import matplotlib.pyplot;"
"matplotlib.pyplot.plot(42);"
],
env=env,check=True,stderr=subprocess.DEVNULL)
@pytest.mark.skipif(
sys.platform=="linux"andnot_c_internal_utils.xdisplay_is_valid(),
reason="headless")
deftest_backend_fallback_headful(tmp_path):
ifparse_version(pytest.__version__)>=parse_version('8.2.0'):
pytest_kwargs=dict(exc_type=ImportError)
else:
pytest_kwargs= {}
pytest.importorskip("tkinter",**pytest_kwargs)
env= {**os.environ,"MPLBACKEND":"","MPLCONFIGDIR":str(tmp_path)}
backend=subprocess_run_for_testing(
[sys.executable,"-c",
"import matplotlib as mpl; "
"sentinel = mpl.rcsetup._auto_backend_sentinel; "
# Check that access on another instance does not resolve the sentinel.
"assert mpl.RcParams({'backend': sentinel})['backend'] == sentinel; "
"assert mpl.rcParams._get('backend') == sentinel; "
"assert mpl.get_backend(auto_select=False) is None; "
"import matplotlib.pyplot; "
"print(matplotlib.get_backend())"],
env=env,text=True,check=True,capture_output=True).stdout
# The actual backend will depend on what's installed, but at least tkagg is
# present.
assertbackend.strip().lower()!="agg"

@jayaddison
Copy link
ContributorAuthor

It's possible to re-order some of theimport andget_backend code lines intest_backend_fallback_headful to get the test to fail without this fix and pass with it in place -- but I'm not completely certain what the expected logic should be, so I'll open this PR for review/feedback.

@jayaddisonjayaddison marked this pull request as ready for reviewMarch 10, 2025 11:29
Copy link
Member

@timhoffmtimhoffm left a comment

Choose a reason for hiding this comment

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

Note: I was wondering whether this is the right case to handle the case. Alternatives could be

  • validate_backend() coercing to lower-case. See
    defvalidate_backend(s):

    While we could do this, the BackendRegistry generally accepts arbitrary casing and coerces internally. Therefore, it may be slightly more consistent to keep the name as is in rcParams, so that the user always sees the name as given: They may usematplotlib.use("TkAgg") and set "TkAgg" in theirmatplotlibrc file. Then it's slightly awkward to return the lower-case variant forrcParams["backend_fallback"] - though one could still argue that eager normalization is still the way to go. I have no strong opinion here.
  • Push everything down to the BackendRegistry. While this would be nice in principle, we have a very specific request here: "Is the given backend name an available interactive backend, but not webagg or nbagg" and that's not easy to express as a high-level BackendRegistry API that could support arbitrary casing.

I therefore think the present solution is right.

@jayaddison
Copy link
ContributorAuthor

@nileshpatra can you confirm that this fixup (f45707d) resolves the problems you encountered during unit tests formatplotlib-dependent packages? Ithink it should do, but it would be good to make sure.

@ianthomas23
Copy link
Member

Thanks@jayaddison, this is a bug that I introduced and the fix here looks good to me. I think you are looking in the right place for a test, but it might be a little awkward due to the subprocess approach.

@jayaddison
Copy link
ContributorAuthor

Thank you@ianthomas23@timhoffm for the code reviews. Also, I think I've figured out what could be some viable test coverage:

Given thattest_backend_fallback_headless tests a negative/failure case (the ability to open atkagg output when headless mode is active is expected to cause a failure), I think that test coverage for this change should add a second headless test that presents a successful rendering case. And to do that, it should be possible I think to importmatplotlib.pyplot followed by creating a plot directly (nomatplotlib.use / other imports required).

I've tested that theory in a shell with and without the fix in place and it seems to behave as expected; I'll try adding it to the test suite in a few moments.

@jayaddison

This comment was marked as outdated.

@jayaddison

This comment was marked as resolved.

@jayaddisonjayaddison marked this pull request as draftMarch 11, 2025 13:08
@jayaddison

This comment was marked as outdated.

@jayaddison

This comment was marked as outdated.

@jayaddison

This comment was marked as resolved.

@jayaddisonjayaddison marked this pull request as ready for reviewMarch 12, 2025 19:35
@tacaswelltacaswell added this to thev3.10.2 milestoneMar 12, 2025
@tacaswell
Copy link
Member

Can we squash this to one or two commits?

jayaddison reacted with thumbs up emoji

Co-authored-by: Ian Thomas <ianthomas23@gmail.com>
@jayaddisonjayaddisonforce-pushed theissue-29713/auto-backend-case-sensitivity-fixup branch fromb07d9c6 to2ed08c1CompareMarch 12, 2025 21:51
@nileshpatra
Copy link

nileshpatra commentedMar 13, 2025 via email

Now that all comments are addressed, could this be merged?
On 13 March 2025 2:18:25 am IST, Thomas A Caswell ***@***.***> wrote:tacaswell left a comment (matplotlib/matplotlib#29721)Can we squash this to one or two commits?--Reply to this email directly or view it on GitHub:#29721 (comment)You are receiving this because you were mentioned.Message ID: ***@***.***>
Best,Nilesh

Copy link
Member

@ianthomas23ianthomas23 left a comment

Choose a reason for hiding this comment

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

Thanks@jayaddison. CI failure is unrelated.

@ianthomas23ianthomas23 merged commit309d380 intomatplotlib:mainMar 14, 2025
36 of 38 checks passed
@jayaddison
Copy link
ContributorAuthor

Thank you@ianthomas23!

@jayaddisonjayaddison deleted the issue-29713/auto-backend-case-sensitivity-fixup branchMarch 14, 2025 09:31
dstansby added a commit that referenced this pull requestMar 21, 2025
…721-on-v3.10.xBackport PR#29721 on branch v3.10.x (FIX: pyplot auto-backend detection case-sensitivity fixup)
@ksundenksunden mentioned this pull requestMay 9, 2025
5 tasks
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@ianthomas23ianthomas23ianthomas23 approved these changes

@timhoffmtimhoffmtimhoffm approved these changes

Assignees
No one assigned
Projects
None yet
Milestone
v3.10.3
Development

Successfully merging this pull request may close these issues.

[Bug]: Matplotlib selects TkAgg backend on LXC containers
5 participants
@jayaddison@ianthomas23@tacaswell@nileshpatra@timhoffm

[8]ページ先頭

©2009-2025 Movatter.jp