Skip to content

Commit f4210aa

Browse files
authored
Merge pull request #4625 from HypothesisWorks/create-pull-request/patch
Update pinned dependencies
2 parents 6462385 + d5b091a commit f4210aa

File tree

11 files changed

+62
-50
lines changed

11 files changed

+62
-50
lines changed

hypothesis-python/RELEASE.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
RELEASE_TYPE: patch
2+
3+
Fixes :ref:`Ghostwriter <ghostwriter>` output for :pypi:`numpy` >= 2.4.0. Also adds support |st.from_type| for :pypi:`numpy` 2.5.0 nightly (which has not yet been released).

hypothesis-python/docs/changelog.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4347,7 +4347,7 @@ Thanks to Felix Divo for the new feature!
43474347
-------------------
43484348

43494349
This patch fixes invalid annotations detected for the tests generated by
4350-
:ref:`Ghostwritter <ghostwriter>`. It will now correctly generate ``Optional``
4350+
:ref:`Ghostwriter <ghostwriter>`. It will now correctly generate ``Optional``
43514351
types with just one type argument and handle union expressions inside of type
43524352
arguments correctly. Additionally, it now supports code with the
43534353
``from __future__ import annotations`` marker for Python 3.10 and newer.
@@ -4381,7 +4381,7 @@ For now, we capture calls made via :func:`~hypothesis.strategies.builds`, and vi
43814381
6.64.0 - 2023-01-23
43824382
-------------------
43834383

