From 9ca816f2473ce6769472d8ee8de785d732976c30 Mon Sep 17 00:00:00 2001 From: Alexander Elbs Date: Sun, 29 Jun 2014 21:35:04 +0200 Subject: [PATCH 1/2] =?UTF-8?q?the=20bucket=20plugin=20transforms=20a=20pa?= =?UTF-8?q?ttern=20like=20'A=20-=20D'=20into=20something=20that=20matches?= =?UTF-8?q?=20all=20letters=20starting=20with=20A=20to=20D=20(upper=20and?= =?UTF-8?q?=20lower=20case).=20This=20change=20allows=20to=20put=20more=20?= =?UTF-8?q?artists=20into=20that=20bucket.=20E.g.=20artists=20starting=20w?= =?UTF-8?q?ith=20=C3=A4=20or=20=C3=84=20and=200=20to=209=20and=20=E2=80=A6?= =?UTF-8?q?=20(three=20dots)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Example config for overriding a bucket pattern: bucket: bucket_alpha: ['A - D', 'E - L', 'M - R', 'S - Z'] bucket_alpha_regex: 'A - D': ^[0-9a-dA-D…äÄ] --- beetsplug/bucket.py | 34 +++++++++++++++++++++++----------- docs/plugins/bucket.rst | 9 +++++++++ test/test_bucket.py | 24 +++++++++++++++++++++++- 3 files changed, 55 insertions(+), 12 deletions(-) diff --git a/beetsplug/bucket.py b/beetsplug/bucket.py index 60ceeb119..fb9feaafd 100644 --- a/beetsplug/bucket.py +++ b/beetsplug/bucket.py @@ -152,22 +152,30 @@ def extract_modes(spans): return deflen, deffmt -def build_alpha_spans(alpha_spans_str): +def build_alpha_spans(alpha_spans_str, alpha_regexs): """Extract alphanumerics from string and return sorted list of chars [from...to] """ spans = [] ASCII_DIGITS = string.digits + string.ascii_lowercase for elem in alpha_spans_str: - bucket = sorted([x for x in elem.lower() if x.isalnum()]) - if bucket: - beginIdx = ASCII_DIGITS.index(bucket[0]) - endIdx = ASCII_DIGITS.index(bucket[-1]) + if elem in alpha_regexs: + spans.append(re.compile(alpha_regexs[elem])) else: - raise ui.UserError("invalid range defined for alpha bucket '%s'" - " : no alphanumeric character found" % - elem) - spans.append(ASCII_DIGITS[beginIdx:endIdx + 1]) + bucket = sorted([x for x in elem.lower() if x.isalnum()]) + if bucket: + beginIdx = ASCII_DIGITS.index(bucket[0]) + endIdx = ASCII_DIGITS.index(bucket[-1]) + else: + raise ui.UserError("invalid range defined for alpha bucket " + "'%s': no alphanumeric character found" % + elem) + spans.append( + re.compile( + "^[" + ASCII_DIGITS[beginIdx:endIdx + 1] + + ASCII_DIGITS[beginIdx:endIdx + 1].upper() + "]" + ) + ) return spans @@ -179,6 +187,7 @@ class BucketPlugin(plugins.BeetsPlugin): self.config.add({ 'bucket_year': [], 'bucket_alpha': [], + 'bucket_alpha_regex': {}, 'extrapolate': False }) self.setup() @@ -193,7 +202,10 @@ class BucketPlugin(plugins.BeetsPlugin): self.year_spans = extend_year_spans(self.year_spans, self.ys_len_mode) - self.alpha_spans = build_alpha_spans(self.config['bucket_alpha'].get()) + self.alpha_spans = build_alpha_spans( + self.config['bucket_alpha'].get(), + self.config['bucket_alpha_regex'].get() + ) def find_bucket_year(self, year): """Return bucket that matches given year or return the year @@ -215,7 +227,7 @@ class BucketPlugin(plugins.BeetsPlugin): string initial if no matching bucket. """ for (i, span) in enumerate(self.alpha_spans): - if s.lower()[0] in span: + if span.match(s): return self.config['bucket_alpha'].get()[i] return s[0].upper() diff --git a/docs/plugins/bucket.rst b/docs/plugins/bucket.rst index a278d4208..f869ea024 100644 --- a/docs/plugins/bucket.rst +++ b/docs/plugins/bucket.rst @@ -38,3 +38,12 @@ of declared buckets:: extrapolate: true The above configuration creates five-year ranges for any input year. + +If the automatic range of an alpha bucket is not sufficient an overriding regular expression can be used:: + + bucket: + bucket_alpha: ['A - D', 'E - L', 'M - R', 'S - Z'] + bucket_alpha_regex: + 'A - D': ^[0-9a-dA-D…äÄ] + +The *A - D* bucket now matches also all artists starting with ä or Ä and 0 to 9 and … (three dots). The other buckets work as ranges (see above). diff --git a/test/test_bucket.py b/test/test_bucket.py index f8b86bf6d..5ff834d52 100644 --- a/test/test_bucket.py +++ b/test/test_bucket.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- # This file is part of beets. # Copyright 2014, Fabrice Laporte. # @@ -31,9 +32,10 @@ class BucketPluginTest(unittest.TestCase, TestHelper): self.teardown_beets() def _setup_config(self, bucket_year=[], bucket_alpha=[], - extrapolate=False): + bucket_alpha_regex = {}, extrapolate=False): config['bucket']['bucket_year'] = bucket_year config['bucket']['bucket_alpha'] = bucket_alpha + config['bucket']['bucket_alpha_regex'] = bucket_alpha_regex config['bucket']['extrapolate'] = extrapolate self.plugin.setup() @@ -107,6 +109,26 @@ class BucketPluginTest(unittest.TestCase, TestHelper): self._setup_config(bucket_alpha=[]) self.assertEqual(self.plugin._tmpl_bucket('errol'), 'E') + def test_alpha_regex(self): + """Check regex is used""" + self._setup_config(bucket_alpha=['foo', 'bar'], + bucket_alpha_regex={'foo': '^[a-d]', + 'bar': '^[e-z]'}) + self.assertEqual(self.plugin._tmpl_bucket('alpha'), 'foo') + self.assertEqual(self.plugin._tmpl_bucket('delta'), 'foo') + self.assertEqual(self.plugin._tmpl_bucket('zeta'), 'bar') + self.assertEqual(self.plugin._tmpl_bucket('Alpha'), 'A') + + def test_alpha_regex_mix(self): + """Check mixing regex and non-regex is possible""" + self._setup_config(bucket_alpha=['A - D', 'E - L'], + bucket_alpha_regex={'A - D': '^[0-9a-dA-D…äÄ]'}) + self.assertEqual(self.plugin._tmpl_bucket('alpha'), 'A - D') + self.assertEqual(self.plugin._tmpl_bucket('Ärzte'), 'A - D') + self.assertEqual(self.plugin._tmpl_bucket('112'), 'A - D') + self.assertEqual(self.plugin._tmpl_bucket('…and Oceans'), 'A - D') + self.assertEqual(self.plugin._tmpl_bucket('Eagles'), 'E - L') + @raises(ui.UserError) def test_bad_alpha_range_def(self): """If bad alpha range definition, a UserError is raised""" From 77d303b6736a0521dcfe6ae10a643ad66c343468 Mon Sep 17 00:00:00 2001 From: Alexander Elbs Date: Sun, 29 Jun 2014 21:35:17 +0200 Subject: [PATCH 2/2] A few artists use three digits, e.g. 112 or 209. They are detected as a year instead of an artist. Improve the heuristic by only allowing four digits to be a year. --- beetsplug/bucket.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beetsplug/bucket.py b/beetsplug/bucket.py index fb9feaafd..49a7cbbaa 100644 --- a/beetsplug/bucket.py +++ b/beetsplug/bucket.py @@ -232,7 +232,7 @@ class BucketPlugin(plugins.BeetsPlugin): return s[0].upper() def _tmpl_bucket(self, text, field=None): - if not field and text.isdigit(): + if not field and len(text) == 4 and text.isdigit(): field = 'year' if field == 'year':