From 18a264882b7bb3e5453241bcafe61f2a3a8ee4c4 Mon Sep 17 00:00:00 2001 From: CPython Developers <> Date: Fri, 13 Feb 2026 18:03:21 +0900 Subject: [PATCH 1/2] Update test_float from v3.14.3 --- Lib/test/test_float.py | 169 ++++++++++++++++++++++++++++++++--------- 1 file changed, 131 insertions(+), 38 deletions(-) diff --git a/Lib/test/test_float.py b/Lib/test/test_float.py index 4ca4103f4..635cfbd8b 100644 --- a/Lib/test/test_float.py +++ b/Lib/test/test_float.py @@ -35,6 +35,28 @@ class FloatSubclass(float): class OtherFloatSubclass(float): pass +class MyIndex: + def __init__(self, value): + self.value = value + + def __index__(self): + return self.value + +class MyInt: + def __init__(self, value): + self.value = value + + def __int__(self): + return self.value + +class FloatLike: + def __init__(self, value): + self.value = value + + def __float__(self): + return self.value + + class GeneralFloatCases(unittest.TestCase): def test_float(self): @@ -184,10 +206,6 @@ class GeneralFloatCases(unittest.TestCase): def test_floatconversion(self): # Make sure that calls to __float__() work properly - class Foo1(object): - def __float__(self): - return 42. - class Foo2(float): def __float__(self): return 42. @@ -209,52 +227,35 @@ class GeneralFloatCases(unittest.TestCase): def __float__(self): return float(str(self)) + 1 - self.assertEqual(float(Foo1()), 42.) + self.assertEqual(float(FloatLike(42.)), 42.) self.assertEqual(float(Foo2()), 42.) with self.assertWarns(DeprecationWarning): self.assertEqual(float(Foo3(21)), 42.) self.assertRaises(TypeError, float, Foo4(42)) self.assertEqual(float(FooStr('8')), 9.) - class Foo5: - def __float__(self): - return "" - self.assertRaises(TypeError, time.sleep, Foo5()) + self.assertRaises(TypeError, time.sleep, FloatLike("")) # Issue #24731 - class F: - def __float__(self): - return OtherFloatSubclass(42.) + f = FloatLike(OtherFloatSubclass(42.)) with self.assertWarns(DeprecationWarning): - self.assertEqual(float(F()), 42.) + self.assertEqual(float(f), 42.) with self.assertWarns(DeprecationWarning): - self.assertIs(type(float(F())), float) + self.assertIs(type(float(f)), float) with self.assertWarns(DeprecationWarning): - self.assertEqual(FloatSubclass(F()), 42.) + self.assertEqual(FloatSubclass(f), 42.) with self.assertWarns(DeprecationWarning): - self.assertIs(type(FloatSubclass(F())), FloatSubclass) - - class MyIndex: - def __init__(self, value): - self.value = value - def __index__(self): - return self.value + self.assertIs(type(FloatSubclass(f)), FloatSubclass) self.assertEqual(float(MyIndex(42)), 42.0) self.assertRaises(OverflowError, float, MyIndex(2**2000)) - - class MyInt: - def __int__(self): - return 42 - - self.assertRaises(TypeError, float, MyInt()) + self.assertRaises(TypeError, float, MyInt(42)) def test_keyword_args(self): with self.assertRaisesRegex(TypeError, 'keyword argument'): float(x='3.14') - # TODO: RUSTPYTHON - @unittest.expectedFailure + @unittest.expectedFailure # TODO: RUSTPYTHON; TypeError: Unexpected keyword argument newarg def test_keywords_in_subclass(self): class subclass(float): pass @@ -282,6 +283,39 @@ class GeneralFloatCases(unittest.TestCase): self.assertEqual(float(u), 2.5) self.assertEqual(u.newarg, 3) + def assertEqualAndType(self, actual, expected_value, expected_type): + self.assertEqual(actual, expected_value) + self.assertIs(type(actual), expected_type) + + @unittest.expectedFailure # TODO: RUSTPYTHON; AttributeError: type object 'float' has no attribute 'from_number' + def test_from_number(self, cls=float): + def eq(actual, expected): + self.assertEqual(actual, expected) + self.assertIs(type(actual), cls) + + eq(cls.from_number(3.14), 3.14) + eq(cls.from_number(314), 314.0) + eq(cls.from_number(OtherFloatSubclass(3.14)), 3.14) + eq(cls.from_number(FloatLike(3.14)), 3.14) + eq(cls.from_number(MyIndex(314)), 314.0) + + x = cls.from_number(NAN) + self.assertTrue(x != x) + self.assertIs(type(x), cls) + if cls is float: + self.assertIs(cls.from_number(NAN), NAN) + + self.assertRaises(TypeError, cls.from_number, '3.14') + self.assertRaises(TypeError, cls.from_number, b'3.14') + self.assertRaises(TypeError, cls.from_number, 3.14j) + self.assertRaises(TypeError, cls.from_number, MyInt(314)) + self.assertRaises(TypeError, cls.from_number, {}) + self.assertRaises(TypeError, cls.from_number) + + @unittest.expectedFailure # TODO: RUSTPYTHON; AttributeError: type object 'FloatSubclass' has no attribute 'from_number' + def test_from_number_subclass(self): + self.test_from_number(FloatSubclass) + def test_is_integer(self): self.assertFalse((1.1).is_integer()) self.assertTrue((1.).is_integer()) @@ -400,9 +434,8 @@ class GeneralFloatCases(unittest.TestCase): self.assertEqualAndEqualSign(mod(1e-100, -1.0), -1.0) self.assertEqualAndEqualSign(mod(1.0, -1.0), -0.0) + @unittest.expectedFailure # TODO: RUSTPYTHON; TypeError: must be real number, not complex @support.requires_IEEE_754 - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_float_pow(self): # test builtin pow and ** operator for IEEE 754 special cases. # Special cases taken from section F.9.4.4 of the C99 specification @@ -622,6 +655,24 @@ class GeneralFloatCases(unittest.TestCase): value = F('nan') self.assertEqual(hash(value), object.__hash__(value)) + def test_issue_gh143006(self): + # When comparing negative non-integer float and int with the + # same number of bits in the integer part, __neg__() in the + # int subclass returning not an int caused an assertion error. + class EvilInt(int): + def __neg__(self): + return "" + + i = -1 << 50 + f = float(i) - 0.5 + i = EvilInt(i) + self.assertFalse(f == i) + self.assertTrue(f != i) + self.assertTrue(f < i) + self.assertTrue(f <= i) + self.assertFalse(f > i) + self.assertFalse(f >= i) + @unittest.skipUnless(hasattr(float, "__getformat__"), "requires __getformat__") class FormatFunctionsTestCase(unittest.TestCase): @@ -727,6 +778,44 @@ class FormatTestCase(unittest.TestCase): self.assertEqual(format(INF, 'f'), 'inf') self.assertEqual(format(INF, 'F'), 'INF') + # thousands separators + x = 123_456.123_456 + self.assertEqual(format(x, '_f'), '123_456.123456') + self.assertEqual(format(x, ',f'), '123,456.123456') + self.assertEqual(format(x, '._f'), '123456.123_456') + self.assertEqual(format(x, '.,f'), '123456.123,456') + self.assertEqual(format(x, '_._f'), '123_456.123_456') + self.assertEqual(format(x, ',.,f'), '123,456.123,456') + self.assertEqual(format(x, '.10_f'), '123456.123_456_000_0') + self.assertEqual(format(x, '.10,f'), '123456.123,456,000,0') + self.assertEqual(format(x, '>21._f'), ' 123456.123_456') + self.assertEqual(format(x, '<21._f'), '123456.123_456 ') + self.assertEqual(format(x, '+.11_e'), '+1.234_561_234_56e+05') + self.assertEqual(format(x, '+.11,e'), '+1.234,561,234,56e+05') + self.assertEqual(format(x, '021_._f'), '0_000_123_456.123_456') + self.assertEqual(format(x, '020_._f'), '0_000_123_456.123_456') + self.assertEqual(format(x, '+021_._f'), '+0_000_123_456.123_456') + self.assertEqual(format(x, '21_._f'), ' 123_456.123_456') + self.assertEqual(format(x, '>021_._f'), '000000123_456.123_456') + self.assertEqual(format(x, '<021_._f'), '123_456.123_456000000') + self.assertEqual(format(x, '023_.10_f'), '0_123_456.123_456_000_0') + self.assertEqual(format(x, '022_.10_f'), '0_123_456.123_456_000_0') + self.assertEqual(format(x, '+023_.10_f'), '+0_123_456.123_456_000_0') + self.assertEqual(format(x, '023_.9_f'), '000_123_456.123_456_000') + self.assertEqual(format(x, '021_._e'), '0_000_001.234_561e+05') + self.assertEqual(format(x, '020_._e'), '0_000_001.234_561e+05') + self.assertEqual(format(x, '+021_._e'), '+0_000_001.234_561e+05') + self.assertEqual(format(x, '023_.10_e'), '0_001.234_561_234_6e+05') + self.assertEqual(format(x, '022_.10_e'), '0_001.234_561_234_6e+05') + self.assertEqual(format(x, '023_.9_e'), '000_001.234_561_235e+05') + + self.assertRaises(ValueError, format, x, '._6f') + self.assertRaises(ValueError, format, x, '.,_f') + self.assertRaises(ValueError, format, x, '.6,_f') + self.assertRaises(ValueError, format, x, '.6_,f') + self.assertRaises(ValueError, format, x, '.6_n') + self.assertRaises(ValueError, format, x, '.6,n') + @support.requires_IEEE_754 @unittest.skipUnless(sys.float_repr_style == 'short', "applies only when using short float repr style") @@ -877,10 +966,9 @@ class RoundTestCase(unittest.TestCase, FloatsAreIdenticalMixin): self.assertRaises(OverflowError, round, 1.6e308, -308) self.assertRaises(OverflowError, round, -1.7e308, -308) + @unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: 56294995342131.51 != 56294995342131.5 @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short', "applies only when using short float repr style") - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_previous_round_bugs(self): # particular cases that have occurred in bug reports self.assertEqual(round(562949953421312.5, 1), @@ -897,10 +985,9 @@ class RoundTestCase(unittest.TestCase, FloatsAreIdenticalMixin): self.assertEqual(round(85.0, -1), 80.0) self.assertEqual(round(95.0, -1), 100.0) + @unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: 0.01 != 0.0 @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short', "applies only when using short float repr style") - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_matches_float_format(self): # round should give the same results as float formatting for i in range(500): @@ -962,6 +1049,13 @@ class RoundTestCase(unittest.TestCase, FloatsAreIdenticalMixin): self.assertEqual(x, 2) self.assertIsInstance(x, int) + @support.cpython_only + def test_round_with_none_arg_direct_call(self): + for val in [(1.0).__round__(None), + round(1.0), + round(1.0, None)]: + self.assertEqual(val, 1) + self.assertIs(type(val), int) # Beginning with Python 2.6 float has cross platform compatible # ways to create and represent inf and nan @@ -1171,8 +1265,7 @@ class HexFloatTestCase(FloatsAreIdenticalMixin, unittest.TestCase): self.identical(got, expected) - # TODO: RUSTPYTHON - @unittest.expectedFailure + @unittest.expectedFailure # TODO: RUSTPYTHON; ValueError: invalid hexadecimal floating-point string def test_from_hex(self): MIN = self.MIN MAX = self.MAX From fb1514b6e80fbbeb4fbd95c405e0c33c0654d4c1 Mon Sep 17 00:00:00 2001 From: Lee Dogeon Date: Fri, 13 Feb 2026 18:05:39 +0900 Subject: [PATCH 2/2] Mark failing tests Co-Authored-By: Claude Opus 4.6 --- Lib/test/test_float.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Lib/test/test_float.py b/Lib/test/test_float.py index 635cfbd8b..09bc50e17 100644 --- a/Lib/test/test_float.py +++ b/Lib/test/test_float.py @@ -727,6 +727,7 @@ class IEEEFormatTestCase(unittest.TestCase): class FormatTestCase(unittest.TestCase): + @unittest.expectedFailure # TODO: RUSTPYTHON; ValueError: Invalid format specifier def test_format(self): # these should be rewritten to use both format(x, spec) and # x.__format__(spec)