File: _cache.py

package info (click to toggle)
python-librosa 0.11.0-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 166,732 kB
  • sloc: python: 21,731; makefile: 141; sh: 2
file content (90 lines) | stat: -rw-r--r-- 2,785 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Function caching"""

import os
from typing import Any, Callable, TypeVar
from joblib import Memory
from decorator import FunctionMaker


def _decorator_apply(dec, func):
    return FunctionMaker.create(
        func,
        "return decfunc(%(shortsignature)s)",
        dict(decfunc=dec(func)),
        __wrapped__=func,
    )


_F = TypeVar("_F", bound=Callable[..., Any])


class CacheManager(object):
    """The librosa cache manager class wraps joblib.Memory
    with a __call__ attribute, so that it may act as a function.

    Additionally, it provides a caching level filter, so that
    different functions can be cached or not depending on the user's
    preference for speed vs. storage usage.
    """

    def __init__(self, *args: Any, **kwargs: Any):
        level = kwargs.pop("level", 10)

        # Initialize the memory object
        self.memory: Memory = Memory(*args, **kwargs)
        # The level parameter controls which data we cache
        # smaller numbers mean less caching
        self.level: int = level

    def __call__(self, level: int) -> Callable[[_F], _F]:
        """
        Cache with an explicitly defined level.

        Example usage:

        @cache(level=2)
        def semi_important_function(some_arguments):
            ...
        """

        def wrapper(function):
            """Add an input/output cache to the specified function."""
            if self.memory.location is not None and self.level >= level:
                return _decorator_apply(self.memory.cache, function)

            else:
                return function

        return wrapper

    def clear(self, *args: Any, **kwargs: Any) -> None:
        """Clear the cache"""
        self.memory.clear(*args, **kwargs)

    def eval(self, *args: Any, **kwargs: Any) -> Any:
        """Evaluate a function"""
        return self.memory.eval(*args, **kwargs)

    def format(self, *args: Any, **kwargs: Any) -> Any:
        """Return the formatted representation of an object"""
        return self.memory.format(*args, **kwargs)

    def reduce_size(self, *args: Any, **kwargs: Any) -> None:
        """Reduce the size of the cache"""
        self.memory.reduce_size(*args, **kwargs)  # pragma: no cover

    def warn(self, *args: Any, **kwargs: Any) -> None:
        """Raise a warning"""
        self.memory.warn(*args, **kwargs)  # pragma: no cover


# Instantiate the cache from the environment
cache: CacheManager = CacheManager(
    os.environ.get("LIBROSA_CACHE_DIR", None),
    mmap_mode=os.environ.get("LIBROSA_CACHE_MMAP", None),
    compress=os.environ.get("LIBROSA_CACHE_COMPRESS", False),
    verbose=int(os.environ.get("LIBROSA_CACHE_VERBOSE", 0)),
    level=int(os.environ.get("LIBROSA_CACHE_LEVEL", 10)),
)