[Pydev-cvs] org.python.pydev/PySrc/ThirdParty/logilab/pylint utils.py,NONE,1.1
Brought to you by:
fabioz
From: Fabio Z. <fa...@us...> - 2005-01-21 17:46:30
|
Update of /cvsroot/pydev/org.python.pydev/PySrc/ThirdParty/logilab/pylint In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv8017/PySrc/ThirdParty/logilab/pylint Added Files: utils.py Log Message: pylint updated to 0.6 --- NEW FILE: utils.py --- # Copyright (c) 2002-2005 Sylvain Thenault (sy...@lo...). # Copyright (c) 2002-2005 LOGILAB S.A. (Paris, FRANCE). # http://www.logilab.fr/ -- mailto:co...@lo... # # This program is free software; you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation; either version 2 of the License, or (at your option) any later # version. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details # # You should have received a copy of the GNU General Public License along with # this program; if not, write to the Free Software Foundation, Inc., # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. """some various utilities and helper classes, most of them used in the main pylint class """ __revision__ = "$Id: utils.py,v 1.1 2005/01/21 17:46:21 fabioz Exp $" from logilab.common.astng import Module from logilab.common.textutils import normalize_text from logilab.common.ureports import Section from logilab.pylint.checkers import EmptyReport class UnknownMessage(Exception): """raised when a unregistered message id is encountered""" MSG_TYPES = { 'I' : 'info', 'C' : 'convention', 'R' : 'refactor', 'W' : 'warning', 'E' : 'error', 'F' : 'fatal' } MSG_CATEGORIES = MSG_TYPES.keys() def sort_checkers(checkers, enabled_only=True): """return a list of enabled checker sorted by priority""" if enabled_only: checkers = [(-checker.priority, checker) for checker in checkers if checker.is_enabled()] else: checkers = [(-checker.priority, checker) for checker in checkers] checkers.sort() return [item[1] for item in checkers] def sort_msgs(msg_ids): """sort message identifiers according to their category first""" msg_order = ['I', 'C', 'R', 'W', 'E', 'F'] def cmp_func(msgid1, msgid2): """comparison function for two message identifiers""" if msgid1[0] != msgid2[0]: return cmp(msg_order.index(msgid1[0]), msg_order.index(msgid2[0])) else: return cmp(msgid1, msgid2) msg_ids.sort(cmp_func) return msg_ids def get_module_and_frameid(node): """return the module name and the frame id in the module""" frame = node.get_frame() module, obj = '', [] while frame: if isinstance(frame, Module): module = frame.name else: obj.append(frame.name) try: frame = frame.parent.get_frame() except AttributeError: frame = None obj.reverse() return module, '.'.join(obj) class MessagesHandlerMixIn: """a mix-in class containing all the messages related methods for the main lint class """ def __init__(self): # dictionary of registered messages self._messages = {} self._messages_help = {} self._msgs_state = {} self._module_msgs_state = None self._msg_cats_state = {} self._module_msg_cats_state = None def register_messages(self, checker): """register a dictionary of messages Keys are message ids, values are a 2-uple with the message type and the message itself message ids should be a string of len 4, where the to first characters are the checker id and the two last the message id in this checker """ msgs_dict = checker.msgs chk_id = None for msg_id, (msg, msg_help) in msgs_dict.items(): # avoid duplicate / malformed ids assert not self._messages.has_key(msg_id), \ 'Message id %r is already defined' % msg_id assert len(msg_id) == 5, 'Invalid message id %s' % msg_id assert chk_id is None or chk_id == msg_id[1:3], \ 'Inconsistent checker part in message id %r' %msg_id assert msg_id[0] in MSG_CATEGORIES, \ 'Bad message type %s in %r' % (msg_id[0], msg_id) chk_id = msg_id[1:3] if checker is not None: add = ' This message belongs to the %s checker.' % checker.name msg_help += add self._messages_help[msg_id] = msg_help self._messages[msg_id] = msg def get_message_help(self, msg_id): """return the help string for the given message id""" msg_id = self.check_message_id(msg_id) msg = self._messages_help[msg_id] msg = normalize_text(' '.join(msg.split()), indent=' ') return '%s:\n%s' % (msg_id, msg) def disable_message(self, msg_id, scope='package', line=None): """don't output message of the given id""" assert scope in ('package', 'module') msg_id = self.check_message_id(msg_id) if scope == 'module': self.add_message('I0011', line=line, args=msg_id) self._module_msgs_state[msg_id] = False else: msgs = self._msgs_state msgs[msg_id] = False # sync configuration object self.config.disable_msg = [mid for mid, val in msgs.items() if not val] def enable_message(self, msg_id, scope='package', line=None): """reenable message of the given id""" assert scope in ('package', 'module') msg_id = self.check_message_id(msg_id) if scope == 'module': self.add_message('I0012', line=line, args=msg_id) self._module_msgs_state[msg_id] = True else: msgs = self._msgs_state msgs[msg_id] = True # sync configuration object self.config.enable_msg = [mid for mid, val in msgs.items() if val] def disable_message_category(self, msg_cat_id, scope='package', line=None): """don't output message in the given category""" assert scope in ('package', 'module') msg_cat_id = msg_cat_id[0].upper() if scope == 'module': self.add_message('I0011', line=line, args=msg_cat_id) self._module_msg_cats_state[msg_cat_id] = False else: self._msg_cats_state[msg_cat_id] = False def enable_message_category(self, msg_cat_id, scope='package', line=None): """reenable message of the given category""" assert scope in ('package', 'module') msg_cat_id = msg_cat_id[0].upper() if scope == 'module': self.add_message('I0012', line=line, args=msg_cat_id) self._module_msg_cats_state[msg_cat_id] = True else: self._msg_cats_state[msg_cat_id] = True def check_message_id(self, msg_id): """raise UnknownMessage if the message id is not defined""" msg_id = msg_id.upper() if not self._messages.has_key(msg_id): raise UnknownMessage('No such message id %s' % msg_id) return msg_id def is_message_enabled(self, msg_id): """return true if the message associated to the given message id is enabled """ try: if not self._module_msg_cats_state[msg_id[0]]: return False except KeyError: if not self._msg_cats_state.get(msg_id[0], True): return False try: return self._module_msgs_state[msg_id] except KeyError: return self._msgs_state.get(msg_id, True) def add_message(self, msg_id, line=None, node=None, args=None): """add the message corresponding to the given id. If provided, msg is expanded using args astng checkers should provide the node argument, raw checkers should provide the line argument. """ # should this message be displayed if not self.is_message_enabled(msg_id): return # update stats msg_cat = MSG_TYPES[msg_id[0]] self.stats[msg_cat] += 1 self.stats['by_module'][self.current_name][msg_cat] += 1 try: self.stats['by_msg'][msg_id] += 1 except KeyError: self.stats['by_msg'][msg_id] = 1 msg = self._messages[msg_id] # expand message ? if args: msg %= args if line is None and node is not None: line = node.lineno or node.get_statement().lineno #if not isinstance(node, Module): # assert line > 0, node.__class__ # get module and object if node is None: module, obj = self.current_name, '' path = self.current_file else: module, obj = get_module_and_frameid(node) path = node.root().file # add the message self.reporter.add_message(msg_id, (path, module, obj, line or 0), msg) def help_message(self, msgids): """display help messages for the given message identifiers""" for msg_id in msgids: try: print self.get_message_help(msg_id) print except UnknownMessage, ex: print ex print continue def list_messages(self): """list available messages""" for checker in sort_checkers(self._checkers.keys()): print checker.name.capitalize() print '-' * len(checker.name) print print 'Description' print '~~~~~~~~~~~' print checker.__doc__ if not checker.msgs: continue print 'Messages' print '~~~~~~~~' for msg_id in sort_msgs(checker.msgs.keys()): print self.get_message_help(msg_id) print print print class ReportsHandlerMixIn: """a mix-in class containing all the reports and stats manipulation related methods for the main lint class """ def __init__(self): self._reports = {} self._reports_state = {} def register_report(self, r_id, r_title, r_cb, checker): """register a report r_id is the unique identifier for the report r_title the report's title r_cb the method to call to make the report checker is the checker defining the report """ r_id = r_id.upper() self._reports.setdefault(checker, []).append( (r_id, r_title, r_cb) ) def enable_report(self, r_id): """disable the report of the given id""" r_id = r_id.upper() self._reports_state[r_id] = True def disable_report(self, r_id): """disable the report of the given id""" r_id = r_id.upper() self._reports_state[r_id] = False def is_report_enabled(self, r_id): """return true if the report associated to the given identifier is enabled """ return self._reports_state.get(r_id, True) def make_reports(self, stats, old_stats): """render registered reports""" if self.config.files_output: filename = 'pylint_global.' + self.reporter.extension self.reporter.set_output(open(filename, 'w')) sect = Section('Report', '%s statements analysed.'% (self.stats['statement'])) checkers = sort_checkers(self._reports.keys()) checkers.reverse() for checker in checkers: for r_id, r_title, r_cb in self._reports[checker]: if not self.is_report_enabled(r_id): continue report_sect = Section(r_title) try: r_cb(report_sect, stats, old_stats) except EmptyReport: continue report_sect.report_id = r_id sect.append(report_sect) self.reporter.display_results(sect) def add_stats(self, **kwargs): """add some stats entries to the statistic dictionary raise an AssertionError if there is a key conflict """ for key, value in kwargs.items(): if key[-1] == '_': key = key[:-1] assert not self.stats.has_key(key) self.stats[key] = value return self.stats |