Source code for simple_report.utils

import datetime
from jinja2 import Environment, FileSystemLoader
from loguru import logger
from typing import Any, Union

from . import TEMPLATE_DIR, SCRIPTS_DIR

#----------------------------------------------------------------------------------------------------------------------#
# region COLOR MAP
#----------------------------------------------------------------------------------------------------------------------#
[docs] class ColorMap: """ Color map object for handling the color space of the report """ def __init__(self, config: dict[str, Any]): """ Initialize a new color map given a config dict Args: config (dict[str, Any]): The configuration for this report. Mainly responsible for defining new color profiles that can later be used """ self.config = config # Default color map - Maps the default bootstrap colors to their respective color names self.cm = { 'blue': 'primary', 'gray': 'secondary', 'green': 'success', 'red': 'danger', 'yellow': 'warning', 'teal': 'info', 'black': 'dark', 'primary': 'primary', 'secondary': 'secondary', 'success': 'success', 'danger': 'danger', 'warning': 'warning', 'info': 'info', 'dark': 'dark', 'light': 'light', } # Create the custom color CSS that will be injected and make the profiles available in the color map self._make_custom_color_css() for cc in self.config['custom_colors']: self.cm[cc] = cc #---------------# # Magic Methods # #---------------# def __getitem__(self, key: str) -> str: """ Verify the color name and return the proper color mapping """ return self.verify_and_get_color(key) #---------# # Private # #---------# def _make_custom_color_css(self): """ Create the custom color css file """ # Prepare the jinja templater file_loader = FileSystemLoader(TEMPLATE_DIR) jinja_env = Environment(loader=file_loader) # Create CSS string color_items = [v | {'name': k} for k,v in self.config['custom_colors'].items()] template = jinja_env.get_template('colors.html') css = template.render(color_items=color_items) # Dump to scripts dir custom_color_file = SCRIPTS_DIR / 'custom_colors.css' custom_color_file.write_text(css) #-----# # API # #-----#
[docs] def verify_and_get_color(self, color: str) -> str: """ Check that the requested color is actually available Args: color (str): Color to check Returns: str - color name to use """ if color not in self.cm: msg = f'No color `{color}` found. Available: {self.cm.keys()}' logger.error(msg) raise RuntimeError(msg) return self.cm[color]
[docs] def get_default_color(self, field: str, color_mode: str) -> str: """ Determine the correct default color for a given color mode and field Args: field (str): The type/field the color should be used for color_mode (str): The color mode of the report, i.e., either `light` or `dark` Returns: str - The color to be used """ color = self.config['default_colors'].get(field, {}).get(color_mode, None) if color is None: msg = f'No default color defined for `{field}` with color mode `{color_mode}`' logger.error(msg) raise RuntimeError(msg) return color
[docs] def get_site_colors(self, color_mode: str): """ Get the background color for the website depending on the color mode """ return self.config['site'][color_mode]
#----------------------------------------------------------------------------------------------------------------------# # region MISC HELPER #----------------------------------------------------------------------------------------------------------------------#
[docs] def coerce_to_date(date: Union[str, int, datetime.date, datetime.datetime]) -> datetime.date: """ Coerce random data formats to a datetime.date object Args: date (Union[str, int, datetime.date, datetime.datetime]): The date to coerce Returns: datetime.date - The coerce date object """ if isinstance(date, datetime.date): return date elif isinstance(date, datetime.datetime): return date.date elif isinstance(date, int): date = str(int) if not isinstance(date, str): msg = f'Cannot coerce date {date}' logger.error(msg) raise RuntimeError(msg) if len(date) == 6: # noqa: PLR2004 year = int(date[:2]) if year < 50: # noqa: PLR2004 year += 2000 else: year += 1900 month = int(date[2:4]) day = int(date[4:]) elif len(date) == 8: # noqa: PLR2004 if date.isdigit(): year = int(date[:4]) month = int(date[4:6]) day = int(date[6:]) else: year = int(date[:2]) if year < 50: # noqa: PLR2004 year += 2000 else: year += 1900 month = int(date[3:5]) day = int(date[6:]) elif len(date) == 10: # noqa: PLR2004 year = int(date[:4]) month = int(date[5:7]) day = int(date[8:]) return datetime.date(year, month, day)
[docs] def verify_alignment(align: str) -> str: """ Check that the requested alignment is actually available Args: align (str): The alignment tag that needs to be verified Returns: str - The alignment if it is acceptable """ alignments = ['left', 'center', 'right'] if align not in alignments: msg = f'Unknown alignment {align}. Available: {alignments}' logger.error(msg) raise RuntimeError(msg) return align
[docs] def verify_color_mode(color_mode: str) -> str: """ Check that the requested alignment is actually available Args: color_mode (str): The alignment tag that needs to be verified Returns: str - The alignment if it is acceptable """ color_modes = ['light', 'dark'] if color_mode not in color_modes: msg = f'Unknown color_mode {color_mode}. Available: {color_modes}' logger.error(msg) raise RuntimeError(msg) return color_mode
[docs] def default(var: Any, default: Any) -> Any: """ Helper function to check kwargs and set them to a default You could simply use var or default. But for future additions we will use a separat function here Args: var (Any): The input variable default (Any): Default value for the variable Returns Any - Either the variable itself, or the default value if var is `None` """ if var is None: return default else: return var