Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/notes/2.34.x.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ Published Pants binaries are now compiled with a new `dist` Cargo profile that e

Pants option config files are now parsed as TOML 1.1 rather than TOML 1.0. This covers `pants.toml` and any other file named by `[GLOBAL].pants_config_files`, the rcfiles named by `[GLOBAL].pantsrc_files` (`/etc/pantsrc`, `~/.pants.rc` and `.pants.rc` by default), and `.toml` files referenced by `@fromfile` option values. Inline tables may now span multiple lines and end with a trailing comma, strings may use the `\e` and `\xHH` escapes, and times may omit their seconds. TOML 1.1 only adds syntax to TOML 1.0, so existing files continue to parse unchanged. TOML files read by backends, such as `pyproject.toml`, are unaffected.

Full exception stack traces are now printed automatically when running at a verbose log level (`-ldebug` or `-ltrace`), unless `--no-print-stacktrace` is passed explicitly. In other words these logging levels imply `--print-stacktrace` by default.

### Goals

### Backends
Expand Down
8 changes: 8 additions & 0 deletions src/python/pants/bin/local_pants_runner_integration_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,11 @@ def run(args: Sequence[str]) -> PantsResult:
assert "Traceback" in print_stacktrace.stderr
assert "Engine traceback:" in print_stacktrace.stderr
assert list_rule_name in print_stacktrace.stderr

debug = run(["-ldebug"])
assert "Traceback" in debug.stderr
assert "Engine traceback:" in debug.stderr
assert list_rule_name in debug.stderr

debug_no_stacktrace = run(["-ldebug", "--no-print-stacktrace"])
assert "Traceback" not in debug_no_stacktrace.stderr
2 changes: 1 addition & 1 deletion src/python/pants/init/engine_initializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ def setup_graph(
ca_certs_path=bootstrap_options.ca_certs_path,
build_root=build_root,
pants_workdir=bootstrap_options.pants_workdir,
include_trace_on_error=bootstrap_options.print_stacktrace,
include_trace_on_error=GlobalOptions.should_print_stacktrace(bootstrap_options),
engine_visualize_to=bootstrap_options.engine_visualize_to,
watch_filesystem=bootstrap_options.watch_filesystem,
is_bootstrap=is_bootstrap,
Expand Down
3 changes: 2 additions & 1 deletion src/python/pants/init/logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import pants.util.logging as pants_logging
from pants.engine.internals import native_engine
from pants.option.global_options import GlobalOptions
from pants.option.option_value_container import OptionValueContainer
from pants.util.dirutil import safe_mkdir_for
from pants.util.docutil import doc_url
Expand Down Expand Up @@ -176,7 +177,7 @@ def initialize_stdio(global_bootstrap_options: OptionValueContainer) -> Iterator
global_bootstrap_options.log_show_rust_3rdparty,
global_bootstrap_options.show_log_target,
_get_log_levels_by_target(global_bootstrap_options),
global_bootstrap_options.print_stacktrace,
GlobalOptions.should_print_stacktrace(global_bootstrap_options),
global_bootstrap_options.ignore_warnings,
global_bootstrap_options.pants_workdir,
):
Expand Down
11 changes: 11 additions & 0 deletions src/python/pants/option/global_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,17 @@ def compute_pantsd_invalidation_globs(
)
return tuple(invalidation_globs)

@staticmethod
def should_print_stacktrace(bootstrap_options: OptionValueContainer) -> bool:
"""Whether full stack traces should be shown for errors.

An explicit `--[no-]print-stacktrace` always wins. Otherwise, stack traces are shown
implicitly at verbose log levels (`-ldebug` / `-ltrace`).
"""
if not bootstrap_options.is_default("print_stacktrace"):
return bootstrap_options.print_stacktrace
return bootstrap_options.level in (LogLevel.DEBUG, LogLevel.TRACE)

@memoized_classmethod
def get_options_flags(cls) -> GlobalOptionsFlags:
return GlobalOptionsFlags.create(cast("Type[GlobalOptions]", cls))
Expand Down
26 changes: 26 additions & 0 deletions src/python/pants/option/global_options_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,13 @@
from pants.option.bootstrap_options import DynamicRemoteOptions, ExecutionOptions, RemoteProvider
from pants.option.errors import OptionsError
from pants.option.global_options import GlobalOptions
from pants.option.option_value_container import OptionValueContainerBuilder
from pants.option.options_bootstrapper import OptionsBootstrapper
from pants.option.ranked_value import Rank, RankedValue
from pants.testutil.option_util import create_dynamic_remote_options
from pants.testutil.pytest_util import no_exception
from pants.util.dirutil import safe_mkdir_for
from pants.util.logging import LogLevel
from pants.version import VERSION


Expand Down Expand Up @@ -144,6 +147,29 @@ def test_invalidation_globs() -> None:
assert suffix not in glob


@pytest.mark.parametrize(
"print_stacktrace, rank, level, expected",
[
(False, Rank.HARDCODED, LogLevel.INFO, False),
(False, Rank.HARDCODED, LogLevel.DEBUG, True),
(False, Rank.HARDCODED, LogLevel.TRACE, True),
(True, Rank.FLAG, LogLevel.INFO, True),
(True, Rank.FLAG, LogLevel.ERROR, True),
(False, Rank.FLAG, LogLevel.DEBUG, False),
(False, Rank.FLAG, LogLevel.TRACE, False),
(True, Rank.CONFIG, LogLevel.INFO, True),
(False, Rank.CONFIG, LogLevel.DEBUG, False),
],
)
def test_should_print_stacktrace(
print_stacktrace: bool, rank: Rank, level: LogLevel, expected: bool
) -> None:
builder = OptionValueContainerBuilder()
builder.print_stacktrace = RankedValue(rank, print_stacktrace)
builder.level = RankedValue(Rank.FLAG, level)
assert GlobalOptions.should_print_stacktrace(builder.build()) is expected


@pytest.mark.parametrize(
("provider", "address", "expect_raises"),
[
Expand Down