Coverage for functions \ flipdare \ mailer \ core \ table_email_formatter.py: 100%

44 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2026-05-08 12:22 +1000

1#!/usr/bin/env python 

2# Copyright (c) 2026 Flipdare Pty Ltd. All rights reserved. 

3# 

4# This file is part of Flipdare's proprietary software and contains 

5# confidential and copyrighted material. Unauthorised copying, 

6# modification, distribution, or use of this file is strictly 

7# prohibited without prior written permission from Flipdare Pty Ltd. 

8# 

9# This software includes third-party components licensed under MIT, 

10# BSD, and Apache 2.0 licences. See THIRD_PARTY_NOTICES for details. 

11# 

12 

13from __future__ import annotations 

14 

15from dataclasses import dataclass 

16from typing import override 

17import pandas as pd 

18from pandas.io.formats.style_render import CSSDict 

19from flipdare.app_log import LOG 

20from flipdare.app_types import ReportListType 

21from flipdare.mailer.core.base_email_formatter import BaseEmailFormatter 

22from flipdare.constants import IS_TRACE 

23from flipdare.mailer.core.email_sanitizer import EmailPostSanitizer, EmailPreSanitizer 

24 

25__all__ = ["TableEmailFormatter"] 

26 

27 

28@dataclass(frozen=True) 

29class ExtraEmailInfo: 

30 title: str 

31 message: str 

32 

33 

34class TableEmailFormatter(BaseEmailFormatter): 

35 def __init__( 

36 self, 

37 headers: list[str], 

38 data: ReportListType, 

39 extra: ExtraEmailInfo | None = None, 

40 ) -> None: 

41 if IS_TRACE: 

42 msg = f"Initializing EmailReport with {len(headers)} columns and {len(data)} rows No images." 

43 LOG().trace(msg) 

44 

45 super().__init__(headers=headers, data=data) 

46 self._extra = extra 

47 

48 @override 

49 def tabulate_text(self) -> str: 

50 table_headers = self.headers 

51 pre_data = EmailPreSanitizer(self.data).format(is_html=False) 

52 

53 df = pd.DataFrame(pre_data, columns=table_headers) 

54 txt = df.to_markdown(index=False) 

55 

56 extra = self._extra 

57 post_data = [txt] if extra is None else [f"{extra.message}", txt] 

58 headers = None if extra is None else [extra.title, "Table"] 

59 

60 return EmailPostSanitizer(data=post_data, headers=headers).format(is_html=False) 

61 

62 @override 

63 def tabulate_html(self) -> str: 

64 table_headers = self.headers 

65 pre_data = EmailPreSanitizer(self.data).format(is_html=True) 

66 

67 df = pd.DataFrame(pre_data, columns=table_headers) 

68 styler = df.style.hide(axis="index") 

69 css_style: list[CSSDict] = [ 

70 { 

71 "selector": "th", 

72 "props": [ 

73 ("background-color", "#f2f2f2"), 

74 ("padding", "8px"), 

75 ("text-align", "left"), 

76 ("border", "1px solid #ddd"), 

77 ], 

78 }, 

79 {"selector": "td", "props": [("padding", "8px"), ("border", "1px solid #ddd")]}, 

80 ] 

81 

82 html = styler.set_table_styles(css_style).to_html(index=False, render_links=True) 

83 

84 extra = self._extra 

85 post_data = [html] if extra is None else [f"<p>{extra.message}</p>", html] 

86 headers = None if extra is None else [extra.title, "Table"] 

87 

88 return EmailPostSanitizer(data=post_data, headers=headers).format(is_html=True)