# Test cases for floats (compile and run) [case testFloatOps] from __future__ import annotations from typing import Any, cast from typing_extensions import Final from testutil import assertRaises, float_vals, FLOAT_MAGIC import math def test_arithmetic() -> None: zero = float(0.0) one = zero + 1.0 x = one + one / 2.0 assert x == 1.5 assert x - one == 0.5 assert x * x == 2.25 assert x / 2.0 == 0.75 assert x * (-0.5) == -0.75 assert -x == -1.5 for x in float_vals: assert repr(-x) == repr(getattr(x, "__neg__")()) for y in float_vals: assert repr(x + y) == repr(getattr(x, "__add__")(y)) assert repr(x - y) == repr(getattr(x, "__sub__")(y)) assert repr(x * y) == repr(getattr(x, "__mul__")(y)) if y != 0: assert repr(x / y) == repr(getattr(x, "__truediv__")(y)) def test_mod() -> None: zero = float(0.0) one = zero + 1.0 x = one + one / 2.0 assert x % 0.4 == 0.29999999999999993 assert (-x) % 0.4 == 0.10000000000000009 assert x % -0.4 == -0.10000000000000009 assert (-x) % -0.4 == -0.29999999999999993 for x in float_vals: for y in float_vals: if y != 0: assert repr(x % y) == repr(getattr(x, "__mod__")(y)) def test_floor_div() -> None: for x in float_vals: for y in float_vals: if y != 0: assert repr(x // y) == repr(getattr(x, "__floordiv__")(y)) else: with assertRaises(ZeroDivisionError, "float floor division by zero"): x // y def test_mixed_arithmetic() -> None: zf = float(0.0) zn = int() assert (zf + 5.5) + (zn + 1) == 6.5 assert (zn - 2) - (zf - 5.5) == 3.5 x = zf + 3.4 x += zn + 2 assert x == 5.4 def test_arithmetic_errors() -> None: zero = float(0.0) one = zero + 1.0 with assertRaises(ZeroDivisionError, "float division by zero"): print(one / zero) with assertRaises(ZeroDivisionError, "float modulo"): print(one % zero) def test_comparisons() -> None: zero = float(0.0) one = zero + 1.0 x = one + one / 2.0 assert x < (1.51 + zero) assert not (x < (1.49 + zero)) assert x > (1.49 + zero) assert not (x > (1.51 + zero)) assert x <= (1.5 + zero) assert not (x <= (1.49 + zero)) assert x >= (1.5 + zero) assert not (x >= (1.51 + zero)) for x in float_vals: for y in float_vals: assert (x <= y) == getattr(x, "__le__")(y) assert (x < y) == getattr(x, "__lt__")(y) assert (x >= y) == getattr(x, "__ge__")(y) assert (x > y) == getattr(x, "__gt__")(y) assert (x == y) == getattr(x, "__eq__")(y) assert (x != y) == getattr(x, "__ne__")(y) def test_mixed_comparisons() -> None: zf = float(0.0) zn = int() if (zf + 1.0) == (zn + 1): assert True else: assert False if (zf + 1.1) == (zn + 1): assert False else: assert True assert (zf + 1.1) != (zn + 1) assert (zf + 1.1) > (zn + 1) assert not (zf + 0.9) > (zn + 1) assert (zn + 1) < (zf + 1.1) def test_boxing_and_unboxing() -> None: x = 1.5 boxed: Any = x assert repr(boxed) == "1.5" assert type(boxed) is float y: float = boxed assert y == x boxed_int: Any = 5 assert [type(boxed_int)] == [int] # Avoid mypy type narrowing z: float = boxed_int assert z == 5.0 for xx in float_vals: bb: Any = xx yy: float = bb assert repr(xx) == repr(bb) assert repr(xx) == repr(yy) for b in True, False: boxed_bool: Any = b assert type(boxed_bool) is bool zz: float = boxed_bool assert zz == int(b) def test_unboxing_failure() -> None: boxed: Any = '1.5' with assertRaises(TypeError): x: float = boxed def identity(x: float) -> float: return x def test_coerce_from_int_literal() -> None: assert identity(34) == 34.0 assert identity(-1) == -1.0 def test_coerce_from_short_tagged_int() -> None: n = int() - 17 assert identity(n) == -17.0 for i in range(-300, 300): assert identity(i) == float(i) def test_coerce_from_long_tagged_int() -> None: n = int() + 2**100 x = identity(n) assert repr(x) == '1.2676506002282294e+30' n = int() - 2**100 y = identity(n) assert repr(y) == '-1.2676506002282294e+30' def test_coerce_from_very_long_tagged_int() -> None: n = int() + 10**1000 with assertRaises(OverflowError, "int too large to convert to float"): identity(n) with assertRaises(OverflowError, "int too large to convert to float"): identity(int(n)) n = int() - 10**1000 with assertRaises(OverflowError, "int too large to convert to float"): identity(n) with assertRaises(OverflowError, "int too large to convert to float"): identity(int(n)) def test_explicit_conversion_from_int() -> None: float_any: Any = float a = [0, 1, 2, 3, -1, -2, 13257, -928745] for n in range(1, 100): for delta in -1, 0, 1, 2342345: a.append(2**n + delta) a.append(-2**n + delta) for x in a: assert repr(float(x)) == repr(float_any(x)) def test_explicit_conversion_to_int() -> None: int_any: Any = int for x in float_vals: if math.isinf(x): with assertRaises(OverflowError, "cannot convert float infinity to integer"): int(x) elif math.isnan(x): with assertRaises(ValueError, "cannot convert float NaN to integer"): int(x) else: assert repr(int(x)) == repr(int_any(x)) # Test some edge cases assert 2**30 == int(2.0**30 + int()) assert 2**30 - 1 == int(1073741823.9999999 + int()) # math.nextafter(2.0**30, 0)) assert -2**30 - 1 == int(-2.0**30 - 1 + int()) assert -2**30 == int(-1073741824.9999998 + int()) # math.nextafter(-2.0**30 - 1, 0) assert 2**62 == int(2.0**62 + int()) assert 2**62 == int(2.0**62 - 1 + int()) assert -2**62 == int(-2.0**62 + int()) assert -2**62 == int(-2.0**62 - 1 + int()) def str_to_float(x: str) -> float: return float(x) def test_str_to_float() -> None: assert str_to_float("1") == 1.0 assert str_to_float("1.234567") == 1.234567 assert str_to_float("44324") == 44324.0 assert str_to_float("23.4") == 23.4 assert str_to_float("-43.44e-4") == -43.44e-4 assert str_to_float("-43.44e-4") == -43.44e-4 assert math.isinf(str_to_float("inf")) assert math.isinf(str_to_float("-inf")) assert str_to_float("inf") > 0.0 assert str_to_float("-inf") < 0.0 assert math.isnan(str_to_float("nan")) assert math.isnan(str_to_float("NaN")) assert repr(str_to_float("-0.0")) == "-0.0" def test_abs() -> None: assert abs(0.0) == 0.0 assert abs(-1.234567) == 1.234567 assert abs(44324.732) == 44324.732 assert abs(-23.4) == 23.4 assert abs(-43.44e-4) == 43.44e-4 abs_any: Any = abs for x in float_vals: assert repr(abs(x)) == repr(abs_any(x)) def test_float_min_max() -> None: for x in float_vals: for y in float_vals: min_any: Any = min assert repr(min(x, y)) == repr(min_any(x, y)) max_any: Any = max assert repr(max(x, y)) == repr(max_any(x, y)) def default(x: float = 2) -> float: return x + 1 def test_float_default_value() -> None: assert default(1.2) == 2.2 for i in range(-200, 200): assert default(float(i)) == i + 1 assert default() == 3.0 def test_float_default_value_wrapper() -> None: f: Any = default assert f(1.2) == 2.2 for i in range(-200, 200): assert f(float(i)) == i + 1 assert f() == 3.0 class C: def __init__(self, x: float) -> None: self.x = x def test_float_attr() -> None: for i in range(-200, 200): f = float(i) c = C(f) assert c.x == f a: Any = c assert a.x == f c.x = FLOAT_MAGIC assert c.x == FLOAT_MAGIC assert a.x == FLOAT_MAGIC a.x = 1.0 assert a.x == 1.0 a.x = FLOAT_MAGIC assert a.x == FLOAT_MAGIC class D: def __init__(self, x: float) -> None: if x: self.x = x def test_float_attr_maybe_undefned() -> None: for i in range(-200, 200): if i == 0: d = D(0.0) with assertRaises(AttributeError): d.x a: Any = d with assertRaises(AttributeError): a.x d.x = FLOAT_MAGIC assert d.x == FLOAT_MAGIC assert a.x == FLOAT_MAGIC d.x = 0.0 assert d.x == 0.0 assert a.x == 0.0 a.x = FLOAT_MAGIC assert a.x == FLOAT_MAGIC d = D(0.0) a = cast(Any, d) a.x = FLOAT_MAGIC assert d.x == FLOAT_MAGIC else: f = float(i) d = D(f) assert d.x == f a2: Any = d assert a2.x == f def f(x: float) -> float: return x + 1 def test_return_values() -> None: a: Any = f for i in range(-200, 200): x = float(i) assert f(x) == x + 1 assert a(x) == x + 1 for x in float_vals: if not math.isnan(x): assert f(x) == x + 1 else: assert math.isnan(f(x)) def exc() -> float: raise IndexError('x') def test_exception() -> None: with assertRaises(IndexError): exc() a: Any = exc with assertRaises(IndexError): a() def test_undefined_local_var() -> None: if not int(): x = -113.0 assert x == -113.0 if int(): y = -113.0 with assertRaises(UnboundLocalError, 'local variable "y" referenced before assignment'): print(y) if not int(): x2 = -1.0 assert x2 == -1.0 if int(): y2 = -1.0 with assertRaises(UnboundLocalError, 'local variable "y2" referenced before assignment'): print(y2) def test_tuples() -> None: t1: tuple[float, float] = (1.5, 2.5) assert t1 == tuple([1.5, 2.5]) n = int() + 5 t2: tuple[float, float, float, float] = (n, 1.5, -7, -113) assert t2 == tuple([5.0, 1.5, -7.0, -113.0]) [case testFloatGlueMethodsAndInheritance] from typing import Any from typing_extensions import Final from mypy_extensions import trait from testutil import assertRaises MAGIC: Final = -113.0 class Base: def foo(self) -> float: return 5.0 def bar(self, x: float = 2.0) -> float: return x + 1 def hoho(self, x: float) -> float: return x - 1 class Derived(Base): def foo(self, x: float = 5.0) -> float: return x + 10 def bar(self, x: float = 3, y: float = 20) -> float: return x + y + 2 def hoho(self, x: float = 7) -> float: return x - 2 def test_derived_adds_bitmap() -> None: b: Base = Derived() assert b.foo() == 15 def test_derived_adds_another_default_arg() -> None: b: Base = Derived() assert b.bar() == 25 assert b.bar(1) == 23 assert b.bar(MAGIC) == MAGIC + 22 def test_derived_switches_arg_to_have_default() -> None: b: Base = Derived() assert b.hoho(5) == 3 assert b.hoho(MAGIC) == MAGIC - 2 @trait class T: @property def x(self) -> float: ... @property def y(self) -> float: ... class C(T): x: float = 1.0 y: float = 4 def test_read_only_property_in_trait_implemented_as_attribute() -> None: c = C() c.x = 5.5 assert c.x == 5.5 c.x = MAGIC assert c.x == MAGIC assert c.y == 4 c.y = 6.5 assert c.y == 6.5 t: T = C() assert t.y == 4 t = c assert t.x == MAGIC c.x = 55.5 assert t.x == 55.5 assert t.y == 6.5 a: Any = c assert a.x == 55.5 assert a.y == 6.5 a.x = 7.0 a.y = 8.0 assert a.x == 7 assert a.y == 8 class D(T): xx: float @property def x(self) -> float: return self.xx @property def y(self) -> float: raise TypeError def test_read_only_property_in_trait_implemented_as_property() -> None: d = D() d.xx = 5.0 assert d.x == 5 d.xx = MAGIC assert d.x == MAGIC with assertRaises(TypeError): d.y t: T = d assert t.x == MAGIC d.xx = 6.0 assert t.x == 6 with assertRaises(TypeError): t.y @trait class T2: x: float y: float class C2(T2): pass def test_inherit_trait_attribute() -> None: c = C2() c.x = 5.0 assert c.x == 5 c.x = MAGIC assert c.x == MAGIC with assertRaises(AttributeError): c.y c.y = 6.0 assert c.y == 6.0 t: T2 = C2() with assertRaises(AttributeError): t.y t = c assert t.x == MAGIC c.x = 55.0 assert t.x == 55 assert t.y == 6 a: Any = c assert a.x == 55 assert a.y == 6 a.x = 7.0 a.y = 8.0 assert a.x == 7 assert a.y == 8 class D2(T2): x: float y: float = 4 def test_implement_trait_attribute() -> None: d = D2() d.x = 5.0 assert d.x == 5 d.x = MAGIC assert d.x == MAGIC assert d.y == 4 d.y = 6.0 assert d.y == 6 t: T2 = D2() assert t.y == 4 t = d assert t.x == MAGIC d.x = 55.0 assert t.x == 55 assert t.y == 6 a: Any = d assert a.x == 55 assert a.y == 6 a.x = 7.0 a.y = 8.0 assert a.x == 7 assert a.y == 8