Skip to content

Commit f2dd165

Browse files
authored
Added TableBlock for test results sampe
Table Block
2 parents f0e25ad + 9963d18 commit f2dd165

File tree

42 files changed

+3875
-37
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+3875
-37
lines changed

dev-requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@ types-PyYAML
1818
types-setuptools
1919
types-retry
2020
types-decorator
21+
types-tabulate

elementary/messages/blocks.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from enum import Enum
2-
from typing import List, Optional, Union
2+
from typing import Any, Dict, List, Optional, Union
33

44
from pydantic import BaseModel
55
from typing_extensions import Literal
@@ -94,6 +94,21 @@ class FactListBlock(BaseBlock):
9494
facts: List[FactBlock]
9595

9696

97+
class TableBlock(BaseBlock):
98+
type: Literal["table"] = "table"
99+
headers: List[str]
100+
rows: List[List[Any]]
101+
102+
@classmethod
103+
def from_dicts(cls, data: List[Dict[str, Any]]) -> "TableBlock":
104+
if not data:
105+
return cls(headers=[], rows=[])
106+
107+
headers = list(data[0].keys())
108+
rows = [[row.get(header) for header in headers] for row in data]
109+
return cls(headers=headers, rows=rows)
110+
111+
97112
class ExpandableBlock(BaseBlock):
98113
type: Literal["expandable"] = "expandable"
99114
title: str
@@ -107,6 +122,7 @@ class ExpandableBlock(BaseBlock):
107122
DividerBlock,
108123
LinesBlock,
109124
FactListBlock,
125+
TableBlock,
110126
"ExpandableBlock",
111127
]
112128

elementary/messages/formats/adaptive_cards.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
LineBlock,
1414
LinesBlock,
1515
LinkBlock,
16+
TableBlock,
1617
TextBlock,
1718
TextStyle,
1819
)
@@ -118,6 +119,31 @@ def format_fact_list_block(block: FactListBlock) -> Dict[str, Any]:
118119
}
119120

120121

122+
def format_table_block(block: TableBlock) -> Dict[str, Any]:
123+
return {
124+
"type": "Table",
125+
"columns": [{"width": 1} for _ in block.headers],
126+
"rows": [
127+
{
128+
"type": "TableRow",
129+
"cells": [
130+
{
131+
"type": "TableCell",
132+
"items": [
133+
{
134+
"type": "TextBlock",
135+
"text": str(cell),
136+
}
137+
],
138+
}
139+
for cell in row
140+
],
141+
}
142+
for row in [block.headers, *block.rows]
143+
],
144+
}
145+
146+
121147
def format_message_block(
122148
block: MessageBlock, color: Optional[Color] = None
123149
) -> List[Dict[str, Any]]:
@@ -131,6 +157,8 @@ def format_message_block(
131157
return [format_fact_list_block(block)]
132158
elif isinstance(block, ExpandableBlock):
133159
return format_expandable_block(block)
160+
elif isinstance(block, TableBlock):
161+
return [format_table_block(block)]
134162
else:
135163
raise ValueError(f"Unsupported message block type: {type(block)}")
136164

elementary/messages/formats/block_kit.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
import json
12
from typing import Any, Dict, List, Optional, Tuple
23

34
from slack_sdk.models import blocks as slack_blocks
5+
from tabulate import tabulate
46

57
from elementary.messages.blocks import (
68
CodeBlock,
@@ -15,6 +17,7 @@
1517
LineBlock,
1618
LinesBlock,
1719
LinkBlock,
20+
TableBlock,
1821
TextBlock,
1922
TextStyle,
2023
)
@@ -31,6 +34,7 @@
3134
class BlockKitBuilder:
3235
_SECONDARY_FACT_CHUNK_SIZE = 2
3336
_LONGEST_MARKDOWN_SUFFIX_LEN = 3 # length of markdown's code suffix (```)
37+
_MAX_CELL_LENGTH_BY_COLUMN_COUNT = {4: 11, 3: 14, 2: 22, 1: 40, 0: 40}
3438

3539
def __init__(self) -> None:
3640
self._blocks: List[dict] = []
@@ -63,6 +67,13 @@ def _format_line_block_text(self, block: LineBlock) -> str:
6367
[self._format_inline_block(inline) for inline in block.inlines]
6468
)
6569

