diff options
-rw-r--r-- | checkers/spelling.py | 150 | ||||
-rw-r--r-- | debian/control | 2 |
2 files changed, 151 insertions, 1 deletions
diff --git a/checkers/spelling.py b/checkers/spelling.py new file mode 100644 index 0000000..ec0a147 --- /dev/null +++ b/checkers/spelling.py @@ -0,0 +1,150 @@ +# Copyright 2014 Michal Nowikowski. +# +# 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., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +"""Checker for spelling errors in comments and docstrings. +""" + +import sys +import tokenize +import string +import re + +import astroid + +from pylint.interfaces import ITokenChecker, IAstroidChecker, IRawChecker +from pylint.checkers import BaseChecker, BaseTokenChecker +from pylint.checkers import utils +from pylint.checkers.utils import check_messages + +try: + import enchant +except ImportError: + enchant = None + +if enchant is not None: + br = enchant.Broker() + dicts = br.list_dicts() + dict_choices = [''] + [d[0] for d in dicts] + dicts = ["%s (%s)" % (d[0], d[1].name) for d in dicts] + dicts = ", ".join(dicts) + instr = "" +else: + dicts = "none" + dict_choices = [''] + instr = " To make it working install python-enchant package." + +table = string.maketrans("", "") + +class SpellingInCommentsChecker(BaseTokenChecker): + """Check spelling in comments""" + __implements__ = (ITokenChecker, IAstroidChecker) + name = 'spelling' + msgs = { + 'C8402': ('Wrong spelling of a word \'%s\' in a comment:\n%s\n%s\nDid you mean: \'%s\'?', + 'wrong-spelling-in-comment', + 'Used when a word in comment is not spelled correctly.'), + 'C8403': ('Wrong spelling of a word \'%s\' in a docstring:\n%s\n%s\nDid you mean: \'%s\'?', + 'wrong-spelling-in-docstring', + 'Used when a word in docstring is not spelled correctly.'), + } + options = (('spelling-dict', + {'default' : '', 'type' : 'choice', 'metavar' : '<dict name>', + 'choices': dict_choices, + 'help' : 'Spelling dictionary name. Available dictionaries: %s.%s' % (dicts, instr)}), + ('spelling-ignore-words', + {'default' : '', 'type' : 'string', 'metavar' : '<comma separated words>', + 'help' : 'List of comma separated words that should not be checked.'}), + ) + + def open(self): + self.initialized = False + + if enchant is None: + return + + dict_name = self.config.spelling_dict + if not dict_name: + return + + self.ignore_list = self.config.spelling_ignore_words.split(",") + self.spelling_dict = enchant.Dict(dict_name) + + puncts = string.punctuation.replace("'", "") + self.regex = re.compile('[%s]' % re.escape(puncts)) + + self.initialized = True + + def process_tokens(self, tokens): + if not self.initialized: + return + + # process tokens and look for comments + for (tok_type, token, (start_row, start_col), _, _) in tokens: + if tok_type == tokenize.COMMENT: + # replace punctuation signs with space: e.g. and/or -> and or + comment = self.regex.sub(' ', token) + + # go through words and check them + for w in comment.split(): + if not w in self.ignore_list and not self.spelling_dict.check(w): + suggestions = self.spelling_dict.suggest(w)[:4] + col = token.index(w) + indicator = (" " * col) + ("^" * len(w)) + self.add_message('wrong-spelling-in-comment', line=start_row, + args=(w, token, indicator, "' or '".join(suggestions))) + + @check_messages('wrong-spelling-in-docstring') + def visit_module(self, node): + if not self.initialized: + return + self._check_docstring(node) + + @check_messages('wrong-spelling-in-docstring') + def visit_class(self, node): + if not self.initialized: + return + self._check_docstring(node) + + @check_messages('wrong-spelling-in-docstring') + def visit_function(self, node): + if not self.initialized: + return + self._check_docstring(node) + + def _check_docstring(self, node): + """check the node has any spelling errors""" + docstring = node.doc + if not docstring: + return + + start_line = node.lineno + 1 + + # go through lines of docstring + for idx, line in enumerate(docstring.splitlines()): + # replace punctuation signs with space: e.g. and/or -> and or + line2 = self.regex.sub(' ', line.strip()) + + # go through words in a line and check them + for w in line2.split(): + if not w in self.ignore_list and not self.spelling_dict.check(w): + suggestions = self.spelling_dict.suggest(w)[:4] + col = line.index(w) + indicator = (" " * col) + ("^" * len(w)) + self.add_message('wrong-spelling-in-docstring', line=start_line + idx, + args=(w, line, indicator, "' or '".join(suggestions))) + + +def register(linter): + """required method to auto register this checker """ + linter.register_checker(SpellingInCommentsChecker(linter)) diff --git a/debian/control b/debian/control index da0c1d1..660eda1 100644 --- a/debian/control +++ b/debian/control @@ -20,7 +20,7 @@ Depends: ${python:Depends}, ${misc:Depends}, python-logilab-common (>= 0.53.0), python-astroid (>= 1.2) -Suggests: python-tk +Suggests: python-tk, python-enchant XB-Python-Version: ${python:Versions} Description: python code static checker and UML diagram generator Pylint is a Python source code analyzer which looks for programming |