1# DExTer : Debugging Experience Tester 2# ~~~~~~ ~ ~~ ~ ~~ 3# 4# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5# See https://llvm.org/LICENSE.txt for license information. 6# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7"""Base class for all subtools.""" 8 9import abc 10import os 11import tempfile 12 13from dex import __version__ 14from dex.utils import ExtArgParse 15from dex.utils import PrettyOutput 16from dex.utils.ReturnCode import ReturnCode 17 18 19class ToolBase(object, metaclass=abc.ABCMeta): 20 def __init__(self, context): 21 self.context = context 22 self.parser = None 23 24 @abc.abstractproperty 25 def name(self): 26 pass 27 28 @abc.abstractmethod 29 def add_tool_arguments(self, parser, defaults): 30 pass 31 32 def parse_command_line(self, args): 33 """Define two parsers: pparser and self.parser. 34 pparser deals with args that need to be parsed prior to any of those of 35 self.parser. For example, any args which may affect the state of 36 argparse error output. 37 """ 38 39 class defaults(object): 40 pass 41 42 pparser = ExtArgParse.ExtArgumentParser( 43 self.context, add_help=False, prog=self.name) 44 45 pparser.add_argument( 46 '--no-color-output', 47 action='store_true', 48 default=False, 49 help='do not use colored output on stdout/stderr') 50 pparser.add_argument( 51 '--time-report', 52 action='store_true', 53 default=False, 54 help='display timing statistics') 55 56 self.parser = ExtArgParse.ExtArgumentParser( 57 self.context, parents=[pparser], prog=self.name) 58 self.parser.add_argument( 59 '-v', 60 '--verbose', 61 action='store_true', 62 default=False, 63 help='enable verbose output') 64 self.parser.add_argument( 65 '-V', 66 '--version', 67 action='store_true', 68 default=False, 69 help='display the DExTer version and exit') 70 self.parser.add_argument( 71 '-w', 72 '--no-warnings', 73 action='store_true', 74 default=False, 75 help='suppress warning output') 76 self.parser.add_argument( 77 '--unittest', 78 type=str, 79 choices=['off', 'show-failures', 'show-all'], 80 default='off', 81 help='run the DExTer codebase unit tests') 82 83 suppress = ExtArgParse.SUPPRESS # pylint: disable=no-member 84 self.parser.add_argument( 85 '--colortest', action='store_true', default=False, help=suppress) 86 self.parser.add_argument( 87 '--error-debug', action='store_true', default=False, help=suppress) 88 defaults.working_directory = os.path.join(tempfile.gettempdir(), 89 'dexter') 90 self.parser.add_argument( 91 '--indent-timer-level', type=int, default=1, help=suppress) 92 self.parser.add_argument( 93 '--working-directory', 94 type=str, 95 metavar='<file>', 96 default=None, 97 display_default=defaults.working_directory, 98 help='location of working directory') 99 self.parser.add_argument( 100 '--save-temps', 101 action='store_true', 102 default=False, 103 help='save temporary files') 104 105 self.add_tool_arguments(self.parser, defaults) 106 107 # If an error is encountered during pparser, show the full usage text 108 # including self.parser options. Strip the preceding 'usage: ' to avoid 109 # having it appear twice. 110 pparser.usage = self.parser.format_usage().lstrip('usage: ') 111 112 options, args = pparser.parse_known_args(args) 113 114 if options.no_color_output: 115 PrettyOutput.stdout.color_enabled = False 116 PrettyOutput.stderr.color_enabled = False 117 118 options = self.parser.parse_args(args, namespace=options) 119 return options, defaults 120 121 def handle_base_options(self, defaults): 122 self.handle_options(defaults) 123 124 options = self.context.options 125 126 if options.working_directory is None: 127 options.working_directory = defaults.working_directory 128 129 @abc.abstractmethod 130 def handle_options(self, defaults): 131 pass 132 133 @abc.abstractmethod 134 def go(self) -> ReturnCode: 135 pass 136