Download lib/python3.12/site-packages/matplotlib/tests/test_backend_qt.py from parallel-reasoner/env-full: direct link, hf CLI and curl.
- Browser
- Download file 13 kB
-
https://huggingface.co/parallel-reasoner/env-full/resolve/a2585bd5ca1cf640fa361bd20177ded829caaa8d/lib/python3.12/site-packages/matplotlib/tests/test_backend_qt.py
- Command line
-
hf download hf://parallel-reasoner/env-full@a2585bd5ca1cf640fa361bd20177ded829caaa8d/lib/python3.12/site-packages/matplotlib/tests/test_backend_qt.py
-
curl -L -o test_backend_qt.py https://huggingface.co/parallel-reasoner/env-full/resolve/a2585bd5ca1cf640fa361bd20177ded829caaa8d/lib/python3.12/site-packages/matplotlib/tests/test_backend_qt.py
13 kB
| import copy | |
| import importlib | |
| import os | |
| import signal | |
| import sys | |
| from datetime import date, datetime | |
| from unittest import mock | |
| import pytest | |
| import matplotlib | |
| from matplotlib import pyplot as plt | |
| from matplotlib._pylab_helpers import Gcf | |
| from matplotlib import _c_internal_utils | |
| try: | |
| from matplotlib.backends.qt_compat import QtGui # type: ignore[attr-defined] # noqa: E501, F401 | |
| from matplotlib.backends.qt_compat import QtWidgets # type: ignore[attr-defined] | |
| from matplotlib.backends.qt_editor import _formlayout | |
| except ImportError: | |
| pytestmark = pytest.mark.skip('No usable Qt bindings') | |
| _test_timeout = 60 # A reasonably safe value for slower architectures. | |
| def qt_core(request): | |
| from matplotlib.backends.qt_compat import QtCore | |
| return QtCore | |
| def test_fig_close(): | |
| # save the state of Gcf.figs | |
| init_figs = copy.copy(Gcf.figs) | |
| # make a figure using pyplot interface | |
| fig = plt.figure() | |
| # simulate user clicking the close button by reaching in | |
| # and calling close on the underlying Qt object | |
| fig.canvas.manager.window.close() | |
| # assert that we have removed the reference to the FigureManager | |
| # that got added by plt.figure() | |
| assert init_figs == Gcf.figs | |
| def test_correct_key(backend, qt_core, qt_key, qt_mods, answer, monkeypatch): | |
| """ | |
| Make a figure. | |
| Send a key_press_event event (using non-public, qtX backend specific api). | |
| Catch the event. | |
| Assert sent and caught keys are the same. | |
| """ | |
| from matplotlib.backends.qt_compat import _to_int, QtCore | |
| if sys.platform == "darwin" and answer is not None: | |
| answer = answer.replace("ctrl", "cmd") | |
| answer = answer.replace("control", "cmd") | |
| answer = answer.replace("meta", "ctrl") | |
| result = None | |
| qt_mod = QtCore.Qt.KeyboardModifier.NoModifier | |
| for mod in qt_mods: | |
| qt_mod |= getattr(QtCore.Qt.KeyboardModifier, mod) | |
| class _Event: | |
| def isAutoRepeat(self): return False | |
| def key(self): return _to_int(getattr(QtCore.Qt.Key, qt_key)) | |
| monkeypatch.setattr(QtWidgets.QApplication, "keyboardModifiers", | |
| lambda self: qt_mod) | |
| def on_key_press(event): | |
| nonlocal result | |
| result = event.key | |
| qt_canvas = plt.figure().canvas | |
| qt_canvas.mpl_connect('key_press_event', on_key_press) | |
| qt_canvas.keyPressEvent(_Event()) | |
| assert result == answer | |
| def test_device_pixel_ratio_change(): | |
| """ | |
| Make sure that if the pixel ratio changes, the figure dpi changes but the | |
| widget remains the same logical size. | |
| """ | |
| prop = 'matplotlib.backends.backend_qt.FigureCanvasQT.devicePixelRatioF' | |
| with mock.patch(prop) as p: | |
| p.return_value = 3 | |
| fig = plt.figure(figsize=(5, 2), dpi=120) | |
| qt_canvas = fig.canvas | |
| qt_canvas.show() | |
| def set_device_pixel_ratio(ratio): | |
| p.return_value = ratio | |
| # The value here doesn't matter, as we can't mock the C++ QScreen | |
| # object, but can override the functional wrapper around it. | |
| # Emitting this event is simply to trigger the DPI change handler | |
| # in Matplotlib in the same manner that it would occur normally. | |
| screen.logicalDotsPerInchChanged.emit(96) | |
| qt_canvas.draw() | |
| qt_canvas.flush_events() | |
| # Make sure the mocking worked | |
| assert qt_canvas.device_pixel_ratio == ratio | |
| qt_canvas.manager.show() | |
| size = qt_canvas.size() | |
| screen = qt_canvas.window().windowHandle().screen() | |
| set_device_pixel_ratio(3) | |
| # The DPI and the renderer width/height change | |
| assert fig.dpi == 360 | |
| assert qt_canvas.renderer.width == 1800 | |
| assert qt_canvas.renderer.height == 720 | |
| # The actual widget size and figure logical size don't change. | |
| assert size.width() == 600 | |
| assert size.height() == 240 | |
| assert qt_canvas.get_width_height() == (600, 240) | |
| assert (fig.get_size_inches() == (5, 2)).all() | |
| set_device_pixel_ratio(2) | |
| # The DPI and the renderer width/height change | |
| assert fig.dpi == 240 | |
| assert qt_canvas.renderer.width == 1200 | |
| assert qt_canvas.renderer.height == 480 | |
| # The actual widget size and figure logical size don't change. | |
| assert size.width() == 600 | |
| assert size.height() == 240 | |
| assert qt_canvas.get_width_height() == (600, 240) | |
| assert (fig.get_size_inches() == (5, 2)).all() | |
| set_device_pixel_ratio(1.5) | |
| # The DPI and the renderer width/height change | |
| assert fig.dpi == 180 | |
| assert qt_canvas.renderer.width == 900 | |
| assert qt_canvas.renderer.height == 360 | |
| # The actual widget size and figure logical size don't change. | |
| assert size.width() == 600 | |
| assert size.height() == 240 | |
| assert qt_canvas.get_width_height() == (600, 240) | |
| assert (fig.get_size_inches() == (5, 2)).all() | |
| def test_subplottool(): | |
| fig, ax = plt.subplots() | |
| with mock.patch("matplotlib.backends.qt_compat._exec", lambda obj: None): | |
| fig.canvas.manager.toolbar.configure_subplots() | |
| def test_figureoptions(): | |
| fig, ax = plt.subplots() | |
| ax.plot([1, 2]) | |
| ax.imshow([[1]]) | |
| ax.scatter(range(3), range(3), c=range(3)) | |
| with mock.patch("matplotlib.backends.qt_compat._exec", lambda obj: None): | |
| fig.canvas.manager.toolbar.edit_parameters() | |
| def test_save_figure_return(): | |
| fig, ax = plt.subplots() | |
| ax.imshow([[1]]) | |
| prop = "matplotlib.backends.qt_compat.QtWidgets.QFileDialog.getSaveFileName" | |
| with mock.patch(prop, return_value=("foobar.png", None)): | |
| fname = fig.canvas.manager.toolbar.save_figure() | |
| os.remove("foobar.png") | |
| assert fname == "foobar.png" | |
| with mock.patch(prop, return_value=(None, None)): | |
| fname = fig.canvas.manager.toolbar.save_figure() | |
| assert fname is None | |
| def test_figureoptions_with_datetime_axes(): | |
| fig, ax = plt.subplots() | |
| xydata = [ | |
| datetime(year=2021, month=1, day=1), | |
| datetime(year=2021, month=2, day=1) | |
| ] | |
| ax.plot(xydata, xydata) | |
| with mock.patch("matplotlib.backends.qt_compat._exec", lambda obj: None): | |
| fig.canvas.manager.toolbar.edit_parameters() | |
| def test_double_resize(): | |
| # Check that resizing a figure twice keeps the same window size | |
| fig, ax = plt.subplots() | |
| fig.canvas.draw() | |
| window = fig.canvas.manager.window | |
| w, h = 3, 2 | |
| fig.set_size_inches(w, h) | |
| assert fig.canvas.width() == w * matplotlib.rcParams['figure.dpi'] | |
| assert fig.canvas.height() == h * matplotlib.rcParams['figure.dpi'] | |
| old_width = window.width() | |
| old_height = window.height() | |
| fig.set_size_inches(w, h) | |
| assert window.width() == old_width | |
| assert window.height() == old_height | |
| def test_canvas_reinit(): | |
| from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg | |
| called = False | |
| def crashing_callback(fig, stale): | |
| nonlocal called | |
| fig.canvas.draw_idle() | |
| called = True | |
| fig, ax = plt.subplots() | |
| fig.stale_callback = crashing_callback | |
| # this should not raise | |
| canvas = FigureCanvasQTAgg(fig) | |
| fig.stale = True | |
| assert called | |
| def test_form_widget_get_with_datetime_and_date_fields(): | |
| from matplotlib.backends.backend_qt import _create_qApp | |
| _create_qApp() | |
| form = [ | |
| ("Datetime field", datetime(year=2021, month=3, day=11)), | |
| ("Date field", date(year=2021, month=3, day=11)) | |
| ] | |
| widget = _formlayout.FormWidget(form) | |
| widget.setup() | |
| values = widget.get() | |
| assert values == [ | |
| datetime(year=2021, month=3, day=11), | |
| date(year=2021, month=3, day=11) | |
| ] | |
| def _get_testable_qt_backends(): | |
| envs = [] | |
| for deps, env in [ | |
| ([qt_api], {"MPLBACKEND": "qtagg", "QT_API": qt_api}) | |
| for qt_api in ["PyQt6", "PySide6", "PyQt5", "PySide2"] | |
| ]: | |
| reason = None | |
| missing = [dep for dep in deps if not importlib.util.find_spec(dep)] | |
| if (sys.platform == "linux" and | |
| not _c_internal_utils.display_is_valid()): | |
| reason = "$DISPLAY and $WAYLAND_DISPLAY are unset" | |
| elif missing: | |
| reason = "{} cannot be imported".format(", ".join(missing)) | |
| elif env["MPLBACKEND"] == 'macosx' and os.environ.get('TF_BUILD'): | |
| reason = "macosx backend fails on Azure" | |
| marks = [] | |
| if reason: | |
| marks.append(pytest.mark.skip( | |
| reason=f"Skipping {env} because {reason}")) | |
| envs.append(pytest.param(env, marks=marks, id=str(env))) | |
| return envs | |
| def test_fig_sigint_override(qt_core): | |
| from matplotlib.backends.backend_qt5 import _BackendQT5 | |
| # Create a figure | |
| plt.figure() | |
| # Variable to access the handler from the inside of the event loop | |
| event_loop_handler = None | |
| # Callback to fire during event loop: save SIGINT handler, then exit | |
| def fire_signal_and_quit(): | |
| # Save event loop signal | |
| nonlocal event_loop_handler | |
| event_loop_handler = signal.getsignal(signal.SIGINT) | |
| # Request event loop exit | |
| qt_core.QCoreApplication.exit() | |
| # Timer to exit event loop | |
| qt_core.QTimer.singleShot(0, fire_signal_and_quit) | |
| # Save original SIGINT handler | |
| original_handler = signal.getsignal(signal.SIGINT) | |
| # Use our own SIGINT handler to be 100% sure this is working | |
| def custom_handler(signum, frame): | |
| pass | |
| signal.signal(signal.SIGINT, custom_handler) | |
| try: | |
| # mainloop() sets SIGINT, starts Qt event loop (which triggers timer | |
| # and exits) and then mainloop() resets SIGINT | |
| matplotlib.backends.backend_qt._BackendQT.mainloop() | |
| # Assert: signal handler during loop execution is changed | |
| # (can't test equality with func) | |
| assert event_loop_handler != custom_handler | |
| # Assert: current signal handler is the same as the one we set before | |
| assert signal.getsignal(signal.SIGINT) == custom_handler | |
| # Repeat again to test that SIG_DFL and SIG_IGN will not be overridden | |
| for custom_handler in (signal.SIG_DFL, signal.SIG_IGN): | |
| qt_core.QTimer.singleShot(0, fire_signal_and_quit) | |
| signal.signal(signal.SIGINT, custom_handler) | |
| _BackendQT5.mainloop() | |
| assert event_loop_handler == custom_handler | |
| assert signal.getsignal(signal.SIGINT) == custom_handler | |
| finally: | |
| # Reset SIGINT handler to what it was before the test | |
| signal.signal(signal.SIGINT, original_handler) | |
| def test_ipython(): | |
| from matplotlib.testing import ipython_in_subprocess | |
| ipython_in_subprocess("qt", {(8, 24): "qtagg", (8, 15): "QtAgg", (7, 0): "Qt5Agg"}) | |