소스 검색

upd: now code should work without Pandas

Mikael Koli 4 년 전
부모
커밋
732adae3e0
3개의 변경된 파일21개의 추가작업 그리고 10개의 파일을 삭제
  1. 9 5
      redmail/email/attachment.py
  2. 10 4
      redmail/email/body.py
  3. 2 1
      redmail/email/utils.py

+ 9 - 5
redmail/email/attachment.py

@@ -8,8 +8,7 @@ import io
 from pathlib import Path, PurePath
 from typing import Union
 
-from .utils import PIL, plt
-import pandas as pd
+from .utils import PIL, plt, pd
 
 
 class Attachments:
@@ -67,12 +66,17 @@ class Attachments:
             raise TypeError(f"Unknown attachment {type(item)}")
 
     def _get_bytes_named(self, item, name:str) -> bytes:
+
+        has_pandas = pd is not None
+        has_pillow = PIL is not None
+        has_matplotlib = plt is not None
+
         if isinstance(item, str):
             # Considered as raw document
             return item
         elif isinstance(item, PurePath):
             return item.read_bytes()
-        elif isinstance(item, (pd.DataFrame, pd.Series)):
+        elif has_pandas and isinstance(item, (pd.DataFrame, pd.Series)):
             buff = io.BytesIO()
             if name.endswith(".xlsx"):
                 item.to_excel(buff)
@@ -87,12 +91,12 @@ class Attachments:
                 raise ValueError(f"Unknown dataframe conversion for '{name}'")
         elif isinstance(item, (bytes, bytearray)):
             return item
-        elif PIL is not None and isinstance(item, PIL.Image.Image):
+        elif has_pillow and isinstance(item, PIL.Image.Image):
             buf = io.BytesIO()
             item.save(buf, format='PNG')
             buf.seek(0)
             return buf.read()
-        elif plt is not None and isinstance(item, plt.Figure):
+        elif has_matplotlib and isinstance(item, plt.Figure):
             buf = io.BytesIO()
             item.savefig(buf, format=Path(name).suffix[1:])
             buf.seek(0)

+ 10 - 4
redmail/email/body.py

@@ -2,7 +2,7 @@ from email.message import EmailMessage
 import mimetypes
 from io import BytesIO
 from pathlib import Path
-from typing import Dict, Union, ByteString
+from typing import TYPE_CHECKING, Dict, Union, ByteString
 from pathlib import Path
 
 
@@ -12,12 +12,15 @@ from redmail.utils import import_from_string
 from email.utils import make_msgid
 
 from jinja2.environment import Template, Environment
-import pandas as pd
 
 from markupsafe import Markup
 
 # We try to import matplotlib and PIL but if fails, they will be None
-from .utils import PIL, plt
+from .utils import PIL, plt, pd
+
+if TYPE_CHECKING:
+    # For type hinting
+    from pandas import DataFrame
 
 class BodyImage:
     "Utility class to represent image on HTML"
@@ -54,6 +57,9 @@ class Body:
         # TODO: Nicer tables. 
         #   https://stackoverflow.com/a/55356741/13696660
         #   Email HTML (generally) does not support CSS
+        if pd is None:
+            raise ImportError("Missing package 'pandas'. Prettifying tables requires Pandas.")
+        
         extra = {} if extra is None else extra
         df = pd.DataFrame(tbl)
 
@@ -119,7 +125,7 @@ class HTMLBody(Body):
             
             self.attach_imgs(html_msg, cid_path_mapping)
 
-    def render(self, html:str, images:Dict[str, Union[dict, bytes, Path]]=None, tables:Dict[str, pd.DataFrame]=None, jinja_params:dict=None, domain=None):
+    def render(self, html:str, images:Dict[str, Union[dict, bytes, Path]]=None, tables:Dict[str, 'DataFrame']=None, jinja_params:dict=None, domain=None):
         """Render Email HTML body (sets cid for image sources and adds data as other parameters)
 
         Parameters

+ 2 - 1
redmail/email/utils.py

@@ -2,4 +2,5 @@
 from redmail.utils import import_from_string
 
 plt = import_from_string("matplotlib.pyplot", if_missing="ignore")
-PIL = import_from_string("PIL", if_missing="ignore")
+PIL = import_from_string("PIL", if_missing="ignore")
+pd = import_from_string("pandas", if_missing="ignore")