Source code for pharmpy.workflows.log

import datetime

from pharmpy.deps import pandas as pd
from pharmpy.internals.immutable import Immutable

CATEGORIES = ('ERROR', 'WARNING', 'INFORMATION')


class LogEntry(Immutable):
    def __init__(self, category: str, message: str, time: datetime.datetime):
        self._category = category
        self._message = message
        self._time = time

    @classmethod
    def create(cls, category: str, message: str):
        if category not in CATEGORIES:
            raise ValueError(f"Unknown category {category}")
        return cls(category=category, message=message, time=datetime.datetime.now())

    @property
    def category(self):
        """Category of message. One of ERROR, WARNING and INFORMATION"""
        return self._category

    @property
    def message(self):
        """The logged message"""
        return self._message

    @property
    def time(self):
        """Time stamp of log entry"""
        return self._time

    def to_dict(self):
        return {
            'category': self._category,
            'message': self._message,
            'time': self._time.isoformat(),
        }

    @classmethod
    def from_dict(cls, d):
        d['time'] = datetime.datetime.fromisoformat(d['time'])
        return LogEntry(**d)


[docs] class Log: """Timestamped error and warning log""" def __init__(self, entries: tuple[LogEntry, ...] = ()): self._entries = entries def __len__(self): return len(self._entries) def __iter__(self): return iter(self._entries)
[docs] def to_dict(self): return {i: entry.to_dict() for i, entry in enumerate(self._entries)}
[docs] @classmethod def from_dict(cls, d): entries = [] for entry in d.values(): log_entry = LogEntry.from_dict(entry) entries.append(log_entry) return cls(tuple(entries))
@property def errors(self): entries = [e for e in self._entries if e.category == 'ERROR'] return Log(tuple(entries)) @property def warnings(self): entries = [e for e in self._entries if e.category == 'WARNING'] return Log(tuple(entries))
[docs] def log_error(self, message): """Log an error Parameters ---------- message : str Error message """ entry = LogEntry.create(category='ERROR', message=message) entries = self._entries + (entry,) return Log(entries)
[docs] def log_warning(self, message): """Log a warning Parameters ---------- message : str Warning message """ entry = LogEntry.create(category='WARNING', message=message) entries = self._entries + (entry,) return Log(entries)
[docs] def to_dataframe(self): """Create an overview dataframe from log Returns ------- pd.DataFrame Dataframe with overview of log entries """ categories = [entry.category for entry in self._entries] times = [entry.time for entry in self._entries] messages = [entry.message for entry in self._entries] df = pd.DataFrame( { 'category': categories, 'time': times, 'message': messages, } ) return df
def __repr__(self): s = '' for entry in self._entries: s += f'{entry.category:<8} {entry.time.strftime("%Y-%m-%d %H:%M:%S")}\n' for line in entry.message.split('\n'): s += f' {line}\n' return s