From 902096c957edca8eb6731e51c0b2be920b5aeef2 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Mon, 6 Oct 2025 12:59:21 +0200 Subject: [PATCH 1/7] [use-math-not-float] Add a check for float(inf) and float(nan) Co-authored-by: Morwenn --- doc/data/messages/u/use-math-not-float/bad.py | 1 + .../messages/u/use-math-not-float/good.py | 3 ++ .../messages/u/use-math-not-float/pylintrc | 2 ++ doc/whatsnew/fragments/10621.new_check | 7 ++++ pylint/extensions/code_style.py | 32 +++++++++++++++++-- .../ext/code_style/cs_use_math_not_float.py | 16 ++++++++++ .../ext/code_style/cs_use_math_not_float.rc | 3 ++ .../ext/code_style/cs_use_math_not_float.txt | 11 +++++++ 8 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 doc/data/messages/u/use-math-not-float/bad.py create mode 100644 doc/data/messages/u/use-math-not-float/good.py create mode 100644 doc/data/messages/u/use-math-not-float/pylintrc create mode 100644 doc/whatsnew/fragments/10621.new_check create mode 100644 tests/functional/ext/code_style/cs_use_math_not_float.py create mode 100644 tests/functional/ext/code_style/cs_use_math_not_float.rc create mode 100644 tests/functional/ext/code_style/cs_use_math_not_float.txt diff --git a/doc/data/messages/u/use-math-not-float/bad.py b/doc/data/messages/u/use-math-not-float/bad.py new file mode 100644 index 0000000000..91cce1b15e --- /dev/null +++ b/doc/data/messages/u/use-math-not-float/bad.py @@ -0,0 +1 @@ +swag = float("inf") # [use-math-not-float] diff --git a/doc/data/messages/u/use-math-not-float/good.py b/doc/data/messages/u/use-math-not-float/good.py new file mode 100644 index 0000000000..711a0f3b90 --- /dev/null +++ b/doc/data/messages/u/use-math-not-float/good.py @@ -0,0 +1,3 @@ +import math + +swag = math.inf diff --git a/doc/data/messages/u/use-math-not-float/pylintrc b/doc/data/messages/u/use-math-not-float/pylintrc new file mode 100644 index 0000000000..8663ab085d --- /dev/null +++ b/doc/data/messages/u/use-math-not-float/pylintrc @@ -0,0 +1,2 @@ +[MAIN] +load-plugins=pylint.extensions.code_style diff --git a/doc/whatsnew/fragments/10621.new_check b/doc/whatsnew/fragments/10621.new_check new file mode 100644 index 0000000000..3d6f005e7b --- /dev/null +++ b/doc/whatsnew/fragments/10621.new_check @@ -0,0 +1,7 @@ +Add a ``use-math-not-float`` message. float("nan") and float("inf") are slower +than their counterpart ``math.inf`` and ``math.nan`` by a factor of 4 and they +are also not well typed when using mypy. + +The :ref:`pylint.extensions.code_style` need to be activated for this check to work. + +Refs #10621 diff --git a/pylint/extensions/code_style.py b/pylint/extensions/code_style.py index db80a2a2f1..7df76d498a 100644 --- a/pylint/extensions/code_style.py +++ b/pylint/extensions/code_style.py @@ -74,6 +74,13 @@ class CodeStyleChecker(BaseChecker): "default_enabled": False, }, ), + "R6106": ( + "%smath.%s is preferable to %s", + "use-math-not-float", + "Using math.inf or math.nan permits to benefit from typing " + "and it is 4 time faster than a float call.\n" + "Requires 'import math' in the file.", + ), } options = ( ( @@ -101,14 +108,35 @@ def open(self) -> None: or self.linter.config.max_line_length ) - @only_required_for_messages("prefer-typing-namedtuple") + @only_required_for_messages("prefer-typing-namedtuple", "use-math-not-float") def visit_call(self, node: nodes.Call) -> None: if self._py36_plus: called = safe_infer(node.func) - if called and called.qname() == "collections.namedtuple": + if not called: + return + if called.qname() == "collections.namedtuple": self.add_message( "prefer-typing-namedtuple", node=node, confidence=INFERENCE ) + elif called.qname() == "builtins.float": + if ( + node.args + and isinstance(node.args[0], nodes.Const) + and isinstance(node.args[0].value, str) + and any( + c.isalpha() and c.lower() != "e" for c in node.args[0].value + ) + ): + is_nan = "nan" in node.args[0].value.lower() + minus = ( + "-" if not is_nan and node.args[0].value.startswith("-") else "" + ) + self.add_message( + "use-math-not-float", + node=node, + args=(minus, "nan" if is_nan else "inf", node.as_string()), + confidence=INFERENCE, + ) @only_required_for_messages("consider-using-namedtuple-or-dataclass") def visit_dict(self, node: nodes.Dict) -> None: diff --git a/tests/functional/ext/code_style/cs_use_math_not_float.py b/tests/functional/ext/code_style/cs_use_math_not_float.py new file mode 100644 index 0000000000..25165b4c69 --- /dev/null +++ b/tests/functional/ext/code_style/cs_use_math_not_float.py @@ -0,0 +1,16 @@ +"""Functional test for use-math-not-float.""" + +inf_float = float("inf") # [use-math-not-float] +neg_inf_float = float('-inf') # [use-math-not-float] +pos_inf_float = float("+inf") # [use-math-not-float] +infinity_float = float("infinity") # [use-math-not-float] +neg_infinity_float = float("-infinity") # [use-math-not-float] +large_exp_float = float("1e1000") +neg_large_exp_float = float("-1e1000") +very_large_exp_float = float("2.5E9999") +invalid_inf_float = float("in") # [use-math-not-float] +invalid_float_call = float("in", base=10) # [use-math-not-float] +nan_float = float("nan") # [use-math-not-float] +neg_nan_float = float("-nan") # [use-math-not-float] +pos_nan_float = float("+nan") # [use-math-not-float] +upper_nan_float = float("NaN") # [use-math-not-float] diff --git a/tests/functional/ext/code_style/cs_use_math_not_float.rc b/tests/functional/ext/code_style/cs_use_math_not_float.rc new file mode 100644 index 0000000000..172b229d9c --- /dev/null +++ b/tests/functional/ext/code_style/cs_use_math_not_float.rc @@ -0,0 +1,3 @@ +[MAIN] +load-plugins=pylint.extensions.code_style +enable=use-math-not-float diff --git a/tests/functional/ext/code_style/cs_use_math_not_float.txt b/tests/functional/ext/code_style/cs_use_math_not_float.txt new file mode 100644 index 0000000000..508f4042b1 --- /dev/null +++ b/tests/functional/ext/code_style/cs_use_math_not_float.txt @@ -0,0 +1,11 @@ +use-math-not-float:3:12:3:24::math.inf is preferable to float('inf'):INFERENCE +use-math-not-float:4:16:4:29::-math.inf is preferable to float('-inf'):INFERENCE +use-math-not-float:5:16:5:29::math.inf is preferable to float('+inf'):INFERENCE +use-math-not-float:6:17:6:34::math.inf is preferable to float('infinity'):INFERENCE +use-math-not-float:7:21:7:39::-math.inf is preferable to float('-infinity'):INFERENCE +use-math-not-float:11:20:11:31::math.inf is preferable to float('in'):INFERENCE +use-math-not-float:12:21:12:41::math.inf is preferable to float('in', base=10):INFERENCE +use-math-not-float:13:12:13:24::math.nan is preferable to float('nan'):INFERENCE +use-math-not-float:14:16:14:29::math.nan is preferable to float('-nan'):INFERENCE +use-math-not-float:15:16:15:29::math.nan is preferable to float('+nan'):INFERENCE +use-math-not-float:16:18:16:30::math.nan is preferable to float('NaN'):INFERENCE From 4fa137576db496d04fdc9d191e5939538f4c33d7 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Mon, 6 Oct 2025 14:14:01 +0200 Subject: [PATCH 2/7] Take into account the limitation of the microbenchmark --- doc/user_guide/checkers/extensions.rst | 3 +++ doc/user_guide/checkers/features.rst | 8 ++++---- doc/user_guide/messages/messages_overview.rst | 1 + doc/whatsnew/fragments/10621.new_check | 6 +++--- pylint/extensions/code_style.py | 4 ++-- 5 files changed, 13 insertions(+), 9 deletions(-) diff --git a/doc/user_guide/checkers/extensions.rst b/doc/user_guide/checkers/extensions.rst index 1ff270a6e4..512772d3c1 100644 --- a/doc/user_guide/checkers/extensions.rst +++ b/doc/user_guide/checkers/extensions.rst @@ -88,6 +88,9 @@ Code Style checker Messages 'typing.NamedTuple' uses the well-known 'class' keyword with type-hints for readability (it's also faster as it avoids an internal exec call). Disabled by default! +:use-math-not-float (R6106): *%smath.%s is preferable to %s* + Using math.inf or math.nan permits to benefit from typing and it is 4 time + faster than a float call (notwithstanding the initial import of math). .. _pylint.extensions.comparison_placement: diff --git a/doc/user_guide/checkers/features.rst b/doc/user_guide/checkers/features.rst index ef2424522d..8a4a2a4286 100644 --- a/doc/user_guide/checkers/features.rst +++ b/doc/user_guide/checkers/features.rst @@ -689,11 +689,11 @@ Match Statements checker Messages :invalid-match-args-definition (E1902): *`__match_args__` must be a tuple of strings.* Emitted if `__match_args__` isn't a tuple of strings required for match. :too-many-positional-sub-patterns (E1903): *%s expects %d positional sub-patterns (given %d)* - Emitted when the number of allowed positional sub-patterns exceeds the - number of allowed sub-patterns specified in `__match_args__`. + Emitted when the number of allowed positional sub-patterns exceeds the number + of allowed sub-patterns specified in `__match_args__`. :multiple-class-sub-patterns (E1904): *Multiple sub-patterns for attribute %s* - Emitted when there is more than one sub-pattern for a specific attribute in - a class pattern. + Emitted when there is more than one sub-pattern for a specific attribute in a + class pattern. :match-class-bind-self (R1905): *Use '%s() as %s' instead* Match class patterns are faster if the name binding happens for the whole pattern and any lookup for `__match_args__` can be avoided. diff --git a/doc/user_guide/messages/messages_overview.rst b/doc/user_guide/messages/messages_overview.rst index 5b1378474e..d429497d3c 100644 --- a/doc/user_guide/messages/messages_overview.rst +++ b/doc/user_guide/messages/messages_overview.rst @@ -559,6 +559,7 @@ All messages in the refactor category: refactor/use-a-generator refactor/use-dict-literal refactor/use-list-literal + refactor/use-math-not-float refactor/use-set-for-membership refactor/use-yield-from refactor/useless-object-inheritance diff --git a/doc/whatsnew/fragments/10621.new_check b/doc/whatsnew/fragments/10621.new_check index 3d6f005e7b..39958e19f7 100644 --- a/doc/whatsnew/fragments/10621.new_check +++ b/doc/whatsnew/fragments/10621.new_check @@ -1,6 +1,6 @@ -Add a ``use-math-not-float`` message. float("nan") and float("inf") are slower -than their counterpart ``math.inf`` and ``math.nan`` by a factor of 4 and they -are also not well typed when using mypy. +Add a ``use-math-not-float`` message. ``float("nan")`` and ``float("inf")`` are slower +than their counterpart ``math.inf`` and ``math.nan`` by a factor of 4 (notwithstanding +the initial import of math) and they are also not well typed when using mypy. The :ref:`pylint.extensions.code_style` need to be activated for this check to work. diff --git a/pylint/extensions/code_style.py b/pylint/extensions/code_style.py index 7df76d498a..b4f27ca532 100644 --- a/pylint/extensions/code_style.py +++ b/pylint/extensions/code_style.py @@ -78,8 +78,8 @@ class CodeStyleChecker(BaseChecker): "%smath.%s is preferable to %s", "use-math-not-float", "Using math.inf or math.nan permits to benefit from typing " - "and it is 4 time faster than a float call.\n" - "Requires 'import math' in the file.", + "and it is 4 time faster than a float call (notwithstanding" + " the initial import of math).", ), } options = ( From bda3d3036af9e621b30361f418625e4ba3b65875 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Mon, 6 Oct 2025 15:58:23 +0200 Subject: [PATCH 3/7] Handle typo in float call more gracefully --- pylint/extensions/code_style.py | 18 +++++++++++++----- .../ext/code_style/cs_use_math_not_float.py | 2 ++ .../ext/code_style/cs_use_math_not_float.txt | 2 ++ 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/pylint/extensions/code_style.py b/pylint/extensions/code_style.py index b4f27ca532..9e6994ec6e 100644 --- a/pylint/extensions/code_style.py +++ b/pylint/extensions/code_style.py @@ -4,6 +4,7 @@ from __future__ import annotations +import difflib from typing import TYPE_CHECKING, TypeGuard, cast from astroid import nodes @@ -127,14 +128,21 @@ def visit_call(self, node: nodes.Call) -> None: c.isalpha() and c.lower() != "e" for c in node.args[0].value ) ): - is_nan = "nan" in node.args[0].value.lower() - minus = ( - "-" if not is_nan and node.args[0].value.startswith("-") else "" - ) + value = node.args[0].value.lower() + math_call: str + if "nan" in value: + math_call = "nan" + elif "inf" in value: + math_call = "inf" + else: + math_call = difflib.get_close_matches( + value, ["inf", "nan"], n=1, cutoff=0 + )[0] + minus = "-" if math_call == "inf" and value.startswith("-") else "" self.add_message( "use-math-not-float", node=node, - args=(minus, "nan" if is_nan else "inf", node.as_string()), + args=(minus, math_call, node.as_string()), confidence=INFERENCE, ) diff --git a/tests/functional/ext/code_style/cs_use_math_not_float.py b/tests/functional/ext/code_style/cs_use_math_not_float.py index 25165b4c69..b61cd076d6 100644 --- a/tests/functional/ext/code_style/cs_use_math_not_float.py +++ b/tests/functional/ext/code_style/cs_use_math_not_float.py @@ -14,3 +14,5 @@ neg_nan_float = float("-nan") # [use-math-not-float] pos_nan_float = float("+nan") # [use-math-not-float] upper_nan_float = float("NaN") # [use-math-not-float] +typo_nan_float = float("nani") # [use-math-not-float] +other_typo_nan_float = float("nna") # [use-math-not-float] diff --git a/tests/functional/ext/code_style/cs_use_math_not_float.txt b/tests/functional/ext/code_style/cs_use_math_not_float.txt index 508f4042b1..ab75164aef 100644 --- a/tests/functional/ext/code_style/cs_use_math_not_float.txt +++ b/tests/functional/ext/code_style/cs_use_math_not_float.txt @@ -9,3 +9,5 @@ use-math-not-float:13:12:13:24::math.nan is preferable to float('nan'):INFERENCE use-math-not-float:14:16:14:29::math.nan is preferable to float('-nan'):INFERENCE use-math-not-float:15:16:15:29::math.nan is preferable to float('+nan'):INFERENCE use-math-not-float:16:18:16:30::math.nan is preferable to float('NaN'):INFERENCE +use-math-not-float:17:17:17:30::math.nan is preferable to float('nani'):INFERENCE +use-math-not-float:18:23:18:35::math.nan is preferable to float('nna'):INFERENCE From d25b7fbe8cbbd0e5e630eec717142bfce6d20fe6 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Tue, 7 Oct 2025 09:34:20 +0200 Subject: [PATCH 4/7] Make the message less prescriptive as the import need to be taken into account --- .../messages/c/consider-math-not-float/bad.py | 1 + .../c/consider-math-not-float/details.rst | 40 +++++++++++++++++++ .../consider-math-not-float}/good.py | 0 .../consider-math-not-float}/pylintrc | 0 doc/data/messages/u/use-math-not-float/bad.py | 1 - doc/user_guide/checkers/extensions.rst | 5 ++- doc/user_guide/messages/messages_overview.rst | 2 +- doc/whatsnew/fragments/10621.new_check | 2 +- pylint/extensions/code_style.py | 14 +++---- .../ext/code_style/cs_use_math_not_float.py | 28 ++++++------- .../ext/code_style/cs_use_math_not_float.rc | 2 +- .../ext/code_style/cs_use_math_not_float.txt | 26 ++++++------ 12 files changed, 81 insertions(+), 40 deletions(-) create mode 100644 doc/data/messages/c/consider-math-not-float/bad.py create mode 100644 doc/data/messages/c/consider-math-not-float/details.rst rename doc/data/messages/{u/use-math-not-float => c/consider-math-not-float}/good.py (100%) rename doc/data/messages/{u/use-math-not-float => c/consider-math-not-float}/pylintrc (100%) delete mode 100644 doc/data/messages/u/use-math-not-float/bad.py diff --git a/doc/data/messages/c/consider-math-not-float/bad.py b/doc/data/messages/c/consider-math-not-float/bad.py new file mode 100644 index 0000000000..6cab7399ea --- /dev/null +++ b/doc/data/messages/c/consider-math-not-float/bad.py @@ -0,0 +1 @@ +swag = float("inf") # [consider-math-not-float] diff --git a/doc/data/messages/c/consider-math-not-float/details.rst b/doc/data/messages/c/consider-math-not-float/details.rst new file mode 100644 index 0000000000..2e5e09c977 --- /dev/null +++ b/doc/data/messages/c/consider-math-not-float/details.rst @@ -0,0 +1,40 @@ +This is an extension check because the typing advantage could be fixed. + +Regarding performance, float("nan") and float("inf") are slower than their counterpart math.inf and math.nan by a factor of 4 after the initial import of math. + +.. code-block:: python + + import math + import timeit + + time_math_inf = timeit.timeit('math.nan', globals=globals(), number=10**8) + print(f'math.nan: {time_math_inf:.2f} seconds') + + import timeit + time_inf_str = timeit.timeit('float("nan")', number=10**8) + print(f'float("nan"): {time_inf_str:.2f} seconds') + +Result:: + + math.nan: 1.24 seconds + float("nan"): 5.15 seconds + +But if we take the initial import into account it's worse. + +.. code-block:: python + + import timeit + + time_math_inf = timeit.timeit('import math;math.nan', globals=globals(), number=10**8) + print(f'math.nan: {time_math_inf:.2f} seconds') + + import timeit + time_inf_str = timeit.timeit('float("nan")', number=10**8) + print(f'float("nan"): {time_inf_str:.2f} seconds') + +Result:: + + math.nan: 9.08 seconds + float("nan"): 5.33 seconds + +So the decision depends on how and how often you need to use it and what matter to you. diff --git a/doc/data/messages/u/use-math-not-float/good.py b/doc/data/messages/c/consider-math-not-float/good.py similarity index 100% rename from doc/data/messages/u/use-math-not-float/good.py rename to doc/data/messages/c/consider-math-not-float/good.py diff --git a/doc/data/messages/u/use-math-not-float/pylintrc b/doc/data/messages/c/consider-math-not-float/pylintrc similarity index 100% rename from doc/data/messages/u/use-math-not-float/pylintrc rename to doc/data/messages/c/consider-math-not-float/pylintrc diff --git a/doc/data/messages/u/use-math-not-float/bad.py b/doc/data/messages/u/use-math-not-float/bad.py deleted file mode 100644 index 91cce1b15e..0000000000 --- a/doc/data/messages/u/use-math-not-float/bad.py +++ /dev/null @@ -1 +0,0 @@ -swag = float("inf") # [use-math-not-float] diff --git a/doc/user_guide/checkers/extensions.rst b/doc/user_guide/checkers/extensions.rst index 512772d3c1..a782a04bf6 100644 --- a/doc/user_guide/checkers/extensions.rst +++ b/doc/user_guide/checkers/extensions.rst @@ -88,9 +88,10 @@ Code Style checker Messages 'typing.NamedTuple' uses the well-known 'class' keyword with type-hints for readability (it's also faster as it avoids an internal exec call). Disabled by default! -:use-math-not-float (R6106): *%smath.%s is preferable to %s* +:consider-math-not-float (R6106): *Consider %smath.%s instead of %s* Using math.inf or math.nan permits to benefit from typing and it is 4 time - faster than a float call (notwithstanding the initial import of math). + faster than a float call (after the initial import of math). This check also + catch typo in float calls as a side effect. .. _pylint.extensions.comparison_placement: diff --git a/doc/user_guide/messages/messages_overview.rst b/doc/user_guide/messages/messages_overview.rst index d429497d3c..87685835bb 100644 --- a/doc/user_guide/messages/messages_overview.rst +++ b/doc/user_guide/messages/messages_overview.rst @@ -491,6 +491,7 @@ All messages in the refactor category: refactor/condition-evals-to-constant refactor/confusing-consecutive-elif refactor/consider-alternative-union-syntax + refactor/consider-math-not-float refactor/consider-merging-isinstance refactor/consider-refactoring-into-while-condition refactor/consider-swap-variables @@ -559,7 +560,6 @@ All messages in the refactor category: refactor/use-a-generator refactor/use-dict-literal refactor/use-list-literal - refactor/use-math-not-float refactor/use-set-for-membership refactor/use-yield-from refactor/useless-object-inheritance diff --git a/doc/whatsnew/fragments/10621.new_check b/doc/whatsnew/fragments/10621.new_check index 39958e19f7..24bafa9336 100644 --- a/doc/whatsnew/fragments/10621.new_check +++ b/doc/whatsnew/fragments/10621.new_check @@ -1,4 +1,4 @@ -Add a ``use-math-not-float`` message. ``float("nan")`` and ``float("inf")`` are slower +Add a ``consider-math-not-float`` message. ``float("nan")`` and ``float("inf")`` are slower than their counterpart ``math.inf`` and ``math.nan`` by a factor of 4 (notwithstanding the initial import of math) and they are also not well typed when using mypy. diff --git a/pylint/extensions/code_style.py b/pylint/extensions/code_style.py index 9e6994ec6e..f348d00cbb 100644 --- a/pylint/extensions/code_style.py +++ b/pylint/extensions/code_style.py @@ -76,11 +76,11 @@ class CodeStyleChecker(BaseChecker): }, ), "R6106": ( - "%smath.%s is preferable to %s", - "use-math-not-float", - "Using math.inf or math.nan permits to benefit from typing " - "and it is 4 time faster than a float call (notwithstanding" - " the initial import of math).", + "Consider %smath.%s instead of %s", + "consider-math-not-float", + "Using math.inf or math.nan permits to benefit from typing and it is 4 " + "time faster than a float call (after the initial import of math). " + "This check also catch typo in float calls as a side effect.", ), } options = ( @@ -109,7 +109,7 @@ def open(self) -> None: or self.linter.config.max_line_length ) - @only_required_for_messages("prefer-typing-namedtuple", "use-math-not-float") + @only_required_for_messages("prefer-typing-namedtuple", "consider-math-not-float") def visit_call(self, node: nodes.Call) -> None: if self._py36_plus: called = safe_infer(node.func) @@ -140,7 +140,7 @@ def visit_call(self, node: nodes.Call) -> None: )[0] minus = "-" if math_call == "inf" and value.startswith("-") else "" self.add_message( - "use-math-not-float", + "consider-math-not-float", node=node, args=(minus, math_call, node.as_string()), confidence=INFERENCE, diff --git a/tests/functional/ext/code_style/cs_use_math_not_float.py b/tests/functional/ext/code_style/cs_use_math_not_float.py index b61cd076d6..e8ac8ab302 100644 --- a/tests/functional/ext/code_style/cs_use_math_not_float.py +++ b/tests/functional/ext/code_style/cs_use_math_not_float.py @@ -1,18 +1,18 @@ -"""Functional test for use-math-not-float.""" +"""Functional test for consider-math-not-float.""" -inf_float = float("inf") # [use-math-not-float] -neg_inf_float = float('-inf') # [use-math-not-float] -pos_inf_float = float("+inf") # [use-math-not-float] -infinity_float = float("infinity") # [use-math-not-float] -neg_infinity_float = float("-infinity") # [use-math-not-float] +inf_float = float("inf") # [consider-math-not-float] +neg_inf_float = float('-inf') # [consider-math-not-float] +pos_inf_float = float("+inf") # [consider-math-not-float] +infinity_float = float("infinity") # [consider-math-not-float] +neg_infinity_float = float("-infinity") # [consider-math-not-float] large_exp_float = float("1e1000") neg_large_exp_float = float("-1e1000") very_large_exp_float = float("2.5E9999") -invalid_inf_float = float("in") # [use-math-not-float] -invalid_float_call = float("in", base=10) # [use-math-not-float] -nan_float = float("nan") # [use-math-not-float] -neg_nan_float = float("-nan") # [use-math-not-float] -pos_nan_float = float("+nan") # [use-math-not-float] -upper_nan_float = float("NaN") # [use-math-not-float] -typo_nan_float = float("nani") # [use-math-not-float] -other_typo_nan_float = float("nna") # [use-math-not-float] +invalid_inf_float = float("in") # [consider-math-not-float] +invalid_float_call = float("in", base=10) # [consider-math-not-float] +nan_float = float("nan") # [consider-math-not-float] +neg_nan_float = float("-nan") # [consider-math-not-float] +pos_nan_float = float("+nan") # [consider-math-not-float] +upper_nan_float = float("NaN") # [consider-math-not-float] +typo_nan_float = float("nani") # [consider-math-not-float] +other_typo_nan_float = float("nna") # [consider-math-not-float] diff --git a/tests/functional/ext/code_style/cs_use_math_not_float.rc b/tests/functional/ext/code_style/cs_use_math_not_float.rc index 172b229d9c..5081401e9f 100644 --- a/tests/functional/ext/code_style/cs_use_math_not_float.rc +++ b/tests/functional/ext/code_style/cs_use_math_not_float.rc @@ -1,3 +1,3 @@ [MAIN] load-plugins=pylint.extensions.code_style -enable=use-math-not-float +enable=consider-math-not-float diff --git a/tests/functional/ext/code_style/cs_use_math_not_float.txt b/tests/functional/ext/code_style/cs_use_math_not_float.txt index ab75164aef..5d30d7e0b8 100644 --- a/tests/functional/ext/code_style/cs_use_math_not_float.txt +++ b/tests/functional/ext/code_style/cs_use_math_not_float.txt @@ -1,13 +1,13 @@ -use-math-not-float:3:12:3:24::math.inf is preferable to float('inf'):INFERENCE -use-math-not-float:4:16:4:29::-math.inf is preferable to float('-inf'):INFERENCE -use-math-not-float:5:16:5:29::math.inf is preferable to float('+inf'):INFERENCE -use-math-not-float:6:17:6:34::math.inf is preferable to float('infinity'):INFERENCE -use-math-not-float:7:21:7:39::-math.inf is preferable to float('-infinity'):INFERENCE -use-math-not-float:11:20:11:31::math.inf is preferable to float('in'):INFERENCE -use-math-not-float:12:21:12:41::math.inf is preferable to float('in', base=10):INFERENCE -use-math-not-float:13:12:13:24::math.nan is preferable to float('nan'):INFERENCE -use-math-not-float:14:16:14:29::math.nan is preferable to float('-nan'):INFERENCE -use-math-not-float:15:16:15:29::math.nan is preferable to float('+nan'):INFERENCE -use-math-not-float:16:18:16:30::math.nan is preferable to float('NaN'):INFERENCE -use-math-not-float:17:17:17:30::math.nan is preferable to float('nani'):INFERENCE -use-math-not-float:18:23:18:35::math.nan is preferable to float('nna'):INFERENCE +consider-math-not-float:3:12:3:24::Consider math.inf instead of float('inf'):INFERENCE +consider-math-not-float:4:16:4:29::Consider -math.inf instead of float('-inf'):INFERENCE +consider-math-not-float:5:16:5:29::Consider math.inf instead of float('+inf'):INFERENCE +consider-math-not-float:6:17:6:34::Consider math.inf instead of float('infinity'):INFERENCE +consider-math-not-float:7:21:7:39::Consider -math.inf instead of float('-infinity'):INFERENCE +consider-math-not-float:11:20:11:31::Consider math.inf instead of float('in'):INFERENCE +consider-math-not-float:12:21:12:41::Consider math.inf instead of float('in', base=10):INFERENCE +consider-math-not-float:13:12:13:24::Consider math.nan instead of float('nan'):INFERENCE +consider-math-not-float:14:16:14:29::Consider math.nan instead of float('-nan'):INFERENCE +consider-math-not-float:15:16:15:29::Consider math.nan instead of float('+nan'):INFERENCE +consider-math-not-float:16:18:16:30::Consider math.nan instead of float('NaN'):INFERENCE +consider-math-not-float:17:17:17:30::Consider math.nan instead of float('nani'):INFERENCE +consider-math-not-float:18:23:18:35::Consider math.nan instead of float('nna'):INFERENCE From 2cd4cdada81ce75f580a090cd1a591bd6a05b752 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Tue, 7 Oct 2025 10:32:01 +0200 Subject: [PATCH 5/7] Update doc/user_guide/checkers/extensions.rst Co-authored-by: Morwenn --- doc/user_guide/checkers/extensions.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/user_guide/checkers/extensions.rst b/doc/user_guide/checkers/extensions.rst index a782a04bf6..250476cc7a 100644 --- a/doc/user_guide/checkers/extensions.rst +++ b/doc/user_guide/checkers/extensions.rst @@ -89,9 +89,9 @@ Code Style checker Messages readability (it's also faster as it avoids an internal exec call). Disabled by default! :consider-math-not-float (R6106): *Consider %smath.%s instead of %s* - Using math.inf or math.nan permits to benefit from typing and it is 4 time + Using math.inf or math.nan permits to benefit from typing and it is up to 4 times faster than a float call (after the initial import of math). This check also - catch typo in float calls as a side effect. + catches typos in float calls as a side effect. .. _pylint.extensions.comparison_placement: From 38914dbd712faf789804b857ebb82b2ef0761056 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Tue, 7 Oct 2025 10:38:53 +0200 Subject: [PATCH 6/7] Upgrade doc / code following typos fix --- doc/user_guide/checkers/extensions.rst | 6 +++--- pylint/extensions/code_style.py | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/user_guide/checkers/extensions.rst b/doc/user_guide/checkers/extensions.rst index 250476cc7a..c9dead7ca3 100644 --- a/doc/user_guide/checkers/extensions.rst +++ b/doc/user_guide/checkers/extensions.rst @@ -89,9 +89,9 @@ Code Style checker Messages readability (it's also faster as it avoids an internal exec call). Disabled by default! :consider-math-not-float (R6106): *Consider %smath.%s instead of %s* - Using math.inf or math.nan permits to benefit from typing and it is up to 4 times - faster than a float call (after the initial import of math). This check also - catches typos in float calls as a side effect. + Using math.inf or math.nan permits to benefit from typing and it is up to 4 + times faster than a float call (after the initial import of math). This check + also catches typos in float calls as a side effect. .. _pylint.extensions.comparison_placement: diff --git a/pylint/extensions/code_style.py b/pylint/extensions/code_style.py index f348d00cbb..d8ea869cb9 100644 --- a/pylint/extensions/code_style.py +++ b/pylint/extensions/code_style.py @@ -78,9 +78,9 @@ class CodeStyleChecker(BaseChecker): "R6106": ( "Consider %smath.%s instead of %s", "consider-math-not-float", - "Using math.inf or math.nan permits to benefit from typing and it is 4 " - "time faster than a float call (after the initial import of math). " - "This check also catch typo in float calls as a side effect.", + "Using math.inf or math.nan permits to benefit from typing and it is up " + "to 4 times faster than a float call (after the initial import of math). " + "This check also catches typos in float calls as a side effect.", ), } options = ( From 3541b9912ed897d2f138aa1aa40634fe9fe59d54 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Tue, 7 Oct 2025 12:19:41 +0200 Subject: [PATCH 7/7] Update doc/whatsnew/fragments/10621.new_check --- doc/whatsnew/fragments/10621.new_check | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/whatsnew/fragments/10621.new_check b/doc/whatsnew/fragments/10621.new_check index 24bafa9336..85ecc32d1b 100644 --- a/doc/whatsnew/fragments/10621.new_check +++ b/doc/whatsnew/fragments/10621.new_check @@ -1,6 +1,7 @@ Add a ``consider-math-not-float`` message. ``float("nan")`` and ``float("inf")`` are slower than their counterpart ``math.inf`` and ``math.nan`` by a factor of 4 (notwithstanding the initial import of math) and they are also not well typed when using mypy. +This check also catches typos in float calls as a side effect. The :ref:`pylint.extensions.code_style` need to be activated for this check to work.