Coverage for lintro / utils / environment / renderer.py: 22%
60 statements
« prev ^ index » next coverage.py v7.13.0, created at 2026-04-03 18:53 +0000
« prev ^ index » next coverage.py v7.13.0, created at 2026-04-03 18:53 +0000
1"""Environment report rendering utilities."""
3from __future__ import annotations
5import os
6import shutil
7from typing import TYPE_CHECKING
9from rich.panel import Panel
11from lintro.utils.environment._protocol import Renderable
12from lintro.utils.environment.environment_report import EnvironmentReport
14if TYPE_CHECKING:
15 from rich.console import Console
17# Consistent label width for alignment (matches original output)
18LABEL_WIDTH = 12
21def render_section(console: Console, section: Renderable | None) -> None:
22 """Render a single environment section to the console.
24 Args:
25 console: Rich console for output.
26 section: Environment section implementing Renderable protocol,
27 or None for optional sections.
28 """
29 if section is None:
30 return
32 if not section.is_available():
33 console.print(f"[bold cyan]{section.section_title}:[/bold cyan]")
34 console.print(" [dim](not installed)[/dim]")
35 console.print()
36 return
38 console.print(f"[bold cyan]{section.section_title}:[/bold cyan]")
39 for label, value in section.to_display_rows():
40 # Pad label for alignment
41 padded_label = f"{label}:".ljust(LABEL_WIDTH)
42 console.print(f" {padded_label} {value}")
43 console.print()
46# Default truncation length for PATH; override via terminal width if available
47_DEFAULT_PATH_TRUNCATE_LEN = 60
50def _get_path_truncate_len() -> int:
51 """Get the truncation length for PATH based on terminal width."""
52 try:
53 terminal_width = shutil.get_terminal_size().columns
54 # Use 70% of terminal width, with a minimum of 40 and maximum of 120
55 return max(40, min(120, int(terminal_width * 0.7)))
56 except (ValueError, OSError):
57 return _DEFAULT_PATH_TRUNCATE_LEN
60def _render_env_vars(console: Console, env_vars: dict[str, str | None]) -> None:
61 """Render environment variables section.
63 Args:
64 console: Rich console for output.
65 env_vars: Dictionary of environment variable names to values.
66 """
67 console.print("[bold cyan]Environment Variables:[/bold cyan]")
68 for var_name, var_value in env_vars.items():
69 display_value: str
70 if var_name == "PATH" and var_value:
71 # Truncate PATH for readability, keeping whole path entries
72 path_truncate_len = _get_path_truncate_len()
73 path_entries = var_value.split(os.pathsep)
74 if len(var_value) > path_truncate_len:
75 # Build truncated string by adding whole entries
76 shown_parts: list[str] = []
77 current_len = 0
78 for entry in path_entries:
79 # Account for separator length (except for first entry)
80 entry_len = len(entry) + (1 if shown_parts else 0)
81 if current_len + entry_len > path_truncate_len:
82 break
83 shown_parts.append(entry)
84 current_len += entry_len
85 # Always show at least one entry even if it exceeds truncate length
86 if not shown_parts and path_entries:
87 shown_parts.append(path_entries[0])
88 remaining = len(path_entries) - len(shown_parts)
89 truncated = os.pathsep.join(shown_parts)
90 entry_word = "entry" if remaining == 1 else "entries"
91 display_value = (
92 f"{truncated}... ({remaining} more {entry_word})"
93 if remaining > 0
94 else truncated
95 )
96 else:
97 display_value = var_value
98 else:
99 display_value = var_value or "(not set)"
100 console.print(f" {var_name}: {display_value}", markup=False)
101 console.print()
104def render_environment_report(console: Console, env: EnvironmentReport) -> None:
105 """Render complete environment report to the console.
107 This is a drop-in replacement for the old _print_environment_report()
108 function, providing identical output using the Renderable protocol.
110 Args:
111 console: Rich console for output.
112 env: Complete environment report.
113 """
114 console.print(
115 Panel.fit(
116 "[bold]Lintro Environment Report[/bold]",
117 border_style="cyan",
118 ),
119 )
120 console.print()
122 # Render each section in order
123 sections: list[Renderable | None] = [
124 env.lintro,
125 env.system,
126 env.python,
127 env.node,
128 env.rust,
129 env.go,
130 env.ruby,
131 env.project,
132 env.ci,
133 ]
135 for section in sections:
136 render_section(console, section)
138 # Environment variables are handled specially (dict, not dataclass)
139 _render_env_vars(console, env.env_vars)