Skip to content
Merged
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
6 changes: 5 additions & 1 deletion Lib/profiling/sampling/pstats_collector.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import collections
import marshal
import pstats
lazy from _colorize import ANSIColors
lazy from _colorize import get_colors

from .collector import Collector, extract_lineno
from .constants import MICROSECONDS_PER_SECOND, PROFILING_MODE_CPU
Expand Down Expand Up @@ -178,6 +178,8 @@ def print_stats(self, sort=-1, limit=None, show_summary=True, mode=None):
}

# Print header with colors and proper alignment
ANSIColors = get_colors()

print(f"{ANSIColors.BOLD_BLUE}Profile Stats:{ANSIColors.RESET}")

header_nsamples = f"{ANSIColors.BOLD_BLUE}{'nsamples':>{col_widths['nsamples']}}{ANSIColors.RESET}"
Expand Down Expand Up @@ -269,6 +271,8 @@ def _determine_best_unit(max_value):

def _print_summary(self, stats_list, total_samples):
"""Print summary of interesting functions."""
ANSIColors = get_colors()

print(
f"\n{ANSIColors.BOLD_BLUE}Summary of Interesting Functions:{ANSIColors.RESET}"
)
Expand Down
8 changes: 7 additions & 1 deletion Lib/profiling/sampling/sample.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import sysconfig
import time
from collections import deque
lazy from _colorize import ANSIColors
lazy from _colorize import get_colors

from .pstats_collector import PstatsCollector
from .stack_collector import CollapsedStackCollector, FlamegraphCollector
Expand Down Expand Up @@ -276,6 +276,8 @@ def _print_realtime_stats(self):
) # Max time = Min Hz

# Build cache stats string if stats collection is enabled
ANSIColors = get_colors()

cache_stats_str = ""
if self.collect_stats:
try:
Expand Down Expand Up @@ -309,6 +311,8 @@ def _print_unwinder_stats(self):
except RuntimeError:
return # Stats not enabled

ANSIColors = get_colors()

print(f"\n{ANSIColors.BOLD_BLUE}{'='*50}{ANSIColors.RESET}")
print(f"{ANSIColors.BOLD_BLUE}Unwinder Statistics:{ANSIColors.RESET}")

Expand Down Expand Up @@ -403,6 +407,8 @@ def _print_binary_stats(self, collector):
except (ValueError, RuntimeError):
return # Collector closed or stats unavailable

ANSIColors = get_colors()

print(f" {ANSIColors.CYAN}Binary Encoding:{ANSIColors.RESET}")

repeat_records = stats.get('repeat_records', 0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"Test only runs when _remote_debugging is available"
)

from test.support import force_not_colorized_test_class
from test.support import force_colorized, force_not_colorized_test_class


def print_sampled_stats(stats, sort=-1, limit=None, show_summary=True, sample_interval_usec=100):
Expand Down Expand Up @@ -484,6 +484,15 @@ def test_print_sampled_stats_basic(self):
self.assertIn("func1", result)
self.assertIn("func2", result)
self.assertIn("func3", result)
self.assertNotIn("\x1b[", result)

@force_colorized
def test_print_sampled_stats_colorized(self):
with io.StringIO() as output, mock.patch("sys.stdout", output):
print_sampled_stats(self.mock_stats)
result = output.getvalue()

self.assertIn("\x1b[1;34mProfile Stats:", result)

def test_print_sampled_stats_sorting(self):
"""Test different sorting options."""
Expand Down Expand Up @@ -751,6 +760,7 @@ def test_print_sampled_stats_sort_by_name(self):
and not "calls" in line # Skip summary lines
and not "total time" in line # Skip summary lines
and not "cumulative time" in line
and not "filename:lineno(function)" in line # Skip header line
): # Skip summary lines
data_lines.append(line)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
The :mod:`profiling.sampling` profiler now respects ``NO_COLOR``,
``FORCE_COLOR``, and ``PYTHON_COLORS`` and avoids colored output when
not writing to a terminal.
Loading