sqlmesh.utils.rich
1from __future__ import annotations 2 3import typing as t 4 5import re 6 7from rich.console import Console 8from rich.progress import Column, ProgressColumn, Task, Text 9from rich.theme import Theme 10from rich.table import Table 11from rich.align import Align 12 13if t.TYPE_CHECKING: 14 import pandas as pd 15 16theme = Theme( 17 { 18 "added": "green", 19 "removed": "red", 20 "direct": "magenta", # directly modified 21 "indirect": "yellow", # indirectly modified 22 "metadata": "cyan", # metadata updated 23 } 24) 25 26console = Console(theme=theme) 27 28 29class BatchColumn(ProgressColumn): 30 """Renders completed count/total, "pending". 31 32 Space pads the completed count so that progress length does not change as task progresses 33 past powers of 10. 34 35 Source: https://rich.readthedocs.io/en/stable/reference/progress.html#rich.progress.MofNCompleteColumn 36 37 Args: 38 separator: Text to separate completed and total values. Defaults to "/". 39 """ 40 41 def __init__(self, separator: str = "/", table_column: t.Optional[Column] = None): 42 self.separator = separator 43 super().__init__(table_column=table_column) 44 45 def render(self, task: Task) -> Text: 46 """Show completed count/total, "pending".""" 47 total = int(task.total) if task.total is not None else "?" 48 completed = int(task.completed) 49 50 if completed == 0 and task.total is not None and task.total > 0: 51 return Text("pending", style="progress.download") 52 53 total_width = len(str(total)) 54 return Text( 55 f"{completed:{total_width}d}{self.separator}{total}", 56 style="progress.download", 57 ) 58 59 60def strip_ansi_codes(text: str) -> str: 61 """Strip ANSI color codes and styling from text.""" 62 ansi_escape = re.compile(r"\x1b\[[0-9;]*[a-zA-Z]") 63 return ansi_escape.sub("", text).strip() 64 65 66def df_to_table( 67 header: str, 68 df: pd.DataFrame, 69 show_index: bool = True, 70 index_name: str = "Row", 71) -> Table: 72 """Convert a pandas.DataFrame obj into a rich.Table obj. 73 Args: 74 df (DataFrame): A Pandas DataFrame to be converted to a rich Table. 75 rich_table (Table): A rich Table that should be populated by the DataFrame values. 76 show_index (bool): Add a column with a row count to the table. Defaults to True. 77 index_name (str, optional): The column name to give to the index column. Defaults to None, showing no value. 78 Returns: 79 Table: The rich Table instance passed, populated with the DataFrame values.""" 80 81 rich_table = Table(title=f"[bold red]{header}[/bold red]", show_lines=True, min_width=60) 82 if show_index: 83 index_name = str(index_name) if index_name else "" 84 rich_table.add_column(Align.center(index_name)) 85 86 for column in df.columns: 87 column_name = column if isinstance(column, str) else ": ".join(str(col) for col in column) 88 89 # Color coding unit test columns (expected/actual), can be removed or refactored if df_to_table is used elswhere too 90 lower = column_name.lower() 91 if "expected" in lower: 92 column_name = f"[green]{column_name}[/green]" 93 elif "actual" in lower: 94 column_name = f"[red]{column_name}[/red]" 95 96 rich_table.add_column(Align.center(column_name)) 97 98 for index, value_list in zip(df.index, df.values.tolist()): 99 row = [str(index)] if show_index else [] 100 row += [str(x) for x in value_list] 101 center = [Align.center(x) for x in row] 102 rich_table.add_row(*center) 103 104 return rich_table
theme =
<rich.theme.Theme object>
console =
<console width=80 None>
class
BatchColumn(rich.progress.ProgressColumn):
30class BatchColumn(ProgressColumn): 31 """Renders completed count/total, "pending". 32 33 Space pads the completed count so that progress length does not change as task progresses 34 past powers of 10. 35 36 Source: https://rich.readthedocs.io/en/stable/reference/progress.html#rich.progress.MofNCompleteColumn 37 38 Args: 39 separator: Text to separate completed and total values. Defaults to "/". 40 """ 41 42 def __init__(self, separator: str = "/", table_column: t.Optional[Column] = None): 43 self.separator = separator 44 super().__init__(table_column=table_column) 45 46 def render(self, task: Task) -> Text: 47 """Show completed count/total, "pending".""" 48 total = int(task.total) if task.total is not None else "?" 49 completed = int(task.completed) 50 51 if completed == 0 and task.total is not None and task.total > 0: 52 return Text("pending", style="progress.download") 53 54 total_width = len(str(total)) 55 return Text( 56 f"{completed:{total_width}d}{self.separator}{total}", 57 style="progress.download", 58 )
Renders completed count/total, "pending".
Space pads the completed count so that progress length does not change as task progresses past powers of 10.
Source: https://rich.readthedocs.io/en/stable/reference/progress.html#rich.progress.MofNCompleteColumn
Arguments:
- separator: Text to separate completed and total values. Defaults to "/".
def
render(self, task: rich.progress.Task) -> rich.text.Text:
46 def render(self, task: Task) -> Text: 47 """Show completed count/total, "pending".""" 48 total = int(task.total) if task.total is not None else "?" 49 completed = int(task.completed) 50 51 if completed == 0 and task.total is not None and task.total > 0: 52 return Text("pending", style="progress.download") 53 54 total_width = len(str(total)) 55 return Text( 56 f"{completed:{total_width}d}{self.separator}{total}", 57 style="progress.download", 58 )
Show completed count/total, "pending".
Inherited Members
- rich.progress.ProgressColumn
- max_refresh
- get_table_column
def
strip_ansi_codes(text: str) -> str:
61def strip_ansi_codes(text: str) -> str: 62 """Strip ANSI color codes and styling from text.""" 63 ansi_escape = re.compile(r"\x1b\[[0-9;]*[a-zA-Z]") 64 return ansi_escape.sub("", text).strip()
Strip ANSI color codes and styling from text.
def
df_to_table( header: str, df: pandas.core.frame.DataFrame, show_index: bool = True, index_name: str = 'Row') -> rich.table.Table:
67def df_to_table( 68 header: str, 69 df: pd.DataFrame, 70 show_index: bool = True, 71 index_name: str = "Row", 72) -> Table: 73 """Convert a pandas.DataFrame obj into a rich.Table obj. 74 Args: 75 df (DataFrame): A Pandas DataFrame to be converted to a rich Table. 76 rich_table (Table): A rich Table that should be populated by the DataFrame values. 77 show_index (bool): Add a column with a row count to the table. Defaults to True. 78 index_name (str, optional): The column name to give to the index column. Defaults to None, showing no value. 79 Returns: 80 Table: The rich Table instance passed, populated with the DataFrame values.""" 81 82 rich_table = Table(title=f"[bold red]{header}[/bold red]", show_lines=True, min_width=60) 83 if show_index: 84 index_name = str(index_name) if index_name else "" 85 rich_table.add_column(Align.center(index_name)) 86 87 for column in df.columns: 88 column_name = column if isinstance(column, str) else ": ".join(str(col) for col in column) 89 90 # Color coding unit test columns (expected/actual), can be removed or refactored if df_to_table is used elswhere too 91 lower = column_name.lower() 92 if "expected" in lower: 93 column_name = f"[green]{column_name}[/green]" 94 elif "actual" in lower: 95 column_name = f"[red]{column_name}[/red]" 96 97 rich_table.add_column(Align.center(column_name)) 98 99 for index, value_list in zip(df.index, df.values.tolist()): 100 row = [str(index)] if show_index else [] 101 row += [str(x) for x in value_list] 102 center = [Align.center(x) for x in row] 103 rich_table.add_row(*center) 104 105 return rich_table
Convert a pandas.DataFrame obj into a rich.Table obj.
Arguments:
- df (DataFrame): A Pandas DataFrame to be converted to a rich Table.
- rich_table (Table): A rich Table that should be populated by the DataFrame values.
- show_index (bool): Add a column with a row count to the table. Defaults to True.
- index_name (str, optional): The column name to give to the index column. Defaults to None, showing no value.
Returns:
Table: The rich Table instance passed, populated with the DataFrame values.