Method: pylint.checkers.strings.StringFormatChecker.visit_binop
Calls: 815, Exceptions: 2, Paths: 29Back
Path 1: 688 calls (0.84)
BinOp (688)
None (688)
1@only_required_for_messages(
2 "bad-format-character",
3 "truncated-format-string",
4 "mixed-format-string",
5 "bad-format-string-key",
6 "missing-format-string-key",
7 "unused-format-string-key",
8 "bad-string-format-type",
9 "format-needs-mapping",
10 "too-many-format-args",
11 "too-few-format-args",
12 "format-string-without-interpolation",
13 )
14 def visit_binop(self, node: nodes.BinOp) -> None:
15 if node.op != "%":
16 return
17 left = node.left
18 args = node.right
19
20 if not (isinstance(left, nodes.Const) and isinstance(left.value, str)):
21 return
22 format_string = left.value
23 try:
24 (
25 required_keys,
26 required_num_args,
27 required_key_types,
28 required_arg_types,
29 ) = utils.parse_format_string(format_string)
30 except utils.UnsupportedFormatCharacter as exc:
31 formatted = format_string[exc.index]
32 self.add_message(
33 "bad-format-character",
34 node=node,
35 args=(formatted, ord(formatted), exc.index),
36 )
37 return
38 except utils.IncompleteFormatString:
39 self.add_message("truncated-format-string", node=node)
40 return
41 if not required_keys and not required_num_args:
42 self.add_message("format-string-without-interpolation", node=node)
43 return
44 if required_keys and required_num_args:
45 # The format string uses both named and unnamed format
46 # specifiers.
47 self.add_message("mixed-format-string", node=node)
48 elif required_keys:
49 # The format string uses only named format specifiers.
50 # Check that the RHS of the % operator is a mapping object
51 # that contains precisely the set of keys required by the
52 # format string.
53 if isinstance(args, nodes.Dict):
54 keys = set()
55 unknown_keys = False
56 for k, _ in args.items:
57 if isinstance(k, nodes.Const):
58 key = k.value
59 if isinstance(key, str):
60 keys.add(key)
61 else:
62 self.add_message(
63 "bad-format-string-key", node=node, args=key
64 )
65 else:
66 # One of the keys was something other than a
67 # constant. Since we can't tell what it is,
68 # suppress checks for missing keys in the
69 # dictionary.
70 unknown_keys = True
71 if not unknown_keys:
72 for key in required_keys:
73 if key not in keys:
74 self.add_message(
75 "missing-format-string-key", node=node, args=key
76 )
77 for key in keys:
78 if key not in required_keys:
79 self.add_message(
80 "unused-format-string-key", node=node, args=key
81 )
82 for key, arg in args.items:
83 if not isinstance(key, nodes.Const):
84 continue
85 format_type = required_key_types.get(key.value, None)
86 arg_type = utils.safe_infer(arg)
87 if (
88 format_type is not None
89 and arg_type
90 and arg_type != astroid.Uninferable
91 and not arg_matches_format_type(arg_type, format_type)
92 ):
93 self.add_message(
94 "bad-string-format-type",
95 node=node,
96 args=(arg_type.pytype(), format_type),
97 )
98 elif isinstance(args, (OTHER_NODES, nodes.Tuple)):
99 type_name = type(args).__name__
100 self.add_message("format-needs-mapping", node=node, args=type_name)
101 # else:
102 # The RHS of the format specifier is a name or
103 # expression. It may be a mapping object, so
104 # there's nothing we can check.
105 else:
106 # The format string uses only unnamed format specifiers.
107 # Check that the number of arguments passed to the RHS of
108 # the % operator matches the number required by the format
109 # string.
110 args_elts = []
111 if isinstance(args, nodes.Tuple):
112 rhs_tuple = utils.safe_infer(args)
113 num_args = None
114 if isinstance(rhs_tuple, nodes.BaseContainer):
115 args_elts = rhs_tuple.elts
116 num_args = len(args_elts)
117 elif isinstance(args, (OTHER_NODES, (nodes.Dict, nodes.DictComp))):
118 args_elts = [args]
119 num_args = 1
120 elif isinstance(args, nodes.Name):
121 inferred = utils.safe_infer(args)
122 if isinstance(inferred, nodes.Tuple):
123 # The variable is a tuple, so we need to get the elements
124 # from it for further inspection
125 args_elts = inferred.elts
126 num_args = len(args_elts)
127 elif isinstance(inferred, nodes.Const):
128 args_elts = [inferred]
129 num_args = 1
130 else:
131 num_args = None
132 else:
133 # The RHS of the format specifier is an expression.
134 # It could be a tuple of unknown size, so
135 # there's nothing we can check.
136 num_args = None
137 if num_args is not None:
138 if num_args > required_num_args:
139 self.add_message("too-many-format-args", node=node)
140 elif num_args < required_num_args:
141 self.add_message("too-few-format-args", node=node)
142 for arg, format_type in zip(args_elts, required_arg_types):
143 if not arg:
144 continue
145 arg_type = utils.safe_infer(arg)
146 if (
147 arg_type
148 and arg_type != astroid.Uninferable
149 and not arg_matches_format_type(arg_type, format_type)
150 ):
151 self.add_message(
152 "bad-string-format-type",
153 node=node,
154 args=(arg_type.pytype(), format_type),
155 )
Path 2: 30 calls (0.04)
BinOp (30)
None (30)
1@only_required_for_messages(
2 "bad-format-character",
3 "truncated-format-string",
4 "mixed-format-string",
5 "bad-format-string-key",
6 "missing-format-string-key",
7 "unused-format-string-key",
8 "bad-string-format-type",
9 "format-needs-mapping",
10 "too-many-format-args",
11 "too-few-format-args",
12 "format-string-without-interpolation",
13 )
14 def visit_binop(self, node: nodes.BinOp) -> None:
15 if node.op != "%":
16 return
17 left = node.left
18 args = node.right
19
20 if not (isinstance(left, nodes.Const) and isinstance(left.value, str)):
21 return
22 format_string = left.value
23 try:
24 (
25 required_keys,
26 required_num_args,
27 required_key_types,
28 required_arg_types,
29 ) = utils.parse_format_string(format_string)
30 except utils.UnsupportedFormatCharacter as exc:
31 formatted = format_string[exc.index]
32 self.add_message(
33 "bad-format-character",
34 node=node,
35 args=(formatted, ord(formatted), exc.index),
36 )
37 return
38 except utils.IncompleteFormatString:
39 self.add_message("truncated-format-string", node=node)
40 return
41 if not required_keys and not required_num_args:
42 self.add_message("format-string-without-interpolation", node=node)
43 return
44 if required_keys and required_num_args:
45 # The format string uses both named and unnamed format
46 # specifiers.
47 self.add_message("mixed-format-string", node=node)
48 elif required_keys:
49 # The format string uses only named format specifiers.
50 # Check that the RHS of the % operator is a mapping object
51 # that contains precisely the set of keys required by the
52 # format string.
53 if isinstance(args, nodes.Dict):
54 keys = set()
55 unknown_keys = False
56 for k, _ in args.items:
57 if isinstance(k, nodes.Const):
58 key = k.value
59 if isinstance(key, str):
60 keys.add(key)
61 else:
62 self.add_message(
63 "bad-format-string-key", node=node, args=key
64 )
65 else:
66 # One of the keys was something other than a
67 # constant. Since we can't tell what it is,
68 # suppress checks for missing keys in the
69 # dictionary.
70 unknown_keys = True
71 if not unknown_keys:
72 for key in required_keys:
73 if key not in keys:
74 self.add_message(
75 "missing-format-string-key", node=node, args=key
76 )
77 for key in keys:
78 if key not in required_keys:
79 self.add_message(
80 "unused-format-string-key", node=node, args=key
81 )
82 for key, arg in args.items:
83 if not isinstance(key, nodes.Const):
84 continue
85 format_type = required_key_types.get(key.value, None)
86 arg_type = utils.safe_infer(arg)
87 if (
88 format_type is not None
89 and arg_type
90 and arg_type != astroid.Uninferable
91 and not arg_matches_format_type(arg_type, format_type)
92 ):
93 self.add_message(
94 "bad-string-format-type",
95 node=node,
96 args=(arg_type.pytype(), format_type),
97 )
98 elif isinstance(args, (OTHER_NODES, nodes.Tuple)):
99 type_name = type(args).__name__
100 self.add_message("format-needs-mapping", node=node, args=type_name)
101 # else:
102 # The RHS of the format specifier is a name or
103 # expression. It may be a mapping object, so
104 # there's nothing we can check.
105 else:
106 # The format string uses only unnamed format specifiers.
107 # Check that the number of arguments passed to the RHS of
108 # the % operator matches the number required by the format
109 # string.
110 args_elts = []
111 if isinstance(args, nodes.Tuple):
112 rhs_tuple = utils.safe_infer(args)
113 num_args = None
114 if isinstance(rhs_tuple, nodes.BaseContainer):
115 args_elts = rhs_tuple.elts
116 num_args = len(args_elts)
117 elif isinstance(args, (OTHER_NODES, (nodes.Dict, nodes.DictComp))):
118 args_elts = [args]
119 num_args = 1
120 elif isinstance(args, nodes.Name):
121 inferred = utils.safe_infer(args)
122 if isinstance(inferred, nodes.Tuple):
123 # The variable is a tuple, so we need to get the elements
124 # from it for further inspection
125 args_elts = inferred.elts
126 num_args = len(args_elts)
127 elif isinstance(inferred, nodes.Const):
128 args_elts = [inferred]
129 num_args = 1
130 else:
131 num_args = None
132 else:
133 # The RHS of the format specifier is an expression.
134 # It could be a tuple of unknown size, so
135 # there's nothing we can check.
136 num_args = None
137 if num_args is not None:
138 if num_args > required_num_args:
139 self.add_message("too-many-format-args", node=node)
140 elif num_args < required_num_args:
141 self.add_message("too-few-format-args", node=node)
142 for arg, format_type in zip(args_elts, required_arg_types):
143 if not arg:
144 continue
145 arg_type = utils.safe_infer(arg)
146 if (
147 arg_type
148 and arg_type != astroid.Uninferable
149 and not arg_matches_format_type(arg_type, format_type)
150 ):
151 self.add_message(
152 "bad-string-format-type",
153 node=node,
154 args=(arg_type.pytype(), format_type),
155 )
Path 3: 24 calls (0.03)
BinOp (24)
1@only_required_for_messages(
2 "bad-format-character",
3 "truncated-format-string",
4 "mixed-format-string",
5 "bad-format-string-key",
6 "missing-format-string-key",
7 "unused-format-string-key",
8 "bad-string-format-type",
9 "format-needs-mapping",
10 "too-many-format-args",
11 "too-few-format-args",
12 "format-string-without-interpolation",
13 )
14 def visit_binop(self, node: nodes.BinOp) -> None:
15 if node.op != "%":
16 return
17 left = node.left
18 args = node.right
19
20 if not (isinstance(left, nodes.Const) and isinstance(left.value, str)):
21 return
22 format_string = left.value
23 try:
24 (
25 required_keys,
26 required_num_args,
27 required_key_types,
28 required_arg_types,
29 ) = utils.parse_format_string(format_string)
30 except utils.UnsupportedFormatCharacter as exc:
31 formatted = format_string[exc.index]
32 self.add_message(
33 "bad-format-character",
34 node=node,
35 args=(formatted, ord(formatted), exc.index),
36 )
37 return
38 except utils.IncompleteFormatString:
39 self.add_message("truncated-format-string", node=node)
40 return
41 if not required_keys and not required_num_args:
42 self.add_message("format-string-without-interpolation", node=node)
43 return
44 if required_keys and required_num_args:
45 # The format string uses both named and unnamed format
46 # specifiers.
47 self.add_message("mixed-format-string", node=node)
48 elif required_keys:
49 # The format string uses only named format specifiers.
50 # Check that the RHS of the % operator is a mapping object
51 # that contains precisely the set of keys required by the
52 # format string.
53 if isinstance(args, nodes.Dict):
54 keys = set()
55 unknown_keys = False
56 for k, _ in args.items:
57 if isinstance(k, nodes.Const):
58 key = k.value
59 if isinstance(key, str):
60 keys.add(key)
61 else:
62 self.add_message(
63 "bad-format-string-key", node=node, args=key
64 )
65 else:
66 # One of the keys was something other than a
67 # constant. Since we can't tell what it is,
68 # suppress checks for missing keys in the
69 # dictionary.
70 unknown_keys = True
71 if not unknown_keys:
72 for key in required_keys:
73 if key not in keys:
74 self.add_message(
75 "missing-format-string-key", node=node, args=key
76 )
77 for key in keys:
78 if key not in required_keys:
79 self.add_message(
80 "unused-format-string-key", node=node, args=key
81 )
82 for key, arg in args.items:
83 if not isinstance(key, nodes.Const):
84 continue
85 format_type = required_key_types.get(key.value, None)
86 arg_type = utils.safe_infer(arg)
87 if (
88 format_type is not None
89 and arg_type
90 and arg_type != astroid.Uninferable
91 and not arg_matches_format_type(arg_type, format_type)
92 ):
93 self.add_message(
94 "bad-string-format-type",
95 node=node,
96 args=(arg_type.pytype(), format_type),
97 )
98 elif isinstance(args, (OTHER_NODES, nodes.Tuple)):
99 type_name = type(args).__name__
100 self.add_message("format-needs-mapping", node=node, args=type_name)
101 # else:
102 # The RHS of the format specifier is a name or
103 # expression. It may be a mapping object, so
104 # there's nothing we can check.
105 else:
106 # The format string uses only unnamed format specifiers.
107 # Check that the number of arguments passed to the RHS of
108 # the % operator matches the number required by the format
109 # string.
110 args_elts = []
111 if isinstance(args, nodes.Tuple):
112 rhs_tuple = utils.safe_infer(args)
113 num_args = None
114 if isinstance(rhs_tuple, nodes.BaseContainer):
115 args_elts = rhs_tuple.elts
116 num_args = len(args_elts)
117 elif isinstance(args, (OTHER_NODES, (nodes.Dict, nodes.DictComp))):
118 args_elts = [args]
119 num_args = 1
120 elif isinstance(args, nodes.Name):
121 inferred = utils.safe_infer(args)
122 if isinstance(inferred, nodes.Tuple):
123 # The variable is a tuple, so we need to get the elements
124 # from it for further inspection
125 args_elts = inferred.elts
126 num_args = len(args_elts)
127 elif isinstance(inferred, nodes.Const):
128 args_elts = [inferred]
129 num_args = 1
130 else:
131 num_args = None
132 else:
133 # The RHS of the format specifier is an expression.
134 # It could be a tuple of unknown size, so
135 # there's nothing we can check.
136 num_args = None
137 if num_args is not None:
138 if num_args > required_num_args:
139 self.add_message("too-many-format-args", node=node)
140 elif num_args < required_num_args:
141 self.add_message("too-few-format-args", node=node)
142 for arg, format_type in zip(args_elts, required_arg_types):
143 if not arg:
144 continue
145 arg_type = utils.safe_infer(arg)
146 if (
147 arg_type
148 and arg_type != astroid.Uninferable
149 and not arg_matches_format_type(arg_type, format_type)
150 ):
151 self.add_message(
152 "bad-string-format-type",
153 node=node,
154 args=(arg_type.pytype(), format_type),
155 )
Path 4: 10 calls (0.01)
BinOp (10)
1@only_required_for_messages(
2 "bad-format-character",
3 "truncated-format-string",
4 "mixed-format-string",
5 "bad-format-string-key",
6 "missing-format-string-key",
7 "unused-format-string-key",
8 "bad-string-format-type",
9 "format-needs-mapping",
10 "too-many-format-args",
11 "too-few-format-args",
12 "format-string-without-interpolation",
13 )
14 def visit_binop(self, node: nodes.BinOp) -> None:
15 if node.op != "%":
16 return
17 left = node.left
18 args = node.right
19
20 if not (isinstance(left, nodes.Const) and isinstance(left.value, str)):
21 return
22 format_string = left.value
23 try:
24 (
25 required_keys,
26 required_num_args,
27 required_key_types,
28 required_arg_types,
29 ) = utils.parse_format_string(format_string)
30 except utils.UnsupportedFormatCharacter as exc:
31 formatted = format_string[exc.index]
32 self.add_message(
33 "bad-format-character",
34 node=node,
35 args=(formatted, ord(formatted), exc.index),
36 )
37 return
38 except utils.IncompleteFormatString:
39 self.add_message("truncated-format-string", node=node)
40 return
41 if not required_keys and not required_num_args:
42 self.add_message("format-string-without-interpolation", node=node)
43 return
44 if required_keys and required_num_args:
45 # The format string uses both named and unnamed format
46 # specifiers.
47 self.add_message("mixed-format-string", node=node)
48 elif required_keys:
49 # The format string uses only named format specifiers.
50 # Check that the RHS of the % operator is a mapping object
51 # that contains precisely the set of keys required by the
52 # format string.
53 if isinstance(args, nodes.Dict):
54 keys = set()
55 unknown_keys = False
56 for k, _ in args.items:
57 if isinstance(k, nodes.Const):
58 key = k.value
59 if isinstance(key, str):
60 keys.add(key)
61 else:
62 self.add_message(
63 "bad-format-string-key", node=node, args=key
64 )
65 else:
66 # One of the keys was something other than a
67 # constant. Since we can't tell what it is,
68 # suppress checks for missing keys in the
69 # dictionary.
70 unknown_keys = True
71 if not unknown_keys:
72 for key in required_keys:
73 if key not in keys:
74 self.add_message(
75 "missing-format-string-key", node=node, args=key
76 )
77 for key in keys:
78 if key not in required_keys:
79 self.add_message(
80 "unused-format-string-key", node=node, args=key
81 )
82 for key, arg in args.items:
83 if not isinstance(key, nodes.Const):
84 continue
85 format_type = required_key_types.get(key.value, None)
86 arg_type = utils.safe_infer(arg)
87 if (
88 format_type is not None
89 and arg_type
90 and arg_type != astroid.Uninferable
91 and not arg_matches_format_type(arg_type, format_type)
92 ):
93 self.add_message(
94 "bad-string-format-type",
95 node=node,
96 args=(arg_type.pytype(), format_type),
97 )
98 elif isinstance(args, (OTHER_NODES, nodes.Tuple)):
99 type_name = type(args).__name__
100 self.add_message("format-needs-mapping", node=node, args=type_name)
101 # else:
102 # The RHS of the format specifier is a name or
103 # expression. It may be a mapping object, so
104 # there's nothing we can check.
105 else:
106 # The format string uses only unnamed format specifiers.
107 # Check that the number of arguments passed to the RHS of
108 # the % operator matches the number required by the format
109 # string.
110 args_elts = []
111 if isinstance(args, nodes.Tuple):
112 rhs_tuple = utils.safe_infer(args)
113 num_args = None
114 if isinstance(rhs_tuple, nodes.BaseContainer):
115 args_elts = rhs_tuple.elts
116 num_args = len(args_elts)
117 elif isinstance(args, (OTHER_NODES, (nodes.Dict, nodes.DictComp))):
118 args_elts = [args]
119 num_args = 1
120 elif isinstance(args, nodes.Name):
121 inferred = utils.safe_infer(args)
122 if isinstance(inferred, nodes.Tuple):
123 # The variable is a tuple, so we need to get the elements
124 # from it for further inspection
125 args_elts = inferred.elts
126 num_args = len(args_elts)
127 elif isinstance(inferred, nodes.Const):
128 args_elts = [inferred]
129 num_args = 1
130 else:
131 num_args = None
132 else:
133 # The RHS of the format specifier is an expression.
134 # It could be a tuple of unknown size, so
135 # there's nothing we can check.
136 num_args = None
137 if num_args is not None:
138 if num_args > required_num_args:
139 self.add_message("too-many-format-args", node=node)
140 elif num_args < required_num_args:
141 self.add_message("too-few-format-args", node=node)
142 for arg, format_type in zip(args_elts, required_arg_types):
143 if not arg:
144 continue
145 arg_type = utils.safe_infer(arg)
146 if (
147 arg_type
148 and arg_type != astroid.Uninferable
149 and not arg_matches_format_type(arg_type, format_type)
150 ):
151 self.add_message(
152 "bad-string-format-type",
153 node=node,
154 args=(arg_type.pytype(), format_type),
155 )
Path 5: 9 calls (0.01)
BinOp (9)
1@only_required_for_messages(
2 "bad-format-character",
3 "truncated-format-string",
4 "mixed-format-string",
5 "bad-format-string-key",
6 "missing-format-string-key",
7 "unused-format-string-key",
8 "bad-string-format-type",
9 "format-needs-mapping",
10 "too-many-format-args",
11 "too-few-format-args",
12 "format-string-without-interpolation",
13 )
14 def visit_binop(self, node: nodes.BinOp) -> None:
15 if node.op != "%":
16 return
17 left = node.left
18 args = node.right
19
20 if not (isinstance(left, nodes.Const) and isinstance(left.value, str)):
21 return
22 format_string = left.value
23 try:
24 (
25 required_keys,
26 required_num_args,
27 required_key_types,
28 required_arg_types,
29 ) = utils.parse_format_string(format_string)
30 except utils.UnsupportedFormatCharacter as exc:
31 formatted = format_string[exc.index]
32 self.add_message(
33 "bad-format-character",
34 node=node,
35 args=(formatted, ord(formatted), exc.index),
36 )
37 return
38 except utils.IncompleteFormatString:
39 self.add_message("truncated-format-string", node=node)
40 return
41 if not required_keys and not required_num_args:
42 self.add_message("format-string-without-interpolation", node=node)
43 return
44 if required_keys and required_num_args:
45 # The format string uses both named and unnamed format
46 # specifiers.
47 self.add_message("mixed-format-string", node=node)
48 elif required_keys:
49 # The format string uses only named format specifiers.
50 # Check that the RHS of the % operator is a mapping object
51 # that contains precisely the set of keys required by the
52 # format string.
53 if isinstance(args, nodes.Dict):
54 keys = set()
55 unknown_keys = False
56 for k, _ in args.items:
57 if isinstance(k, nodes.Const):
58 key = k.value
59 if isinstance(key, str):
60 keys.add(key)
61 else:
62 self.add_message(
63 "bad-format-string-key", node=node, args=key
64 )
65 else:
66 # One of the keys was something other than a
67 # constant. Since we can't tell what it is,
68 # suppress checks for missing keys in the
69 # dictionary.
70 unknown_keys = True
71 if not unknown_keys:
72 for key in required_keys:
73 if key not in keys:
74 self.add_message(
75 "missing-format-string-key", node=node, args=key
76 )
77 for key in keys:
78 if key not in required_keys:
79 self.add_message(
80 "unused-format-string-key", node=node, args=key
81 )
82 for key, arg in args.items:
83 if not isinstance(key, nodes.Const):
84 continue
85 format_type = required_key_types.get(key.value, None)
86 arg_type = utils.safe_infer(arg)
87 if (
88 format_type is not None
89 and arg_type
90 and arg_type != astroid.Uninferable
91 and not arg_matches_format_type(arg_type, format_type)
92 ):
93 self.add_message(
94 "bad-string-format-type",
95 node=node,
96 args=(arg_type.pytype(), format_type),
97 )
98 elif isinstance(args, (OTHER_NODES, nodes.Tuple)):
99 type_name = type(args).__name__
100 self.add_message("format-needs-mapping", node=node, args=type_name)
101 # else:
102 # The RHS of the format specifier is a name or
103 # expression. It may be a mapping object, so
104 # there's nothing we can check.
105 else:
106 # The format string uses only unnamed format specifiers.
107 # Check that the number of arguments passed to the RHS of
108 # the % operator matches the number required by the format
109 # string.
110 args_elts = []
111 if isinstance(args, nodes.Tuple):
112 rhs_tuple = utils.safe_infer(args)
113 num_args = None
114 if isinstance(rhs_tuple, nodes.BaseContainer):
115 args_elts = rhs_tuple.elts
116 num_args = len(args_elts)
117 elif isinstance(args, (OTHER_NODES, (nodes.Dict, nodes.DictComp))):
118 args_elts = [args]
119 num_args = 1
120 elif isinstance(args, nodes.Name):
121 inferred = utils.safe_infer(args)
122 if isinstance(inferred, nodes.Tuple):
123 # The variable is a tuple, so we need to get the elements
124 # from it for further inspection
125 args_elts = inferred.elts
126 num_args = len(args_elts)
127 elif isinstance(inferred, nodes.Const):
128 args_elts = [inferred]
129 num_args = 1
130 else:
131 num_args = None
132 else:
133 # The RHS of the format specifier is an expression.
134 # It could be a tuple of unknown size, so
135 # there's nothing we can check.
136 num_args = None
137 if num_args is not None:
138 if num_args > required_num_args:
139 self.add_message("too-many-format-args", node=node)
140 elif num_args < required_num_args:
141 self.add_message("too-few-format-args", node=node)
142 for arg, format_type in zip(args_elts, required_arg_types):
143 if not arg:
144 continue
145 arg_type = utils.safe_infer(arg)
146 if (
147 arg_type
148 and arg_type != astroid.Uninferable
149 and not arg_matches_format_type(arg_type, format_type)
150 ):
151 self.add_message(
152 "bad-string-format-type",
153 node=node,
154 args=(arg_type.pytype(), format_type),
155 )
Path 6: 8 calls (0.01)
BinOp (8)
1@only_required_for_messages(
2 "bad-format-character",
3 "truncated-format-string",
4 "mixed-format-string",
5 "bad-format-string-key",
6 "missing-format-string-key",
7 "unused-format-string-key",
8 "bad-string-format-type",
9 "format-needs-mapping",
10 "too-many-format-args",
11 "too-few-format-args",
12 "format-string-without-interpolation",
13 )
14 def visit_binop(self, node: nodes.BinOp) -> None:
15 if node.op != "%":
16 return
17 left = node.left
18 args = node.right
19
20 if not (isinstance(left, nodes.Const) and isinstance(left.value, str)):
21 return
22 format_string = left.value
23 try:
24 (
25 required_keys,
26 required_num_args,
27 required_key_types,
28 required_arg_types,
29 ) = utils.parse_format_string(format_string)
30 except utils.UnsupportedFormatCharacter as exc:
31 formatted = format_string[exc.index]
32 self.add_message(
33 "bad-format-character",
34 node=node,
35 args=(formatted, ord(formatted), exc.index),
36 )
37 return
38 except utils.IncompleteFormatString:
39 self.add_message("truncated-format-string", node=node)
40 return
41 if not required_keys and not required_num_args:
42 self.add_message("format-string-without-interpolation", node=node)
43 return
44 if required_keys and required_num_args:
45 # The format string uses both named and unnamed format
46 # specifiers.
47 self.add_message("mixed-format-string", node=node)
48 elif required_keys:
49 # The format string uses only named format specifiers.
50 # Check that the RHS of the % operator is a mapping object
51 # that contains precisely the set of keys required by the
52 # format string.
53 if isinstance(args, nodes.Dict):
54 keys = set()
55 unknown_keys = False
56 for k, _ in args.items:
57 if isinstance(k, nodes.Const):
58 key = k.value
59 if isinstance(key, str):
60 keys.add(key)
61 else:
62 self.add_message(
63 "bad-format-string-key", node=node, args=key
64 )
65 else:
66 # One of the keys was something other than a
67 # constant. Since we can't tell what it is,
68 # suppress checks for missing keys in the
69 # dictionary.
70 unknown_keys = True
71 if not unknown_keys:
72 for key in required_keys:
73 if key not in keys:
74 self.add_message(
75 "missing-format-string-key", node=node, args=key
76 )
77 for key in keys:
78 if key not in required_keys:
79 self.add_message(
80 "unused-format-string-key", node=node, args=key
81 )
82 for key, arg in args.items:
83 if not isinstance(key, nodes.Const):
84 continue
85 format_type = required_key_types.get(key.value, None)
86 arg_type = utils.safe_infer(arg)
87 if (
88 format_type is not None
89 and arg_type
90 and arg_type != astroid.Uninferable
91 and not arg_matches_format_type(arg_type, format_type)
92 ):
93 self.add_message(
94 "bad-string-format-type",
95 node=node,
96 args=(arg_type.pytype(), format_type),
97 )
98 elif isinstance(args, (OTHER_NODES, nodes.Tuple)):
99 type_name = type(args).__name__
100 self.add_message("format-needs-mapping", node=node, args=type_name)
101 # else:
102 # The RHS of the format specifier is a name or
103 # expression. It may be a mapping object, so
104 # there's nothing we can check.
105 else:
106 # The format string uses only unnamed format specifiers.
107 # Check that the number of arguments passed to the RHS of
108 # the % operator matches the number required by the format
109 # string.
110 args_elts = []
111 if isinstance(args, nodes.Tuple):
112 rhs_tuple = utils.safe_infer(args)
113 num_args = None
114 if isinstance(rhs_tuple, nodes.BaseContainer):
115 args_elts = rhs_tuple.elts
116 num_args = len(args_elts)
117 elif isinstance(args, (OTHER_NODES, (nodes.Dict, nodes.DictComp))):
118 args_elts = [args]
119 num_args = 1
120 elif isinstance(args, nodes.Name):
121 inferred = utils.safe_infer(args)
122 if isinstance(inferred, nodes.Tuple):
123 # The variable is a tuple, so we need to get the elements
124 # from it for further inspection
125 args_elts = inferred.elts
126 num_args = len(args_elts)
127 elif isinstance(inferred, nodes.Const):
128 args_elts = [inferred]
129 num_args = 1
130 else:
131 num_args = None
132 else:
133 # The RHS of the format specifier is an expression.
134 # It could be a tuple of unknown size, so
135 # there's nothing we can check.
136 num_args = None
137 if num_args is not None:
138 if num_args > required_num_args:
139 self.add_message("too-many-format-args", node=node)
140 elif num_args < required_num_args:
141 self.add_message("too-few-format-args", node=node)
142 for arg, format_type in zip(args_elts, required_arg_types):
143 if not arg:
144 continue
145 arg_type = utils.safe_infer(arg)
146 if (
147 arg_type
148 and arg_type != astroid.Uninferable
149 and not arg_matches_format_type(arg_type, format_type)
150 ):
151 self.add_message(
152 "bad-string-format-type",
153 node=node,
154 args=(arg_type.pytype(), format_type),
155 )
Path 7: 7 calls (0.01)
BinOp (7)
1@only_required_for_messages(
2 "bad-format-character",
3 "truncated-format-string",
4 "mixed-format-string",
5 "bad-format-string-key",
6 "missing-format-string-key",
7 "unused-format-string-key",
8 "bad-string-format-type",
9 "format-needs-mapping",
10 "too-many-format-args",
11 "too-few-format-args",
12 "format-string-without-interpolation",
13 )
14 def visit_binop(self, node: nodes.BinOp) -> None:
15 if node.op != "%":
16 return
17 left = node.left
18 args = node.right
19
20 if not (isinstance(left, nodes.Const) and isinstance(left.value, str)):
21 return
22 format_string = left.value
23 try:
24 (
25 required_keys,
26 required_num_args,
27 required_key_types,
28 required_arg_types,
29 ) = utils.parse_format_string(format_string)
30 except utils.UnsupportedFormatCharacter as exc:
31 formatted = format_string[exc.index]
32 self.add_message(
33 "bad-format-character",
34 node=node,
35 args=(formatted, ord(formatted), exc.index),
36 )
37 return
38 except utils.IncompleteFormatString:
39 self.add_message("truncated-format-string", node=node)
40 return
41 if not required_keys and not required_num_args:
42 self.add_message("format-string-without-interpolation", node=node)
43 return
44 if required_keys and required_num_args:
45 # The format string uses both named and unnamed format
46 # specifiers.
47 self.add_message("mixed-format-string", node=node)
48 elif required_keys:
49 # The format string uses only named format specifiers.
50 # Check that the RHS of the % operator is a mapping object
51 # that contains precisely the set of keys required by the
52 # format string.
53 if isinstance(args, nodes.Dict):
54 keys = set()
55 unknown_keys = False
56 for k, _ in args.items:
57 if isinstance(k, nodes.Const):
58 key = k.value
59 if isinstance(key, str):
60 keys.add(key)
61 else:
62 self.add_message(
63 "bad-format-string-key", node=node, args=key
64 )
65 else:
66 # One of the keys was something other than a
67 # constant. Since we can't tell what it is,
68 # suppress checks for missing keys in the
69 # dictionary.
70 unknown_keys = True
71 if not unknown_keys:
72 for key in required_keys:
73 if key not in keys:
74 self.add_message(
75 "missing-format-string-key", node=node, args=key
76 )
77 for key in keys:
78 if key not in required_keys:
79 self.add_message(
80 "unused-format-string-key", node=node, args=key
81 )
82 for key, arg in args.items:
83 if not isinstance(key, nodes.Const):
84 continue
85 format_type = required_key_types.get(key.value, None)
86 arg_type = utils.safe_infer(arg)
87 if (
88 format_type is not None
89 and arg_type
90 and arg_type != astroid.Uninferable
91 and not arg_matches_format_type(arg_type, format_type)
92 ):
93 self.add_message(
94 "bad-string-format-type",
95 node=node,
96 args=(arg_type.pytype(), format_type),
97 )
98 elif isinstance(args, (OTHER_NODES, nodes.Tuple)):
99 type_name = type(args).__name__
100 self.add_message("format-needs-mapping", node=node, args=type_name)
101 # else:
102 # The RHS of the format specifier is a name or
103 # expression. It may be a mapping object, so
104 # there's nothing we can check.
105 else:
106 # The format string uses only unnamed format specifiers.
107 # Check that the number of arguments passed to the RHS of
108 # the % operator matches the number required by the format
109 # string.
110 args_elts = []
111 if isinstance(args, nodes.Tuple):
112 rhs_tuple = utils.safe_infer(args)
113 num_args = None
114 if isinstance(rhs_tuple, nodes.BaseContainer):
115 args_elts = rhs_tuple.elts
116 num_args = len(args_elts)
117 elif isinstance(args, (OTHER_NODES, (nodes.Dict, nodes.DictComp))):
118 args_elts = [args]
119 num_args = 1
120 elif isinstance(args, nodes.Name):
121 inferred = utils.safe_infer(args)
122 if isinstance(inferred, nodes.Tuple):
123 # The variable is a tuple, so we need to get the elements
124 # from it for further inspection
125 args_elts = inferred.elts
126 num_args = len(args_elts)
127 elif isinstance(inferred, nodes.Const):
128 args_elts = [inferred]
129 num_args = 1
130 else:
131 num_args = None
132 else:
133 # The RHS of the format specifier is an expression.
134 # It could be a tuple of unknown size, so
135 # there's nothing we can check.
136 num_args = None
137 if num_args is not None:
138 if num_args > required_num_args:
139 self.add_message("too-many-format-args", node=node)
140 elif num_args < required_num_args:
141 self.add_message("too-few-format-args", node=node)
142 for arg, format_type in zip(args_elts, required_arg_types):
143 if not arg:
144 continue
145 arg_type = utils.safe_infer(arg)
146 if (
147 arg_type
148 and arg_type != astroid.Uninferable
149 and not arg_matches_format_type(arg_type, format_type)
150 ):
151 self.add_message(
152 "bad-string-format-type",
153 node=node,
154 args=(arg_type.pytype(), format_type),
155 )
Path 8: 6 calls (0.01)
BinOp (6)
1@only_required_for_messages(
2 "bad-format-character",
3 "truncated-format-string",
4 "mixed-format-string",
5 "bad-format-string-key",
6 "missing-format-string-key",
7 "unused-format-string-key",
8 "bad-string-format-type",
9 "format-needs-mapping",
10 "too-many-format-args",
11 "too-few-format-args",
12 "format-string-without-interpolation",
13 )
14 def visit_binop(self, node: nodes.BinOp) -> None:
15 if node.op != "%":
16 return
17 left = node.left
18 args = node.right
19
20 if not (isinstance(left, nodes.Const) and isinstance(left.value, str)):
21 return
22 format_string = left.value
23 try:
24 (
25 required_keys,
26 required_num_args,
27 required_key_types,
28 required_arg_types,
29 ) = utils.parse_format_string(format_string)
30 except utils.UnsupportedFormatCharacter as exc:
31 formatted = format_string[exc.index]
32 self.add_message(
33 "bad-format-character",
34 node=node,
35 args=(formatted, ord(formatted), exc.index),
36 )
37 return
38 except utils.IncompleteFormatString:
39 self.add_message("truncated-format-string", node=node)
40 return
41 if not required_keys and not required_num_args:
42 self.add_message("format-string-without-interpolation", node=node)
43 return
44 if required_keys and required_num_args:
45 # The format string uses both named and unnamed format
46 # specifiers.
47 self.add_message("mixed-format-string", node=node)
48 elif required_keys:
49 # The format string uses only named format specifiers.
50 # Check that the RHS of the % operator is a mapping object
51 # that contains precisely the set of keys required by the
52 # format string.
53 if isinstance(args, nodes.Dict):
54 keys = set()
55 unknown_keys = False
56 for k, _ in args.items:
57 if isinstance(k, nodes.Const):
58 key = k.value
59 if isinstance(key, str):
60 keys.add(key)
61 else:
62 self.add_message(
63 "bad-format-string-key", node=node, args=key
64 )
65 else:
66 # One of the keys was something other than a
67 # constant. Since we can't tell what it is,
68 # suppress checks for missing keys in the
69 # dictionary.
70 unknown_keys = True
71 if not unknown_keys:
72 for key in required_keys:
73 if key not in keys:
74 self.add_message(
75 "missing-format-string-key", node=node, args=key
76 )
77 for key in keys:
78 if key not in required_keys:
79 self.add_message(
80 "unused-format-string-key", node=node, args=key
81 )
82 for key, arg in args.items:
83 if not isinstance(key, nodes.Const):
84 continue
85 format_type = required_key_types.get(key.value, None)
86 arg_type = utils.safe_infer(arg)
87 if (
88 format_type is not None
89 and arg_type
90 and arg_type != astroid.Uninferable
91 and not arg_matches_format_type(arg_type, format_type)
92 ):
93 self.add_message(
94 "bad-string-format-type",
95 node=node,
96 args=(arg_type.pytype(), format_type),
97 )
98 elif isinstance(args, (OTHER_NODES, nodes.Tuple)):
99 type_name = type(args).__name__
100 self.add_message("format-needs-mapping", node=node, args=type_name)
101 # else:
102 # The RHS of the format specifier is a name or
103 # expression. It may be a mapping object, so
104 # there's nothing we can check.
105 else:
106 # The format string uses only unnamed format specifiers.
107 # Check that the number of arguments passed to the RHS of
108 # the % operator matches the number required by the format
109 # string.
110 args_elts = []
111 if isinstance(args, nodes.Tuple):
112 rhs_tuple = utils.safe_infer(args)
113 num_args = None
114 if isinstance(rhs_tuple, nodes.BaseContainer):
115 args_elts = rhs_tuple.elts
116 num_args = len(args_elts)
117 elif isinstance(args, (OTHER_NODES, (nodes.Dict, nodes.DictComp))):
118 args_elts = [args]
119 num_args = 1
120 elif isinstance(args, nodes.Name):
121 inferred = utils.safe_infer(args)
122 if isinstance(inferred, nodes.Tuple):
123 # The variable is a tuple, so we need to get the elements
124 # from it for further inspection
125 args_elts = inferred.elts
126 num_args = len(args_elts)
127 elif isinstance(inferred, nodes.Const):
128 args_elts = [inferred]
129 num_args = 1
130 else:
131 num_args = None
132 else:
133 # The RHS of the format specifier is an expression.
134 # It could be a tuple of unknown size, so
135 # there's nothing we can check.
136 num_args = None
137 if num_args is not None:
138 if num_args > required_num_args:
139 self.add_message("too-many-format-args", node=node)
140 elif num_args < required_num_args:
141 self.add_message("too-few-format-args", node=node)
142 for arg, format_type in zip(args_elts, required_arg_types):
143 if not arg:
144 continue
145 arg_type = utils.safe_infer(arg)
146 if (
147 arg_type
148 and arg_type != astroid.Uninferable
149 and not arg_matches_format_type(arg_type, format_type)
150 ):
151 self.add_message(
152 "bad-string-format-type",
153 node=node,
154 args=(arg_type.pytype(), format_type),
155 )
Path 9: 4 calls (0.0)
BinOp (4)
None (4)
1@only_required_for_messages(
2 "bad-format-character",
3 "truncated-format-string",
4 "mixed-format-string",
5 "bad-format-string-key",
6 "missing-format-string-key",
7 "unused-format-string-key",
8 "bad-string-format-type",
9 "format-needs-mapping",
10 "too-many-format-args",
11 "too-few-format-args",
12 "format-string-without-interpolation",
13 )
14 def visit_binop(self, node: nodes.BinOp) -> None:
15 if node.op != "%":
16 return
17 left = node.left
18 args = node.right
19
20 if not (isinstance(left, nodes.Const) and isinstance(left.value, str)):
21 return
22 format_string = left.value
23 try:
24 (
25 required_keys,
26 required_num_args,
27 required_key_types,
28 required_arg_types,
29 ) = utils.parse_format_string(format_string)
30 except utils.UnsupportedFormatCharacter as exc:
31 formatted = format_string[exc.index]
32 self.add_message(
33 "bad-format-character",
34 node=node,
35 args=(formatted, ord(formatted), exc.index),
36 )
37 return
38 except utils.IncompleteFormatString:
39 self.add_message("truncated-format-string", node=node)
40 return
41 if not required_keys and not required_num_args:
42 self.add_message("format-string-without-interpolation", node=node)
43 return
44 if required_keys and required_num_args:
45 # The format string uses both named and unnamed format
46 # specifiers.
47 self.add_message("mixed-format-string", node=node)
48 elif required_keys:
49 # The format string uses only named format specifiers.
50 # Check that the RHS of the % operator is a mapping object
51 # that contains precisely the set of keys required by the
52 # format string.
53 if isinstance(args, nodes.Dict):
54 keys = set()
55 unknown_keys = False
56 for k, _ in args.items:
57 if isinstance(k, nodes.Const):
58 key = k.value
59 if isinstance(key, str):
60 keys.add(key)
61 else:
62 self.add_message(
63 "bad-format-string-key", node=node, args=key
64 )
65 else:
66 # One of the keys was something other than a
67 # constant. Since we can't tell what it is,
68 # suppress checks for missing keys in the
69 # dictionary.
70 unknown_keys = True
71 if not unknown_keys:
72 for key in required_keys:
73 if key not in keys:
74 self.add_message(
75 "missing-format-string-key", node=node, args=key
76 )
77 for key in keys:
78 if key not in required_keys:
79 self.add_message(
80 "unused-format-string-key", node=node, args=key
81 )
82 for key, arg in args.items:
83 if not isinstance(key, nodes.Const):
84 continue
85 format_type = required_key_types.get(key.value, None)
86 arg_type = utils.safe_infer(arg)
87 if (
88 format_type is not None
89 and arg_type
90 and arg_type != astroid.Uninferable
91 and not arg_matches_format_type(arg_type, format_type)
92 ):
93 self.add_message(
94 "bad-string-format-type",
95 node=node,
96 args=(arg_type.pytype(), format_type),
97 )
98 elif isinstance(args, (OTHER_NODES, nodes.Tuple)):
99 type_name = type(args).__name__
100 self.add_message("format-needs-mapping", node=node, args=type_name)
101 # else:
102 # The RHS of the format specifier is a name or
103 # expression. It may be a mapping object, so
104 # there's nothing we can check.
105 else:
106 # The format string uses only unnamed format specifiers.
107 # Check that the number of arguments passed to the RHS of
108 # the % operator matches the number required by the format
109 # string.
110 args_elts = []
111 if isinstance(args, nodes.Tuple):
112 rhs_tuple = utils.safe_infer(args)
113 num_args = None
114 if isinstance(rhs_tuple, nodes.BaseContainer):
115 args_elts = rhs_tuple.elts
116 num_args = len(args_elts)
117 elif isinstance(args, (OTHER_NODES, (nodes.Dict, nodes.DictComp))):
118 args_elts = [args]
119 num_args = 1
120 elif isinstance(args, nodes.Name):
121 inferred = utils.safe_infer(args)
122 if isinstance(inferred, nodes.Tuple):
123 # The variable is a tuple, so we need to get the elements
124 # from it for further inspection
125 args_elts = inferred.elts
126 num_args = len(args_elts)
127 elif isinstance(inferred, nodes.Const):
128 args_elts = [inferred]
129 num_args = 1
130 else:
131 num_args = None
132 else:
133 # The RHS of the format specifier is an expression.
134 # It could be a tuple of unknown size, so
135 # there's nothing we can check.
136 num_args = None
137 if num_args is not None:
138 if num_args > required_num_args:
139 self.add_message("too-many-format-args", node=node)
140 elif num_args < required_num_args:
141 self.add_message("too-few-format-args", node=node)
142 for arg, format_type in zip(args_elts, required_arg_types):
143 if not arg:
144 continue
145 arg_type = utils.safe_infer(arg)
146 if (
147 arg_type
148 and arg_type != astroid.Uninferable
149 and not arg_matches_format_type(arg_type, format_type)
150 ):
151 self.add_message(
152 "bad-string-format-type",
153 node=node,
154 args=(arg_type.pytype(), format_type),
155 )
Path 10: 3 calls (0.0)
BinOp (3)
1@only_required_for_messages(
2 "bad-format-character",
3 "truncated-format-string",
4 "mixed-format-string",
5 "bad-format-string-key",
6 "missing-format-string-key",
7 "unused-format-string-key",
8 "bad-string-format-type",
9 "format-needs-mapping",
10 "too-many-format-args",
11 "too-few-format-args",
12 "format-string-without-interpolation",
13 )
14 def visit_binop(self, node: nodes.BinOp) -> None:
15 if node.op != "%":
16 return
17 left = node.left
18 args = node.right
19
20 if not (isinstance(left, nodes.Const) and isinstance(left.value, str)):
21 return
22 format_string = left.value
23 try:
24 (
25 required_keys,
26 required_num_args,
27 required_key_types,
28 required_arg_types,
29 ) = utils.parse_format_string(format_string)
30 except utils.UnsupportedFormatCharacter as exc:
31 formatted = format_string[exc.index]
32 self.add_message(
33 "bad-format-character",
34 node=node,
35 args=(formatted, ord(formatted), exc.index),
36 )
37 return
38 except utils.IncompleteFormatString:
39 self.add_message("truncated-format-string", node=node)
40 return
41 if not required_keys and not required_num_args:
42 self.add_message("format-string-without-interpolation", node=node)
43 return
44 if required_keys and required_num_args:
45 # The format string uses both named and unnamed format
46 # specifiers.
47 self.add_message("mixed-format-string", node=node)
48 elif required_keys:
49 # The format string uses only named format specifiers.
50 # Check that the RHS of the % operator is a mapping object
51 # that contains precisely the set of keys required by the
52 # format string.
53 if isinstance(args, nodes.Dict):
54 keys = set()
55 unknown_keys = False
56 for k, _ in args.items:
57 if isinstance(k, nodes.Const):
58 key = k.value
59 if isinstance(key, str):
60 keys.add(key)
61 else:
62 self.add_message(
63 "bad-format-string-key", node=node, args=key
64 )
65 else:
66 # One of the keys was something other than a
67 # constant. Since we can't tell what it is,
68 # suppress checks for missing keys in the
69 # dictionary.
70 unknown_keys = True
71 if not unknown_keys:
72 for key in required_keys:
73 if key not in keys:
74 self.add_message(
75 "missing-format-string-key", node=node, args=key
76 )
77 for key in keys:
78 if key not in required_keys:
79 self.add_message(
80 "unused-format-string-key", node=node, args=key
81 )
82 for key, arg in args.items:
83 if not isinstance(key, nodes.Const):
84 continue
85 format_type = required_key_types.get(key.value, None)
86 arg_type = utils.safe_infer(arg)
87 if (
88 format_type is not None
89 and arg_type
90 and arg_type != astroid.Uninferable
91 and not arg_matches_format_type(arg_type, format_type)
92 ):
93 self.add_message(
94 "bad-string-format-type",
95 node=node,
96 args=(arg_type.pytype(), format_type),
97 )
98 elif isinstance(args, (OTHER_NODES, nodes.Tuple)):
99 type_name = type(args).__name__
100 self.add_message("format-needs-mapping", node=node, args=type_name)
101 # else:
102 # The RHS of the format specifier is a name or
103 # expression. It may be a mapping object, so
104 # there's nothing we can check.
105 else:
106 # The format string uses only unnamed format specifiers.
107 # Check that the number of arguments passed to the RHS of
108 # the % operator matches the number required by the format
109 # string.
110 args_elts = []
111 if isinstance(args, nodes.Tuple):
112 rhs_tuple = utils.safe_infer(args)
113 num_args = None
114 if isinstance(rhs_tuple, nodes.BaseContainer):
115 args_elts = rhs_tuple.elts
116 num_args = len(args_elts)
117 elif isinstance(args, (OTHER_NODES, (nodes.Dict, nodes.DictComp))):
118 args_elts = [args]
119 num_args = 1
120 elif isinstance(args, nodes.Name):
121 inferred = utils.safe_infer(args)
122 if isinstance(inferred, nodes.Tuple):
123 # The variable is a tuple, so we need to get the elements
124 # from it for further inspection
125 args_elts = inferred.elts
126 num_args = len(args_elts)
127 elif isinstance(inferred, nodes.Const):
128 args_elts = [inferred]
129 num_args = 1
130 else:
131 num_args = None
132 else:
133 # The RHS of the format specifier is an expression.
134 # It could be a tuple of unknown size, so
135 # there's nothing we can check.
136 num_args = None
137 if num_args is not None:
138 if num_args > required_num_args:
139 self.add_message("too-many-format-args", node=node)
140 elif num_args < required_num_args:
141 self.add_message("too-few-format-args", node=node)
142 for arg, format_type in zip(args_elts, required_arg_types):
143 if not arg:
144 continue
145 arg_type = utils.safe_infer(arg)
146 if (
147 arg_type
148 and arg_type != astroid.Uninferable
149 and not arg_matches_format_type(arg_type, format_type)
150 ):
151 self.add_message(
152 "bad-string-format-type",
153 node=node,
154 args=(arg_type.pytype(), format_type),
155 )
Path 11: 3 calls (0.0)
BinOp (3)
1@only_required_for_messages(
2 "bad-format-character",
3 "truncated-format-string",
4 "mixed-format-string",
5 "bad-format-string-key",
6 "missing-format-string-key",
7 "unused-format-string-key",
8 "bad-string-format-type",
9 "format-needs-mapping",
10 "too-many-format-args",
11 "too-few-format-args",
12 "format-string-without-interpolation",
13 )
14 def visit_binop(self, node: nodes.BinOp) -> None:
15 if node.op != "%":
16 return
17 left = node.left
18 args = node.right
19
20 if not (isinstance(left, nodes.Const) and isinstance(left.value, str)):
21 return
22 format_string = left.value
23 try:
24 (
25 required_keys,
26 required_num_args,
27 required_key_types,
28 required_arg_types,
29 ) = utils.parse_format_string(format_string)
30 except utils.UnsupportedFormatCharacter as exc:
31 formatted = format_string[exc.index]
32 self.add_message(
33 "bad-format-character",
34 node=node,
35 args=(formatted, ord(formatted), exc.index),
36 )
37 return
38 except utils.IncompleteFormatString:
39 self.add_message("truncated-format-string", node=node)
40 return
41 if not required_keys and not required_num_args:
42 self.add_message("format-string-without-interpolation", node=node)
43 return
44 if required_keys and required_num_args:
45 # The format string uses both named and unnamed format
46 # specifiers.
47 self.add_message("mixed-format-string", node=node)
48 elif required_keys:
49 # The format string uses only named format specifiers.
50 # Check that the RHS of the % operator is a mapping object
51 # that contains precisely the set of keys required by the
52 # format string.
53 if isinstance(args, nodes.Dict):
54 keys = set()
55 unknown_keys = False
56 for k, _ in args.items:
57 if isinstance(k, nodes.Const):
58 key = k.value
59 if isinstance(key, str):
60 keys.add(key)
61 else:
62 self.add_message(
63 "bad-format-string-key", node=node, args=key
64 )
65 else:
66 # One of the keys was something other than a
67 # constant. Since we can't tell what it is,
68 # suppress checks for missing keys in the
69 # dictionary.
70 unknown_keys = True
71 if not unknown_keys:
72 for key in required_keys:
73 if key not in keys:
74 self.add_message(
75 "missing-format-string-key", node=node, args=key
76 )
77 for key in keys:
78 if key not in required_keys:
79 self.add_message(
80 "unused-format-string-key", node=node, args=key
81 )
82 for key, arg in args.items:
83 if not isinstance(key, nodes.Const):
84 continue
85 format_type = required_key_types.get(key.value, None)
86 arg_type = utils.safe_infer(arg)
87 if (
88 format_type is not None
89 and arg_type
90 and arg_type != astroid.Uninferable
91 and not arg_matches_format_type(arg_type, format_type)
92 ):
93 self.add_message(
94 "bad-string-format-type",
95 node=node,
96 args=(arg_type.pytype(), format_type),
97 )
98 elif isinstance(args, (OTHER_NODES, nodes.Tuple)):
99 type_name = type(args).__name__
100 self.add_message("format-needs-mapping", node=node, args=type_name)
101 # else:
102 # The RHS of the format specifier is a name or
103 # expression. It may be a mapping object, so
104 # there's nothing we can check.
105 else:
106 # The format string uses only unnamed format specifiers.
107 # Check that the number of arguments passed to the RHS of
108 # the % operator matches the number required by the format
109 # string.
110 args_elts = []
111 if isinstance(args, nodes.Tuple):
112 rhs_tuple = utils.safe_infer(args)
113 num_args = None
114 if isinstance(rhs_tuple, nodes.BaseContainer):
115 args_elts = rhs_tuple.elts
116 num_args = len(args_elts)
117 elif isinstance(args, (OTHER_NODES, (nodes.Dict, nodes.DictComp))):
118 args_elts = [args]
119 num_args = 1
120 elif isinstance(args, nodes.Name):
121 inferred = utils.safe_infer(args)
122 if isinstance(inferred, nodes.Tuple):
123 # The variable is a tuple, so we need to get the elements
124 # from it for further inspection
125 args_elts = inferred.elts
126 num_args = len(args_elts)
127 elif isinstance(inferred, nodes.Const):
128 args_elts = [inferred]
129 num_args = 1
130 else:
131 num_args = None
132 else:
133 # The RHS of the format specifier is an expression.
134 # It could be a tuple of unknown size, so
135 # there's nothing we can check.
136 num_args = None
137 if num_args is not None:
138 if num_args > required_num_args:
139 self.add_message("too-many-format-args", node=node)
140 elif num_args < required_num_args:
141 self.add_message("too-few-format-args", node=node)
142 for arg, format_type in zip(args_elts, required_arg_types):
143 if not arg:
144 continue
145 arg_type = utils.safe_infer(arg)
146 if (
147 arg_type
148 and arg_type != astroid.Uninferable
149 and not arg_matches_format_type(arg_type, format_type)
150 ):
151 self.add_message(
152 "bad-string-format-type",
153 node=node,
154 args=(arg_type.pytype(), format_type),
155 )
Path 12: 3 calls (0.0)
BinOp (3)
1@only_required_for_messages(
2 "bad-format-character",
3 "truncated-format-string",
4 "mixed-format-string",
5 "bad-format-string-key",
6 "missing-format-string-key",
7 "unused-format-string-key",
8 "bad-string-format-type",
9 "format-needs-mapping",
10 "too-many-format-args",
11 "too-few-format-args",
12 "format-string-without-interpolation",
13 )
14 def visit_binop(self, node: nodes.BinOp) -> None:
15 if node.op != "%":
16 return
17 left = node.left
18 args = node.right
19
20 if not (isinstance(left, nodes.Const) and isinstance(left.value, str)):
21 return
22 format_string = left.value
23 try:
24 (
25 required_keys,
26 required_num_args,
27 required_key_types,
28 required_arg_types,
29 ) = utils.parse_format_string(format_string)
30 except utils.UnsupportedFormatCharacter as exc:
31 formatted = format_string[exc.index]
32 self.add_message(
33 "bad-format-character",
34 node=node,
35 args=(formatted, ord(formatted), exc.index),
36 )
37 return
38 except utils.IncompleteFormatString:
39 self.add_message("truncated-format-string", node=node)
40 return
41 if not required_keys and not required_num_args:
42 self.add_message("format-string-without-interpolation", node=node)
43 return
44 if required_keys and required_num_args:
45 # The format string uses both named and unnamed format
46 # specifiers.
47 self.add_message("mixed-format-string", node=node)
48 elif required_keys:
49 # The format string uses only named format specifiers.
50 # Check that the RHS of the % operator is a mapping object
51 # that contains precisely the set of keys required by the
52 # format string.
53 if isinstance(args, nodes.Dict):
54 keys = set()
55 unknown_keys = False
56 for k, _ in args.items:
57 if isinstance(k, nodes.Const):
58 key = k.value
59 if isinstance(key, str):
60 keys.add(key)
61 else:
62 self.add_message(
63 "bad-format-string-key", node=node, args=key
64 )
65 else:
66 # One of the keys was something other than a
67 # constant. Since we can't tell what it is,
68 # suppress checks for missing keys in the
69 # dictionary.
70 unknown_keys = True
71 if not unknown_keys:
72 for key in required_keys:
73 if key not in keys:
74 self.add_message(
75 "missing-format-string-key", node=node, args=key
76 )
77 for key in keys:
78 if key not in required_keys:
79 self.add_message(
80 "unused-format-string-key", node=node, args=key
81 )
82 for key, arg in args.items:
83 if not isinstance(key, nodes.Const):
84 continue
85 format_type = required_key_types.get(key.value, None)
86 arg_type = utils.safe_infer(arg)
87 if (
88 format_type is not None
89 and arg_type
90 and arg_type != astroid.Uninferable
91 and not arg_matches_format_type(arg_type, format_type)
92 ):
93 self.add_message(
94 "bad-string-format-type",
95 node=node,
96 args=(arg_type.pytype(), format_type),
97 )
98 elif isinstance(args, (OTHER_NODES, nodes.Tuple)):
99 type_name = type(args).__name__
100 self.add_message("format-needs-mapping", node=node, args=type_name)
101 # else:
102 # The RHS of the format specifier is a name or
103 # expression. It may be a mapping object, so
104 # there's nothing we can check.
105 else:
106 # The format string uses only unnamed format specifiers.
107 # Check that the number of arguments passed to the RHS of
108 # the % operator matches the number required by the format
109 # string.
110 args_elts = []
111 if isinstance(args, nodes.Tuple):
112 rhs_tuple = utils.safe_infer(args)
113 num_args = None
114 if isinstance(rhs_tuple, nodes.BaseContainer):
115 args_elts = rhs_tuple.elts
116 num_args = len(args_elts)
117 elif isinstance(args, (OTHER_NODES, (nodes.Dict, nodes.DictComp))):
118 args_elts = [args]
119 num_args = 1
120 elif isinstance(args, nodes.Name):
121 inferred = utils.safe_infer(args)
122 if isinstance(inferred, nodes.Tuple):
123 # The variable is a tuple, so we need to get the elements
124 # from it for further inspection
125 args_elts = inferred.elts
126 num_args = len(args_elts)
127 elif isinstance(inferred, nodes.Const):
128 args_elts = [inferred]
129 num_args = 1
130 else:
131 num_args = None
132 else:
133 # The RHS of the format specifier is an expression.
134 # It could be a tuple of unknown size, so
135 # there's nothing we can check.
136 num_args = None
137 if num_args is not None:
138 if num_args > required_num_args:
139 self.add_message("too-many-format-args", node=node)
140 elif num_args < required_num_args:
141 self.add_message("too-few-format-args", node=node)
142 for arg, format_type in zip(args_elts, required_arg_types):
143 if not arg:
144 continue
145 arg_type = utils.safe_infer(arg)
146 if (
147 arg_type
148 and arg_type != astroid.Uninferable
149 and not arg_matches_format_type(arg_type, format_type)
150 ):
151 self.add_message(
152 "bad-string-format-type",
153 node=node,
154 args=(arg_type.pytype(), format_type),
155 )
Path 13: 2 calls (0.0)
BinOp (2)
1@only_required_for_messages(
2 "bad-format-character",
3 "truncated-format-string",
4 "mixed-format-string",
5 "bad-format-string-key",
6 "missing-format-string-key",
7 "unused-format-string-key",
8 "bad-string-format-type",
9 "format-needs-mapping",
10 "too-many-format-args",
11 "too-few-format-args",
12 "format-string-without-interpolation",
13 )
14 def visit_binop(self, node: nodes.BinOp) -> None:
15 if node.op != "%":
16 return
17 left = node.left
18 args = node.right
19
20 if not (isinstance(left, nodes.Const) and isinstance(left.value, str)):
21 return
22 format_string = left.value
23 try:
24 (
25 required_keys,
26 required_num_args,
27 required_key_types,
28 required_arg_types,
29 ) = utils.parse_format_string(format_string)
30 except utils.UnsupportedFormatCharacter as exc:
31 formatted = format_string[exc.index]
32 self.add_message(
33 "bad-format-character",
34 node=node,
35 args=(formatted, ord(formatted), exc.index),
36 )
37 return
38 except utils.IncompleteFormatString:
39 self.add_message("truncated-format-string", node=node)
40 return
41 if not required_keys and not required_num_args:
42 self.add_message("format-string-without-interpolation", node=node)
43 return
44 if required_keys and required_num_args:
45 # The format string uses both named and unnamed format
46 # specifiers.
47 self.add_message("mixed-format-string", node=node)
48 elif required_keys:
49 # The format string uses only named format specifiers.
50 # Check that the RHS of the % operator is a mapping object
51 # that contains precisely the set of keys required by the
52 # format string.
53 if isinstance(args, nodes.Dict):
54 keys = set()
55 unknown_keys = False
56 for k, _ in args.items:
57 if isinstance(k, nodes.Const):
58 key = k.value
59 if isinstance(key, str):
60 keys.add(key)
61 else:
62 self.add_message(
63 "bad-format-string-key", node=node, args=key
64 )
65 else:
66 # One of the keys was something other than a
67 # constant. Since we can't tell what it is,
68 # suppress checks for missing keys in the
69 # dictionary.
70 unknown_keys = True
71 if not unknown_keys:
72 for key in required_keys:
73 if key not in keys:
74 self.add_message(
75 "missing-format-string-key", node=node, args=key
76 )
77 for key in keys:
78 if key not in required_keys:
79 self.add_message(
80 "unused-format-string-key", node=node, args=key
81 )
82 for key, arg in args.items:
83 if not isinstance(key, nodes.Const):
84 continue
85 format_type = required_key_types.get(key.value, None)
86 arg_type = utils.safe_infer(arg)
87 if (
88 format_type is not None
89 and arg_type
90 and arg_type != astroid.Uninferable
91 and not arg_matches_format_type(arg_type, format_type)
92 ):
93 self.add_message(
94 "bad-string-format-type",
95 node=node,
96 args=(arg_type.pytype(), format_type),
97 )
98 elif isinstance(args, (OTHER_NODES, nodes.Tuple)):
99 type_name = type(args).__name__
100 self.add_message("format-needs-mapping", node=node, args=type_name)
101 # else:
102 # The RHS of the format specifier is a name or
103 # expression. It may be a mapping object, so
104 # there's nothing we can check.
105 else:
106 # The format string uses only unnamed format specifiers.
107 # Check that the number of arguments passed to the RHS of
108 # the % operator matches the number required by the format
109 # string.
110 args_elts = []
111 if isinstance(args, nodes.Tuple):
112 rhs_tuple = utils.safe_infer(args)
113 num_args = None
114 if isinstance(rhs_tuple, nodes.BaseContainer):
115 args_elts = rhs_tuple.elts
116 num_args = len(args_elts)
117 elif isinstance(args, (OTHER_NODES, (nodes.Dict, nodes.DictComp))):
118 args_elts = [args]
119 num_args = 1
120 elif isinstance(args, nodes.Name):
121 inferred = utils.safe_infer(args)
122 if isinstance(inferred, nodes.Tuple):
123 # The variable is a tuple, so we need to get the elements
124 # from it for further inspection
125 args_elts = inferred.elts
126 num_args = len(args_elts)
127 elif isinstance(inferred, nodes.Const):
128 args_elts = [inferred]
129 num_args = 1
130 else:
131 num_args = None
132 else:
133 # The RHS of the format specifier is an expression.
134 # It could be a tuple of unknown size, so
135 # there's nothing we can check.
136 num_args = None
137 if num_args is not None:
138 if num_args > required_num_args:
139 self.add_message("too-many-format-args", node=node)
140 elif num_args < required_num_args:
141 self.add_message("too-few-format-args", node=node)
142 for arg, format_type in zip(args_elts, required_arg_types):
143 if not arg:
144 continue
145 arg_type = utils.safe_infer(arg)
146 if (
147 arg_type
148 and arg_type != astroid.Uninferable
149 and not arg_matches_format_type(arg_type, format_type)
150 ):
151 self.add_message(
152 "bad-string-format-type",
153 node=node,
154 args=(arg_type.pytype(), format_type),
155 )
Path 14: 2 calls (0.0)
BinOp (2)
1@only_required_for_messages(
2 "bad-format-character",
3 "truncated-format-string",
4 "mixed-format-string",
5 "bad-format-string-key",
6 "missing-format-string-key",
7 "unused-format-string-key",
8 "bad-string-format-type",
9 "format-needs-mapping",
10 "too-many-format-args",
11 "too-few-format-args",
12 "format-string-without-interpolation",
13 )
14 def visit_binop(self, node: nodes.BinOp) -> None:
15 if node.op != "%":
16 return
17 left = node.left
18 args = node.right
19
20 if not (isinstance(left, nodes.Const) and isinstance(left.value, str)):
21 return
22 format_string = left.value
23 try:
24 (
25 required_keys,
26 required_num_args,
27 required_key_types,
28 required_arg_types,
29 ) = utils.parse_format_string(format_string)
30 except utils.UnsupportedFormatCharacter as exc:
31 formatted = format_string[exc.index]
32 self.add_message(
33 "bad-format-character",
34 node=node,
35 args=(formatted, ord(formatted), exc.index),
36 )
37 return
38 except utils.IncompleteFormatString:
39 self.add_message("truncated-format-string", node=node)
40 return
41 if not required_keys and not required_num_args:
42 self.add_message("format-string-without-interpolation", node=node)
43 return
44 if required_keys and required_num_args:
45 # The format string uses both named and unnamed format
46 # specifiers.
47 self.add_message("mixed-format-string", node=node)
48 elif required_keys:
49 # The format string uses only named format specifiers.
50 # Check that the RHS of the % operator is a mapping object
51 # that contains precisely the set of keys required by the
52 # format string.
53 if isinstance(args, nodes.Dict):
54 keys = set()
55 unknown_keys = False
56 for k, _ in args.items:
57 if isinstance(k, nodes.Const):
58 key = k.value
59 if isinstance(key, str):
60 keys.add(key)
61 else:
62 self.add_message(
63 "bad-format-string-key", node=node, args=key
64 )
65 else:
66 # One of the keys was something other than a
67 # constant. Since we can't tell what it is,
68 # suppress checks for missing keys in the
69 # dictionary.
70 unknown_keys = True
71 if not unknown_keys:
72 for key in required_keys:
73 if key not in keys:
74 self.add_message(
75 "missing-format-string-key", node=node, args=key
76 )
77 for key in keys:
78 if key not in required_keys:
79 self.add_message(
80 "unused-format-string-key", node=node, args=key
81 )
82 for key, arg in args.items:
83 if not isinstance(key, nodes.Const):
84 continue
85 format_type = required_key_types.get(key.value, None)
86 arg_type = utils.safe_infer(arg)
87 if (
88 format_type is not None
89 and arg_type
90 and arg_type != astroid.Uninferable
91 and not arg_matches_format_type(arg_type, format_type)
92 ):
93 self.add_message(
94 "bad-string-format-type",
95 node=node,
96 args=(arg_type.pytype(), format_type),
97 )
98 elif isinstance(args, (OTHER_NODES, nodes.Tuple)):
99 type_name = type(args).__name__
100 self.add_message("format-needs-mapping", node=node, args=type_name)
101 # else:
102 # The RHS of the format specifier is a name or
103 # expression. It may be a mapping object, so
104 # there's nothing we can check.
105 else:
106 # The format string uses only unnamed format specifiers.
107 # Check that the number of arguments passed to the RHS of
108 # the % operator matches the number required by the format
109 # string.
110 args_elts = []
111 if isinstance(args, nodes.Tuple):
112 rhs_tuple = utils.safe_infer(args)
113 num_args = None
114 if isinstance(rhs_tuple, nodes.BaseContainer):
115 args_elts = rhs_tuple.elts
116 num_args = len(args_elts)
117 elif isinstance(args, (OTHER_NODES, (nodes.Dict, nodes.DictComp))):
118 args_elts = [args]
119 num_args = 1
120 elif isinstance(args, nodes.Name):
121 inferred = utils.safe_infer(args)
122 if isinstance(inferred, nodes.Tuple):
123 # The variable is a tuple, so we need to get the elements
124 # from it for further inspection
125 args_elts = inferred.elts
126 num_args = len(args_elts)
127 elif isinstance(inferred, nodes.Const):
128 args_elts = [inferred]
129 num_args = 1
130 else:
131 num_args = None
132 else:
133 # The RHS of the format specifier is an expression.
134 # It could be a tuple of unknown size, so
135 # there's nothing we can check.
136 num_args = None
137 if num_args is not None:
138 if num_args > required_num_args:
139 self.add_message("too-many-format-args", node=node)
140 elif num_args < required_num_args:
141 self.add_message("too-few-format-args", node=node)
142 for arg, format_type in zip(args_elts, required_arg_types):
143 if not arg:
144 continue
145 arg_type = utils.safe_infer(arg)
146 if (
147 arg_type
148 and arg_type != astroid.Uninferable
149 and not arg_matches_format_type(arg_type, format_type)
150 ):
151 self.add_message(
152 "bad-string-format-type",
153 node=node,
154 args=(arg_type.pytype(), format_type),
155 )
Path 15: 2 calls (0.0)
BinOp (2)
1@only_required_for_messages(
2 "bad-format-character",
3 "truncated-format-string",
4 "mixed-format-string",
5 "bad-format-string-key",
6 "missing-format-string-key",
7 "unused-format-string-key",
8 "bad-string-format-type",
9 "format-needs-mapping",
10 "too-many-format-args",
11 "too-few-format-args",
12 "format-string-without-interpolation",
13 )
14 def visit_binop(self, node: nodes.BinOp) -> None:
15 if node.op != "%":
16 return
17 left = node.left
18 args = node.right
19
20 if not (isinstance(left, nodes.Const) and isinstance(left.value, str)):
21 return
22 format_string = left.value
23 try:
24 (
25 required_keys,
26 required_num_args,
27 required_key_types,
28 required_arg_types,
29 ) = utils.parse_format_string(format_string)
30 except utils.UnsupportedFormatCharacter as exc:
31 formatted = format_string[exc.index]
32 self.add_message(
33 "bad-format-character",
34 node=node,
35 args=(formatted, ord(formatted), exc.index),
36 )
37 return
38 except utils.IncompleteFormatString:
39 self.add_message("truncated-format-string", node=node)
40 return
41 if not required_keys and not required_num_args:
42 self.add_message("format-string-without-interpolation", node=node)
43 return
44 if required_keys and required_num_args:
45 # The format string uses both named and unnamed format
46 # specifiers.
47 self.add_message("mixed-format-string", node=node)
48 elif required_keys:
49 # The format string uses only named format specifiers.
50 # Check that the RHS of the % operator is a mapping object
51 # that contains precisely the set of keys required by the
52 # format string.
53 if isinstance(args, nodes.Dict):
54 keys = set()
55 unknown_keys = False
56 for k, _ in args.items:
57 if isinstance(k, nodes.Const):
58 key = k.value
59 if isinstance(key, str):
60 keys.add(key)
61 else:
62 self.add_message(
63 "bad-format-string-key", node=node, args=key
64 )
65 else:
66 # One of the keys was something other than a
67 # constant. Since we can't tell what it is,
68 # suppress checks for missing keys in the
69 # dictionary.
70 unknown_keys = True
71 if not unknown_keys:
72 for key in required_keys:
73 if key not in keys:
74 self.add_message(
75 "missing-format-string-key", node=node, args=key
76 )
77 for key in keys:
78 if key not in required_keys:
79 self.add_message(
80 "unused-format-string-key", node=node, args=key
81 )
82 for key, arg in args.items:
83 if not isinstance(key, nodes.Const):
84 continue
85 format_type = required_key_types.get(key.value, None)
86 arg_type = utils.safe_infer(arg)
87 if (
88 format_type is not None
89 and arg_type
90 and arg_type != astroid.Uninferable
91 and not arg_matches_format_type(arg_type, format_type)
92 ):
93 self.add_message(
94 "bad-string-format-type",
95 node=node,
96 args=(arg_type.pytype(), format_type),
97 )
98 elif isinstance(args, (OTHER_NODES, nodes.Tuple)):
99 type_name = type(args).__name__
100 self.add_message("format-needs-mapping", node=node, args=type_name)
101 # else:
102 # The RHS of the format specifier is a name or
103 # expression. It may be a mapping object, so
104 # there's nothing we can check.
105 else:
106 # The format string uses only unnamed format specifiers.
107 # Check that the number of arguments passed to the RHS of
108 # the % operator matches the number required by the format
109 # string.
110 args_elts = []
111 if isinstance(args, nodes.Tuple):
112 rhs_tuple = utils.safe_infer(args)
113 num_args = None
114 if isinstance(rhs_tuple, nodes.BaseContainer):
115 args_elts = rhs_tuple.elts
116 num_args = len(args_elts)
117 elif isinstance(args, (OTHER_NODES, (nodes.Dict, nodes.DictComp))):
118 args_elts = [args]
119 num_args = 1
120 elif isinstance(args, nodes.Name):
121 inferred = utils.safe_infer(args)
122 if isinstance(inferred, nodes.Tuple):
123 # The variable is a tuple, so we need to get the elements
124 # from it for further inspection
125 args_elts = inferred.elts
126 num_args = len(args_elts)
127 elif isinstance(inferred, nodes.Const):
128 args_elts = [inferred]
129 num_args = 1
130 else:
131 num_args = None
132 else:
133 # The RHS of the format specifier is an expression.
134 # It could be a tuple of unknown size, so
135 # there's nothing we can check.
136 num_args = None
137 if num_args is not None:
138 if num_args > required_num_args:
139 self.add_message("too-many-format-args", node=node)
140 elif num_args < required_num_args:
141 self.add_message("too-few-format-args", node=node)
142 for arg, format_type in zip(args_elts, required_arg_types):
143 if not arg:
144 continue
145 arg_type = utils.safe_infer(arg)
146 if (
147 arg_type
148 and arg_type != astroid.Uninferable
149 and not arg_matches_format_type(arg_type, format_type)
150 ):
151 self.add_message(
152 "bad-string-format-type",
153 node=node,
154 args=(arg_type.pytype(), format_type),
155 )
Path 16: 1 calls (0.0)
BinOp (1)
1@only_required_for_messages(
2 "bad-format-character",
3 "truncated-format-string",
4 "mixed-format-string",
5 "bad-format-string-key",
6 "missing-format-string-key",
7 "unused-format-string-key",
8 "bad-string-format-type",
9 "format-needs-mapping",
10 "too-many-format-args",
11 "too-few-format-args",
12 "format-string-without-interpolation",
13 )
14 def visit_binop(self, node: nodes.BinOp) -> None:
15 if node.op != "%":
16 return
17 left = node.left
18 args = node.right
19
20 if not (isinstance(left, nodes.Const) and isinstance(left.value, str)):
21 return
22 format_string = left.value
23 try:
24 (
25 required_keys,
26 required_num_args,
27 required_key_types,
28 required_arg_types,
29 ) = utils.parse_format_string(format_string)
30 except utils.UnsupportedFormatCharacter as exc:
31 formatted = format_string[exc.index]
32 self.add_message(
33 "bad-format-character",
34 node=node,
35 args=(formatted, ord(formatted), exc.index),
36 )
37 return
38 except utils.IncompleteFormatString:
39 self.add_message("truncated-format-string", node=node)
40 return
41 if not required_keys and not required_num_args:
42 self.add_message("format-string-without-interpolation", node=node)
43 return
44 if required_keys and required_num_args:
45 # The format string uses both named and unnamed format
46 # specifiers.
47 self.add_message("mixed-format-string", node=node)
48 elif required_keys:
49 # The format string uses only named format specifiers.
50 # Check that the RHS of the % operator is a mapping object
51 # that contains precisely the set of keys required by the
52 # format string.
53 if isinstance(args, nodes.Dict):
54 keys = set()
55 unknown_keys = False
56 for k, _ in args.items:
57 if isinstance(k, nodes.Const):
58 key = k.value
59 if isinstance(key, str):
60 keys.add(key)
61 else:
62 self.add_message(
63 "bad-format-string-key", node=node, args=key
64 )
65 else:
66 # One of the keys was something other than a
67 # constant. Since we can't tell what it is,
68 # suppress checks for missing keys in the
69 # dictionary.
70 unknown_keys = True
71 if not unknown_keys:
72 for key in required_keys:
73 if key not in keys:
74 self.add_message(
75 "missing-format-string-key", node=node, args=key
76 )
77 for key in keys:
78 if key not in required_keys:
79 self.add_message(
80 "unused-format-string-key", node=node, args=key
81 )
82 for key, arg in args.items:
83 if not isinstance(key, nodes.Const):
84 continue
85 format_type = required_key_types.get(key.value, None)
86 arg_type = utils.safe_infer(arg)
87 if (
88 format_type is not None
89 and arg_type
90 and arg_type != astroid.Uninferable
91 and not arg_matches_format_type(arg_type, format_type)
92 ):
93 self.add_message(
94 "bad-string-format-type",
95 node=node,
96 args=(arg_type.pytype(), format_type),
97 )
98 elif isinstance(args, (OTHER_NODES, nodes.Tuple)):
99 type_name = type(args).__name__
100 self.add_message("format-needs-mapping", node=node, args=type_name)
101 # else:
102 # The RHS of the format specifier is a name or
103 # expression. It may be a mapping object, so
104 # there's nothing we can check.
105 else:
106 # The format string uses only unnamed format specifiers.
107 # Check that the number of arguments passed to the RHS of
108 # the % operator matches the number required by the format
109 # string.
110 args_elts = []
111 if isinstance(args, nodes.Tuple):
112 rhs_tuple = utils.safe_infer(args)
113 num_args = None
114 if isinstance(rhs_tuple, nodes.BaseContainer):
115 args_elts = rhs_tuple.elts
116 num_args = len(args_elts)
117 elif isinstance(args, (OTHER_NODES, (nodes.Dict, nodes.DictComp))):
118 args_elts = [args]
119 num_args = 1
120 elif isinstance(args, nodes.Name):
121 inferred = utils.safe_infer(args)
122 if isinstance(inferred, nodes.Tuple):
123 # The variable is a tuple, so we need to get the elements
124 # from it for further inspection
125 args_elts = inferred.elts
126 num_args = len(args_elts)
127 elif isinstance(inferred, nodes.Const):
128 args_elts = [inferred]
129 num_args = 1
130 else:
131 num_args = None
132 else:
133 # The RHS of the format specifier is an expression.
134 # It could be a tuple of unknown size, so
135 # there's nothing we can check.
136 num_args = None
137 if num_args is not None:
138 if num_args > required_num_args:
139 self.add_message("too-many-format-args", node=node)
140 elif num_args < required_num_args:
141 self.add_message("too-few-format-args", node=node)
142 for arg, format_type in zip(args_elts, required_arg_types):
143 if not arg:
144 continue
145 arg_type = utils.safe_infer(arg)
146 if (
147 arg_type
148 and arg_type != astroid.Uninferable
149 and not arg_matches_format_type(arg_type, format_type)
150 ):
151 self.add_message(
152 "bad-string-format-type",
153 node=node,
154 args=(arg_type.pytype(), format_type),
155 )
Path 17: 1 calls (0.0)
BinOp (1)
1@only_required_for_messages(
2 "bad-format-character",
3 "truncated-format-string",
4 "mixed-format-string",
5 "bad-format-string-key",
6 "missing-format-string-key",
7 "unused-format-string-key",
8 "bad-string-format-type",
9 "format-needs-mapping",
10 "too-many-format-args",
11 "too-few-format-args",
12 "format-string-without-interpolation",
13 )
14 def visit_binop(self, node: nodes.BinOp) -> None:
15 if node.op != "%":
16 return
17 left = node.left
18 args = node.right
19
20 if not (isinstance(left, nodes.Const) and isinstance(left.value, str)):
21 return
22 format_string = left.value
23 try:
24 (
25 required_keys,
26 required_num_args,
27 required_key_types,
28 required_arg_types,
29 ) = utils.parse_format_string(format_string)
30 except utils.UnsupportedFormatCharacter as exc:
31 formatted = format_string[exc.index]
32 self.add_message(
33 "bad-format-character",
34 node=node,
35 args=(formatted, ord(formatted), exc.index),
36 )
37 return
38 except utils.IncompleteFormatString:
39 self.add_message("truncated-format-string", node=node)
40 return
41 if not required_keys and not required_num_args:
42 self.add_message("format-string-without-interpolation", node=node)
43 return
44 if required_keys and required_num_args:
45 # The format string uses both named and unnamed format
46 # specifiers.
47 self.add_message("mixed-format-string", node=node)
48 elif required_keys:
49 # The format string uses only named format specifiers.
50 # Check that the RHS of the % operator is a mapping object
51 # that contains precisely the set of keys required by the
52 # format string.
53 if isinstance(args, nodes.Dict):
54 keys = set()
55 unknown_keys = False
56 for k, _ in args.items:
57 if isinstance(k, nodes.Const):
58 key = k.value
59 if isinstance(key, str):
60 keys.add(key)
61 else:
62 self.add_message(
63 "bad-format-string-key", node=node, args=key
64 )
65 else:
66 # One of the keys was something other than a
67 # constant. Since we can't tell what it is,
68 # suppress checks for missing keys in the
69 # dictionary.
70 unknown_keys = True
71 if not unknown_keys:
72 for key in required_keys:
73 if key not in keys:
74 self.add_message(
75 "missing-format-string-key", node=node, args=key
76 )
77 for key in keys:
78 if key not in required_keys:
79 self.add_message(
80 "unused-format-string-key", node=node, args=key
81 )
82 for key, arg in args.items:
83 if not isinstance(key, nodes.Const):
84 continue
85 format_type = required_key_types.get(key.value, None)
86 arg_type = utils.safe_infer(arg)
87 if (
88 format_type is not None
89 and arg_type
90 and arg_type != astroid.Uninferable
91 and not arg_matches_format_type(arg_type, format_type)
92 ):
93 self.add_message(
94 "bad-string-format-type",
95 node=node,
96 args=(arg_type.pytype(), format_type),
97 )
98 elif isinstance(args, (OTHER_NODES, nodes.Tuple)):
99 type_name = type(args).__name__
100 self.add_message("format-needs-mapping", node=node, args=type_name)
101 # else:
102 # The RHS of the format specifier is a name or
103 # expression. It may be a mapping object, so
104 # there's nothing we can check.
105 else:
106 # The format string uses only unnamed format specifiers.
107 # Check that the number of arguments passed to the RHS of
108 # the % operator matches the number required by the format
109 # string.
110 args_elts = []
111 if isinstance(args, nodes.Tuple):
112 rhs_tuple = utils.safe_infer(args)
113 num_args = None
114 if isinstance(rhs_tuple, nodes.BaseContainer):
115 args_elts = rhs_tuple.elts
116 num_args = len(args_elts)
117 elif isinstance(args, (OTHER_NODES, (nodes.Dict, nodes.DictComp))):
118 args_elts = [args]
119 num_args = 1
120 elif isinstance(args, nodes.Name):
121 inferred = utils.safe_infer(args)
122 if isinstance(inferred, nodes.Tuple):
123 # The variable is a tuple, so we need to get the elements
124 # from it for further inspection
125 args_elts = inferred.elts
126 num_args = len(args_elts)
127 elif isinstance(inferred, nodes.Const):
128 args_elts = [inferred]
129 num_args = 1
130 else:
131 num_args = None
132 else:
133 # The RHS of the format specifier is an expression.
134 # It could be a tuple of unknown size, so
135 # there's nothing we can check.
136 num_args = None
137 if num_args is not None:
138 if num_args > required_num_args:
139 self.add_message("too-many-format-args", node=node)
140 elif num_args < required_num_args:
141 self.add_message("too-few-format-args", node=node)
142 for arg, format_type in zip(args_elts, required_arg_types):
143 if not arg:
144 continue
145 arg_type = utils.safe_infer(arg)
146 if (
147 arg_type
148 and arg_type != astroid.Uninferable
149 and not arg_matches_format_type(arg_type, format_type)
150 ):
151 self.add_message(
152 "bad-string-format-type",
153 node=node,
154 args=(arg_type.pytype(), format_type),
155 )
Path 18: 1 calls (0.0)
BinOp (1)
1@only_required_for_messages(
2 "bad-format-character",
3 "truncated-format-string",
4 "mixed-format-string",
5 "bad-format-string-key",
6 "missing-format-string-key",
7 "unused-format-string-key",
8 "bad-string-format-type",
9 "format-needs-mapping",
10 "too-many-format-args",
11 "too-few-format-args",
12 "format-string-without-interpolation",
13 )
14 def visit_binop(self, node: nodes.BinOp) -> None:
15 if node.op != "%":
16 return
17 left = node.left
18 args = node.right
19
20 if not (isinstance(left, nodes.Const) and isinstance(left.value, str)):
21 return
22 format_string = left.value
23 try:
24 (
25 required_keys,
26 required_num_args,
27 required_key_types,
28 required_arg_types,
29 ) = utils.parse_format_string(format_string)
30 except utils.UnsupportedFormatCharacter as exc:
31 formatted = format_string[exc.index]
32 self.add_message(
33 "bad-format-character",
34 node=node,
35 args=(formatted, ord(formatted), exc.index),
36 )
37 return
38 except utils.IncompleteFormatString:
39 self.add_message("truncated-format-string", node=node)
40 return
41 if not required_keys and not required_num_args:
42 self.add_message("format-string-without-interpolation", node=node)
43 return
44 if required_keys and required_num_args:
45 # The format string uses both named and unnamed format
46 # specifiers.
47 self.add_message("mixed-format-string", node=node)
48 elif required_keys:
49 # The format string uses only named format specifiers.
50 # Check that the RHS of the % operator is a mapping object
51 # that contains precisely the set of keys required by the
52 # format string.
53 if isinstance(args, nodes.Dict):
54 keys = set()
55 unknown_keys = False
56 for k, _ in args.items:
57 if isinstance(k, nodes.Const):
58 key = k.value
59 if isinstance(key, str):
60 keys.add(key)
61 else:
62 self.add_message(
63 "bad-format-string-key", node=node, args=key
64 )
65 else:
66 # One of the keys was something other than a
67 # constant. Since we can't tell what it is,
68 # suppress checks for missing keys in the
69 # dictionary.
70 unknown_keys = True
71 if not unknown_keys:
72 for key in required_keys:
73 if key not in keys:
74 self.add_message(
75 "missing-format-string-key", node=node, args=key
76 )
77 for key in keys:
78 if key not in required_keys:
79 self.add_message(
80 "unused-format-string-key", node=node, args=key
81 )
82 for key, arg in args.items:
83 if not isinstance(key, nodes.Const):
84 continue
85 format_type = required_key_types.get(key.value, None)
86 arg_type = utils.safe_infer(arg)
87 if (
88 format_type is not None
89 and arg_type
90 and arg_type != astroid.Uninferable
91 and not arg_matches_format_type(arg_type, format_type)
92 ):
93 self.add_message(
94 "bad-string-format-type",
95 node=node,
96 args=(arg_type.pytype(), format_type),
97 )
98 elif isinstance(args, (OTHER_NODES, nodes.Tuple)):
99 type_name = type(args).__name__
100 self.add_message("format-needs-mapping", node=node, args=type_name)
101 # else:
102 # The RHS of the format specifier is a name or
103 # expression. It may be a mapping object, so
104 # there's nothing we can check.
105 else:
106 # The format string uses only unnamed format specifiers.
107 # Check that the number of arguments passed to the RHS of
108 # the % operator matches the number required by the format
109 # string.
110 args_elts = []
111 if isinstance(args, nodes.Tuple):
112 rhs_tuple = utils.safe_infer(args)
113 num_args = None
114 if isinstance(rhs_tuple, nodes.BaseContainer):
115 args_elts = rhs_tuple.elts
116 num_args = len(args_elts)
117 elif isinstance(args, (OTHER_NODES, (nodes.Dict, nodes.DictComp))):
118 args_elts = [args]
119 num_args = 1
120 elif isinstance(args, nodes.Name):
121 inferred = utils.safe_infer(args)
122 if isinstance(inferred, nodes.Tuple):
123 # The variable is a tuple, so we need to get the elements
124 # from it for further inspection
125 args_elts = inferred.elts
126 num_args = len(args_elts)
127 elif isinstance(inferred, nodes.Const):
128 args_elts = [inferred]
129 num_args = 1
130 else:
131 num_args = None
132 else:
133 # The RHS of the format specifier is an expression.
134 # It could be a tuple of unknown size, so
135 # there's nothing we can check.
136 num_args = None
137 if num_args is not None:
138 if num_args > required_num_args:
139 self.add_message("too-many-format-args", node=node)
140 elif num_args < required_num_args:
141 self.add_message("too-few-format-args", node=node)
142 for arg, format_type in zip(args_elts, required_arg_types):
143 if not arg:
144 continue
145 arg_type = utils.safe_infer(arg)
146 if (
147 arg_type
148 and arg_type != astroid.Uninferable
149 and not arg_matches_format_type(arg_type, format_type)
150 ):
151 self.add_message(
152 "bad-string-format-type",
153 node=node,
154 args=(arg_type.pytype(), format_type),
155 )
Path 19: 1 calls (0.0)
BinOp (1)
1@only_required_for_messages(
2 "bad-format-character",
3 "truncated-format-string",
4 "mixed-format-string",
5 "bad-format-string-key",
6 "missing-format-string-key",
7 "unused-format-string-key",
8 "bad-string-format-type",
9 "format-needs-mapping",
10 "too-many-format-args",
11 "too-few-format-args",
12 "format-string-without-interpolation",
13 )
14 def visit_binop(self, node: nodes.BinOp) -> None:
15 if node.op != "%":
16 return
17 left = node.left
18 args = node.right
19
20 if not (isinstance(left, nodes.Const) and isinstance(left.value, str)):
21 return
22 format_string = left.value
23 try:
24 (
25 required_keys,
26 required_num_args,
27 required_key_types,
28 required_arg_types,
29 ) = utils.parse_format_string(format_string)
30 except utils.UnsupportedFormatCharacter as exc:
31 formatted = format_string[exc.index]
32 self.add_message(
33 "bad-format-character",
34 node=node,
35 args=(formatted, ord(formatted), exc.index),
36 )
37 return
38 except utils.IncompleteFormatString:
39 self.add_message("truncated-format-string", node=node)
40 return
41 if not required_keys and not required_num_args:
42 self.add_message("format-string-without-interpolation", node=node)
43 return
44 if required_keys and required_num_args:
45 # The format string uses both named and unnamed format
46 # specifiers.
47 self.add_message("mixed-format-string", node=node)
48 elif required_keys:
49 # The format string uses only named format specifiers.
50 # Check that the RHS of the % operator is a mapping object
51 # that contains precisely the set of keys required by the
52 # format string.
53 if isinstance(args, nodes.Dict):
54 keys = set()
55 unknown_keys = False
56 for k, _ in args.items:
57 if isinstance(k, nodes.Const):
58 key = k.value
59 if isinstance(key, str):
60 keys.add(key)
61 else:
62 self.add_message(
63 "bad-format-string-key", node=node, args=key
64 )
65 else:
66 # One of the keys was something other than a
67 # constant. Since we can't tell what it is,
68 # suppress checks for missing keys in the
69 # dictionary.
70 unknown_keys = True
71 if not unknown_keys:
72 for key in required_keys:
73 if key not in keys:
74 self.add_message(
75 "missing-format-string-key", node=node, args=key
76 )
77 for key in keys:
78 if key not in required_keys:
79 self.add_message(
80 "unused-format-string-key", node=node, args=key
81 )
82 for key, arg in args.items:
83 if not isinstance(key, nodes.Const):
84 continue
85 format_type = required_key_types.get(key.value, None)
86 arg_type = utils.safe_infer(arg)
87 if (
88 format_type is not None
89 and arg_type
90 and arg_type != astroid.Uninferable
91 and not arg_matches_format_type(arg_type, format_type)
92 ):
93 self.add_message(
94 "bad-string-format-type",
95 node=node,
96 args=(arg_type.pytype(), format_type),
97 )
98 elif isinstance(args, (OTHER_NODES, nodes.Tuple)):
99 type_name = type(args).__name__
100 self.add_message("format-needs-mapping", node=node, args=type_name)
101 # else:
102 # The RHS of the format specifier is a name or
103 # expression. It may be a mapping object, so
104 # there's nothing we can check.
105 else:
106 # The format string uses only unnamed format specifiers.
107 # Check that the number of arguments passed to the RHS of
108 # the % operator matches the number required by the format
109 # string.
110 args_elts = []
111 if isinstance(args, nodes.Tuple):
112 rhs_tuple = utils.safe_infer(args)
113 num_args = None
114 if isinstance(rhs_tuple, nodes.BaseContainer):
115 args_elts = rhs_tuple.elts
116 num_args = len(args_elts)
117 elif isinstance(args, (OTHER_NODES, (nodes.Dict, nodes.DictComp))):
118 args_elts = [args]
119 num_args = 1
120 elif isinstance(args, nodes.Name):
121 inferred = utils.safe_infer(args)
122 if isinstance(inferred, nodes.Tuple):
123 # The variable is a tuple, so we need to get the elements
124 # from it for further inspection
125 args_elts = inferred.elts
126 num_args = len(args_elts)
127 elif isinstance(inferred, nodes.Const):
128 args_elts = [inferred]
129 num_args = 1
130 else:
131 num_args = None
132 else:
133 # The RHS of the format specifier is an expression.
134 # It could be a tuple of unknown size, so
135 # there's nothing we can check.
136 num_args = None
137 if num_args is not None:
138 if num_args > required_num_args:
139 self.add_message("too-many-format-args", node=node)
140 elif num_args < required_num_args:
141 self.add_message("too-few-format-args", node=node)
142 for arg, format_type in zip(args_elts, required_arg_types):
143 if not arg:
144 continue
145 arg_type = utils.safe_infer(arg)
146 if (
147 arg_type
148 and arg_type != astroid.Uninferable
149 and not arg_matches_format_type(arg_type, format_type)
150 ):
151 self.add_message(
152 "bad-string-format-type",
153 node=node,
154 args=(arg_type.pytype(), format_type),
155 )
Path 20: 1 calls (0.0)
BinOp (1)
1@only_required_for_messages(
2 "bad-format-character",
3 "truncated-format-string",
4 "mixed-format-string",
5 "bad-format-string-key",
6 "missing-format-string-key",
7 "unused-format-string-key",
8 "bad-string-format-type",
9 "format-needs-mapping",
10 "too-many-format-args",
11 "too-few-format-args",
12 "format-string-without-interpolation",
13 )
14 def visit_binop(self, node: nodes.BinOp) -> None:
15 if node.op != "%":
16 return
17 left = node.left
18 args = node.right
19
20 if not (isinstance(left, nodes.Const) and isinstance(left.value, str)):
21 return
22 format_string = left.value
23 try:
24 (
25 required_keys,
26 required_num_args,
27 required_key_types,
28 required_arg_types,
29 ) = utils.parse_format_string(format_string)
30 except utils.UnsupportedFormatCharacter as exc:
31 formatted = format_string[exc.index]
32 self.add_message(
33 "bad-format-character",
34 node=node,
35 args=(formatted, ord(formatted), exc.index),
36 )
37 return
38 except utils.IncompleteFormatString:
39 self.add_message("truncated-format-string", node=node)
40 return
41 if not required_keys and not required_num_args:
42 self.add_message("format-string-without-interpolation", node=node)
43 return
44 if required_keys and required_num_args:
45 # The format string uses both named and unnamed format
46 # specifiers.
47 self.add_message("mixed-format-string", node=node)
48 elif required_keys:
49 # The format string uses only named format specifiers.
50 # Check that the RHS of the % operator is a mapping object
51 # that contains precisely the set of keys required by the
52 # format string.
53 if isinstance(args, nodes.Dict):
54 keys = set()
55 unknown_keys = False
56 for k, _ in args.items:
57 if isinstance(k, nodes.Const):
58 key = k.value
59 if isinstance(key, str):
60 keys.add(key)
61 else:
62 self.add_message(
63 "bad-format-string-key", node=node, args=key
64 )
65 else:
66 # One of the keys was something other than a
67 # constant. Since we can't tell what it is,
68 # suppress checks for missing keys in the
69 # dictionary.
70 unknown_keys = True
71 if not unknown_keys:
72 for key in required_keys:
73 if key not in keys:
74 self.add_message(
75 "missing-format-string-key", node=node, args=key
76 )
77 for key in keys:
78 if key not in required_keys:
79 self.add_message(
80 "unused-format-string-key", node=node, args=key
81 )
82 for key, arg in args.items:
83 if not isinstance(key, nodes.Const):
84 continue
85 format_type = required_key_types.get(key.value, None)
86 arg_type = utils.safe_infer(arg)
87 if (
88 format_type is not None
89 and arg_type
90 and arg_type != astroid.Uninferable
91 and not arg_matches_format_type(arg_type, format_type)
92 ):
93 self.add_message(
94 "bad-string-format-type",
95 node=node,
96 args=(arg_type.pytype(), format_type),
97 )
98 elif isinstance(args, (OTHER_NODES, nodes.Tuple)):
99 type_name = type(args).__name__
100 self.add_message("format-needs-mapping", node=node, args=type_name)
101 # else:
102 # The RHS of the format specifier is a name or
103 # expression. It may be a mapping object, so
104 # there's nothing we can check.
105 else:
106 # The format string uses only unnamed format specifiers.
107 # Check that the number of arguments passed to the RHS of
108 # the % operator matches the number required by the format
109 # string.
110 args_elts = []
111 if isinstance(args, nodes.Tuple):
112 rhs_tuple = utils.safe_infer(args)
113 num_args = None
114 if isinstance(rhs_tuple, nodes.BaseContainer):
115 args_elts = rhs_tuple.elts
116 num_args = len(args_elts)
117 elif isinstance(args, (OTHER_NODES, (nodes.Dict, nodes.DictComp))):
118 args_elts = [args]
119 num_args = 1
120 elif isinstance(args, nodes.Name):
121 inferred = utils.safe_infer(args)
122 if isinstance(inferred, nodes.Tuple):
123 # The variable is a tuple, so we need to get the elements
124 # from it for further inspection
125 args_elts = inferred.elts
126 num_args = len(args_elts)
127 elif isinstance(inferred, nodes.Const):
128 args_elts = [inferred]
129 num_args = 1
130 else:
131 num_args = None
132 else:
133 # The RHS of the format specifier is an expression.
134 # It could be a tuple of unknown size, so
135 # there's nothing we can check.
136 num_args = None
137 if num_args is not None:
138 if num_args > required_num_args:
139 self.add_message("too-many-format-args", node=node)
140 elif num_args < required_num_args:
141 self.add_message("too-few-format-args", node=node)
142 for arg, format_type in zip(args_elts, required_arg_types):
143 if not arg:
144 continue
145 arg_type = utils.safe_infer(arg)
146 if (
147 arg_type
148 and arg_type != astroid.Uninferable
149 and not arg_matches_format_type(arg_type, format_type)
150 ):
151 self.add_message(
152 "bad-string-format-type",
153 node=node,
154 args=(arg_type.pytype(), format_type),
155 )
Path 21: 1 calls (0.0)
BinOp (1)
1@only_required_for_messages(
2 "bad-format-character",
3 "truncated-format-string",
4 "mixed-format-string",
5 "bad-format-string-key",
6 "missing-format-string-key",
7 "unused-format-string-key",
8 "bad-string-format-type",
9 "format-needs-mapping",
10 "too-many-format-args",
11 "too-few-format-args",
12 "format-string-without-interpolation",
13 )
14 def visit_binop(self, node: nodes.BinOp) -> None:
15 if node.op != "%":
16 return
17 left = node.left
18 args = node.right
19
20 if not (isinstance(left, nodes.Const) and isinstance(left.value, str)):
21 return
22 format_string = left.value
23 try:
24 (
25 required_keys,
26 required_num_args,
27 required_key_types,
28 required_arg_types,
29 ) = utils.parse_format_string(format_string)
30 except utils.UnsupportedFormatCharacter as exc:
31 formatted = format_string[exc.index]
32 self.add_message(
33 "bad-format-character",
34 node=node,
35 args=(formatted, ord(formatted), exc.index),
36 )
37 return
38 except utils.IncompleteFormatString:
39 self.add_message("truncated-format-string", node=node)
40 return
41 if not required_keys and not required_num_args:
42 self.add_message("format-string-without-interpolation", node=node)
43 return
44 if required_keys and required_num_args:
45 # The format string uses both named and unnamed format
46 # specifiers.
47 self.add_message("mixed-format-string", node=node)
48 elif required_keys:
49 # The format string uses only named format specifiers.
50 # Check that the RHS of the % operator is a mapping object
51 # that contains precisely the set of keys required by the
52 # format string.
53 if isinstance(args, nodes.Dict):
54 keys = set()
55 unknown_keys = False
56 for k, _ in args.items:
57 if isinstance(k, nodes.Const):
58 key = k.value
59 if isinstance(key, str):
60 keys.add(key)
61 else:
62 self.add_message(
63 "bad-format-string-key", node=node, args=key
64 )
65 else:
66 # One of the keys was something other than a
67 # constant. Since we can't tell what it is,
68 # suppress checks for missing keys in the
69 # dictionary.
70 unknown_keys = True
71 if not unknown_keys:
72 for key in required_keys:
73 if key not in keys:
74 self.add_message(
75 "missing-format-string-key", node=node, args=key
76 )
77 for key in keys:
78 if key not in required_keys:
79 self.add_message(
80 "unused-format-string-key", node=node, args=key
81 )
82 for key, arg in args.items:
83 if not isinstance(key, nodes.Const):
84 continue
85 format_type = required_key_types.get(key.value, None)
86 arg_type = utils.safe_infer(arg)
87 if (
88 format_type is not None
89 and arg_type
90 and arg_type != astroid.Uninferable
91 and not arg_matches_format_type(arg_type, format_type)
92 ):
93 self.add_message(
94 "bad-string-format-type",
95 node=node,
96 args=(arg_type.pytype(), format_type),
97 )
98 elif isinstance(args, (OTHER_NODES, nodes.Tuple)):
99 type_name = type(args).__name__
100 self.add_message("format-needs-mapping", node=node, args=type_name)
101 # else:
102 # The RHS of the format specifier is a name or
103 # expression. It may be a mapping object, so
104 # there's nothing we can check.
105 else:
106 # The format string uses only unnamed format specifiers.
107 # Check that the number of arguments passed to the RHS of
108 # the % operator matches the number required by the format
109 # string.
110 args_elts = []
111 if isinstance(args, nodes.Tuple):
112 rhs_tuple = utils.safe_infer(args)
113 num_args = None
114 if isinstance(rhs_tuple, nodes.BaseContainer):
115 args_elts = rhs_tuple.elts
116 num_args = len(args_elts)
117 elif isinstance(args, (OTHER_NODES, (nodes.Dict, nodes.DictComp))):
118 args_elts = [args]
119 num_args = 1
120 elif isinstance(args, nodes.Name):
121 inferred = utils.safe_infer(args)
122 if isinstance(inferred, nodes.Tuple):
123 # The variable is a tuple, so we need to get the elements
124 # from it for further inspection
125 args_elts = inferred.elts
126 num_args = len(args_elts)
127 elif isinstance(inferred, nodes.Const):
128 args_elts = [inferred]
129 num_args = 1
130 else:
131 num_args = None
132 else:
133 # The RHS of the format specifier is an expression.
134 # It could be a tuple of unknown size, so
135 # there's nothing we can check.
136 num_args = None
137 if num_args is not None:
138 if num_args > required_num_args:
139 self.add_message("too-many-format-args", node=node)
140 elif num_args < required_num_args:
141 self.add_message("too-few-format-args", node=node)
142 for arg, format_type in zip(args_elts, required_arg_types):
143 if not arg:
144 continue
145 arg_type = utils.safe_infer(arg)
146 if (
147 arg_type
148 and arg_type != astroid.Uninferable
149 and not arg_matches_format_type(arg_type, format_type)
150 ):
151 self.add_message(
152 "bad-string-format-type",
153 node=node,
154 args=(arg_type.pytype(), format_type),
155 )
Path 22: 1 calls (0.0)
BinOp (1)
1@only_required_for_messages(
2 "bad-format-character",
3 "truncated-format-string",
4 "mixed-format-string",
5 "bad-format-string-key",
6 "missing-format-string-key",
7 "unused-format-string-key",
8 "bad-string-format-type",
9 "format-needs-mapping",
10 "too-many-format-args",
11 "too-few-format-args",
12 "format-string-without-interpolation",
13 )
14 def visit_binop(self, node: nodes.BinOp) -> None:
15 if node.op != "%":
16 return
17 left = node.left
18 args = node.right
19
20 if not (isinstance(left, nodes.Const) and isinstance(left.value, str)):
21 return
22 format_string = left.value
23 try:
24 (
25 required_keys,
26 required_num_args,
27 required_key_types,
28 required_arg_types,
29 ) = utils.parse_format_string(format_string)
30 except utils.UnsupportedFormatCharacter as exc:
31 formatted = format_string[exc.index]
32 self.add_message(
33 "bad-format-character",
34 node=node,
35 args=(formatted, ord(formatted), exc.index),
36 )
37 return
38 except utils.IncompleteFormatString:
39 self.add_message("truncated-format-string", node=node)
40 return
41 if not required_keys and not required_num_args:
42 self.add_message("format-string-without-interpolation", node=node)
43 return
44 if required_keys and required_num_args:
45 # The format string uses both named and unnamed format
46 # specifiers.
47 self.add_message("mixed-format-string", node=node)
48 elif required_keys:
49 # The format string uses only named format specifiers.
50 # Check that the RHS of the % operator is a mapping object
51 # that contains precisely the set of keys required by the
52 # format string.
53 if isinstance(args, nodes.Dict):
54 keys = set()
55 unknown_keys = False
56 for k, _ in args.items:
57 if isinstance(k, nodes.Const):
58 key = k.value
59 if isinstance(key, str):
60 keys.add(key)
61 else:
62 self.add_message(
63 "bad-format-string-key", node=node, args=key
64 )
65 else:
66 # One of the keys was something other than a
67 # constant. Since we can't tell what it is,
68 # suppress checks for missing keys in the
69 # dictionary.
70 unknown_keys = True
71 if not unknown_keys:
72 for key in required_keys:
73 if key not in keys:
74 self.add_message(
75 "missing-format-string-key", node=node, args=key
76 )
77 for key in keys:
78 if key not in required_keys:
79 self.add_message(
80 "unused-format-string-key", node=node, args=key
81 )
82 for key, arg in args.items:
83 if not isinstance(key, nodes.Const):
84 continue
85 format_type = required_key_types.get(key.value, None)
86 arg_type = utils.safe_infer(arg)
87 if (
88 format_type is not None
89 and arg_type
90 and arg_type != astroid.Uninferable
91 and not arg_matches_format_type(arg_type, format_type)
92 ):
93 self.add_message(
94 "bad-string-format-type",
95 node=node,
96 args=(arg_type.pytype(), format_type),
97 )
98 elif isinstance(args, (OTHER_NODES, nodes.Tuple)):
99 type_name = type(args).__name__
100 self.add_message("format-needs-mapping", node=node, args=type_name)
101 # else:
102 # The RHS of the format specifier is a name or
103 # expression. It may be a mapping object, so
104 # there's nothing we can check.
105 else:
106 # The format string uses only unnamed format specifiers.
107 # Check that the number of arguments passed to the RHS of
108 # the % operator matches the number required by the format
109 # string.
110 args_elts = []
111 if isinstance(args, nodes.Tuple):
112 rhs_tuple = utils.safe_infer(args)
113 num_args = None
114 if isinstance(rhs_tuple, nodes.BaseContainer):
115 args_elts = rhs_tuple.elts
116 num_args = len(args_elts)
117 elif isinstance(args, (OTHER_NODES, (nodes.Dict, nodes.DictComp))):
118 args_elts = [args]
119 num_args = 1
120 elif isinstance(args, nodes.Name):
121 inferred = utils.safe_infer(args)
122 if isinstance(inferred, nodes.Tuple):
123 # The variable is a tuple, so we need to get the elements
124 # from it for further inspection
125 args_elts = inferred.elts
126 num_args = len(args_elts)
127 elif isinstance(inferred, nodes.Const):
128 args_elts = [inferred]
129 num_args = 1
130 else:
131 num_args = None
132 else:
133 # The RHS of the format specifier is an expression.
134 # It could be a tuple of unknown size, so
135 # there's nothing we can check.
136 num_args = None
137 if num_args is not None:
138 if num_args > required_num_args:
139 self.add_message("too-many-format-args", node=node)
140 elif num_args < required_num_args:
141 self.add_message("too-few-format-args", node=node)
142 for arg, format_type in zip(args_elts, required_arg_types):
143 if not arg:
144 continue
145 arg_type = utils.safe_infer(arg)
146 if (
147 arg_type
148 and arg_type != astroid.Uninferable
149 and not arg_matches_format_type(arg_type, format_type)
150 ):
151 self.add_message(
152 "bad-string-format-type",
153 node=node,
154 args=(arg_type.pytype(), format_type),
155 )
Path 23: 1 calls (0.0)
BinOp (1)
1@only_required_for_messages(
2 "bad-format-character",
3 "truncated-format-string",
4 "mixed-format-string",
5 "bad-format-string-key",
6 "missing-format-string-key",
7 "unused-format-string-key",
8 "bad-string-format-type",
9 "format-needs-mapping",
10 "too-many-format-args",
11 "too-few-format-args",
12 "format-string-without-interpolation",
13 )
14 def visit_binop(self, node: nodes.BinOp) -> None:
15 if node.op != "%":
16 return
17 left = node.left
18 args = node.right
19
20 if not (isinstance(left, nodes.Const) and isinstance(left.value, str)):
21 return
22 format_string = left.value
23 try:
24 (
25 required_keys,
26 required_num_args,
27 required_key_types,
28 required_arg_types,
29 ) = utils.parse_format_string(format_string)
30 except utils.UnsupportedFormatCharacter as exc:
31 formatted = format_string[exc.index]
32 self.add_message(
33 "bad-format-character",
34 node=node,
35 args=(formatted, ord(formatted), exc.index),
36 )
37 return
38 except utils.IncompleteFormatString:
39 self.add_message("truncated-format-string", node=node)
40 return
41 if not required_keys and not required_num_args:
42 self.add_message("format-string-without-interpolation", node=node)
43 return
44 if required_keys and required_num_args:
45 # The format string uses both named and unnamed format
46 # specifiers.
47 self.add_message("mixed-format-string", node=node)
48 elif required_keys:
49 # The format string uses only named format specifiers.
50 # Check that the RHS of the % operator is a mapping object
51 # that contains precisely the set of keys required by the
52 # format string.
53 if isinstance(args, nodes.Dict):
54 keys = set()
55 unknown_keys = False
56 for k, _ in args.items:
57 if isinstance(k, nodes.Const):
58 key = k.value
59 if isinstance(key, str):
60 keys.add(key)
61 else:
62 self.add_message(
63 "bad-format-string-key", node=node, args=key
64 )
65 else:
66 # One of the keys was something other than a
67 # constant. Since we can't tell what it is,
68 # suppress checks for missing keys in the
69 # dictionary.
70 unknown_keys = True
71 if not unknown_keys:
72 for key in required_keys:
73 if key not in keys:
74 self.add_message(
75 "missing-format-string-key", node=node, args=key
76 )
77 for key in keys:
78 if key not in required_keys:
79 self.add_message(
80 "unused-format-string-key", node=node, args=key
81 )
82 for key, arg in args.items:
83 if not isinstance(key, nodes.Const):
84 continue
85 format_type = required_key_types.get(key.value, None)
86 arg_type = utils.safe_infer(arg)
87 if (
88 format_type is not None
89 and arg_type
90 and arg_type != astroid.Uninferable
91 and not arg_matches_format_type(arg_type, format_type)
92 ):
93 self.add_message(
94 "bad-string-format-type",
95 node=node,
96 args=(arg_type.pytype(), format_type),
97 )
98 elif isinstance(args, (OTHER_NODES, nodes.Tuple)):
99 type_name = type(args).__name__
100 self.add_message("format-needs-mapping", node=node, args=type_name)
101 # else:
102 # The RHS of the format specifier is a name or
103 # expression. It may be a mapping object, so
104 # there's nothing we can check.
105 else:
106 # The format string uses only unnamed format specifiers.
107 # Check that the number of arguments passed to the RHS of
108 # the % operator matches the number required by the format
109 # string.
110 args_elts = []
111 if isinstance(args, nodes.Tuple):
112 rhs_tuple = utils.safe_infer(args)
113 num_args = None
114 if isinstance(rhs_tuple, nodes.BaseContainer):
115 args_elts = rhs_tuple.elts
116 num_args = len(args_elts)
117 elif isinstance(args, (OTHER_NODES, (nodes.Dict, nodes.DictComp))):
118 args_elts = [args]
119 num_args = 1
120 elif isinstance(args, nodes.Name):
121 inferred = utils.safe_infer(args)
122 if isinstance(inferred, nodes.Tuple):
123 # The variable is a tuple, so we need to get the elements
124 # from it for further inspection
125 args_elts = inferred.elts
126 num_args = len(args_elts)
127 elif isinstance(inferred, nodes.Const):
128 args_elts = [inferred]
129 num_args = 1
130 else:
131 num_args = None
132 else:
133 # The RHS of the format specifier is an expression.
134 # It could be a tuple of unknown size, so
135 # there's nothing we can check.
136 num_args = None
137 if num_args is not None:
138 if num_args > required_num_args:
139 self.add_message("too-many-format-args", node=node)
140 elif num_args < required_num_args:
141 self.add_message("too-few-format-args", node=node)
142 for arg, format_type in zip(args_elts, required_arg_types):
143 if not arg:
144 continue
145 arg_type = utils.safe_infer(arg)
146 if (
147 arg_type
148 and arg_type != astroid.Uninferable
149 and not arg_matches_format_type(arg_type, format_type)
150 ):
151 self.add_message(
152 "bad-string-format-type",
153 node=node,
154 args=(arg_type.pytype(), format_type),
155 )
Path 24: 1 calls (0.0)
BinOp (1)
1@only_required_for_messages(
2 "bad-format-character",
3 "truncated-format-string",
4 "mixed-format-string",
5 "bad-format-string-key",
6 "missing-format-string-key",
7 "unused-format-string-key",
8 "bad-string-format-type",
9 "format-needs-mapping",
10 "too-many-format-args",
11 "too-few-format-args",
12 "format-string-without-interpolation",
13 )
14 def visit_binop(self, node: nodes.BinOp) -> None:
15 if node.op != "%":
16 return
17 left = node.left
18 args = node.right
19
20 if not (isinstance(left, nodes.Const) and isinstance(left.value, str)):
21 return
22 format_string = left.value
23 try:
24 (
25 required_keys,
26 required_num_args,
27 required_key_types,
28 required_arg_types,
29 ) = utils.parse_format_string(format_string)
30 except utils.UnsupportedFormatCharacter as exc:
31 formatted = format_string[exc.index]
32 self.add_message(
33 "bad-format-character",
34 node=node,
35 args=(formatted, ord(formatted), exc.index),
36 )
37 return
38 except utils.IncompleteFormatString:
39 self.add_message("truncated-format-string", node=node)
40 return
41 if not required_keys and not required_num_args:
42 self.add_message("format-string-without-interpolation", node=node)
43 return
44 if required_keys and required_num_args:
45 # The format string uses both named and unnamed format
46 # specifiers.
47 self.add_message("mixed-format-string", node=node)
48 elif required_keys:
49 # The format string uses only named format specifiers.
50 # Check that the RHS of the % operator is a mapping object
51 # that contains precisely the set of keys required by the
52 # format string.
53 if isinstance(args, nodes.Dict):
54 keys = set()
55 unknown_keys = False
56 for k, _ in args.items:
57 if isinstance(k, nodes.Const):
58 key = k.value
59 if isinstance(key, str):
60 keys.add(key)
61 else:
62 self.add_message(
63 "bad-format-string-key", node=node, args=key
64 )
65 else:
66 # One of the keys was something other than a
67 # constant. Since we can't tell what it is,
68 # suppress checks for missing keys in the
69 # dictionary.
70 unknown_keys = True
71 if not unknown_keys:
72 for key in required_keys:
73 if key not in keys:
74 self.add_message(
75 "missing-format-string-key", node=node, args=key
76 )
77 for key in keys:
78 if key not in required_keys:
79 self.add_message(
80 "unused-format-string-key", node=node, args=key
81 )
82 for key, arg in args.items:
83 if not isinstance(key, nodes.Const):
84 continue
85 format_type = required_key_types.get(key.value, None)
86 arg_type = utils.safe_infer(arg)
87 if (
88 format_type is not None
89 and arg_type
90 and arg_type != astroid.Uninferable
91 and not arg_matches_format_type(arg_type, format_type)
92 ):
93 self.add_message(
94 "bad-string-format-type",
95 node=node,
96 args=(arg_type.pytype(), format_type),
97 )
98 elif isinstance(args, (OTHER_NODES, nodes.Tuple)):
99 type_name = type(args).__name__
100 self.add_message("format-needs-mapping", node=node, args=type_name)
101 # else:
102 # The RHS of the format specifier is a name or
103 # expression. It may be a mapping object, so
104 # there's nothing we can check.
105 else:
106 # The format string uses only unnamed format specifiers.
107 # Check that the number of arguments passed to the RHS of
108 # the % operator matches the number required by the format
109 # string.
110 args_elts = []
111 if isinstance(args, nodes.Tuple):
112 rhs_tuple = utils.safe_infer(args)
113 num_args = None
114 if isinstance(rhs_tuple, nodes.BaseContainer):
115 args_elts = rhs_tuple.elts
116 num_args = len(args_elts)
117 elif isinstance(args, (OTHER_NODES, (nodes.Dict, nodes.DictComp))):
118 args_elts = [args]
119 num_args = 1
120 elif isinstance(args, nodes.Name):
121 inferred = utils.safe_infer(args)
122 if isinstance(inferred, nodes.Tuple):
123 # The variable is a tuple, so we need to get the elements
124 # from it for further inspection
125 args_elts = inferred.elts
126 num_args = len(args_elts)
127 elif isinstance(inferred, nodes.Const):
128 args_elts = [inferred]
129 num_args = 1
130 else:
131 num_args = None
132 else:
133 # The RHS of the format specifier is an expression.
134 # It could be a tuple of unknown size, so
135 # there's nothing we can check.
136 num_args = None
137 if num_args is not None:
138 if num_args > required_num_args:
139 self.add_message("too-many-format-args", node=node)
140 elif num_args < required_num_args:
141 self.add_message("too-few-format-args", node=node)
142 for arg, format_type in zip(args_elts, required_arg_types):
143 if not arg:
144 continue
145 arg_type = utils.safe_infer(arg)
146 if (
147 arg_type
148 and arg_type != astroid.Uninferable
149 and not arg_matches_format_type(arg_type, format_type)
150 ):
151 self.add_message(
152 "bad-string-format-type",
153 node=node,
154 args=(arg_type.pytype(), format_type),
155 )
Path 25: 1 calls (0.0)
BinOp (1)
1@only_required_for_messages(
2 "bad-format-character",
3 "truncated-format-string",
4 "mixed-format-string",
5 "bad-format-string-key",
6 "missing-format-string-key",
7 "unused-format-string-key",
8 "bad-string-format-type",
9 "format-needs-mapping",
10 "too-many-format-args",
11 "too-few-format-args",
12 "format-string-without-interpolation",
13 )
14 def visit_binop(self, node: nodes.BinOp) -> None:
15 if node.op != "%":
16 return
17 left = node.left
18 args = node.right
19
20 if not (isinstance(left, nodes.Const) and isinstance(left.value, str)):
21 return
22 format_string = left.value
23 try:
24 (
25 required_keys,
26 required_num_args,
27 required_key_types,
28 required_arg_types,
29 ) = utils.parse_format_string(format_string)
30 except utils.UnsupportedFormatCharacter as exc:
31 formatted = format_string[exc.index]
32 self.add_message(
33 "bad-format-character",
34 node=node,
35 args=(formatted, ord(formatted), exc.index),
36 )
37 return
38 except utils.IncompleteFormatString:
39 self.add_message("truncated-format-string", node=node)
40 return
41 if not required_keys and not required_num_args:
42 self.add_message("format-string-without-interpolation", node=node)
43 return
44 if required_keys and required_num_args:
45 # The format string uses both named and unnamed format
46 # specifiers.
47 self.add_message("mixed-format-string", node=node)
48 elif required_keys:
49 # The format string uses only named format specifiers.
50 # Check that the RHS of the % operator is a mapping object
51 # that contains precisely the set of keys required by the
52 # format string.
53 if isinstance(args, nodes.Dict):
54 keys = set()
55 unknown_keys = False
56 for k, _ in args.items:
57 if isinstance(k, nodes.Const):
58 key = k.value
59 if isinstance(key, str):
60 keys.add(key)
61 else:
62 self.add_message(
63 "bad-format-string-key", node=node, args=key
64 )
65 else:
66 # One of the keys was something other than a
67 # constant. Since we can't tell what it is,
68 # suppress checks for missing keys in the
69 # dictionary.
70 unknown_keys = True
71 if not unknown_keys:
72 for key in required_keys:
73 if key not in keys:
74 self.add_message(
75 "missing-format-string-key", node=node, args=key
76 )
77 for key in keys:
78 if key not in required_keys:
79 self.add_message(
80 "unused-format-string-key", node=node, args=key
81 )
82 for key, arg in args.items:
83 if not isinstance(key, nodes.Const):
84 continue
85 format_type = required_key_types.get(key.value, None)
86 arg_type = utils.safe_infer(arg)
87 if (
88 format_type is not None
89 and arg_type
90 and arg_type != astroid.Uninferable
91 and not arg_matches_format_type(arg_type, format_type)
92 ):
93 self.add_message(
94 "bad-string-format-type",
95 node=node,
96 args=(arg_type.pytype(), format_type),
97 )
98 elif isinstance(args, (OTHER_NODES, nodes.Tuple)):
99 type_name = type(args).__name__
100 self.add_message("format-needs-mapping", node=node, args=type_name)
101 # else:
102 # The RHS of the format specifier is a name or
103 # expression. It may be a mapping object, so
104 # there's nothing we can check.
105 else:
106 # The format string uses only unnamed format specifiers.
107 # Check that the number of arguments passed to the RHS of
108 # the % operator matches the number required by the format
109 # string.
110 args_elts = []
111 if isinstance(args, nodes.Tuple):
112 rhs_tuple = utils.safe_infer(args)
113 num_args = None
114 if isinstance(rhs_tuple, nodes.BaseContainer):
115 args_elts = rhs_tuple.elts
116 num_args = len(args_elts)
117 elif isinstance(args, (OTHER_NODES, (nodes.Dict, nodes.DictComp))):
118 args_elts = [args]
119 num_args = 1
120 elif isinstance(args, nodes.Name):
121 inferred = utils.safe_infer(args)
122 if isinstance(inferred, nodes.Tuple):
123 # The variable is a tuple, so we need to get the elements
124 # from it for further inspection
125 args_elts = inferred.elts
126 num_args = len(args_elts)
127 elif isinstance(inferred, nodes.Const):
128 args_elts = [inferred]
129 num_args = 1
130 else:
131 num_args = None
132 else:
133 # The RHS of the format specifier is an expression.
134 # It could be a tuple of unknown size, so
135 # there's nothing we can check.
136 num_args = None
137 if num_args is not None:
138 if num_args > required_num_args:
139 self.add_message("too-many-format-args", node=node)
140 elif num_args < required_num_args:
141 self.add_message("too-few-format-args", node=node)
142 for arg, format_type in zip(args_elts, required_arg_types):
143 if not arg:
144 continue
145 arg_type = utils.safe_infer(arg)
146 if (
147 arg_type
148 and arg_type != astroid.Uninferable
149 and not arg_matches_format_type(arg_type, format_type)
150 ):
151 self.add_message(
152 "bad-string-format-type",
153 node=node,
154 args=(arg_type.pytype(), format_type),
155 )
Path 26: 1 calls (0.0)
BinOp (1)
None (1)
UnsupportedFormatCharacter (1)
1@only_required_for_messages(
2 "bad-format-character",
3 "truncated-format-string",
4 "mixed-format-string",
5 "bad-format-string-key",
6 "missing-format-string-key",
7 "unused-format-string-key",
8 "bad-string-format-type",
9 "format-needs-mapping",
10 "too-many-format-args",
11 "too-few-format-args",
12 "format-string-without-interpolation",
13 )
14 def visit_binop(self, node: nodes.BinOp) -> None:
15 if node.op != "%":
16 return
17 left = node.left
18 args = node.right
19
20 if not (isinstance(left, nodes.Const) and isinstance(left.value, str)):
21 return
22 format_string = left.value
23 try:
24 (
25 required_keys,
26 required_num_args,
27 required_key_types,
28 required_arg_types,
29 ) = utils.parse_format_string(format_string)
30 except utils.UnsupportedFormatCharacter as exc:
31 formatted = format_string[exc.index]
32 self.add_message(
33 "bad-format-character",
34 node=node,
35 args=(formatted, ord(formatted), exc.index),
36 )
37 return
38 except utils.IncompleteFormatString:
39 self.add_message("truncated-format-string", node=node)
40 return
41 if not required_keys and not required_num_args:
42 self.add_message("format-string-without-interpolation", node=node)
43 return
44 if required_keys and required_num_args:
45 # The format string uses both named and unnamed format
46 # specifiers.
47 self.add_message("mixed-format-string", node=node)
48 elif required_keys:
49 # The format string uses only named format specifiers.
50 # Check that the RHS of the % operator is a mapping object
51 # that contains precisely the set of keys required by the
52 # format string.
53 if isinstance(args, nodes.Dict):
54 keys = set()
55 unknown_keys = False
56 for k, _ in args.items:
57 if isinstance(k, nodes.Const):
58 key = k.value
59 if isinstance(key, str):
60 keys.add(key)
61 else:
62 self.add_message(
63 "bad-format-string-key", node=node, args=key
64 )
65 else:
66 # One of the keys was something other than a
67 # constant. Since we can't tell what it is,
68 # suppress checks for missing keys in the
69 # dictionary.
70 unknown_keys = True
71 if not unknown_keys:
72 for key in required_keys:
73 if key not in keys:
74 self.add_message(
75 "missing-format-string-key", node=node, args=key
76 )
77 for key in keys:
78 if key not in required_keys:
79 self.add_message(
80 "unused-format-string-key", node=node, args=key
81 )
82 for key, arg in args.items:
83 if not isinstance(key, nodes.Const):
84 continue
85 format_type = required_key_types.get(key.value, None)
86 arg_type = utils.safe_infer(arg)
87 if (
88 format_type is not None
89 and arg_type
90 and arg_type != astroid.Uninferable
91 and not arg_matches_format_type(arg_type, format_type)
92 ):
93 self.add_message(
94 "bad-string-format-type",
95 node=node,
96 args=(arg_type.pytype(), format_type),
97 )
98 elif isinstance(args, (OTHER_NODES, nodes.Tuple)):
99 type_name = type(args).__name__
100 self.add_message("format-needs-mapping", node=node, args=type_name)
101 # else:
102 # The RHS of the format specifier is a name or
103 # expression. It may be a mapping object, so
104 # there's nothing we can check.
105 else:
106 # The format string uses only unnamed format specifiers.
107 # Check that the number of arguments passed to the RHS of
108 # the % operator matches the number required by the format
109 # string.
110 args_elts = []
111 if isinstance(args, nodes.Tuple):
112 rhs_tuple = utils.safe_infer(args)
113 num_args = None
114 if isinstance(rhs_tuple, nodes.BaseContainer):
115 args_elts = rhs_tuple.elts
116 num_args = len(args_elts)
117 elif isinstance(args, (OTHER_NODES, (nodes.Dict, nodes.DictComp))):
118 args_elts = [args]
119 num_args = 1
120 elif isinstance(args, nodes.Name):
121 inferred = utils.safe_infer(args)
122 if isinstance(inferred, nodes.Tuple):
123 # The variable is a tuple, so we need to get the elements
124 # from it for further inspection
125 args_elts = inferred.elts
126 num_args = len(args_elts)
127 elif isinstance(inferred, nodes.Const):
128 args_elts = [inferred]
129 num_args = 1
130 else:
131 num_args = None
132 else:
133 # The RHS of the format specifier is an expression.
134 # It could be a tuple of unknown size, so
135 # there's nothing we can check.
136 num_args = None
137 if num_args is not None:
138 if num_args > required_num_args:
139 self.add_message("too-many-format-args", node=node)
140 elif num_args < required_num_args:
141 self.add_message("too-few-format-args", node=node)
142 for arg, format_type in zip(args_elts, required_arg_types):
143 if not arg:
144 continue
145 arg_type = utils.safe_infer(arg)
146 if (
147 arg_type
148 and arg_type != astroid.Uninferable
149 and not arg_matches_format_type(arg_type, format_type)
150 ):
151 self.add_message(
152 "bad-string-format-type",
153 node=node,
154 args=(arg_type.pytype(), format_type),
155 )
Path 27: 1 calls (0.0)
BinOp (1)
None (1)
IncompleteFormatString (1)
1@only_required_for_messages(
2 "bad-format-character",
3 "truncated-format-string",
4 "mixed-format-string",
5 "bad-format-string-key",
6 "missing-format-string-key",
7 "unused-format-string-key",
8 "bad-string-format-type",
9 "format-needs-mapping",
10 "too-many-format-args",
11 "too-few-format-args",
12 "format-string-without-interpolation",
13 )
14 def visit_binop(self, node: nodes.BinOp) -> None:
15 if node.op != "%":
16 return
17 left = node.left
18 args = node.right
19
20 if not (isinstance(left, nodes.Const) and isinstance(left.value, str)):
21 return
22 format_string = left.value
23 try:
24 (
25 required_keys,
26 required_num_args,
27 required_key_types,
28 required_arg_types,
29 ) = utils.parse_format_string(format_string)
30 except utils.UnsupportedFormatCharacter as exc:
31 formatted = format_string[exc.index]
32 self.add_message(
33 "bad-format-character",
34 node=node,
35 args=(formatted, ord(formatted), exc.index),
36 )
37 return
38 except utils.IncompleteFormatString:
39 self.add_message("truncated-format-string", node=node)
40 return
41 if not required_keys and not required_num_args:
42 self.add_message("format-string-without-interpolation", node=node)
43 return
44 if required_keys and required_num_args:
45 # The format string uses both named and unnamed format
46 # specifiers.
47 self.add_message("mixed-format-string", node=node)
48 elif required_keys:
49 # The format string uses only named format specifiers.
50 # Check that the RHS of the % operator is a mapping object
51 # that contains precisely the set of keys required by the
52 # format string.
53 if isinstance(args, nodes.Dict):
54 keys = set()
55 unknown_keys = False
56 for k, _ in args.items:
57 if isinstance(k, nodes.Const):
58 key = k.value
59 if isinstance(key, str):
60 keys.add(key)
61 else:
62 self.add_message(
63 "bad-format-string-key", node=node, args=key
64 )
65 else:
66 # One of the keys was something other than a
67 # constant. Since we can't tell what it is,
68 # suppress checks for missing keys in the
69 # dictionary.
70 unknown_keys = True
71 if not unknown_keys:
72 for key in required_keys:
73 if key not in keys:
74 self.add_message(
75 "missing-format-string-key", node=node, args=key
76 )
77 for key in keys:
78 if key not in required_keys:
79 self.add_message(
80 "unused-format-string-key", node=node, args=key
81 )
82 for key, arg in args.items:
83 if not isinstance(key, nodes.Const):
84 continue
85 format_type = required_key_types.get(key.value, None)
86 arg_type = utils.safe_infer(arg)
87 if (
88 format_type is not None
89 and arg_type
90 and arg_type != astroid.Uninferable
91 and not arg_matches_format_type(arg_type, format_type)
92 ):
93 self.add_message(
94 "bad-string-format-type",
95 node=node,
96 args=(arg_type.pytype(), format_type),
97 )
98 elif isinstance(args, (OTHER_NODES, nodes.Tuple)):
99 type_name = type(args).__name__
100 self.add_message("format-needs-mapping", node=node, args=type_name)
101 # else:
102 # The RHS of the format specifier is a name or
103 # expression. It may be a mapping object, so
104 # there's nothing we can check.
105 else:
106 # The format string uses only unnamed format specifiers.
107 # Check that the number of arguments passed to the RHS of
108 # the % operator matches the number required by the format
109 # string.
110 args_elts = []
111 if isinstance(args, nodes.Tuple):
112 rhs_tuple = utils.safe_infer(args)
113 num_args = None
114 if isinstance(rhs_tuple, nodes.BaseContainer):
115 args_elts = rhs_tuple.elts
116 num_args = len(args_elts)
117 elif isinstance(args, (OTHER_NODES, (nodes.Dict, nodes.DictComp))):
118 args_elts = [args]
119 num_args = 1
120 elif isinstance(args, nodes.Name):
121 inferred = utils.safe_infer(args)
122 if isinstance(inferred, nodes.Tuple):
123 # The variable is a tuple, so we need to get the elements
124 # from it for further inspection
125 args_elts = inferred.elts
126 num_args = len(args_elts)
127 elif isinstance(inferred, nodes.Const):
128 args_elts = [inferred]
129 num_args = 1
130 else:
131 num_args = None
132 else:
133 # The RHS of the format specifier is an expression.
134 # It could be a tuple of unknown size, so
135 # there's nothing we can check.
136 num_args = None
137 if num_args is not None:
138 if num_args > required_num_args:
139 self.add_message("too-many-format-args", node=node)
140 elif num_args < required_num_args:
141 self.add_message("too-few-format-args", node=node)
142 for arg, format_type in zip(args_elts, required_arg_types):
143 if not arg:
144 continue
145 arg_type = utils.safe_infer(arg)
146 if (
147 arg_type
148 and arg_type != astroid.Uninferable
149 and not arg_matches_format_type(arg_type, format_type)
150 ):
151 self.add_message(
152 "bad-string-format-type",
153 node=node,
154 args=(arg_type.pytype(), format_type),
155 )
Path 28: 1 calls (0.0)
BinOp (1)
1@only_required_for_messages(
2 "bad-format-character",
3 "truncated-format-string",
4 "mixed-format-string",
5 "bad-format-string-key",
6 "missing-format-string-key",
7 "unused-format-string-key",
8 "bad-string-format-type",
9 "format-needs-mapping",
10 "too-many-format-args",
11 "too-few-format-args",
12 "format-string-without-interpolation",
13 )
14 def visit_binop(self, node: nodes.BinOp) -> None:
15 if node.op != "%":
16 return
17 left = node.left
18 args = node.right
19
20 if not (isinstance(left, nodes.Const) and isinstance(left.value, str)):
21 return
22 format_string = left.value
23 try:
24 (
25 required_keys,
26 required_num_args,
27 required_key_types,
28 required_arg_types,
29 ) = utils.parse_format_string(format_string)
30 except utils.UnsupportedFormatCharacter as exc:
31 formatted = format_string[exc.index]
32 self.add_message(
33 "bad-format-character",
34 node=node,
35 args=(formatted, ord(formatted), exc.index),
36 )
37 return
38 except utils.IncompleteFormatString:
39 self.add_message("truncated-format-string", node=node)
40 return
41 if not required_keys and not required_num_args:
42 self.add_message("format-string-without-interpolation", node=node)
43 return
44 if required_keys and required_num_args:
45 # The format string uses both named and unnamed format
46 # specifiers.
47 self.add_message("mixed-format-string", node=node)
48 elif required_keys:
49 # The format string uses only named format specifiers.
50 # Check that the RHS of the % operator is a mapping object
51 # that contains precisely the set of keys required by the
52 # format string.
53 if isinstance(args, nodes.Dict):
54 keys = set()
55 unknown_keys = False
56 for k, _ in args.items:
57 if isinstance(k, nodes.Const):
58 key = k.value
59 if isinstance(key, str):
60 keys.add(key)
61 else:
62 self.add_message(
63 "bad-format-string-key", node=node, args=key
64 )
65 else:
66 # One of the keys was something other than a
67 # constant. Since we can't tell what it is,
68 # suppress checks for missing keys in the
69 # dictionary.
70 unknown_keys = True
71 if not unknown_keys:
72 for key in required_keys:
73 if key not in keys:
74 self.add_message(
75 "missing-format-string-key", node=node, args=key
76 )
77 for key in keys:
78 if key not in required_keys:
79 self.add_message(
80 "unused-format-string-key", node=node, args=key
81 )
82 for key, arg in args.items:
83 if not isinstance(key, nodes.Const):
84 continue
85 format_type = required_key_types.get(key.value, None)
86 arg_type = utils.safe_infer(arg)
87 if (
88 format_type is not None
89 and arg_type
90 and arg_type != astroid.Uninferable
91 and not arg_matches_format_type(arg_type, format_type)
92 ):
93 self.add_message(
94 "bad-string-format-type",
95 node=node,
96 args=(arg_type.pytype(), format_type),
97 )
98 elif isinstance(args, (OTHER_NODES, nodes.Tuple)):
99 type_name = type(args).__name__
100 self.add_message("format-needs-mapping", node=node, args=type_name)
101 # else:
102 # The RHS of the format specifier is a name or
103 # expression. It may be a mapping object, so
104 # there's nothing we can check.
105 else:
106 # The format string uses only unnamed format specifiers.
107 # Check that the number of arguments passed to the RHS of
108 # the % operator matches the number required by the format
109 # string.
110 args_elts = []
111 if isinstance(args, nodes.Tuple):
112 rhs_tuple = utils.safe_infer(args)
113 num_args = None
114 if isinstance(rhs_tuple, nodes.BaseContainer):
115 args_elts = rhs_tuple.elts
116 num_args = len(args_elts)
117 elif isinstance(args, (OTHER_NODES, (nodes.Dict, nodes.DictComp))):
118 args_elts = [args]
119 num_args = 1
120 elif isinstance(args, nodes.Name):
121 inferred = utils.safe_infer(args)
122 if isinstance(inferred, nodes.Tuple):
123 # The variable is a tuple, so we need to get the elements
124 # from it for further inspection
125 args_elts = inferred.elts
126 num_args = len(args_elts)
127 elif isinstance(inferred, nodes.Const):
128 args_elts = [inferred]
129 num_args = 1
130 else:
131 num_args = None
132 else:
133 # The RHS of the format specifier is an expression.
134 # It could be a tuple of unknown size, so
135 # there's nothing we can check.
136 num_args = None
137 if num_args is not None:
138 if num_args > required_num_args:
139 self.add_message("too-many-format-args", node=node)
140 elif num_args < required_num_args:
141 self.add_message("too-few-format-args", node=node)
142 for arg, format_type in zip(args_elts, required_arg_types):
143 if not arg:
144 continue
145 arg_type = utils.safe_infer(arg)
146 if (
147 arg_type
148 and arg_type != astroid.Uninferable
149 and not arg_matches_format_type(arg_type, format_type)
150 ):
151 self.add_message(
152 "bad-string-format-type",
153 node=node,
154 args=(arg_type.pytype(), format_type),
155 )
Path 29: 1 calls (0.0)
BinOp (1)
1@only_required_for_messages(
2 "bad-format-character",
3 "truncated-format-string",
4 "mixed-format-string",
5 "bad-format-string-key",
6 "missing-format-string-key",
7 "unused-format-string-key",
8 "bad-string-format-type",
9 "format-needs-mapping",
10 "too-many-format-args",
11 "too-few-format-args",
12 "format-string-without-interpolation",
13 )
14 def visit_binop(self, node: nodes.BinOp) -> None:
15 if node.op != "%":
16 return
17 left = node.left
18 args = node.right
19
20 if not (isinstance(left, nodes.Const) and isinstance(left.value, str)):
21 return
22 format_string = left.value
23 try:
24 (
25 required_keys,
26 required_num_args,
27 required_key_types,
28 required_arg_types,
29 ) = utils.parse_format_string(format_string)
30 except utils.UnsupportedFormatCharacter as exc:
31 formatted = format_string[exc.index]
32 self.add_message(
33 "bad-format-character",
34 node=node,
35 args=(formatted, ord(formatted), exc.index),
36 )
37 return
38 except utils.IncompleteFormatString:
39 self.add_message("truncated-format-string", node=node)
40 return
41 if not required_keys and not required_num_args:
42 self.add_message("format-string-without-interpolation", node=node)
43 return
44 if required_keys and required_num_args:
45 # The format string uses both named and unnamed format
46 # specifiers.
47 self.add_message("mixed-format-string", node=node)
48 elif required_keys:
49 # The format string uses only named format specifiers.
50 # Check that the RHS of the % operator is a mapping object
51 # that contains precisely the set of keys required by the
52 # format string.
53 if isinstance(args, nodes.Dict):
54 keys = set()
55 unknown_keys = False
56 for k, _ in args.items:
57 if isinstance(k, nodes.Const):
58 key = k.value
59 if isinstance(key, str):
60 keys.add(key)
61 else:
62 self.add_message(
63 "bad-format-string-key", node=node, args=key
64 )
65 else:
66 # One of the keys was something other than a
67 # constant. Since we can't tell what it is,
68 # suppress checks for missing keys in the
69 # dictionary.
70 unknown_keys = True
71 if not unknown_keys:
72 for key in required_keys:
73 if key not in keys:
74 self.add_message(
75 "missing-format-string-key", node=node, args=key
76 )
77 for key in keys:
78 if key not in required_keys:
79 self.add_message(
80 "unused-format-string-key", node=node, args=key
81 )
82 for key, arg in args.items:
83 if not isinstance(key, nodes.Const):
84 continue
85 format_type = required_key_types.get(key.value, None)
86 arg_type = utils.safe_infer(arg)
87 if (
88 format_type is not None
89 and arg_type
90 and arg_type != astroid.Uninferable
91 and not arg_matches_format_type(arg_type, format_type)
92 ):
93 self.add_message(
94 "bad-string-format-type",
95 node=node,
96 args=(arg_type.pytype(), format_type),
97 )
98 elif isinstance(args, (OTHER_NODES, nodes.Tuple)):
99 type_name = type(args).__name__
100 self.add_message("format-needs-mapping", node=node, args=type_name)
101 # else:
102 # The RHS of the format specifier is a name or
103 # expression. It may be a mapping object, so
104 # there's nothing we can check.
105 else:
106 # The format string uses only unnamed format specifiers.
107 # Check that the number of arguments passed to the RHS of
108 # the % operator matches the number required by the format
109 # string.
110 args_elts = []
111 if isinstance(args, nodes.Tuple):
112 rhs_tuple = utils.safe_infer(args)
113 num_args = None
114 if isinstance(rhs_tuple, nodes.BaseContainer):
115 args_elts = rhs_tuple.elts
116 num_args = len(args_elts)
117 elif isinstance(args, (OTHER_NODES, (nodes.Dict, nodes.DictComp))):
118 args_elts = [args]
119 num_args = 1
120 elif isinstance(args, nodes.Name):
121 inferred = utils.safe_infer(args)
122 if isinstance(inferred, nodes.Tuple):
123 # The variable is a tuple, so we need to get the elements
124 # from it for further inspection
125 args_elts = inferred.elts
126 num_args = len(args_elts)
127 elif isinstance(inferred, nodes.Const):
128 args_elts = [inferred]
129 num_args = 1
130 else:
131 num_args = None
132 else:
133 # The RHS of the format specifier is an expression.
134 # It could be a tuple of unknown size, so
135 # there's nothing we can check.
136 num_args = None
137 if num_args is not None:
138 if num_args > required_num_args:
139 self.add_message("too-many-format-args", node=node)
140 elif num_args < required_num_args:
141 self.add_message("too-few-format-args", node=node)
142 for arg, format_type in zip(args_elts, required_arg_types):
143 if not arg:
144 continue
145 arg_type = utils.safe_infer(arg)
146 if (
147 arg_type
148 and arg_type != astroid.Uninferable
149 and not arg_matches_format_type(arg_type, format_type)
150 ):
151 self.add_message(
152 "bad-string-format-type",
153 node=node,
154 args=(arg_type.pytype(), format_type),
155 )