diff --git a/beets/autotag/hooks.py b/beets/autotag/hooks.py index c1dabdb09..efd71da9b 100644 --- a/beets/autotag/hooks.py +++ b/beets/autotag/hooks.py @@ -39,7 +39,7 @@ from unidecode import unidecode from beets import config, logging, plugins from beets.autotag import mb from beets.library import Item -from beets.util import as_string +from beets.util import as_string, cached_classproperty log = logging.getLogger("beets") @@ -413,23 +413,6 @@ def string_dist(str1: Optional[str], str2: Optional[str]) -> float: return base_dist + penalty -class LazyClassProperty: - """A decorator implementing a read-only property that is *lazy* in - the sense that the getter is only invoked once. Subsequent accesses - through *any* instance use the cached result. - """ - - def __init__(self, getter): - self.getter = getter - self.computed = False - - def __get__(self, obj, owner): - if not self.computed: - self.value = self.getter(owner) - self.computed = True - return self.value - - @total_ordering class Distance: """Keeps track of multiple distance penalties. Provides a single @@ -441,7 +424,7 @@ class Distance: self._penalties = {} self.tracks: Dict[TrackInfo, Distance] = {} - @LazyClassProperty + @cached_classproperty def _weights(cls) -> Dict[str, float]: # noqa: N805 """A dictionary from keys to floating-point weights.""" weights_view = config["match"]["distance_weights"] diff --git a/beets/util/__init__.py b/beets/util/__init__.py index 8cbbda8f9..6b5b984a0 100644 --- a/beets/util/__init__.py +++ b/beets/util/__init__.py @@ -1055,3 +1055,20 @@ def par_map(transform: Callable, items: Iterable): pool.map(transform, items) pool.close() pool.join() + + +class cached_classproperty: # noqa: N801 + """A decorator implementing a read-only property that is *lazy* in + the sense that the getter is only invoked once. Subsequent accesses + through *any* instance use the cached result. + """ + + def __init__(self, getter): + self.getter = getter + self.cache = {} + + def __get__(self, instance, owner): + if owner not in self.cache: + self.cache[owner] = self.getter(owner) + + return self.cache[owner] diff --git a/setup.cfg b/setup.cfg index b91c84bda..b918bdb1d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -31,7 +31,9 @@ show_contexts = true min-version = 3.8 accept-encodings = utf-8 max-line-length = 88 -docstring-convention = google +classmethod-decorators = + classmethod + cached_classproperty # errors we ignore; see https://www.flake8rules.com/ for more info ignore = # pycodestyle errors diff --git a/test/test_autotag.py b/test/test_autotag.py index 868138411..e9b44458c 100644 --- a/test/test_autotag.py +++ b/test/test_autotag.py @@ -143,7 +143,7 @@ def _clear_weights(): """Hack around the lazy descriptor used to cache weights for Distance calculations. """ - Distance.__dict__["_weights"].computed = False + Distance.__dict__["_weights"].cache = {} class DistanceTest(_common.TestCase):