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