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

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

Issue 876793002: pylint: upgrade to 1.4.1 (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@master
Patch Set: Created 5 years, 10 months 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
« no previous file with comments | « third_party/pylint/checkers/base.py ('k') | third_party/pylint/checkers/exceptions.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright (c) 2003-2014 LOGILAB S.A. (Paris, FRANCE). 1 # Copyright (c) 2003-2014 LOGILAB S.A. (Paris, FRANCE).
2 # http://www.logilab.fr/ -- mailto:contact@logilab.fr 2 # http://www.logilab.fr/ -- mailto:contact@logilab.fr
3 # 3 #
4 # This program is free software; you can redistribute it and/or modify it under 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 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 6 # Foundation; either version 2 of the License, or (at your option) any later
7 # version. 7 # version.
8 # 8 #
9 # This program is distributed in the hope that it will be useful, but WITHOUT 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 10 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
(...skipping 12 matching lines...) Expand all
23 import astroid 23 import astroid
24 from astroid import YES, Instance, are_exclusive, AssAttr, Class 24 from astroid import YES, Instance, are_exclusive, AssAttr, Class
25 from astroid.bases import Generator, BUILTINS 25 from astroid.bases import Generator, BUILTINS
26 from astroid.inference import InferenceContext 26 from astroid.inference import InferenceContext
27 27
28 from pylint.interfaces import IAstroidChecker 28 from pylint.interfaces import IAstroidChecker
29 from pylint.checkers import BaseChecker 29 from pylint.checkers import BaseChecker
30 from pylint.checkers.utils import ( 30 from pylint.checkers.utils import (
31 PYMETHODS, overrides_a_method, check_messages, is_attr_private, 31 PYMETHODS, overrides_a_method, check_messages, is_attr_private,
32 is_attr_protected, node_frame_class, safe_infer, is_builtin_object, 32 is_attr_protected, node_frame_class, safe_infer, is_builtin_object,
33 decorated_with_property) 33 decorated_with_property, unimplemented_abstract_methods)
34 import six 34 import six
35 35
36 if sys.version_info >= (3, 0): 36 if sys.version_info >= (3, 0):
37 NEXT_METHOD = '__next__' 37 NEXT_METHOD = '__next__'
38 else: 38 else:
39 NEXT_METHOD = 'next' 39 NEXT_METHOD = 'next'
40 ITER_METHODS = ('__iter__', '__getitem__') 40 ITER_METHODS = ('__iter__', '__getitem__')
41 41
42 def _called_in_methods(func, klass, methods): 42 def _called_in_methods(func, klass, methods):
43 """ Check if the func was called in any of the given methods, 43 """ Check if the func was called in any of the given methods,
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 ), 172 ),
173 173
174 'E0221': ('Interface resolved to %s is not a class', 174 'E0221': ('Interface resolved to %s is not a class',
175 'interface-is-not-class', 175 'interface-is-not-class',
176 'Used when a class claims to implement an interface which is not \ 176 'Used when a class claims to implement an interface which is not \
177 a class.'), 177 a class.'),
178 'E0222': ('Missing method %r from %s interface', 178 'E0222': ('Missing method %r from %s interface',
179 'missing-interface-method', 179 'missing-interface-method',
180 'Used when a method declared in an interface is missing from a \ 180 'Used when a method declared in an interface is missing from a \
181 class implementing this interface'), 181 class implementing this interface'),
182 'W0221': ('Arguments number differs from %s method', 182 'W0221': ('Arguments number differs from %s %r method',
183 'arguments-differ', 183 'arguments-differ',
184 'Used when a method has a different number of arguments than in \ 184 'Used when a method has a different number of arguments than in \
185 the implemented interface or in an overridden method.'), 185 the implemented interface or in an overridden method.'),
186 'W0222': ('Signature differs from %s method', 186 'W0222': ('Signature differs from %s %r method',
187 'signature-differs', 187 'signature-differs',
188 'Used when a method signature is different than in the \ 188 'Used when a method signature is different than in the \
189 implemented interface or in an overridden method.'), 189 implemented interface or in an overridden method.'),
190 'W0223': ('Method %r is abstract in class %r but is not overridden', 190 'W0223': ('Method %r is abstract in class %r but is not overridden',
191 'abstract-method', 191 'abstract-method',
192 'Used when an abstract method (i.e. raise NotImplementedError) is \ 192 'Used when an abstract method (i.e. raise NotImplementedError) is \
193 not overridden in concrete class.' 193 not overridden in concrete class.'
194 ), 194 ),
195 'F0220': ('failed to resolve interfaces implemented by %s (%s)', # W0224 195 'F0220': ('failed to resolve interfaces implemented by %s (%s)', # W0224
196 'unresolved-interface', 196 'unresolved-interface',
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after
489 try: 489 try:
490 self._check_slots_elt(elt) 490 self._check_slots_elt(elt)
491 except astroid.InferenceError: 491 except astroid.InferenceError:
492 continue 492 continue
493 493
494 def _check_slots_elt(self, elt): 494 def _check_slots_elt(self, elt):
495 for infered in elt.infer(): 495 for infered in elt.infer():
496 if infered is YES: 496 if infered is YES:
497 continue 497 continue
498 if (not isinstance(infered, astroid.Const) or 498 if (not isinstance(infered, astroid.Const) or
499 not isinstance(infered.value, str)): 499 not isinstance(infered.value, six.string_types)):
500 self.add_message('invalid-slots-object', 500 self.add_message('invalid-slots-object',
501 args=infered.as_string(), 501 args=infered.as_string(),
502 node=elt) 502 node=elt)
503 continue 503 continue
504 if not infered.value: 504 if not infered.value:
505 self.add_message('invalid-slots-object', 505 self.add_message('invalid-slots-object',
506 args=infered.as_string(), 506 args=infered.as_string(),
507 node=elt) 507 node=elt)
508 508
509 def _check_iter(self, node): 509 def _check_iter(self, node):
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
578 """ Check that the given assattr node 578 """ Check that the given assattr node
579 is defined in the class slots. 579 is defined in the class slots.
580 """ 580 """
581 infered = safe_infer(node.expr) 581 infered = safe_infer(node.expr)
582 if infered and isinstance(infered, Instance): 582 if infered and isinstance(infered, Instance):
583 klass = infered._proxied 583 klass = infered._proxied
584 if '__slots__' not in klass.locals or not klass.newstyle: 584 if '__slots__' not in klass.locals or not klass.newstyle:
585 return 585 return
586 586
587 slots = klass.slots() 587 slots = klass.slots()
588 if slots is None:
589 return
588 # If any ancestor doesn't use slots, the slots 590 # If any ancestor doesn't use slots, the slots
589 # defined for this class are superfluous. 591 # defined for this class are superfluous.
590 if any('__slots__' not in ancestor.locals and 592 if any('__slots__' not in ancestor.locals and
591 ancestor.name != 'object' 593 ancestor.name != 'object'
592 for ancestor in klass.ancestors()): 594 for ancestor in klass.ancestors()):
593 return 595 return
594 596
595 if not any(slot.value == node.attrname for slot in slots): 597 if not any(slot.value == node.attrname for slot in slots):
596 # If we have a '__dict__' in slots, then 598 # If we have a '__dict__' in slots, then
597 # assigning any name is valid. 599 # assigning any name is valid.
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
791 valid = repr(config[0]) 793 valid = repr(config[0])
792 else: 794 else:
793 valid = ', '.join(repr(v) for v in config[:-1]) 795 valid = ', '.join(repr(v) for v in config[:-1])
794 valid = '%s or %r' % (valid, config[-1]) 796 valid = '%s or %r' % (valid, config[-1])
795 self.add_message(message, args=(method_name, valid), node=node) 797 self.add_message(message, args=(method_name, valid), node=node)
796 798
797 def _check_bases_classes(self, node): 799 def _check_bases_classes(self, node):
798 """check that the given class node implements abstract methods from 800 """check that the given class node implements abstract methods from
799 base classes 801 base classes
800 """ 802 """
803 def is_abstract(method):
804 return method.is_abstract(pass_is_abstract=False)
805
801 # check if this class abstract 806 # check if this class abstract
802 if class_is_abstract(node): 807 if class_is_abstract(node):
803 return 808 return
804 for method in node.methods(): 809
810 methods = sorted(
811 unimplemented_abstract_methods(node, is_abstract).items(),
812 key=lambda item: item[0],
813 )
814 for name, method in methods:
805 owner = method.parent.frame() 815 owner = method.parent.frame()
806 if owner is node: 816 if owner is node:
807 continue 817 continue
808 # owner is not this class, it must be a parent class 818 # owner is not this class, it must be a parent class
809 # check that the ancestor's method is not abstract 819 # check that the ancestor's method is not abstract
810 if method.name in node.locals: 820 if name in node.locals:
811 # it is redefined as an attribute or with a descriptor 821 # it is redefined as an attribute or with a descriptor
812 continue 822 continue
813 if method.is_abstract(pass_is_abstract=False): 823 self.add_message('abstract-method', node=node,
814 self.add_message('abstract-method', node=node, 824 args=(name, owner.name))
815 args=(method.name, owner.name))
816 825
817 def _check_interfaces(self, node): 826 def _check_interfaces(self, node):
818 """check that the given class node really implements declared 827 """check that the given class node really implements declared
819 interfaces 828 interfaces
820 """ 829 """
821 e0221_hack = [False] 830 e0221_hack = [False]
822 def iface_handler(obj): 831 def iface_handler(obj):
823 """filter interface objects, it should be classes""" 832 """filter interface objects, it should be classes"""
824 if not isinstance(obj, astroid.Class): 833 if not isinstance(obj, astroid.Class):
825 e0221_hack[0] = True 834 e0221_hack[0] = True
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
923 return 932 return
924 # don't care about functions with unknown argument (builtins) 933 # don't care about functions with unknown argument (builtins)
925 if method1.args.args is None or refmethod.args.args is None: 934 if method1.args.args is None or refmethod.args.args is None:
926 return 935 return
927 # if we use *args, **kwargs, skip the below checks 936 # if we use *args, **kwargs, skip the below checks
928 if method1.args.vararg or method1.args.kwarg: 937 if method1.args.vararg or method1.args.kwarg:
929 return 938 return
930 if is_attr_private(method1.name): 939 if is_attr_private(method1.name):
931 return 940 return
932 if len(method1.args.args) != len(refmethod.args.args): 941 if len(method1.args.args) != len(refmethod.args.args):
933 self.add_message('arguments-differ', args=class_type, node=method1) 942 self.add_message('arguments-differ',
943 args=(class_type, method1.name),
944 node=method1)
934 elif len(method1.args.defaults) < len(refmethod.args.defaults): 945 elif len(method1.args.defaults) < len(refmethod.args.defaults):
935 self.add_message('signature-differs', args=class_type, node=method1) 946 self.add_message('signature-differs',
947 args=(class_type, method1.name),
948 node=method1)
936 949
937 def is_first_attr(self, node): 950 def is_first_attr(self, node):
938 """Check that attribute lookup name use first attribute variable name 951 """Check that attribute lookup name use first attribute variable name
939 (self for method, cls for classmethod and mcs for metaclass). 952 (self for method, cls for classmethod and mcs for metaclass).
940 """ 953 """
941 return self._first_attrs and isinstance(node.expr, astroid.Name) and \ 954 return self._first_attrs and isinstance(node.expr, astroid.Name) and \
942 node.expr.name == self._first_attrs[-1] 955 node.expr.name == self._first_attrs[-1]
943 956
944 def _ancestors_to_call(klass_node, method='__init__'): 957 def _ancestors_to_call(klass_node, method='__init__'):
945 """return a dictionary where keys are the list of base classes providing 958 """return a dictionary where keys are the list of base classes providing
(...skipping 13 matching lines...) Expand all
959 is a Function node 972 is a Function node
960 """ 973 """
961 for n in node.local_attr(method_name): 974 for n in node.local_attr(method_name):
962 if isinstance(n, astroid.Function): 975 if isinstance(n, astroid.Function):
963 return n 976 return n
964 raise astroid.NotFoundError(method_name) 977 raise astroid.NotFoundError(method_name)
965 978
966 def register(linter): 979 def register(linter):
967 """required method to auto register this checker """ 980 """required method to auto register this checker """
968 linter.register_checker(ClassChecker(linter)) 981 linter.register_checker(ClassChecker(linter))
OLDNEW
« no previous file with comments | « third_party/pylint/checkers/base.py ('k') | third_party/pylint/checkers/exceptions.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698