Upgraded embedded Radon library to version 4.5.0.

Sun, 25 Apr 2021 16:35:17 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sun, 25 Apr 2021 16:35:17 +0200
changeset 76
5523ecb9d763
parent 75
e7ed383ac6a7
child 77
7e1793d03381

Upgraded embedded Radon library to version 4.5.0.

ChangeLog file | annotate | diff | comparison | revisions
PluginMetricsRadon.epj file | annotate | diff | comparison | revisions
RadonMetrics/radon/__init__.py file | annotate | diff | comparison | revisions
RadonMetrics/radon/complexity.py file | annotate | diff | comparison | revisions
RadonMetrics/radon/metrics.py file | annotate | diff | comparison | revisions
RadonMetrics/radon/raw.py file | annotate | diff | comparison | revisions
RadonMetrics/radon/visitors.py file | annotate | diff | comparison | revisions
--- a/ChangeLog	Wed Dec 30 11:02:04 2020 +0100
+++ b/ChangeLog	Sun Apr 25 16:35:17 2021 +0200
@@ -1,5 +1,8 @@
 ChangeLog
 ---------
+Version 3.1.0:
+- upgraded embedded Radon library to version 4.5.0
+
 Version 3.0.2:
 - bug fixes
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PluginMetricsRadon.epj	Sun Apr 25 16:35:17 2021 +0200
@@ -0,0 +1,250 @@
+{
+  "header": {
+    "comment": "eric project file for project PluginMetricsRadon",
+    "copyright": "Copyright (C) 2021 Detlev Offenbach, detlev@die-offenbachs.de"
+  },
+  "project": {
+    "AUTHOR": "Detlev Offenbach",
+    "CHECKERSPARMS": {
+      "Pep8Checker": {
+        "AnnotationsChecker": {
+          "MaximumComplexity": 3,
+          "MinimumCoverage": 75
+        },
+        "BlankLines": [
+          2,
+          1
+        ],
+        "BuiltinsChecker": {
+          "bytes": [
+            "unicode"
+          ],
+          "chr": [
+            "unichr"
+          ],
+          "str": [
+            "unicode"
+          ]
+        },
+        "CommentedCodeChecker": {
+          "Aggressive": false
+        },
+        "CopyrightAuthor": "",
+        "CopyrightMinFileSize": 0,
+        "DocstringType": "eric",
+        "EnabledCheckerCategories": "C, D, E, M, N, S, W",
+        "ExcludeFiles": "*/Ui_*.py, */*_rc.py,*/radon/*",
+        "ExcludeMessages": "C101,E265,E266,E305,E402,M811,N802,N803,N807,N808,N821,W293,M201,W504",
+        "FixCodes": "",
+        "FixIssues": false,
+        "FutureChecker": "",
+        "HangClosing": false,
+        "IncludeMessages": "",
+        "LineComplexity": 20,
+        "LineComplexityScore": 10,
+        "MaxCodeComplexity": 10,
+        "MaxDocLineLength": 79,
+        "MaxLineLength": 79,
+        "NoFixCodes": "E501",
+        "RepeatMessages": true,
+        "SecurityChecker": {
+          "CheckTypedException": false,
+          "HardcodedTmpDirectories": [
+            "/tmp",
+            "/var/tmp",
+            "/dev/shm",
+            "~/tmp"
+          ],
+          "InsecureHashes": [
+            "md4",
+            "md5",
+            "sha",
+            "sha1"
+          ],
+          "InsecureSslProtocolVersions": [
+            "PROTOCOL_SSLv2",
+            "SSLv2_METHOD",
+            "SSLv23_METHOD",
+            "PROTOCOL_SSLv3",
+            "PROTOCOL_TLSv1",
+            "SSLv3_METHOD",
+            "TLSv1_METHOD"
+          ],
+          "WeakKeySizeDsaHigh": "1024",
+          "WeakKeySizeDsaMedium": "2048",
+          "WeakKeySizeEcHigh": "160",
+          "WeakKeySizeEcMedium": "224",
+          "WeakKeySizeRsaHigh": "1024",
+          "WeakKeySizeRsaMedium": "2048"
+        },
+        "ShowIgnored": false,
+        "ValidEncodings": "latin-1, utf-8"
+      }
+    },
+    "DESCRIPTION": "This plugin implements dialogs for various code metrics determined using the radon library.",
+    "DOCSTRING": "",
+    "DOCUMENTATIONPARMS": {
+      "ERIC4DOC": {
+        "cssFile": "%PYTHON%/eric6/CSSs/default.css",
+        "ignoreDirectories": [
+          ".hg",
+          ".ropeproject",
+          "_ropeproject",
+          ".eric6project",
+          "_eric6project",
+          "radon"
+        ],
+        "ignoreFilePatterns": [
+          "Ui_*.py"
+        ],
+        "outputDirectory": "RadonMetrics/Documentation/source",
+        "qtHelpEnabled": false,
+        "useRecursion": true
+      }
+    },
+    "EMAIL": "detlev@die-offenbachs.de",
+    "EOL": 1,
+    "FILETYPES": {
+      "*.idl": "INTERFACES",
+      "*.py": "SOURCES",
+      "*.py3": "SOURCES",
+      "*.pyw": "SOURCES",
+      "*.pyw3": "SOURCES",
+      "*.qm": "TRANSLATIONS",
+      "*.qrc": "RESOURCES",
+      "*.ts": "TRANSLATIONS",
+      "*.ui": "FORMS",
+      "Ui_*.py": "__IGNORE__"
+    },
+    "FORMS": [
+      "RadonMetrics/CyclomaticComplexityDialog.ui",
+      "RadonMetrics/MaintainabilityIndexDialog.ui",
+      "RadonMetrics/RawMetricsDialog.ui"
+    ],
+    "HASH": "662232fb888fb1b426cf967a2c238f4dd2f58f08",
+    "IDLPARAMS": {
+      "DefinedNames": [],
+      "IncludeDirs": [],
+      "UndefinedNames": []
+    },
+    "INTERFACES": [],
+    "LEXERASSOCS": {},
+    "MAINSCRIPT": "PluginMetricsRadon.py",
+    "MAKEPARAMS": {
+      "MakeEnabled": false,
+      "MakeExecutable": "",
+      "MakeFile": "",
+      "MakeParameters": "",
+      "MakeTarget": "",
+      "MakeTestOnly": true
+    },
+    "MIXEDLANGUAGE": false,
+    "OTHERS": [
+      ".hgignore",
+      "ChangeLog",
+      "PKGLIST",
+      "PluginMetricsRadon.e4p",
+      "PluginMetricsRadon.zip",
+      "RadonMetrics/Documentation/LICENSE.GPL3",
+      "RadonMetrics/Documentation/source",
+      "RadonMetrics/radon/LICENSE",
+      "PluginMetricsRadon.epj"
+    ],
+    "OTHERTOOLSPARMS": {
+      "RadonCodeMetrics": {
+        "ExcludeFiles": "*/radon/*",
+        "MinimumRank": "C"
+      }
+    },
+    "PACKAGERSPARMS": {},
+    "PROGLANGUAGE": "Python3",
+    "PROJECTTYPE": "E6Plugin",
+    "PROJECTTYPESPECIFICDATA": {},
+    "PROTOCOLS": [],
+    "RCCPARAMS": {
+      "CompressLevel": 0,
+      "CompressionDisable": false,
+      "CompressionThreshold": 70,
+      "PathPrefix": ""
+    },
+    "RESOURCES": [],
+    "SOURCES": [
+      "PluginMetricsRadon.py",
+      "RadonMetrics/CodeMetricsCalculator.py",
+      "RadonMetrics/CyclomaticComplexityCalculator.py",
+      "RadonMetrics/CyclomaticComplexityDialog.py",
+      "RadonMetrics/MaintainabilityIndexCalculator.py",
+      "RadonMetrics/MaintainabilityIndexDialog.py",
+      "RadonMetrics/RawMetricsDialog.py",
+      "RadonMetrics/__init__.py",
+      "RadonMetrics/radon/__init__.py",
+      "RadonMetrics/radon/complexity.py",
+      "RadonMetrics/radon/metrics.py",
+      "RadonMetrics/radon/raw.py",
+      "RadonMetrics/radon/visitors.py",
+      "__init__.py"
+    ],
+    "SPELLEXCLUDES": "",
+    "SPELLLANGUAGE": "en_US",
+    "SPELLWORDS": "",
+    "TRANSLATIONEXCEPTIONS": [],
+    "TRANSLATIONPATTERN": "RadonMetrics/i18n/radon_%language%.ts",
+    "TRANSLATIONS": [
+      "RadonMetrics/i18n/radon_de.qm",
+      "RadonMetrics/i18n/radon_de.ts",
+      "RadonMetrics/i18n/radon_en.qm",
+      "RadonMetrics/i18n/radon_en.ts",
+      "RadonMetrics/i18n/radon_es.qm",
+      "RadonMetrics/i18n/radon_es.ts",
+      "RadonMetrics/i18n/radon_ru.qm",
+      "RadonMetrics/i18n/radon_ru.ts"
+    ],
+    "TRANSLATIONSBINPATH": "",
+    "UICPARAMS": {
+      "Package": "",
+      "PackagesRoot": "",
+      "RcSuffix": ""
+    },
+    "VCS": "Mercurial",
+    "VCSOPTIONS": {
+      "add": [
+        ""
+      ],
+      "checkout": [
+        ""
+      ],
+      "commit": [
+        ""
+      ],
+      "diff": [
+        ""
+      ],
+      "export": [
+        ""
+      ],
+      "global": [
+        ""
+      ],
+      "history": [
+        ""
+      ],
+      "log": [
+        ""
+      ],
+      "remove": [
+        ""
+      ],
+      "status": [
+        ""
+      ],
+      "tag": [
+        ""
+      ],
+      "update": [
+        ""
+      ]
+    },
+    "VCSOTHERDATA": {},
+    "VERSION": "0.x"
+  }
+}
\ No newline at end of file
--- a/RadonMetrics/radon/__init__.py	Wed Dec 30 11:02:04 2020 +0100
+++ b/RadonMetrics/radon/__init__.py	Sun Apr 25 16:35:17 2021 +0200
@@ -1,7 +1,7 @@
 '''This module contains the main() function, which is the entry point for the
 command line interface.'''
 
