114
114
"Used when there is different newline than expected." ,
115
115
),
116
116
"C0329" : (
117
- "float literal should be written as '%s' instead" ,
117
+ "'%s' %s, and it should be written as '%s' instead" ,
118
118
"bad-float-notation" ,
119
119
"Emitted when a number is written in a non-standard notation. The three "
120
120
"allowed notation above the threshold are the scientific notation, the "
@@ -516,10 +516,9 @@ def process_tokens(self, tokens: list[tokenize.TokenInfo]) -> None:
516
516
if tok_type == tokenize .NUMBER :
517
517
if (
518
518
self .linter .is_message_enabled ("bad-float-notation" )
519
- and
520
519
# You don't deserve a linter if you mix non-decimal notation and
521
520
# exponential or underscore,
522
- "x" not in string # not a hexadecimal
521
+ and "x" not in string # not a hexadecimal
523
522
and "o" not in string # not an octal
524
523
and "j" not in string # not a complex
525
524
and "b" not in string # not a binary
@@ -653,7 +652,7 @@ def _check_bad_float_notation( # pylint: disable=too-many-locals
653
652
or self .linter .config .strict_underscore_notation
654
653
)
655
654
656
- def raise_bad_float_notation () -> None :
655
+ def raise_bad_float_notation (reason : str ) -> None :
657
656
suggested = set ()
658
657
if scientific :
659
658
suggested .add (self .to_standard_scientific_notation (value ))
@@ -663,7 +662,7 @@ def raise_bad_float_notation() -> None:
663
662
suggested .add (self .to_standard_underscore_grouping (value ))
664
663
return self .add_message (
665
664
"bad-float-notation" ,
666
- args = ("' or '" .join (sorted (suggested ))),
665
+ args = (string , reason , "' or '" .join (sorted (suggested ))),
667
666
line = line_num ,
668
667
end_lineno = line_num ,
669
668
col_offset = start [1 ],
@@ -682,11 +681,12 @@ def raise_bad_float_notation() -> None:
682
681
# If the value does not deserve a complex notation then write it in a simple way.
683
682
# The threshold is guaranteed to be higher than those value.
684
683
# When 1 <= value < 10 the engineering notation is equivalent to the scientific notation
685
- return raise_bad_float_notation ()
684
+ return raise_bad_float_notation ("has underscore or exponent" )
686
685
687
686
abs_value = abs (value )
687
+ under_threshold = abs_value < self .linter .config .float_notation_threshold
688
688
should_not_be_checked_because_of_threshold = (
689
- abs_value < self . linter . config . float_notation_threshold # under threshold
689
+ under_threshold # under threshold
690
690
and ( # use scientific or engineering notation and under 1/threshold
691
691
self .linter .config .strict_underscore_notation
692
692
or (
@@ -700,11 +700,22 @@ def raise_bad_float_notation() -> None:
700
700
# This number is free style, we do not have to check it, unless it's
701
701
# written complexly, then it could be badly written
702
702
return None
703
- return raise_bad_float_notation ()
703
+ threshold = self .linter .config .float_notation_threshold
704
+ close_to_zero_threshold = self .to_standard_scientific_notation (
705
+ 1 / threshold
706
+ )
707
+ threshold = self .to_standard_scientific_notation (threshold )
708
+ return raise_bad_float_notation (
709
+ f"is smaller than { close_to_zero_threshold } "
710
+ if under_threshold
711
+ else f"is bigger than { threshold } "
712
+ )
704
713
if has_exponent :
705
714
if self .linter .config .strict_underscore_notation or has_underscore :
706
715
# If we have exponent it means it's not proper underscore
707
- return raise_bad_float_notation ()
716
+ return raise_bad_float_notation (
717
+ "has exponent and underscore at the same time"
718
+ )
708
719
base_as_str , exponent_as_str = string .lower ().split ("e" )
709
720
base = float (base_as_str )
710
721
# print("\tBase:", base, "Exponent:", exponent_as_str)
@@ -713,29 +724,45 @@ def raise_bad_float_notation() -> None:
713
724
self .linter .config .strict_scientific_notation
714
725
and wrong_scientific_notation
715
726
):
716
- return raise_bad_float_notation ()
727
+ return raise_bad_float_notation (
728
+ f"has a base, '{ base } ', that is not strictly inferior to 10"
729
+ if base == 10
730
+ else f"has a base, '{ base } ', that is not between 1 and 10"
731
+ )
717
732
wrong_engineering_notation = not (
718
733
1 <= base < 1000 and int (exponent_as_str ) % 3 == 0
719
734
)
720
735
if (
721
736
self .linter .config .strict_engineering_notation
722
737
and wrong_engineering_notation
723
738
) or (wrong_scientific_notation and wrong_engineering_notation ):
724
- return raise_bad_float_notation ()
739
+ return raise_bad_float_notation (
740
+ f"has an exponent '{ exponent_as_str } ' that is not a multiple of 3"
741
+ if 1 <= base < 1000
742
+ else (
743
+ f"has a base, '{ base } ', that is not strictly inferior to 1000"
744
+ if base == 1000
745
+ else f"has a base, '{ base } ', that is not between 1 and 1000"
746
+ )
747
+ )
725
748
elif has_underscore :
726
749
# If we have underscore and exponent, we suggest exponent by default
727
750
if (
728
751
self .linter .config .strict_scientific_notation
729
752
or self .linter .config .strict_engineering_notation
730
753
):
731
- return raise_bad_float_notation ()
754
+ return raise_bad_float_notation (
755
+ "use underscore instead of exponents" + ""
756
+ if self .linter .config .strict_scientific_notation
757
+ else " that are multiple of 3"
758
+ )
732
759
wrong_underscore_notation = not re .match (
733
760
r"^\d{0,3}(_\d{3})*\.?\d*([eE]-?\d{0,3}(_\d{3})*)?$" , string
734
761
)
735
762
if pep515 and wrong_underscore_notation :
736
- return raise_bad_float_notation ()
737
- else :
738
- return raise_bad_float_notation ( )
763
+ return raise_bad_float_notation (
764
+ "has underscores that are not delimiting packs of three digits"
765
+ )
739
766
return None
740
767
741
768
def _check_line_ending (self , line_ending : str , line_num : int ) -> None :
0 commit comments