eric6/Plugins/CheckerPlugins/SyntaxChecker/tomlCheckSyntax.py

changeset 7756
c23a94f7e2e5
parent 7755
1f0a5024360c
child 7923
91e843545d9a
equal deleted inserted replaced
7755:1f0a5024360c 7756:c23a94f7e2e5
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2020 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing the syntax check for TOML.
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 tomlSyntaxCheck
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 tomlSyntaxBatchCheck
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 = codestring + '\n'
47
48 return codestring
49
50
51 def tomlSyntaxCheck(file, codestring):
52 """
53 Function to check a TOML 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 __tomlSyntaxCheck(file, codestring)
66
67
68 def tomlSyntaxBatchCheck(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 tomlSyntaxCheck
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 for _ in range(NumberOfProcesses):
105 multiprocessing.Process(
106 target=worker, args=(taskQueue, doneQueue)
107 ).start()
108
109 # Get and send results
110 endIndex = len(argumentsList) - initialTasks
111 for i in range(len(argumentsList)):
112 resultSent = False
113 wasCancelled = False
114
115 while not resultSent:
116 try:
117 # get result (waiting max. 3 seconds and send it to frontend
118 filename, result = doneQueue.get()
119 send(fx, filename, result)
120 resultSent = True
121 except queue.Empty:
122 # ignore empty queue, just carry on
123 if cancelled():
124 wasCancelled = True
125 break
126
127 if wasCancelled or cancelled():
128 # just exit the loop ignoring the results of queued tasks
129 break
130
131 if i < endIndex:
132 taskQueue.put(argumentsList[i + initialTasks])
133
134 # Tell child processes to stop
135 for _ in range(NumberOfProcesses):
136 taskQueue.put('STOP')
137
138
139 def worker(inputQueue, outputQueue):
140 """
141 Module function acting as the parallel worker for the syntax check.
142
143 @param inputQueue input queue
144 @type multiprocessing.Queue
145 @param outputQueue output queue
146 @type multiprocessing.Queue
147 """
148 for filename, args in iter(inputQueue.get, 'STOP'):
149 source = args[0]
150 result = __tomlSyntaxCheck(filename, source)
151 outputQueue.put((filename, result))
152
153
154 def __tomlSyntaxCheck(file, codestring):
155 """
156 Function to check a TOML source file for syntax errors.
157
158 @param file source filename
159 @type str
160 @param codestring string containing the code to check
161 @type str
162 @return dictionary with the keys 'error' and 'warnings' which
163 hold a list containing details about the error/ warnings
164 (file name, line number, column, codestring (only at syntax
165 errors), the message, a list with arguments for the message)
166 @rtype dict
167 """
168 try:
169 import toml
170 except ImportError:
171 error = "toml not available. Install it via the PyPI interface."
172 return [{'error': (file, 0, 0, '', error)}]
173
174 codestring = normalizeCode(codestring)
175
176 try:
177 toml.loads(codestring)
178 except toml.TomlDecodeError as exc:
179 line = exc.lineno
180 column = exc.colno
181 error = exc.msg
182
183 cline = min(len(codestring.splitlines()), int(line)) - 1
184 code = codestring.splitlines()[cline]
185
186 return [{'error': (file, line, column, code, error)}]
187
188 return [{}]

eric ide

mercurial