utils - Django-Components" > utils - Django-Components" >
Skip to content

utils ¤

gen_id ¤

gen_id(length: int = 5) -> str

Generate a unique ID that can be associated with a Node

Source code in src/django_components/utils.py
def gen_id(length: int = 5) -> str:
    """Generate a unique ID that can be associated with a Node"""
    # Global counter to avoid conflicts
    global _id
    _id += 1

    # Pad the ID with `0`s up to 4 digits, e.g. `0007`
    return f"{_id:04}"

lazy_cache ¤

lazy_cache(make_cache: Callable[[], Callable[[Callable], Callable]]) -> Callable[[TFunc], TFunc]

Decorator that caches the given function similarly to functools.lru_cache. But the cache is instantiated only at first invocation.

cache argument is a function that generates the cache function, e.g. functools.lru_cache().

Source code in src/django_components/utils.py
def lazy_cache(
    make_cache: Callable[[], Callable[[Callable], Callable]],
) -> Callable[[TFunc], TFunc]:
    """
    Decorator that caches the given function similarly to `functools.lru_cache`.
    But the cache is instantiated only at first invocation.

    `cache` argument is a function that generates the cache function,
    e.g. `functools.lru_cache()`.
    """
    _cached_fn = None

    def decorator(fn: TFunc) -> TFunc:
        @functools.wraps(fn)
        def wrapper(*args: Any, **kwargs: Any) -> Any:
            # Lazily initialize the cache
            nonlocal _cached_fn
            if not _cached_fn:
                # E.g. `lambda: functools.lru_cache(maxsize=app_settings.TEMPLATE_CACHE_SIZE)`
                cache = make_cache()
                _cached_fn = cache(fn)

            return _cached_fn(*args, **kwargs)

        # Allow to access the LRU cache methods
        # See https://stackoverflow.com/a/37654201/9788634
        wrapper.cache_info = lambda: _cached_fn.cache_info()  # type: ignore
        wrapper.cache_clear = lambda: _cached_fn.cache_clear()  # type: ignore

        # And allow to remove the cache instance (mostly for tests)
        def cache_remove() -> None:
            nonlocal _cached_fn
            _cached_fn = None

        wrapper.cache_remove = cache_remove  # type: ignore

        return cast(TFunc, wrapper)

    return decorator