Optimized the PEP-8 naming checker (Python2 variant).

Sat, 14 Sep 2013 17:11:41 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sat, 14 Sep 2013 17:11:41 +0200
changeset 2913
4e395efc0ef9
parent 2912
9ff696796092
child 2914
6b30a602e404

Optimized the PEP-8 naming checker (Python2 variant).

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.UtilitiesPython2.Pep8NamingCheckerPy2.html file | annotate | diff | comparison | revisions
UtilitiesPython2/Pep8NamingCheckerPy2.py file | annotate | diff | comparison | revisions
UtilitiesPython2/pep8.py file | annotate | diff | comparison | revisions
--- a/APIs/Python3/eric5.api	Sat Sep 14 13:29:32 2013 +0200
+++ b/APIs/Python3/eric5.api	Sat Sep 14 17:11:41 2013 +0200
@@ -8391,7 +8391,7 @@
 eric5.UtilitiesPython2.Pep8NamingCheckerPy2.Pep8NamingChecker.UppercaseRegexp?7
 eric5.UtilitiesPython2.Pep8NamingCheckerPy2.Pep8NamingChecker.run?4()
 eric5.UtilitiesPython2.Pep8NamingCheckerPy2.Pep8NamingChecker.unpackArgs?4()
-eric5.UtilitiesPython2.Pep8NamingCheckerPy2.Pep8NamingChecker?1(tree, filename)
+eric5.UtilitiesPython2.Pep8NamingCheckerPy2.Pep8NamingChecker?1(tree, filename, options)
 eric5.UtilitiesPython2.Py2SyntaxChecker.compile?4(file, codestring)
 eric5.UtilitiesPython2.Py2SyntaxChecker.flakesCheck?4(fileName, codestring, ignoreStarImportWarnings)
 eric5.UtilitiesPython2.Tabnanny.NannyNag.get_line?4()
--- a/APIs/Python3/eric5.bas	Sat Sep 14 13:29:32 2013 +0200
+++ b/APIs/Python3/eric5.bas	Sat Sep 14 17:11:41 2013 +0200
@@ -63,7 +63,7 @@
 ChangeBookmarkCommand QUndoCommand
 ChatWidget QWidget Ui_ChatWidget
 ChromeImporter BookmarksImporter
-Class ClbrBase
+Class ClbrBaseClasses.Class VisibilityMixin
 ClassItem UMLItem
 ClassModel UMLModel
 ClassScope Scope
Binary file Documentation/Help/source.qch has changed
--- a/Documentation/Help/source.qhp	Sat Sep 14 13:29:32 2013 +0200
+++ b/Documentation/Help/source.qhp	Sat Sep 14 17:11:41 2013 +0200
@@ -8087,6 +8087,7 @@
       <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.__checkNameToBeAvoided" id="Pep8NamingChecker.__checkNameToBeAvoided" ref="eric5.UtilitiesPython2.Pep8NamingCheckerPy2.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.UtilitiesPython2.Pep8NamingCheckerPy2.html	Sat Sep 14 13:29:32 2013 +0200
+++ b/Documentation/Source/eric5.UtilitiesPython2.Pep8NamingCheckerPy2.html	Sat Sep 14 17:11:41 2013 +0200
@@ -58,16 +58,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>
@@ -75,8 +75,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>
@@ -112,9 +115,9 @@
 </table>
 <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>
@@ -122,13 +125,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.
@@ -148,7 +154,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
@@ -169,7 +175,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
@@ -222,11 +228,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/UtilitiesPython2/Pep8NamingCheckerPy2.py	Sat Sep 14 13:29:32 2013 +0200
+++ b/UtilitiesPython2/Pep8NamingCheckerPy2.py	Sat Sep 14 17:11:41 2013 +0200
@@ -27,26 +27,49 @@
         "N811", "N812", "N813", "N814", "N821", "N831"
     ]
     
-    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):
         """
@@ -207,10 +230,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.
@@ -219,17 +273,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
@@ -243,10 +293,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")
@@ -254,7 +300,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
@@ -294,17 +340,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.
         
@@ -324,10 +366,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/UtilitiesPython2/pep8.py	Sat Sep 14 13:29:32 2013 +0200
+++ b/UtilitiesPython2/pep8.py	Sat Sep 14 17:11:41 2013 +0200
@@ -1220,6 +1220,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]
@@ -1352,7 +1355,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 result in checker.run():
                 lineno, offset, code, check = result[:4]
                 args = result[4:]

eric ide

mercurial