Source code for law.contrib.profiling.decorator

# coding: utf-8

"""
Profiling decorators.
"""

from __future__ import annotations

__all__ = ["profile_by_line"]

from law.task.base import Task
from law.decorator import factory, get_task
from law.util import colored
from law._types import Callable, Any


[docs] @factory(output_unit=None, stripzeros=False, accept_generator=True) def profile_by_line( fn: Callable, opts: dict[str, Any], task: Task, *args, **kwargs, ) -> tuple[Callable, Callable, Callable, Callable]: """ profile_by_line(output_unit=None, stripzeros=False) Decorator for law task methods that performs a line-by-line profiling and prints the results after the method was called. This requires `line-profiler <https://pypi.org/project/line-profiler/>`__ to be installed on your system. *output_unit* and *stripzeros* are forwarded to :py:meth:`line_profiler.LineProfiler.print_stats`. Accepts generator functions. """ import line_profiler # type: ignore[import-untyped, import-not-found] def print_stats(profiler: line_profiler.LineProfiler, text: str | None = None) -> None: task_repr = get_task(task).repr() print(colored("-" * 100, "light_blue")) print(f"line profiling of method {colored(fn.__name__, style='bright')} of {task_repr}") if text: print(text) print("") profiler.print_stats(output_unit=opts["output_unit"], stripzeros=opts["stripzeros"]) print(colored("-" * 100, "light_blue")) def before_call() -> line_profiler.LineProfiler: # create and return a LineProfiler instance return line_profiler.LineProfiler() def call(profiler: line_profiler.LineProfiler) -> Any: return profiler(fn)(task, *args, **kwargs) def after_call(profiler: line_profiler.LineProfiler) -> None: # call print_stats print_stats(profiler) def on_error(error: Exception, profiler: line_profiler.LineProfiler) -> None: # call print_stats with an additional hint that an error occured print_stats(profiler, f"(up to exception of type '{error.__class__.__name__}')") return before_call, call, after_call, on_error