Package _setup :: Package dev :: Module _pylint
[hide private]
[frames] | no frames]

Source Code for Module _setup.dev._pylint

  1  # -*- coding: ascii -*- 
  2  # 
  3  # Copyright 2006, 2007, 2008, 2009, 2010 
  4  # Andr\xe9 Malo or his licensors, as applicable 
  5  # 
  6  # Licensed under the Apache License, Version 2.0 (the "License"); 
  7  # you may not use this file except in compliance with the License. 
  8  # You may obtain a copy of the License at 
  9  # 
 10  #     http://www.apache.org/licenses/LICENSE-2.0 
 11  # 
 12  # Unless required by applicable law or agreed to in writing, software 
 13  # distributed under the License is distributed on an "AS IS" BASIS, 
 14  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 15  # See the License for the specific language governing permissions and 
 16  # limitations under the License. 
 17  """ 
 18  ================================= 
 19   Support for code analysis tools 
 20  ================================= 
 21   
 22  Support for code analysis tools. 
 23  """ 
 24  __author__ = u"Andr\xe9 Malo" 
 25  __docformat__ = "restructuredtext en" 
 26   
 27  import re as _re 
 28  import sys as _sys 
 29   
 30  from _setup import term as _term 
 31  from _setup import shell as _shell 
 32   
 33   
