Skip to content

Commit cbe8b6a

Browse files
Fix the strict notation functional tests
1 parent 74a6ffe commit cbe8b6a

File tree

7 files changed

+142
-93
lines changed

7 files changed

+142
-93
lines changed
Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1 @@
11
proper_grouping = 123_456_789
2-
scientific_notation = 1.2345678e16
3-
engineering_notation = 12.345678e15

pylint/checkers/format.py

Lines changed: 114 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -313,22 +313,29 @@ def open(self) -> None:
313313
scientific = self.linter.config.strict_scientific_notation
314314
engineering = self.linter.config.strict_engineering_notation
315315
underscore = self.linter.config.strict_underscore_notation
316-
float_config = sum([scientific, engineering, underscore])
317-
if float_config > 1:
316+
number_of_strict_float_notation = sum([scientific, engineering, underscore])
317+
if number_of_strict_float_notation > 1:
318318
raise ValueError(
319319
"Only one of strict-scientific-notation, "
320-
"strict-engineering-notation, or strict-underscore-notation "
320+
"'strict-engineering-notation', or 'strict-underscore-notation' "
321321
"can be set to True at a time."
322322
)
323-
if float_config == 0:
324-
# i.e. nothing is strict so we should check all
325-
self.should_check_scientific_notation = True
326-
self.should_check_engineering_notation = True
327-
self.should_check_underscore_notation = True
328-
else:
329-
self.should_check_scientific_notation = scientific
330-
self.should_check_engineering_notation = engineering
331-
self.should_check_underscore_notation = underscore
323+
self.all_float_notation_allowed = number_of_strict_float_notation == 0
324+
if (
325+
self.linter.config.float_notation_threshold < 10
326+
and self.linter.config.strict_scientific_notation
327+
):
328+
raise ValueError(
329+
"'float-notation-threshold' must be at least 10 "
330+
"when 'strict-scientific-notation' is enabled, got "
331+
f"{self.linter.config.float_notation_threshold}."
332+
)
333+
if self.linter.config.float_notation_threshold < 1000:
334+
raise ValueError(
335+
"'float-notation-threshold' must be at least 1000 "
336+
f"when 'strict-scientific-notation' is disabled, got "
337+
f"{self.linter.config.float_notation_threshold}."
338+
)
332339

333340
def new_line(self, tokens: TokenWrapper, line_end: int, line_start: int) -> None:
334341
"""A new line has been encountered, process it if necessary."""
@@ -557,6 +564,9 @@ def to_standard_or_engineering_base(cls, number: float) -> tuple[str, str]:
557564
"""
558565
if number == 0:
559566
return "0", "0"
567+
if number == math.inf:
568+
return "math.inf", "0"
569+
print(f"Converting {number} to standard or engineering base")
560570
exponent = math.floor(math.log10(abs(number)))
561571
if exponent == 0:
562572
return str(number), "0"
@@ -570,6 +580,8 @@ def to_standard_or_engineering_base(cls, number: float) -> tuple[str, str]:
570580
@classmethod
571581
def to_standard_scientific_notation(cls, number: float) -> str:
572582
base, exp = cls.to_standard_or_engineering_base(number)
583+
if base == "math.inf":
584+
return "math.inf"
573585
if exp != "0":
574586
return f"{base}e{int(exp)}"
575587
if "." in base:
@@ -579,6 +591,8 @@ def to_standard_scientific_notation(cls, number: float) -> str:
579591
@classmethod
580592
def to_standard_engineering_notation(cls, number: float) -> str:
581593
base, exp = cls.to_standard_or_engineering_base(number)
594+
if base == "math.inf":
595+
return "math.inf"
582596
exp_value = int(exp)
583597
remainder = exp_value % 3
584598
# For negative exponents, the adjustment is different
@@ -623,91 +637,114 @@ def to_standard_underscore_grouping(cls, number: float) -> str:
623637
grouped_int_part = digit + grouped_int_part
624638
return f"{grouped_int_part}.{dec_part}"
625639

626-
def _check_bad_float_notation(
640+
def _check_bad_float_notation( # pylint: disable=too-many-locals
627641
self, line_num: int, start: tuple[int, int], string: str
628642
) -> None:
643+
value = float(string)
644+
engineering = (
645+
self.all_float_notation_allowed
646+
or self.linter.config.strict_engineering_notation
647+
)
648+
scientific = (
649+
self.all_float_notation_allowed
650+
or self.linter.config.strict_scientific_notation
651+
)
652+
pep515 = (
653+
self.all_float_notation_allowed
654+
or self.linter.config.strict_underscore_notation
655+
)
629656

630-
def raise_bad_float_notation(suggested: set[str]) -> None:
657+
def raise_bad_float_notation() -> None:
658+
suggested = set()
659+
if scientific:
660+
suggested.add(self.to_standard_scientific_notation(value))
661+
if engineering:
662+
suggested.add(self.to_standard_engineering_notation(value))
663+
if pep515:
664+
suggested.add(self.to_standard_underscore_grouping(value))
665+
print("\tBad float notation, suggesting:", suggested)
631666
return self.add_message(
632667
"bad-float-notation",
633-
args=("' or '".join(suggested)),
668+
args=("' or '".join(sorted(suggested))),
634669
line=line_num,
670+
end_lineno=line_num,
635671
col_offset=start[1],
672+
end_col_offset=start[1] + len(string),
636673
confidence=HIGH,
637674
)
638675

639-
value = float(string)
640-
threshold = self.linter.config.float_notation_threshold
641-
abs_value = abs(value)
642676
has_underscore = "_" in string
643677
has_exponent = "e" in string or "E" in string
678+
should_be_written_simply = (
679+
1 <= value < 10 and self.linter.config.strict_scientific_notation
680+
) or 1 <= value < 1000
681+
is_written_complexly = has_underscore or has_exponent
682+
print(f"Checking {string} line {line_num}")
683+
if should_be_written_simply and is_written_complexly:
684+
print(f"\t{value} is a simple number")
685+
# If the value does not deserve a complex notation then write it in a simple way.
686+
# The threshold is guaranteed to be higher than those value.
687+
# When 1 <= value < 10 the engineering notation is equivalent to the scientific notation
688+
return raise_bad_float_notation()
689+
690+
abs_value = abs(value)
691+
should_not_be_checked_because_of_threshold = (
692+
abs_value < self.linter.config.float_notation_threshold # under threshold
693+
and ( # use scientific or engineering notation and under 1/threshold
694+
self.linter.config.strict_underscore_notation
695+
or abs_value > 1 / self.linter.config.float_notation_threshold
696+
)
697+
)
644698
print(
645-
f"Checking {string} {line_num}: "
646-
f"s:{self.should_check_scientific_notation} "
647-
f"e:{self.should_check_engineering_notation} "
648-
f"u;{self.should_check_underscore_notation} "
649-
f"has_underscore: {has_underscore} "
650-
f"has_exponent: {has_exponent} "
651-
f"abs_value: {abs_value} "
652-
f"threshold: {threshold} "
653-
f"strict_scientific_notation: {self.linter.config.strict_scientific_notation} "
699+
"\tshould_not_be_checked_because_of_threshold=",
700+
should_not_be_checked_because_of_threshold,
654701
)
702+
if not is_written_complexly:
703+
if should_not_be_checked_because_of_threshold:
704+
# This number is free style, we do not have to check it, unless it's
705+
# written complexly, then it could be badly written
706+
print("\tFree style number, no need to check")
707+
return None
708+
return raise_bad_float_notation()
655709
if has_exponent:
656710
if self.linter.config.strict_underscore_notation:
657711
# If we have exponent it means it's not proper underscore
658-
return raise_bad_float_notation(
659-
{self.to_standard_underscore_grouping(value)}
660-
)
661-
if abs_value > threshold or abs_value < 1 / threshold:
662-
value_as_str, exponent_as_str = string.lower().split("e")
663-
value = float(value_as_str)
664-
wrong_scientific_notation = (
665-
self.should_check_scientific_notation and not (1 <= value < 10)
666-
)
667-
if (
668-
self.linter.config.strict_scientific_notation
669-
and wrong_scientific_notation
670-
):
671-
return raise_bad_float_notation(
672-
{self.to_standard_scientific_notation(value)}
673-
)
674-
wrong_engineering_notation = (
675-
self.should_check_engineering_notation
676-
and not (1 <= value < 1000 and int(exponent_as_str) % 3 == 0)
677-
)
678-
if (
679-
self.linter.config.strict_engineering_notation
680-
and wrong_engineering_notation
681-
):
682-
return raise_bad_float_notation(
683-
{self.to_standard_engineering_notation(value)}
684-
)
685-
if wrong_scientific_notation and wrong_engineering_notation:
686-
return raise_bad_float_notation(
687-
{
688-
self.to_standard_scientific_notation(value),
689-
self.to_standard_engineering_notation(value),
690-
self.to_standard_underscore_grouping(value),
691-
}
692-
)
693-
if has_underscore:
712+
return raise_bad_float_notation()
713+
base_as_str, exponent_as_str = string.lower().split("e")
714+
base = float(base_as_str)
715+
print("\tBase:", base, "Exponent:", exponent_as_str)
716+
wrong_scientific_notation = not (1 <= base < 10)
717+
print(f"\twrong_scientific_notation:{wrong_scientific_notation}")
718+
if (
719+
self.linter.config.strict_scientific_notation
720+
and wrong_scientific_notation
721+
):
722+
return raise_bad_float_notation()
723+
wrong_engineering_notation = not (
724+
1 <= base < 1000 and int(exponent_as_str) % 3 == 0
725+
)
726+
print(f"\twrong_engineering_notation:{wrong_engineering_notation}")
727+
if (
728+
self.linter.config.strict_engineering_notation
729+
and wrong_engineering_notation
730+
) or (wrong_scientific_notation and wrong_engineering_notation):
731+
return raise_bad_float_notation()
732+
elif has_underscore:
694733
# If we have underscore and exponent, we suggest exponent by default
695-
if self.linter.config.strict_scientific_notation:
696-
return raise_bad_float_notation(
697-
{self.to_standard_scientific_notation(value)}
698-
)
699-
if self.linter.config.strict_engineering_notation:
700-
return raise_bad_float_notation(
701-
{self.to_standard_engineering_notation(value)}
702-
)
703-
underscore_notation = has_underscore and re.match(
734+
print("\tHas underscore, checking underscore grouping")
735+
if (
736+
self.linter.config.strict_scientific_notation
737+
or self.linter.config.strict_engineering_notation
738+
):
739+
return raise_bad_float_notation()
740+
wrong_underscore_notation = not re.match(
704741
r"^\d{0,3}(_\d{3})*\.?\d*([eE]-?\d{0,3}(_\d{3})*)?$", string
705742
)
706-
if not underscore_notation:
707-
return raise_bad_float_notation(
708-
{self.to_standard_underscore_grouping(value)}
709-
)
710-
return None
743+
print(f"\twrong_underscore_notation:{wrong_underscore_notation}")
744+
if pep515 and wrong_underscore_notation:
745+
return raise_bad_float_notation()
746+
else:
747+
return raise_bad_float_notation()
711748
return None
712749

713750
def _check_line_ending(self, line_ending: str, line_num: int) -> None:
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
bad-float-notation:3:33:3:38::float literal should be written as '1.23e6' instead:HIGH
2+
bad-float-notation:4:38:4:45::float literal should be written as '12.344999999999999e9' instead:HIGH
3+
bad-float-notation:5:35:5:43::float literal should be written as '10e6' instead:HIGH
4+
bad-float-notation:6:33:6:38::float literal should be written as '990.0' instead:HIGH

tests/functional/b/bad_float/bad_float_notation_default.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,22 +24,22 @@
2424
under_a_thousand = 990
2525

2626
# Content of bad_float_scientific_notation strict tests tested with default configuration
27-
base_not_between_one_and_ten = 10e3 # [bad-float-notation]
27+
base_not_between_one_and_ten = 10e3
2828
above_threshold_without_exponent_2 = 10000000 # [bad-float-notation]
2929
under_ten_with_exponent = 9.9e0 # [bad-float-notation]
3030
base_between_one_and_ten = 1e4
3131
above_threshold_with_exponent = 1e7
3232
under_ten = 9.9
3333

3434

35-
wrong_big = 45.3e6 # [bad-float-notation]
36-
uppercase_e_wrong = 45.3E6 # [bad-float-notation]
35+
wrong_big = 45.3e7 # [bad-float-notation]
36+
uppercase_e_wrong = 45.3E7 # [bad-float-notation]
3737
wrong_small = 0.00012e-26 # [bad-float-notation]
3838
uppercase_e_wrong_small = 0.00012E-26 # [bad-float-notation]
39-
wrong_negative_and_big = -10e3 # [bad-float-notation]
40-
actual_trolling = 11000e26 # [bad-float-notation]
39+
wrong_negative_and_big = -10e5 # [bad-float-notation]
40+
actual_trolling = 11000e27 # [bad-float-notation]
4141
scientific_double_digit = 12e8 # [bad-float-notation]
42-
scientific_triple_digit = 123e3 # [bad-float-notation]
42+
scientific_triple_digit = 123e3
4343
zero_before_decimal_small = 0.0001e-5 # [bad-float-notation]
4444
zero_before_decimal_big = 0.0001e5 # [bad-float-notation]
4545
negative_decimal = -0.5e10 # [bad-float-notation]
@@ -57,9 +57,10 @@
5757
correct_with_plus = 1.2e+10
5858
correct_decimal_only = 3.14
5959
negative_correct = -5.67e-8
60-
correct_small_exponent = 1.5e1
61-
actually_nine = 9e0
62-
actually_one = 1.0e0
60+
correct_small_exponent = 1.5e1 # [bad-float-notation]
61+
actually_nine = 9e0 # [bad-float-notation]
62+
actually_one = 1.0e0 # [bad-float-notation]
63+
6364

6465

6566
hex_constant = 0x1e4 # Hexadecimal, not scientific notation
@@ -76,15 +77,15 @@
7677

7778
complex_number = 1.5e3 + 2.5e3j # Complex number with scientific notation
7879
# false negative for complex numbers:
79-
complex_number_wrong = 15e3 + 25e3j # [bad-float-notation]
80+
complex_number_wrong = 15e4 + 25e7j # [bad-float-notation]
8081

8182

8283
#+1: [bad-float-notation, bad-float-notation]
83-
def function_with_sci(param=10.0e3, other_param=20.0e3):
84+
def function_with_sci(param=10.0e4, other_param=20.0e5):
8485
return param, other_param
8586

8687
#+1: [bad-float-notation, bad-float-notation]
87-
result = function_with_sci(20.0e3, 10.0e3)
88+
result = function_with_sci(20.0e4, 10.0e7)
8889

8990
valid_underscore_int = 1_000_000
9091
valid_underscore_float = 1_000_000.12345

tests/functional/b/bad_float/bad_float_pep515.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
not_grouped_by_three = 1_23_456_7_89 # [bad-float-notation]
44
mixing_with_exponent = 1_23_4_5_67_8e9 # [bad-float-notation]
55
above_threshold_without_grouping = 123456789 # [bad-float-notation]
6+
scientific_notation = 1.2345678e16 # [bad-float-notation]
7+
engineering_notation = 12.345678e15 # [bad-float-notation]
8+
69
proper_grouping = 123_456_789
7-
scientific_notation = 1.2345678e16
8-
engineering_notation = 12.345678e15
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
bad-float-notation:3:23:3:36::float literal should be written as '123_456_789.0' instead:HIGH
2+
bad-float-notation:4:23:4:38::float literal should be written as '1.2345678e+16' instead:HIGH
3+
bad-float-notation:5:35:5:44::float literal should be written as '123_456_789.0' instead:HIGH
4+
bad-float-notation:6:22:6:34::float literal should be written as '1.2345678e+16' instead:HIGH
5+
bad-float-notation:7:23:7:35::float literal should be written as '1.2345678e+16' instead:HIGH
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
bad-float-notation:3:31:3:35::float literal should be written as '1e4' instead:HIGH
2+
bad-float-notation:4:35:4:43::float literal should be written as '1e7' instead:HIGH
3+
bad-float-notation:5:26:5:31::float literal should be written as '9.9' instead:HIGH

0 commit comments

Comments
 (0)