Skip to content

Commit 978d61a

Browse files
johnslavikCopilot
andcommitted
Strip live_collector to its user-facing API surface
Guiding principle: stubs should only contain what users of the profiling API would actually import or tab-complete. The live_collector subpackage is primarily a TUI display component; its internal widget/display architecture is not part of any user-facing API. Judgement calls — removed: - live_collector/widgets.pyi: deleted — Widget, ProgressBarWidget, HeaderWidget, TableWidget, FooterWidget, HelpWidget, OpcodePanel are internal TUI rendering components; nobody writing code against the profiling API would import them - live_collector/trend_tracker.pyi: deleted — TrendTracker is an internal widget state helper used only inside the TUI rendering loop - live_collector/constants.pyi: deleted — TUI layout dimensions and curses color pair IDs (COLOR_PAIR_*, WIDTH_THRESHOLD_*, MIN_TERMINAL_*, etc.) have no meaning outside the live_collector implementation - live_collector/display.pyi: removed CursesDisplay (internal curses wrapper) and MockDisplay (test helper only referenced in tests, not production API); kept DisplayInterface because it is the type of the display= parameter on LiveStatsCollector.__init__ - live_collector/collector.pyi: removed all constant imports (COLOR_PAIR_*, MICROSECONDS_PER_SECOND, MIN_TERMINAL_*, etc.) that were leaked implementation imports not used in any type annotations; removed widget imports (HeaderWidget, TableWidget, etc.) and TrendTracker; removed ThreadData dataclass (internal per-sample accumulator); stripped LiveStatsCollector of TUI-state attributes (stdscr, selected_row, scroll_offset, paused, show_help, filter_*, view_mode, current_thread_index, per_thread_data, *_widget, display_update_interval_sec, thread_status_counts, gc_frame_samples, opcode_stats) and internal methods (simplify_path, process_frames, init_curses, cleanup_curses) - live_collector/__init__.pyi: stripped __all__ and re-exports to just LiveStatsCollector and DisplayInterface Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 5816e2d commit 978d61a

File tree

6 files changed

+10
-290
lines changed

6 files changed

+10
-290
lines changed
Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,4 @@
11
from .collector import LiveStatsCollector as LiveStatsCollector
2-
from .display import CursesDisplay as CursesDisplay, DisplayInterface as DisplayInterface, MockDisplay as MockDisplay
3-
from .widgets import (
4-
FooterWidget as FooterWidget,
5-
HeaderWidget as HeaderWidget,
6-
HelpWidget as HelpWidget,
7-
ProgressBarWidget as ProgressBarWidget,
8-
TableWidget as TableWidget,
9-
Widget as Widget,
10-
)
2+
from .display import DisplayInterface as DisplayInterface
113

12-
__all__ = [
13-
"LiveStatsCollector",
14-
"DisplayInterface",
15-
"CursesDisplay",
16-
"MockDisplay",
17-
"Widget",
18-
"ProgressBarWidget",
19-
"HeaderWidget",
20-
"TableWidget",
21-
"FooterWidget",
22-
"HelpWidget",
23-
]
4+
__all__ = ["LiveStatsCollector", "DisplayInterface"]
Lines changed: 8 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,8 @@
1-
import curses
21
from _typeshed import StrOrBytesPath
3-
from dataclasses import dataclass
42
from typing import Any
53

