diff --git a/docs/options.md b/docs/options.md index 5e842277b..5bbf79aa6 100644 --- a/docs/options.md +++ b/docs/options.md @@ -152,9 +152,11 @@ Log details of loaded .FLM flash algos. debug.traceback bool -True +False -Print tracebacks for exceptions. +Print tracebacks for exceptions, including errors that are only logged as well as critical errors that cause pyocd to terminate. + +Disabled by default, unless the log level is raised to Debug. enable_multicore_debug diff --git a/pyocd/commands/commander.py b/pyocd/commands/commander.py index 3059f5396..1e8079615 100755 --- a/pyocd/commands/commander.py +++ b/pyocd/commands/commander.py @@ -214,10 +214,11 @@ def connect(self) -> bool: connect_mode=connect_mode, frequency=self.args.frequency, options=options, - option_defaults=dict( - auto_unlock=False, - resume_on_disconnect=False, - ) + option_defaults={ + 'auto_unlock': False, + 'resume_on_disconnect': False, + 'debug.traceback': logging.getLogger('pyocd').isEnabledFor(logging.DEBUG), + } ) if not self._post_connect(): diff --git a/pyocd/core/options.py b/pyocd/core/options.py index b99b5ef01..1e4b3b0f6 100644 --- a/pyocd/core/options.py +++ b/pyocd/core/options.py @@ -64,7 +64,7 @@ class OptionInfo(NamedTuple): "When switching between SWD and JTAG, use the SWJ sequence from ADIv5.2 that utilizes a new dormant state."), OptionInfo('debug.log_flm_info', bool, False, "Log details of loaded .FLM flash algos."), - OptionInfo('debug.traceback', bool, True, + OptionInfo('debug.traceback', bool, False, "Print tracebacks for exceptions."), OptionInfo('enable_multicore_debug', bool, False, "Whether to put pyOCD into multicore debug mode. Doing so changes the default software reset type of " diff --git a/pyocd/subcommands/base.py b/pyocd/subcommands/base.py index 16542331d..4a65cdcd6 100644 --- a/pyocd/subcommands/base.py +++ b/pyocd/subcommands/base.py @@ -1,5 +1,5 @@ # pyOCD debugger -# Copyright (c) 2021 Chris Reed +# Copyright (c) 2021-2023 Chris Reed # SPDX-License-Identifier: Apache-2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,7 +17,7 @@ import argparse import logging import prettytable -from typing import (List, Optional, Type) +from typing import (Any, Dict, List, Optional, Type) from ..utility.cmdline import convert_frequency @@ -169,4 +169,17 @@ def _get_pretty_table(self, fields: List[str], header: bool = None) -> prettytab pt.vrules = prettytable.NONE return pt + def _modified_option_defaults(self) -> Dict[str, Any]: + """@brief Returns a dict of session option defaults. + + @return A dict containing updated default values for session options, based on common + subcommand arguments. It is intended to be passed as the `option_defaults` argument when + creating a `Session` instance. + @precondition Logging must have been configured. + """ + return { + # Change 'debug.traceback' default to True if debug logging is enabled. + 'debug.traceback': logging.getLogger('pyocd').isEnabledFor(logging.DEBUG), + } + diff --git a/pyocd/subcommands/erase_cmd.py b/pyocd/subcommands/erase_cmd.py index 918820ea5..602d3fff0 100644 --- a/pyocd/subcommands/erase_cmd.py +++ b/pyocd/subcommands/erase_cmd.py @@ -85,7 +85,9 @@ def invoke(self) -> int: frequency=self._args.frequency, blocking=(not self._args.no_wait), connect_mode=self._args.connect_mode, - options=convert_session_options(self._args.options)) + options=convert_session_options(self._args.options), + option_defaults=self._modified_option_defaults(), + ) if session is None: LOG.error("No device available to erase") return 1 diff --git a/pyocd/subcommands/gdbserver_cmd.py b/pyocd/subcommands/gdbserver_cmd.py index a788c2c64..7b7df012c 100644 --- a/pyocd/subcommands/gdbserver_cmd.py +++ b/pyocd/subcommands/gdbserver_cmd.py @@ -183,7 +183,9 @@ def invoke(self) -> int: target_override=self._args.target_override, frequency=self._args.frequency, connect_mode=self._args.connect_mode, - options=sessionOptions) + options=sessionOptions, + option_defaults=self._modified_option_defaults(), + ) if session is None: LOG.error("No probe selected.") return 1 diff --git a/pyocd/subcommands/load_cmd.py b/pyocd/subcommands/load_cmd.py index a27b8c079..29f7b2ef2 100644 --- a/pyocd/subcommands/load_cmd.py +++ b/pyocd/subcommands/load_cmd.py @@ -91,7 +91,9 @@ def invoke(self) -> int: frequency=self._args.frequency, blocking=(not self._args.no_wait), connect_mode=self._args.connect_mode, - options=convert_session_options(self._args.options)) + options=convert_session_options(self._args.options), + option_defaults=self._modified_option_defaults(), + ) if session is None: LOG.error("No target device available") return 1 diff --git a/pyocd/subcommands/reset_cmd.py b/pyocd/subcommands/reset_cmd.py index 8d642546d..d14075c29 100644 --- a/pyocd/subcommands/reset_cmd.py +++ b/pyocd/subcommands/reset_cmd.py @@ -84,7 +84,9 @@ def invoke(self) -> None: connect_mode=self._args.connect_mode, resume_on_disconnect=not self._args.halt, reset_type=self._args.reset_type, - options=convert_session_options(self._args.options)) + options=convert_session_options(self._args.options), + option_defaults=self._modified_option_defaults(), + ) if session is None: LOG.error("No target device available to reset") sys.exit(1) diff --git a/pyocd/subcommands/rtt_cmd.py b/pyocd/subcommands/rtt_cmd.py index 4561ddea6..62e1648b4 100644 --- a/pyocd/subcommands/rtt_cmd.py +++ b/pyocd/subcommands/rtt_cmd.py @@ -80,7 +80,9 @@ def invoke(self) -> int: frequency=self._args.frequency, blocking=(not self._args.no_wait), connect_mode=self._args.connect_mode, - options=convert_session_options(self._args.options)) + options=convert_session_options(self._args.options), + option_defaults=self._modified_option_defaults(), + ) if session is None: LOG.error("No target device available")