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

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.""" 

8 

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 

16 

17 

18class HeaderOptions(TypedDict, total=False): 

19 """Rich table column options.""" 

20 

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 

30 

31 

32Header = str | HeaderOptions 

33Headers = dict[str, Header] 

34 

35 

36class Context(click.Context): 

37 """SeedboxSync Click context.""" 

38 

39 @cached_property 

40 def app(self) -> Flask: 

41 """ 

42 Return the current Flask application. 

43 

44 Returns: 

45 Flask: The current Flask application. 

46 """ 

47 return current_app 

48 

49 def render(self, data: Iterable[Any], headers: Headers, title: str | None = None) -> str: 

50 """ 

51 Render tabular data as a Rich table. 

52 

53 Args: 

54 data: Tabular data to render. 

55 headers: Column headers. 

56 title: Table title. 

57 

58 Returns: 

59 str: The formatted table.. 

60 """ 

61 console = Console() 

62 table = Table(title=title) 

63 

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 

70 

71 column_title = header.get("title", key) 

72 

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 ) 

84 

85 # Set rows from headers and data 

86 for row in data: 

87 table.add_row(*(str(row.get(column, "")) for column in headers)) 

88 

89 # Return as string 

90 with console.capture() as capture: 

91 console.print(table) 

92 return capture.get()