Optimized the PEP-8 naming checker.

Fri, 13 Sep 2013 18:49:26 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Fri, 13 Sep 2013 18:49:26 +0200
changeset 2910
cdc56e9d9f12
parent 2909
c3fb85fe41f9
child 2912
9ff696796092

Optimized the PEP-8 naming checker.

APIs/Python3/eric5.api file | annotate | diff | comparison | revisions
APIs/Python3/eric5.bas file | annotate | diff | comparison | revisions
Documentation/Help/source.qch file | annotate | diff | comparison | revisions
Documentation/Help/source.qhp file | annotate | diff | comparison | revisions
Documentation/Source/eric5.Plugins.CheckerPlugins.Pep8.Pep8NamingChecker.html file | annotate | diff | comparison | revisions
Plugins/CheckerPlugins/Pep8/Pep8NamingChecker.py file | annotate | diff | comparison | revisions
Plugins/CheckerPlugins/Pep8/pep8.py file | annotate | diff | comparison | revisions
--- a/APIs/Python3/eric5.api	Fri Sep 13 18:38:34 2013 +0200
+++ b/APIs/Python3/eric5.api	Fri Sep 13 18:49:26 2013 +0200
@@ -3767,7 +3767,7 @@
 eric5.Plugins.CheckerPlugins.Pep8.Pep8NamingChecker.Pep8NamingChecker.UppercaseRegexp?7
 eric5.Plugins.CheckerPlugins.Pep8.Pep8NamingChecker.Pep8NamingChecker.getMessage?4(code, *args)
 eric5.Plugins.CheckerPlugins.Pep8.Pep8NamingChecker.Pep8NamingChecker.run?4()
-eric5.Plugins.CheckerPlugins.Pep8.Pep8NamingChecker.Pep8NamingChecker?1(tree, filename)
+eric5.Plugins.CheckerPlugins.Pep8.Pep8NamingChecker.Pep8NamingChecker?1(tree, filename, options)
 eric5.Plugins.CheckerPlugins.Pep8.Pep8StatisticsDialog.Pep8StatisticsDialog?1(statistics, parent=None)
 eric5.Plugins.CheckerPlugins.Pep8.pep8.ARITHMETIC_OP?7
 eric5.Plugins.CheckerPlugins.Pep8.pep8.BENCHMARK_KEYS?7
--- a/APIs/Python3/eric5.bas	Fri Sep 13 18:38:34 2013 +0200
+++ b/APIs/Python3/eric5.bas	Fri Sep 13 18:49:26 2013 +0200
@@ -63,7 +63,7 @@
 ChangeBookmarkCommand QUndoCommand
 ChatWidget QWidget Ui_ChatWidget
 ChromeImporter BookmarksImporter
-Class ClbrBaseClasses.Class VisibilityMixin
+Class ClbrBase
 ClassItem UMLItem
 ClassModel UMLModel
 ClassScope Scope
Binary file Documentation/Help/source.qch has changed
--- a/Documentation/Help/source.qhp	Fri Sep 13 18:38:34 2013 +0200
+++ b/Documentation/Help/source.qhp	Fri Sep 13 18:49:26 2013 +0200
@@ -8086,6 +8086,7 @@
       <keyword name="Pep8NamingChecker.__checkImportAs" id="Pep8NamingChecker.__checkImportAs" ref="eric5.UtilitiesPython2.Pep8NamingCheckerPy2.html#Pep8NamingChecker.__checkImportAs" />
       <keyword name="Pep8NamingChecker.__checkModule" id="Pep8NamingChecker.__checkModule" ref="eric5.Plugins.CheckerPlugins.Pep8.Pep8NamingChecker.html#Pep8NamingChecker.__checkModule" />
       <keyword name="Pep8NamingChecker.__checkModule" id="Pep8NamingChecker.__checkModule" ref="eric5.UtilitiesPython2.Pep8NamingCheckerPy2.html#Pep8NamingChecker.__checkModule" />
