def cache_with_key(keyfunc, cache_name=None, timeout=None, with_statsd_key=None):
    # type: ignore # CANNOT_INFER_LAMBDA_TYPE issue with models.py
    """Decorator which applies Django caching to a function.

       Decorator argument is a function which computes a cache key
       from the original function's arguments.  You are responsible
       for avoiding collisions with other uses of this decorator or
       other uses of caching."""

    def decorator(func):
        # type: (Callable[..., Any]) -> (Callable[..., Any])
        @wraps(func)
        def func_with_caching(*args, **kwargs):
            # type: (*Any, **Any) -> Callable[..., Any]
            key = keyfunc(*args, **kwargs)

            val = cache_get(key, cache_name=cache_name)

            extra = ""
            if cache_name == 'database':
                extra = ".dbcache"

            if with_statsd_key is not None:
                metric_key = with_statsd_key
            else:
                metric_key = statsd_key(key)

            status = "hit" if val is not None else "miss"
            statsd.incr((extra, metric_key, status) % "cache%s.%s.%s")

            # Values are singleton tuples so that we can distinguish
            # a result of None from a missing key.
            if val is not None:
                return val[0]

            val = func(*args, **kwargs)

            cache_set(key, val, cache_name=cache_name, timeout=timeout)

            return val

        return func_with_caching

    return decorator
dataset/ETHPy150Open zulip/zulip/zerver/lib/cache.py/cache_with_key/swapped operands of `%`