src/eric7/Plugins/CheckerPlugins/SyntaxChecker/jsonCheckSyntax.py

branch
eric7
changeset 9209
b99e7fd55fd3
parent 8881
54e42bc2437a
child 9221
bf71ee032bb4
equal deleted inserted replaced
9208:3fc8dfeb6ebe 9209:b99e7fd55fd3
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2019 - 2022 Detlev Offenbach <detlev@die-offenbachs.de>
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.
17
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.
27
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.
37
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
45 if codestring and codestring[-1] != '\n':
46 codestring += '\n'
47
48 return codestring
49
50
51 def jsonSyntaxCheck(file, codestring):
52 """
53 Function to check a JSON source file for syntax errors.
54
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.
71
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
98 # Submit tasks (initially two time number of processes
99 initialTasks = 2 * NumberOfProcesses
100 for task in argumentsList[:initialTasks]:
101 taskQueue.put(task)
102
103 # Start worker processes
104 workers = [
105 multiprocessing.Process(
106 target=workerTask, args=(taskQueue, doneQueue)
107 ) for _ in range(NumberOfProcesses)
108 ]
109 for worker in workers:
110 worker.start()
111
112 # Get and send results
113 endIndex = len(argumentsList) - initialTasks
114 for i in range(len(argumentsList)):
115 resultSent = False
116 wasCancelled = False
117
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
129
130 if wasCancelled or cancelled():
131 # just exit the loop ignoring the results of queued tasks
132 break
133
134 if i < endIndex:
135 taskQueue.put(argumentsList[i + initialTasks])
136
137 # Tell child processes to stop
138 for _ in range(NumberOfProcesses):
139 taskQueue.put('STOP')
140
141 for worker in workers:
142 worker.join()
143 worker.close()
144
145
146 def workerTask(inputQueue, outputQueue):
147 """
148 Module function acting as the parallel worker for the syntax check.
149
150 @param inputQueue input queue
151 @type multiprocessing.Queue
152 @param outputQueue output queue
153 @type multiprocessing.Queue
154 """
155 for filename, args in iter(inputQueue.get, 'STOP'):
156 source = args[0]
157 result = __jsonSyntaxCheck(filename, source)
158 outputQueue.put((filename, result))
159
160
161 def __jsonSyntaxCheck(file, codestring):
162 """
163 Function to check a YAML source file for syntax errors.
164
165 @param file source filename
166 @type str
167 @param codestring string containing the code to check
168 @type str
169 @return dictionary with the keys 'error' and 'warnings' which
170 hold a list containing details about the error/ warnings
171 (file name, line number, column, codestring (only at syntax
172 errors), the message, a list with arguments for the message)
173 @rtype dict
174 """
175 import json
176
177 codestring = normalizeCode(codestring)
178
179 try:
180 json.loads(codestring)
181 except json.JSONDecodeError as exc:
182 line = exc.lineno
183 column = exc.colno
184 error = exc.msg
185
186 cline = min(len(codestring.splitlines()), int(line)) - 1
187 code = codestring.splitlines()[cline]
188
189 return [{'error': (file, line, column, code, error)}]
190
191 return [{}]

eric ide

mercurial