Make LazyClassProperty / cached_classproperty reusable

This commit is contained in:
Šarūnas Nejus 2024-05-02 12:02:10 +01:00
parent 0e87389994
commit 265e40b14e
No known key found for this signature in database
GPG key ID: DD28F6704DBE3435
4 changed files with 23 additions and 21 deletions

View file

@ -39,7 +39,7 @@ from unidecode import unidecode
from beets import config, logging, plugins from beets import config, logging, plugins
from beets.autotag import mb from beets.autotag import mb
from beets.library import Item from beets.library import Item
from beets.util import as_string from beets.util import as_string, cached_classproperty
log = logging.getLogger("beets") log = logging.getLogger("beets")
@ -413,23 +413,6 @@ def string_dist(str1: Optional[str], str2: Optional[str]) -> float:
return base_dist + penalty 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 @total_ordering
class Distance: class Distance:
"""Keeps track of multiple distance penalties. Provides a single """Keeps track of multiple distance penalties. Provides a single
@ -441,7 +424,7 @@ class Distance:
self._penalties = {} self._penalties = {}
self.tracks: Dict[TrackInfo, Distance] = {} self.tracks: Dict[TrackInfo, Distance] = {}
@LazyClassProperty @cached_classproperty
def _weights(cls) -> Dict[str, float]: # noqa: N805 def _weights(cls) -> Dict[str, float]: # noqa: N805
"""A dictionary from keys to floating-point weights.""" """A dictionary from keys to floating-point weights."""
weights_view = config["match"]["distance_weights"] weights_view = config["match"]["distance_weights"]

View file

@ -1055,3 +1055,20 @@ def par_map(transform: Callable, items: Iterable):
pool.map(transform, items) pool.map(transform, items)
pool.close() pool.close()
pool.join() 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]

View file

@ -31,7 +31,9 @@ show_contexts = true
min-version = 3.8 min-version = 3.8
accept-encodings = utf-8 accept-encodings = utf-8
max-line-length = 88 max-line-length = 88
docstring-convention = google classmethod-decorators =
classmethod
cached_classproperty
# errors we ignore; see https://www.flake8rules.com/ for more info # errors we ignore; see https://www.flake8rules.com/ for more info
ignore = ignore =
# pycodestyle errors # pycodestyle errors

View file

@ -143,7 +143,7 @@ def _clear_weights():
"""Hack around the lazy descriptor used to cache weights for """Hack around the lazy descriptor used to cache weights for
Distance calculations. Distance calculations.
""" """
Distance.__dict__["_weights"].computed = False Distance.__dict__["_weights"].cache = {}
class DistanceTest(_common.TestCase): class DistanceTest(_common.TestCase):