1- import sys
1+ from typing import List
22
33from pylint .exceptions import UnknownMessageError
4+ from pylint .lint import PyLinter
45
56
67def get_class (module_name , kls ):
@@ -21,14 +22,14 @@ def __repr__(self):
2122 return self .message
2223
2324
24- def get_checker (linter , checker_class ):
25+ def get_checker (linter : PyLinter , checker_class ):
2526 for checker in linter .get_checkers ():
2627 if isinstance (checker , checker_class ):
2728 return checker
2829 raise NoSuchChecker (checker_class )
2930
3031
31- def augment_visit (linter , checker_method , augmentation ):
32+ def augment_visit (linter : PyLinter , checker_method , augmentation ):
3233 """
3334 Augmenting a visit enables additional errors to be raised (although that case is
3435 better served using a new checker) or to suppress all warnings in certain circumstances.
@@ -39,25 +40,34 @@ def augment_visit(linter, checker_method, augmentation):
3940 prevent any further checking.
4041 """
4142
42- if sys .version_info [0 ] <= 2 :
43- checker = get_checker (linter , checker_method .im_class )
44- else :
45- try :
46- checker = get_checker (linter , checker_method .__self__ .__class__ )
47- except AttributeError :
48- checker = get_checker (linter , get_class (checker_method .__module__ , checker_method .__qualname__ ))
43+ try :
44+ checker = get_checker (linter , checker_method .__self__ .__class__ )
45+ except AttributeError :
46+ checker = get_checker (linter , get_class (checker_method .__module__ , checker_method .__qualname__ ))
4947
5048 old_method = getattr (checker , checker_method .__name__ )
49+ setattr (checker , checker_method .__name__ , AugmentFunc (old_method , augmentation ))
50+
51+
52+ class AugmentFunc :
53+ def __init__ (self , old_method , augmentation_func ):
54+ self .old_method = old_method
55+ self .augmentation_func = augmentation_func
56+
57+ def __call__ (self , node ):
58+ self .augmentation_func (Chain (self .old_method , node ), node )
59+
5160
52- def augment_func ( node ) :
53- def chain ( ):
54- old_method ( node )
55- augmentation ( chain , node )
61+ class Chain :
62+ def __init__ ( self , old_method , node ):
63+ self . old_method = old_method
64+ self . node = node
5665
57- setattr (checker , checker_method .__name__ , augment_func )
66+ def __call__ (self ):
67+ self .old_method (self .node )
5868
5969
60- class Suppress ( object ) :
70+ class Suppress :
6171
6272 def __init__ (self , linter ):
6373 self ._linter = linter
@@ -91,31 +101,54 @@ def __exit__(self, exc_type, exc_val, exc_tb):
91101 self ._linter .add_message (* to_append_args , ** to_append_kwargs )
92102
93103
94- def supress_message (linter , checker_method , message_id , test_func ):
95- import warnings
96- warnings .warn ("'supress_message' has been deprecated in favour of the correctly-spelled 'suppress_message'" ,
97- DeprecationWarning )
98- return suppress_message (linter , checker_method , message_id , test_func )
99-
100-
101- def suppress_message (linter , checker_method , message_id_or_symbol , test_func ):
104+ def suppress_message (linter : PyLinter , checker_method , message_id_or_symbol , test_func ):
102105 """
103106 This wrapper allows the suppression of a message if the supplied test function
104107 returns True. It is useful to prevent one particular message from being raised
105108 in one particular case, while leaving the rest of the messages intact.
106109 """
107- # At some point, pylint started preferring message symbols to message IDs. However this is not done
108- # consistently or uniformly - occasionally there are some message IDs with no matching symbols.
109- # We try to work around this here by suppressing both the ID and the symbol, if we can find it.
110- # This also gives us compatability with a broader range of pylint versions.
111-
112- # Similarly, a commit between version 1.2 and 1.3 changed where the messages are stored - see:
113- # https://bitbucket.org/logilab/pylint/commits/0b67f42799bed08aebb47babdc9fb0e761efc4ff#chg-reporters/__init__.py
114- # Therefore here, we try the new attribute name, and fall back to the old version for
115- # compatability with <=1.2 and >=1.3
116- msgs_store = getattr (linter , 'msgs_store' , linter )
117-
118- def get_message_definitions (message_id_or_symbol ):
110+ augment_visit (linter , checker_method , DoSuppress (linter , message_id_or_symbol , test_func ))
111+
112+
113+ class DoSuppress :
114+ def __init__ (self , linter : PyLinter , message_id_or_symbol , test_func ):
115+ self .linter = linter
116+ self .message_id_or_symbol = message_id_or_symbol
117+ self .test_func = test_func
118+
119+ def __call__ (self , chain , node ):
120+ with Suppress (self .linter ) as s :
121+ if self .test_func (node ):
122+ s .suppress (* self .symbols )
123+ chain ()
124+
125+ @property
126+ def symbols (self ) -> List :
127+ # At some point, pylint started preferring message symbols to message IDs. However this is not done
128+ # consistently or uniformly - occasionally there are some message IDs with no matching symbols.
129+ # We try to work around this here by suppressing both the ID and the symbol, if we can find it.
130+ # This also gives us compatability with a broader range of pylint versions.
131+
132+ # Similarly, a commit between version 1.2 and 1.3 changed where the messages are stored - see:
133+ # https://bitbucket.org/logilab/pylint/commits/0b67f42799bed08aebb47babdc9fb0e761efc4ff#chg-reporters/__init__.py
134+ # Therefore here, we try the new attribute name, and fall back to the old version for
135+ # compatability with <=1.2 and >=1.3
136+
137+ try :
138+ pylint_messages = self .get_message_definitions (self .message_id_or_symbol )
139+ the_symbols = [symbol
140+ for pylint_message in pylint_messages
141+ for symbol in (pylint_message .msgid , pylint_message .symbol )
142+ if symbol is not None ]
143+ except UnknownMessageError :
144+ # This can happen due to mismatches of pylint versions and plugin expectations of available messages
145+ the_symbols = [self .message_id_or_symbol ]
146+
147+ return the_symbols
148+
149+ def get_message_definitions (self , message_id_or_symbol ):
150+ msgs_store = getattr (self .linter , 'msgs_store' , self .linter )
151+
119152 if hasattr (msgs_store , 'check_message_id' ):
120153 return [msgs_store .check_message_id (message_id_or_symbol )]
121154 # pylint 2.0 renamed check_message_id to get_message_definition in:
@@ -128,20 +161,3 @@ def get_message_definitions(message_id_or_symbol):
128161 return msgs_store .get_message_definitions (message_id_or_symbol )
129162 else :
130163 raise ValueError ('pylint.utils.MessagesStore does not have a get_message_definition(s) method' )
131-
132- try :
133- pylint_messages = get_message_definitions (message_id_or_symbol )
134- symbols = [symbol
135- for pylint_message in pylint_messages
136- for symbol in (pylint_message .msgid , pylint_message .symbol )
137- if symbol is not None ]
138- except UnknownMessageError :
139- # This can happen due to mismatches of pylint versions and plugin expectations of available messages
140- symbols = [message_id_or_symbol ]
141-
142- def do_suppress (chain , node ):
143- with Suppress (linter ) as s :
144- if test_func (node ):
145- s .suppress (* symbols )
146- chain ()
147- augment_visit (linter , checker_method , do_suppress )
0 commit comments