Repository: HypothesisWorks/hypothesis

Issue:
Strange behavior of the floats strategy with allow_infinite and min_value or max_value
When using `allow_infinity` in conjunction with `min_value` or `max_value`, it does not work correctly.

Repro:

```python
from hypothesis import given
from hypothesis.strategies import floats 

inf = float("inf")


@given(floats(allow_infinity=False, min_value=-1))
def repro_min(value):
	assert value != inf


@given(floats(allow_infinity=False, max_value=1))
def repro_max(value):
	assert value != -inf


def run(f):
	try:
		f()
	except:
		pass


if __name__ == "__main__":
	run(repro_min)
	run(repro_max)
```

Output:

```
Falsifying example: repro_min(value=inf)
Falsifying example: repro_max(value=-inf)
```

In the [documentation](https://hypothesis.readthedocs.io/en/latest/data.html#hypothesis.strategies.floats) it says

> If both min_value and max_value are not None, it is an error to enable allow_infinity

but I am not using both, just one at a time.


Discussion:
I can reproduce this with 3.66.30; investigating.

@Hendrikto, thanks for the report! You get an extra gold star for providing a repro script without using `.example()`.
Some version bisecting suggests this bug has been around since Hypothesis 3.0, but didn't affect 2.0.

Resolving patch:
diff --git a/hypothesis-python/src/hypothesis/strategies.py b/hypothesis-python/src/hypothesis/strategies.py
--- a/hypothesis-python/src/hypothesis/strategies.py
+++ b/hypothesis-python/src/hypothesis/strategies.py
@@ -466,7 +466,7 @@ def floats(
     elif min_value is not None:
         if min_value < 0:
             result = floats(
-                min_value=0.0
+                min_value=0.0, allow_infinity=allow_infinity
             ) | floats(min_value=min_value, max_value=-0.0)
         else:
             result = (
@@ -483,7 +483,7 @@ def floats(
             result = floats(
                 min_value=0.0,
                 max_value=max_value,
-            ) | floats(max_value=-0.0)
+            ) | floats(max_value=-0.0, allow_infinity=allow_infinity)
         else:
             result = (
                 floats(allow_infinity=allow_infinity, allow_nan=False).map(


Test patch:
diff --git a/hypothesis-python/tests/cover/test_direct_strategies.py b/hypothesis-python/tests/cover/test_direct_strategies.py
--- a/hypothesis-python/tests/cover/test_direct_strategies.py
+++ b/hypothesis-python/tests/cover/test_direct_strategies.py
@@ -422,3 +422,33 @@ def test_empty_elements_with_max_size_is_deprecated():
 @checks_deprecated_behaviour
 def test_average_size_is_deprecated():
     ds.lists(ds.integers(), average_size=1).example()
+
+
+@pytest.mark.parametrize('parameter_name', ['min_value', 'max_value'])
+@pytest.mark.parametrize('value', [-1, 0, 1])
+def test_no_infinity_for_min_max_values(value, parameter_name):
+    kwargs = {
+        'allow_infinity': False,
+        parameter_name: value,
+    }
+
+    @given(ds.floats(**kwargs))
+    def test_not_infinite(xs):
+        assert not math.isinf(xs)
+
+    test_not_infinite()
+
+
+@pytest.mark.parametrize('parameter_name', ['min_value', 'max_value'])
+@pytest.mark.parametrize('value', [-1, 0, 1])
+def test_no_nan_for_min_max_values(value, parameter_name):
+    kwargs = {
+        'allow_nan': False,
+        parameter_name: value,
+    }
+
+    @given(ds.floats(**kwargs))
+    def test_not_nan(xs):
+        assert not math.isnan(xs)
+
+    test_not_nan()