from __future__ import annotations import sys from datetime import datetime from enum import Enum from functools import total_ordering from typing import TextIO # https://docs.python.org/3/library/functools.html#functools.total_ordering @total_ordering class WarnLevel(Enum): NONE = 0 # Not a warning. Everything is ok. LOW = 1 NORMAL = 2 HIGH = 3 def __eq__(self, other): if isinstance(other, WarnLevel): return self.value == other.value return NotImplemented def __lt__(self, other): if isinstance(other, WarnLevel): return self.value < other.value return NotImplemented class WarnMessage: def __init__(self, level: WarnLevel, date: datetime = None, message: str = None): """ @param level: @param date: Required, except if `WarnLevel.NONE` given. @param message: Required, except if `WarnLevel.NONE` given. """ self.level = level self.date = date self.message = message if self.level != WarnLevel.NONE: if self.date is None: raise ValueError() if self.message is None: raise ValueError() if self.level == WarnLevel.NONE: if self.date is not None: raise ValueError() if self.message is not None: raise ValueError() def is_warning(self) -> bool: return self.level > WarnLevel.NONE def print(self) -> WarnMessage: """ return: self """ if self.level == WarnLevel.NONE: pass else: print(self.formatted_message(), file=self.file()) return self def formatted_message(self) -> str: return self.prefix() + self.message def prefix(self) -> str: if self.level == WarnLevel.NONE: raise ValueError() if self.level > WarnLevel.HIGH: return f'[CRITICAL] {self.date}: ' return f'{self.date}:' def file(self) -> TextIO: if self.level == WarnLevel.NONE: raise ValueError() if self.level >= WarnLevel.NORMAL: return sys.stderr return sys.stdout