Source code for gfw.common.decorators

"""Module that contains simple function decorators."""

import logging

from functools import wraps
from time import time
from typing import Any, Callable, Generator


logger = logging.getLogger(__name__)


[docs] def counter( items: Generator[Any, None, None], logger: logging.Logger = logger, message: str = "{count}" ) -> Generator[Any, None, None]: """Decorator generator function to log the number of items that are being iterated. This is particularly useful when you have a generator, you want to know its size but you don't control the function that is going to iterate it. Args: items: Items to be iterated. logger: The logger to use. message: The string template to use as message. Must include an entry for a "count" variable. """ count = 0 for item in items: count += 1 yield item logger.info(message.format(count=count))
[docs] def timing( f: Callable[..., Any], quiet: bool = False, logger: logging.Logger = logger, decimals: int = 4 ) -> Callable[..., tuple[Any, float]]: """Decorator to measure execution time of a function. Args: f: The function to time. quiet: If true, doesn't log the elapsed time. logger: The logger to use. decimals: How many decimals to use when rounding. Only used for logging. Returns: :class:`Callable`: A wrapper around the original callable that returns a 2D tuple with: - Whatever the original callable returns. - The elapsed time. """ @wraps(f) def wrap(*args: Any, **kwargs: Any) -> tuple[Any, float]: start_time = time() result = f(*args, **kwargs) end_time = time() elapsed_time = end_time - start_time if not quiet: logger.info("func: {} took: {} sec".format(f.__name__, round(elapsed_time, decimals))) return result, elapsed_time return wrap