Source code for pyowl2.utils.utils

import time
from functools import wraps

from tabulate import tabulate

# Global log store
execution_log: dict[str, dict] = dict()


[docs] def timer_decorator(cls): """ This class decorator instruments a class by wrapping its public, non-dunder methods to measure and log their execution performance. Upon application, it iterates through the class's attributes, identifying callable members that do not start with double underscores, and replaces them with a wrapper that records the elapsed time using high-resolution timers. The wrapper accumulates the total execution time for each method in a global dictionary named `execution_log`, associating it with the fully qualified method name and truncated representations of the passed arguments and keyword arguments. While the decorator modifies the global log state and the class's method attributes, it ensures the original method's behavior and return values are preserved. :param cls: The class whose methods will be timed and logged. :type cls: typing.Any """ for attr_name, attr_value in cls.__dict__.items(): if callable(attr_value) and not attr_name.startswith("__"): # Wrap the method original_method = attr_value @wraps(original_method) def wrapped_method( self, *args, __method=original_method, __name=attr_name, **kwargs ): f_name: str = f"{cls.__name__}.{__name}" start: int = time.perf_counter_ns() result = __method(self, *args, **kwargs) end: int = time.perf_counter_ns() elapsed: float = (end - start) * 1e-9 old_elapsed: float = execution_log.get(f_name, {"Time (s)": 0}).get("Time (s)") # if old_elapsed < elapsed: # Log the call execution_log[f_name] = { "Function": f"{cls.__name__}.{__name}", "Time (s)": elapsed + old_elapsed, "Args": ( f"{repr(args)[:50]}..." if len(repr(args)) > 50 else repr(args) ), "Kwargs": ( f"{repr(kwargs)[:50]}..." if len(repr(kwargs)) > 50 else repr(kwargs) ), } return result setattr(cls, attr_name, wrapped_method) return cls