beautiful-python-cli 0.0.0-stage → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,57 @@
1
+ # Layouts and Terminal User Interfaces (TUIs)
2
+
3
+ Use `rich.layout.Layout` to partition the terminal screen into responsive grids, sidebars, headers, and footers for dashboards and monitoring tools.
4
+
5
+ ## 1. Basic Layout Hierarchy
6
+
7
+ ```python
8
+ from rich.layout import Layout
9
+ from rich.panel import Panel
10
+
11
+ layout = Layout()
12
+
13
+ # Split into header, body, and footer
14
+ layout.split_column(
15
+ Layout(name="header", size=3),
16
+ Layout(name="body", ratio=1),
17
+ Layout(name="footer", size=3),
18
+ )
19
+
20
+ # Split the body into sidebar and main area
21
+ layout["body"].split_row(
22
+ Layout(name="sidebar", ratio=1),
23
+ Layout(name="main", ratio=3),
24
+ )
25
+
26
+ # Populate panels
27
+ layout["header"].update(Panel("[accent]Monitoring Dashboard[/accent]", style="bold"))
28
+ layout["sidebar"].update(Panel("Node Status\n• Node 1: [success]OK[/success]\n• Node 2: [warning]BUSY[/warning]"))
29
+ layout["main"].update(Panel("Recent Telemetry Events", border_style="cyan"))
30
+ layout["footer"].update(Panel("[muted]Press Ctrl+C to exit | Refresh: 1.0s[/muted]"))
31
+
32
+ console.print(layout)
33
+ ```
34
+
35
+ ## 2. Dynamic Live TUI
36
+
37
+ Combine `Layout` with `rich.live.Live` for continuously updating full-screen or embedded monitoring:
38
+
39
+ ```python
40
+ import time
41
+ from rich.live import Live
42
+
43
+ with Live(layout, console=console, screen=False, refresh_per_second=4) as live:
44
+ try:
45
+ while True:
46
+ # Update individual panes without re-creating the layout tree
47
+ layout["main"].update(render_telemetry_table())
48
+ time.sleep(0.25)
49
+ except KeyboardInterrupt:
50
+ pass
51
+ ```
52
+
53
+ ## 3. Best Practices
54
+ - **Use `screen=False` by default**: Leaves scrollback history intact when the command terminates. Only use `screen=True` for full-screen curses-style apps.
55
+ - **Set fixed `size` for headers and footers**: Let the body use `ratio=1` to absorb the remaining vertical space.
56
+ - **Test at 80x24**: Ensure the layout degrades gracefully in small terminal windows without raising truncation errors.
57
+ - **Provide clean exit handling**: Catch `KeyboardInterrupt` cleanly so the terminal state restores properly.
@@ -0,0 +1,91 @@
1
+ # Interactive Prompts and User Input
2
+
3
+ Use `rich.prompt` to collect interactive input from users in terminal sessions while preserving styling and validation.
4
+
5
+ ## 1. Text Prompt
6
+
7
+ Collect strings with default values and styling:
8
+
9
+ ```python
10
+ from rich.prompt import Prompt
11
+
12
+ # Basic prompt with default
13
+ username = Prompt.ask("Enter username", default="admin", console=console)
14
+
15
+ # Styled prompt with required non-empty input
16
+ project = Prompt.ask(
17
+ "[bold cyan]Project name[/bold cyan]",
18
+ default="my-cli",
19
+ console=console,
20
+ )
21
+ ```
22
+
23
+ ## 2. Constrained Choices
24
+
25
+ Restrict input to a list of allowed values:
26
+
27
+ ```python
28
+ env = Prompt.ask(
29
+ "Deployment target",
30
+ choices=["development", "staging", "production"],
31
+ default="development",
32
+ case_sensitive=False,
33
+ console=console,
34
+ )
35
+ ```
36
+
37
+ Rich automatically validates user input against the choices, re-prompting with an error message if an invalid value is entered.
38
+
39
+ ## 3. Confirmations (Yes/No)
40
+
41
+ Ask binary questions:
42
+
43
+ ```python
44
+ from rich.prompt import Confirm
45
+
46
+ if Confirm.ask("Proceed with deployment?", default=True, console=console):
47
+ console.print("[success]Deploying…[/success]")
48
+ else:
49
+ console.print("[warning]Aborted by user.[/warning]")
50
+ raise SystemExit(1)
51
+ ```
52
+
53
+ ## 4. Typed Numeric Prompts
54
+
55
+ Enforce integers or floats:
56
+
57
+ ```python
58
+ from rich.prompt import IntPrompt, FloatPrompt
59
+
60
+ port = IntPrompt.ask("Listen port", default=8080, console=console)
61
+ rate = FloatPrompt.ask("Sample rate", default=0.05, console=console)
62
+ ```
63
+
64
+ ## 5. Password & Secret Input
65
+
66
+ Hide input characters for credentials, tokens, or private keys:
67
+
68
+ ```python
69
+ api_key = Prompt.ask(
70
+ "[accent]API Token[/accent]",
71
+ password=True,
72
+ console=console,
73
+ )
74
+ ```
75
+
76
+ Never print the collected secret back to the terminal or logs.
77
+
78
+ ## 6. Non-Interactive Fallbacks & Guardrails
79
+
80
+ Interactive prompts will fail or block indefinitely in CI/CD, cron jobs, or redirected stdin (`sys.stdin.isatty() is False`). Always guard prompts:
81
+
82
+ ```python
83
+ import sys
84
+
85
+ def get_target_environment(cli_flag: str | None) -> str:
86
+ if cli_flag:
87
+ return cli_flag
88
+ if not sys.stdin.isatty():
89
+ return "development" # Non-interactive default or fail explicitly
90
+ return Prompt.ask("Target environment", choices=["dev", "prod"], default="dev")
91
+ ```
@@ -0,0 +1,118 @@
1
+ # Rich components and API selection
2
+
3
+ Use this as a focused API map. Confirm exact signatures against the Rich version already installed in the project.
4
+
5
+ ## Console and themes
6
+
7
+ Create one application-level console. Keep stdout and stderr separate when the command supports machine-readable output.
8
+
9
+ ```python
10
+ from rich.console import Console
11
+ from rich.theme import Theme
12
+
13
+ theme = Theme({
14
+ "success": "bold green",
15
+ "warning": "bold yellow",
16
+ "error": "bold red",
17
+ "info": "cyan",
18
+ "muted": "dim",
19
+ "accent": "bold bright_magenta",
20
+ })
21
+
22
+ console = Console(theme=theme)
23
+ error_console = Console(stderr=True, theme=theme)
24
+ ```
25
+
26
+ Do not set `force_terminal=True` in normal application code. Let Rich detect terminal capability. Use `no_color=True` only when an explicit no-color mode is selected.
27
+
28
+ ## Core renderables
29
+
30
+ | Component | Use it for |
31
+ |---|---|
32
+ | `Panel` | A cohesive summary, warning, or grouped section |
33
+ | `Table` | Structured rows and columns |
34
+ | `Rule` | Major section separators |
35
+ | `Columns` | Compact side-by-side renderables |
36
+ | `Group` | Grouping multiple renderables into one display |
37
+ | `Tree` | Hierarchical data such as directories or attack paths |
38
+ | `Layout` | Responsive screen partitioning (header, body, sidebar, footer) |
39
+ | `Prompt` / `Confirm` | Interactive user input with validation and defaults |
40
+ | `Syntax` | Source code with syntax highlighting |
41
+ | `Traceback` | Readable, formatted stack traces with frame suppression |
42
+ | `Markdown` | Render Markdown in a terminal |
43
+ | `Pretty` / `inspect` | Object introspection and structure formatting |
44
+ | `Text` | Fine-grained spans, styling, and markup-safe text |
45
+
46
+ Example:
47
+
48
+ ```python
49
+ from rich.panel import Panel
50
+ from rich.table import Table
51
+ from rich.text import Text
52
+
53
+ table = Table(title="Findings", expand=True)
54
+ table.add_column("Severity", no_wrap=True)
55
+ table.add_column("Finding", ratio=2)
56
+ table.add_column("Status", justify="right")
57
+
58
+ table.add_row(
59
+ Text("HIGH", style="bold red"),
60
+ "Unauthenticated endpoint disclosure",
61
+ "[warning]Needs review[/warning]",
62
+ )
63
+
64
+ console.print(Panel(table, title="[accent]Assessment summary[/accent]"))
65
+ ```
66
+
67
+ ## Tables
68
+
69
+ - Use `expand=True` when the table should occupy available width; otherwise let it size naturally.
70
+ - Use `ratio` to allocate flexible width between descriptive columns.
71
+ - Use `no_wrap=True` only for short values such as IDs, severity, and status.
72
+ - Use `overflow="fold"` for descriptions that must remain readable; use `ellipsis` for secondary text.
73
+ - Right-align numeric columns.
74
+ - Add a table caption or explicit empty-state text when no records exist.
75
+ - Avoid very wide tables. Prefer a concise default view and an optional verbose/details view.
76
+
77
+ ## Progress columns
78
+
79
+ Common columns:
80
+
81
+ - `SpinnerColumn`
82
+ - `TextColumn`
83
+ - `BarColumn`
84
+ - `TaskProgressColumn`
85
+ - `MofNCompleteColumn`
86
+ - `TimeElapsedColumn`
87
+ - `TimeRemainingColumn`
88
+ - `DownloadColumn`
89
+ - `TransferSpeedColumn`
90
+ - `FileSizeColumn`
91
+
92
+ Build a reusable `Progress` factory if multiple commands share the same style. Use only columns whose values are meaningful for the task.
93
+
94
+ ## Logging
95
+
96
+ Use `rich.logging.RichHandler` with the standard `logging` module when possible. Configure it once at the CLI boundary. Avoid configuring handlers from imported library modules.
97
+
98
+ ## Windows and UTF-8 terminal compatibility
99
+
100
+ On Windows systems (PowerShell / Command Prompt), ensure UTF-8 encoding is enabled to avoid `UnicodeEncodeError`:
101
+
102
+ ```python
103
+ import sys
104
+
105
+ # Ensure UTF-8 output encoding for terminals
106
+ if sys.platform == "win32" and sys.stdout.encoding.lower() != "utf-8":
107
+ try:
108
+ sys.stdout.reconfigure(encoding="utf-8")
109
+ sys.stderr.reconfigure(encoding="utf-8")
110
+ except AttributeError:
111
+ pass
112
+ ```
113
+
114
+ Rich natively handles Windows console color (VT100) via colorama integration. Avoid manual ANSI sequences.
115
+
116
+ ## Dependency policy
117
+
118
+ Rich is the core dependency. Typer, Click, Questionary, Loguru, and PyFiglet are optional. Do not add them merely for decoration; use the project's existing CLI and logging stack.
@@ -0,0 +1,81 @@
1
+ # Testing, accessibility, and output contracts
2
+
3
+ ## Terminal and redirected output
4
+
5
+ - Let Rich detect terminal capability; do not force ANSI output by default.
6
+ - Disable animated progress when `console.is_terminal` is false.
7
+ - Respect `NO_COLOR` and explicit `--no-color`.
8
+ - Test SSH, CI, redirected stdout, and narrow terminal widths.
9
+ - Do not rely on Unicode symbols being available. Use text labels as a fallback.
10
+ - Never use color as the only indicator of severity or success.
11
+
12
+ ## stdout, stderr, and JSON
13
+
14
+ If stdout is a machine-readable stream, keep it free of banners, progress bars, logs, and status messages.
15
+
16
+ ```python
17
+ import json
18
+ import sys
19
+ from rich.console import Console
20
+
21
+ data_console = Console(file=sys.stdout, no_color=True)
22
+ diagnostic_console = Console(file=sys.stderr)
23
+
24
+ if args.json:
25
+ json.dump(result, sys.stdout)
26
+ sys.stdout.write("\n")
27
+ else:
28
+ render_human_result(data_console, result)
29
+ ```
30
+
31
+ Send progress and diagnostics to stderr when stdout is reserved for JSON, CSV, or another pipeable format. Keep `--quiet`, `--plain`, and `--json` behavior documented and tested.
32
+
33
+ ## Narrow widths
34
+
35
+ - Avoid hardcoded terminal widths in normal rendering.
36
+ - Use flexible table columns and wrapping.
37
+ - Test at widths such as 40, 60, 80, and 120 columns.
38
+ - Keep essential identifiers visible; wrap or truncate only secondary descriptions.
39
+
40
+ ## Snapshot and unit testing
41
+
42
+ Rich supports an in-memory console:
43
+
44
+ ```python
45
+ from io import StringIO
46
+ from rich.console import Console
47
+
48
+ buffer = StringIO()
49
+ test_console = Console(
50
+ file=buffer,
51
+ force_terminal=True,
52
+ width=80,
53
+ record=True,
54
+ )
55
+ test_console.print("[success]Completed[/success]")
56
+
57
+ plain_text = test_console.export_text(styles=False)
58
+ assert "Completed" in plain_text
59
+ ```
60
+
61
+ Test semantic content, not brittle ANSI escape sequences. Add tests for:
62
+ - empty result sets
63
+ - success and failure states
64
+ - exceptions and Ctrl-C/cancellation
65
+ - `--no-color` / `NO_COLOR`
66
+ - non-TTY and redirected output
67
+ - JSON purity
68
+ - narrow terminal widths
69
+ - progress completion and cleanup
70
+
71
+ For deterministic snapshots, fix time values and avoid asserting spinner animation frames.
72
+
73
+ ## UX checklist
74
+
75
+ - Can a user identify the current operation immediately?
76
+ - Is the difference between unknown progress and measurable progress clear?
77
+ - Are success, warning, and failure distinguishable without color?
78
+ - Are tables readable when the terminal is narrow?
79
+ - Can users copy results without decorative noise?
80
+ - Does the application still work when output is piped?
81
+ - Does every spinner/live display stop on all exit paths?
@@ -0,0 +1,88 @@
1
+ # Tracebacks, Syntax, and Introspection
2
+
3
+ Use Rich's diagnostics to make errors actionable and debugging intuitive without leaking internal implementation details to end users.
4
+
5
+ ## 1. Polished Tracebacks
6
+
7
+ Install Rich's traceback handler at the application boundary (entry point):
8
+
9
+ ```python
10
+ from rich.traceback import install
11
+
12
+ # Production mode: concise, syntax-highlighted tracebacks with suppressed internal frames
13
+ install(
14
+ show_locals=False,
15
+ max_frames=5,
16
+ suppress=["click", "typer", "urllib3", "requests"],
17
+ )
18
+
19
+ # Debug mode (--debug / --verbose): include local variable values for troubleshooting
20
+ if debug_mode:
21
+ install(show_locals=True, max_frames=20)
22
+ ```
23
+
24
+ ### Guidelines
25
+ - In production, keep `show_locals=False` to prevent leaking sensitive variables (tokens, passwords, PII) in stack dumps.
26
+ - Suppress framework frames (`click`, `typer`, `asyncio`) to direct attention to user-authored code.
27
+ - For expected operational errors (e.g. file not found, bad network connection), print a concise error panel instead of dumping a full stack trace:
28
+
29
+ ```python
30
+ try:
31
+ connect_to_server(host)
32
+ except ConnectionError as err:
33
+ error_console.print(
34
+ Panel(
35
+ f"[error]Could not connect to {host}:[/error] {err}\n"
36
+ "[muted]Check your network connection or verify --host.[/muted]",
37
+ title="[error]Connection Failed[/error]",
38
+ border_style="red",
39
+ )
40
+ )
41
+ raise SystemExit(1)
42
+ ```
43
+
44
+ ## 2. Syntax Highlighting
45
+
46
+ Render snippets of Python, JSON, YAML, or SQL directly in the terminal:
47
+
48
+ ```python
49
+ from rich.syntax import Syntax
50
+
51
+ code_snippet = """def hello(name: str) -> str:
52
+ return f"Hello, {name}!"
53
+ """
54
+
55
+ syntax = Syntax(
56
+ code_snippet,
57
+ lexer="python",
58
+ theme="monokai",
59
+ line_numbers=True,
60
+ word_wrap=True,
61
+ )
62
+ console.print(syntax)
63
+ ```
64
+
65
+ ## 3. Object Introspection with `inspect`
66
+
67
+ Debug complex objects, types, or modules interactively:
68
+
69
+ ```python
70
+ from rich import inspect
71
+
72
+ # Inspect attributes and methods
73
+ inspect(my_object, methods=True)
74
+
75
+ # Inspect with docstrings and help
76
+ inspect(my_object, help=True)
77
+ ```
78
+
79
+ ## 4. Pretty-Printing Structures
80
+
81
+ Format complex dictionaries, lists, or dataclasses without messy `pprint`:
82
+
83
+ ```python
84
+ from rich.pretty import pprint
85
+
86
+ data = {"user": "alice", "roles": ["admin", "developer"], "active": True}
87
+ pprint(data, indent_guides=True, expand_all=False)
88
+ ```
@@ -0,0 +1 @@
1
+ rich>=13.7