add timed_cache()

This commit is contained in:
Yusur 2025-07-22 22:15:11 +02:00
parent b4ef56f260
commit 303e9e2b2d
7 changed files with 57 additions and 11 deletions

View file

@ -1,5 +1,10 @@
# Changelog
## 0.5.0
+ Add `timed_cache()`
+ Move obsolete stuff to `obsolete` package
## 0.4.0
+ `pydantic` is now a hard dependency

View file

@ -21,7 +21,7 @@ from .codecs import (StringCase, cb32encode, cb32decode, b32lencode, b32ldecode,
jsonencode, want_bytes, want_str, ssv_list, want_urlsafe)
from .bits import count_ones, mask_shift, split_bits, join_bits, mod_ceil, mod_floor
from .configparse import MissingConfigError, MissingConfigWarning, ConfigOptions, ConfigParserConfigSource, ConfigSource, DictConfigSource, ConfigValue, EnvConfigSource
from .functools import deprecated, not_implemented
from .functools import deprecated, not_implemented, timed_cache
from .classtools import Wanted, Incomplete
from .itertools import makelist, kwargs_prefix, ltuple, rtuple, additem
from .i18n import I18n, JsonI18n, TomlI18n
@ -29,7 +29,7 @@ from .snowflake import Snowflake, SnowflakeGen
from .lex import symbol_table, lex, ilex
from .strtools import PrefixIdentifier
__version__ = "0.4.0"
__version__ = "0.5.0-dev29"
__all__ = (
'ConfigOptions', 'ConfigParserConfigSource', 'ConfigSource', 'ConfigValue',
@ -41,5 +41,5 @@ __all__ = (
'deprecated', 'ilex', 'join_bits', 'jsonencode', 'kwargs_prefix', 'lex',
'ltuple', 'makelist', 'mask_shift', 'mod_ceil', 'mod_floor',
'not_implemented', 'rtuple', 'split_bits', 'ssv_list', 'symbol_table',
'want_bytes', 'want_str', 'want_urlsafe'
'timed_cache', 'want_bytes', 'want_str', 'want_urlsafe'
)

View file

@ -14,9 +14,11 @@ This software is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
import math
import time
from typing import Callable
import warnings
from functools import wraps
from functools import wraps, lru_cache
try:
from warnings import deprecated
@ -64,6 +66,28 @@ def not_implemented(msg: Callable | str | None = None):
return decorator(msg)
return decorator
def timed_cache(ttl: int, maxsize: int = 128, typed: bool = False) -> Callable[[Callable], Callable]:
"""
LRU cache which expires after the TTL in seconds passed as argument.
"""
def decorator(func):
start_time = None
@lru_cache(maxsize, typed)
def inner_wrapper(ttl_period: int, *a, **k):
return func(*a, **k)
@wraps(func)
def wrapper(*a, **k):
nonlocal start_time
if not start_time:
start_time = int(time.time())
return inner_wrapper(math.floor((time.time() - start_time) // ttl), *a, **k)
return wrapper
return decorator
__all__ = (
'deprecated', 'not_implemented'
'deprecated', 'not_implemented', 'timed_cache'
)

View file

@ -43,9 +43,9 @@ class SpoilerExtension(markdown.extensions.Extension):
"""
Add spoiler tags to text, using >!Reddit syntax!<.
XXX remember to call SpoilerExtension.patch_blockquote_processor()
to clear conflicts with the blockquote processor and allow
spoiler tags to start at beginning of line.
If blockquotes interfer with rendered markup, you might want to call
SpoilerExtension.patch_blockquote_processor() to clear conflicts with
the blockquote processor and allow spoiler tags to start at beginning of line.
"""
def extendMarkdown(self, md: markdown.Markdown, md_globals=None):
md.inlinePatterns.register(SimpleTagInlineProcessor(r'()>!(.*?)!<', 'span class="spoiler"'), 'spoiler', 14)

View file

@ -0,0 +1,16 @@
"""
This stuff might still be good, but it's out of support.
---
Copyright (c) 2025 Sakuragasaki46.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
See LICENSE for the specific language governing permissions and
limitations under the License.
This software is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""

View file

@ -28,8 +28,8 @@ from typing import Any, Callable, Iterator
from collections import OrderedDict
import warnings
from .functools import deprecated
from .exceptions import MissingConfigError, MissingConfigWarning
from ..functools import deprecated
from ..exceptions import MissingConfigError, MissingConfigWarning
warnings.warn('This module will be removed in 0.5.0 and is kept only in case new implementation breaks!\n'\
'Do not use unless you know what you are doing.', DeprecationWarning)

View file

@ -35,6 +35,7 @@ class TestCodecs(unittest.TestCase):
self.assertEqual(b64decode('6RgpyyfClq7ehg'), B3)
self.assertEqual(b64decode('ByO8WGlGLEB8e77jDHqoyw'), B4)
self.assertEqual(b64decode('__init__'), B5)
self.assertEqual(b64decode('//init//'), B5)
self.assertEqual(b64decode('TvC0ww'), B1[:4])
self.assertEqual(b64decode('AE7wtMM'), b'\0' + B1[:4])
self.assertEqual(b64decode('AAAAAABO8LTD'), b'\0\0\0\0\0' + B1[:4])