2022-08-30 00:45:27 +00:00
|
|
|
"""Util functions to help filter out similar results."""
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
from collections.abc import Callable
|
|
|
|
from datetime import datetime, timedelta
|
|
|
|
import functools
|
2023-01-23 06:28:43 +00:00
|
|
|
from typing import Any, ParamSpec, TypeVar, overload
|
2022-12-13 14:22:23 +00:00
|
|
|
|
|
|
|
_R = TypeVar("_R", int, float, datetime)
|
|
|
|
_P = ParamSpec("_P")
|
2022-08-30 00:45:27 +00:00
|
|
|
|
|
|
|
|
|
|
|
@overload
|
|
|
|
def ignore_variance(
|
2022-12-13 14:22:23 +00:00
|
|
|
func: Callable[_P, int], ignored_variance: int
|
|
|
|
) -> Callable[_P, int]:
|
2022-08-30 00:45:27 +00:00
|
|
|
...
|
|
|
|
|
|
|
|
|
|
|
|
@overload
|
|
|
|
def ignore_variance(
|
2022-12-13 14:22:23 +00:00
|
|
|
func: Callable[_P, float], ignored_variance: float
|
|
|
|
) -> Callable[_P, float]:
|
2022-08-30 00:45:27 +00:00
|
|
|
...
|
|
|
|
|
|
|
|
|
|
|
|
@overload
|
|
|
|
def ignore_variance(
|
2022-12-13 14:22:23 +00:00
|
|
|
func: Callable[_P, datetime], ignored_variance: timedelta
|
|
|
|
) -> Callable[_P, datetime]:
|
2022-08-30 00:45:27 +00:00
|
|
|
...
|
|
|
|
|
|
|
|
|
2022-12-13 14:22:23 +00:00
|
|
|
def ignore_variance(func: Callable[_P, _R], ignored_variance: Any) -> Callable[_P, _R]:
|
2022-08-30 00:45:27 +00:00
|
|
|
"""Wrap a function that returns old result if new result does not vary enough."""
|
2022-12-13 14:22:23 +00:00
|
|
|
last_value: _R | None = None
|
2022-08-30 00:45:27 +00:00
|
|
|
|
|
|
|
@functools.wraps(func)
|
2022-12-13 14:22:23 +00:00
|
|
|
def wrapper(*args: _P.args, **kwargs: _P.kwargs) -> _R:
|
2022-08-30 00:45:27 +00:00
|
|
|
nonlocal last_value
|
|
|
|
|
|
|
|
value = func(*args, **kwargs)
|
|
|
|
|
|
|
|
if last_value is not None and abs(value - last_value) < ignored_variance:
|
|
|
|
return last_value
|
|
|
|
|
|
|
|
last_value = value
|
|
|
|
return value
|
|
|
|
|
|
|
|
return wrapper
|