6-
from ..collector import Collector as Collector, extract_lineno as extract_lineno
7-
from ..constants import (
8-
PROFILING_MODE_CPU as PROFILING_MODE_CPU,
9-
PROFILING_MODE_GIL as PROFILING_MODE_GIL,
10-
PROFILING_MODE_WALL as PROFILING_MODE_WALL,
11-
THREAD_STATUS_GIL_REQUESTED as THREAD_STATUS_GIL_REQUESTED,
12-
THREAD_STATUS_HAS_EXCEPTION as THREAD_STATUS_HAS_EXCEPTION,
13-
THREAD_STATUS_HAS_GIL as THREAD_STATUS_HAS_GIL,
14-
THREAD_STATUS_ON_CPU as THREAD_STATUS_ON_CPU,
15-
THREAD_STATUS_UNKNOWN as THREAD_STATUS_UNKNOWN,
16-
)
17-
from .constants import (
18-
COLOR_PAIR_CYAN as COLOR_PAIR_CYAN,
19-
COLOR_PAIR_FILE as COLOR_PAIR_FILE,
20-
COLOR_PAIR_FUNC as COLOR_PAIR_FUNC,
21-
COLOR_PAIR_GREEN as COLOR_PAIR_GREEN,
22-
COLOR_PAIR_HEADER_BG as COLOR_PAIR_HEADER_BG,
23-
COLOR_PAIR_MAGENTA as COLOR_PAIR_MAGENTA,
24-
COLOR_PAIR_RED as COLOR_PAIR_RED,
25-
COLOR_PAIR_SAMPLES as COLOR_PAIR_SAMPLES,
26-
COLOR_PAIR_SORTED_HEADER as COLOR_PAIR_SORTED_HEADER,
27-
COLOR_PAIR_YELLOW as COLOR_PAIR_YELLOW,
28-
DEFAULT_DISPLAY_LIMIT as DEFAULT_DISPLAY_LIMIT,
29-
DEFAULT_SORT_BY as DEFAULT_SORT_BY,
30-
DISPLAY_UPDATE_INTERVAL_SEC as DISPLAY_UPDATE_INTERVAL_SEC,
31-
FINISHED_BANNER_EXTRA_LINES as FINISHED_BANNER_EXTRA_LINES,
32-
FOOTER_LINES as FOOTER_LINES,
33-
HEADER_LINES as HEADER_LINES,
34-
MICROSECONDS_PER_SECOND as MICROSECONDS_PER_SECOND,
35-
MIN_TERMINAL_HEIGHT as MIN_TERMINAL_HEIGHT,
36-
MIN_TERMINAL_WIDTH as MIN_TERMINAL_WIDTH,
37-
SAFETY_MARGIN as SAFETY_MARGIN,
38-
)
39-
from .display import CursesDisplay as CursesDisplay, DisplayInterface as DisplayInterface
40-
from .trend_tracker import TrendTracker as TrendTracker
41-
from .widgets import (
42-
FooterWidget as FooterWidget,
43-
HeaderWidget as HeaderWidget,
44-
HelpWidget as HelpWidget,
45-
OpcodePanel as OpcodePanel,
46-
TableWidget as TableWidget,
47-
)
48-
49-
@dataclass
50-
class ThreadData:
51-
thread_id: int
52-
result: dict[Any, Any] = ...
53-
has_gil: int = ...
54-
on_cpu: int = ...
55-
gil_requested: int = ...
56-
unknown: int = ...
57-
has_exception: int = ...
58-
total: int = ...
59-
sample_count: int = ...
60-
gc_frame_samples: int = ...
61-
opcode_stats: dict[Any, Any] = ...
62-
def increment_status_flag(self, status_flags: int) -> None: ...
63-
def as_status_dict(self) -> dict[str, int]: ...
4+
from ..collector import Collector as Collector
5+
from .display import DisplayInterface as DisplayInterface
646

