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