|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2024 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing the code coverage interface to the eric-ide server. |
|
8 """ |
|
9 |
|
10 import contextlib |
|
11 |
|
12 from PyQt6.QtCore import QEventLoop, QObject |
|
13 |
|
14 from eric7.RemoteServer.EricRequestCategory import EricRequestCategory |
|
15 from eric7.SystemUtilities import FileSystemUtilities |
|
16 |
|
17 |
|
18 class EricServerCoverageError(Exception): |
|
19 """ |
|
20 Class defining a substitute exception for coverage errors of the server. |
|
21 """ |
|
22 |
|
23 pass |
|
24 |
|
25 |
|
26 class EricServerCoverageInterface(QObject): |
|
27 """ |
|
28 Class implementing the code coverage interface to the eric-ide server. |
|
29 """ |
|
30 |
|
31 def __init__(self, serverInterface): |
|
32 """ |
|
33 Constructor |
|
34 |
|
35 @param serverInterface reference to the eric-ide server interface |
|
36 @type EricServerInterface |
|
37 """ |
|
38 super().__init__(parent=serverInterface) |
|
39 |
|
40 self.__serverInterface = serverInterface |
|
41 |
|
42 def loadCoverageData(self, dataFile, excludePattern): |
|
43 """ |
|
44 Public method to tell the server to load the coverage data for a later analysis. |
|
45 |
|
46 @param dataFile name of the data file to be loaded |
|
47 @type str |
|
48 @param excludePattern regular expression determining files to be excluded |
|
49 @type str |
|
50 @return tuple containing a success flag and an error message |
|
51 @rtype tuple of (bool, str) |
|
52 """ |
|
53 loop = QEventLoop() |
|
54 ok = False |
|
55 error = "" |
|
56 |
|
57 def callback(reply, params): |
|
58 """ |
|
59 Function to handle the server reply |
|
60 |
|
61 @param reply name of the server reply |
|
62 @type str |
|
63 @param params dictionary containing the reply data |
|
64 @type dict |
|
65 """ |
|
66 nonlocal ok, error |
|
67 |
|
68 if reply == "LoadData": |
|
69 ok = params["ok"] |
|
70 with contextlib.suppress(KeyError): |
|
71 error = params["error"] |
|
72 loop.quit() |
|
73 |
|
74 self.__serverInterface.sendJson( |
|
75 category=EricRequestCategory.Coverage, |
|
76 request="LoadData", |
|
77 params={ |
|
78 "data_file": FileSystemUtilities.plainFileName(dataFile), |
|
79 "exclude": excludePattern, |
|
80 }, |
|
81 callback=callback, |
|
82 ) |
|
83 |
|
84 loop.exec() |
|
85 return ok, error |
|
86 |
|
87 def analyzeFile(self, filename): |
|
88 """ |
|
89 Public method to analyze the code coverage of one file. |
|
90 |
|
91 @param filename name of the file to be analyzed |
|
92 @type str |
|
93 @return list containing coverage result as reported by Coverage.analysis2() |
|
94 @rtype list of [str, list of int, list of int, list of int, str] |
|
95 @exception EricServerCoverageException raised to indicate a coverage exception |
|
96 """ |
|
97 loop = QEventLoop() |
|
98 ok = False |
|
99 error = "" |
|
100 result = None |
|
101 |
|
102 def callback(reply, params): |
|
103 """ |
|
104 Function to handle the server reply |
|
105 |
|
106 @param reply name of the server reply |
|
107 @type str |
|
108 @param params dictionary containing the reply data |
|
109 @type dict |
|
110 """ |
|
111 nonlocal ok, error, result |
|
112 |
|
113 if reply == "AnalyzeFile": |
|
114 ok = params["ok"] |
|
115 if ok: |
|
116 result = params["result"] |
|
117 else: |
|
118 error = params["error"] |
|
119 loop.quit() |
|
120 |
|
121 self.__serverInterface.sendJson( |
|
122 category=EricRequestCategory.Coverage, |
|
123 request="AnalyzeFile", |
|
124 params={"filename": FileSystemUtilities.plainFileName(filename)}, |
|
125 callback=callback, |
|
126 ) |
|
127 |
|
128 loop.exec() |
|
129 if not ok: |
|
130 raise EricServerCoverageError(error) |
|
131 |
|
132 return result |
|
133 |
|
134 def analyzeFiles(self, filenames): |
|
135 """ |
|
136 Public method to analyze the code coverage of a list of files. |
|
137 |
|
138 @param filenames list of file names to be analyzed |
|
139 @type str |
|
140 @return lists containing coverage results as reported by Coverage.analysis2() |
|
141 @rtype list of [list of [str, list of int, list of int, list of int, str]] |
|
142 @exception EricServerCoverageException raised to indicate a coverage exception |
|
143 """ |
|
144 loop = QEventLoop() |
|
145 ok = False |
|
146 error = "" |
|
147 result = None |
|
148 |
|
149 def callback(reply, params): |
|
150 """ |
|
151 Function to handle the server reply |
|
152 |
|
153 @param reply name of the server reply |
|
154 @type str |
|
155 @param params dictionary containing the reply data |
|
156 @type dict |
|
157 """ |
|
158 nonlocal ok, error, result |
|
159 |
|
160 if reply == "AnalyzeFiles": |
|
161 ok = params["ok"] |
|
162 if ok: |
|
163 result = params["results"] |
|
164 else: |
|
165 error = params["error"] |
|
166 loop.quit() |
|
167 |
|
168 self.__serverInterface.sendJson( |
|
169 category=EricRequestCategory.Coverage, |
|
170 request="AnalyzeFiles", |
|
171 params={ |
|
172 "filenames": [FileSystemUtilities.plainFileName(f) for f in filenames] |
|
173 }, |
|
174 callback=callback, |
|
175 ) |
|
176 |
|
177 loop.exec() |
|
178 if not ok: |
|
179 raise EricServerCoverageError(error) |
|
180 |
|
181 return result |
|
182 |
|
183 def analyzeDirectory(self, directory): |
|
184 """ |
|
185 Public method to analyze the code coverage of a directory. |
|
186 |
|
187 @param directory directory name to be analyzed |
|
188 @type str |
|
189 @return lists containing coverage results as reported by Coverage.analysis2() |
|
190 @rtype list of [list of [str, list of int, list of int, list of int, str]] |
|
191 @exception EricServerCoverageException raised to indicate a coverage exception |
|
192 """ |
|
193 loop = QEventLoop() |
|
194 ok = False |
|
195 error = "" |
|
196 result = None |
|
197 |
|
198 def callback(reply, params): |
|
199 """ |
|
200 Function to handle the server reply |
|
201 |
|
202 @param reply name of the server reply |
|
203 @type str |
|
204 @param params dictionary containing the reply data |
|
205 @type dict |
|
206 """ |
|
207 nonlocal ok, error, result |
|
208 |
|
209 if reply == "AnalyzeDirectory": |
|
210 ok = params["ok"] |
|
211 if ok: |
|
212 result = params["results"] |
|
213 else: |
|
214 error = params["error"] |
|
215 loop.quit() |
|
216 |
|
217 self.__serverInterface.sendJson( |
|
218 category=EricRequestCategory.Coverage, |
|
219 request="AnalyzeDirectory", |
|
220 params={"directory": FileSystemUtilities.plainFileName(directory)}, |
|
221 callback=callback, |
|
222 ) |
|
223 |
|
224 loop.exec() |
|
225 if not ok: |
|
226 raise EricServerCoverageError(error) |
|
227 |
|
228 return result |