diff --git a/hypothesis-python/RELEASE.rst b/hypothesis-python/RELEASE.rst new file mode 100644 index 0000000000..59b06a0af7 --- /dev/null +++ b/hypothesis-python/RELEASE.rst @@ -0,0 +1,4 @@ +RELEASE_TYPE: patch + +Fix :func:`~hypothesis.strategies.from_type` +on :class:`collections.abc.Callable` returning ``None``. diff --git a/hypothesis-python/src/hypothesis/strategies/_internal/types.py b/hypothesis-python/src/hypothesis/strategies/_internal/types.py index 4fd4829136..3c736bf3be 100644 --- a/hypothesis-python/src/hypothesis/strategies/_internal/types.py +++ b/hypothesis-python/src/hypothesis/strategies/_internal/types.py @@ -1031,6 +1031,9 @@ def resolve_Callable(thing): "Consider using an explicit strategy, or opening an issue." ) + if get_origin(thing) is collections.abc.Callable and return_type is None: + return_type = type(None) + return st.functions( like=(lambda *a, **k: None) if args_types else (lambda: None), returns=st.from_type(return_type), diff --git a/hypothesis-python/tests/cover/test_lookup_py39.py b/hypothesis-python/tests/cover/test_lookup_py39.py index 3181850c8e..6b7ade8dd0 100644 --- a/hypothesis-python/tests/cover/test_lookup_py39.py +++ b/hypothesis-python/tests/cover/test_lookup_py39.py @@ -8,6 +8,7 @@ # 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 collections.abc import dataclasses import sys import typing @@ -174,3 +175,9 @@ def __iter__(self): @given(...) def test_grouped_protocol_strategy(x: typing.Annotated[int, LazyStrategyAnnotation()]): assert x is sentinel + + +def test_collections_abc_callable_none(): + # https://github.com/HypothesisWorks/hypothesis/issues/4192 + s = st.from_type(collections.abc.Callable[[None], None]) + assert_all_examples(s, lambda x: callable(x) and x(None) is None)