Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add format-string-without-interpolation checker #4794

Merged
merged 7 commits into from
Aug 4, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ Release date: TBA
Closes #3608
Closes #4346

* Added ``format-string-without-interpolation`` checker: Emitted when formatting is applied to a string without any variables to be replaced

Closes #4042


What's New in Pylint 2.9.6?
===========================
Expand Down
4 changes: 4 additions & 0 deletions doc/whatsnew/2.10.rst
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,7 @@ Other Changes
Closes #3249
Closes #3608
Closes #4346

* Added ``format-string-without-interpolation`` checker: Emitted when formatting is applied to a string without any variables to be replaced

Closes #4042
14 changes: 14 additions & 0 deletions pylint/checkers/strings.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,13 @@
"Used when we detect an f-string that does not use any interpolation variables, "
"in which case it can be either a normal string or a bug in the code.",
),
"W1310": (
"Using formatting for a string that does not have any interpolated variables",
"format-string-without-interpolation",
"Used when we detect a string that does not have any interpolation variables, "
"in which case it can be either a normal string without formatting or a bug in the code.",
DanielNoord marked this conversation as resolved.
Show resolved Hide resolved
{"old_names": [("E1305", "too-many-format-args")]},
),
}

OTHER_NODES = (
Expand Down Expand Up @@ -273,6 +280,7 @@ class StringFormatChecker(BaseChecker):
"too-many-format-args",
"too-few-format-args",
"bad-string-format-type",
"format-string-without-interpolation",
)
def visit_binop(self, node):
if node.op != "%":
Expand Down Expand Up @@ -301,6 +309,9 @@ def visit_binop(self, node):
except utils.IncompleteFormatString:
self.add_message("truncated-format-string", node=node)
return
if not required_keys and not required_num_args:
self.add_message("format-string-without-interpolation", node=node)
return
if required_keys and required_num_args:
# The format string uses both named and unnamed format
# specifiers.
Expand Down Expand Up @@ -518,6 +529,9 @@ def _check_new_format(self, node, func):
if check_args:
# num_args can be 0 if manual_pos is not.
num_args = num_args or manual_pos
if not num_args:
self.add_message("format-string-without-interpolation", node=node)
return
if len(positional_arguments) > num_args:
self.add_message("too-many-format-args", node=node)
elif len(positional_arguments) < num_args:
Expand Down
5 changes: 1 addition & 4 deletions pylint/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,7 @@ def find_pylintrc():

PYLINTRC = find_pylintrc()

