newstyle.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. # Copyright (c) 2005-2006 LOGILAB S.A. (Paris, FRANCE).
  2. # http://www.logilab.fr/ -- mailto:contact@logilab.fr
  3. #
  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. """check for new / old style related problems
  17. """
  18. from logilab import astng
  19. from pylint.interfaces import IASTNGChecker
  20. from pylint.checkers import BaseChecker
  21. from pylint.checkers.utils import check_messages
  22. MSGS = {
  23. 'E1001': ('Use of __slots__ on an old style class',
  24. 'Used when an old style class uses the __slots__ attribute.'),
  25. 'E1002': ('Use of super on an old style class',
  26. 'Used when an old style class uses the super builtin.'),
  27. 'E1003': ('Bad first argument %r given to super class',
  28. 'Used when another argument than the current class is given as \
  29. first argument of the super builtin.'),
  30. 'W1001': ('Use of "property" on an old style class',
  31. 'Used when PyLint detect the use of the builtin "property" \
  32. on an old style class while this is relying on new style \
  33. classes features'),
  34. }
  35. class NewStyleConflictChecker(BaseChecker):
  36. """checks for usage of new style capabilities on old style classes and
  37. other new/old styles conflicts problems
  38. * use of property, __slots__, super
  39. * "super" usage
  40. """
  41. __implements__ = (IASTNGChecker,)
  42. # configuration section name
  43. name = 'newstyle'
  44. # messages
  45. msgs = MSGS
  46. priority = -2
  47. # configuration options
  48. options = ()
  49. @check_messages('E1001')
  50. def visit_class(self, node):
  51. """check __slots__ usage
  52. """
  53. if '__slots__' in node and not node.newstyle:
  54. self.add_message('E1001', node=node)
  55. @check_messages('W1001')
  56. def visit_callfunc(self, node):
  57. """check property usage"""
  58. parent = node.parent.frame()
  59. if (isinstance(parent, astng.Class) and
  60. not parent.newstyle and
  61. isinstance(node.func, astng.Name)):
  62. name = node.func.name
  63. if name == 'property':
  64. self.add_message('W1001', node=node)
  65. @check_messages('E1002', 'E1003')
  66. def visit_function(self, node):
  67. """check use of super"""
  68. # ignore actual functions or method within a new style class
  69. if not node.is_method():
  70. return
  71. klass = node.parent.frame()
  72. for stmt in node.nodes_of_class(astng.CallFunc):
  73. expr = stmt.func
  74. if not isinstance(expr, astng.Getattr):
  75. continue
  76. call = expr.expr
  77. # skip the test if using super
  78. if isinstance(call, astng.CallFunc) and \
  79. isinstance(call.func, astng.Name) and \
  80. call.func.name == 'super':
  81. if not klass.newstyle:
  82. # super should not be used on an old style class
  83. self.add_message('E1002', node=node)
  84. else:
  85. # super first arg should be the class
  86. try:
  87. supcls = (call.args and call.args[0].infer().next()
  88. or None)
  89. except astng.InferenceError:
  90. continue
  91. if klass is not supcls:
  92. supcls = getattr(supcls, 'name', supcls)
  93. self.add_message('E1003', node=node, args=supcls)
  94. def register(linter):
  95. """required method to auto register this checker """
  96. linter.register_checker(NewStyleConflictChecker(linter))