22
22
from logilab import astng
23
23
from pylint.interfaces import IASTNGChecker
24
24
from pylint.checkers import BaseChecker
25
from pylint.checkers import utils
27
'E9900': ("Unsupported format character %r (%#02x) at index %d",
29
'E1300': ("Unsupported format character %r (%#02x) at index %d",
28
30
"Used when a unsupported format character is used in a format\
30
'E9901': ("Format string ends in middle of conversion specifier",
32
'E1301': ("Format string ends in middle of conversion specifier",
31
33
"Used when a format string terminates before the end of a \
32
34
conversion specifier."),
33
'E9902': ("Mixing named and unnamed conversion specifiers in format string",
35
'E1302': ("Mixing named and unnamed conversion specifiers in format string",
34
36
"Used when a format string contains both named (e.g. '%(foo)d') \
35
37
and unnamed (e.g. '%d') conversion specifiers. This is also \
36
38
used when a named conversion specifier contains * for the \
37
39
minimum field width and/or precision."),
38
'E9903': ("Expected mapping for format string, not %s",
40
'E1303': ("Expected mapping for format string, not %s",
39
41
"Used when a format string that uses named conversion specifiers \
40
42
is used with an argument that is not a mapping."),
41
'W9900': ("Format string dictionary key should be a string, not %s",
43
'W1300': ("Format string dictionary key should be a string, not %s",
42
44
"Used when a format string that uses named conversion specifiers \
43
45
is used with a dictionary whose keys are not all strings."),
44
'W9901': ("Unused key %r in format string dictionary",
46
'W1301': ("Unused key %r in format string dictionary",
45
47
"Used when a format string that uses named conversion specifiers \
46
48
is used with a dictionary that conWtains keys not required by the \
48
'E9904': ("Missing key %r in format string dictionary",
50
'E1304': ("Missing key %r in format string dictionary",
49
51
"Used when a format string that uses named conversion specifiers \
50
52
is used with a dictionary that doesn't contain all the keys \
51
53
required by the format string."),
52
'E9905': ("Too many arguments for format string",
54
'E1305': ("Too many arguments for format string",
53
55
"Used when a format string that uses unnamed conversion \
54
56
specifiers is given too few arguments."),
55
'E9906': ("Not enough arguments for format string",
57
'E1306': ("Not enough arguments for format string",
56
58
"Used when a format string that uses unnamed conversion \
57
59
specifiers is given too many arguments"),
60
class IncompleteFormatString(Exception):
61
"""A format string ended in the middle of a format specifier."""
64
class UnsupportedFormatCharacter(Exception):
65
"""A format character in a format string is not one of the supported
67
def __init__(self, index):
68
Exception.__init__(self, index)
71
def parse_format_string(format_string):
72
"""Parses a format string, returning a tuple of (keys, num_args), where keys
73
is the set of mapping keys in the format string, and num_args is the number
74
of arguments required by the format string. Raises
75
IncompleteFormatString or UnsupportedFormatCharacter if a
76
parse error occurs."""
81
if i == len(format_string):
82
raise IncompleteFormatString
83
return (i, format_string[i])
85
while i < len(format_string):
89
# Parse the mapping key (optional).
102
key = format_string[key_start:key_end]
104
# Parse the conversion flags (optional).
107
# Parse the minimum field width (optional).
112
while c in string.digits:
114
# Parse the precision (optional).
121
while c in string.digits:
123
# Parse the length modifier (optional).
126
# Parse the conversion type (mandatory).
127
if c not in 'diouxXeEfFgGcrs%':
128
raise UnsupportedFormatCharacter(i)
134
return keys, num_args
136
62
OTHER_NODES = (astng.Const, astng.List, astng.Backquote,
137
63
astng.Lambda, astng.Function,
138
64
astng.ListComp, astng.SetComp, astng.GenExpr)
158
84
format_string = left.value
160
86
required_keys, required_num_args = \
161
parse_format_string(format_string)
162
except UnsupportedFormatCharacter, e:
87
utils.parse_format_string(format_string)
88
except utils.UnsupportedFormatCharacter, e:
163
89
c = format_string[e.index]
164
self.add_message('E9900', node=node, args=(c, ord(c), e.index))
90
self.add_message('E1300', node=node, args=(c, ord(c), e.index))
166
except IncompleteFormatString:
167
self.add_message('E9901', node=node)
92
except utils.IncompleteFormatString:
93
self.add_message('E1301', node=node)
169
95
if required_keys and required_num_args:
170
96
# The format string uses both named and unnamed format
172
self.add_message('E9902', node=node)
98
self.add_message('E1302', node=node)
173
99
elif required_keys:
174
100
# The format string uses only named format specifiers.
175
101
# Check that the RHS of the % operator is a mapping object
194
120
if not unknown_keys:
195
121
for key in required_keys:
196
122
if key not in keys:
197
self.add_message('E9904', node=node, args=key)
123
self.add_message('E1304', node=node, args=key)
199
125
if key not in required_keys:
200
self.add_message('W9901', node=node, args=key)
126
self.add_message('W1301', node=node, args=key)
201
127
elif isinstance(args, OTHER_NODES + (astng.Tuple,)):
202
128
type_name = type(args).__name__
203
self.add_message('E9903', node=node, args=type_name)
129
self.add_message('E1303', node=node, args=type_name)
205
131
# The RHS of the format specifier is a name or
206
132
# expression. It may be a mapping object, so