VultureChecker/VultureCheckerService.py

changeset 2
b517a1c5d5de
child 7
a1a6ff3e5486
equal deleted inserted replaced
1:ea6aed49cd69 2:b517a1c5d5de
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2015 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing the cyclomatic complexity service.
8 """
9
10 from __future__ import unicode_literals
11
12 try:
13 str = unicode # __IGNORE_EXCEPTION__ __IGNORE_WARNING__
14 except NameError:
15 pass
16
17 import ast
18
19 import multiprocessing
20 import sys
21
22 from vulture import Vulture
23
24
25 def initService():
26 """
27 Initialize the service and return the entry point.
28
29 @return the entry point for the background client (function)
30 """
31 return vultureCheck
32
33
34 def initBatchService():
35 """
36 Initialize the batch service and return the entry point.
37
38 @return the entry point for the background client (function)
39 """
40 return batchVultureCheck
41
42
43 def vultureCheck(file, text=""):
44 """
45 Private function to analyze one file.
46
47 @param file source filename
48 @type str
49 @param text source text
50 @type str
51 @return tuple containing the result dictionary
52 @rtype (tuple of dict)
53 """
54 return __analyze(file, text)
55
56
57 def batchVultureCheck(argumentsList, send, fx, cancelled):
58 """
59 Module function to analyze a batch of files.
60
61 @param argumentsList list of arguments tuples as given for vultureCheck
62 @type list
63 @param send reference to send function
64 @type function
65 @param fx registered service name
66 @type str
67 @param cancelled reference to function checking for a cancellation
68 @type function
69 """
70 try:
71 NumberOfProcesses = multiprocessing.cpu_count()
72 if NumberOfProcesses >= 1:
73 NumberOfProcesses -= 1
74 except NotImplementedError:
75 NumberOfProcesses = 1
76
77 # Create queues
78 taskQueue = multiprocessing.Queue()
79 doneQueue = multiprocessing.Queue()
80
81 # Submit tasks (initially two time number of processes
82 initialTasks = 2 * NumberOfProcesses
83 for task in argumentsList[:initialTasks]:
84 taskQueue.put(task)
85
86 # Start worker processes
87 for i in range(NumberOfProcesses):
88 multiprocessing.Process(target=worker, args=(taskQueue, doneQueue))\
89 .start()
90
91 # Get and send results
92 endIndex = len(argumentsList) - initialTasks
93 for i in range(len(argumentsList)):
94 filename, result = doneQueue.get()
95 send(fx, filename, result)
96 if cancelled():
97 # just exit the loop ignoring the results of queued tasks
98 break
99 if i < endIndex:
100 taskQueue.put(argumentsList[i + initialTasks])
101
102 # Tell child processes to stop
103 for i in range(NumberOfProcesses):
104 taskQueue.put('STOP')
105
106
107 def worker(input, output):
108 """
109 Module function acting as the parallel worker for the cyclomatic
110 complexity calculation.
111
112 @param input input queue
113 @type multiprocessing.Queue
114 @param output output queue
115 @type multiprocessing.Queue
116 """
117 for filename, source in iter(input.get, 'STOP'):
118 result = __analyze(filename, source)
119 output.put((filename, result))
120
121
122 def __analyze(file, text=""):
123 """
124 Private function to analyze one Python file.
125
126 @param file source file name
127 @type str
128 @param text source text
129 @type str
130 @return tuple containing the result dictionary
131 @rtype (tuple of dict)
132 """
133
134 # Check type for py2: if not str it's unicode
135 if sys.version_info[0] == 2:
136 try:
137 text = text.encode('utf-8')
138 except UnicodeError:
139 pass
140
141 try:
142 v = EricVulture(file)
143 v.scan(text)
144 res = v.getResults()
145 except Exception as err:
146 res = {"error": str(err)}
147 return (res, )
148
149
150 class EricVulture(Vulture):
151 """
152 Class to adopt the Vulture class to the eric plug-in functionality.
153 """
154 def __init__(self, filename):
155 """
156 Constructor
157
158 @param filename source file name
159 @type str
160 """
161 super(EricVulture, self).__init__()
162
163 self.file = filename
164 self.code = None
165
166 def scan(self, source):
167 """
168 Public method to scan the source text.
169
170 @param source source text
171 @type str
172 """
173 self.code = source.splitlines()
174 node = ast.parse(source, filename=self.file)
175 self.visit(node)
176
177 def __item2Dict(self, item):
178 """
179 Private method to convert a vulture item to a dictionary.
180
181 @param item vulture item
182 @type vulture.Item
183 @return item dictionary
184 @rtype dict
185 """
186 d = {
187 "name": str(item),
188 "type": getattr(item, "typ", ""),
189 "file": getattr(item, "file", ""),
190 "line": getattr(item, "lineno", ""),
191 }
192 return d
193
194 def getResults(self):
195 """
196 Public method to get the scan results.
197
198 @return scan results
199 @rtype dict
200 """
201 return {
202 "DefinedAttributes":
203 [self.__item2Dict(i) for i in self.defined_attrs],
204 "DefinedFunctions":
205 [self.__item2Dict(i) for i in self.defined_funcs],
206 "DefinedProperties":
207 [self.__item2Dict(i) for i in self.defined_props],
208 "DefinedVariables":
209 [self.__item2Dict(i) for i in self.defined_vars],
210 "UsedAttributes":
211 [self.__item2Dict(i) for i in self.used_attrs],
212 "UsedVariables":
213 [self.__item2Dict(i) for i in self.used_vars],
214 "TupleVariables":
215 [self.__item2Dict(i) for i in self.tuple_assign_vars],
216 "Aliases":
217 [self.__item2Dict(i) for i in self.names_imported_as_aliases],
218 }

eric ide

mercurial