70+
def _format_table_cell(self, cell_value: Any, column_count: int) -> str:
71+
value = str(cell_value)
72+
max_cell_length = self._MAX_CELL_LENGTH_BY_COLUMN_COUNT[column_count]
73+
if len(value) > max_cell_length:
74+
return value[: max_cell_length - 2] + ".."
75+
return value
76+
6677
def _format_markdown_section_text(self, text: str) -> dict:
6778
if len(text) > slack_blocks.SectionBlock.text_max_length:
6879
text = (
@@ -157,6 +168,25 @@ def _add_divider_block(self, block: DividerBlock) -> None:
157168
self._add_block({"type": "divider"})
158169
self._is_divided = True
159170

171+
def _add_table_block(self, block: TableBlock) -> None:
172+
column_count = len(block.headers)
173+
if column_count not in self._MAX_CELL_LENGTH_BY_COLUMN_COUNT:
174+
dicts = [
175+
{header: cell for header, cell in zip(block.headers, row)}
176+
for row in block.rows
177+
]
178+
table_text = json.dumps(dicts, indent=2)
179+
else:
180+
new_rows = [
181+
[self._format_table_cell(cell, column_count) for cell in row]
182+
for row in block.rows
183+
]
184+
new_headers = [
185+
self._format_table_cell(cell, column_count) for cell in block.headers
186+
]
187+
table_text = tabulate(new_rows, headers=new_headers, tablefmt="simple")
188+
self._add_block(self._format_markdown_section(f"```{table_text}```"))
189+
160190
def _add_expandable_block(self, block: ExpandableBlock) -> None:
161191
"""
162192
Expandable blocks are not supported in Slack Block Kit.
@@ -183,6 +213,8 @@ def _add_message_block(self, block: MessageBlock) -> None:
183213
self._add_divider_block(block)
184214
elif isinstance(block, ExpandableBlock):
185215
self._add_expandable_block(block)
216+
elif isinstance(block, TableBlock):
217+
self._add_table_block(block)
186218
else:
187219
raise ValueError(f"Unsupported message block type: {type(block)}")
188220

elementary/messages/message_body.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
FactListBlock,
1111
HeaderBlock,
1212
LinesBlock,
13+
TableBlock,
1314
)
1415

1516

@@ -26,6 +27,7 @@ class Color(Enum):
2627
LinesBlock,
2728
FactListBlock,
2829
ExpandableBlock,
30+
TableBlock,
2931
]
3032

3133

elementary/monitor/alerts/alert_messages/builder.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
LineBlock,
2525
LinesBlock,
2626
LinkBlock,
27+
TableBlock,
2728
TextBlock,
2829
TextStyle,
2930
)
@@ -284,9 +285,14 @@ def _get_result_blocks(
284285
]
285286
)
286287
)
287-
result_blocks.append(
288-
JsonCodeBlock(content=result_sample),
289-
)
288+
if isinstance(result_sample, list) and len(result_sample[0].keys()) <= 4:
289+
result_blocks.append(
290+
TableBlock.from_dicts(result_sample),
291+
)
292+
else:
293+
result_blocks.append(
294+
JsonCodeBlock(content=result_sample),
295+
)
290296
if result_query:
291297
result_blocks.append(
292298
LinesBlock(

tests/unit/alerts/alert_messages/fixtures/adaptive_card_dbt_test_alert_status-error_link-True_description-True_tags-True_owners-True_table-True_error-True_sample-True_env-True.json

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -117,16 +117,59 @@
117117
"wrap": true
118118
},
119119
{
120-
"type": "Container",
121-
"style": "emphasis",
122-
"items": [
120+
"type": "Table",
121+
"columns": [
123122
{
124-
"type": "RichTextBlock",
125-
"inlines": [
123+
"width": 1
124+
},
125+
{
126+
"width": 1
127+
}
128+
],
129+
"rows": [
130+
{
131+
"type": "TableRow",
132+
"cells": [
126133
{
127-
"type": "TextRun",
128-
"text": "{\n \"column1\": \"value1\",\n \"column2\": \"value2\"\n}",
129-
"fontType": "Monospace"
134+
"type": "TableCell",
135+
"items": [
136+
{
137+
"type": "TextBlock",
138+
"text": "column1"
139+
}
140+
]
141+
},
142+
{
143+
"type": "TableCell",
144+
"items": [
145+
{
146+
"type": "TextBlock",
147+
"text": "column2"
148+
}
149+
]
150+
}
151+
]
152+
},
153+
{
154+
"type": "TableRow",
155+
"cells": [
156+
{
157+
"type": "TableCell",
158+
"items": [
159+
{
160+
"type": "TextBlock",
161+
"text": "value1"
162+
}
163+
]
164+
},
165+
{
166+
"type": "TableCell",
167+
"items": [
168+
{
169+
"type": "TextBlock",
170+
"text": "value2"
171+
}
172+
]
130173
}
131174
]
132175
}

tests/unit/alerts/alert_messages/fixtures/adaptive_card_dbt_test_alert_status-fail_link-True_description-True_tags-True_owners-True_table-True_error-True_sample-True_env-False.json

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -117,16 +117,59 @@
117117
"wrap": true
118118
},
119119
{
120-
"type": "Container",
121-
"style": "emphasis",
122-
"items": [
120+
"type": "Table",
121+
"columns": [
123122
{
124-
"type": "RichTextBlock",
125-
"inlines": [
123+
"width": 1
124+
},
125+
{
126+
"width": 1
127+
}
128+
],
129+
"rows": [
130+
{
131+
"type": "TableRow",
132+
"cells": [
126133
{
127-
"type": "TextRun",
128-
"text": "{\n \"column1\": \"value1\",\n \"column2\": \"value2\"\n}",
129-
"fontType": "Monospace"
134+
"type": "TableCell",
135+
"items": [
136+
{
137+
"type": "TextBlock",
138+
"text": "column1"
139+
}
140+
]
141+
},
142+
{
143+
"type": "TableCell",
144+
"items": [
145+
{
146+
"type": "TextBlock",
147+
"text": "column2"
148+
}
149+
]
150+
}
151+
]
152+
},
153+
{
154+
"type": "TableRow",
155+
"cells": [
156+
{
157+
"type": "TableCell",
158+
"items": [
159+
{
160+
"type": "TextBlock",
161+
"text": "value1"
162+
}
163+
]
164+
},
165+
{
166+
"type": "TableCell",
167+
"items": [
168+
{
169+
"type": "TextBlock",
170+
"text": "value2"
171+
}
172+
]
130173
}
131174
]
132175
}

0 commit comments

Comments
 (0)