ENV_HELP = (
"""
ENV_HELP = """
The following environment variables are used:
* PYLINTHOME
Path to the directory where persistent data for the run will be stored. If
Expand All @@ -126,5 +125,3 @@ def find_pylintrc():
Path to the configuration file. See the documentation for the method used
to search for configuration file.
"""
% globals() # type: ignore
)
6 changes: 5 additions & 1 deletion tests/functional/s/string/string_formatting.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def print_good():

def pprint_bad():
"""Test string format """
"{{}}".format(1) # [too-many-format-args]
"{{}}".format(1) # [format-string-without-interpolation]
DanielNoord marked this conversation as resolved.
Show resolved Hide resolved
"{} {".format() # [bad-format-string]
"{} }".format() # [bad-format-string]
"{0} {}".format(1, 2) # [format-combined-specification]
Expand Down Expand Up @@ -98,6 +98,10 @@ def pprint_bad():
"{[0]} {}".format([4], 5, 6) # [too-many-format-args]
logging.debug("%s %s", 42) # [logging-too-few-args]
logging.debug("%s", 42, 43) # [logging-too-many-args]
"String".format(1) # [format-string-without-interpolation]
"String".format(()) # [format-string-without-interpolation]
"String".format([]) # [format-string-without-interpolation]
"String".format(None) # [format-string-without-interpolation]


def good_issue288(*args, **kwargs):
Expand Down
26 changes: 15 additions & 11 deletions tests/functional/s/string/string_formatting.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
too-many-format-args:68:4:pprint_bad:Too many arguments for format string
format-string-without-interpolation:68:4:pprint_bad:Using formatting for a string that does not have any interpolated variables
bad-format-string:69:4:pprint_bad:Invalid format string
bad-format-string:70:4:pprint_bad:Invalid format string
format-combined-specification:71:4:pprint_bad:Format string contains both automatic field numbering and manual field specification
Expand Down Expand Up @@ -31,13 +31,17 @@ too-few-format-args:97:4:pprint_bad:Not enough arguments for format string
too-many-format-args:98:4:pprint_bad:Too many arguments for format string
logging-too-few-args:99:4:pprint_bad:Not enough arguments for logging format string
logging-too-many-args:100:4:pprint_bad:Too many arguments for logging format string
too-few-format-args:128:4:nested_issue294:Not enough arguments for format string
too-many-format-args:129:4:nested_issue294:Too many arguments for format string
missing-format-argument-key:130:4:nested_issue294:Missing keyword argument 'a' for format string
missing-format-attribute:131:4:nested_issue294:Missing format attribute 'x' in format specifier 'a.x'
too-few-format-args:137:4:issue310:Not enough arguments for format string
too-many-format-args:145:4:issue322:Too many arguments for format string
too-few-format-args:146:4:issue322:Not enough arguments for format string
too-few-format-args:171:4:issue351:Not enough arguments for format string
too-many-format-args:173:4:issue351:Too many arguments for format string
bad-format-string:209:11:avoid_empty_attribute:Invalid format string
format-string-without-interpolation:101:4:pprint_bad:Using formatting for a string that does not have any interpolated variables
format-string-without-interpolation:102:4:pprint_bad:Using formatting for a string that does not have any interpolated variables
format-string-without-interpolation:103:4:pprint_bad:Using formatting for a string that does not have any interpolated variables
format-string-without-interpolation:104:4:pprint_bad:Using formatting for a string that does not have any interpolated variables
too-few-format-args:132:4:nested_issue294:Not enough arguments for format string
too-many-format-args:133:4:nested_issue294:Too many arguments for format string
missing-format-argument-key:134:4:nested_issue294:Missing keyword argument 'a' for format string
missing-format-attribute:135:4:nested_issue294:Missing format attribute 'x' in format specifier 'a.x'
too-few-format-args:141:4:issue310:Not enough arguments for format string
too-many-format-args:149:4:issue322:Too many arguments for format string
too-few-format-args:150:4:issue322:Not enough arguments for format string
too-few-format-args:175:4:issue351:Not enough arguments for format string
too-many-format-args:177:4:issue351:Too many arguments for format string
bad-format-string:213:11:avoid_empty_attribute:Invalid format string
4 changes: 4 additions & 0 deletions tests/functional/s/string/string_formatting_error.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,7 @@ def pprint():
print("%2z" % PARG_1) # [bad-format-character]
print("strange format %2" % PARG_2) # [truncated-format-string]
print("works in 3 %a" % 1)
print("String" % PARG_1) # [format-string-without-interpolation]
print("String" % ()) # [format-string-without-interpolation]
print("String" % []) # [format-string-without-interpolation]
print("String" % None) # [format-string-without-interpolation]
4 changes: 4 additions & 0 deletions tests/functional/s/string/string_formatting_error.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ format-needs-mapping:16:10:pprint:Expected mapping for format string, not Tuple
format-needs-mapping:17:10:pprint:Expected mapping for format string, not List
bad-format-character:18:10:pprint:Unsupported format character 'z' (0x7a) at index 2
truncated-format-string:19:10:pprint:Format string ends in middle of conversion specifier
format-string-without-interpolation:21:10:pprint:Using formatting for a string that does not have any interpolated variables
format-string-without-interpolation:22:10:pprint:Using formatting for a string that does not have any interpolated variables
format-string-without-interpolation:23:10:pprint:Using formatting for a string that does not have any interpolated variables
format-string-without-interpolation:24:10:pprint:Using formatting for a string that does not have any interpolated variables