-__version__ = '3.0.1'
+__version__ = '4.5.0'
 
 
 def main():
--- a/RadonMetrics/radon/complexity.py	Wed Dec 30 11:02:04 2020 +0100
+++ b/RadonMetrics/radon/complexity.py	Sun Apr 25 16:35:17 2021 +0200
@@ -2,17 +2,10 @@
 Cyclomatic Complexity
 '''
 
-#
-# Patched for use within eric6
-# Removed the Flake8Checker related code
-#
-# Modifications Copyright (c) 2018 - 2021 Detlev Offenbach <detlev@die-offenbachs.de>
-#
+import math
 
-import math
 from radon.visitors import GET_COMPLEXITY, ComplexityVisitor, code2ast
 
-
 # sorted_block ordering functions
 SCORE = lambda block: -GET_COMPLEXITY(block)
 LINES = lambda block: block.lineno
@@ -46,7 +39,9 @@
     '''
     if cc < 0:
         raise ValueError('Complexity must be a non-negative value')
-    return chr(min(int(math.ceil(cc / 10.) or 1) - (1, 0)[5 - cc < 0], 5) + 65)
+    return chr(
+        min(int(math.ceil(cc / 10.0) or 1) - (1, 0)[5 - cc < 0], 5) + 65
+    )
 
 
 def average_complexity(blocks):
@@ -58,7 +53,7 @@
     size = len(blocks)
     if size == 0:
         return 0
-    return sum((GET_COMPLEXITY(block) for block in blocks), .0) / len(blocks)
+    return sum((GET_COMPLEXITY(block) for block in blocks), 0.0) / len(blocks)
 
 
 def sorted_results(blocks, order=SCORE):
--- a/RadonMetrics/radon/metrics.py	Wed Dec 30 11:02:04 2020 +0100
+++ b/RadonMetrics/radon/metrics.py	Sun Apr 25 16:35:17 2021 +0200
@@ -3,16 +3,19 @@
 '''
 
 import ast
+import collections
 import math
-import collections
-from radon.visitors import HalsteadVisitor, ComplexityVisitor
+
 from radon.raw import analyze
-
+from radon.visitors import ComplexityVisitor, HalsteadVisitor
 
 # Halstead metrics
-HalsteadReport = collections.namedtuple('HalsteadReport', 'h1 h2 N1 N2 vocabulary length '
-                                        'calculated_length volume '
-                                        'difficulty effort time bugs')
+HalsteadReport = collections.namedtuple(
+    'HalsteadReport',
+    'h1 h2 N1 N2 vocabulary length '
+    'calculated_length volume '
+    'difficulty effort time bugs',
+)
 
 # `total` is a HalsteadReport for the entire scanned file, while `functions` is
 # a list of `HalsteadReport`s for each function in the file.
@@ -55,7 +58,10 @@
     '''
     visitor = HalsteadVisitor.from_ast(ast_node)
     total = halstead_visitor_report(visitor)
-    functions = [(v.context, halstead_visitor_report(v)) for v in visitor.function_visitors]
+    functions = [
+        (v.context, halstead_visitor_report(v))
+        for v in visitor.function_visitors
+    ]
 
     return Halstead(total, functions)
 
@@ -74,8 +80,18 @@
     difficulty = (h1 * N2) / float(2 * h2) if h2 != 0 else 0
     effort = difficulty * volume
     return HalsteadReport(
-        h1, h2, N1, N2, h, N, length, volume, difficulty, effort,
-        effort / 18., volume / 3000.
+        h1,
+        h2,
+        N1,
+        N2,
+        h,
+        N,
+        length,
+        volume,
+        difficulty,
+        effort,
+        effort / 18.0,
+        volume / 3000.0,
     )
 
 
@@ -86,14 +102,19 @@
     is preferred.
     '''
     if any(metric <= 0 for metric in (halstead_volume, sloc)):
-        return 100.
+        return 100.0
     sloc_scale = math.log(sloc)
     volume_scale = math.log(halstead_volume)
     comments_scale = math.sqrt(2.46 * math.radians(comments))
     # Non-normalized MI
-    nn_mi = (171 - 5.2 * volume_scale - .23 * complexity - 16.2 * sloc_scale +
-             50 * math.sin(comments_scale))
-    return min(max(0., nn_mi * 100 / 171.), 100.)
+    nn_mi = (
+        171
+        - 5.2 * volume_scale
+        - 0.23 * complexity
+        - 16.2 * sloc_scale
+        + 50 * math.sin(comments_scale)
+    )
+    return min(max(0.0, nn_mi * 100 / 171.0), 100.0)
 
 
 def mi_parameters(code, count_multi=True):
@@ -113,9 +134,12 @@
     raw = analyze(code)
     comments_lines = raw.comments + (raw.multi if count_multi else 0)
     comments = comments_lines / float(raw.sloc) * 100 if raw.sloc != 0 else 0
-    return (h_visit_ast(ast_node).total.volume,
-            ComplexityVisitor.from_ast(ast_node).total_complexity, raw.lloc,
-            comments)
+    return (
+        h_visit_ast(ast_node).total.volume,
+        ComplexityVisitor.from_ast(ast_node).total_complexity,
+        raw.lloc,
+        comments,
+    )
 
 
 def mi_visit(code, multi):
--- a/RadonMetrics/radon/raw.py	Wed Dec 30 11:02:04 2020 +0100
+++ b/RadonMetrics/radon/raw.py	Sun Apr 25 16:35:17 2021 +0200
@@ -4,17 +4,30 @@
 that is used.
 '''
 
-import tokenize
+import collections
 import operator
-import collections
+import tokenize
+
 try:
     import StringIO as io
 except ImportError:  # pragma: no cover
     import io
 
 
-__all__ = ['OP', 'COMMENT', 'TOKEN_NUMBER', 'NL', 'NEWLINE', 'EM', 'Module',
-           '_generate', '_fewer_tokens', '_find', '_logical', 'analyze']
+__all__ = [
+    'OP',
+    'COMMENT',
+    'TOKEN_NUMBER',
+    'NL',
+    'NEWLINE',
+    'EM',
+    'Module',
+    '_generate',
+    '_fewer_tokens',
+    '_find',
+    '_logical',
+    'analyze',
+]
 
 COMMENT = tokenize.COMMENT
 OP = tokenize.OP
@@ -32,9 +45,10 @@
 #   multi = Multi-line strings (assumed to be docstrings)
 #   blank = Blank lines (or whitespace-only lines)
 #   single_comments = Single-line comments or docstrings
-Module = collections.namedtuple('Module', ['loc', 'lloc', 'sloc',
-                                           'comments', 'multi', 'blank',
-                                           'single_comments'])
+Module = collections.namedtuple(
+    'Module',
+    ['loc', 'lloc', 'sloc', 'comments', 'multi', 'blank', 'single_comments'],
+)
 
 
 def _generate(code):
@@ -133,6 +147,7 @@
 
         if cond: return 0  # Only a comment  -> 2
     '''
+
     def aux(sub_tokens):
         '''The actual function which does the job.'''
         # Get the tokens and, in the meantime, remove comments
@@ -154,6 +169,7 @@
             if not list(_fewer_tokens(processed, [NL, NEWLINE, EM])):
                 return 0
             return 1
+
     return sum(aux(sub) for sub in _split_tokens(tokens, OP, ';'))
 
 
@@ -161,9 +177,9 @@
     '''Is this a single token matching token_number followed by ENDMARKER, NL
     or NEWLINE tokens.
     '''
-    return (TOKEN_NUMBER(tokens[0]) == token_number and
-            all(TOKEN_NUMBER(t) in (EM, NL, NEWLINE)
-                for t in tokens[1:]))
+    return TOKEN_NUMBER(tokens[0]) == token_number and all(
+        TOKEN_NUMBER(t) in (EM, NL, NEWLINE) for t in tokens[1:]
+    )
 
 
 def analyze(source):
@@ -197,8 +213,9 @@
 
         lineno += len(parsed_lines)
 
-        comments += sum(1 for t in tokens
-                        if TOKEN_NUMBER(t) == tokenize.COMMENT)
+        comments += sum(
+            1 for t in tokens if TOKEN_NUMBER(t) == tokenize.COMMENT
+        )
 
         # Identify single line comments, conservatively
         if is_single_token(tokenize.COMMENT, tokens):
--- a/RadonMetrics/radon/visitors.py	Wed Dec 30 11:02:04 2020 +0100
+++ b/RadonMetrics/radon/visitors.py	Sun Apr 25 16:35:17 2021 +0200
@@ -3,9 +3,8 @@
 HalsteadVisitor, that counts Halstead metrics.'''
 
 import ast
+import collections
 import operator
-import collections
-
 
 # Helper functions to use in combination with map()
 GET_COMPLEXITY = operator.attrgetter('complexity')
@@ -13,14 +12,31 @@
 NAMES_GETTER = operator.attrgetter('name', 'asname')
 GET_ENDLINE = operator.attrgetter('endline')
 
-BaseFunc = collections.namedtuple('Function', ['name', 'lineno', 'col_offset',
-                                               'endline', 'is_method',
-                                               'classname', 'closures',
-                                               'complexity'])
-BaseClass = collections.namedtuple('Class', ['name', 'lineno', 'col_offset',
-                                             'endline', 'methods',
-                                             'inner_classes',
-                                             'real_complexity'])
+BaseFunc = collections.namedtuple(
+    'Function',
+    [
+        'name',
+        'lineno',
+        'col_offset',
+        'endline',
+        'is_method',
+        'classname',
+        'closures',
+        'complexity',
+    ],
+)
+BaseClass = collections.namedtuple(
+    'Class',
+    [
+        'name',
+        'lineno',
+        'col_offset',
+        'endline',
+        'methods',
+        'inner_classes',
+        'real_complexity',
+    ],
+)
 
 
 def code2ast(source):
@@ -55,11 +71,14 @@
 
     def __str__(self):
         '''String representation of a function block.'''
-        return '{0} {1}:{2}->{3} {4} - {5}'.format(self.letter, self.lineno,
-                                                   self.col_offset,
-                                                   self.endline,
-                                                   self.fullname,
-                                                   self.complexity)
+        return '{0} {1}:{2}->{3} {4} - {5}'.format(
+            self.letter,
+            self.lineno,
+            self.col_offset,
+            self.endline,
+            self.fullname,
+            self.complexity,
+        )
 
 
 class Class(BaseClass):
@@ -86,10 +105,14 @@
 
     def __str__(self):
         '''String representation of a class block.'''
-        return '{0} {1}:{2}->{3} {4} - {5}'.format(self.letter, self.lineno,
-                                                   self.col_offset,
-                                                   self.endline, self.name,
-                                                   self.complexity)
+        return '{0} {1}:{2}->{3} {4} - {5}'.format(
+            self.letter,
+            self.lineno,
+            self.col_offset,
+            self.endline,
+            self.name,
+            self.complexity,
+        )
 
 
 class CodeVisitor(ast.NodeVisitor):
