12 |
12 |
13 |
13 |
14 def initService(): |
14 def initService(): |
15 """ |
15 """ |
16 Initialize the service and return the entry point. |
16 Initialize the service and return the entry point. |
17 |
17 |
18 @return the entry point for the background client |
18 @return the entry point for the background client |
19 @rtype func |
19 @rtype func |
20 """ |
20 """ |
21 return yamlSyntaxCheck |
21 return yamlSyntaxCheck |
22 |
22 |
23 |
23 |
24 def initBatchService(): |
24 def initBatchService(): |
25 """ |
25 """ |
26 Initialize the batch service and return the entry point. |
26 Initialize the batch service and return the entry point. |
27 |
27 |
28 @return the entry point for the background client |
28 @return the entry point for the background client |
29 @rtype func |
29 @rtype func |
30 """ |
30 """ |
31 return yamlSyntaxBatchCheck |
31 return yamlSyntaxBatchCheck |
32 |
32 |
33 |
33 |
34 def normalizeCode(codestring): |
34 def normalizeCode(codestring): |
35 """ |
35 """ |
36 Function to normalize the given code. |
36 Function to normalize the given code. |
37 |
37 |
38 @param codestring code to be normalized |
38 @param codestring code to be normalized |
39 @type str |
39 @type str |
40 @return normalized code |
40 @return normalized code |
41 @rtype str |
41 @rtype str |
42 """ |
42 """ |
43 codestring = codestring.replace("\r\n", "\n").replace("\r", "\n") |
43 codestring = codestring.replace("\r\n", "\n").replace("\r", "\n") |
44 |
44 |
45 if codestring and codestring[-1] != '\n': |
45 if codestring and codestring[-1] != "\n": |
46 codestring += '\n' |
46 codestring += "\n" |
47 |
47 |
48 return codestring |
48 return codestring |
49 |
49 |
50 |
50 |
51 def yamlSyntaxCheck(file, codestring): |
51 def yamlSyntaxCheck(file, codestring): |
52 """ |
52 """ |
53 Function to check a YAML source file for syntax errors. |
53 Function to check a YAML source file for syntax errors. |
54 |
54 |
55 @param file source filename |
55 @param file source filename |
56 @type str |
56 @type str |
57 @param codestring string containing the code to check |
57 @param codestring string containing the code to check |
58 @type str |
58 @type str |
59 @return dictionary with the keys 'error' and 'warnings' which |
59 @return dictionary with the keys 'error' and 'warnings' which |
66 |
66 |
67 |
67 |
68 def yamlSyntaxBatchCheck(argumentsList, send, fx, cancelled, maxProcesses=0): |
68 def yamlSyntaxBatchCheck(argumentsList, send, fx, cancelled, maxProcesses=0): |
69 """ |
69 """ |
70 Module function to check syntax for a batch of files. |
70 Module function to check syntax for a batch of files. |
71 |
71 |
72 @param argumentsList list of arguments tuples as given for yamlSyntaxCheck |
72 @param argumentsList list of arguments tuples as given for yamlSyntaxCheck |
73 @type list |
73 @type list |
74 @param send reference to send function |
74 @param send reference to send function |
75 @type func |
75 @type func |
76 @param fx registered service name |
76 @param fx registered service name |
100 for task in argumentsList[:initialTasks]: |
100 for task in argumentsList[:initialTasks]: |
101 taskQueue.put(task) |
101 taskQueue.put(task) |
102 |
102 |
103 # Start worker processes |
103 # Start worker processes |
104 workers = [ |
104 workers = [ |
105 multiprocessing.Process( |
105 multiprocessing.Process(target=workerTask, args=(taskQueue, doneQueue)) |
106 target=workerTask, args=(taskQueue, doneQueue) |
106 for _ in range(NumberOfProcesses) |
107 ) for _ in range(NumberOfProcesses) |
|
108 ] |
107 ] |
109 for worker in workers: |
108 for worker in workers: |
110 worker.start() |
109 worker.start() |
111 |
110 |
112 # Get and send results |
111 # Get and send results |
113 endIndex = len(argumentsList) - initialTasks |
112 endIndex = len(argumentsList) - initialTasks |
114 for i in range(len(argumentsList)): |
113 for i in range(len(argumentsList)): |
115 resultSent = False |
114 resultSent = False |
116 wasCancelled = False |
115 wasCancelled = False |
117 |
116 |
118 while not resultSent: |
117 while not resultSent: |
119 try: |
118 try: |
120 # get result (waiting max. 3 seconds and send it to frontend |
119 # get result (waiting max. 3 seconds and send it to frontend |
121 filename, result = doneQueue.get() |
120 filename, result = doneQueue.get() |
122 send(fx, filename, result) |
121 send(fx, filename, result) |
124 except queue.Empty: |
123 except queue.Empty: |
125 # ignore empty queue, just carry on |
124 # ignore empty queue, just carry on |
126 if cancelled(): |
125 if cancelled(): |
127 wasCancelled = True |
126 wasCancelled = True |
128 break |
127 break |
129 |
128 |
130 if wasCancelled or cancelled(): |
129 if wasCancelled or cancelled(): |
131 # just exit the loop ignoring the results of queued tasks |
130 # just exit the loop ignoring the results of queued tasks |
132 break |
131 break |
133 |
132 |
134 if i < endIndex: |
133 if i < endIndex: |
135 taskQueue.put(argumentsList[i + initialTasks]) |
134 taskQueue.put(argumentsList[i + initialTasks]) |
136 |
135 |
137 # Tell child processes to stop |
136 # Tell child processes to stop |
138 for _ in range(NumberOfProcesses): |
137 for _ in range(NumberOfProcesses): |
139 taskQueue.put('STOP') |
138 taskQueue.put("STOP") |
140 |
139 |
141 for worker in workers: |
140 for worker in workers: |
142 worker.join() |
141 worker.join() |
143 worker.close() |
142 worker.close() |
144 |
143 |
145 |
144 |
146 def workerTask(inputQueue, outputQueue): |
145 def workerTask(inputQueue, outputQueue): |
147 """ |
146 """ |
148 Module function acting as the parallel worker for the syntax check. |
147 Module function acting as the parallel worker for the syntax check. |
149 |
148 |
150 @param inputQueue input queue |
149 @param inputQueue input queue |
151 @type multiprocessing.Queue |
150 @type multiprocessing.Queue |
152 @param outputQueue output queue |
151 @param outputQueue output queue |
153 @type multiprocessing.Queue |
152 @type multiprocessing.Queue |
154 """ |
153 """ |
155 for filename, args in iter(inputQueue.get, 'STOP'): |
154 for filename, args in iter(inputQueue.get, "STOP"): |
156 source = args[0] |
155 source = args[0] |
157 result = __yamlSyntaxCheck(filename, source) |
156 result = __yamlSyntaxCheck(filename, source) |
158 outputQueue.put((filename, result)) |
157 outputQueue.put((filename, result)) |
159 |
158 |
160 |
159 |
161 def __yamlSyntaxCheck(file, codestring): |
160 def __yamlSyntaxCheck(file, codestring): |
162 """ |
161 """ |
163 Function to check a YAML source file for syntax errors. |
162 Function to check a YAML source file for syntax errors. |
164 |
163 |
165 @param file source filename |
164 @param file source filename |
166 @type str |
165 @type str |
167 @param codestring string containing the code to check |
166 @param codestring string containing the code to check |
168 @type str |
167 @type str |
169 @return dictionary with the keys 'error' and 'warnings' which |
168 @return dictionary with the keys 'error' and 'warnings' which |
174 """ |
173 """ |
175 try: |
174 try: |
176 from yaml import safe_load_all, MarkedYAMLError |
175 from yaml import safe_load_all, MarkedYAMLError |
177 except ImportError: |
176 except ImportError: |
178 error = "pyyaml not available. Install it via the PyPI interface." |
177 error = "pyyaml not available. Install it via the PyPI interface." |
179 return [{'error': (file, 0, 0, '', error)}] |
178 return [{"error": (file, 0, 0, "", error)}] |
180 |
179 |
181 codestring = normalizeCode(codestring) |
180 codestring = normalizeCode(codestring) |
182 |
181 |
183 try: |
182 try: |
184 for _obj in safe_load_all(codestring): |
183 for _obj in safe_load_all(codestring): |
185 # do nothing with it, just to get parse errors |
184 # do nothing with it, just to get parse errors |
186 pass |
185 pass |
187 except MarkedYAMLError as exc: |
186 except MarkedYAMLError as exc: |
189 line = exc.problem_mark.line + 1 |
188 line = exc.problem_mark.line + 1 |
190 column = exc.problem_mark.column |
189 column = exc.problem_mark.column |
191 else: |
190 else: |
192 line, column = 0, 0 |
191 line, column = 0, 0 |
193 error = exc.problem |
192 error = exc.problem |
194 |
193 |
195 cline = min(len(codestring.splitlines()), int(line)) - 1 |
194 cline = min(len(codestring.splitlines()), int(line)) - 1 |
196 code = codestring.splitlines()[cline] |
195 code = codestring.splitlines()[cline] |
197 |
196 |
198 return [{'error': (file, line, column, code, error)}] |
197 return [{"error": (file, line, column, code, error)}] |
199 |
198 |
200 return [{}] |
199 return [{}] |