| # Test cases for floats (compile and run) |
| |
| [case testFloatOps] |
| from __future__ import annotations |
| from typing import Final, Any, cast |
| 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 Final, Any |
| |
| 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 |