+      <keyword name="Pep8NamingChecker.__checkNameToBeAvoided" id="Pep8NamingChecker.__checkNameToBeAvoided" ref="eric5.Plugins.CheckerPlugins.Pep8.Pep8NamingChecker.html#Pep8NamingChecker.__checkNameToBeAvoided" />
       <keyword name="Pep8NamingChecker.__checkVariablesInFunction" id="Pep8NamingChecker.__checkVariablesInFunction" ref="eric5.Plugins.CheckerPlugins.Pep8.Pep8NamingChecker.html#Pep8NamingChecker.__checkVariablesInFunction" />
       <keyword name="Pep8NamingChecker.__checkVariablesInFunction" id="Pep8NamingChecker.__checkVariablesInFunction" ref="eric5.UtilitiesPython2.Pep8NamingCheckerPy2.html#Pep8NamingChecker.__checkVariablesInFunction" />
       <keyword name="Pep8NamingChecker.__error" id="Pep8NamingChecker.__error" ref="eric5.Plugins.CheckerPlugins.Pep8.Pep8NamingChecker.html#Pep8NamingChecker.__error" />
--- a/Documentation/Source/eric5.Plugins.CheckerPlugins.Pep8.Pep8NamingChecker.html	Fri Sep 13 18:38:34 2013 +0200
+++ b/Documentation/Source/eric5.Plugins.CheckerPlugins.Pep8.Pep8NamingChecker.html	Fri Sep 13 18:49:26 2013 +0200
@@ -61,16 +61,16 @@
 <table>
 <tr>
 <td><a href="#Pep8NamingChecker.__init__">Pep8NamingChecker</a></td>
-<td>Constructor (according to pep8.py API)</td>
+<td>Constructor (according to 'extended' pep8.py API)</td>
 </tr><tr>
 <td><a href="#Pep8NamingChecker.__checkClassName">__checkClassName</a></td>
-<td>Private class to check the given node for class name conventions (N801, N831).</td>
+<td>Private class to check the given node for class name conventions (N801).</td>
 </tr><tr>
 <td><a href="#Pep8NamingChecker.__checkFunctionArgumentNames">__checkFunctionArgumentNames</a></td>
-<td>Private class to check the argument names of functions (N803, N804, N805, N806, N831).</td>
+<td>Private class to check the argument names of functions (N803, N804, N805, N806).</td>
 </tr><tr>
 <td><a href="#Pep8NamingChecker.__checkFuntionName">__checkFuntionName</a></td>
-<td>Private class to check the given node for function name conventions (N802, N831).</td>
+<td>Private class to check the given node for function name conventions (N802).</td>
 </tr><tr>
 <td><a href="#Pep8NamingChecker.__checkImportAs">__checkImportAs</a></td>
 <td>Private method to check that imports don't change the naming convention (N811, N812, N813, N814).</td>
@@ -78,8 +78,11 @@
 <td><a href="#Pep8NamingChecker.__checkModule">__checkModule</a></td>
 <td>Private method to check module naming conventions (N807, N808).</td>
 </tr><tr>
+<td><a href="#Pep8NamingChecker.__checkNameToBeAvoided">__checkNameToBeAvoided</a></td>
+<td>Private class to check the given node for a name to be avoided (N831).</td>
+</tr><tr>
 <td><a href="#Pep8NamingChecker.__checkVariablesInFunction">__checkVariablesInFunction</a></td>
-<td>Private method to check local variables in functions (N821, N831).</td>
+<td>Private method to check local variables in functions (N821).</td>
 </tr><tr>
 <td><a href="#Pep8NamingChecker.__error">__error</a></td>
 <td>Private method to build the error information</td>
@@ -131,9 +134,9 @@
 </dd>
 </dl><a NAME="Pep8NamingChecker.__init__" ID="Pep8NamingChecker.__init__"></a>
 <h4>Pep8NamingChecker (Constructor)</h4>
-<b>Pep8NamingChecker</b>(<i>tree, filename</i>)
+<b>Pep8NamingChecker</b>(<i>tree, filename, options</i>)
 <p>
-        Constructor (according to pep8.py API)
+        Constructor (according to 'extended' pep8.py API)
 </p><dl>
 <dt><i>tree</i></dt>
 <dd>
@@ -141,13 +144,16 @@
 </dd><dt><i>filename</i></dt>
 <dd>
 name of the source file (string)
+</dd><dt><i>options</i></dt>
+<dd>
+options as parsed by pep8.StyleGuide
 </dd>
 </dl><a NAME="Pep8NamingChecker.__checkClassName" ID="Pep8NamingChecker.__checkClassName"></a>
 <h4>Pep8NamingChecker.__checkClassName</h4>
 <b>__checkClassName</b>(<i>node, parents</i>)
 <p>
         Private class to check the given node for class name
-        conventions (N801, N831).
+        conventions (N801).
 </p><p>
         Almost without exception, class names use the CapWords convention.
         Classes for internal use have a leading underscore in addition.
