def floats(min_value=None, max_value=None): """Returns a strategy which generates floats. If min_value is not None, all values will be >= min_value. If max_value is not None, all values will be <= max_value. Where not explicitly ruled out by the bounds, all of infinity, -infinity and NaN are possible values generated by this strategy. """ for e in (min_value, max_value): if e is not None and math.isnan(e): raise InvalidArgument('nan is not a valid end point') if min_value == float('-inf'): min_value = None if max_value == float('inf'): max_value = None from hypothesis.searchstrategy.numbers import WrapperFloatStrategy, \ GaussianFloatStrategy, BoundedFloatStrategy, ExponentialFloatStrategy,\ JustIntFloats, NastyFloats, FullRangeFloats, \ FixedBoundedFloatStrategy, FloatsFromBase if min_value is None and max_value is None: return WrapperFloatStrategy(GaussianFloatStrategy() | BoundedFloatStrategy() | ExponentialFloatStrategy() | JustIntFloats() | NastyFloats() | FullRangeFloats()) elif min_value is not None and max_value is not None: if max_value < min_value: raise InvalidArgument('Cannot have max_value=%r < min_value=%r' % (max_value, min_value)) elif min_value == max_value: return just(min_value) elif math.isinf(max_value - min_value): assert min_value < 0 and max_value > 0 return floats(min_value=0, max_value=max_value) | floats( min_value=min_value, max_value=0) return FixedBoundedFloatStrategy(min_value, max_value) elif min_value is not None: return FloatsFromBase( base=min_value, sign=1, ) | just(float('inf')) else: assert max_value is not None return FloatsFromBase(base=max_value, sign=-1) | just(float('-inf'))
@fails @given(floats(), settings=TRY_HARDER) def test_can_find_floats_that_do_not_round_trip_through_reprs(x): assert float(repr(x)) == x @given(floats(), floats(), randoms()) def test_floats_are_in_range(x, y, rand): assume(not (math.isnan(x) or math.isnan(y))) assume(not (math.isinf(x) or math.isinf(y))) x, y = sorted((x, y)) assume(x < y) with Settings(max_examples=10): @given(floats(x, y), random=rand) def test_is_in_range(t): assert x <= t <= y try: test_is_in_range() except Unsatisfiable: assume(False) @fails_with(AssertionError) @given(NastyFloats()) def test_can_use_just_nasty(x): assert not math.isnan(x)
def floats(min_value=None, max_value=None): """Returns a strategy which generates floats. If min_value is not None, all values will be >= min_value. If max_value is not None, all values will be <= max_value. Where not explicitly ruled out by the bounds, all of infinity, -infinity and NaN are possible values generated by this strategy. """ for e in (min_value, max_value): if e is not None and math.isnan(e): raise InvalidArgument(u'nan is not a valid end point') if min_value is not None: min_value = float(min_value) if max_value is not None: max_value = float(max_value) if min_value == float(u'-inf'): min_value = None if max_value == float(u'inf'): max_value = None from hypothesis.searchstrategy.numbers import WrapperFloatStrategy, \ GaussianFloatStrategy, BoundedFloatStrategy, ExponentialFloatStrategy,\ JustIntFloats, NastyFloats, FullRangeFloats, \ FixedBoundedFloatStrategy, FloatsFromBase if min_value is None and max_value is None: return WrapperFloatStrategy( GaussianFloatStrategy() | BoundedFloatStrategy() | ExponentialFloatStrategy() | JustIntFloats() | NastyFloats() | FullRangeFloats() ) elif min_value is not None and max_value is not None: if max_value < min_value: raise InvalidArgument( u'Cannot have max_value=%r < min_value=%r' % ( max_value, min_value )) elif min_value == max_value: return just(min_value) elif math.isinf(max_value - min_value): assert min_value < 0 and max_value > 0 return floats(min_value=0, max_value=max_value) | floats( min_value=min_value, max_value=0 ) elif count_between_floats(min_value, max_value) > 1000: critical_values = [ min_value, max_value, min_value + (max_value - min_value) / 2] if min_value <= 0 <= max_value: if not is_negative(max_value): critical_values.append(0.0) if is_negative(min_value): critical_values.append(-0.0) return FixedBoundedFloatStrategy( lower_bound=min_value, upper_bound=max_value ) | sampled_from(critical_values) elif is_negative(max_value): assert is_negative(min_value) ub_int = float_to_int(max_value) lb_int = float_to_int(min_value) assert ub_int <= lb_int return integers(min_value=ub_int, max_value=lb_int).map( int_to_float ) elif is_negative(min_value): return floats(min_value=min_value, max_value=-0.0) | floats( min_value=0, max_value=max_value ) else: ub_int = float_to_int(max_value) lb_int = float_to_int(min_value) assert lb_int <= ub_int return integers(min_value=lb_int, max_value=ub_int).map( int_to_float ) elif min_value is not None: critical_values = [min_value, float(u'inf')] if is_negative(min_value): critical_values.append(-0.0) if min_value <= 0: critical_values.append(0.0) return FloatsFromBase( base=min_value, sign=1, ) | sampled_from(critical_values) else: assert max_value is not None critical_values = [max_value, float(u'-inf')] if max_value >= 0: critical_values.append(-0.0) if not is_negative(max_value): critical_values.append(0.0) return FloatsFromBase( base=max_value, sign=-1 ) | sampled_from(critical_values)
@given(floats(), floats(), integers()) def test_floats_are_in_range(x, y, s): assume(not (math.isnan(x) or math.isnan(y))) assume(not (math.isinf(x) or math.isinf(y))) x, y = sorted((x, y)) assume(x < y) @given(floats(x, y)) @seed(s) @settings(max_examples=10) def test_is_in_range(t): assert x <= t <= y try: test_is_in_range() except Unsatisfiable: assume(False) @fails_with(AssertionError) @given(NastyFloats()) def test_can_use_just_nasty(x): assert not math.isnan(x) @given(NastyFloats(allow_nan=False)) def test_nasty_filter_nan(x): assert not math.isnan(x)
def floats(min_value=None, max_value=None, allow_nan=None, allow_infinity=None): """Returns a strategy which generates floats. - If min_value is not None, all values will be >= min_value. - If max_value is not None, all values will be <= max_value. - If min_value or max_value is not None, it is an error to enable allow_nan. - If both min_value and max_value are not None, it is an error to enable allow_infinity. Where not explicitly ruled out by the bounds, all of infinity, -infinity and NaN are possible values generated by this strategy. """ if allow_nan is None: allow_nan = bool(min_value is None and max_value is None) elif allow_nan: if min_value is not None or max_value is not None: raise InvalidArgument( 'Cannot have allow_nan=%r, with min_value or max_value' % (allow_nan)) check_valid_bound(min_value, 'min_value') check_valid_bound(max_value, 'max_value') check_valid_interval(min_value, max_value, 'min_value', 'max_value') if min_value is not None: min_value = float(min_value) if max_value is not None: max_value = float(max_value) if min_value == float(u'-inf'): min_value = None if max_value == float(u'inf'): max_value = None if allow_infinity is None: allow_infinity = bool(min_value is None or max_value is None) elif allow_infinity: if min_value is not None and max_value is not None: raise InvalidArgument( 'Cannot have allow_infinity=%r, with both min_value and ' 'max_value' % (allow_infinity)) from hypothesis.searchstrategy.numbers import WrapperFloatStrategy, \ GaussianFloatStrategy, BoundedFloatStrategy, ExponentialFloatStrategy,\ JustIntFloats, NastyFloats, FullRangeFloats, \ FixedBoundedFloatStrategy if min_value is None and max_value is None: return WrapperFloatStrategy( GaussianFloatStrategy() | BoundedFloatStrategy() | ExponentialFloatStrategy() | JustIntFloats() | NastyFloats(allow_nan, allow_infinity) | FullRangeFloats(allow_nan, allow_infinity)) elif min_value is not None and max_value is not None: if min_value == max_value: return just(min_value) elif math.isinf(max_value - min_value): assert min_value < 0 and max_value > 0 return floats(min_value=0, max_value=max_value) | floats( min_value=min_value, max_value=0) elif count_between_floats(min_value, max_value) > 1000: critical_values = [ min_value, max_value, min_value + (max_value - min_value) / 2 ] if min_value <= 0 <= max_value: if not is_negative(max_value): critical_values.append(0.0) if is_negative(min_value): critical_values.append(-0.0) return FixedBoundedFloatStrategy( lower_bound=min_value, upper_bound=max_value) | sampled_from(critical_values) elif is_negative(max_value): assert is_negative(min_value) ub_int = float_to_int(max_value) lb_int = float_to_int(min_value) assert ub_int <= lb_int return integers(min_value=ub_int, max_value=lb_int).map(int_to_float) elif is_negative(min_value): return floats(min_value=min_value, max_value=-0.0) | floats( min_value=0, max_value=max_value) else: ub_int = float_to_int(max_value) lb_int = float_to_int(min_value) assert lb_int <= ub_int return integers(min_value=lb_int, max_value=ub_int).map(int_to_float) elif min_value is not None: critical_values = [min_value] if allow_infinity: critical_values.append(float(u'inf')) if is_negative(min_value): critical_values.append(-0.0) if min_value <= 0: critical_values.append(0.0) return (floats( allow_infinity=allow_infinity, allow_nan=False).map(lambda x: assume(not math.isnan( x)) and min_value + abs(x))) | sampled_from(critical_values) else: assert max_value is not None critical_values = [max_value] if allow_infinity: critical_values.append(float(u'-inf')) if max_value >= 0: critical_values.append(-0.0) if not is_negative(max_value): critical_values.append(0.0) return (floats( allow_infinity=allow_infinity, allow_nan=False).map(lambda x: assume(not math.isnan( x)) and max_value - abs(x))) | sampled_from(critical_values)