Spaces:
Running
Running
| import pytest | |
| import sys | |
| import matplotlib | |
| from matplotlib import _api | |
| def pytest_configure(config): | |
| # config is initialized here rather than in pytest.ini so that `pytest | |
| # --pyargs matplotlib` (which would not find pytest.ini) works. The only | |
| # entries in pytest.ini set minversion (which is checked earlier), | |
| # testpaths/python_files, as they are required to properly find the tests | |
| for key, value in [ | |
| ("markers", "flaky: (Provided by pytest-rerunfailures.)"), | |
| ("markers", "timeout: (Provided by pytest-timeout.)"), | |
| ("markers", "backend: Set alternate Matplotlib backend temporarily."), | |
| ("markers", "baseline_images: Compare output against references."), | |
| ("markers", "pytz: Tests that require pytz to be installed."), | |
| ("filterwarnings", "error"), | |
| ("filterwarnings", | |
| "ignore:.*The py23 module has been deprecated:DeprecationWarning"), | |
| ("filterwarnings", | |
| r"ignore:DynamicImporter.find_spec\(\) not found; " | |
| r"falling back to find_module\(\):ImportWarning"), | |
| ]: | |
| config.addinivalue_line(key, value) | |
| matplotlib.use('agg', force=True) | |
| matplotlib._called_from_pytest = True | |
| matplotlib._init_tests() | |
| def pytest_unconfigure(config): | |
| matplotlib._called_from_pytest = False | |
| def mpl_test_settings(request): | |
| from matplotlib.testing.decorators import _cleanup_cm | |
| with _cleanup_cm(): | |
| backend = None | |
| backend_marker = request.node.get_closest_marker('backend') | |
| prev_backend = matplotlib.get_backend() | |
| if backend_marker is not None: | |
| assert len(backend_marker.args) == 1, \ | |
| "Marker 'backend' must specify 1 backend." | |
| backend, = backend_marker.args | |
| skip_on_importerror = backend_marker.kwargs.get( | |
| 'skip_on_importerror', False) | |
| # special case Qt backend importing to avoid conflicts | |
| if backend.lower().startswith('qt5'): | |
| if any(sys.modules.get(k) for k in ('PyQt4', 'PySide')): | |
| pytest.skip('Qt4 binding already imported') | |
| matplotlib.testing.setup() | |
| with _api.suppress_matplotlib_deprecation_warning(): | |
| if backend is not None: | |
| # This import must come after setup() so it doesn't load the | |
| # default backend prematurely. | |
| import matplotlib.pyplot as plt | |
| try: | |
| plt.switch_backend(backend) | |
| except ImportError as exc: | |
| # Should only occur for the cairo backend tests, if neither | |
| # pycairo nor cairocffi are installed. | |
| if 'cairo' in backend.lower() or skip_on_importerror: | |
| pytest.skip("Failed to switch to backend " | |
| f"{backend} ({exc}).") | |
| else: | |
| raise | |
| # Default of cleanup and image_comparison too. | |
| matplotlib.style.use(["classic", "_classic_test_patch"]) | |
| try: | |
| yield | |
| finally: | |
| if backend is not None: | |
| plt.close("all") | |
| matplotlib.use(prev_backend) | |
| def pd(): | |
| """ | |
| Fixture to import and configure pandas. Using this fixture, the test is skipped when | |
| pandas is not installed. Use this fixture instead of importing pandas in test files. | |
| Examples | |
| -------- | |
| Request the pandas fixture by passing in ``pd`` as an argument to the test :: | |
| def test_matshow_pandas(pd): | |
| df = pd.DataFrame({'x':[1,2,3], 'y':[4,5,6]}) | |
| im = plt.figure().subplots().matshow(df) | |
| np.testing.assert_array_equal(im.get_array(), df) | |
| """ | |
| pd = pytest.importorskip('pandas') | |
| try: | |
| from pandas.plotting import ( | |
| deregister_matplotlib_converters as deregister) | |
| deregister() | |
| except ImportError: | |
| pass | |
| return pd | |
| def xr(): | |
| """ | |
| Fixture to import xarray so that the test is skipped when xarray is not installed. | |
| Use this fixture instead of importing xrray in test files. | |
| Examples | |
| -------- | |
| Request the xarray fixture by passing in ``xr`` as an argument to the test :: | |
| def test_imshow_xarray(xr): | |
| ds = xr.DataArray(np.random.randn(2, 3)) | |
| im = plt.figure().subplots().imshow(ds) | |
| np.testing.assert_array_equal(im.get_array(), ds) | |
| """ | |
| xr = pytest.importorskip('xarray') | |
| return xr | |
| def text_placeholders(monkeypatch): | |
| """ | |
| Replace texts with placeholder rectangles. | |
| The rectangle size only depends on the font size and the number of characters. It is | |
| thus insensitive to font properties and rendering details. This should be used for | |
| tests that depend on text geometries but not the actual text rendering, e.g. layout | |
| tests. | |
| """ | |
| from matplotlib.patches import Rectangle | |
| def patched_get_text_metrics_with_cache(renderer, text, fontprop, ismath, dpi): | |
| """ | |
| Replace ``_get_text_metrics_with_cache`` with fixed results. | |
| The usual ``renderer.get_text_width_height_descent`` would depend on font | |
| metrics; instead the fixed results are based on font size and the length of the | |
| string only. | |
| """ | |
| # While get_window_extent returns pixels and font size is in points, font size | |
| # includes ascenders and descenders. Leaving out this factor and setting | |
| # descent=0 ends up with a box that is relatively close to DejaVu Sans. | |
| height = fontprop.get_size() | |
| width = len(text) * height / 1.618 # Golden ratio for character size. | |
| descent = 0 | |
| return width, height, descent | |
| def patched_text_draw(self, renderer): | |
| """ | |
| Replace ``Text.draw`` with a fixed bounding box Rectangle. | |
| The bounding box corresponds to ``Text.get_window_extent``, which ultimately | |
| depends on the above patched ``_get_text_metrics_with_cache``. | |
| """ | |
| if renderer is not None: | |
| self._renderer = renderer | |
| if not self.get_visible(): | |
| return | |
| if self.get_text() == '': | |
| return | |
| bbox = self.get_window_extent() | |
| rect = Rectangle(bbox.p0, bbox.width, bbox.height, | |
| facecolor=self.get_color(), edgecolor='none') | |
| rect.draw(renderer) | |
| monkeypatch.setattr('matplotlib.text._get_text_metrics_with_cache', | |
| patched_get_text_metrics_with_cache) | |
| monkeypatch.setattr('matplotlib.text.Text.draw', patched_text_draw) | |