From 895108843db743e831b15334bd60a13a58eba5b7 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Wed, 21 Jan 2026 01:39:05 +0100 Subject: [PATCH 01/23] Add support for unicode MINUS SIGN in `int`, `float` and `complex` --- Objects/unicodeobject.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index fdcbcf51cb62c2..4e22bb41fb4feb 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -9475,6 +9475,9 @@ _PyUnicode_TransformDecimalAndSpaceToASCII(PyObject *unicode) else if (Py_UNICODE_ISSPACE(ch)) { out[i] = ' '; } + else if (ch == 0x2212) { /* MINUS SIGN */ + out[i] = '-'; + } else { int decimal = Py_UNICODE_TODECIMAL(ch); if (decimal < 0) { From d3f7c80c4811df38cba3fcb25cf867ba0dcd7b1e Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sat, 14 Feb 2026 00:39:08 +0100 Subject: [PATCH 02/23] Add some test coverage Some tests are failing! --- Lib/test/test_complex.py | 9 +++++++++ Lib/test/test_float.py | 4 ++++ Lib/test/test_long.py | 4 +++- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_complex.py b/Lib/test/test_complex.py index 0c7e7341f13d4e..9134731f49c2ff 100644 --- a/Lib/test/test_complex.py +++ b/Lib/test/test_complex.py @@ -669,18 +669,22 @@ def check(z, x, y): check(complex("1"), 1.0, 0.0) check(complex("1j"), 0.0, 1.0) check(complex("-1"), -1.0, 0.0) + check(complex("\N{MINUS SIGN}1"), -1.0, 0.0) check(complex("+1"), 1.0, 0.0) check(complex("1+2j"), 1.0, 2.0) check(complex("(1+2j)"), 1.0, 2.0) check(complex("(1.5+4.25j)"), 1.5, 4.25) check(complex("4.25+1J"), 4.25, 1.0) check(complex(" ( +4.25-6J )"), 4.25, -6.0) + check(complex(" ( +4.25\N{MINUS SIGN}6J )"), 4.25, -6.0) check(complex(" ( +4.25-J )"), 4.25, -1.0) + check(complex(" ( +4.25\N{MINUS SIGN}J )"), 4.25, -1.0) check(complex(" ( +4.25+j )"), 4.25, 1.0) check(complex("J"), 0.0, 1.0) check(complex("( j )"), 0.0, 1.0) check(complex("+J"), 0.0, 1.0) check(complex("( -j)"), 0.0, -1.0) + check(complex("( \N{MINUS SIGN}j)"), 0.0, -1.0) check(complex('1-1j'), 1.0, -1.0) check(complex('1J'), 0.0, 1.0) @@ -690,6 +694,7 @@ def check(z, x, y): check(complex('-1e-500+1e-500j'), -0.0, 0.0) check(complex('1e-500-1e-500j'), 0.0, -0.0) check(complex('-1e-500-1e-500j'), -0.0, -0.0) + check(complex('\N{MINUS SIGN}1e\N{MINUS SIGN}500\N{MINUS SIGN}1e\N{MINUS SIGN}500j'), -0.0, -0.0) # SF bug 543840: complex(string) accepts strings with \0 # Fixed in 2.3. @@ -700,6 +705,8 @@ def check(z, x, y): self.assertRaises(ValueError, complex, "1+") self.assertRaises(ValueError, complex, "1+1j+1j") self.assertRaises(ValueError, complex, "--") + self.assertRaises(ValueError, complex, "-\N{MINUS SIGN}") + self.assertRaises(ValueError, complex, "\N{MINUS SIGN}\N{MINUS SIGN}") self.assertRaises(ValueError, complex, "(1+2j") self.assertRaises(ValueError, complex, "1+2j)") self.assertRaises(ValueError, complex, "1+(2j)") @@ -726,7 +733,9 @@ def test_constructor_negative_nans_from_string(self): self.assertEqual(copysign(1., complex("-nan").real), -1.) self.assertEqual(copysign(1., complex("-nanj").imag), -1.) self.assertEqual(copysign(1., complex("-nan-nanj").real), -1.) + self.assertEqual(copysign(1., complex("-nan\N{MINUS SIGN}nanj").real), -1.) self.assertEqual(copysign(1., complex("-nan-nanj").imag), -1.) + self.assertEqual(copysign(1., complex("\N{MINUS SIGN}nan\N{MINUS SIGN}nanj").imag), -1.) def test_underscores(self): # check underscores diff --git a/Lib/test/test_float.py b/Lib/test/test_float.py index c03b0a09f71889..8c8710e4bce5f6 100644 --- a/Lib/test/test_float.py +++ b/Lib/test/test_float.py @@ -68,12 +68,16 @@ def test_float(self): self.assertRaises(ValueError, float, " +0x3.p-1 ") self.assertRaises(ValueError, float, "++3.14") self.assertRaises(ValueError, float, "+-3.14") + self.assertRaises(ValueError, float, "+\N{MINUS SIGN}3.14") self.assertRaises(ValueError, float, "-+3.14") self.assertRaises(ValueError, float, "--3.14") + self.assertRaises(ValueError, float, "-\N{MINUS SIGN}3.14") + self.assertRaises(ValueError, float, "\N{MINUS SIGN}\N{MINUS SIGN}3.14") self.assertRaises(ValueError, float, ".nan") self.assertRaises(ValueError, float, "+.inf") self.assertRaises(ValueError, float, ".") self.assertRaises(ValueError, float, "-.") + self.assertRaises(ValueError, float, "\N{MINUS SIGN}.") self.assertRaises(TypeError, float, {}) self.assertRaisesRegex(TypeError, "not 'dict'", float, {}) # Lone surrogate diff --git a/Lib/test/test_long.py b/Lib/test/test_long.py index b48a8812a1a2d1..b3ee0b7792c002 100644 --- a/Lib/test/test_long.py +++ b/Lib/test/test_long.py @@ -328,7 +328,7 @@ def test_long(self): ('1' + '0'*100, 10**100) ] for s, v in LL: - for sign in "", "+", "-": + for sign in "", "+", "-", "\N{MINUS SIGN}": for prefix in "", " ", "\t", " \t\t ": ss = prefix + sign + s vv = v @@ -360,9 +360,11 @@ def test_long(self): self.assertEqual(int('0', 0), 0) self.assertEqual(int('+0', 0), 0) self.assertEqual(int('-0', 0), 0) + self.assertEqual(int('\N{MINUS SIGN}0', 0), 0) self.assertEqual(int('00', 0), 0) self.assertRaises(ValueError, int, '08', 0) self.assertRaises(ValueError, int, '-012395', 0) + self.assertRaises(ValueError, int, '\N{MINUS SIGN}012395', 0) # invalid bases invalid_bases = [-909, From 3fe1b8215541129d8e10104926593514bc3fe0b1 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sat, 14 Feb 2026 02:51:41 +0100 Subject: [PATCH 03/23] Fix test --- Lib/test/test_long.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_long.py b/Lib/test/test_long.py index b3ee0b7792c002..188638fe1474fe 100644 --- a/Lib/test/test_long.py +++ b/Lib/test/test_long.py @@ -332,7 +332,7 @@ def test_long(self): for prefix in "", " ", "\t", " \t\t ": ss = prefix + sign + s vv = v - if sign == "-" and v is not ValueError: + if sign in ("-", "\N{MINUS SIGN}") and v is not ValueError: vv = -v try: self.assertEqual(int(ss), vv) From 973e191981da14d9901d32028b01432ff1da56ee Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sat, 14 Feb 2026 03:05:24 +0100 Subject: [PATCH 04/23] Add news entry --- .../2026-02-14-03-03-07.gh-issue-144087.KT9kaM.rst | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-14-03-03-07.gh-issue-144087.KT9kaM.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-14-03-03-07.gh-issue-144087.KT9kaM.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-14-03-03-07.gh-issue-144087.KT9kaM.rst new file mode 100644 index 00000000000000..9d36e54f9d9c18 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-14-03-03-07.gh-issue-144087.KT9kaM.rst @@ -0,0 +1,3 @@ +:class:`int`, :class:`float` and :class:`complex` constructors now support +strings with unicode MINUS SIGN ``−`` (U+2212) as an alternative to ASCII +HYPHEN-SIGN ``-`` (U+002D). Contributed by Bartosz Sławecki. From 2695c0685eb599590109751a846c9c8efb63fcc0 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sat, 14 Feb 2026 03:13:43 +0100 Subject: [PATCH 05/23] Add C API test coverage (only `test_long_fromunicodeobject`) - `CAPIFloatTest.test_fromstring` doesn't test for minus signs - I can't find `complex` C API tests --- Lib/test/test_capi/test_long.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Lib/test/test_capi/test_long.py b/Lib/test/test_capi/test_long.py index d3156645eeec2d..a9389b1b533780 100644 --- a/Lib/test/test_capi/test_long.py +++ b/Lib/test/test_capi/test_long.py @@ -143,7 +143,9 @@ def test_long_fromunicodeobject(self): self.assertEqual(fromunicodeobject('0xcafe', 0), 0xcafe) self.assertRaises(ValueError, fromunicodeobject, 'cafe', 0) self.assertEqual(fromunicodeobject('-123', 10), -123) + self.assertEqual(fromunicodeobject('\N{MINUS SIGN}123', 10), -123) self.assertEqual(fromunicodeobject(' -123 ', 10), -123) + self.assertEqual(fromunicodeobject(' \N{MINUS SIGN}123 ', 10), -123) self.assertEqual(fromunicodeobject('1_23', 10), 123) self.assertRaises(ValueError, fromunicodeobject, '- 123', 10) self.assertRaises(ValueError, fromunicodeobject, '', 10) From cf0324a3ef205bbe07686e1aee10513671d4c0a6 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sat, 14 Feb 2026 03:28:43 +0100 Subject: [PATCH 06/23] Use `:func:` in news entry for better display --- .../2026-02-14-03-03-07.gh-issue-144087.KT9kaM.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-14-03-03-07.gh-issue-144087.KT9kaM.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-14-03-03-07.gh-issue-144087.KT9kaM.rst index 9d36e54f9d9c18..9a7b420eca105e 100644 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-14-03-03-07.gh-issue-144087.KT9kaM.rst +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-14-03-03-07.gh-issue-144087.KT9kaM.rst @@ -1,3 +1,3 @@ -:class:`int`, :class:`float` and :class:`complex` constructors now support -strings with unicode MINUS SIGN ``−`` (U+2212) as an alternative to ASCII +:func:`int`, :func:`float` and :func:`complex` now support strings +with unicode MINUS SIGN ``−`` (U+2212) as an alternative to ASCII HYPHEN-SIGN ``-`` (U+002D). Contributed by Bartosz Sławecki. From 3855919a5ce7e4dc7fd65d558d99aca4197c89e3 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sat, 14 Feb 2026 03:30:05 +0100 Subject: [PATCH 07/23] Update `int` docs --- Doc/library/functions.rst | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index cd819b8d06480a..6b8878bb8f3306 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -1036,8 +1036,9 @@ are always available. They are listed here in alphabetical order. If the argument is not a number or if *base* is given, then it must be a string, :class:`bytes`, or :class:`bytearray` instance representing an integer - in radix *base*. Optionally, the string can be preceded by ``+`` or ``-`` - (with no space in between), have leading zeros, be surrounded by whitespace, + in radix *base*. Optionally, the string can be directly preceded (with no whitespaces + in between) by ASCII plus sign ``+``, ASCII hyphen minus ``-`` or Unicode minus sign + ``−`` (U+2212), have leading zeros, be surrounded by whitespace, and have single underscores interspersed between digits. A base-n integer string contains digits, each representing a value from 0 to @@ -1080,6 +1081,10 @@ are always available. They are listed here in alphabetical order. .. versionchanged:: 3.14 :func:`int` no longer delegates to the :meth:`~object.__trunc__` method. + .. versionchanged:: 3.15 + :func:`int` now supports Unicode minus sign ``−`` (U+2212) as an alternative + to ASCII hyphen minus ``-`` for denoting negative integers. + .. function:: isinstance(object, classinfo, /) Return ``True`` if the *object* argument is an instance of the *classinfo* From ae6cd6cc7052a86d5ebbd31c1b88f451b19a27ce Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sat, 14 Feb 2026 03:33:02 +0100 Subject: [PATCH 08/23] Update `float` docs --- Doc/library/functions.rst | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 6b8878bb8f3306..dc7b7665de6f28 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -781,7 +781,8 @@ are always available. They are listed here in alphabetical order. If the argument is a string, it should contain a decimal number, optionally preceded by a sign, and optionally embedded in whitespace. The optional - sign may be ``'+'`` or ``'-'``; a ``'+'`` sign has no effect on the value + sign may be ``'+'`` (ASCII plus sign), ``'-'`` (ASCII hyphen minus) or ``−`` + (Unicode minus sign, U+2212); a ``'+'`` sign has no effect on the value produced. The argument may also be a string representing a NaN (not-a-number), or positive or negative infinity. More precisely, the input must conform to the :token:`~float:floatvalue` @@ -827,6 +828,10 @@ are always available. They are listed here in alphabetical order. .. versionchanged:: 3.8 Falls back to :meth:`~object.__index__` if :meth:`~object.__float__` is not defined. + .. versionchanged:: 3.15 + Added support for Unicode minus sign ``−`` (U+2212) as an alternative to ASCII + hyphen minus ``-`` for denoting negative floats. + .. index:: single: __format__ From 4a78b3ab66aed8c2338de96b7338f1d5e3c4af1a Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sat, 14 Feb 2026 03:35:11 +0100 Subject: [PATCH 09/23] Update `complex` docs --- Doc/library/functions.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index dc7b7665de6f28..d49f4862180f96 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -417,7 +417,7 @@ are always available. They are listed here in alphabetical order. parts (the sign of the imaginary part is mandatory in this case). The string can optionally be surrounded by whitespaces and the round parentheses ``'('`` and ``')'``, which are ignored. - The string must not contain whitespace between ``'+'``, ``'-'``, the + The string must not contain whitespace between ``'+'``, ``'-'``, ``'−'`` (U+2212), the ``'j'`` or ``'J'`` suffix, and the decimal number. For example, ``complex('1+2j')`` is fine, but ``complex('1 + 2j')`` raises :exc:`ValueError`. @@ -466,6 +466,10 @@ are always available. They are listed here in alphabetical order. Passing a complex number as the *real* or *imag* argument is now deprecated; it should only be passed as a single positional argument. + .. versionchanged:: 3.15 + Unicode minus sign ``'−'`` (U+2212) can be now used as an alternative to ASCII + hyphen minus ``'-'`` for denoting negative sign. + .. function:: delattr(object, name, /) From f233ebd2e0f83497a6f8a7651fc1898a752f3f4d Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sat, 14 Feb 2026 03:40:09 +0100 Subject: [PATCH 10/23] Simplify complex `complex` docs --- Doc/library/functions.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index d49f4862180f96..1ad393f12f3203 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -417,9 +417,9 @@ are always available. They are listed here in alphabetical order. parts (the sign of the imaginary part is mandatory in this case). The string can optionally be surrounded by whitespaces and the round parentheses ``'('`` and ``')'``, which are ignored. - The string must not contain whitespace between ``'+'``, ``'-'``, ``'−'`` (U+2212), the - ``'j'`` or ``'J'`` suffix, and the decimal number. - For example, ``complex('1+2j')`` is fine, but ``complex('1 + 2j')`` raises + The string must not contain whitespace between ASCII plus sign ``'+'``, ASCII hyphen minus + ``'-'``, Unicode minus sign``'−'`` (U+2212), the ``'j'`` or ``'J'`` suffix, and the decimal + number. For example, ``complex('1+2j')`` is fine, but ``complex('1 + 2j')`` raises :exc:`ValueError`. More precisely, the input must conform to the :token:`~float:complexvalue` production rule in the following grammar, after parentheses and leading and From 03d24b2e448d5271fcce54c90084c6191950a2c7 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sat, 14 Feb 2026 03:40:55 +0100 Subject: [PATCH 11/23] Fix formatting --- Doc/library/functions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 1ad393f12f3203..4c0c49caaa9f12 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -418,7 +418,7 @@ are always available. They are listed here in alphabetical order. The string can optionally be surrounded by whitespaces and the round parentheses ``'('`` and ``')'``, which are ignored. The string must not contain whitespace between ASCII plus sign ``'+'``, ASCII hyphen minus - ``'-'``, Unicode minus sign``'−'`` (U+2212), the ``'j'`` or ``'J'`` suffix, and the decimal + ``'-'``, Unicode minus sign ``'−'`` (U+2212), the ``'j'`` or ``'J'`` suffix, and the decimal number. For example, ``complex('1+2j')`` is fine, but ``complex('1 + 2j')`` raises :exc:`ValueError`. More precisely, the input must conform to the :token:`~float:complexvalue` From 5ce17c9664df235fac29adcb27100e736cc34a66 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sat, 14 Feb 2026 03:44:05 +0100 Subject: [PATCH 12/23] Update float syntax snippet --- Doc/library/functions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 4c0c49caaa9f12..2d4d5c2815ab09 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -794,7 +794,7 @@ are always available. They are listed here in alphabetical order. whitespace characters are removed: .. productionlist:: float - sign: "+" | "-" + sign: "+" | "-" | infinity: "Infinity" | "inf" nan: "nan" digit: From b4b95745d1a168aeea2ae880a5e4536a18b0ec5f Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sat, 14 Feb 2026 03:49:26 +0100 Subject: [PATCH 13/23] Update stdtypes reference --- Doc/library/stdtypes.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index ce0d7cbb2e4276..bc825824eb011e 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -352,8 +352,9 @@ Notes: alternative conversions. (4) - float also accepts the strings "nan" and "inf" with an optional prefix "+" - or "-" for Not a Number (NaN) and positive or negative infinity. + float also accepts the strings "nan" and "inf" with an optional prefix ASCII plus + sign "+" or ASCII hyphen minus "-" or Unicode minus sign "−" (U+2212) for Not a Number + (NaN) and positive or negative infinity. (5) Python defines ``pow(0, 0)`` and ``0 ** 0`` to be ``1``, as is common for From ff013f565b7fa724471e40b9e607852d5b817ebb Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sat, 14 Feb 2026 04:00:51 +0100 Subject: [PATCH 14/23] Clarify `complex` docs --- Doc/library/functions.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 2d4d5c2815ab09..4503f742b37a77 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -417,8 +417,8 @@ are always available. They are listed here in alphabetical order. parts (the sign of the imaginary part is mandatory in this case). The string can optionally be surrounded by whitespaces and the round parentheses ``'('`` and ``')'``, which are ignored. - The string must not contain whitespace between ASCII plus sign ``'+'``, ASCII hyphen minus - ``'-'``, Unicode minus sign ``'−'`` (U+2212), the ``'j'`` or ``'J'`` suffix, and the decimal + The string must not contain whitespace between ASCII plus sign ``'+'`` or ASCII hyphen minus + ``'-'`` or Unicode minus sign ``'−'`` (U+2212), the ``'j'`` or ``'J'`` suffix, and the decimal number. For example, ``complex('1+2j')`` is fine, but ``complex('1 + 2j')`` raises :exc:`ValueError`. More precisely, the input must conform to the :token:`~float:complexvalue` From ca6eca065704f7eaca0494ee0890c967252e9629 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sat, 14 Feb 2026 04:03:03 +0100 Subject: [PATCH 15/23] Slightly changed "syntax" used in `float` production list --- Doc/library/functions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 4503f742b37a77..e252227d50229b 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -794,7 +794,7 @@ are always available. They are listed here in alphabetical order. whitespace characters are removed: .. productionlist:: float - sign: "+" | "-" | + sign: "+" | "-" | "−" infinity: "Infinity" | "inf" nan: "nan" digit: From 26dadc58c1984050dddcbd2d85ffd64b0ab5adcc Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sat, 14 Feb 2026 04:06:45 +0100 Subject: [PATCH 16/23] Fix alternative used in `complex` docs, I think it was incorrect --- Doc/library/functions.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index e252227d50229b..41b0edc097ef1e 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -417,10 +417,10 @@ are always available. They are listed here in alphabetical order. parts (the sign of the imaginary part is mandatory in this case). The string can optionally be surrounded by whitespaces and the round parentheses ``'('`` and ``')'``, which are ignored. - The string must not contain whitespace between ASCII plus sign ``'+'`` or ASCII hyphen minus - ``'-'`` or Unicode minus sign ``'−'`` (U+2212), the ``'j'`` or ``'J'`` suffix, and the decimal - number. For example, ``complex('1+2j')`` is fine, but ``complex('1 + 2j')`` raises - :exc:`ValueError`. + The string must not contain whitespace between ``'+'`` (ASCII plus sign), + ``'-'`` (ASCII hyphen minus), ``'−'`` (Unicode minus sign, U+2212), the + ``'j'`` or ``'J'`` suffix, and the decimal number. For example, + ``complex('1+2j')`` is fine, but ``complex('1 + 2j')`` raises :exc:`ValueError`. More precisely, the input must conform to the :token:`~float:complexvalue` production rule in the following grammar, after parentheses and leading and trailing whitespace characters are removed: @@ -1046,8 +1046,8 @@ are always available. They are listed here in alphabetical order. If the argument is not a number or if *base* is given, then it must be a string, :class:`bytes`, or :class:`bytearray` instance representing an integer in radix *base*. Optionally, the string can be directly preceded (with no whitespaces - in between) by ASCII plus sign ``+``, ASCII hyphen minus ``-`` or Unicode minus sign - ``−`` (U+2212), have leading zeros, be surrounded by whitespace, + in between) by ``+`` (ASCII plus sign), ``-`` (ASCII hyphen minus) or ``−`` (Unicode + minus sign, U+2212), have leading zeros, be surrounded by whitespace, and have single underscores interspersed between digits. A base-n integer string contains digits, each representing a value from 0 to From 6391d272a864d9dd51ba5bc55b5aac03e0e302a3 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sat, 14 Feb 2026 04:09:59 +0100 Subject: [PATCH 17/23] Parenthesize consistently I think that reads better --- Doc/library/functions.rst | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 41b0edc097ef1e..97e22b98973f82 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -467,8 +467,9 @@ are always available. They are listed here in alphabetical order. deprecated; it should only be passed as a single positional argument. .. versionchanged:: 3.15 - Unicode minus sign ``'−'`` (U+2212) can be now used as an alternative to ASCII - hyphen minus ``'-'`` for denoting negative sign. + ``'−'`` (Unicode minus sign, U+2212) can be now used as an + alternative to ``'-'`` (ASCII hyphen minus) for denoting + negative sign. .. function:: delattr(object, name, /) @@ -1091,8 +1092,9 @@ are always available. They are listed here in alphabetical order. :func:`int` no longer delegates to the :meth:`~object.__trunc__` method. .. versionchanged:: 3.15 - :func:`int` now supports Unicode minus sign ``−`` (U+2212) as an alternative - to ASCII hyphen minus ``-`` for denoting negative integers. + :func:`int` now supports ``−`` (Unicode minus sign, U+2212) + as an alternative to ``-`` (ASCII hyphen minus) for denoting + negative integers. .. function:: isinstance(object, classinfo, /) From f7c3fa72da949b1aff208746b6193ceba1e1a5b2 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sat, 14 Feb 2026 04:11:37 +0100 Subject: [PATCH 18/23] Parenthesize consistently vol. 2 --- Doc/library/functions.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 97e22b98973f82..421d2c3635538b 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -834,8 +834,9 @@ are always available. They are listed here in alphabetical order. Falls back to :meth:`~object.__index__` if :meth:`~object.__float__` is not defined. .. versionchanged:: 3.15 - Added support for Unicode minus sign ``−`` (U+2212) as an alternative to ASCII - hyphen minus ``-`` for denoting negative floats. + Added support for ``−`` (Unicode minus sign, U+2212) as an + alternative to ``-`` (ASCII hyphen minus) for denoting negative + floats. .. index:: From 0d519f43291fa28f485da97e423f40084060a748 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sat, 14 Feb 2026 04:15:21 +0100 Subject: [PATCH 19/23] Empty commit to try to skip incremental lint From 6c5994a3f97170697b939954e38b2dc790ded57b Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sat, 14 Feb 2026 04:20:38 +0100 Subject: [PATCH 20/23] Test NaNs properly --- Lib/test/test_float.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Lib/test/test_float.py b/Lib/test/test_float.py index 8c8710e4bce5f6..c9445bccd4b4c1 100644 --- a/Lib/test/test_float.py +++ b/Lib/test/test_float.py @@ -1114,30 +1114,40 @@ def test_nan_from_str(self): self.assertTrue(isnan(float("nan"))) self.assertTrue(isnan(float("+nan"))) self.assertTrue(isnan(float("-nan"))) + self.assertTrue(isnan(float("\N{MINUS SIGN}nan"))) self.assertEqual(repr(float("nan")), "nan") self.assertEqual(repr(float("+nan")), "nan") self.assertEqual(repr(float("-nan")), "nan") + self.assertEqual(repr(float("\N{MINUS SIGN}nan")), "nan") self.assertEqual(repr(float("NAN")), "nan") self.assertEqual(repr(float("+NAn")), "nan") self.assertEqual(repr(float("-NaN")), "nan") + self.assertEqual(repr(float("\N{MINUS SIGN}NaN")), "nan") self.assertEqual(str(float("nan")), "nan") self.assertEqual(str(float("+nan")), "nan") self.assertEqual(str(float("-nan")), "nan") + self.assertEqual(str(float("\N{MINUS SIGN}nan")), "nan") self.assertRaises(ValueError, float, "nana") self.assertRaises(ValueError, float, "+nana") self.assertRaises(ValueError, float, "-nana") + self.assertRaises(ValueError, float, "\N{MINUS SIGN}nana") self.assertRaises(ValueError, float, "na") self.assertRaises(ValueError, float, "+na") self.assertRaises(ValueError, float, "-na") + self.assertRaises(ValueError, float, "\N{MINUS SIGN}na") self.assertRaises(ValueError, float, "++nan") self.assertRaises(ValueError, float, "-+NAN") self.assertRaises(ValueError, float, "+-NaN") self.assertRaises(ValueError, float, "--nAn") + self.assertRaises(ValueError, float, "\N{MINUS SIGN}+NAN") + self.assertRaises(ValueError, float, "-\N{MINUS SIGN}nAn") + self.assertRaises(ValueError, float, "\N{MINUS SIGN}-nAn") + self.assertRaises(ValueError, float, "\N{MINUS SIGN}\N{MINUS SIGN}nAn") def test_nan_as_str(self): self.assertEqual(repr(1e300 * 1e300 * 0), "nan") @@ -1149,11 +1159,13 @@ def test_nan_as_str(self): def test_inf_signs(self): self.assertEqual(copysign(1.0, float('inf')), 1.0) self.assertEqual(copysign(1.0, float('-inf')), -1.0) + self.assertEqual(copysign(1.0, float('\N{MINUS SIGN}inf')), -1.0) def test_nan_signs(self): # The sign of float('nan') should be predictable. self.assertEqual(copysign(1.0, float('nan')), 1.0) self.assertEqual(copysign(1.0, float('-nan')), -1.0) + self.assertEqual(copysign(1.0, float('\N{MINUS SIGN}nan')), -1.0) fromHex = float.fromhex From 0e7110c6c70aae5a338a42e6bcc45bcee175231f Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sat, 14 Feb 2026 04:22:47 +0100 Subject: [PATCH 21/23] Fix trailing whitespace (was confused) --- Doc/library/functions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 421d2c3635538b..a3f1eccff24ed4 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -467,7 +467,7 @@ are always available. They are listed here in alphabetical order. deprecated; it should only be passed as a single positional argument. .. versionchanged:: 3.15 - ``'−'`` (Unicode minus sign, U+2212) can be now used as an + ``'−'`` (Unicode minus sign, U+2212) can be now used as an alternative to ``'-'`` (ASCII hyphen minus) for denoting negative sign. From 199a879b33b32d7e69f3f8c75f28e92784e9dd37 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sat, 14 Feb 2026 04:25:40 +0100 Subject: [PATCH 22/23] Parenthesize in news entry too --- .../2026-02-14-03-03-07.gh-issue-144087.KT9kaM.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-14-03-03-07.gh-issue-144087.KT9kaM.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-14-03-03-07.gh-issue-144087.KT9kaM.rst index 9a7b420eca105e..054f9d021a4808 100644 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-14-03-03-07.gh-issue-144087.KT9kaM.rst +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-14-03-03-07.gh-issue-144087.KT9kaM.rst @@ -1,3 +1,3 @@ :func:`int`, :func:`float` and :func:`complex` now support strings -with unicode MINUS SIGN ``−`` (U+2212) as an alternative to ASCII -HYPHEN-SIGN ``-`` (U+002D). Contributed by Bartosz Sławecki. +with ``−`` (Unicode minus sign, U+2212) as an alternative to ``-`` +(ASCII hyphen minus, U+002D). Contributed by Bartosz Sławecki. From a9874e7cfa1d67798993c1bb1dd3222df9f09b17 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 15 Feb 2026 21:09:36 +0100 Subject: [PATCH 23/23] Use `.. versionchanged:: next` --- Doc/library/functions.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index a3f1eccff24ed4..fd8714c77da98d 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -466,7 +466,7 @@ are always available. They are listed here in alphabetical order. Passing a complex number as the *real* or *imag* argument is now deprecated; it should only be passed as a single positional argument. - .. versionchanged:: 3.15 + .. versionchanged:: next ``'−'`` (Unicode minus sign, U+2212) can be now used as an alternative to ``'-'`` (ASCII hyphen minus) for denoting negative sign. @@ -833,7 +833,7 @@ are always available. They are listed here in alphabetical order. .. versionchanged:: 3.8 Falls back to :meth:`~object.__index__` if :meth:`~object.__float__` is not defined. - .. versionchanged:: 3.15 + .. versionchanged:: next Added support for ``−`` (Unicode minus sign, U+2212) as an alternative to ``-`` (ASCII hyphen minus) for denoting negative floats. @@ -1092,7 +1092,7 @@ are always available. They are listed here in alphabetical order. .. versionchanged:: 3.14 :func:`int` no longer delegates to the :meth:`~object.__trunc__` method. - .. versionchanged:: 3.15 + .. versionchanged:: next :func:`int` now supports ``−`` (Unicode minus sign, U+2212) as an alternative to ``-`` (ASCII hyphen minus) for denoting negative integers.