34 -class NotFinished(Exception):
35 """ Exception used for message passing in the stream filter """
36
37 -class NotParseable(Exception):
38 """ Exception used for message passing in the stream filter """
39
40 -class SpecialMessage(Exception):
41 """ Exception used for message passing in the stream filter """
42 43
44 -class FilterStream(object):
45 """ Stream filter """ 46 _LINERE = _re.compile(r''' 47 (?P<name>[^:]+) 48 : 49 (?P<lineno>\d+) 50 :\s+ 51 \[(?P<mid>[^\],]+)(?:,\s+(?P<func>[^\]]+))?\] 52 \s+ 53 (?P<desc>.*) 54 ''', _re.X) 55 _SIMRE = _re.compile(r'in (?P<number>\d+) files') 56
57 - def __init__(self, term, stream=_sys.stdout):
58 self.written = False 59 self._stream = stream 60 self._lastname = None 61 self._term = dict(term) 62 self._buffer = ''
63
64 - def write(self, towrite):
65 """ Stream write function """ 66 self._buffer += towrite 67 term = self._term 68 69 while True: 70 try: 71 name, lineno, mid, func, desc = self._parse() 72 except NotFinished: 73 break 74 except SpecialMessage, e: 75 self._dospecial(e) 76 continue 77 except NotParseable, e: 78 self._print_literal(str(e.args[0])) 79 continue 80 81 if name != self._lastname: 82 if self._lastname is not None: 83 self._stream.write("\n") 84 term['path'] = name 85 self._stream.write( 86 "%(BOLD)s>>> %(path)s%(NORMAL)s\n" % term 87 ) 88 self._lastname = name 89 self.written = True 90 91 term['mid'] = mid 92 if mid.startswith('E') or mid.startswith('F'): 93 self._stream.write("%(BOLD)s%(RED)s%(mid)s%(NORMAL)s" % term) 94 elif mid == 'W0511': 95 self._stream.write( 96 "%(BOLD)s%(GREEN)s%(mid)s%(NORMAL)s" % term 97 ) 98 else: 99 self._stream.write( 100 "%(BOLD)s%(YELLOW)s%(mid)s%(NORMAL)s" % term 101 ) 102 103 if int(lineno) != 0: 104 term['lineno'] = lineno 105 self._stream.write(" (%(lineno)s" % term) 106 if func: 107 term['func'] = func 108 self._stream.write( 109 ", %(BOLD)s%(YELLOW)s%(func)s%(NORMAL)s" % term 110 ) 111 self._stream.write(')') 112 113 self._stream.write(": %s\n" % desc) 114 self._stream.flush() 115 116 return
117
118 - def _print_literal(self, line):
119 """ Print literal """ 120 suppress = ( 121 line.startswith('Unable to get imported names for ') or 122 line.startswith("Exception exceptions.RuntimeError: 'generator " 123 "ignored GeneratorExit' in <generator object at") or 124 line.startswith("Exception RuntimeError: 'generator " 125 "ignored GeneratorExit' in <generator object") or 126 not line.strip() 127 ) 128 if not suppress: 129 self._stream.write("%s\n" % line) 130 self._stream.flush() 131 self.written = True
132
133 - def _dospecial(self, e):
134 """ Deal with special messages """ 135 if e.args[0] == 'R0801': 136 match = self._SIMRE.search(e.args[1]) 137 if not match: 138 raise AssertionError( 139 'Could not determine number of similar files' 140 ) 141 142 numfiles = int(match.group('number')) 143 pos = -1 144 for _ in range(numfiles + 1): 145 pos = self._buffer.find('\n', pos + 1) 146 if pos >= 0: 147 lines = self._buffer[:pos + 1] 148 self._buffer = self._buffer[pos + 1:] 149 term = self._term 150 151 self._stream.write("\n") 152 for name in lines.splitlines()[1:]: 153 name = name.rstrip()[2:] 154 term['path'] = name 155 self._stream.write( 156 "%(BOLD)s=== %(path)s%(NORMAL)s\n" % term 157 ) 158 self._lastname = name 159 160 term['mid'] = e.args[0] 161 self._stream.write( 162 "%(BOLD)s%(YELLOW)s%(mid)s%(NORMAL)s" % term 163 ) 164 self._stream.write(": %s\n" % e.args[1]) 165 self._stream.flush() 166 self.written = True
167
168 - def _parse(self):
169 """ Parse output """ 170 if '\n' not in self._buffer: 171 raise NotFinished() 172 173 line = self._buffer[:self._buffer.find('\n') + 1] 174 self._buffer = self._buffer[len(line):] 175 line = line.rstrip() 176 match = self._LINERE.match(line) 177 if not match: 178 raise NotParseable(line) 179 180 mid = match.group('mid') 181 if mid == 'R0801': 182 self._buffer = "%s\n%s" % (line, self._buffer) 183 raise SpecialMessage(mid, match.group('desc')) 184 185 return match.group('name', 'lineno', 'mid', 'func', 'desc')
186 187
188 -def run(config, *args):
189 """ Run pylint """ 190 try: 191 from pylint import lint 192 from pylint.reporters import text 193 except ImportError: 194 return 2 195 196 if config is None: 197 config = _shell.native('pylint.conf') 198 argv = ['--rcfile', config, 199 '--reports', 'no', 200 '--output-format', 'parseable', 201 '--include-ids', 'yes' 202 ] 203 204 libpath = _shell.native('lib') 205 if libpath != _sys.path[0]: 206 while libpath in _sys.path: 207 _sys.path.remove(libpath) 208 _sys.path.insert(0, libpath) 209 210 stream = FilterStream(_term.terminfo()) 211 212 old_stderr = _sys.stderr 213 try: 214 # pylint: disable = E1101 215 _sys.stderr = stream 216 from pylint import __pkginfo__ 217 if __pkginfo__.numversion < (0, 13): 218 # The lint tool is not very user friendly, so we need a hack here. 219 lint.REPORTER_OPT_MAP['parseable'] = \ 220 lambda: text.TextReporter2(stream) 221 reporter = text.TextReporter2(stream) 222 else: 223 reporter = text.ParseableTextReporter(stream) 224 lint.REPORTER_OPT_MAP['parseable'] = lambda: reporter 225 226 for path in args: 227 try: 228 path = _shell.native(path) 229 try: 230 lint.Run(argv + [path], reporter=reporter) 231 except SystemExit: 232 pass # don't accept the exit. strange errors happen... 233 234 if stream.written: 235 print 236 stream.written = False 237 except KeyboardInterrupt: 238 print 239 raise 240 finally: 241 _sys.stderr = old_stderr 242 243 return 0
244