4384-
The :ref:`Ghostwritter <ghostwriter>` will now include type annotations on tests
4384+
The :ref:`Ghostwriter <ghostwriter>` will now include type annotations on tests
43854385
for type-annotated code. If you want to force this to happen (or not happen),
43864386
pass a boolean to the new ``annotate=`` argument to the Python functions, or
43874387
the ``--[no-]annotate`` CLI flag.
@@ -4924,7 +4924,7 @@ This PR was kindly supported by `Ordina Pythoneers
49244924
6.47.0 - 2022-06-07
49254925
-------------------
49264926

4927-
The :ref:`Ghostwritter <ghostwriter>` can now write tests for
4927+
The :ref:`Ghostwriter <ghostwriter>` can now write tests for
49284928
:obj:`@classmethod <classmethod>` or :obj:`@staticmethod <staticmethod>`
49294929
methods, in addition to the existing support for functions and other callables
49304930
(:issue:`3318`). Thanks to Cheuk Ting Ho for the patch.

hypothesis-python/src/hypothesis/extra/ghostwriter.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -491,11 +491,16 @@ def _get_params(func: Callable) -> dict[str, inspect.Parameter]:
491491
# we're out of ideas and should just re-raise the exception.
492492
raise
493493
else:
494-
# If the params we got look like an uninformative placeholder, try fallbacks.
495494
P = inspect.Parameter
496495
placeholder = [("args", P.VAR_POSITIONAL), ("kwargs", P.VAR_KEYWORD)]
497-
if [(p.name, p.kind) for p in params] == placeholder:
498-
params = _get_params_ufunc(func) or _get_params_builtin_fn(func) or params
496+
if ufunc_params := _get_params_ufunc(func):
497+
# If func is a ufunc, prefer _get_params_ufunc over get_signature,
498+
# as the latter includes keyword arguments we aren't well-equipped
499+
# to ghostwrite.
500+
params = ufunc_params
501+
elif [(p.name, p.kind) for p in params] == placeholder:
502+
# If the params we got look like an uninformative placeholder, try fallbacks.
503+
params = _get_params_builtin_fn(func) or params
499504
return _params_to_dict(params)
500505

501506

hypothesis-python/src/hypothesis/extra/numpy.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1433,7 +1433,9 @@ def _from_type(thing: type[Ex]) -> st.SearchStrategy[Ex] | None:
14331433
st.recursive(st.tuples(base_strat, base_strat), st.tuples),
14341434
)
14351435

1436-
if origin in [np.ndarray, _SupportsArray]:
1436+
# note: get_origin(np.typing.NDArray[np.int64]) is np.ndarray in numpy < 2.5.0,
1437+
# but is np.typing.NDArray in numpy >= 2.5.0. Support both here.
1438+
if origin in [np.typing.NDArray, np.ndarray, _SupportsArray]:
14371439
dtype = _dtype_from_args(args)
14381440
return arrays(dtype, array_shapes(max_dims=2)) # type: ignore[return-value]
14391441

hypothesis-python/src/hypothesis/strategies/_internal/core.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1585,7 +1585,7 @@ def _get_typeddict_qualifiers(key, annotation_type):
15851585
f"{from_type_repr} resolved to {builds_repr}, because we could not "
15861586
"find any (non-varargs) arguments. Use st.register_type_strategy() "
15871587
"to resolve to a strategy which can generate more than one value, "
1588-
"or silence this warning.",
1588+
"or to silence this warning.",
15891589
SmallSearchSpaceWarning,
15901590
stacklevel=2,
15911591
)

hypothesis-python/tests/numpy/test_floor_ceil.py

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
# obtain one at https://mozilla.org/MPL/2.0/.
1010

1111
import math
12-
import warnings
1312

1413
import numpy as np
1514
import pytest
@@ -33,22 +32,16 @@
3332
],
3433
)
3534
def test_our_floor_and_ceil_avoid_numpy_rounding(value):
36-
a = np.array([eval(value)])
37-
38-
with warnings.catch_warnings():
39-
warnings.simplefilter("ignore", DeprecationWarning)
40-
# See https://numpy.org/doc/stable/release/1.25.0-notes.html#deprecations
41-
f = floor(a)
42-
c = ceil(a)
35+
a = np.array(eval(value))
36+
f = floor(a)
37+
c = ceil(a)
4338

4439
# Check *exact* type - we don't want to allow a subclass of int here
4540
assert type(f) == int
4641
assert type(c) == int
4742

4843
# Using math.floor or math.ceil for these values would give an incorrect result.
49-
with warnings.catch_warnings():
50-
warnings.simplefilter("ignore", DeprecationWarning)
51-
assert (math.floor(a) > a) or (math.ceil(a) < a)
44+
assert (math.floor(a) > a) or (math.ceil(a) < a)
5245

5346
assert f <= a <= c
5447
assert f + 1 > a > c - 1

hypothesis-python/tests/numpy/test_from_type.py

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@
99
# obtain one at https://mozilla.org/MPL/2.0/.
1010

1111
import typing
12+
import warnings
1213

1314
import numpy as np
1415
import pytest
1516

16-
from hypothesis import given
17+
from hypothesis import given, strategies as st
18+
from hypothesis.errors import SmallSearchSpaceWarning
1719
from hypothesis.extra.numpy import ArrayLike, NDArray, _NestedSequence, _SupportsArray
18-
from hypothesis.strategies import builds, from_type
1920

2021
from .test_from_dtype import STANDARD_TYPES
2122
from tests.common.debug import assert_simple_property, find_any
@@ -26,29 +27,37 @@
2627
needs_np_private_typing = {"reason": "numpy._typing is not available"}
2728

2829

29-
@given(dtype=from_type(np.dtype))
30+
@given(dtype=st.from_type(np.dtype))
3031
def test_resolves_dtype_type(dtype):
3132
assert isinstance(dtype, np.dtype)
3233

3334

34-
@pytest.mark.parametrize("typ", [np.object_, np.void])
35-
def test_does_not_resolve_nonscalar_types(typ):
36-
# Comparing the objects directly fails on Windows,
37-
# so compare their reprs instead.
38-
assert repr(from_type(typ)) == repr(builds(typ))
35+
def test_does_not_resolve_nonscalar_types():
36+
# this was previously a parametrized test over np.object_ and np.void which
37+
# used the same repr code path for the test. But then numpy changed their types
38+
# such that we defer evaluation for st.from_type and are no longer identical
39+
# to st.builds, but rather something morally equivalent to it. So we have
40+
# these slightly more complicated checks.
41+
with warnings.catch_warnings():
42+
warnings.simplefilter("ignore", SmallSearchSpaceWarning)
43+
assert_simple_property(st.from_type(np.object_), lambda value: value is None)
44+
45+
with pytest.raises(TypeError):
46+
# np.void() requires an argument, and so throws when instantiated
47+
assert_simple_property(st.from_type(np.void))
3948

4049

4150
@pytest.mark.parametrize("typ", STANDARD_TYPES_TYPE)
4251
def test_resolves_and_varies_numpy_scalar_type(typ):
4352
# Check that we find an instance that is not equal to the default
44-
x = find_any(from_type(typ), lambda x: x != type(x)())
53+
x = find_any(st.from_type(typ), lambda x: x != type(x)())
4554
assert isinstance(x, typ)
4655

4756

4857
@pytest.mark.parametrize("atype", [np.ndarray, NDArray])
4958
def test_resolves_unspecified_array_type(atype):
5059
if atype is not None:
51-
assert_simple_property(from_type(atype), lambda v: isinstance(v, np.ndarray))
60+
assert_simple_property(st.from_type(atype), lambda v: isinstance(v, np.ndarray))
5261

5362

5463
def workaround(dtype):
@@ -65,12 +74,12 @@ def workaround(dtype):
6574
@pytest.mark.parametrize("typ", [workaround(t) for t in STANDARD_TYPES_TYPE])
6675
def test_resolves_specified_ndarray_type(typ):
6776
assert_simple_property(
68-
from_type(np.ndarray[typ]),
77+
st.from_type(np.ndarray[typ]),
6978
lambda arr: isinstance(arr, np.ndarray) and arr.dtype.type == typ,
7079
)
7180

7281
assert_simple_property(
73-
from_type(np.ndarray[typing.Any, typ]),
82+
st.from_type(np.ndarray[typing.Any, typ]),
7483
lambda arr: isinstance(arr, np.ndarray) and arr.dtype.type == typ,
7584
)
7685

@@ -79,20 +88,20 @@ def test_resolves_specified_ndarray_type(typ):
7988
@pytest.mark.parametrize("typ", [workaround(t) for t in STANDARD_TYPES_TYPE])
8089
def test_resolves_specified_NDArray_type(typ):
8190
assert_simple_property(
82-
from_type(NDArray[typ]),
91+
st.from_type(NDArray[typ]),
8392
lambda arr: isinstance(arr, np.ndarray) and arr.dtype.type == typ,
8493
)
8594

8695

8796
@pytest.mark.skipif(NDArray is None, **needs_np_typing)
8897
def test_resolves_NDArray_with_dtype_union():
89-
strat = from_type(NDArray[np.float64 | np.complex128])
98+
strat = st.from_type(NDArray[np.float64 | np.complex128])
9099
find_any(strat, lambda arr: arr.dtype == np.dtype("float64"))
91100
find_any(strat, lambda arr: arr.dtype == np.dtype("complex128"))
92101

93102

94103
@pytest.mark.skipif(ArrayLike is None, **needs_np_typing)
95-
@given(arr_like=from_type(ArrayLike))
104+
@given(arr_like=st.from_type(ArrayLike))
96105
def test_resolves_ArrayLike_type(arr_like):
97106
arr = np.array(arr_like)
98107
assert isinstance(arr, np.ndarray)
@@ -103,7 +112,7 @@ def test_resolves_ArrayLike_type(arr_like):
103112

104113
@pytest.mark.skipif(_NestedSequence is None, **needs_np_private_typing)
105114
def test_resolves_specified_NestedSequence():
106-
@given(seq=from_type(_NestedSequence[int]))
115+
@given(seq=st.from_type(_NestedSequence[int]))
107116
def test(seq):
108117
assert hasattr(seq, "__iter__")
109118

@@ -120,20 +129,20 @@ def flatten(lst):
120129

121130

122131
@pytest.mark.skipif(_NestedSequence is None, **needs_np_private_typing)
123-
@given(seq=from_type(_NestedSequence))
132+
@given(seq=st.from_type(_NestedSequence))
124133
def test_resolves_unspecified_NestedSequence(seq):
125134
assert hasattr(seq, "__iter__")
126135

127136

128137
@pytest.mark.skipif(_SupportsArray is None, **needs_np_private_typing)
129-
@given(arr=from_type(_SupportsArray))
138+
@given(arr=st.from_type(_SupportsArray))
130139
def test_resolves_unspecified_SupportsArray(arr):
131140
assert hasattr(arr, "__array__")
132141

133142

134143
@pytest.mark.skipif(_SupportsArray is None, **needs_np_private_typing)
135144
def test_resolves_SupportsArray():
136-
@given(arr=from_type(_SupportsArray[int]))
145+
@given(arr=st.from_type(_SupportsArray[int]))
137146
def test(arr):
138147
assert hasattr(arr, "__array__")
139148
assert np.asarray(arr).dtype.kind == "i"
@@ -162,7 +171,7 @@ def test_resolve_ArrayLike_equivalent():
162171
]
163172
)
164173

165-
@given(arr_like=from_type(ArrayLike_like))
174+
@given(arr_like=st.from_type(ArrayLike_like))
166175
def test(arr_like):
167176
arr = np.array(arr_like)
168177
assert isinstance(arr, np.ndarray)

hypothesis-python/tox.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ allowlist_externals =
7676
commands_pre =
7777
bash -c "pip install --upgrade --pre --only-binary :all: -i https://pypi.anaconda.org/scientific-python-nightly-wheels/simple numpy"
7878
commands =
79-
python -bb -X dev -m pytest tests/numpy/ tests/array_api/ tests/pandas/ tests/ghostwriter/ tests/conjecture/ tests/cover -n auto
79+
python -bb -X dev -m pytest tests/numpy/ tests/array_api/ tests/pandas/ tests/ghostwriter/ tests/conjecture/ tests/cover -n auto {posargs}
8080

8181
# Note: when adding or removing tested Pandas versions, make sure to update the
8282
# docs in numpy.rst too. To see current download rates of each minor version:

requirements/crosshair.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@ exceptiongroup==1.3.1 ; python_version < "3.11"
2525
# pytest
2626
execnet==2.1.2
2727
# via pytest-xdist
28-
hypothesis==6.148.7
28+
hypothesis==6.148.8
2929
# via hypothesis-crosshair
3030
hypothesis-crosshair==0.0.27
3131
# via -r requirements/crosshair.in
32-
importlib-metadata==8.7.0
32+
importlib-metadata==8.7.1
3333
# via crosshair-tool
3434
importlib-resources==6.5.2
3535
# via typeshed-client

requirements/fuzzing.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ hyperframe==6.1.0
5757
# via h2
5858
hypofuzz==25.11.1
5959
# via -r requirements/fuzzing.in
60-
hypothesis[cli,watchdog]==6.148.7
60+
hypothesis[cli,watchdog]==6.148.8
6161
# via hypofuzz
6262
idna==3.11
6363
# via
@@ -101,7 +101,7 @@ pluggy==1.6.0
101101
# pytest-cov
102102
priority==2.0.0
103103
# via hypercorn
104-
psutil==7.1.3
104+
psutil==7.2.0
105105
# via hypofuzz
106106
ptyprocess==0.7.0
107107
# via pexpect

0 commit comments

Comments
 (0)