# DExTer : Debugging Experience Tester # ~~~~~~ ~ ~~ ~ ~~ # # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. # See https://llvm.org/LICENSE.txt for license information. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception """Base class for all subtools.""" import abc import os import tempfile from dex import __version__ from dex.utils import ExtArgParse from dex.utils import PrettyOutput from dex.utils.ReturnCode import ReturnCode class ToolBase(object, metaclass=abc.ABCMeta): def __init__(self, context): self.context = context self.parser = None @abc.abstractproperty def name(self): pass @abc.abstractmethod def add_tool_arguments(self, parser, defaults): pass def parse_command_line(self, args): """Define two parsers: pparser and self.parser. pparser deals with args that need to be parsed prior to any of those of self.parser. For example, any args which may affect the state of argparse error output. """ class defaults(object): pass pparser = ExtArgParse.ExtArgumentParser( self.context, add_help=False, prog=self.name) pparser.add_argument( '--no-color-output', action='store_true', default=False, help='do not use colored output on stdout/stderr') pparser.add_argument( '--time-report', action='store_true', default=False, help='display timing statistics') self.parser = ExtArgParse.ExtArgumentParser( self.context, parents=[pparser], prog=self.name) self.parser.add_argument( '-v', '--verbose', action='store_true', default=False, help='enable verbose output') self.parser.add_argument( '-V', '--version', action='store_true', default=False, help='display the DExTer version and exit') self.parser.add_argument( '-w', '--no-warnings', action='store_true', default=False, help='suppress warning output') self.parser.add_argument( '--unittest', type=str, choices=['off', 'show-failures', 'show-all'], default='off', help='run the DExTer codebase unit tests') suppress = ExtArgParse.SUPPRESS # pylint: disable=no-member self.parser.add_argument( '--colortest', action='store_true', default=False, help=suppress) self.parser.add_argument( '--error-debug', action='store_true', default=False, help=suppress) defaults.working_directory = os.path.join(tempfile.gettempdir(), 'dexter') self.parser.add_argument( '--indent-timer-level', type=int, default=1, help=suppress) self.parser.add_argument( '--working-directory', type=str, metavar='', default=None, display_default=defaults.working_directory, help='location of working directory') self.parser.add_argument( '--save-temps', action='store_true', default=False, help='save temporary files') self.add_tool_arguments(self.parser, defaults) # If an error is encountered during pparser, show the full usage text # including self.parser options. Strip the preceding 'usage: ' to avoid # having it appear twice. pparser.usage = self.parser.format_usage().lstrip('usage: ') options, args = pparser.parse_known_args(args) if options.no_color_output: PrettyOutput.stdout.color_enabled = False PrettyOutput.stderr.color_enabled = False options = self.parser.parse_args(args, namespace=options) return options, defaults def handle_base_options(self, defaults): self.handle_options(defaults) options = self.context.options if options.working_directory is None: options.working_directory = defaults.working_directory @abc.abstractmethod def handle_options(self, defaults): pass @abc.abstractmethod def go(self) -> ReturnCode: pass