diff --git a/beets/autotag/hooks.py b/beets/autotag/hooks.py index ddc5151c8..4f6a2e4bc 100644 --- a/beets/autotag/hooks.py +++ b/beets/autotag/hooks.py @@ -260,6 +260,22 @@ def string_dist(str1, str2): return base_dist + penalty +class LazyClassProperty(object): + """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 + + class Distance(object): """Keeps track of multiple distance penalties. Provides a single weighted distance for all penalties as well as a weighted distance @@ -268,10 +284,16 @@ class Distance(object): def __init__(self): self._penalties = {} + + @LazyClassProperty + def _weights(cls): + """A dictionary from keys to floating-point weights. + """ weights_view = config['match']['distance_weights'] - self._weights = {} + weights = {} for key in weights_view.keys(): - self._weights[key] = weights_view[key].as_number() + weights[key] = weights_view[key].as_number() + return weights # Access the components and their aggregates. diff --git a/docs/changelog.rst b/docs/changelog.rst index 49cdee63e..aee77266d 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -35,6 +35,9 @@ New stuff: * The :ref:`modify-cmd` command now allows removing flexible attributes. For example, ``beet modify artist:beatles oldies!`` deletes the ``oldies`` attribute from matching items. Thanks to brilnius. +* The performance of the autotagger's matching mechanism is vastly improved. + This should be noticeable when matching against very large releases such as + box sets. Fixes: