RadonMetrics/radon/visitors.py

Sat, 23 Feb 2019 10:08:14 +0100

author
T.Rzepka <Tobias.Rzepka@gmail.com>
date
Sat, 23 Feb 2019 10:08:14 +0100
changeset 61
f7c284ce1e18
parent 55
755bc8e1485a
child 76
5523ecb9d763
permissions
-rw-r--r--

Upgraded the embedded Radon library to version 3.0.1.

1
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
1 '''This module contains the ComplexityVisitor class which is where all the
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
2 analysis concerning Cyclomatic Complexity is done. There is also the class
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
3 HalsteadVisitor, that counts Halstead metrics.'''
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
4
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
5 import ast
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
6 import operator
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
7 import collections
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
8
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
9
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
10 # Helper functions to use in combination with map()
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
11 GET_COMPLEXITY = operator.attrgetter('complexity')
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
12 GET_REAL_COMPLEXITY = operator.attrgetter('real_complexity')
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
13 NAMES_GETTER = operator.attrgetter('name', 'asname')
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
14 GET_ENDLINE = operator.attrgetter('endline')
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
15
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
16 BaseFunc = collections.namedtuple('Function', ['name', 'lineno', 'col_offset',
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
17 'endline', 'is_method',
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
18 'classname', 'closures',
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
19 'complexity'])
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
20 BaseClass = collections.namedtuple('Class', ['name', 'lineno', 'col_offset',
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
21 'endline', 'methods',
55
755bc8e1485a Upgraded the embedded Radon library to version 2.4.0.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 20
diff changeset
22 'inner_classes',
1
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
23 'real_complexity'])
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
24
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
25
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
26 def code2ast(source):
55
755bc8e1485a Upgraded the embedded Radon library to version 2.4.0.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 20
diff changeset
27 '''Convert a string object into an AST object.
755bc8e1485a Upgraded the embedded Radon library to version 2.4.0.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 20
diff changeset
28
755bc8e1485a Upgraded the embedded Radon library to version 2.4.0.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 20
diff changeset
29 This function is retained for backwards compatibility, but it no longer
755bc8e1485a Upgraded the embedded Radon library to version 2.4.0.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 20
diff changeset
30 attemps any conversions. It's equivalent to a call to ``ast.parse``.
1
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
31 '''
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
32 return ast.parse(source)
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
33
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
34
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
35 class Function(BaseFunc):
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
36 '''Object represeting a function block.'''
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
37
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
38 @property
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
39 def letter(self):
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
40 '''The letter representing the function. It is `M` if the function is
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
41 actually a method, `F` otherwise.
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
42 '''
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
43 return 'M' if self.is_method else 'F'
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
44
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
45 @property
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
46 def fullname(self):
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
47 '''The full name of the function. If it is a method, then the full name
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
48 is:
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
49 {class name}.{method name}
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
50 Otherwise it is just the function name.
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
51 '''
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
52 if self.classname is None:
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
53 return self.name
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
54 return '{0}.{1}'.format(self.classname, self.name)
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
55
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
56 def __str__(self):
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
57 '''String representation of a function block.'''
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
58 return '{0} {1}:{2}->{3} {4} - {5}'.format(self.letter, self.lineno,
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
59 self.col_offset,
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
60 self.endline,
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
61 self.fullname,
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
62 self.complexity)
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
63
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
64
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
65 class Class(BaseClass):
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
66 '''Object representing a class block.'''
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
67
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
68 letter = 'C'
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
69
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
70 @property
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
71 def fullname(self):
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
72 '''The full name of the class. It is just its name. This attribute
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
73 exists for consistency (see :data:`Function.fullname`).
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
74 '''
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
75 return self.name
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
76
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
77 @property
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
78 def complexity(self):
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
79 '''The average complexity of the class. It corresponds to the average
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
80 complexity of its methods plus one.
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
81 '''
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
82 if not self.methods:
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
83 return self.real_complexity
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
84 methods = len(self.methods)
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
85 return int(self.real_complexity / float(methods)) + (methods > 1)
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
86
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
87 def __str__(self):
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
88 '''String representation of a class block.'''
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
89 return '{0} {1}:{2}->{3} {4} - {5}'.format(self.letter, self.lineno,
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
90 self.col_offset,
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
91 self.endline, self.name,
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
92 self.complexity)
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
93
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
94
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
95 class CodeVisitor(ast.NodeVisitor):
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
96 '''Base class for every NodeVisitors in `radon.visitors`. It implements a
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
97 couple utility class methods and a static method.
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
98 '''
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
99
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
100 @staticmethod
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
101 def get_name(obj):
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
102 '''Shorthand for ``obj.__class__.__name__``.'''
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
103 return obj.__class__.__name__
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
104
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
105 @classmethod
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
106 def from_code(cls, code, **kwargs):
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
107 '''Instanciate the class from source code (string object). The
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
108 `**kwargs` are directly passed to the `ast.NodeVisitor` constructor.
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
109 '''
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
110 return cls.from_ast(code2ast(code), **kwargs)
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
111
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
112 @classmethod
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
113 def from_ast(cls, ast_node, **kwargs):
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
114 '''Instantiate the class from an AST node. The `**kwargs` are
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
115 directly passed to the `ast.NodeVisitor` constructor.
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
116 '''
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
117 visitor = cls(**kwargs)
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
118 visitor.visit(ast_node)
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
119 return visitor
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
120
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
121
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
122 class ComplexityVisitor(CodeVisitor):
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
123 '''A visitor that keeps track of the cyclomatic complexity of
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
124 the elements.
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
125
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
126 :param to_method: If True, every function is treated as a method. In this
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
127 case the *classname* parameter is used as class name.
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
128 :param classname: Name of parent class.
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
129 :param off: If True, the starting value for the complexity is set to 1,
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
130 otherwise to 0.
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
131 '''
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
132
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
133 def __init__(self, to_method=False, classname=None, off=True,
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
134 no_assert=False):
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
135 self.off = off
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
136 self.complexity = 1 if off else 0
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
137 self.functions = []
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
138 self.classes = []
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
139 self.to_method = to_method
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
140 self.classname = classname
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
141 self.no_assert = no_assert
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
142 self._max_line = float('-inf')
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
143
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
144 @property
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
145 def functions_complexity(self):
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
146 '''The total complexity from all functions (i.e. the total number of
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
147 decision points + 1).
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
148
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
149 This is *not* the sum of all the complexity from the functions. Rather,
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
150 it's the complexity of the code *inside* all the functions.
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
151 '''
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
152 return sum(map(GET_COMPLEXITY, self.functions)) - len(self.functions)
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
153
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
154 @property
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
155 def classes_complexity(self):
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
156 '''The total complexity from all classes (i.e. the total number of
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
157 decision points + 1).
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
158 '''
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
159 return sum(map(GET_REAL_COMPLEXITY, self.classes)) - len(self.classes)
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
160
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
161 @property
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
162 def total_complexity(self):
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
163 '''The total complexity. Computed adding up the visitor complexity, the
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
164 functions complexity, and the classes complexity.
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
165 '''
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
166 return (self.complexity + self.functions_complexity +
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
167 self.classes_complexity + (not self.off))
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
168
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
169 @property
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
170 def blocks(self):
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
171 '''All the blocks visited. These include: all the functions, the
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
172 classes and their methods. The returned list is not sorted.
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
173 '''
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
174 blocks = []
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
175 blocks.extend(self.functions)
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
176 for cls in self.classes:
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
177 blocks.append(cls)
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
178 blocks.extend(cls.methods)
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
179 return blocks
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
180
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
181 @property
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
182 def max_line(self):
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
183 '''The maximum line number among the analyzed lines.'''
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
184 return self._max_line
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
185
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
186 @max_line.setter
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
187 def max_line(self, value):
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
188 '''The maximum line number among the analyzed lines.'''
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
189 if value > self._max_line:
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
190 self._max_line = value
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
191
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
192 def generic_visit(self, node):
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
193 '''Main entry point for the visitor.'''
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
194 # Get the name of the class
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
195 name = self.get_name(node)
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
196 # Check for a lineno attribute
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
197 if hasattr(node, 'lineno'):
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
198 self.max_line = node.lineno
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
199 # The Try/Except block is counted as the number of handlers
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
200 # plus the `else` block.
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
201 # In Python 3.3 the TryExcept and TryFinally nodes have been merged
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
202 # into a single node: Try
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
203 if name in ('Try', 'TryExcept'):
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
204 self.complexity += len(node.handlers) + len(node.orelse)
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
205 elif name == 'BoolOp':
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
206 self.complexity += len(node.values) - 1
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
207 # Ifs, with and assert statements count all as 1.
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
208 # Note: Lambda functions are not counted anymore, see #68
61
f7c284ce1e18 Upgraded the embedded Radon library to version 3.0.1.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents: 55
diff changeset
209 elif name in ('If', 'IfExp'):
1
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
210 self.complexity += 1
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
211 # The For and While blocks count as 1 plus the `else` block.
20
2677fbceea32 Patched the radon files to support Python 3.5 'async def'.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 1
diff changeset
212 elif name in ('For', 'While', 'AsyncFor'):
1
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
213 self.complexity += bool(node.orelse) + 1
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
214 # List, set, dict comprehensions and generator exps count as 1 plus
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
215 # the `if` statement.
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
216 elif name == 'comprehension':
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
217 self.complexity += len(node.ifs) + 1
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
218
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
219 super(ComplexityVisitor, self).generic_visit(node)
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
220
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
221 def visit_Assert(self, node):
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
222 '''When visiting `assert` statements, the complexity is increased only
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
223 if the `no_assert` attribute is `False`.
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
224 '''
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
225 self.complexity += not self.no_assert
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
226
55
755bc8e1485a Upgraded the embedded Radon library to version 2.4.0.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 20
diff changeset
227 def visit_AsyncFunctionDef(self, node):
755bc8e1485a Upgraded the embedded Radon library to version 2.4.0.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 20
diff changeset
228 '''Async function definition is the same thing as the synchronous
755bc8e1485a Upgraded the embedded Radon library to version 2.4.0.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 20
diff changeset
229 one.
755bc8e1485a Upgraded the embedded Radon library to version 2.4.0.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 20
diff changeset
230 '''
755bc8e1485a Upgraded the embedded Radon library to version 2.4.0.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 20
diff changeset
231 self.visit_FunctionDef(node)
755bc8e1485a Upgraded the embedded Radon library to version 2.4.0.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 20
diff changeset
232
1
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
233 def visit_FunctionDef(self, node):
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
234 '''When visiting functions a new visitor is created to recursively
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
235 analyze the function's body.
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
236 '''
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
237 # The complexity of a function is computed taking into account
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
238 # the following factors: number of decorators, the complexity
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
239 # the function's body and the number of closures (which count
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
240 # double).
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
241 closures = []
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
242 body_complexity = 1
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
243 for child in node.body:
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
244 visitor = ComplexityVisitor(off=False, no_assert=self.no_assert)
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
245 visitor.visit(child)
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
246 closures.extend(visitor.functions)
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
247 # Add general complexity but not closures' complexity, see #68
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
248 body_complexity += visitor.complexity
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
249
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
250 func = Function(node.name, node.lineno, node.col_offset,
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
251 max(node.lineno, visitor.max_line), self.to_method,
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
252 self.classname, closures, body_complexity)
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
253 self.functions.append(func)
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
254
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
255 def visit_ClassDef(self, node):
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
256 '''When visiting classes a new visitor is created to recursively
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
257 analyze the class' body and methods.
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
258 '''
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
259 # The complexity of a class is computed taking into account
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
260 # the following factors: number of decorators and the complexity
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
261 # of the class' body (which is the sum of all the complexities).
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
262 methods = []
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
263 # According to Cyclomatic Complexity definition it has to start off
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
264 # from 1.
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
265 body_complexity = 1
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
266 classname = node.name
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
267 visitors_max_lines = [node.lineno]
55
755bc8e1485a Upgraded the embedded Radon library to version 2.4.0.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 20
diff changeset
268 inner_classes = []
1
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
269 for child in node.body:
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
270 visitor = ComplexityVisitor(True, classname, off=False,
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
271 no_assert=self.no_assert)
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
272 visitor.visit(child)
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
273 methods.extend(visitor.functions)
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
274 body_complexity += (visitor.complexity +
61
f7c284ce1e18 Upgraded the embedded Radon library to version 3.0.1.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents: 55
diff changeset
275 visitor.functions_complexity +
f7c284ce1e18 Upgraded the embedded Radon library to version 3.0.1.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents: 55
diff changeset
276 len(visitor.functions))
1
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
277 visitors_max_lines.append(visitor.max_line)
55
755bc8e1485a Upgraded the embedded Radon library to version 2.4.0.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 20
diff changeset
278 inner_classes.extend(visitor.classes)
1
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
279
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
280 cls = Class(classname, node.lineno, node.col_offset,
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
281 max(visitors_max_lines + list(map(GET_ENDLINE, methods))),
55
755bc8e1485a Upgraded the embedded Radon library to version 2.4.0.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 20
diff changeset
282 methods, inner_classes, body_complexity)
1
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
283 self.classes.append(cls)
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
284
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
285
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
286 class HalsteadVisitor(CodeVisitor):
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
287 '''Visitor that keeps track of operators and operands, in order to compute
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
288 Halstead metrics (see :func:`radon.metrics.h_visit`).
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
289 '''
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
290
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
291 types = {ast.Num: 'n',
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
292 ast.Name: 'id',
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
293 ast.Attribute: 'attr'}
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
294
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
295 def __init__(self, context=None):
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
296 '''*context* is a string used to keep track the analysis' context.'''
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
297 self.operators_seen = set()
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
298 self.operands_seen = set()
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
299 self.operators = 0
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
300 self.operands = 0
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
301 self.context = context
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
302
55
755bc8e1485a Upgraded the embedded Radon library to version 2.4.0.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 20
diff changeset
303 # A new visitor is spawned for every scanned function.
755bc8e1485a Upgraded the embedded Radon library to version 2.4.0.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 20
diff changeset
304 self.function_visitors = []
755bc8e1485a Upgraded the embedded Radon library to version 2.4.0.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 20
diff changeset
305
1
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
306 @property
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
307 def distinct_operators(self):
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
308 '''The number of distinct operators.'''
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
309 return len(self.operators_seen)
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
310
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
311 @property
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
312 def distinct_operands(self):
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
313 '''The number of distinct operands.'''
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
314 return len(self.operands_seen)
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
315
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
316 def dispatch(meth):
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
317 '''This decorator does all the hard work needed for every node.
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
318
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
319 The decorated method must return a tuple of 4 elements:
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
320
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
321 * the number of operators
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
322 * the number of operands
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
323 * the operators seen (a sequence)
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
324 * the operands seen (a sequence)
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
325 '''
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
326 def aux(self, node):
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
327 '''Actual function that updates the stats.'''
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
328 results = meth(self, node)
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
329 self.operators += results[0]
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
330 self.operands += results[1]
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
331 self.operators_seen.update(results[2])
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
332 for operand in results[3]:
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
333 new_operand = getattr(operand,
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
334 self.types.get(type(operand), ''),
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
335 operand)
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
336
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
337 self.operands_seen.add((self.context, new_operand))
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
338 # Now dispatch to children
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
339 super(HalsteadVisitor, self).generic_visit(node)
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
340 return aux
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
341
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
342 @dispatch
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
343 def visit_BinOp(self, node):
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
344 '''A binary operator.'''
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
345 return (1, 2, (self.get_name(node.op),), (node.left, node.right))
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
346
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
347 @dispatch
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
348 def visit_UnaryOp(self, node):
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
349 '''A unary operator.'''
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
350 return (1, 1, (self.get_name(node.op),), (node.operand,))
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
351
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
352 @dispatch
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
353 def visit_BoolOp(self, node):
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
354 '''A boolean operator.'''
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
355 return (1, len(node.values), (self.get_name(node.op),), node.values)
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
356
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
357 @dispatch
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
358 def visit_AugAssign(self, node):
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
359 '''An augmented assign (contains an operator).'''
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
360 return (1, 2, (self.get_name(node.op),), (node.target, node.value))
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
361
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
362 @dispatch
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
363 def visit_Compare(self, node):
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
364 '''A comparison.'''
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
365 return (len(node.ops), len(node.comparators) + 1,
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
366 map(self.get_name, node.ops), node.comparators + [node.left])
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
367
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
368 def visit_FunctionDef(self, node):
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
369 '''When visiting functions, another visitor is created to recursively
55
755bc8e1485a Upgraded the embedded Radon library to version 2.4.0.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 20
diff changeset
370 analyze the function's body. We also track information on the function
755bc8e1485a Upgraded the embedded Radon library to version 2.4.0.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 20
diff changeset
371 itself.
1
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
372 '''
55
755bc8e1485a Upgraded the embedded Radon library to version 2.4.0.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 20
diff changeset
373 func_visitor = HalsteadVisitor(context=node.name)
755bc8e1485a Upgraded the embedded Radon library to version 2.4.0.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 20
diff changeset
374
1
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
375 for child in node.body:
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
376 visitor = HalsteadVisitor.from_ast(child, context=node.name)
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
377 self.operators += visitor.operators
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
378 self.operands += visitor.operands
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
379 self.operators_seen.update(visitor.operators_seen)
b6cced815847 Added the radon files.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff changeset
380 self.operands_seen.update(visitor.operands_seen)
20
2677fbceea32 Patched the radon files to support Python 3.5 'async def'.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 1
diff changeset
381
55
755bc8e1485a Upgraded the embedded Radon library to version 2.4.0.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 20
diff changeset
382 func_visitor.operators += visitor.operators
755bc8e1485a Upgraded the embedded Radon library to version 2.4.0.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 20
diff changeset
383 func_visitor.operands += visitor.operands
755bc8e1485a Upgraded the embedded Radon library to version 2.4.0.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 20
diff changeset
384 func_visitor.operators_seen.update(visitor.operators_seen)
755bc8e1485a Upgraded the embedded Radon library to version 2.4.0.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 20
diff changeset
385 func_visitor.operands_seen.update(visitor.operands_seen)
755bc8e1485a Upgraded the embedded Radon library to version 2.4.0.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 20
diff changeset
386
755bc8e1485a Upgraded the embedded Radon library to version 2.4.0.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 20
diff changeset
387 # Save the visited function visitor for later reference.
755bc8e1485a Upgraded the embedded Radon library to version 2.4.0.
Detlev Offenbach <detlev@die-offenbachs.de>
parents: 20
diff changeset
388 self.function_visitors.append(func_visitor)

eric ide

mercurial