@@ -167,7 +173,7 @@
 <b>__checkFunctionArgumentNames</b>(<i>node, parents</i>)
 <p>
         Private class to check the argument names of functions
-        (N803, N804, N805, N806, N831).
+        (N803, N804, N805, N806).
 </p><p>
         The argument names of a function should be lowercase, with words
         separated by underscores. A class method should have 'cls' as the
@@ -188,7 +194,7 @@
 <b>__checkFuntionName</b>(<i>node, parents</i>)
 <p>
         Private class to check the given node for function name
-        conventions (N802, N831).
+        conventions (N802).
 </p><p>
         Function names should be lowercase, with words separated by underscores
         as necessary to improve readability. Functions <b>not</b> being
@@ -241,11 +247,27 @@
 tuple giving line number, offset within line and error code
             (integer, integer, string)
 </dd>
+</dl><a NAME="Pep8NamingChecker.__checkNameToBeAvoided" ID="Pep8NamingChecker.__checkNameToBeAvoided"></a>
+<h4>Pep8NamingChecker.__checkNameToBeAvoided</h4>
+<b>__checkNameToBeAvoided</b>(<i>node, parents</i>)
+<p>
+        Private class to check the given node for a name to be avoided (N831).
+</p><dl>
+<dt><i>node</i></dt>
+<dd>
+AST note to check
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+tuple giving line number, offset within line and error code
+            (integer, integer, string)
+</dd>
 </dl><a NAME="Pep8NamingChecker.__checkVariablesInFunction" ID="Pep8NamingChecker.__checkVariablesInFunction"></a>
 <h4>Pep8NamingChecker.__checkVariablesInFunction</h4>
 <b>__checkVariablesInFunction</b>(<i>node, parents</i>)
 <p>
-        Private method to check local variables in functions (N821, N831).
+        Private method to check local variables in functions (N821).
 </p><p>
         Local variables in functions should be lowercase.
 </p><dl>
--- a/Plugins/CheckerPlugins/Pep8/Pep8NamingChecker.py	Fri Sep 13 18:38:34 2013 +0200
+++ b/Plugins/CheckerPlugins/Pep8/Pep8NamingChecker.py	Fri Sep 13 18:49:26 2013 +0200
@@ -60,26 +60,49 @@
             "names 'l', 'O' and 'I' should be avoided"),
     }
     
-    def __init__(self, tree, filename):
+    def __init__(self, tree, filename, options):
         """
-        Constructor (according to pep8.py API)
+        Constructor (according to 'extended' pep8.py API)
         
         @param tree AST tree of the source file
         @param filename name of the source file (string)
+        @param options options as parsed by pep8.StyleGuide
         """
         self.__parents = collections.deque()
         self.__tree = tree
         self.__filename = filename
         
