Coverage for seedboxsync/cli/context.py: 93%
29 statements
« prev ^ index » next coverage.py v7.16.1, created at 2026-09-26 17:14 +0000
« prev ^ index » next coverage.py v7.16.1, created at 2026-09-26 17:14 +0000
1#
2# Copyright (C) 2015-2026 Guillaume Kulakowski <guillaume@kulakowski.fr>
3#
4# For the full copyright and license information, please view the LICENSE
5# file that was distributed with this source code.
6#
7"""Build a context used by Click."""
9from collections.abc import Iterable
10from functools import cached_property
11from typing import Any, Literal, TypedDict
12import click
13from rich.console import Console
14from rich.table import Table
15from seedboxsync.core import Flask, current_app
18class HeaderOptions(TypedDict, total=False):
19 """Rich table column options."""
21 title: str
22 justify: Literal["default", "left", "center", "right", "full"]
23 style: str
24 no_wrap: bool
25 overflow: Literal["fold", "crop", "ellipsis", "ignore"]
26 width: int
27 min_width: int
28 max_width: int
29 ratio: int
32Header = str | HeaderOptions
33Headers = dict[str, Header]
36class Context(click.Context):
37 """SeedboxSync Click context."""
39 @cached_property
40 def app(self) -> Flask:
41 """
42 Return the current Flask application.
44 Returns:
45 Flask: The current Flask application.
46 """
47 return current_app
49 def render(self, data: Iterable[Any], headers: Headers, title: str | None = None) -> str:
50 """
51 Render tabular data as a Rich table.
53 Args:
54 data: Tabular data to render.
55 headers: Column headers.
56 title: Table title.
58 Returns:
59 str: The formatted table..
60 """
61 console = Console()
62 table = Table(title=title)
64 # Set columns from headers
65 for key, header in headers.items():
66 if isinstance(header, str):
67 column_title = header
68 table.add_column(column_title)
69 continue
71 column_title = header.get("title", key)
73 table.add_column(
74 column_title,
75 justify=header.get("justify", "left"),
76 style=header.get("style"),
77 no_wrap=header.get("no_wrap", False),
78 overflow=header.get("overflow", "ellipsis"),
79 width=header.get("width"),
80 min_width=header.get("min_width"),
81 max_width=header.get("max_width"),
82 ratio=header.get("ratio"),
83 )
85 # Set rows from headers and data
86 for row in data:
87 table.add_row(*(str(row.get(column, "")) for column in headers))
89 # Return as string
90 with console.capture() as capture:
91 console.print(table)
92 return capture.get()