Tue, 16 Aug 2022 19:07:16 +0200
Did some optimizations in the multiprocessing code.
7335 | 1 | # -*- coding: utf-8 -*- |
2 | ||
8881
54e42bc2437a
Updated copyright for 2022.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
8650
diff
changeset
|
3 | # Copyright (c) 2019 - 2022 Detlev Offenbach <detlev@die-offenbachs.de> |
7335 | 4 | # |
5 | ||
6 | """ | |
7 | Module implementing the syntax check for JSON. | |
8 | """ | |
9 | ||
10 | import queue | |
11 | import multiprocessing | |
12 | ||
13 | ||
14 | def initService(): | |
15 | """ | |
16 | Initialize the service and return the entry point. | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
17 | |
7335 | 18 | @return the entry point for the background client |
19 | @rtype func | |
20 | """ | |
21 | return jsonSyntaxCheck | |
22 | ||
23 | ||
24 | def initBatchService(): | |
25 | """ | |
26 | Initialize the batch service and return the entry point. | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
27 | |
7335 | 28 | @return the entry point for the background client |
29 | @rtype func | |
30 | """ | |
31 | return jsonSyntaxBatchCheck | |
32 | ||
33 | ||
34 | def normalizeCode(codestring): | |
35 | """ | |
36 | Function to normalize the given code. | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
37 | |
7335 | 38 | @param codestring code to be normalized |
39 | @type str | |
40 | @return normalized code | |
41 | @rtype str | |
42 | """ | |
43 | codestring = codestring.replace("\r\n", "\n").replace("\r", "\n") | |
44 | ||
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
45 | if codestring and codestring[-1] != "\n": |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
46 | codestring += "\n" |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
47 | |
7335 | 48 | return codestring |
49 | ||
50 | ||
51 | def jsonSyntaxCheck(file, codestring): | |
52 | """ | |
53 | Function to check a JSON source file for syntax errors. | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
54 | |
7335 | 55 | @param file source filename |
56 | @type str | |
57 | @param codestring string containing the code to check | |
58 | @type str | |
59 | @return dictionary with the keys 'error' and 'warnings' which | |
60 | hold a list containing details about the error/ warnings | |
61 | (file name, line number, column, codestring (only at syntax | |
62 | errors), the message, a list with arguments for the message) | |
63 | @rtype dict | |
64 | """ | |
65 | return __jsonSyntaxCheck(file, codestring) | |
66 | ||
67 | ||
68 | def jsonSyntaxBatchCheck(argumentsList, send, fx, cancelled, maxProcesses=0): | |
69 | """ | |
70 | Module function to check syntax for a batch of files. | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
71 | |
7335 | 72 | @param argumentsList list of arguments tuples as given for yamlSyntaxCheck |
73 | @type list | |
74 | @param send reference to send function | |
75 | @type func | |
76 | @param fx registered service name | |
77 | @type str | |
78 | @param cancelled reference to function checking for a cancellation | |
79 | @type func | |
80 | @param maxProcesses number of processes to be used | |
81 | @type int | |
82 | """ | |
83 | if maxProcesses == 0: | |
84 | # determine based on CPU count | |
85 | try: | |
86 | NumberOfProcesses = multiprocessing.cpu_count() | |
87 | if NumberOfProcesses >= 1: | |
88 | NumberOfProcesses -= 1 | |
89 | except NotImplementedError: | |
90 | NumberOfProcesses = 1 | |
91 | else: | |
92 | NumberOfProcesses = maxProcesses | |
93 | ||
94 | # Create queues | |
95 | taskQueue = multiprocessing.Queue() | |
96 | doneQueue = multiprocessing.Queue() | |
97 | ||
9289
ba49c41e8f63
Did some optimizations in the multiprocessing code.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9284
diff
changeset
|
98 | # Submit tasks (initially two times the number of processes) |
ba49c41e8f63
Did some optimizations in the multiprocessing code.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9284
diff
changeset
|
99 | tasks = len(argumentsList) |
7335 | 100 | initialTasks = 2 * NumberOfProcesses |
9289
ba49c41e8f63
Did some optimizations in the multiprocessing code.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9284
diff
changeset
|
101 | for _ in range(initialTasks): |
ba49c41e8f63
Did some optimizations in the multiprocessing code.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9284
diff
changeset
|
102 | taskQueue.put(argumentsList.pop(0)) |
7335 | 103 | |
104 | # Start worker processes | |
8650
100726f55a9a
Changed the 'multiprocessing.Process()' code of the background batch services to (hopefully) cure the slow down when used multiple times.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
8312
diff
changeset
|
105 | workers = [ |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
106 | multiprocessing.Process(target=workerTask, args=(taskQueue, doneQueue)) |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
107 | for _ in range(NumberOfProcesses) |
8650
100726f55a9a
Changed the 'multiprocessing.Process()' code of the background batch services to (hopefully) cure the slow down when used multiple times.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
8312
diff
changeset
|
108 | ] |
100726f55a9a
Changed the 'multiprocessing.Process()' code of the background batch services to (hopefully) cure the slow down when used multiple times.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
8312
diff
changeset
|
109 | for worker in workers: |
100726f55a9a
Changed the 'multiprocessing.Process()' code of the background batch services to (hopefully) cure the slow down when used multiple times.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
8312
diff
changeset
|
110 | worker.start() |
7335 | 111 | |
112 | # Get and send results | |
9289
ba49c41e8f63
Did some optimizations in the multiprocessing code.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9284
diff
changeset
|
113 | for _ in range(tasks): |
7335 | 114 | resultSent = False |
115 | wasCancelled = False | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
116 | |
7335 | 117 | while not resultSent: |
118 | try: | |
119 | # get result (waiting max. 3 seconds and send it to frontend | |
120 | filename, result = doneQueue.get() | |
121 | send(fx, filename, result) | |
122 | resultSent = True | |
123 | except queue.Empty: | |
124 | # ignore empty queue, just carry on | |
125 | if cancelled(): | |
126 | wasCancelled = True | |
127 | break | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
128 | |
7335 | 129 | if wasCancelled or cancelled(): |
130 | # just exit the loop ignoring the results of queued tasks | |
131 | break | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
132 | |
9289
ba49c41e8f63
Did some optimizations in the multiprocessing code.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9284
diff
changeset
|
133 | if argumentsList: |
ba49c41e8f63
Did some optimizations in the multiprocessing code.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9284
diff
changeset
|
134 | taskQueue.put(argumentsList.pop(0)) |
7335 | 135 | |
136 | # Tell child processes to stop | |
137 | for _ in range(NumberOfProcesses): | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
138 | taskQueue.put("STOP") |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
139 | |
8650
100726f55a9a
Changed the 'multiprocessing.Process()' code of the background batch services to (hopefully) cure the slow down when used multiple times.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
8312
diff
changeset
|
140 | for worker in workers: |
100726f55a9a
Changed the 'multiprocessing.Process()' code of the background batch services to (hopefully) cure the slow down when used multiple times.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
8312
diff
changeset
|
141 | worker.join() |
100726f55a9a
Changed the 'multiprocessing.Process()' code of the background batch services to (hopefully) cure the slow down when used multiple times.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
8312
diff
changeset
|
142 | worker.close() |
9284
3b3a4f659782
"Blacked" the sources.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9279
diff
changeset
|
143 | |
9279
e252f827aaa7
Added code to explicitly close the queues to/from the workers at the end of a batch check.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9221
diff
changeset
|
144 | taskQueue.close() |
e252f827aaa7
Added code to explicitly close the queues to/from the workers at the end of a batch check.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9221
diff
changeset
|
145 | doneQueue.close() |
7335 | 146 | |
147 | ||
8650
100726f55a9a
Changed the 'multiprocessing.Process()' code of the background batch services to (hopefully) cure the slow down when used multiple times.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
8312
diff
changeset
|
148 | def workerTask(inputQueue, outputQueue): |
7335 | 149 | """ |
150 | Module function acting as the parallel worker for the syntax check. | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
151 | |
7335 | 152 | @param inputQueue input queue |
153 | @type multiprocessing.Queue | |
154 | @param outputQueue output queue | |
155 | @type multiprocessing.Queue | |
156 | """ | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
157 | for filename, args in iter(inputQueue.get, "STOP"): |
7335 | 158 | source = args[0] |
159 | result = __jsonSyntaxCheck(filename, source) | |
160 | outputQueue.put((filename, result)) | |
161 | ||
162 | ||
163 | def __jsonSyntaxCheck(file, codestring): | |
164 | """ | |
165 | Function to check a YAML source file for syntax errors. | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
166 | |
7335 | 167 | @param file source filename |
168 | @type str | |
169 | @param codestring string containing the code to check | |
170 | @type str | |
171 | @return dictionary with the keys 'error' and 'warnings' which | |
172 | hold a list containing details about the error/ warnings | |
173 | (file name, line number, column, codestring (only at syntax | |
174 | errors), the message, a list with arguments for the message) | |
175 | @rtype dict | |
176 | """ | |
177 | import json | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
178 | |
7335 | 179 | codestring = normalizeCode(codestring) |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
180 | |
7335 | 181 | try: |
182 | json.loads(codestring) | |
183 | except json.JSONDecodeError as exc: | |
184 | line = exc.lineno | |
185 | column = exc.colno | |
186 | error = exc.msg | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
187 | |
7335 | 188 | cline = min(len(codestring.splitlines()), int(line)) - 1 |
189 | code = codestring.splitlines()[cline] | |
9221
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
190 | |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
191 | return [{"error": (file, line, column, code, error)}] |
bf71ee032bb4
Reformatted the source code using the 'Black' utility.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9209
diff
changeset
|
192 | |
7335 | 193 | return [{}] |