@@ -130,8 +153,9 @@
         otherwise to 0.
     '''
 
-    def __init__(self, to_method=False, classname=None, off=True,
-                 no_assert=False):
+    def __init__(
+        self, to_method=False, classname=None, off=True, no_assert=False
+    ):
         self.off = off
         self.complexity = 1 if off else 0
         self.functions = []
@@ -163,8 +187,12 @@
         '''The total complexity. Computed adding up the visitor complexity, the
         functions complexity, and the classes complexity.
         '''
-        return (self.complexity + self.functions_complexity +
-                self.classes_complexity + (not self.off))
+        return (
+            self.complexity
+            + self.functions_complexity
+            + self.classes_complexity
+            + (not self.off)
+        )
 
     @property
     def blocks(self):
@@ -247,9 +275,16 @@
             # Add general complexity but not closures' complexity, see #68
             body_complexity += visitor.complexity
 
-        func = Function(node.name, node.lineno, node.col_offset,
-                        max(node.lineno, visitor.max_line), self.to_method,
-                        self.classname, closures, body_complexity)
+        func = Function(
+            node.name,
+            node.lineno,
+            node.col_offset,
+            max(node.lineno, visitor.max_line),
+            self.to_method,
+            self.classname,
+            closures,
+            body_complexity,
+        )
         self.functions.append(func)
 
     def visit_ClassDef(self, node):
@@ -267,19 +302,28 @@
         visitors_max_lines = [node.lineno]
         inner_classes = []
         for child in node.body:
-            visitor = ComplexityVisitor(True, classname, off=False,
-                                        no_assert=self.no_assert)
+            visitor = ComplexityVisitor(
+                True, classname, off=False, no_assert=self.no_assert
+            )
             visitor.visit(child)
             methods.extend(visitor.functions)
-            body_complexity += (visitor.complexity +
-                                visitor.functions_complexity +
-                                len(visitor.functions))
+            body_complexity += (
+                visitor.complexity
+                + visitor.functions_complexity
+                + len(visitor.functions)
+            )
             visitors_max_lines.append(visitor.max_line)
             inner_classes.extend(visitor.classes)
 
-        cls = Class(classname, node.lineno, node.col_offset,
-                    max(visitors_max_lines + list(map(GET_ENDLINE, methods))),
-                    methods, inner_classes, body_complexity)
+        cls = Class(
+            classname,
+            node.lineno,
+            node.col_offset,
+            max(visitors_max_lines + list(map(GET_ENDLINE, methods))),
+            methods,
+            inner_classes,
+            body_complexity,
+        )
         self.classes.append(cls)
 
 
@@ -288,9 +332,14 @@
     Halstead metrics (see :func:`radon.metrics.h_visit`).
     '''
 
-    types = {ast.Num: 'n',
-             ast.Name: 'id',
-             ast.Attribute: 'attr'}
+    # As of Python 3.8 Num/Str/Bytes/NameConstat
+    # are now in a common node Constant.
+    types = {
+        "Num": "n",
+        "Name": "id",
+        "Attribute": "attr",
+        "Constant": "value",
+    }
 
     def __init__(self, context=None):
         '''*context* is a string used to keep track the analysis' context.'''
@@ -323,6 +372,7 @@
             * the operators seen (a sequence)
             * the operands seen (a sequence)
         '''
+
         def aux(self, node):
             '''Actual function that updates the stats.'''
             results = meth(self, node)
@@ -330,13 +380,18 @@
             self.operands += results[1]
             self.operators_seen.update(results[2])
             for operand in results[3]:
-                new_operand = getattr(operand,
-                                      self.types.get(type(operand), ''),
-                                      operand)
+                new_operand = getattr(
+                    operand, self.types.get(type(operand), ''), operand
+                )
+                name = self.get_name(operand)
+                new_operand = getattr(
+                    operand, self.types.get(name, ""), operand
+                )
 
                 self.operands_seen.add((self.context, new_operand))
             # Now dispatch to children
             super(HalsteadVisitor, self).generic_visit(node)
+
         return aux
 
     @dispatch
@@ -362,8 +417,12 @@
     @dispatch
     def visit_Compare(self, node):
         '''A comparison.'''
-        return (len(node.ops), len(node.comparators) + 1,
-                map(self.get_name, node.ops), node.comparators + [node.left])
+        return (
+            len(node.ops),
+            len(node.comparators) + 1,
+            map(self.get_name, node.ops),
+            node.comparators + [node.left],
+        )
 
     def visit_FunctionDef(self, node):
         '''When visiting functions, another visitor is created to recursively
@@ -386,3 +445,9 @@
 
         # Save the visited function visitor for later reference.
         self.function_visitors.append(func_visitor)
+
+    def visit_AsyncFunctionDef(self, node):
+        '''Async functions are similar to standard functions, so treat them as
+        such.
+        '''
+        self.visit_FunctionDef(node)

eric ide

mercurial