2022-06-16 10:12:37 +09:00
|
|
|
# SPDX-FileCopyrightText: 2022 n9k <https://git.076.ne.jp/ninya9k>
|
2022-03-07 23:51:59 +09:00
|
|
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
|
2022-02-14 19:16:09 +09:00
|
|
|
import time
|
2022-02-13 13:00:10 +09:00
|
|
|
from functools import wraps
|
|
|
|
|
2022-06-16 05:41:35 +09:00
|
|
|
def with_function_call(fn, *fn_args, **fn_kwargs):
|
|
|
|
def with_result(f):
|
2022-02-13 13:00:10 +09:00
|
|
|
@wraps(f)
|
2022-02-16 18:55:30 +09:00
|
|
|
def wrapper(*args, **kwargs):
|
2022-06-16 05:41:35 +09:00
|
|
|
result = fn(*fn_args, **fn_kwargs)
|
|
|
|
return f(result, *args, **kwargs)
|
2022-02-13 13:00:10 +09:00
|
|
|
return wrapper
|
2022-06-16 05:41:35 +09:00
|
|
|
return with_result
|
|
|
|
|
|
|
|
def with_constant(x):
|
|
|
|
return with_function_call(lambda: x)
|
2022-02-14 19:16:09 +09:00
|
|
|
|
2022-06-19 17:10:23 +09:00
|
|
|
def get_timestamp(monotonic=False, precise=False):
|
2022-06-16 05:41:35 +09:00
|
|
|
n = 1_000_000_000
|
|
|
|
if monotonic:
|
2022-06-19 17:10:23 +09:00
|
|
|
timestamp = precise and time.monotonic() or time.monotonic_ns() // n
|
2022-06-16 05:41:35 +09:00
|
|
|
else:
|
2022-06-19 17:10:23 +09:00
|
|
|
timestamp = precise and time.time() or time.time_ns() // n
|
|
|
|
return timestamp
|
|
|
|
|
|
|
|
def with_timestamp(monotonic=False, precise=False):
|
|
|
|
def get_timestamp_specific():
|
|
|
|
return get_timestamp(monotonic=monotonic, precise=precise)
|
|
|
|
return with_function_call(get_timestamp_specific)
|
2022-02-17 21:51:09 +09:00
|
|
|
|
|
|
|
def try_except_log(errors, exception_class):
|
|
|
|
def try_except_log_specific(f):
|
|
|
|
@wraps(f)
|
|
|
|
def wrapper(*args, **kwargs):
|
|
|
|
try:
|
|
|
|
return f(*args, **kwargs)
|
|
|
|
except exception_class as e:
|
|
|
|
errors.append(e)
|
|
|
|
return wrapper
|
|
|
|
return try_except_log_specific
|
2022-02-22 12:57:48 +09:00
|
|
|
|
|
|
|
def ttl_cache(ttl):
|
|
|
|
'''
|
|
|
|
Expiring cache with exactly one slot. Only wraps
|
|
|
|
functions that take no arguments.
|
|
|
|
'''
|
|
|
|
def ttl_cache_specific(f):
|
|
|
|
value, expires = None, None
|
|
|
|
@wraps(f)
|
|
|
|
def wrapper():
|
|
|
|
nonlocal value, expires
|
|
|
|
if expires is None or time.monotonic() >= expires:
|
|
|
|
value = f()
|
|
|
|
expires = time.monotonic() + ttl
|
|
|
|
return value
|
|
|
|
return wrapper
|
|
|
|
return ttl_cache_specific
|
2022-02-22 19:43:09 +09:00
|
|
|
|
|
|
|
def ttl_cache_async(ttl):
|
|
|
|
'''
|
|
|
|
Async version of `ttl_cache`. Wraps zero-argument coroutines.
|
|
|
|
'''
|
|
|
|
def ttl_cache_specific(f):
|
|
|
|
value, expires = None, None
|
|
|
|
@wraps(f)
|
|
|
|
async def wrapper():
|
|
|
|
nonlocal value, expires
|
|
|
|
if expires is None or time.monotonic() >= expires:
|
|
|
|
value = await f()
|
|
|
|
expires = time.monotonic() + ttl
|
|
|
|
return value
|
|
|
|
return wrapper
|
|
|
|
return ttl_cache_specific
|