From 8c3972450ac7e280e6bc6bf5d494e7cf10a9fba2 Mon Sep 17 00:00:00 2001 From: Matthew Broadway Date: Wed, 28 Feb 2024 21:30:50 +0000 Subject: [PATCH] fixed some Windows and pypy issues --- tests/test_import_hook/common.py | 16 +++++++++++++++- tests/test_import_hook/test_project_importer.py | 9 +++++---- .../test_import_hook/test_rust_file_importer.py | 9 +++++---- tests/test_import_hook/test_utilities.py | 14 ++++++++++++++ 4 files changed, 39 insertions(+), 9 deletions(-) diff --git a/tests/test_import_hook/common.py b/tests/test_import_hook/common.py index ef7ab3c..865b427 100644 --- a/tests/test_import_hook/common.py +++ b/tests/test_import_hook/common.py @@ -42,6 +42,13 @@ maturin_import_hook.install() """ +RELOAD_SUPPORTED = platform.system() != "Windows" and sys.version_info >= (3, 9) +""" +- reloading is not yet supported on Windows +- pyo3 does not support re-initialising modules for + python < 3.9 (https://github.com/PyO3/pyo3/commit/f17e70316751285340508d0009103570af7e0873) +""" + @dataclass class ResolvedPackage: @@ -270,7 +277,14 @@ def run_concurrent_python( def get_file_times(path: Path) -> Tuple[float, float]: s = path.stat() - return (s.st_atime, s.st_mtime) + times = (s.st_atime, s.st_mtime) + if platform.system() == "Windows" and platform.python_implementation() == "PyPy": + # workaround for https://github.com/pypy/pypy/issues/4916 + for _ in range(10): + set_file_times(path, times) + if path.stat().st_mtime == times[1]: + break + return times def set_file_times_recursive(path: Path, times: Tuple[float, float]) -> None: diff --git a/tests/test_import_hook/test_project_importer.py b/tests/test_import_hook/test_project_importer.py index 0098ca2..06ce1af 100644 --- a/tests/test_import_hook/test_project_importer.py +++ b/tests/test_import_hook/test_project_importer.py @@ -1,7 +1,6 @@ import json import logging import os -import platform import re import shutil import site @@ -17,6 +16,7 @@ from .common import ( IMPORT_HOOK_HEADER, + RELOAD_SUPPORTED, TEST_CRATES_DIR, all_usable_test_crate_names, check_match, @@ -578,7 +578,7 @@ def set_mtimes_equal() -> None: assert "SUCCESS" in output4 -@pytest.mark.skipif(platform.system() == "Windows", reason="reload not yet supported on windows") +@pytest.mark.skipif(not RELOAD_SUPPORTED, reason="reload not supported") class TestReload: """test that importlib.reload() can be used to reload modules imported by the import hook @@ -1049,7 +1049,8 @@ def _create_clean_project(tmp_dir: Path, is_mixed: bool) -> Path: def test_maturin_detection(self, workspace: Path) -> None: self._create_clean_project(workspace, True) - env = {"PATH": remove_executable_from_path(os.environ["PATH"], "maturin")} + env = os.environ.copy() + env["PATH"] = remove_executable_from_path(env["PATH"], "maturin") output, _ = run_python_code(self._logging_helper(), env=env) assert output == "building \"test_project\"\ncaught MaturinError('maturin not found')\n" @@ -1150,7 +1151,7 @@ def test_default_compile_warning(self, workspace: Path, is_mixed: bool) -> None: ) check_match(output2, pattern, flags=re.MULTILINE | re.DOTALL) - @pytest.mark.skipif(platform.system() == "Windows", reason="reload not yet supported on windows") + @pytest.mark.skipif(not RELOAD_SUPPORTED, reason="reload not supported") def test_reload(self, workspace: Path) -> None: self._create_clean_project(workspace, is_mixed=False) diff --git a/tests/test_import_hook/test_rust_file_importer.py b/tests/test_import_hook/test_rust_file_importer.py index d9a0439..6e545c3 100644 --- a/tests/test_import_hook/test_rust_file_importer.py +++ b/tests/test_import_hook/test_rust_file_importer.py @@ -1,5 +1,4 @@ import os -import platform import re import shutil from pathlib import Path @@ -9,6 +8,7 @@ import pytest from .common import ( + RELOAD_SUPPORTED, check_match, create_echo_script, get_file_times, @@ -247,7 +247,7 @@ def test_rebuild_on_settings_change(workspace: Path) -> None: assert "SUCCESS" in output4 -@pytest.mark.skipif(platform.system() == "Windows", reason="reload not yet supported on windows") +@pytest.mark.skipif(not RELOAD_SUPPORTED, reason="reload not supported") class TestReload: """test that importlib.reload() can be used to reload modules imported by the import hook @@ -611,7 +611,8 @@ def _create_clean_package(self, package_path: Path, *, reload_helper: bool = Fal def test_maturin_detection(self, workspace: Path) -> None: rs_path, py_path = self._create_clean_package(workspace / "package") - env = {"PATH": remove_executable_from_path(os.environ["PATH"], "maturin")} + env = os.environ.copy() + env["PATH"] = remove_executable_from_path(env["PATH"], "maturin") output, _ = run_python([str(py_path)], workspace, env=env) assert output == "building \"my_script\"\ncaught MaturinError('maturin not found')\n" @@ -701,7 +702,7 @@ def test_default_compile_warning(self, workspace: Path) -> None: ) check_match(output2, pattern, flags=re.MULTILINE | re.DOTALL) - @pytest.mark.skipif(platform.system() == "Windows", reason="reload not yet supported on windows") + @pytest.mark.skipif(not RELOAD_SUPPORTED, reason="reload not supported") def test_reload(self, workspace: Path) -> None: rs_path, py_path = self._create_clean_package(workspace / "package", reload_helper=True) diff --git a/tests/test_import_hook/test_utilities.py b/tests/test_import_hook/test_utilities.py index d45a26f..5400a61 100644 --- a/tests/test_import_hook/test_utilities.py +++ b/tests/test_import_hook/test_utilities.py @@ -3,6 +3,7 @@ import platform import re import subprocess +import time from pathlib import Path from typing import List, cast @@ -402,6 +403,19 @@ def test_get_string_between() -> None: assert get_string_between("11aaabbbccc11", "xxx", "xxx") is None +def test_set_file_times(tmp_path: Path) -> None: + for _ in range(10): + file_a = tmp_path / "a" + file_a.touch() + time.sleep(0.1) + file_b = tmp_path / "b" + file_b.touch() + assert file_a.stat().st_mtime != file_b.stat().st_mtime + times = get_file_times(file_a) + set_file_times(file_b, times) + assert file_a.stat().st_mtime == file_b.stat().st_mtime + + def _mock_directory_as_unreadable(dir_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: """cause PermissionError to be raised when calling `pathlib.Path.stat()` on a file inside the given directory