-        self.__checkers = {
-            "classdef": [self.__checkClassName],
-            "functiondef": [self.__checkFuntionName,
-                self.__checkFunctionArgumentNames,
-                            ],
-            "assign": [self.__checkVariablesInFunction],
-            "importfrom": [self.__checkImportAs],
-            "module": [self.__checkModule],
+        self.__checkersWithCodes = {
+            "classdef": [
+                (self.__checkClassName, ("N801",)),
+                (self.__checkNameToBeAvoided, ("N831",)),
+            ],
+            "functiondef": [
+                (self.__checkFuntionName, ("N802",)),
+                (self.__checkFunctionArgumentNames,
+                    ("N803", "N804", "N805", "N806")),
+                (self.__checkNameToBeAvoided, ("N831",)),
+            ],
+            "assign": [
+                (self.__checkVariablesInFunction, ("N821",)),
+                (self.__checkNameToBeAvoided, ("N831",)),
+            ],
+            "importfrom": [
+                (self.__checkImportAs, ("N811", "N812", "N813", "N814")),
+            ],
+            "module": [
+                (self.__checkModule, ("N807", "N808")),
+            ],
         }
+        
+        self.__checkers = {}
+        for key, checkers in self.__checkersWithCodes.items():
+            for checker, codes in checkers:
+                if any(not (code and options.ignore_code(code))
+                        for code in codes):
+                    if key not in self.__checkers:
+                        self.__checkers[key] = []
+                    self.__checkers[key].append(checker)
 
     def run(self):
         """
@@ -244,10 +267,41 @@
         """
         return name in ("l", "O", "I")
     
+    def __checkNameToBeAvoided(self, node, parents):
+        """
+        Private class to check the given node for a name to be avoided (N831).
+        
+        @param node AST note to check
+        @return tuple giving line number, offset within line and error code
+            (integer, integer, string)
+        """
+        if isinstance(node, (ast.ClassDef, ast.FunctionDef)):
+            name = node.name
+            if self.__isNameToBeAvoided(name):
+                yield self.__error(node, "N831")
+                return
+        
+        if isinstance(node, ast.FunctionDef):
+            argNames = self.__getArgNames(node)
+            for arg in argNames:
+                if self.__isNameToBeAvoided(arg):
+                    yield self.__error(node, "N831")
+                    return
+        
+        if isinstance(node, ast.Assign):
+            for target in node.targets:
+                name = isinstance(target, ast.Name) and target.id
+                if not name:
+                    return
+                
+                if self.__isNameToBeAvoided(name):
+                    yield self.__error(node, "N831")
+                    return
+    
     def __checkClassName(self, node, parents):
         """
         Private class to check the given node for class name
-        conventions (N801, N831).
+        conventions (N801).
         
         Almost without exception, class names use the CapWords convention.
         Classes for internal use have a leading underscore in addition.
@@ -256,17 +310,13 @@
         @return tuple giving line number, offset within line and error code
             (integer, integer, string)
         """
-        if self.__isNameToBeAvoided(node.name):
-            yield self.__error(node, "N831")
-            return
-
         if not self.CamelcaseRegexp.match(node.name):
             yield self.__error(node, "N801")
     
     def __checkFuntionName(self, node, parents):
         """
         Private class to check the given node for function name
-        conventions (N802, N831).
+        conventions (N802).
         
         Function names should be lowercase, with words separated by underscores
         as necessary to improve readability. Functions <b>not</b> being
@@ -280,10 +330,6 @@
         """
         functionType = getattr(node, "function_type", "function")
         name = node.name
-        if self.__isNameToBeAvoided(name):
-            yield self.__error(node, "N831")
-            return
-
         if (functionType == "function" and "__" in (name[:2], name[-2:])) or \
                 not self.LowercaseRegex.match(name):
             yield self.__error(node, "N802")
@@ -291,7 +337,7 @@
     def __checkFunctionArgumentNames(self, node, parents):
         """
         Private class to check the argument names of functions
-        (N803, N804, N805, N806, N831).
+        (N803, N804, N805, N806).
         
         The argument names of a function should be lowercase, with words
         separated by underscores. A class method should have 'cls' as the
@@ -331,17 +377,13 @@
             if argNames[0] in ("cls", "self"):
                 yield self.__error(node, "N806")
         for arg in argNames:
-            if self.__isNameToBeAvoided(arg):
-                yield self.__error(node, "N831")
-                return
-
             if not self.LowercaseRegex.match(arg):
                 yield self.__error(node, "N803")
                 return
     
     def __checkVariablesInFunction(self, node, parents):
         """
-        Private method to check local variables in functions (N821, N831).
+        Private method to check local variables in functions (N821).
         
         Local variables in functions should be lowercase.
         
@@ -361,10 +403,6 @@
             if not name or name in parentFunc.global_names:
                 return
             
-            if self.__isNameToBeAvoided(name):
-                yield self.__error(node, "N831")
-                return
-
             if not self.LowercaseRegex.match(name) and name[:1] != '_':
                 yield self.__error(target, "N821")
     
--- a/Plugins/CheckerPlugins/Pep8/pep8.py	Fri Sep 13 18:38:34 2013 +0200
+++ b/Plugins/CheckerPlugins/Pep8/pep8.py	Fri Sep 13 18:49:26 2013 +0200
@@ -1378,6 +1378,9 @@
         self.report = report or options.report
         self.report_error = self.report.error
         self.report_error_args = self.report.error_args
+        
+        # added for eric5 integration
+        self.options = options
 
     def report_invalid_syntax(self):
         exc_type, exc = sys.exc_info()[:2]
@@ -1508,7 +1511,8 @@
         except (SyntaxError, TypeError):
             return self.report_invalid_syntax()
         for name, cls, _ in self._ast_checks:
-            checker = cls(tree, self.filename)
+            # extended API for eric5 integration
+            checker = cls(tree, self.filename, self.options)
             for lineno, offset, code, check, *args in checker.run():
                 if not noqa(self.lines[lineno - 1]):
                     self.report_error_args(lineno, offset, code, check, *args)

eric ide

mercurial