diff --git a/hypothesis-python/scripts/other-tests.sh b/hypothesis-python/scripts/other-tests.sh index 4e24e51c11..8a7b3dcac8 100644 --- a/hypothesis-python/scripts/other-tests.sh +++ b/hypothesis-python/scripts/other-tests.sh @@ -31,7 +31,9 @@ $PYTEST tests/redis/ pip uninstall -y redis fakeredis $PYTEST tests/typing_extensions/ -pip uninstall -y typing_extensions +if [[ "$HYPOTHESIS_PROFILE" != "crosshair" ]]; then + pip uninstall -y typing_extensions +fi if [ "$(python -c 'import sys; print(sys.version_info[:2] >= (3, 9))')" = "True" ] ; then pip install "$(grep 'annotated-types==' ../requirements/coverage.txt)" @@ -62,14 +64,10 @@ if [ "$(python -c $'import platform, sys; print(sys.version_info.releaselevel == pip install "$(grep 'numpy==' ../requirements/coverage.txt)" fi - case "$(python -c 'import platform; print(platform.python_implementation())')" in - PyPy|GraalVM) - ;; - *) - $PYTEST tests/array_api - $PYTEST tests/numpy - esac - $PYTEST tests/ghostwriter/ - pip uninstall -y black numpy + pip uninstall -y black + + if [ "$(python -c "import platform; print(platform.python_implementation() not in {'PyPy', 'GraalVM'})")" = "True" ] ; then + $PYTEST tests/array_api tests/numpy + fi fi diff --git a/hypothesis-python/setup.py b/hypothesis-python/setup.py index fd0e774269..7cdfa3c402 100644 --- a/hypothesis-python/setup.py +++ b/hypothesis-python/setup.py @@ -60,7 +60,7 @@ def local_file(name): "pytest": ["pytest>=4.6"], "dpcontracts": ["dpcontracts>=0.4"], "redis": ["redis>=3.0.0"], - "crosshair": ["hypothesis-crosshair>=0.0.7", "crosshair-tool>=0.0.61"], + "crosshair": ["hypothesis-crosshair>=0.0.8", "crosshair-tool>=0.0.62"], # zoneinfo is an odd one: every dependency is conditional, because they're # only necessary on old versions of Python or Windows systems or emscripten. "zoneinfo": [ diff --git a/hypothesis-python/tests/cover/test_draw_example.py b/hypothesis-python/tests/cover/test_draw_example.py index a417297614..94e08d5c73 100644 --- a/hypothesis-python/tests/cover/test_draw_example.py +++ b/hypothesis-python/tests/cover/test_draw_example.py @@ -16,11 +16,11 @@ from tests.common.debug import check_can_generate_examples -@pytest.mark.parametrize("spec", standard_types, ids=list(map(repr, standard_types))) +@pytest.mark.parametrize("spec", standard_types, ids=repr) def test_single_example(spec): check_can_generate_examples(spec) -@pytest.mark.parametrize("spec", standard_types, ids=list(map(repr, standard_types))) +@pytest.mark.parametrize("spec", standard_types, ids=repr) def test_list_example(spec): check_can_generate_examples(lists(spec)) diff --git a/hypothesis-python/tests/cover/test_explicit_examples.py b/hypothesis-python/tests/cover/test_explicit_examples.py index d47e9ae41e..efbb4377d3 100644 --- a/hypothesis-python/tests/cover/test_explicit_examples.py +++ b/hypothesis-python/tests/cover/test_explicit_examples.py @@ -27,7 +27,7 @@ from hypothesis.internal.compat import ExceptionGroup from hypothesis.strategies import floats, integers, text -from tests.common.utils import assert_falsifying_output, capture_out +from tests.common.utils import assert_falsifying_output, capture_out, fails_with class TestInstanceMethods(TestCase): @@ -222,15 +222,12 @@ def test(a): test() -def test_runs_deadline_for_examples(): - @example(10) - @settings(phases=[Phase.explicit]) - @given(integers()) - def test(x): - time.sleep(10) - - with pytest.raises(DeadlineExceeded): - test() +@fails_with(DeadlineExceeded) +@example(10) +@settings(phases=[Phase.explicit]) +@given(integers()) +def test(x): + time.sleep(10) @given(value=floats(0, 1)) diff --git a/hypothesis-python/tests/ghostwriter/test_ghostwriter.py b/hypothesis-python/tests/ghostwriter/test_ghostwriter.py index f63f881bf3..402209ea63 100644 --- a/hypothesis-python/tests/ghostwriter/test_ghostwriter.py +++ b/hypothesis-python/tests/ghostwriter/test_ghostwriter.py @@ -11,6 +11,8 @@ import ast import enum import json +import os +import platform import re import socket import unittest @@ -450,13 +452,22 @@ def test_get_imports_for_strategy(strategy, imports): @pytest.fixture -def temp_script_file(): - """Fixture to yield a Path to a temporary file in the local directory. File name will end - in .py and will include an importable function. +def in_temp_path(tmp_path): + """Fixture to execute tests in a temporary path.""" + old_path = Path.cwd() + os.chdir(tmp_path) + yield + os.chdir(old_path) + + +@pytest.fixture +def temp_script_file(in_temp_path): + """Fixture to create a script file in a temporary working directory. + + Changes the working directory to a temporary directory, then yields an extant file + whose name will end in .py and which includes an importable function. """ p = Path("my_temp_script.py") - if p.exists(): - raise FileExistsError(f"Did not expect {p} to exist during testing") p.write_text( dedent( """ @@ -466,18 +477,17 @@ def say_hello(): ), encoding="utf-8", ) - yield p - p.unlink() + return p @pytest.fixture -def temp_script_file_with_py_function(): - """Fixture to yield a Path to a temporary file in the local directory. File name will end - in .py and will include an importable function named "py" +def temp_script_file_with_py_function(in_temp_path): + """Fixture to create a python file in a temporary working directory. + + Changes the working directory to a temporary directory, then yields an extant file + whose name will end in .py and which includes an importable function named "py". """ p = Path("my_temp_script_with_py_function.py") - if p.exists(): - raise FileExistsError(f"Did not expect {p} to exist during testing") p.write_text( dedent( """ @@ -487,8 +497,7 @@ def py(): ), encoding="utf-8", ) - yield p - p.unlink() + return p def test_obj_name(temp_script_file, temp_script_file_with_py_function): @@ -500,7 +509,7 @@ def test_obj_name(temp_script_file, temp_script_file_with_py_function): ) # Windows paths (strings including a "\") should also raise a meaningful UsageError with pytest.raises(click.exceptions.UsageError) as e: - cli.obj_name("mydirectory\\myscript.py") + cli.obj_name(R"mydirectory\myscript.py") assert e.match( "Remember that the ghostwriter should be passed the name of a module, not a path." ) @@ -510,7 +519,10 @@ def test_obj_name(temp_script_file, temp_script_file_with_py_function): assert e.match( "Remember that the ghostwriter should be passed the name of a module, not a file." ) + # File names of modules (strings ending in ".py") that exist should get a suggestion + if platform.system() == "Darwin": + return # bad/flaky interaction between importlib and tempdirs here with pytest.raises(click.exceptions.UsageError) as e: cli.obj_name(str(temp_script_file)) assert e.match( diff --git a/hypothesis-python/tests/nocover/test_collective_minimization.py b/hypothesis-python/tests/nocover/test_collective_minimization.py index ae9b9b3959..ebd846096b 100644 --- a/hypothesis-python/tests/nocover/test_collective_minimization.py +++ b/hypothesis-python/tests/nocover/test_collective_minimization.py @@ -18,7 +18,7 @@ from tests.common.debug import minimal -@pytest.mark.parametrize("spec", standard_types, ids=list(map(repr, standard_types))) +@pytest.mark.parametrize("spec", standard_types, ids=repr) def test_can_collectively_minimize(spec): n = 10 try: diff --git a/pyproject.toml b/pyproject.toml index 59a77bae6f..5e4e160149 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -47,6 +47,7 @@ ignore = [ "PIE790", # See https://github.com/astral-sh/ruff/issues/10538 "PT001", "PT003", + "PT004", "PT006", "PT007", "PT009",