657
class LiveStatsCollector(Collector):
668
result: dict[Any, Any]
@@ -70,40 +12,19 @@ class LiveStatsCollector(Collector):
7012
sort_by: str
7113
limit: int
7214
total_samples: int
15+
successful_samples: int
16+
failed_samples: int
7317
start_time: float | None
74-
stdscr: curses.window | None
75-
display: DisplayInterface | None
7618
running: bool
19+
finished: bool
20+
finish_timestamp: float | None
21+
finish_wall_time: float | None
7722
pid: int | None
7823
mode: int | None
7924
async_aware: str | bool | None
8025
max_sample_rate: int
81-
successful_samples: int
82-
failed_samples: int
83-
display_update_interval_sec: float
84-
thread_status_counts: dict[str, int]
85-
gc_frame_samples: int
86-
opcode_stats: dict[Any, Any]
87-
show_opcodes: bool
88-
selected_row: int
89-
scroll_offset: int
90-
paused: bool
91-
show_help: bool
92-
filter_pattern: str | None
93-
filter_input_mode: bool
94-
filter_input_buffer: str
95-
finished: bool
96-
finish_timestamp: float | None
97-
finish_wall_time: float | None
26+
display: DisplayInterface | None
9827
thread_ids: list[int]
99-
view_mode: str
100-
current_thread_index: int
101-
per_thread_data: dict[int, ThreadData]
102-
header_widget: HeaderWidget | None
103-
table_widget: TableWidget | None
104-
footer_widget: FooterWidget | None
105-
help_widget: HelpWidget | None
106-
opcode_panel: OpcodePanel | None
10728
def __init__(
10829
self,
10930
sample_interval_usec: int,
@@ -121,13 +42,9 @@ class LiveStatsCollector(Collector):
12142
def elapsed_time(self) -> float: ...
12243
@property
12344
def current_time_display(self) -> str: ...
124-
def simplify_path(self, filepath: str) -> str: ...
125-
def process_frames(self, frames: Any, thread_id: int | None = None) -> None: ...
12645
def collect_failed_sample(self) -> None: ...
12746
def collect(self, stack_frames: Any, timestamp_us: int | None = None) -> None: ...
12847
def build_stats_list(self) -> list[Any]: ...
12948
def reset_stats(self) -> None: ...
13049
def mark_finished(self) -> None: ...
131-
def init_curses(self, stdscr: curses.window) -> None: ...
132-
def cleanup_curses(self) -> None: ...
13350
def export(self, filename: StrOrBytesPath) -> None: ...

stdlib/profiling/sampling/live_collector/constants.pyi

Lines changed: 0 additions & 32 deletions
This file was deleted.
Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import abc
2-
import curses
32
from abc import ABC, abstractmethod
43

54
class DisplayInterface(ABC, metaclass=abc.ABCMeta):
@@ -25,47 +24,3 @@ class DisplayInterface(ABC, metaclass=abc.ABCMeta):
2524
def get_color_pair(self, pair_id: int) -> int: ...
2625
@abstractmethod
2726
def get_attr(self, name: str) -> int: ...
28-
29-
class CursesDisplay(DisplayInterface):
30-
stdscr: curses.window
31-
def __init__(self, stdscr: curses.window) -> None: ...
32-
def get_dimensions(self) -> tuple[int, int]: ...
33-
def clear(self) -> None: ...
34-
def refresh(self) -> None: ...
35-
def redraw(self) -> None: ...
36-
def add_str(self, line: int, col: int, text: str, attr: int = 0) -> None: ...
37-
def get_input(self) -> int: ...
38-
def set_nodelay(self, flag: bool) -> None: ...
39-
def has_colors(self) -> bool: ...
40-
def init_color_pair(self, pair_id: int, fg: int, bg: int) -> None: ...
41-
def get_color_pair(self, pair_id: int) -> int: ...
42-
def get_attr(self, name: str) -> int: ...
43-
44-
class MockDisplay(DisplayInterface):
45-
height: int
46-
width: int
47-
buffer: dict[tuple[int, int], tuple[str, int]]
48-
cleared: bool
49-
refreshed: bool
50-
redrawn: bool
51-
input_queue: list[int]
52-
nodelay_flag: bool
53-
colors_supported: bool
54-
color_pairs: dict[int, int]
55-
def __init__(self, height: int = 40, width: int = 160) -> None: ...
56-
def get_dimensions(self) -> tuple[int, int]: ...
57-
def clear(self) -> None: ...
58-
def refresh(self) -> None: ...
59-
def redraw(self) -> None: ...
60-
def add_str(self, line: int, col: int, text: str, attr: int = 0) -> None: ...
61-
def get_input(self) -> int: ...
62-
def set_nodelay(self, flag: bool) -> None: ...
63-
def has_colors(self) -> bool: ...
64-
def init_color_pair(self, pair_id: int, fg: int, bg: int) -> None: ...
65-
def get_color_pair(self, pair_id: int) -> int: ...
66-
def get_attr(self, name: str) -> int: ...
67-
def simulate_input(self, char: int) -> None: ...
68-
def get_text_at(self, line: int, col: int) -> str | None: ...
69-
def get_all_lines(self) -> list[str]: ...
70-
def find_text(self, pattern: str) -> tuple[int, int] | None: ...
71-
def contains_text(self, text: str) -> bool: ...

stdlib/profiling/sampling/live_collector/trend_tracker.pyi

Lines changed: 0 additions & 17 deletions
This file was deleted.

stdlib/profiling/sampling/live_collector/widgets.pyi

Lines changed: 0 additions & 84 deletions
This file was deleted.

0 commit comments

Comments
 (0)