string_format.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  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. """Checker for string formatting operations.
  17. """
  18. import string
  19. from logilab import astng
  20. from pylint.interfaces import IASTNGChecker
  21. from pylint.checkers import BaseChecker
  22. from pylint.checkers import utils
  23. MSGS = {
  24. 'E1300': ("Unsupported format character %r (%#02x) at index %d",
  25. "Used when a unsupported format character is used in a format\
  26. string."),
  27. 'E1301': ("Format string ends in middle of conversion specifier",
  28. "Used when a format string terminates before the end of a \
  29. conversion specifier."),
  30. 'E1302': ("Mixing named and unnamed conversion specifiers in format string",
  31. "Used when a format string contains both named (e.g. '%(foo)d') \
  32. and unnamed (e.g. '%d') conversion specifiers. This is also \
  33. used when a named conversion specifier contains * for the \
  34. minimum field width and/or precision."),
  35. 'E1303': ("Expected mapping for format string, not %s",
  36. "Used when a format string that uses named conversion specifiers \
  37. is used with an argument that is not a mapping."),
  38. 'W1300': ("Format string dictionary key should be a string, not %s",
  39. "Used when a format string that uses named conversion specifiers \
  40. is used with a dictionary whose keys are not all strings."),
  41. 'W1301': ("Unused key %r in format string dictionary",
  42. "Used when a format string that uses named conversion specifiers \
  43. is used with a dictionary that conWtains keys not required by the \
  44. format string."),
  45. 'E1304': ("Missing key %r in format string dictionary",
  46. "Used when a format string that uses named conversion specifiers \
  47. is used with a dictionary that doesn't contain all the keys \
  48. required by the format string."),
  49. 'E1305': ("Too many arguments for format string",
  50. "Used when a format string that uses unnamed conversion \
  51. specifiers is given too few arguments."),
  52. 'E1306': ("Not enough arguments for format string",
  53. "Used when a format string that uses unnamed conversion \
  54. specifiers is given too many arguments"),
  55. }
  56. OTHER_NODES = (astng.Const, astng.List, astng.Backquote,
  57. astng.Lambda, astng.Function,
  58. astng.ListComp, astng.SetComp, astng.GenExpr)
  59. class StringFormatChecker(BaseChecker):
  60. """Checks string formatting operations to ensure that the format string
  61. is valid and the arguments match the format string.
  62. """
  63. __implements__ = (IASTNGChecker,)
  64. name = 'string_format'
  65. msgs = MSGS
  66. def visit_binop(self, node):
  67. if node.op != '%':
  68. return
  69. left = node.left
  70. args = node.right
  71. if not (isinstance(left, astng.Const)
  72. and isinstance(left.value, basestring)):
  73. return
  74. format_string = left.value
  75. try:
  76. required_keys, required_num_args = \
  77. utils.parse_format_string(format_string)
  78. except utils.UnsupportedFormatCharacter, e:
  79. c = format_string[e.index]
  80. self.add_message('E1300', node=node, args=(c, ord(c), e.index))
  81. return
  82. except utils.IncompleteFormatString:
  83. self.add_message('E1301', node=node)
  84. return
  85. if required_keys and required_num_args:
  86. # The format string uses both named and unnamed format
  87. # specifiers.
  88. self.add_message('E1302', node=node)
  89. elif required_keys:
  90. # The format string uses only named format specifiers.
  91. # Check that the RHS of the % operator is a mapping object
  92. # that contains precisely the set of keys required by the
  93. # format string.
  94. if isinstance(args, astng.Dict):
  95. keys = set()
  96. unknown_keys = False
  97. for k, v in args.items:
  98. if isinstance(k, astng.Const):
  99. key = k.value
  100. if isinstance(key, basestring):
  101. keys.add(key)
  102. else:
  103. self.add_message('W1300', node=node, args=key)
  104. else:
  105. # One of the keys was something other than a
  106. # constant. Since we can't tell what it is,
  107. # supress checks for missing keys in the
  108. # dictionary.
  109. unknown_keys = True
  110. if not unknown_keys:
  111. for key in required_keys:
  112. if key not in keys:
  113. self.add_message('E1304', node=node, args=key)
  114. for key in keys:
  115. if key not in required_keys:
  116. self.add_message('W1301', node=node, args=key)
  117. elif isinstance(args, OTHER_NODES + (astng.Tuple,)):
  118. type_name = type(args).__name__
  119. self.add_message('E1303', node=node, args=type_name)
  120. # else:
  121. # The RHS of the format specifier is a name or
  122. # expression. It may be a mapping object, so
  123. # there's nothing we can check.
  124. else:
  125. # The format string uses only unnamed format specifiers.
  126. # Check that the number of arguments passed to the RHS of
  127. # the % operator matches the number required by the format
  128. # string.
  129. if isinstance(args, astng.Tuple):
  130. num_args = len(args.elts)
  131. elif isinstance(args, OTHER_NODES + (astng.Dict, astng.DictComp)):
  132. num_args = 1
  133. else:
  134. # The RHS of the format specifier is a name or
  135. # expression. It could be a tuple of unknown size, so
  136. # there's nothing we can check.
  137. num_args = None
  138. if num_args is not None:
  139. if num_args > required_num_args:
  140. self.add_message('E1305', node=node)
  141. elif num_args < required_num_args:
  142. self.add_message('E1306', node=node)
  143. def register(linter):
  144. """required method to auto register this checker """
  145. linter.register_checker(StringFormatChecker(linter))