[Dexter] Add a simple logging class to Dexter
Adds a basic logging class to Dexter that uses the existing PrettyOutput class for printing and supports 3 levels of verbosity (note, warning, error). Intended to consolidate the logging logic for Dexter into one place, removing the need for conditional log statements and making it easier for us later if we wish to use a more complete logging class. Reviewed By: Orlando Differential Revision: https://reviews.llvm.org/D144983
This commit is contained in:
parent
bc14c40dc1
commit
73a01952b5
|
@ -18,7 +18,6 @@ from dex.dextIR import DextIR
|
||||||
from dex.utils import get_root_directory, Timer
|
from dex.utils import get_root_directory, Timer
|
||||||
from dex.utils.Environment import is_native_windows
|
from dex.utils.Environment import is_native_windows
|
||||||
from dex.utils.Exceptions import ToolArgumentError
|
from dex.utils.Exceptions import ToolArgumentError
|
||||||
from dex.utils.Warning import warn
|
|
||||||
from dex.utils.Exceptions import DebuggerException
|
from dex.utils.Exceptions import DebuggerException
|
||||||
|
|
||||||
from dex.debugger.DebuggerControllers.DefaultController import DefaultController
|
from dex.debugger.DebuggerControllers.DefaultController import DefaultController
|
||||||
|
@ -48,9 +47,10 @@ def _warn_meaningless_option(context, option):
|
||||||
if hasattr(context.options, 'list_debuggers'):
|
if hasattr(context.options, 'list_debuggers'):
|
||||||
return
|
return
|
||||||
|
|
||||||
warn(context,
|
context.logger.warning(
|
||||||
'option <y>"{}"</> is meaningless with this debugger'.format(option),
|
f'option "{option}" is meaningless with this debugger',
|
||||||
'--debugger={}'.format(context.options.debugger))
|
enable_prefix=True,
|
||||||
|
flag=f'--debugger={context.options.debugger}')
|
||||||
|
|
||||||
|
|
||||||
def add_debugger_tool_base_arguments(parser, defaults):
|
def add_debugger_tool_base_arguments(parser, defaults):
|
||||||
|
|
|
@ -10,7 +10,7 @@ import abc
|
||||||
import imp
|
import imp
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from pathlib import PurePath
|
from pathlib import PurePath, Path
|
||||||
from collections import defaultdict, namedtuple
|
from collections import defaultdict, namedtuple
|
||||||
|
|
||||||
from dex.command.CommandBase import StepExpectInfo
|
from dex.command.CommandBase import StepExpectInfo
|
||||||
|
@ -249,9 +249,13 @@ class VisualStudio(DebuggerBase, metaclass=abc.ABCMeta): # pylint: disable=abst
|
||||||
assert False, "Couldn't find property {}".format(name)
|
assert False, "Couldn't find property {}".format(name)
|
||||||
|
|
||||||
def launch(self, cmdline):
|
def launch(self, cmdline):
|
||||||
|
exe_path = Path(self.context.options.executable)
|
||||||
|
self.context.logger.note(f"VS: Using executable: '{exe_path}'")
|
||||||
cmdline_str = ' '.join(cmdline)
|
cmdline_str = ' '.join(cmdline)
|
||||||
if self.context.options.target_run_args:
|
if self.context.options.target_run_args:
|
||||||
cmdline_str += f" {self.context.options.target_run_args}"
|
cmdline_str += f" {self.context.options.target_run_args}"
|
||||||
|
if cmdline_str:
|
||||||
|
self.context.logger.note(f"VS: Using executable args: '{cmdline_str}'")
|
||||||
|
|
||||||
# In a slightly baroque manner, lookup the VS project that runs when
|
# In a slightly baroque manner, lookup the VS project that runs when
|
||||||
# you click "run", and set its command line options to the desired
|
# you click "run", and set its command line options to the desired
|
||||||
|
@ -261,6 +265,7 @@ class VisualStudio(DebuggerBase, metaclass=abc.ABCMeta): # pylint: disable=abst
|
||||||
ActiveConfiguration = self._fetch_property(project.Properties, 'ActiveConfiguration').Object
|
ActiveConfiguration = self._fetch_property(project.Properties, 'ActiveConfiguration').Object
|
||||||
ActiveConfiguration.DebugSettings.CommandArguments = cmdline_str
|
ActiveConfiguration.DebugSettings.CommandArguments = cmdline_str
|
||||||
|
|
||||||
|
self.context.logger.note("Launching VS debugger...")
|
||||||
self._fn_go(False)
|
self._fn_go(False)
|
||||||
|
|
||||||
def step(self):
|
def step(self):
|
||||||
|
|
|
@ -18,6 +18,7 @@ from dex.utils import PrettyOutput, Timer
|
||||||
from dex.utils import ExtArgParse as argparse
|
from dex.utils import ExtArgParse as argparse
|
||||||
from dex.utils import get_root_directory
|
from dex.utils import get_root_directory
|
||||||
from dex.utils.Exceptions import Error, ToolArgumentError
|
from dex.utils.Exceptions import Error, ToolArgumentError
|
||||||
|
from dex.utils.Logging import Logger
|
||||||
from dex.utils.UnitTests import unit_tests_ok
|
from dex.utils.UnitTests import unit_tests_ok
|
||||||
from dex.utils.Version import version
|
from dex.utils.Version import version
|
||||||
from dex.utils import WorkingDirectory
|
from dex.utils import WorkingDirectory
|
||||||
|
@ -145,6 +146,11 @@ def tool_main(context, tool, args):
|
||||||
context.o.green('{}\n'.format(context.version))
|
context.o.green('{}\n'.format(context.version))
|
||||||
return ReturnCode.OK
|
return ReturnCode.OK
|
||||||
|
|
||||||
|
if options.verbose:
|
||||||
|
context.logger.verbosity = 2
|
||||||
|
elif options.no_warnings:
|
||||||
|
context.logger.verbosity = 0
|
||||||
|
|
||||||
if (options.unittest != 'off' and not unit_tests_ok(context)):
|
if (options.unittest != 'off' and not unit_tests_ok(context)):
|
||||||
raise Error('<d>unit test failures</>')
|
raise Error('<d>unit test failures</>')
|
||||||
|
|
||||||
|
@ -171,6 +177,7 @@ class Context(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.o: PrettyOutput = None
|
self.o: PrettyOutput = None
|
||||||
|
self.logger: Logger = None
|
||||||
self.working_directory: str = None
|
self.working_directory: str = None
|
||||||
self.options: dict = None
|
self.options: dict = None
|
||||||
self.version: str = None
|
self.version: str = None
|
||||||
|
@ -182,6 +189,7 @@ def main() -> ReturnCode:
|
||||||
context = Context()
|
context = Context()
|
||||||
|
|
||||||
with PrettyOutput() as context.o:
|
with PrettyOutput() as context.o:
|
||||||
|
context.logger = Logger(context.o)
|
||||||
try:
|
try:
|
||||||
context.root_directory = get_root_directory()
|
context.root_directory = get_root_directory()
|
||||||
# Flag some strings for auto-highlighting.
|
# Flag some strings for auto-highlighting.
|
||||||
|
@ -192,8 +200,7 @@ def main() -> ReturnCode:
|
||||||
module = _import_tool_module(tool_name)
|
module = _import_tool_module(tool_name)
|
||||||
return tool_main(context, module.Tool(context), args)
|
return tool_main(context, module.Tool(context), args)
|
||||||
except Error as e:
|
except Error as e:
|
||||||
context.o.auto(
|
context.logger.error(str(e))
|
||||||
'\nerror: {}\n'.format(str(e)), stream=PrettyOutput.stderr)
|
|
||||||
try:
|
try:
|
||||||
if context.options.error_debug:
|
if context.options.error_debug:
|
||||||
raise
|
raise
|
||||||
|
|
|
@ -17,7 +17,7 @@ from dex.debugger.Debuggers import add_debugger_tool_arguments
|
||||||
from dex.debugger.Debuggers import handle_debugger_tool_options
|
from dex.debugger.Debuggers import handle_debugger_tool_options
|
||||||
from dex.heuristic.Heuristic import add_heuristic_tool_arguments
|
from dex.heuristic.Heuristic import add_heuristic_tool_arguments
|
||||||
from dex.tools.ToolBase import ToolBase
|
from dex.tools.ToolBase import ToolBase
|
||||||
from dex.utils import get_root_directory, warn
|
from dex.utils import get_root_directory
|
||||||
from dex.utils.Exceptions import Error, ToolArgumentError
|
from dex.utils.Exceptions import Error, ToolArgumentError
|
||||||
from dex.utils.ReturnCode import ReturnCode
|
from dex.utils.ReturnCode import ReturnCode
|
||||||
|
|
||||||
|
@ -53,8 +53,9 @@ class TestToolBase(ToolBase):
|
||||||
options = self.context.options
|
options = self.context.options
|
||||||
|
|
||||||
if not options.builder and (options.cflags or options.ldflags):
|
if not options.builder and (options.cflags or options.ldflags):
|
||||||
warn(self.context, '--cflags and --ldflags will be ignored when not'
|
self.context.logger.warning(
|
||||||
' using --builder')
|
'--cflags and --ldflags will be ignored when not using --builder',
|
||||||
|
enable_prefix=True)
|
||||||
|
|
||||||
if options.vs_solution:
|
if options.vs_solution:
|
||||||
options.vs_solution = os.path.abspath(options.vs_solution)
|
options.vs_solution = os.path.abspath(options.vs_solution)
|
||||||
|
|
|
@ -60,7 +60,7 @@ class ToolBase(object, metaclass=abc.ABCMeta):
|
||||||
'--verbose',
|
'--verbose',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
default=False,
|
default=False,
|
||||||
help='enable verbose output')
|
help='enable verbose output (overrides --no-warnings)')
|
||||||
self.parser.add_argument(
|
self.parser.add_argument(
|
||||||
'-V',
|
'-V',
|
||||||
'--version',
|
'--version',
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
# 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
|
||||||
|
"""Utility functions for producing command line warnings."""
|
||||||
|
|
||||||
|
from dex.utils import PrettyOutput
|
||||||
|
|
||||||
|
class Logger(object):
|
||||||
|
def __init__(self, pretty_output: PrettyOutput):
|
||||||
|
self.o = pretty_output
|
||||||
|
self.error_color = self.o.red
|
||||||
|
self.warning_color = self.o.yellow
|
||||||
|
self.note_color = self.o.default
|
||||||
|
self.verbosity = 1
|
||||||
|
|
||||||
|
def error(self, msg, enable_prefix=True, flag=None):
|
||||||
|
if self.verbosity < 0:
|
||||||
|
return
|
||||||
|
if enable_prefix:
|
||||||
|
msg = f'error: {msg}'
|
||||||
|
if flag:
|
||||||
|
msg = f'{msg} <y>[{flag}]</>'
|
||||||
|
self.error_color('{}\n'.format(msg), stream=PrettyOutput.stderr)
|
||||||
|
|
||||||
|
def warning(self, msg, enable_prefix=True, flag=None):
|
||||||
|
if self.verbosity < 1:
|
||||||
|
return
|
||||||
|
if enable_prefix:
|
||||||
|
msg = f'warning: {msg}'
|
||||||
|
if flag:
|
||||||
|
msg = f'{msg} <y>[{flag}]</>'
|
||||||
|
self.warning_color('{}\n'.format(msg), stream=PrettyOutput.stderr)
|
||||||
|
|
||||||
|
def note(self, msg, enable_prefix=True, flag=None):
|
||||||
|
if self.verbosity < 2:
|
||||||
|
return
|
||||||
|
if enable_prefix:
|
||||||
|
msg = f'note: {msg}'
|
||||||
|
if flag:
|
||||||
|
msg = f'{msg} <y>[{flag}]</>'
|
||||||
|
self.note_color('{}\n'.format(msg), stream=PrettyOutput.stderr)
|
|
@ -1,18 +0,0 @@
|
||||||
# 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
|
|
||||||
"""Utility functions for producing command line warnings."""
|
|
||||||
|
|
||||||
|
|
||||||
def warn(context, msg, flag=None):
|
|
||||||
if context.options.no_warnings:
|
|
||||||
return
|
|
||||||
|
|
||||||
msg = msg.rstrip()
|
|
||||||
if flag:
|
|
||||||
msg = '{} <y>[{}]</>'.format(msg, flag)
|
|
||||||
|
|
||||||
context.o.auto('warning: <d>{}</>\n'.format(msg))
|
|
|
@ -12,7 +12,6 @@ import tempfile
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from dex.utils.Exceptions import Error
|
from dex.utils.Exceptions import Error
|
||||||
from dex.utils.Warning import warn
|
|
||||||
|
|
||||||
class WorkingDirectory(object):
|
class WorkingDirectory(object):
|
||||||
def __init__(self, context, *args, **kwargs):
|
def __init__(self, context, *args, **kwargs):
|
||||||
|
@ -42,5 +41,5 @@ class WorkingDirectory(object):
|
||||||
except OSError:
|
except OSError:
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
|
|
||||||
warn(self.context, '"{}" left in place (couldn\'t delete)\n'.format(self.path))
|
self.context.logger.warning(f'"{self.path}" left in place (couldn\'t delete)', enable_prefix=True)
|
||||||
return
|
return
|
||||||
|
|
|
@ -12,10 +12,11 @@ from dex.utils.Environment import is_native_windows, has_pywin32
|
||||||
from dex.utils.PrettyOutputBase import PreserveAutoColors
|
from dex.utils.PrettyOutputBase import PreserveAutoColors
|
||||||
from dex.utils.RootDirectory import get_root_directory
|
from dex.utils.RootDirectory import get_root_directory
|
||||||
from dex.utils.Timer import Timer
|
from dex.utils.Timer import Timer
|
||||||
from dex.utils.Warning import warn
|
|
||||||
from dex.utils.WorkingDirectory import WorkingDirectory
|
from dex.utils.WorkingDirectory import WorkingDirectory
|
||||||
|
|
||||||
if is_native_windows():
|
if is_native_windows():
|
||||||
from dex.utils.windows.PrettyOutput import PrettyOutput
|
from dex.utils.windows.PrettyOutput import PrettyOutput
|
||||||
else:
|
else:
|
||||||
from dex.utils.posix.PrettyOutput import PrettyOutput
|
from dex.utils.posix.PrettyOutput import PrettyOutput
|
||||||
|
|
||||||
|
from dex.utils.Logging import Logger
|
||||||
|
|
Loading…
Reference in New Issue
Block a user