Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(138)

Side by Side Diff: third_party/pylint/checkers/string_format.py

Issue 739393004: Revert "Revert "pylint: upgrade to 1.3.1"" (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools/
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « third_party/pylint/checkers/stdlib.py ('k') | third_party/pylint/checkers/strings.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 # Copyright (c) 2009-2010 Arista Networks, Inc. - James Lingard
2 # Copyright (c) 2004-2010 LOGILAB S.A. (Paris, FRANCE).
3 # http://www.logilab.fr/ -- mailto:contact@logilab.fr
4 # This program is free software; you can redistribute it and/or modify it under
5 # the terms of the GNU General Public License as published by the Free Software
6 # Foundation; either version 2 of the License, or (at your option) any later
7 # version.
8 #
9 # This program is distributed in the hope that it will be useful, but WITHOUT
10 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details
12 #
13 # You should have received a copy of the GNU General Public License along with
14 # this program; if not, write to the Free Software Foundation, Inc.,
15 # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16
17
18 """Checker for string formatting operations.
19 """
20
21 import string
22 from logilab import astng
23 from pylint.interfaces import IASTNGChecker
24 from pylint.checkers import BaseChecker
25 from pylint.checkers import utils
26
27
28 MSGS = {
29 'E1300': ("Unsupported format character %r (%#02x) at index %d",
30 "Used when a unsupported format character is used in a format\
31 string."),
32 'E1301': ("Format string ends in middle of conversion specifier",
33 "Used when a format string terminates before the end of a \
34 conversion specifier."),
35 'E1302': ("Mixing named and unnamed conversion specifiers in format string",
36 "Used when a format string contains both named (e.g. '%(foo)d') \
37 and unnamed (e.g. '%d') conversion specifiers. This is also \
38 used when a named conversion specifier contains * for the \
39 minimum field width and/or precision."),
40 'E1303': ("Expected mapping for format string, not %s",
41 "Used when a format string that uses named conversion specifiers \
42 is used with an argument that is not a mapping."),
43 'W1300': ("Format string dictionary key should be a string, not %s",
44 "Used when a format string that uses named conversion specifiers \
45 is used with a dictionary whose keys are not all strings."),
46 'W1301': ("Unused key %r in format string dictionary",
47 "Used when a format string that uses named conversion specifiers \
48 is used with a dictionary that conWtains keys not required by the \
49 format string."),
50 'E1304': ("Missing key %r in format string dictionary",
51 "Used when a format string that uses named conversion specifiers \
52 is used with a dictionary that doesn't contain all the keys \
53 required by the format string."),
54 'E1305': ("Too many arguments for format string",
55 "Used when a format string that uses unnamed conversion \
56 specifiers is given too few arguments."),
57 'E1306': ("Not enough arguments for format string",
58 "Used when a format string that uses unnamed conversion \
59 specifiers is given too many arguments"),
60 }
61
62 OTHER_NODES = (astng.Const, astng.List, astng.Backquote,
63 astng.Lambda, astng.Function,
64 astng.ListComp, astng.SetComp, astng.GenExpr)
65
66 class StringFormatChecker(BaseChecker):
67 """Checks string formatting operations to ensure that the format string
68 is valid and the arguments match the format string.
69 """
70
71 __implements__ = (IASTNGChecker,)
72 name = 'string_format'
73 msgs = MSGS
74
75 def visit_binop(self, node):
76 if node.op != '%':
77 return
78 left = node.left
79 args = node.right
80
81 if not (isinstance(left, astng.Const)
82 and isinstance(left.value, basestring)):
83 return
84 format_string = left.value
85 try:
86 required_keys, required_num_args = \
87 utils.parse_format_string(format_string)
88 except utils.UnsupportedFormatCharacter, e:
89 c = format_string[e.index]
90 self.add_message('E1300', node=node, args=(c, ord(c), e.index))
91 return
92 except utils.IncompleteFormatString:
93 self.add_message('E1301', node=node)
94 return
95 if required_keys and required_num_args:
96 # The format string uses both named and unnamed format
97 # specifiers.
98 self.add_message('E1302', node=node)
99 elif required_keys:
100 # The format string uses only named format specifiers.
101 # Check that the RHS of the % operator is a mapping object
102 # that contains precisely the set of keys required by the
103 # format string.
104 if isinstance(args, astng.Dict):
105 keys = set()
106 unknown_keys = False
107 for k, v in args.items:
108 if isinstance(k, astng.Const):
109 key = k.value
110 if isinstance(key, basestring):
111 keys.add(key)
112 else:
113 self.add_message('W1300', node=node, args=key)
114 else:
115 # One of the keys was something other than a
116 # constant. Since we can't tell what it is,
117 # supress checks for missing keys in the
118 # dictionary.
119 unknown_keys = True
120 if not unknown_keys:
121 for key in required_keys:
122 if key not in keys:
123 self.add_message('E1304', node=node, args=key)
124 for key in keys:
125 if key not in required_keys:
126 self.add_message('W1301', node=node, args=key)
127 elif isinstance(args, OTHER_NODES + (astng.Tuple,)):
128 type_name = type(args).__name__
129 self.add_message('E1303', node=node, args=type_name)
130 # else:
131 # The RHS of the format specifier is a name or
132 # expression. It may be a mapping object, so
133 # there's nothing we can check.
134 else:
135 # The format string uses only unnamed format specifiers.
136 # Check that the number of arguments passed to the RHS of
137 # the % operator matches the number required by the format
138 # string.
139 if isinstance(args, astng.Tuple):
140 num_args = len(args.elts)
141 elif isinstance(args, OTHER_NODES + (astng.Dict, astng.DictComp)):
142 num_args = 1
143 else:
144 # The RHS of the format specifier is a name or
145 # expression. It could be a tuple of unknown size, so
146 # there's nothing we can check.
147 num_args = None
148 if num_args is not None:
149 if num_args > required_num_args:
150 self.add_message('E1305', node=node)
151 elif num_args < required_num_args:
152 self.add_message('E1306', node=node)
153
154
155 def register(linter):
156 """required method to auto register this checker """
157 linter.register_checker(StringFormatChecker(linter))
OLDNEW
« no previous file with comments | « third_party/pylint/checkers/stdlib.py ('k') | third_party/pylint/checkers/strings.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698