From 07e12f4fe360493899c53c172a8d1a02cfdd0d21 Mon Sep 17 00:00:00 2001 From: Eero Vaher Date: Mon, 20 Nov 2023 23:43:18 +0100 Subject: [PATCH] Remove usage of `py.path` with `pytest` 7 `py.path` provides classes for representing filesystem paths, but became obsolete when `pathlib` was added to Python standard library. `pytest` recommends creating temporary directories with the `tmp_path` fixture, which uses `pathlib`, instead of the older `tmpdir` fixture, which uses `py.path`. Furthermore, it is suggested to call `pytest` with `-p no:legacypath` to remove support for `py.path` entirely, which helps ensure `tmpdir` is not used at all. However, this also breaks any code accessing `_pytest.nodes.Node.fspath`. Because `pytest-mpl` includes such code then packages using it cannot turn off `py.path` support to guard against `tmpdir` usage. Although replacing accessing `fspath` in older versions of `pytest` is complicated, it is very simple since `pytest` 7, so now at least the packages using recent versions of `pytest` can choose to make use of the `-p no:legacypath` option. --- pytest_mpl/plugin.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/pytest_mpl/plugin.py b/pytest_mpl/plugin.py index 69aa26f..4ab01dd 100644 --- a/pytest_mpl/plugin.py +++ b/pytest_mpl/plugin.py @@ -63,6 +63,11 @@ ALL_IMAGE_FORMATS = RASTER_IMAGE_FORMATS + VECTOR_IMAGE_FORMATS +def _get_item_dir(item): + # .path is available starting from pytest 7, .fspath is for older versions. + return getattr(item, "path", Path(item.fspath)).parent + + def _hash_file(in_stream): """ Hashes an already opened file. @@ -445,11 +450,11 @@ def get_baseline_directory(self, item): baseline_dir = compare.kwargs.get('baseline_dir', None) if baseline_dir is None: if self.baseline_dir is None: - baseline_dir = Path(item.fspath).parent / 'baseline' + baseline_dir = _get_item_dir(item) / 'baseline' else: if self.baseline_relative_dir: # baseline dir is relative to the current test - baseline_dir = Path(item.fspath).parent / self.baseline_relative_dir + baseline_dir = _get_item_dir(item) / self.baseline_relative_dir else: # baseline dir is relative to where pytest was run baseline_dir = self.baseline_dir @@ -457,7 +462,7 @@ def get_baseline_directory(self, item): baseline_remote = (isinstance(baseline_dir, str) and # noqa baseline_dir.startswith(('http://', 'https://'))) if not baseline_remote: - return Path(item.fspath).parent / baseline_dir + return _get_item_dir(item) / baseline_dir return baseline_dir @@ -686,7 +691,7 @@ def compare_image_to_hash_library(self, item, fig, result_dir, summary=None): hash_library_filename = compare.kwargs.get("hash_library", None) or self.hash_library if self._hash_library_from_cli: # for backwards compatibility hash_library_filename = self.hash_library - hash_library_filename = (Path(item.fspath).parent / hash_library_filename).absolute() + hash_library_filename = _get_item_dir(item) / hash_library_filename if not Path(hash_library_filename).exists(): pytest.fail(f"Can't find hash library at path {hash_library_filename}")