Failed Conditions
Pull Request — master (#2076)
by Abdeali
02:04
created

run_global_bears()   B

Complexity

Conditions 4

Size

Total Lines 44

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 4
dl 0
loc 44
rs 8.5806
1
import queue
2
import traceback
3
4
from coalib.bears.BEAR_KIND import BEAR_KIND
5
from coalib.bears.GlobalBear import GlobalBear
6
from coalib.bears.LocalBear import LocalBear
7
from coalib.misc import Constants
8
from coalib.processes.communication.LogMessage import LOG_LEVEL, LogMessage
9
from coalib.processes.CONTROL_ELEMENT import CONTROL_ELEMENT
10
from coalib.results.Result import Result
11
12
13
def send_msg(message_queue, timeout, log_level, *args, delimiter=' ', end=''):
14
    """
15
    Puts message into message queue for a LogPrinter to present to the user.
16
17
    :param message_queue: The queue to put the message into and which the
18
                          LogPrinter reads.
19
    :param timeout:       The queue blocks at most timeout seconds for a free
20
                          slot to execute the put operation on. After the
21
                          timeout it returns queue Full exception.
22
    :param log_level:     The log_level i.e Error,Debug or Warning.It is sent
23
                          to the LogPrinter depending on the message.
24
    :param args:          This includes the elements of the message.
25
    :param delimiter:     It is the value placed between each arg. By default
26
                          it is a ' '.
27
    :param end:           It is the value placed at the end of the message.
28
    """
29
    output = str(delimiter).join(str(arg) for arg in args) + str(end)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable arg does not seem to be defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable args does not seem to be defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable end does not seem to be defined.
Loading history...
30
    message_queue.put(LogMessage(log_level, output),
31
                      timeout=timeout)
32
33
34
def validate_results(message_queue, timeout, result_list, name, args, kwargs):
35
    """
36
    Validates if the result_list passed to it contains valid set of results.
37
    That is the result_list must itself be a list and contain objects of the
38
    instance of Result object. If any irregularity is found a message is put in
39
    the message_queue to present the irregularity to the user. Each result_list
40
    belongs to an execution of a bear.
41
42
    :param message_queue: A queue that contains messages of type
43
                          errors/warnings/debug statements to be printed in the
44
                          Log.
45
    :param timeout:       The queue blocks at most timeout seconds for a free
46
                          slot to execute the put operation on. After the
47
                          timeout it returns queue Full exception.
48
    :param result_list:   The list of results to validate.
49
    :param name:          The name of the bear executed.
50
    :param args:          The args with which the bear was executed.
51
    :param kwargs:        The kwargs with which the bear was executed.
52
    :return:              Returns None if the result_list is invalid. Else it
53
                          returns the result_list itself.
54
    """
55
    if result_list is None:
56
        return None
57
58
    for result in result_list:
59
        if not isinstance(result, Result):
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable Result does not seem to be defined.
Loading history...
60
            send_msg(message_queue,
61
                     timeout,
62
                     LOG_LEVEL.ERROR,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable LOG_LEVEL does not seem to be defined.
Loading history...
63
                     "The results from the bear {bear} could only be "
64
                     "partially processed with arguments {arglist}, "
65
                     "{kwarglist}"
66
                     .format(bear=name, arglist=args, kwarglist=kwargs))
67
            send_msg(message_queue,
68
                     timeout,
69
                     LOG_LEVEL.DEBUG,
70
                     "One of the results in the list for the bear {bear} is "
71
                     "an instance of {ret} but it should be an instance of "
72
                     "Result"
73
                     .format(bear=name, ret=result.__class__))
74
            result_list.remove(result)
75
76
    return result_list
77
78
79
def run_bear(message_queue, timeout, bear_instance, *args, **kwargs):
80
    """
81
    This method is responsible for executing the instance of a bear. It also
82
    reports or logs errors if any occur during the execution of that bear
83
    instance.
84
85
    :param message_queue: A queue that contains messages of type
86
                          errors/warnings/debug statements to be printed in the
87
                          Log.
88
    :param timeout:       The queue blocks at most timeout seconds for a free
89
                          slot to execute the put operation on. After the
90
                          timeout it returns queue Full exception.
91
    :param bear_instance: The instance of the bear to be executed.
92
    :param args:          The arguments that are to be passed to the bear.
93
    :param kwargs:        The keyword arguments that are to be passed to the
94
                          bear.
95
    :return:              Returns a valid list of objects of the type Result
96
                          if the bear executed succesfully. None otherwise.
97
    """
98
    if kwargs.get("dependency_results", True) is None:
99
        del kwargs["dependency_results"]
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable kwargs does not seem to be defined.
Loading history...
100
101
    name = bear_instance.name
102
103
    try:
104
        result_list = bear_instance.execute(*args, **kwargs)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable args does not seem to be defined.
Loading history...
105
    except:
106
        send_msg(message_queue,
107
                 timeout,
108
                 LOG_LEVEL.ERROR,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable LOG_LEVEL does not seem to be defined.
Loading history...
109
                 "The bear {bear} failed to run with the arguments "
110
                 "{arglist}, {kwarglist}. Skipping bear..."
111
                 .format(bear=name, arglist=args, kwarglist=kwargs))
112
        send_msg(message_queue,
113
                 timeout,
114
                 LOG_LEVEL.DEBUG,
115
                 "Traceback for error in bear {bear}:"
116
                 .format(bear=name),
117
                 traceback.format_exc(),
118
                 delimiter="\n")
119
120
        return None
121
122
    return validate_results(message_queue,
123
                            timeout,
124
                            result_list,
125
                            name,
126
                            args,
127
                            kwargs)
128
129
130
def get_local_dependency_results(local_result_list, bear_instance):
131
    """
132
    This method gets all the results originating from the dependencies of a
133
    bear_instance. Each bear_instance may or may not have dependencies.
134
135
    :param local_result_list: The list of results out of which the dependency
136
                              results are picked.
137
    :param bear_instance:     The instance of a local bear to get the
138
                              dependencies from.
139
    :return:                  Return none if there are no dependencies for the
140
                              bear. Else return a dictionary containing
141
                              dependency results.
142
    """
143
    deps = bear_instance.get_dependencies()
144
    if deps == []:
145
        return None
146
147
    dependency_results = {}
148
    dep_strings = []
149
    for dep in deps:
150
        dep_strings.append(dep.__name__)
151
152
    for result in local_result_list:
153
        if result.origin in dep_strings:
154
            results = dependency_results.get(result.origin, [])
155
            results.append(result)
156
            dependency_results[result.origin] = results
157
158
    return dependency_results
159
160
161
def run_local_bear(message_queue,
162
                   timeout,
163
                   local_result_list,
164
                   file_dict,
165
                   bear_instance,
166
                   filename):
167
    """
168
    Runs an instance of a local bear. Checks if bear_instance is of type
169
    LocalBear and then passes it to the run_bear to execute.
170
171
    :param message_queue:     A queue that contains messages of type
172
                              errors/warnings/debug statements to be printed in
173
                              the Log.
174
    :param timeout:           The queue blocks at most timeout seconds for a
175
                              free slot to execute the put operation on. After
176
                              the timeout it returns queue Full exception.
177
    :param local_result_list: Its a list that stores the results of all local
178
                              bears.
179
    :param file_dict:         Dictionary containing contents of file.
180
    :param bear_instance:     Instance of LocalBear the run.
181
    :param filename:          Name of the file to run it on.
182
    :return:                  Returns a list of results generated by the passed
183
                              bear_instance.
184
    """
185
    if (not isinstance(bear_instance, LocalBear) or
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable LocalBear does not seem to be defined.
Loading history...
186
            bear_instance.kind() != BEAR_KIND.LOCAL):
187
        send_msg(message_queue,
188
                 timeout,
189
                 LOG_LEVEL.WARNING,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable LOG_LEVEL does not seem to be defined.
Loading history...
190
                 "A given local bear ({}) is not valid. Leaving "
191
                 "it out...".format(bear_instance.__class__.__name__),
192
                 Constants.THIS_IS_A_BUG)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable Constants does not seem to be defined.
Loading history...
193
194
        return None
195
196
    kwargs = {"dependency_results":
197
              get_local_dependency_results(local_result_list,
198
                                           bear_instance)}
199
    return run_bear(message_queue,
200
                    timeout,
201
                    bear_instance,
202
                    filename,
203
                    file_dict[filename],
204
                    **kwargs)
205
206
207
def run_global_bear(message_queue,
208
                    timeout,
209
                    global_bear_instance,
210
                    dependency_results):
211
    """
212
    Runs an instance of a global bear. Checks if bear_instance is of type
213
    GlobalBear and then passes it to the run_bear to execute.
214
215
    :param message_queue:        A queue that contains messages of type
216
                                 errors/warnings/debug statements to be printed
217
                                 in the Log.
218
    :param timeout:              The queue blocks at most timeout seconds for a
219
                                 free slot to execute the put operation on.
220
                                 After the timeout it returns queue Full
221
                                 exception.
222
    :param global_bear_instance: Instance of GlobalBear to run.
223
    :param dependency_results:   The results of all the bears on which the
224
                                 instance of the passed bear to be run depends
225
                                 on.
226
    :return:                     Returns a list of results generated by the
227
                                 passed bear_instance.
228
    """
229
    if (not isinstance(global_bear_instance, GlobalBear)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable GlobalBear does not seem to be defined.
Loading history...
230
            or global_bear_instance.kind() != BEAR_KIND.GLOBAL):
231
        send_msg(message_queue,
232
                 timeout,
233
                 LOG_LEVEL.WARNING,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable LOG_LEVEL does not seem to be defined.
Loading history...
234
                 "A given global bear ({}) is not valid. Leaving it "
235
                 "out..."
236
                 .format(global_bear_instance.__class__.__name__),
237
                 Constants.THIS_IS_A_BUG)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable Constants does not seem to be defined.
Loading history...
238
239
        return None
240
241
    kwargs = {"dependency_results": dependency_results}
242
    return run_bear(message_queue,
243
                    timeout,
244
                    global_bear_instance,
245
                    **kwargs)
246
247
248
def run_local_bears_on_file(message_queue,
249
                            timeout,
250
                            file_dict,
251
                            local_bear_list,
252
                            local_result_dict,
253
                            control_queue,
254
                            filename):
255
    """
256
    This method runs a list of local bears on one file.
257
258
    :param message_queue:     A queue that contains messages of type
259
                              errors/warnings/debug statements to be printed
260
                              in the Log.
261
    :param timeout:           The queue blocks at most timeout seconds for a
262
                              free slot to execute the put operation on. After
263
                              the timeout it returns queue Full exception.
264
    :param file_dict:         Dictionary that contains contents of files.
265
    :param local_bear_list:   List of local bears to run on file.
266
    :param local_result_dict: A Manager.dict that will be used to store local
267
                              bear results. A list of all local bear results
268
                              will be stored with the filename as key.
269
    :param control_queue:     If any result gets written to the result_dict a
270
                              tuple containing a CONTROL_ELEMENT (to indicate
271
                              what kind of event happened) and either a bear
272
                              name(for global results) or a file name to
273
                              indicate the result will be put to the queue.
274
    :param filename:          The name of file on which to run the bears.
275
    """
276
    if filename not in file_dict:
277
        send_msg(message_queue,
278
                 timeout,
279
                 LOG_LEVEL.ERROR,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable LOG_LEVEL does not seem to be defined.
Loading history...
280
                 "An internal error occurred.",
281
                 Constants.THIS_IS_A_BUG)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable Constants does not seem to be defined.
Loading history...
282
        send_msg(message_queue,
283
                 timeout,
284
                 LOG_LEVEL.DEBUG,
285
                 "The given file through the queue is not in the file "
286
                 "dictionary.")
287
288
        return
289
290
    local_result_list = []
291
    for bear_instance in local_bear_list:
292
        result = run_local_bear(message_queue,
293
                                timeout,
294
                                local_result_list,
295
                                file_dict,
296
                                bear_instance,
297
                                filename)
298
        if result is not None:
299
            local_result_list.extend(result)
300
301
    local_result_dict[filename] = local_result_list
302
    control_queue.put((CONTROL_ELEMENT.LOCAL, filename))
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable CONTROL_ELEMENT does not seem to be defined.
Loading history...
303
304
305
def get_global_dependency_results(global_result_dict, bear_instance):
306
    """
307
    This method gets all the results originating from the dependencies of a
308
    bear_instance. Each bear_instance may or may not have dependencies.
309
310
    :param global_result_dict: The list of results out of which the dependency
311
                               results are picked.
312
    :return:                   None if bear has no dependencies, False if
313
                               dependencies are not met, the dependency dict
314
                               otherwise.
315
    """
316
    try:
317
        deps = bear_instance.get_dependencies()
318
        if deps == []:
319
            return None
320
    except AttributeError:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable AttributeError does not seem to be defined.
Loading history...
321
        # When this occurs we have an invalid bear and a warning will be
322
        # emitted later.
323
        return None
324
325
    dependency_results = {}
326
    for dep in deps:
327
        depname = dep.__name__
328
        if depname not in global_result_dict:
329
            return False
330
331
        dependency_results[depname] = global_result_dict[depname]
332
333
    return dependency_results
334
335
336
def get_next_global_bear(timeout,
337
                         global_bear_queue,
338
                         global_bear_list,
339
                         global_result_dict):
340
    """
341
    Retrieves the next global bear.
342
343
    :param timeout:            The queue blocks at most timeout seconds for a
344
                               free slot to execute the put operation on. After
345
                               the timeout it returns queue Full exception.
346
    :param global_bear_queue:  queue (read, write) of indexes of global bear
347
                               instances in the global_bear_list.
348
    :param global_bear_list:   A list containing all global bears to be
349
                               executed.
350
    :param global_result_dict: A Manager.dict that will be used to store global
351
                               results. The list of results of one global bear
352
                               will be stored with the bear name as key.
353
    :return:                   (bear, bearname, dependency_results)
354
    """
355
    dependency_results = False
356
357
    while dependency_results is False:
358
        bear_id = global_bear_queue.get(timeout=timeout)
359
        bear = global_bear_list[bear_id]
360
361
        dependency_results = (
362
            get_global_dependency_results(global_result_dict, bear))
363
        if dependency_results is False:
364
            global_bear_queue.put(bear_id)
365
366
    return bear, dependency_results
0 ignored issues
show
introduced by
The variable bear does not seem to be defined in case the while loop on line 357 is not entered. Are you sure this can never be the case?
Loading history...
367
368
369
def task_done(obj):
370
    """
371
    Invokes task_done if the given queue provides this operation. Otherwise
372
    passes silently.
373
374
    :param obj: Any object.
375
    """
376
    if hasattr(obj, "task_done"):
377
        obj.task_done()
378
379
380
def run_local_bears(filename_queue,
381
                    message_queue,
382
                    timeout,
383
                    file_dict,
384
                    local_bear_list,
385
                    local_result_dict,
386
                    control_queue):
387
    """
388
    Run local bears on all the files given.
389
390
    :param filename_queue:    queue (read) of file names to check with
391
                              local bears.
392
    :param message_queue:     A queue that contains messages of type
393
                              errors/warnings/debug statements to be printed
394
                              in the Log.
395
    :param timeout:           The queue blocks at most timeout seconds for a
396
                              free slot to execute the put operation on. After
397
                              the timeout it returns queue Full exception.
398
    :param file_dict:         Dictionary that contains contents of files.
399
    :param local_bear_list:   List of local bears to run.
400
    :param local_result_dict: A Manager.dict that will be used to store local
401
                              bear results. A list of all local bear results
402
                              will be stored with the filename as key.
403
    :param control_queue:     If any result gets written to the result_dict a
404
                              tuple containing a CONTROL_ELEMENT (to indicate
405
                              what kind of event happened) and either a bear
406
                              name(for global results) or a file name to
407
                              indicate the result will be put to the queue.
408
    """
409
    try:
410
        while True:
411
            filename = filename_queue.get(timeout=timeout)
412
            run_local_bears_on_file(message_queue,
413
                                    timeout,
414
                                    file_dict,
415
                                    local_bear_list,
416
                                    local_result_dict,
417
                                    control_queue,
418
                                    filename)
419
            task_done(filename_queue)
420
    except queue.Empty:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable queue does not seem to be defined.
Loading history...
421
        return
422
423
424
def run_global_bears(message_queue,
425
                     timeout,
426
                     global_bear_queue,
427
                     global_bear_list,
428
                     global_result_dict,
429
                     control_queue):
430
    """
431
    Run all global bears.
432
433
    :param message_queue:      A queue that contains messages of type
434
                               errors/warnings/debug statements to be printed
435
                               in the Log.
436
    :param timeout:            The queue blocks at most timeout seconds for a
437
                               free slot to execute the put operation on. After
438
                               the timeout it returns queue Full exception.
439
    :param global_bear_queue:  queue (read, write) of indexes of global bear
440
                               instances in the global_bear_list.
441
    :param global_bear_list:   list of global bear instances
442
    :param global_result_dict: A Manager.dict that will be used to store global
443
                               results. The list of results of one global bear
444
                               will be stored with the bear name as key.
445
    :param control_queue:      If any result gets written to the result_dict a
446
                               tuple containing a CONTROL_ELEMENT (to indicate
447
                               what kind of event happened) and either a bear
448
                               name(for global results) or a file name to
449
                               indicate the result will be put to the queue.
450
    """
451
    try:
452
        while True:
453
            bear, dep_results = (
454
                get_next_global_bear(timeout,
455
                                     global_bear_queue,
456
                                     global_bear_list,
457
                                     global_result_dict))
458
            bearname = bear.__class__.__name__
459
            result = run_global_bear(message_queue, timeout, bear, dep_results)
460
            if result:
461
                global_result_dict[bearname] = result
462
                control_queue.put((CONTROL_ELEMENT.GLOBAL, bearname))
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable CONTROL_ELEMENT does not seem to be defined.
Loading history...
463
            else:
464
                global_result_dict[bearname] = None
465
            task_done(global_bear_queue)
466
    except queue.Empty:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable queue does not seem to be defined.
Loading history...
467
        return
468
469
470
def run(file_name_queue,
471
        local_bear_list,
472
        global_bear_list,
473
        global_bear_queue,
474
        file_dict,
475
        local_result_dict,
476
        global_result_dict,
477
        message_queue,
478
        control_queue,
479
        timeout=0):
480
    """
481
    This is the method that is actually runs by processes.
482
483
    If parameters type is 'queue (read)' this means it has to implement the
484
    get(timeout=TIMEOUT) method and it shall raise queue.Empty if the queue
485
    is empty up until the end of the timeout. If the queue has the
486
    (optional!) task_done() attribute, the run method will call it after
487
    processing each item.
488
489
    If parameters type is 'queue (write)' it shall implement the
490
    put(object, timeout=TIMEOUT) method.
491
492
    If the queues raise any exception not specified here the user will get
493
    an 'unknown error' message. So beware of that.
494
495
    :param file_name_queue:    queue (read) of file names to check with local
496
                               bears. Each invocation of the run method needs
497
                               one such queue which it checks with all the
498
                               local bears. The queue could be empty.
499
                               (Repeat until queue empty.)
500
    :param local_bear_list:    List of local bear instances.
501
    :param global_bear_list:   List of global bear instances.
502
    :param global_bear_queue:  queue (read, write) of indexes of global bear
503
                               instances in the global_bear_list.
504
    :param file_dict:          dict of all files as {filename:file}, file as in
505
                               file.readlines().
506
    :param local_result_dict:  A Manager.dict that will be used to store local
507
                               results. A list of all local results.
508
                               will be stored with the filename as key.
509
    :param global_result_dict: A Manager.dict that will be used to store global
510
                               results. The list of results of one global bear
511
                               will be stored with the bear name as key.
512
    :param message_queue:      queue (write) for debug/warning/error
513
                               messages (type LogMessage)
514
    :param control_queue:      queue (write). If any result gets written to the
515
                               result_dict a tuple containing a CONTROL_ELEMENT
516
                               (to indicate what kind of event happened) and
517
                               either a bear name (for global results) or a
518
                               file name to indicate the result will be put to
519
                               the queue. If the run method finished all its
520
                               local bears it will put
521
                               (CONTROL_ELEMENT.LOCAL_FINISHED, None) to the
522
                               queue, if it finished all global ones,
523
                               (CONTROL_ELEMENT.GLOBAL_FINISHED, None) will
524
                               be put there.
525
    :param timeout:            The queue blocks at most timeout seconds for a
526
                               free slot to execute the put operation on. After
527
                               the timeout it returns queue Full exception.
528
    """
529
    try:
530
        run_local_bears(file_name_queue,
531
                        message_queue,
532
                        timeout,
533
                        file_dict,
534
                        local_bear_list,
535
                        local_result_dict,
536
                        control_queue)
537
        control_queue.put((CONTROL_ELEMENT.LOCAL_FINISHED, None))
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable CONTROL_ELEMENT does not seem to be defined.
Loading history...
538
539
        run_global_bears(message_queue,
540
                         timeout,
541
                         global_bear_queue,
542
                         global_bear_list,
543
                         global_result_dict,
544
                         control_queue)
545
        control_queue.put((CONTROL_ELEMENT.GLOBAL_FINISHED, None))
546
    except (OSError, KeyboardInterrupt):  # pragma: no cover
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable KeyboardInterrupt does not seem to be defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable OSError does not seem to be defined.
Loading history...
547
        pass
548