From 61411462d248e94515c25b75d938510f72f3e195 Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Sun, 21 Apr 2024 19:04:25 +0200 Subject: [PATCH 01/36] don't expect HypothesisWarning to be raised at the top level --- hypothesis-python/tests/array_api/conftest.py | 6 +++--- hypothesis-python/tests/array_api/test_partial_adoptors.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/hypothesis-python/tests/array_api/conftest.py b/hypothesis-python/tests/array_api/conftest.py index 630df48363..2d4ac26274 100644 --- a/hypothesis-python/tests/array_api/conftest.py +++ b/hypothesis-python/tests/array_api/conftest.py @@ -35,9 +35,9 @@ f"HYPOTHESIS_TEST_ARRAY_API_VERSION='{test_version_option}' is not " f"'default' or a valid api_version {NOMINAL_VERSIONS}." ) -with pytest.warns(HypothesisWarning): - mock_version = "draft" if test_version_option == "default" else test_version_option - mock_xps = make_strategies_namespace(mock_xp, api_version=mock_version) +# with pytest.warns(HypothesisWarning): +mock_version = "draft" if test_version_option == "default" else test_version_option +mock_xps = make_strategies_namespace(mock_xp, api_version=mock_version) api_version = None if test_version_option == "default" else test_version_option diff --git a/hypothesis-python/tests/array_api/test_partial_adoptors.py b/hypothesis-python/tests/array_api/test_partial_adoptors.py index 6de5d9dbb8..e587e12996 100644 --- a/hypothesis-python/tests/array_api/test_partial_adoptors.py +++ b/hypothesis-python/tests/array_api/test_partial_adoptors.py @@ -62,8 +62,8 @@ def test_error_on_missing_attr(stratname, args, attr): dtypeless_xp = make_mock_xp(exclude=tuple(DTYPE_NAMES)) -with pytest.warns(HypothesisWarning): - dtypeless_xps = make_strategies_namespace(dtypeless_xp, api_version="draft") +# with pytest.warns(HypothesisWarning): +dtypeless_xps = make_strategies_namespace(dtypeless_xp, api_version="draft") @pytest.mark.parametrize( From 018faec966e8e7cdc8b85b1fc779eb2cb90e9b39 Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Sun, 21 Apr 2024 19:20:12 +0200 Subject: [PATCH 02/36] check that we can generate arrays of float dtype other than f8 --- .../tests/array_api/test_arrays.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/hypothesis-python/tests/array_api/test_arrays.py b/hypothesis-python/tests/array_api/test_arrays.py index f63b03b9f6..22c3213f1c 100644 --- a/hypothesis-python/tests/array_api/test_arrays.py +++ b/hypothesis-python/tests/array_api/test_arrays.py @@ -296,6 +296,23 @@ def test_may_not_fill_unique_array_with_non_nan(xp, xps): check_can_generate_examples(strat) +def test_floating_point_array(): + from hypothesis.extra.array_api import make_strategies_namespace + + try: + import numpy.array_api as nxp + except ModuleNotFoundError: + import numpy as np + xps = make_strategies_namespace(np) + dtypes= xps.floating_dtypes() + + strat = xps.arrays( + dtype=dtypes, + shape=10 + ) + + check_can_generate_examples(strat) + @pytest.mark.parametrize( "kwargs", [ From 99c1729005cc436e4ab616200332cb8a0c3165c8 Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Wed, 24 Apr 2024 18:18:56 +0200 Subject: [PATCH 03/36] ignore the warning when importing `numpy.array_api` --- hypothesis-python/tests/array_api/test_arrays.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/hypothesis-python/tests/array_api/test_arrays.py b/hypothesis-python/tests/array_api/test_arrays.py index 22c3213f1c..bb182bed87 100644 --- a/hypothesis-python/tests/array_api/test_arrays.py +++ b/hypothesis-python/tests/array_api/test_arrays.py @@ -297,13 +297,16 @@ def test_may_not_fill_unique_array_with_non_nan(xp, xps): def test_floating_point_array(): + import warnings from hypothesis.extra.array_api import make_strategies_namespace try: - import numpy.array_api as nxp + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + import numpy.array_api as nxp except ModuleNotFoundError: - import numpy as np - xps = make_strategies_namespace(np) + import numpy as nxp + xps = make_strategies_namespace(nxp) dtypes= xps.floating_dtypes() strat = xps.arrays( From 24016426b64a9b07008889b117af89b1780e3807 Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Wed, 24 Apr 2024 18:25:07 +0200 Subject: [PATCH 04/36] also check complex dtypes --- hypothesis-python/tests/array_api/test_arrays.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hypothesis-python/tests/array_api/test_arrays.py b/hypothesis-python/tests/array_api/test_arrays.py index bb182bed87..4d94462e9e 100644 --- a/hypothesis-python/tests/array_api/test_arrays.py +++ b/hypothesis-python/tests/array_api/test_arrays.py @@ -307,7 +307,7 @@ def test_floating_point_array(): except ModuleNotFoundError: import numpy as nxp xps = make_strategies_namespace(nxp) - dtypes= xps.floating_dtypes() + dtypes= xps.floating_dtypes() | xps.complex_dtypes() strat = xps.arrays( dtype=dtypes, From e3414fd4329a25ab8ba4038e471c0d46bb1688f2 Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Wed, 24 Apr 2024 18:25:18 +0200 Subject: [PATCH 05/36] use `warnings.filterwarnings` to filter out a expected warning --- hypothesis-python/tests/array_api/conftest.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/hypothesis-python/tests/array_api/conftest.py b/hypothesis-python/tests/array_api/conftest.py index 2d4ac26274..128f357fb9 100644 --- a/hypothesis-python/tests/array_api/conftest.py +++ b/hypothesis-python/tests/array_api/conftest.py @@ -35,9 +35,10 @@ f"HYPOTHESIS_TEST_ARRAY_API_VERSION='{test_version_option}' is not " f"'default' or a valid api_version {NOMINAL_VERSIONS}." ) -# with pytest.warns(HypothesisWarning): -mock_version = "draft" if test_version_option == "default" else test_version_option -mock_xps = make_strategies_namespace(mock_xp, api_version=mock_version) +with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=HypothesisWarning) + mock_version = "draft" if test_version_option == "default" else test_version_option + mock_xps = make_strategies_namespace(mock_xp, api_version=mock_version) api_version = None if test_version_option == "default" else test_version_option From 43894fef625f7c0515c1a112939c241821fe3374 Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Wed, 24 Apr 2024 18:27:41 +0200 Subject: [PATCH 06/36] cast `finfo.smallest_normal` to builtin python `float` --- hypothesis-python/src/hypothesis/extra/array_api.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hypothesis-python/src/hypothesis/extra/array_api.py b/hypothesis-python/src/hypothesis/extra/array_api.py index 8c82f63114..85e5f3f8f9 100644 --- a/hypothesis-python/src/hypothesis/extra/array_api.py +++ b/hypothesis-python/src/hypothesis/extra/array_api.py @@ -282,7 +282,7 @@ def check_valid_minmax(prefix, val, info_obj): if allow_subnormal is not None: kw["allow_subnormal"] = allow_subnormal else: - subnormal = next_down(finfo.smallest_normal, width=finfo.bits) + subnormal = next_down(float(finfo.smallest_normal), width=finfo.bits) ftz = bool(xp.asarray(subnormal, dtype=dtype) == 0) if ftz: kw["allow_subnormal"] = False @@ -303,7 +303,7 @@ def check_valid_minmax(prefix, val, info_obj): # complex array, in case complex arrays have different FTZ behaviour # than arrays of the respective composite float. if allow_subnormal is None: - subnormal = next_down(finfo.smallest_normal, width=finfo.bits) + subnormal = next_down(float(finfo.smallest_normal), width=finfo.bits) x = xp.asarray(complex(subnormal, subnormal), dtype=dtype) builtin_x = complex(x) allow_subnormal = builtin_x.real != 0 and builtin_x.imag != 0 From ef7f6ee5f90fd6a4a8a22f6729ccd646f4b06e2f Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Wed, 24 Apr 2024 18:32:02 +0200 Subject: [PATCH 07/36] authors --- AUTHORS.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS.rst b/AUTHORS.rst index fe47bf7527..8b56decfee 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -96,6 +96,7 @@ their individual contributions. * `Jonty Wareing `_ (jonty@jonty.co.uk) * `Joshua Boone `_ (joshuaboone4190@gmail.com) * `jmhsi `_ +* `Justus Magin `_ * `jwg4 `_ * `Kai Chen `_ (kaichen120@gmail.com) * `Karthikeyan Singaravelan `_ (tir.karthi@gmail.com) From 1815bb62128417cdbc2688ebc5a2ba936e9553eb Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Wed, 24 Apr 2024 18:33:37 +0200 Subject: [PATCH 08/36] release note --- hypothesis-python/RELEASE.rst | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 hypothesis-python/RELEASE.rst diff --git a/hypothesis-python/RELEASE.rst b/hypothesis-python/RELEASE.rst new file mode 100644 index 0000000000..d8c68a9ab9 --- /dev/null +++ b/hypothesis-python/RELEASE.rst @@ -0,0 +1,3 @@ +RELEASE_TYPE: patch + +Explicitly cast `finfo.smallest_normal` to builtin `float` in preparation for the `numpy=2.0` release (:issue:`3950`) From b3a3e15110d30379242ffa76c9f09dbf757b406c Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Wed, 24 Apr 2024 18:39:06 +0200 Subject: [PATCH 09/36] ignore another warning --- hypothesis-python/tests/array_api/test_partial_adoptors.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hypothesis-python/tests/array_api/test_partial_adoptors.py b/hypothesis-python/tests/array_api/test_partial_adoptors.py index e587e12996..ca52be77a1 100644 --- a/hypothesis-python/tests/array_api/test_partial_adoptors.py +++ b/hypothesis-python/tests/array_api/test_partial_adoptors.py @@ -11,6 +11,7 @@ from copy import copy from types import SimpleNamespace from typing import Tuple +import warnings import pytest @@ -62,8 +63,9 @@ def test_error_on_missing_attr(stratname, args, attr): dtypeless_xp = make_mock_xp(exclude=tuple(DTYPE_NAMES)) -# with pytest.warns(HypothesisWarning): -dtypeless_xps = make_strategies_namespace(dtypeless_xp, api_version="draft") +with warnings.catch_warnings(): + warnings.filterwarning("ignore", category=HypothesisWarning) + dtypeless_xps = make_strategies_namespace(dtypeless_xp, api_version="draft") @pytest.mark.parametrize( From 74819c90116733b3350cb1005a86ea270e6db3a5 Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Wed, 24 Apr 2024 19:25:48 +0200 Subject: [PATCH 10/36] typo --- hypothesis-python/tests/array_api/test_partial_adoptors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hypothesis-python/tests/array_api/test_partial_adoptors.py b/hypothesis-python/tests/array_api/test_partial_adoptors.py index ca52be77a1..0ffbc420f7 100644 --- a/hypothesis-python/tests/array_api/test_partial_adoptors.py +++ b/hypothesis-python/tests/array_api/test_partial_adoptors.py @@ -64,7 +64,7 @@ def test_error_on_missing_attr(stratname, args, attr): dtypeless_xp = make_mock_xp(exclude=tuple(DTYPE_NAMES)) with warnings.catch_warnings(): - warnings.filterwarning("ignore", category=HypothesisWarning) + warnings.filterwarnings("ignore", category=HypothesisWarning) dtypeless_xps = make_strategies_namespace(dtypeless_xp, api_version="draft") From 24eed9fab8b5450788db2c125d3ef607754ae208 Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Wed, 24 Apr 2024 22:40:27 +0200 Subject: [PATCH 11/36] add a "numpy nightly" CI job --- .github/workflows/main.yml | 1 + hypothesis-python/tox.ini | 10 ++++++++++ tooling/src/hypothesistooling/__main__.py | 1 + 3 files changed, 12 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b126372768..7538458670 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -77,6 +77,7 @@ jobs: # - check-crosshair-nocover # - check-crosshair-niche - check-py38-oldestnumpy + - check-numpy-nightly fail-fast: false steps: - uses: actions/checkout@v3 diff --git a/hypothesis-python/tox.ini b/hypothesis-python/tox.ini index 2b8c5bf356..0aea2033c7 100644 --- a/hypothesis-python/tox.ini +++ b/hypothesis-python/tox.ini @@ -55,6 +55,16 @@ commands= bash -c "pip install --only-binary=:all: numpy==$(grep 'numpy>=' setup.py | grep -oE '[0-9.]+')" python -bb -X dev -m pytest tests/numpy/ -n auto +# This test job runs against the nightly version of `numpy` +[testenv:numpy-nightly] +deps= + -r../requirements/test.txt +allowlist_externals = + bash +commands= + bash -c "pip install --upgrade --pre --only-binary :all: -i https://pypi.anaconda.org/scientific-python-nightly-wheels/simple numpy" + python -bb -X dev -m pytest tests/numpy/ -n auto + # Note: when adding or removing tested Pandas versions, make sure to update the # docs in numpy.rst too. To see current download rates of each minor version: # https://pepy.tech/project/pandas?versions=1.1.*&versions=1.2.*&versions=1.3.*&versions=1.4.*&versions=1.5.*&versions=2.0.* diff --git a/tooling/src/hypothesistooling/__main__.py b/tooling/src/hypothesistooling/__main__.py index 08cd84bab6..07f08ef06d 100644 --- a/tooling/src/hypothesistooling/__main__.py +++ b/tooling/src/hypothesistooling/__main__.py @@ -502,6 +502,7 @@ def standard_tox_task(name, py=ci_version): standard_tox_task(f"crosshair-{kind}") standard_tox_task("py38-oldestnumpy", py="3.8") +standard_tox_task("numpy-nightly") standard_tox_task("coverage") standard_tox_task("conjecture-coverage") From ffd88a369f77c99b0ba04258bfe09504855a15d2 Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Wed, 24 Apr 2024 22:42:11 +0200 Subject: [PATCH 12/36] convert to `rst` syntax Co-authored-by: Zac Hatfield-Dodds --- hypothesis-python/RELEASE.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hypothesis-python/RELEASE.rst b/hypothesis-python/RELEASE.rst index d8c68a9ab9..a09e90423f 100644 --- a/hypothesis-python/RELEASE.rst +++ b/hypothesis-python/RELEASE.rst @@ -1,3 +1,4 @@ RELEASE_TYPE: patch -Explicitly cast `finfo.smallest_normal` to builtin `float` in preparation for the `numpy=2.0` release (:issue:`3950`) +Explicitly cast :obj:`numpy.finfo.smallest_normal` to builtin `float` in +preparation for the :pypi:`numpy==2.0 ` release (:issue:`3950`) From cb116250a8e1fb66defe6c927aade1cb2cc608bb Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Wed, 24 Apr 2024 22:50:34 +0200 Subject: [PATCH 13/36] require `python>=3.9` for the test --- hypothesis-python/tests/array_api/test_arrays.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hypothesis-python/tests/array_api/test_arrays.py b/hypothesis-python/tests/array_api/test_arrays.py index 4d94462e9e..4eea88f0f4 100644 --- a/hypothesis-python/tests/array_api/test_arrays.py +++ b/hypothesis-python/tests/array_api/test_arrays.py @@ -7,6 +7,7 @@ # This Source Code Form is subject to the terms of the Mozilla Public License, # v. 2.0. If a copy of the MPL was not distributed with this file, You can # obtain one at https://mozilla.org/MPL/2.0/. +import sys import pytest @@ -296,6 +297,7 @@ def test_may_not_fill_unique_array_with_non_nan(xp, xps): check_can_generate_examples(strat) +@pytest.mark.skipif(sys.version_info[:2] < (3, 9), reason="no complex") def test_floating_point_array(): import warnings from hypothesis.extra.array_api import make_strategies_namespace From 077e1c3555af69aa1f79d07b56f1ba70c21bba7b Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Wed, 24 Apr 2024 22:57:10 +0200 Subject: [PATCH 14/36] compare to `python=3.8` --- hypothesis-python/tests/array_api/test_arrays.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hypothesis-python/tests/array_api/test_arrays.py b/hypothesis-python/tests/array_api/test_arrays.py index 4eea88f0f4..7400a6a8e2 100644 --- a/hypothesis-python/tests/array_api/test_arrays.py +++ b/hypothesis-python/tests/array_api/test_arrays.py @@ -297,7 +297,7 @@ def test_may_not_fill_unique_array_with_non_nan(xp, xps): check_can_generate_examples(strat) -@pytest.mark.skipif(sys.version_info[:2] < (3, 9), reason="no complex") +@pytest.mark.skipif(sys.version_info[:2] <= (3, 8), reason="no complex") def test_floating_point_array(): import warnings from hypothesis.extra.array_api import make_strategies_namespace From 0eec1d308c2c0f41c2c29e3744936b3c7fdfcbda Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Wed, 24 Apr 2024 23:06:28 +0200 Subject: [PATCH 15/36] formatting --- hypothesis-python/tests/array_api/test_arrays.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/hypothesis-python/tests/array_api/test_arrays.py b/hypothesis-python/tests/array_api/test_arrays.py index 7400a6a8e2..464e4fd05f 100644 --- a/hypothesis-python/tests/array_api/test_arrays.py +++ b/hypothesis-python/tests/array_api/test_arrays.py @@ -309,15 +309,13 @@ def test_floating_point_array(): except ModuleNotFoundError: import numpy as nxp xps = make_strategies_namespace(nxp) - dtypes= xps.floating_dtypes() | xps.complex_dtypes() + dtypes = xps.floating_dtypes() | xps.complex_dtypes() - strat = xps.arrays( - dtype=dtypes, - shape=10 - ) + strat = xps.arrays(dtype=dtypes, shape=10) check_can_generate_examples(strat) + @pytest.mark.parametrize( "kwargs", [ From a5ac237bc5e729180d84e412b69bc18b029cd92e Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Wed, 24 Apr 2024 23:11:09 +0200 Subject: [PATCH 16/36] skip checking the `"a"` dtype kind on `numpy<2.0` --- hypothesis-python/tests/numpy/test_from_dtype.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/hypothesis-python/tests/numpy/test_from_dtype.py b/hypothesis-python/tests/numpy/test_from_dtype.py index 8dbb9d21c6..af21d7bc9d 100644 --- a/hypothesis-python/tests/numpy/test_from_dtype.py +++ b/hypothesis-python/tests/numpy/test_from_dtype.py @@ -10,6 +10,8 @@ import sys +from packaging import Version + import numpy as np import pytest @@ -126,7 +128,16 @@ def test_byte_string_dtypes_generate_unicode_strings(data): assert isinstance(result, bytes) -@pytest.mark.parametrize("dtype", ["U", "S", "a"]) +@pytest.mark.parametrize( + "dtype", + [ + "U", + "S", + pytest.param( + "a", marks=pytest.mark.skipif(Version(np.__version__) >= Version("2.0")) + ), + ], +) def test_unsized_strings_length_gt_one(dtype): # See https://github.com/HypothesisWorks/hypothesis/issues/2229 find_any(nps.arrays(dtype=dtype, shape=1), lambda arr: len(arr[0]) >= 2) From c97d221d62351ebc1b5d5bf94d53b5bbb1cf9188 Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Wed, 24 Apr 2024 23:15:54 +0200 Subject: [PATCH 17/36] replace packaging with a manually parsed version --- hypothesis-python/tests/numpy/test_from_dtype.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/hypothesis-python/tests/numpy/test_from_dtype.py b/hypothesis-python/tests/numpy/test_from_dtype.py index af21d7bc9d..6fd0ead441 100644 --- a/hypothesis-python/tests/numpy/test_from_dtype.py +++ b/hypothesis-python/tests/numpy/test_from_dtype.py @@ -10,8 +10,6 @@ import sys -from packaging import Version - import numpy as np import pytest @@ -23,6 +21,8 @@ from tests.common.debug import assert_no_examples, check_can_generate_examples, find_any +np_version = tuple(int(x) for x in np.__version__.split(".")[:2]) + STANDARD_TYPES = [ np.dtype(t) for t in ( @@ -133,9 +133,7 @@ def test_byte_string_dtypes_generate_unicode_strings(data): [ "U", "S", - pytest.param( - "a", marks=pytest.mark.skipif(Version(np.__version__) >= Version("2.0")) - ), + pytest.param("a", marks=pytest.mark.skipif(np_version >= (2, 0))), ], ) def test_unsized_strings_length_gt_one(dtype): From 464e9ccfdadbc15ddf3af1eb3fd83cd289b3e98d Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Wed, 24 Apr 2024 23:16:12 +0200 Subject: [PATCH 18/36] check for `OverflowError` on `numpy>=2.0` --- hypothesis-python/tests/numpy/test_gen_data.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hypothesis-python/tests/numpy/test_gen_data.py b/hypothesis-python/tests/numpy/test_gen_data.py index f16ef8bd7f..c5d7ee4dd0 100644 --- a/hypothesis-python/tests/numpy/test_gen_data.py +++ b/hypothesis-python/tests/numpy/test_gen_data.py @@ -348,7 +348,11 @@ def test_may_not_fill_with_non_nan_when_unique_is_set_and_type_is_not_number(arr @pytest.mark.parametrize("fill", [False, True]) # Overflowing elements deprecated upstream in Numpy 1.24 :-) -@fails_with(InvalidArgument if np_version < (1, 24) else DeprecationWarning) +@fails_with( + InvalidArgument + if np_version < (1, 24) + else (DeprecationWarning if np_version < (2, 0) else OverflowError) +) @given(st.data()) def test_overflowing_integers_are_deprecated(fill, data): kw = {"elements": st.just(300)} From 311fbe5dd07c11890721d1eb4ee05bda8d1862ea Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Wed, 24 Apr 2024 23:19:55 +0200 Subject: [PATCH 19/36] add a reason to the skipif --- hypothesis-python/tests/numpy/test_from_dtype.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hypothesis-python/tests/numpy/test_from_dtype.py b/hypothesis-python/tests/numpy/test_from_dtype.py index 6fd0ead441..cc95630d8f 100644 --- a/hypothesis-python/tests/numpy/test_from_dtype.py +++ b/hypothesis-python/tests/numpy/test_from_dtype.py @@ -133,7 +133,7 @@ def test_byte_string_dtypes_generate_unicode_strings(data): [ "U", "S", - pytest.param("a", marks=pytest.mark.skipif(np_version >= (2, 0))), + pytest.param("a", marks=pytest.mark.skipif(np_version >= (2, 0), reason="not supported on `numpy>=2.0`")), ], ) def test_unsized_strings_length_gt_one(dtype): From f615a4b079e59dcab91453b5712b0f48580d0dd6 Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Wed, 24 Apr 2024 23:23:21 +0200 Subject: [PATCH 20/36] more formatting --- hypothesis-python/tests/array_api/test_arrays.py | 1 + 1 file changed, 1 insertion(+) diff --git a/hypothesis-python/tests/array_api/test_arrays.py b/hypothesis-python/tests/array_api/test_arrays.py index 464e4fd05f..c9fe8e28ce 100644 --- a/hypothesis-python/tests/array_api/test_arrays.py +++ b/hypothesis-python/tests/array_api/test_arrays.py @@ -7,6 +7,7 @@ # This Source Code Form is subject to the terms of the Mozilla Public License, # v. 2.0. If a copy of the MPL was not distributed with this file, You can # obtain one at https://mozilla.org/MPL/2.0/. + import sys import pytest From ae0d62570fc1ac65c2e7b865c899fd1c2ea9a60b Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Wed, 24 Apr 2024 23:32:02 +0200 Subject: [PATCH 21/36] try running on `python=3.12` --- tooling/src/hypothesistooling/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tooling/src/hypothesistooling/__main__.py b/tooling/src/hypothesistooling/__main__.py index 07f08ef06d..9a2db040b9 100644 --- a/tooling/src/hypothesistooling/__main__.py +++ b/tooling/src/hypothesistooling/__main__.py @@ -502,7 +502,7 @@ def standard_tox_task(name, py=ci_version): standard_tox_task(f"crosshair-{kind}") standard_tox_task("py38-oldestnumpy", py="3.8") -standard_tox_task("numpy-nightly") +standard_tox_task("numpy-nightly", py="3.12") standard_tox_task("coverage") standard_tox_task("conjecture-coverage") From 4f2f0fe0109d0d6331b3dbe5866113fbb58bd013 Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Wed, 24 Apr 2024 23:32:51 +0200 Subject: [PATCH 22/36] run all tests, not just `numpy` --- hypothesis-python/tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hypothesis-python/tox.ini b/hypothesis-python/tox.ini index 0aea2033c7..00cb23c27a 100644 --- a/hypothesis-python/tox.ini +++ b/hypothesis-python/tox.ini @@ -63,7 +63,7 @@ allowlist_externals = bash commands= bash -c "pip install --upgrade --pre --only-binary :all: -i https://pypi.anaconda.org/scientific-python-nightly-wheels/simple numpy" - python -bb -X dev -m pytest tests/numpy/ -n auto + python -bb -X dev -m pytest tests/ -n auto # Note: when adding or removing tested Pandas versions, make sure to update the # docs in numpy.rst too. To see current download rates of each minor version: From 9bb1a87628b31b74d206abf4715d09077b74adea Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Thu, 25 Apr 2024 12:12:24 +0200 Subject: [PATCH 23/36] explicitly list the directories to check --- hypothesis-python/tox.ini | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hypothesis-python/tox.ini b/hypothesis-python/tox.ini index 00cb23c27a..c6362a3646 100644 --- a/hypothesis-python/tox.ini +++ b/hypothesis-python/tox.ini @@ -63,7 +63,11 @@ allowlist_externals = bash commands= bash -c "pip install --upgrade --pre --only-binary :all: -i https://pypi.anaconda.org/scientific-python-nightly-wheels/simple numpy" - python -bb -X dev -m pytest tests/ -n auto + python -bb -X dev -m pytest tests/numpy/ -n auto + python -bb -X dev -m pytest tests/array_api/ -n auto + python -bb -X dev -m pytest tests/pandas/ -n auto + python -bb -X dev -m pytest tests/ghostwriter/ -n auto + python -bb -X dev -m pytest tests/conjecture/ -n auto # Note: when adding or removing tested Pandas versions, make sure to update the # docs in numpy.rst too. To see current download rates of each minor version: From 8745fe763f1cce68d6dd755db8512733b44e1d6e Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Thu, 25 Apr 2024 12:17:38 +0200 Subject: [PATCH 24/36] run all tests together --- hypothesis-python/tox.ini | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/hypothesis-python/tox.ini b/hypothesis-python/tox.ini index c6362a3646..bdd97edbac 100644 --- a/hypothesis-python/tox.ini +++ b/hypothesis-python/tox.ini @@ -63,11 +63,7 @@ allowlist_externals = bash commands= bash -c "pip install --upgrade --pre --only-binary :all: -i https://pypi.anaconda.org/scientific-python-nightly-wheels/simple numpy" - python -bb -X dev -m pytest tests/numpy/ -n auto - python -bb -X dev -m pytest tests/array_api/ -n auto - python -bb -X dev -m pytest tests/pandas/ -n auto - python -bb -X dev -m pytest tests/ghostwriter/ -n auto - python -bb -X dev -m pytest tests/conjecture/ -n auto + python -bb -X dev -m pytest tests/numpy/ tests/array_api/ tests/pandas/ tests/ghostwriter/ tests/conjecture/ -n auto # Note: when adding or removing tested Pandas versions, make sure to update the # docs in numpy.rst too. To see current download rates of each minor version: From 883b895741a8f1a78b8210cb60a92dc2d06dd515 Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Thu, 25 Apr 2024 12:25:36 +0200 Subject: [PATCH 25/36] explicitly install pandas, black and click --- hypothesis-python/tox.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/hypothesis-python/tox.ini b/hypothesis-python/tox.ini index bdd97edbac..097c359fb1 100644 --- a/hypothesis-python/tox.ini +++ b/hypothesis-python/tox.ini @@ -63,6 +63,7 @@ allowlist_externals = bash commands= bash -c "pip install --upgrade --pre --only-binary :all: -i https://pypi.anaconda.org/scientific-python-nightly-wheels/simple numpy" + bash -c "pip install pandas black click" python -bb -X dev -m pytest tests/numpy/ tests/array_api/ tests/pandas/ tests/ghostwriter/ tests/conjecture/ -n auto # Note: when adding or removing tested Pandas versions, make sure to update the From 2031532953c4d62e85ad0380aa89555d7f2ec89e Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Thu, 25 Apr 2024 12:26:46 +0200 Subject: [PATCH 26/36] use tox to install the additional dependencies --- hypothesis-python/tox.ini | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hypothesis-python/tox.ini b/hypothesis-python/tox.ini index 097c359fb1..bdc1fc2bd4 100644 --- a/hypothesis-python/tox.ini +++ b/hypothesis-python/tox.ini @@ -59,11 +59,13 @@ commands= [testenv:numpy-nightly] deps= -r../requirements/test.txt + pandas + black + click allowlist_externals = bash commands= bash -c "pip install --upgrade --pre --only-binary :all: -i https://pypi.anaconda.org/scientific-python-nightly-wheels/simple numpy" - bash -c "pip install pandas black click" python -bb -X dev -m pytest tests/numpy/ tests/array_api/ tests/pandas/ tests/ghostwriter/ tests/conjecture/ -n auto # Note: when adding or removing tested Pandas versions, make sure to update the From d00167304c903b156ac40843eb27b6eebffa6703 Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Thu, 25 Apr 2024 14:04:53 +0200 Subject: [PATCH 27/36] also test `cover` --- hypothesis-python/tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hypothesis-python/tox.ini b/hypothesis-python/tox.ini index bdc1fc2bd4..23c3bcbfe7 100644 --- a/hypothesis-python/tox.ini +++ b/hypothesis-python/tox.ini @@ -66,7 +66,7 @@ allowlist_externals = bash commands= bash -c "pip install --upgrade --pre --only-binary :all: -i https://pypi.anaconda.org/scientific-python-nightly-wheels/simple numpy" - python -bb -X dev -m pytest tests/numpy/ tests/array_api/ tests/pandas/ tests/ghostwriter/ tests/conjecture/ -n auto + python -bb -X dev -m pytest tests/numpy/ tests/array_api/ tests/pandas/ tests/ghostwriter/ tests/conjecture/ tests/cover -n auto # Note: when adding or removing tested Pandas versions, make sure to update the # docs in numpy.rst too. To see current download rates of each minor version: From dbaa61c51af6f49d426dbc04709d2bf97ff7b4de Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Thu, 25 Apr 2024 14:15:57 +0200 Subject: [PATCH 28/36] only append `asfarray` on `numpy<2.0` --- .../src/hypothesis/strategies/_internal/strategies.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/hypothesis-python/src/hypothesis/strategies/_internal/strategies.py b/hypothesis-python/src/hypothesis/strategies/_internal/strategies.py index 448f7e51ac..bc2ba650d5 100644 --- a/hypothesis-python/src/hypothesis/strategies/_internal/strategies.py +++ b/hypothesis-python/src/hypothesis/strategies/_internal/strategies.py @@ -908,9 +908,12 @@ def _collection_ish_functions(): np.diag, # bonus undocumented functions from tab-completion: np.asarray_chkfinite, - np.asfarray, np.asfortranarray, ] + np_version = tuple(np.__version__.split(".", maxsplit=2)[:2]) + if np_version < (2, 0): + funcs += [np.asfarray] + return funcs From 68861bb457f0867fb63e0cf2f9a83b9ddfffcc06 Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Thu, 25 Apr 2024 14:35:25 +0200 Subject: [PATCH 29/36] fix the comparison --- .../src/hypothesis/strategies/_internal/strategies.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hypothesis-python/src/hypothesis/strategies/_internal/strategies.py b/hypothesis-python/src/hypothesis/strategies/_internal/strategies.py index bc2ba650d5..7ae5a11dff 100644 --- a/hypothesis-python/src/hypothesis/strategies/_internal/strategies.py +++ b/hypothesis-python/src/hypothesis/strategies/_internal/strategies.py @@ -910,8 +910,9 @@ def _collection_ish_functions(): np.asarray_chkfinite, np.asfortranarray, ] - np_version = tuple(np.__version__.split(".", maxsplit=2)[:2]) + np_version = tuple(int(_) for _ in np.__version__.split(".", maxsplit=2)[:2]) if np_version < (2, 0): + # removed in numpy>=2.0 funcs += [np.asfarray] return funcs From aa2ebdceaaaaa88e6aa514791ca8ef0bcc348869 Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Thu, 25 Apr 2024 15:17:24 +0200 Subject: [PATCH 30/36] allow patching out methods on the returned array --- .../tests/array_api/test_partial_adoptors.py | 38 ++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/hypothesis-python/tests/array_api/test_partial_adoptors.py b/hypothesis-python/tests/array_api/test_partial_adoptors.py index 0ffbc420f7..947ed042b5 100644 --- a/hypothesis-python/tests/array_api/test_partial_adoptors.py +++ b/hypothesis-python/tests/array_api/test_partial_adoptors.py @@ -11,6 +11,7 @@ from copy import copy from types import SimpleNamespace from typing import Tuple +import functools import warnings import pytest @@ -32,11 +33,46 @@ MOCK_WARN_MSG = f"determine.*{mock_xp.__name__}.*Array API" -def make_mock_xp(*, exclude: Tuple[str, ...] = ()) -> SimpleNamespace: +class MockedArray: + def __init__(self, wrapped, *, exclude=()): + self.wrapped = wrapped + self.exclude = exclude + + def __getattribute__(self, name): + if name in self.exclude: + raise AttributeError(f"removed on the mock: {name}") + + return super().__getattribute__(self, name) + + +def wrap_array(func: callable, exclude: Tuple[str, ...] =()) -> callable: + @functools.wraps(func) + def wrapped(*args, **kwargs): + result = func(*args, **kwargs) + + if isinstance(result, tuple): + return tuple(MockedArray(arr, exclude=exclude) for arr in result) + + return MockedArray(result, exclude=exclude) + + return wrapped + +def make_mock_xp(*, exclude: Tuple[str, ...] = (), exclude_methods: Tuple[str, ...] = ()) -> SimpleNamespace: xp = copy(mock_xp) assert isinstance(exclude, tuple) # sanity check + assert isinstance(exclude_methods, tuple) # sanity check for attr in exclude: delattr(xp, attr) + + array_returning_funcs = ("astype", "broadcast_arrays", "arange", "asarray", "empty", "zeros", "ones", "reshape", "isnan", "isfinite", "logical_or", "sum", "nonzero", "sort", "unique_values", "any", "all") + + for name in array_returning_funcs: + func = getattr(xp, name, None) + if func is None: + # removed in the step before + continue + setattr(xp, name, wrap_array(func, exclude=exclude_methods)) + return xp From 0412cb172659a2cba84f1e9c2073f74687946424 Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Thu, 25 Apr 2024 15:17:35 +0200 Subject: [PATCH 31/36] remove `__array_namespace__` on the returned array --- hypothesis-python/tests/array_api/test_partial_adoptors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hypothesis-python/tests/array_api/test_partial_adoptors.py b/hypothesis-python/tests/array_api/test_partial_adoptors.py index 947ed042b5..12e6091034 100644 --- a/hypothesis-python/tests/array_api/test_partial_adoptors.py +++ b/hypothesis-python/tests/array_api/test_partial_adoptors.py @@ -78,7 +78,7 @@ def make_mock_xp(*, exclude: Tuple[str, ...] = (), exclude_methods: Tuple[str, . def test_warning_on_noncompliant_xp(): """Using non-compliant array modules raises helpful warning""" - xp = make_mock_xp() + xp = make_mock_xp(exclude_methods=("__array_namespace__",)) with pytest.warns(HypothesisWarning, match=MOCK_WARN_MSG): make_strategies_namespace(xp, api_version="draft") From f8fa04881765fcfc3ff4ec14f2225e29c92d3153 Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Thu, 25 Apr 2024 15:18:29 +0200 Subject: [PATCH 32/36] formatting --- .../tests/array_api/test_partial_adoptors.py | 27 ++++++++++++++++--- .../tests/numpy/test_from_dtype.py | 7 ++++- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/hypothesis-python/tests/array_api/test_partial_adoptors.py b/hypothesis-python/tests/array_api/test_partial_adoptors.py index 12e6091034..ffdd7d0f14 100644 --- a/hypothesis-python/tests/array_api/test_partial_adoptors.py +++ b/hypothesis-python/tests/array_api/test_partial_adoptors.py @@ -45,7 +45,7 @@ def __getattribute__(self, name): return super().__getattribute__(self, name) -def wrap_array(func: callable, exclude: Tuple[str, ...] =()) -> callable: +def wrap_array(func: callable, exclude: Tuple[str, ...] = ()) -> callable: @functools.wraps(func) def wrapped(*args, **kwargs): result = func(*args, **kwargs) @@ -57,14 +57,35 @@ def wrapped(*args, **kwargs): return wrapped -def make_mock_xp(*, exclude: Tuple[str, ...] = (), exclude_methods: Tuple[str, ...] = ()) -> SimpleNamespace: + +def make_mock_xp( + *, exclude: Tuple[str, ...] = (), exclude_methods: Tuple[str, ...] = () +) -> SimpleNamespace: xp = copy(mock_xp) assert isinstance(exclude, tuple) # sanity check assert isinstance(exclude_methods, tuple) # sanity check for attr in exclude: delattr(xp, attr) - array_returning_funcs = ("astype", "broadcast_arrays", "arange", "asarray", "empty", "zeros", "ones", "reshape", "isnan", "isfinite", "logical_or", "sum", "nonzero", "sort", "unique_values", "any", "all") + array_returning_funcs = ( + "astype", + "broadcast_arrays", + "arange", + "asarray", + "empty", + "zeros", + "ones", + "reshape", + "isnan", + "isfinite", + "logical_or", + "sum", + "nonzero", + "sort", + "unique_values", + "any", + "all", + ) for name in array_returning_funcs: func = getattr(xp, name, None) diff --git a/hypothesis-python/tests/numpy/test_from_dtype.py b/hypothesis-python/tests/numpy/test_from_dtype.py index cc95630d8f..1338e2efab 100644 --- a/hypothesis-python/tests/numpy/test_from_dtype.py +++ b/hypothesis-python/tests/numpy/test_from_dtype.py @@ -133,7 +133,12 @@ def test_byte_string_dtypes_generate_unicode_strings(data): [ "U", "S", - pytest.param("a", marks=pytest.mark.skipif(np_version >= (2, 0), reason="not supported on `numpy>=2.0`")), + pytest.param( + "a", + marks=pytest.mark.skipif( + np_version >= (2, 0), reason="not supported on `numpy>=2.0`" + ), + ), ], ) def test_unsized_strings_length_gt_one(dtype): From ecd4593bbbc197e9f5d655ce48daaa66f9021558 Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Thu, 25 Apr 2024 15:43:37 +0200 Subject: [PATCH 33/36] try explicitly returning the result of `object.__getattribute__` --- hypothesis-python/tests/array_api/test_partial_adoptors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hypothesis-python/tests/array_api/test_partial_adoptors.py b/hypothesis-python/tests/array_api/test_partial_adoptors.py index ffdd7d0f14..cb2ab2655e 100644 --- a/hypothesis-python/tests/array_api/test_partial_adoptors.py +++ b/hypothesis-python/tests/array_api/test_partial_adoptors.py @@ -42,7 +42,7 @@ def __getattribute__(self, name): if name in self.exclude: raise AttributeError(f"removed on the mock: {name}") - return super().__getattribute__(self, name) + return object.__getattribute__(self, name) def wrap_array(func: callable, exclude: Tuple[str, ...] = ()) -> callable: From fe34343ec0c40e3461b7a75fb6f36cee35339ec3 Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Thu, 25 Apr 2024 19:49:03 +0200 Subject: [PATCH 34/36] remove `asfarray` entirely --- .../src/hypothesis/strategies/_internal/strategies.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/hypothesis-python/src/hypothesis/strategies/_internal/strategies.py b/hypothesis-python/src/hypothesis/strategies/_internal/strategies.py index 7ae5a11dff..53bee1fe22 100644 --- a/hypothesis-python/src/hypothesis/strategies/_internal/strategies.py +++ b/hypothesis-python/src/hypothesis/strategies/_internal/strategies.py @@ -910,10 +910,6 @@ def _collection_ish_functions(): np.asarray_chkfinite, np.asfortranarray, ] - np_version = tuple(int(_) for _ in np.__version__.split(".", maxsplit=2)[:2]) - if np_version < (2, 0): - # removed in numpy>=2.0 - funcs += [np.asfarray] return funcs From 8d5ef72d207e92c76e3c21daca6e83adc259454f Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Thu, 25 Apr 2024 19:50:32 +0200 Subject: [PATCH 35/36] store the "removed in numpy 2" mark in a variable Co-authored-by: Zac Hatfield-Dodds --- hypothesis-python/tests/numpy/test_from_dtype.py | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/hypothesis-python/tests/numpy/test_from_dtype.py b/hypothesis-python/tests/numpy/test_from_dtype.py index 1338e2efab..4316f00577 100644 --- a/hypothesis-python/tests/numpy/test_from_dtype.py +++ b/hypothesis-python/tests/numpy/test_from_dtype.py @@ -128,18 +128,11 @@ def test_byte_string_dtypes_generate_unicode_strings(data): assert isinstance(result, bytes) +skipif_np2 = pytest.mark.skipif(np_version >= (2, 0), reason="removed in new version") + @pytest.mark.parametrize( "dtype", - [ - "U", - "S", - pytest.param( - "a", - marks=pytest.mark.skipif( - np_version >= (2, 0), reason="not supported on `numpy>=2.0`" - ), - ), - ], + ["U", "S", pytest.param("a", marks=skipif_np2)], ) def test_unsized_strings_length_gt_one(dtype): # See https://github.com/HypothesisWorks/hypothesis/issues/2229 From f8e048e3654ac99a13fd45bb4c7d738e0d3305e0 Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Fri, 26 Apr 2024 21:28:04 +0200 Subject: [PATCH 36/36] use `__getattr__` instead of `__getattribute__` --- hypothesis-python/tests/array_api/test_partial_adoptors.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hypothesis-python/tests/array_api/test_partial_adoptors.py b/hypothesis-python/tests/array_api/test_partial_adoptors.py index cb2ab2655e..422b109acf 100644 --- a/hypothesis-python/tests/array_api/test_partial_adoptors.py +++ b/hypothesis-python/tests/array_api/test_partial_adoptors.py @@ -38,11 +38,11 @@ def __init__(self, wrapped, *, exclude=()): self.wrapped = wrapped self.exclude = exclude - def __getattribute__(self, name): + def __getattr__(self, name): if name in self.exclude: raise AttributeError(f"removed on the mock: {name}") - return object.__getattribute__(self, name) + return object.__getattr__(self, name) def wrap_array(func: callable, exclude: Tuple[str, ...] = ()) -> callable: