Skip to content

Commit 8357bd3

Browse files
Fix pylint regression with invalid format strings (#2496) (#2497)
Catch exceptions when calling string.format (cherry picked from commit 04f4f3f) Co-authored-by: Eric Vergnaud <[email protected]>
1 parent 47030b1 commit 8357bd3

File tree

3 files changed

+66
-28
lines changed

3 files changed

+66
-28
lines changed

ChangeLog

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ What's New in astroid 3.3.1?
1313
============================
1414
Release date: TBA
1515

16+
* Fix a crash introduced in 3.3.0 involving invalid format strings.
17+
18+
Closes #2492
1619

1720

1821
What's New in astroid 3.3.0?

astroid/nodes/node_classes.py

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4687,19 +4687,24 @@ def _infer(
46874687
uninferable_already_generated = True
46884688
continue
46894689
for value in self.value.infer(context, **kwargs):
4690-
if not isinstance(value, Const):
4691-
if not uninferable_already_generated:
4692-
yield util.Uninferable
4693-
uninferable_already_generated = True
4694-
continue
4695-
formatted = format(value.value, format_spec.value)
4696-
yield Const(
4697-
formatted,
4698-
lineno=self.lineno,
4699-
col_offset=self.col_offset,
4700-
end_lineno=self.end_lineno,
4701-
end_col_offset=self.end_col_offset,
4702-
)
4690+
if isinstance(value, Const):
4691+
try:
4692+
formatted = format(value.value, format_spec.value)
4693+
yield Const(
4694+
formatted,
4695+
lineno=self.lineno,
4696+
col_offset=self.col_offset,
4697+
end_lineno=self.end_lineno,
4698+
end_col_offset=self.end_col_offset,
4699+
)
4700+
continue
4701+
except (ValueError, TypeError):
4702+
# happens when format_spec.value is invalid
4703+
pass # fall through
4704+
if not uninferable_already_generated:
4705+
yield util.Uninferable
4706+
uninferable_already_generated = True
4707+
continue
47034708

47044709

47054710
MISSING_VALUE = "{MISSING_VALUE}"

tests/test_inference.py

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -666,21 +666,6 @@ def test_fstring_inference(self) -> None:
666666
self.assertIsInstance(value_node, Const)
667667
self.assertEqual(value_node.value, "Hello John!")
668668

669-
def test_formatted_fstring_inference(self) -> None:
670-
code = """
671-
width = 10
672-
precision = 4
673-
value = 12.34567
674-
result = f"result: {value:{width}.{precision}}!"
675-
"""
676-
ast = parse(code, __name__)
677-
node = ast["result"]
678-
inferred = node.inferred()
679-
self.assertEqual(len(inferred), 1)
680-
value_node = inferred[0]
681-
self.assertIsInstance(value_node, Const)
682-
self.assertEqual(value_node.value, "result: 12.35!")
683-
684669
def test_float_complex_ambiguity(self) -> None:
685670
code = '''
686671
def no_conjugate_member(magic_flag): #@
@@ -5517,6 +5502,51 @@ class instance(object):
55175502
self.assertIsInstance(inferred, Instance)
55185503

55195504

5505+
@pytest.mark.parametrize(
5506+
"code, result",
5507+
[
5508+
# regular f-string
5509+
(
5510+
"""width = 10
5511+
precision = 4
5512+
value = 12.34567
5513+
result = f"result: {value:{width}.{precision}}!"
5514+
""",
5515+
"result: 12.35!",
5516+
),
5517+
# unsupported format
5518+
(
5519+
"""width = None
5520+
precision = 4
5521+
value = 12.34567
5522+
result = f"result: {value:{width}.{precision}}!"
5523+
""",
5524+
None,
5525+
),
5526+
# unsupported value
5527+
(
5528+
"""width = 10
5529+
precision = 4
5530+
value = None
5531+
result = f"result: {value:{width}.{precision}}!"
5532+
""",
5533+
None,
5534+
),
5535+
],
5536+
)
5537+
def test_formatted_fstring_inference(code, result) -> None:
5538+
ast = parse(code, __name__)
5539+
node = ast["result"]
5540+
inferred = node.inferred()
5541+
assert len(inferred) == 1
5542+
value_node = inferred[0]
5543+
if result is None:
5544+
assert value_node is util.Uninferable
5545+
else:
5546+
assert isinstance(value_node, Const)
5547+
assert value_node.value == result
5548+
5549+
55205550
def test_augassign_recursion() -> None:
55215551
"""Make sure inference doesn't throw a RecursionError.
55225552

0 commit comments

Comments
 (0)