1 | try: |
||
2 | # This import has side effects and is needed to make input() behave nicely |
||
3 | import readline # pylint: disable=unused-import |
||
4 | except ImportError: # pragma: no cover |
||
5 | pass |
||
6 | import os.path |
||
7 | |||
8 | from pyprint.ConsolePrinter import ConsolePrinter |
||
9 | |||
10 | from coalib.misc.DictUtilities import inverse_dicts |
||
11 | from coalib.bearlib.spacing.SpacingHelper import SpacingHelper |
||
12 | from coalib.output.printers.LOG_LEVEL import LOG_LEVEL |
||
13 | from coalib.results.Result import Result |
||
14 | from coalib.results.result_actions.ApplyPatchAction import ApplyPatchAction |
||
15 | from coalib.results.result_actions.OpenEditorAction import OpenEditorAction |
||
16 | from coalib.results.result_actions.PrintDebugMessageAction import ( |
||
17 | PrintDebugMessageAction) |
||
18 | from coalib.results.result_actions.ShowPatchAction import ShowPatchAction |
||
19 | from coalib.results.RESULT_SEVERITY import ( |
||
20 | RESULT_SEVERITY, RESULT_SEVERITY_COLORS) |
||
21 | from coalib.settings.Setting import Setting |
||
22 | |||
23 | STR_GET_VAL_FOR_SETTING = ("Please enter a value for the setting \"{}\" ({}) " |
||
24 | "needed by {}: ") |
||
25 | STR_LINE_DOESNT_EXIST = ("The line belonging to the following result " |
||
26 | "cannot be printed because it refers to a line " |
||
27 | "that doesn't seem to exist in the given file.") |
||
28 | STR_PROJECT_WIDE = "Project wide:" |
||
29 | FILE_NAME_COLOR = "blue" |
||
30 | FILE_LINES_COLOR = "blue" |
||
31 | HIGHLIGHTED_CODE_COLOR = 'red' |
||
32 | SUCCESS_COLOR = 'green' |
||
33 | CLI_ACTIONS = [OpenEditorAction(), |
||
34 | ApplyPatchAction(), |
||
35 | PrintDebugMessageAction(), |
||
36 | ShowPatchAction()] |
||
37 | |||
38 | |||
39 | def format_lines(lines, line_nr=""): |
||
40 | return '\n'.join("|{:>4}| {}".format(line_nr, line) |
||
41 | for line in lines.rstrip("\n").split('\n')) |
||
42 | |||
43 | |||
44 | def print_section_beginning(console_printer, section): |
||
45 | """ |
||
46 | Will be called after initialization current_section in |
||
47 | begin_section() |
||
48 | |||
49 | :param console_printer: Object to print messages on the console. |
||
50 | :param section: The section that will get executed now. |
||
51 | """ |
||
52 | console_printer.print("Executing section {name}...".format( |
||
53 | name=section.name)) |
||
54 | |||
55 | |||
56 | def nothing_done(log_printer): |
||
57 | """ |
||
58 | Will be called after processing a coafile when nothing had to be done, |
||
59 | i.e. no section was enabled/targeted. |
||
60 | |||
61 | :param log_printer: A LogPrinter object. |
||
62 | """ |
||
63 | log_printer.warn("No existent section was targeted or enabled. " |
||
64 | "Nothing to do.") |
||
65 | |||
66 | |||
67 | def acquire_actions_and_apply(console_printer, |
||
68 | log_printer, |
||
69 | section, |
||
70 | file_diff_dict, |
||
71 | result, |
||
72 | file_dict, |
||
73 | cli_actions=None): |
||
74 | """ |
||
75 | Acquires applicable actions and applies them. |
||
76 | |||
77 | :param console_printer: Object to print messages on the console. |
||
78 | :param log_printer: Printer responsible for logging the messages. |
||
79 | :param section: Name of section to which the result belongs. |
||
80 | :param file_diff_dict: Dictionary containing filenames as keys and Diff |
||
81 | objects as values. |
||
82 | :param result: A derivative of Result. |
||
83 | :param file_dict: A dictionary containing all files with filename as |
||
84 | key. |
||
85 | :param cli_actions: The list of cli actions available. |
||
86 | """ |
||
87 | cli_actions = cli_actions or CLI_ACTIONS |
||
88 | failed_actions = set() |
||
89 | while True: |
||
90 | actions = [] |
||
91 | for action in cli_actions: |
||
92 | if action.is_applicable(result, file_dict, file_diff_dict): |
||
93 | actions.append(action) |
||
94 | |||
95 | if actions == []: |
||
96 | return |
||
97 | |||
98 | action_dict = {} |
||
99 | metadata_list = [] |
||
100 | for action in actions: |
||
101 | metadata = action.get_metadata() |
||
102 | action_dict[metadata.name] = action |
||
103 | metadata_list.append(metadata) |
||
104 | |||
105 | # User can always choose no action which is guaranteed to succeed |
||
106 | if not ask_for_action_and_apply(log_printer, |
||
107 | console_printer, |
||
108 | section, |
||
109 | metadata_list, |
||
110 | action_dict, |
||
111 | failed_actions, |
||
112 | result, |
||
113 | file_diff_dict, |
||
114 | file_dict): |
||
115 | break |
||
116 | |||
117 | |||
118 | def print_spaces_tabs_in_unicode(console_printer, line, tab_dict, |
||
119 | color, index=0): |
||
120 | """ |
||
121 | Prints the lines with tabs and spaces replaced by unicode symbols. |
||
122 | |||
123 | :param console_printer: The ``Printer`` object to print to. |
||
124 | :param line: The line-text to print to ``console_printer``. |
||
125 | :param tab_dict: A dictionary containing the indices of tabs inside |
||
126 | ``line`` as keys and the tab-length as values. |
||
127 | :param color: The color to print the line with (except for spaces |
||
128 | and tabs. |
||
129 | :param index: The index from where to start the printing. |
||
130 | """ |
||
131 | for char in line: |
||
132 | if char == " ": |
||
133 | try: |
||
134 | console_printer.print("•", color='cyan', end='') |
||
135 | except UnicodeEncodeError: |
||
136 | console_printer.print(".", color='cyan', end='') |
||
137 | elif char == '\t' and tab_dict: |
||
138 | tab_count = tab_dict[index] |
||
139 | console_printer.print( |
||
140 | '-'*(tab_count-1) + '>', color='cyan', end='') |
||
141 | else: |
||
142 | console_printer.print(char, color=color, end='') |
||
143 | index += 1 |
||
144 | |||
145 | |||
146 | def print_lines(console_printer, |
||
147 | file_dict, |
||
148 | section, |
||
149 | sourcerange): |
||
150 | """ |
||
151 | Prints the lines between the current and the result line. If needed |
||
152 | they will be shortened. |
||
153 | |||
154 | :param console_printer: Object to print messages on the console. |
||
155 | :param file_dict: A dictionary containing all files as values with |
||
156 | filenames as key. |
||
157 | :param sourcerange: The SourceRange object referring to the related |
||
158 | lines to print. |
||
159 | """ |
||
160 | for i in range(sourcerange.start.line, sourcerange.end.line + 1): |
||
161 | console_printer.print(format_lines(lines='', line_nr=i), |
||
162 | color=FILE_LINES_COLOR, |
||
163 | end='') |
||
164 | line = file_dict[sourcerange.file][i - 1].rstrip("\n") |
||
165 | tab_width = int(section.get('tab_width', 4)) |
||
166 | s = SpacingHelper(tab_width) |
||
167 | tab_dict = dict(s.yield_tab_lengths(line)) |
||
168 | printed_chars = 0 |
||
169 | if i == sourcerange.start.line and sourcerange.start.column: |
||
170 | print_spaces_tabs_in_unicode( |
||
171 | console_printer, line[:sourcerange.start.column-1], |
||
172 | tab_dict, FILE_LINES_COLOR) |
||
173 | |||
174 | printed_chars = sourcerange.start.column-1 |
||
175 | |||
176 | if i == sourcerange.end.line and sourcerange.end.column: |
||
177 | print_spaces_tabs_in_unicode( |
||
178 | console_printer, line[printed_chars:sourcerange.end.column-1], |
||
179 | tab_dict, HIGHLIGHTED_CODE_COLOR, printed_chars) |
||
180 | |||
181 | print_spaces_tabs_in_unicode( |
||
182 | console_printer, line[sourcerange.end.column-1:], |
||
183 | tab_dict, FILE_LINES_COLOR, sourcerange.end.column) |
||
184 | console_printer.print("") |
||
185 | else: |
||
186 | print_spaces_tabs_in_unicode( |
||
187 | console_printer, line[printed_chars:], tab_dict, |
||
188 | HIGHLIGHTED_CODE_COLOR, printed_chars) |
||
189 | console_printer.print("") |
||
190 | |||
191 | |||
192 | def print_result(console_printer, |
||
193 | log_printer, |
||
194 | section, |
||
195 | file_diff_dict, |
||
196 | result, |
||
197 | file_dict, |
||
198 | interactive=True): |
||
199 | """ |
||
200 | Prints the result to console. |
||
201 | |||
202 | :param console_printer: Object to print messages on the console. |
||
203 | :param log_printer: Printer responsible for logging the messages. |
||
204 | :param section: Name of section to which the result belongs. |
||
205 | :param file_diff_dict: Dictionary containing filenames as keys and Diff |
||
206 | objects as values. |
||
207 | :param result: A derivative of Result. |
||
208 | :param file_dict: A dictionary containing all files with filename as |
||
209 | key. |
||
210 | :interactive: Variable to check wether or not to |
||
211 | offer the user actions interactively. |
||
212 | """ |
||
213 | if not isinstance(result, Result): |
||
214 | log_printer.warn("One of the results can not be printed since it is " |
||
215 | "not a valid derivative of the coala result " |
||
216 | "class.") |
||
217 | return |
||
218 | |||
219 | console_printer.print(format_lines("[{sev}] {bear}:".format( |
||
220 | sev=RESULT_SEVERITY.__str__(result.severity), bear=result.origin)), |
||
221 | color=RESULT_SEVERITY_COLORS[result.severity]) |
||
222 | console_printer.print(format_lines(result.message), delimiter="\n") |
||
223 | |||
224 | if interactive: |
||
225 | acquire_actions_and_apply(console_printer, |
||
226 | log_printer, |
||
227 | section, |
||
228 | file_diff_dict, |
||
229 | result, |
||
230 | file_dict) |
||
231 | |||
232 | |||
233 | def print_results_formatted(log_printer, |
||
234 | section, |
||
235 | result_list, |
||
236 | *args): |
||
237 | format_str = str(section.get( |
||
238 | "format_str", |
||
239 | "id:{id}:origin:{origin}:file:{file}:line:{line}:column:" |
||
240 | "{column}:end_line:{end_line}:end_column:{end_column}:severity:" |
||
241 | "{severity}:severity_str:{severity_str}:message:{message}")) |
||
242 | for result in result_list: |
||
243 | severity_str = RESULT_SEVERITY.__str__(result.severity) |
||
244 | try: |
||
245 | if len(result.affected_code) == 0: |
||
246 | print(format_str.format(file=None, |
||
247 | line=None, |
||
248 | end_line=None, |
||
249 | column=None, |
||
250 | end_column=None, |
||
251 | severity_str=severity_str, |
||
252 | **result.__dict__)) |
||
253 | continue |
||
254 | |||
255 | for range in result.affected_code: |
||
256 | print(format_str.format(file=range.start.file, |
||
257 | line=range.start.line, |
||
258 | end_line=range.end.line, |
||
259 | column=range.start.column, |
||
260 | end_column=range.end.column, |
||
261 | severity_str=severity_str, |
||
262 | **result.__dict__)) |
||
263 | except KeyError as exception: |
||
264 | log_printer.log_exception( |
||
265 | "Unable to print the result with the given format string.", |
||
266 | exception) |
||
267 | |||
268 | |||
269 | def print_affected_files(console_printer, |
||
270 | log_printer, |
||
271 | section, |
||
272 | result, |
||
273 | file_dict, |
||
274 | color=True): |
||
275 | """ |
||
276 | Print all the afected files and affected lines within them. |
||
277 | |||
278 | :param console_printer: Object to print messages on the console. |
||
279 | :param log_printer: Printer responsible for logging the messages. |
||
280 | :param section: The section to which the results belong to. |
||
281 | :param result_list: List containing the results |
||
282 | :param file_dict: A dictionary containing all files with filename as |
||
283 | key. |
||
284 | :param color: Boolean variable to print the results in color or |
||
285 | not. Can be used for testing. |
||
286 | """ |
||
287 | if len(result.affected_code) == 0: |
||
288 | console_printer.print("\n" + STR_PROJECT_WIDE, |
||
289 | color=FILE_NAME_COLOR) |
||
290 | else: |
||
291 | for sourcerange in result.affected_code: |
||
292 | if ( |
||
293 | sourcerange.file is not None and |
||
294 | sourcerange.file not in file_dict): |
||
295 | log_printer.warn("The context for the result ({}) cannot " |
||
296 | "be printed because it refers to a file " |
||
297 | "that doesn't seem to exist ({})" |
||
298 | ".".format(str(result), sourcerange.file)) |
||
299 | else: |
||
300 | print_affected_lines(console_printer, |
||
301 | file_dict, |
||
302 | section, |
||
303 | sourcerange) |
||
304 | |||
305 | |||
306 | def print_results_no_input(log_printer, |
||
307 | section, |
||
308 | result_list, |
||
309 | file_dict, |
||
310 | file_diff_dict, |
||
311 | color=True): |
||
312 | """ |
||
313 | Print all non interactive results in a section |
||
314 | |||
315 | :param log_printer: Printer responsible for logging the messages. |
||
316 | :param section: The section to which the results belong to. |
||
317 | :param result_list: List containing the results |
||
318 | :param file_dict: A dictionary containing all files with filename as |
||
319 | key. |
||
320 | :param file_diff_dict: A dictionary that contains filenames as keys and |
||
321 | diff objects as values. |
||
322 | :param color: Boolean variable to print the results in color or |
||
323 | not. Can be used for testing. |
||
324 | """ |
||
325 | console_printer = ConsolePrinter(print_colored=color) |
||
326 | for result in result_list: |
||
327 | |||
328 | print_affected_files(console_printer, |
||
329 | log_printer, |
||
330 | section, |
||
331 | result, |
||
332 | file_dict, |
||
333 | color=color) |
||
334 | |||
335 | print_result(console_printer, |
||
336 | log_printer, |
||
337 | section, |
||
338 | file_diff_dict, |
||
339 | result, |
||
340 | file_dict, |
||
341 | interactive=False) |
||
342 | |||
343 | |||
344 | def print_results(log_printer, |
||
345 | section, |
||
346 | result_list, |
||
347 | file_dict, |
||
348 | file_diff_dict, |
||
349 | color=True): |
||
350 | """ |
||
351 | Print all the results in a section. |
||
352 | |||
353 | :param log_printer: Printer responsible for logging the messages. |
||
354 | :param section: The section to which the results belong to. |
||
355 | :param result_list: List containing the results |
||
356 | :param file_dict: A dictionary containing all files with filename as |
||
357 | key. |
||
358 | :param file_diff_dict: A dictionary that contains filenames as keys and |
||
359 | diff objects as values. |
||
360 | :param color: Boolean variable to print the results in color or |
||
361 | not. Can be used for testing. |
||
362 | """ |
||
363 | console_printer = ConsolePrinter(print_colored=color) |
||
364 | |||
365 | for result in sorted(result_list): |
||
366 | |||
367 | print_affected_files(console_printer, |
||
368 | log_printer, |
||
369 | section, |
||
370 | result, |
||
371 | file_dict, |
||
372 | color=color) |
||
373 | |||
374 | print_result(console_printer, |
||
375 | log_printer, |
||
376 | section, |
||
377 | file_diff_dict, |
||
378 | result, |
||
379 | file_dict) |
||
380 | |||
381 | |||
382 | def print_affected_lines(console_printer, file_dict, section, sourcerange): |
||
383 | console_printer.print("\n" + os.path.relpath(sourcerange.file), |
||
384 | color=FILE_NAME_COLOR) |
||
385 | |||
386 | if sourcerange.start.line is not None: |
||
387 | if len(file_dict[sourcerange.file]) < sourcerange.end.line: |
||
388 | console_printer.print(format_lines(lines=STR_LINE_DOESNT_EXIST)) |
||
389 | else: |
||
390 | print_lines(console_printer, |
||
391 | file_dict, |
||
392 | section, |
||
393 | sourcerange) |
||
394 | |||
395 | |||
396 | def require_setting(log_printer, setting_name, arr): |
||
397 | """ |
||
398 | This method is responsible for prompting a user about a missing setting and |
||
399 | taking its value as input from the user. |
||
400 | |||
401 | :param log_printer: Printer responsible for logging the messages. |
||
402 | :param setting_name: Name od the setting missing |
||
403 | :param arr: a list containing a description in [0] and the name |
||
404 | of the bears who need this setting in [1] and |
||
405 | following. |
||
406 | """ |
||
407 | if not isinstance(arr, list) or len(arr) < 2: |
||
408 | log_printer.log(LOG_LEVEL.WARNING, |
||
409 | "One of the given settings ({}) is not properly " |
||
410 | "described.".format(str(setting_name))) |
||
411 | |||
412 | return None |
||
413 | |||
414 | if len(arr) == 2: |
||
415 | needed = arr[1] |
||
416 | else: |
||
417 | needed = ", ".join(arr[1:-1]) + " and " + arr[-1] |
||
418 | |||
419 | return input(STR_GET_VAL_FOR_SETTING.format(str(setting_name), |
||
420 | str(arr[0]), |
||
421 | needed)) |
||
422 | |||
423 | |||
424 | def acquire_settings(log_printer, settings_names_dict): |
||
425 | """ |
||
426 | This method prompts the user for the given settings. |
||
427 | |||
428 | :param log_printer: Printer responsible for logging the messages. |
||
429 | :param settings: a dictionary with the settings name as key and a list |
||
430 | containing a description in [0] and the name of the |
||
431 | bears who need this setting in [1] and following. |
||
432 | |||
433 | Example: |
||
434 | |||
435 | :: |
||
436 | |||
437 | {"UseTabs": ["describes whether tabs should be used instead of spaces", |
||
438 | "SpaceConsistencyBear", |
||
439 | "SomeOtherBear"]} |
||
440 | |||
441 | :return: a dictionary with the settings name as key and the |
||
442 | given value as value. |
||
443 | """ |
||
444 | if not isinstance(settings_names_dict, dict): |
||
445 | raise TypeError("The settings_names_dict parameter has to be a " |
||
446 | "dictionary.") |
||
447 | |||
448 | result = {} |
||
449 | for setting_name, arr in settings_names_dict.items(): |
||
450 | value = require_setting(log_printer, setting_name, arr) |
||
451 | if value is not None: |
||
452 | result[setting_name] = value |
||
453 | |||
454 | return result |
||
455 | |||
456 | |||
457 | def get_action_info(section, action, failed_actions): |
||
458 | """ |
||
459 | Get all the required Settings for an action. It updates the section with |
||
460 | the Settings. |
||
461 | |||
462 | :param section: The section the action corresponds to. |
||
463 | :param action: The action to get the info for. |
||
464 | :param failed_actions: A set of all actions that have failed. A failed |
||
465 | action remains in the list until it is successfully |
||
466 | executed. |
||
467 | :return: Action name and the updated section. |
||
468 | """ |
||
469 | params = action.non_optional_params |
||
470 | |||
471 | if section is None: |
||
472 | raise ValueError("section has to be intializied.") |
||
473 | |||
474 | for param_name in params: |
||
475 | if param_name not in section or action.name in failed_actions: |
||
476 | question = format_lines( |
||
477 | "Please enter a value for the parameter '{}' ({}): " |
||
478 | .format(param_name, params[param_name][0])) |
||
479 | section.append(Setting(param_name, input(question))) |
||
480 | |||
481 | return action.name, section |
||
482 | |||
483 | |||
484 | def choose_action(console_printer, actions): |
||
485 | """ |
||
486 | Presents the actions available to the user and takes as input the action |
||
487 | the user wants to choose. |
||
488 | |||
489 | :param console_printer: Object to print messages on the console. |
||
490 | :param actions: Actions available to the user. |
||
491 | :return: Return choice of action of user. |
||
492 | """ |
||
493 | console_printer.print(format_lines( |
||
494 | "The following actions are applicable to this result:")) |
||
495 | |||
496 | while True: |
||
497 | console_printer.print(format_lines(" 0: " + |
||
498 | "Apply no further actions.")) |
||
499 | for i, action in enumerate(actions, 1): |
||
500 | console_printer.print(format_lines("{:>2}: {}".format( |
||
501 | i, |
||
502 | action.desc))) |
||
503 | |||
504 | try: |
||
505 | line = format_lines("Please enter the number of the action " |
||
506 | "you want to execute. ") |
||
507 | choice = int(input(line)) |
||
508 | if 0 <= choice <= len(actions): |
||
509 | return choice |
||
510 | except ValueError: |
||
511 | pass |
||
512 | |||
513 | console_printer.print(format_lines("Please enter a valid number.")) |
||
514 | |||
515 | |||
516 | def print_actions(console_printer, section, actions, failed_actions): |
||
517 | """ |
||
518 | Prints the given actions and lets the user choose. |
||
519 | |||
520 | :param console_printer: Object to print messages on the console. |
||
521 | :param actions: A list of FunctionMetadata objects. |
||
522 | :param failed_actions: A set of all actions that have failed. A failed |
||
523 | action remains in the list until it is |
||
524 | successfully executed. |
||
525 | :return: A touple with the name member of the |
||
526 | FunctionMetadata object chosen by the user |
||
527 | and a Section containing at least all needed |
||
528 | values for the action. If the user did |
||
529 | choose to do nothing, return (None, None). |
||
530 | """ |
||
531 | choice = choose_action(console_printer, actions) |
||
532 | |||
533 | if choice == 0: |
||
534 | return None, None |
||
535 | |||
536 | return get_action_info(section, actions[choice - 1], failed_actions) |
||
537 | |||
538 | |||
539 | def ask_for_action_and_apply(log_printer, |
||
540 | console_printer, |
||
541 | section, |
||
542 | metadata_list, |
||
543 | action_dict, |
||
544 | failed_actions, |
||
545 | result, |
||
546 | file_diff_dict, |
||
547 | file_dict): |
||
548 | """ |
||
549 | Asks the user for an action and applies it. |
||
550 | |||
551 | :param log_printer: Printer responsible for logging the messages. |
||
552 | :param console_printer: Object to print messages on the console. |
||
553 | :param section: Currently active section. |
||
554 | :param metadata_list: Contains metadata for all the actions. |
||
555 | :param action_dict: Contains the action names as keys and their |
||
556 | references as values. |
||
557 | :param failed_actions: A set of all actions that have failed. A failed |
||
558 | action remains in the list until it is successfully |
||
559 | executed. |
||
560 | :param result: Result corresponding to the actions. |
||
561 | :param file_diff_dict: If its an action which applies a patch, this |
||
562 | contains the diff of the patch to be applied to |
||
563 | the file with filename as keys. |
||
564 | :param file_dict: Dictionary with filename as keys and its contents |
||
565 | as values. |
||
566 | :return: Returns a boolean value. True will be returned, if |
||
567 | it makes sense that the user may choose to execute |
||
568 | another action, False otherwise. |
||
569 | """ |
||
570 | action_name, section = print_actions(console_printer, section, |
||
571 | metadata_list, failed_actions) |
||
572 | if action_name is None: |
||
573 | return False |
||
574 | |||
575 | chosen_action = action_dict[action_name] |
||
576 | try: |
||
577 | chosen_action.apply_from_section(result, |
||
578 | file_dict, |
||
579 | file_diff_dict, |
||
580 | section) |
||
581 | console_printer.print( |
||
582 | format_lines(chosen_action.success_message), |
||
583 | color=SUCCESS_COLOR) |
||
584 | failed_actions.discard(action_name) |
||
585 | except Exception as exception: # pylint: disable=broad-except |
||
586 | log_printer.log_exception("Failed to execute the action " |
||
587 | "{} with error: {}.".format(action_name, |
||
588 | exception), |
||
589 | exception) |
||
590 | failed_actions.add(action_name) |
||
591 | return True |
||
592 | |||
593 | |||
594 | def show_enumeration(console_printer, |
||
595 | title, |
||
596 | items, |
||
597 | indentation, |
||
598 | no_items_text): |
||
599 | """ |
||
600 | This function takes as input an iterable object (preferably a list or |
||
601 | a dict). And prints in a stylized format. If the iterable object is |
||
602 | empty, it prints a specific statement give by the user. An e.g : |
||
603 | |||
604 | <indentation>Title: |
||
605 | <indentation> * Item 1 |
||
606 | <indentation> * Item 2 |
||
607 | |||
608 | :param console_printer: Object to print messages on the console. |
||
609 | :param title: Title of the text to be printed |
||
610 | :param items: The iterable object. |
||
611 | :param indentation: Number of spaces to indent every line by. |
||
612 | :param no_items_text: Text printed when iterable object is empty. |
||
613 | """ |
||
614 | if not items: |
||
615 | console_printer.print(indentation + no_items_text) |
||
616 | else: |
||
617 | console_printer.print(indentation + title) |
||
618 | if isinstance(items, dict): |
||
619 | for key, value in items.items(): |
||
620 | console_printer.print(indentation + " * " + key + ": " + |
||
621 | value[0]) |
||
622 | else: |
||
623 | for item in items: |
||
624 | console_printer.print(indentation + " * " + item) |
||
625 | console_printer.print() |
||
626 | |||
627 | |||
628 | def show_bear(console_printer, bear, sections, metadata): |
||
629 | """ |
||
630 | Display all information about a bear. |
||
631 | |||
632 | :param console_printer: Object to print messages on the console. |
||
633 | :param bear: The bear to be displayed. |
||
634 | :param sections: The sections to which the bear belongs. |
||
635 | :param metadata: Metadata about the bear. |
||
636 | """ |
||
637 | console_printer.print("{bear}:".format(bear=bear.name)) |
||
638 | console_printer.print(" " + metadata.desc + "\n") |
||
639 | |||
640 | show_enumeration( |
||
641 | console_printer, "Supported languages:", |
||
642 | (bear.LANGUAGES,) if isinstance(bear.LANGUAGES, str) else bear.LANGUAGES, |
||
0 ignored issues
–
show
|
|||
643 | " ", "The bear does not provide information about which languages " |
||
644 | "it can analyze.") |
||
645 | show_enumeration(console_printer, |
||
646 | "Used in:", |
||
647 | sections, |
||
648 | " ", |
||
649 | "No sections.") |
||
650 | |||
651 | show_enumeration(console_printer, |
||
652 | "Needed Settings:", |
||
653 | metadata.non_optional_params, |
||
654 | " ", |
||
655 | "No needed settings.") |
||
656 | show_enumeration(console_printer, |
||
657 | "Optional Settings:", |
||
658 | metadata.optional_params, |
||
659 | " ", |
||
660 | "No optional settings.") |
||
661 | |||
662 | |||
663 | def print_bears(console_printer, bears, compress): |
||
664 | """ |
||
665 | Presents all bears being used in a stylized manner. |
||
666 | |||
667 | :param console_printer: Object to print messages on the console. |
||
668 | :param bears: Its a dictionary with bears as keys and list of |
||
669 | sections containing those bears as values. |
||
670 | :param compress: If set to true, output will be compressed (just |
||
671 | show bear names as a list) |
||
672 | """ |
||
673 | if not bears: |
||
674 | console_printer.print("No bears to show.") |
||
675 | elif compress: |
||
676 | bear_list = sorted(bears.keys(), key=lambda bear: bear.name) |
||
677 | for bear in bear_list: |
||
678 | console_printer.print(" *", bear.name) |
||
679 | else: |
||
680 | for bear in sorted(bears.keys(), |
||
681 | key=lambda bear: bear.name): |
||
682 | show_bear(console_printer, |
||
683 | bear, |
||
684 | bears[bear], |
||
685 | bear.get_metadata()) |
||
686 | |||
687 | |||
688 | def show_bears(local_bears, global_bears, compress, console_printer): |
||
689 | """ |
||
690 | Extracts all the bears from each enabled section or the sections in the |
||
691 | targets and passes a dictionary to the show_bears_callback method. |
||
692 | |||
693 | :param local_bears: Dictionary of local bears with section names |
||
694 | as keys and bear list as values. |
||
695 | :param global_bears: Dictionary of global bears with section |
||
696 | names as keys and bear list as values. |
||
697 | :param compress: If set to true, output will be compressed (just |
||
698 | show bear names as a list) |
||
699 | :param show_bears_callback: The callback that is used to print these |
||
700 | bears. It will get one parameter holding |
||
701 | bears as key and the list of section names |
||
702 | where it's used as values. |
||
703 | """ |
||
704 | bears = inverse_dicts(local_bears, global_bears) |
||
705 | |||
706 | print_bears(console_printer, bears, compress) |
||
707 |
This check looks for lines that are too long. You can specify the maximum line length.