mirror of
https://github.com/beetbox/beets.git
synced 2025-12-06 08:39:17 +01:00
115 lines
3.9 KiB
Python
115 lines
3.9 KiB
Python
# This file is part of beets.
|
|
# Copyright 2014, Fabrice Laporte.
|
|
#
|
|
# Permission is hereby granted, free of charge, to any person obtaining
|
|
# a copy of this software and associated documentation files (the
|
|
# "Software"), to deal in the Software without restriction, including
|
|
# without limitation the rights to use, copy, modify, merge, publish,
|
|
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
# permit persons to whom the Software is furnished to do so, subject to
|
|
# the following conditions:
|
|
#
|
|
# The above copyright notice and this permission notice shall be
|
|
# included in all copies or substantial portions of the Software.
|
|
|
|
"""Enrich path formatting with %bucket_alpha and %bucket_date functions
|
|
"""
|
|
|
|
from datetime import datetime
|
|
import logging
|
|
import re
|
|
import string
|
|
from beets import plugins
|
|
|
|
log = logging.getLogger('beets')
|
|
|
|
|
|
def extract_years(lst):
|
|
"""Extract years from a list of strings"""
|
|
|
|
def make_date(s):
|
|
"""Convert string representing a year to int
|
|
"""
|
|
d = int(s)
|
|
if d < 100: # two digits imply it is 20th century
|
|
d = 1900 + d
|
|
return d
|
|
|
|
res = []
|
|
for bucket in lst:
|
|
yearspan_str = re.findall('\d+', bucket)
|
|
yearspan = [make_date(x) for x in yearspan_str]
|
|
res.append(yearspan)
|
|
return res
|
|
|
|
|
|
class BucketPlugin(plugins.BeetsPlugin):
|
|
def __init__(self):
|
|
super(BucketPlugin, self).__init__()
|
|
self.template_funcs['bucket'] = self._tmpl_bucket
|
|
|
|
self.config.add({
|
|
'bucket_year': [],
|
|
'bucket_alpha': [],
|
|
})
|
|
self.setup()
|
|
|
|
def setup(self):
|
|
"""Setup plugin from config options
|
|
"""
|
|
yearranges = extract_years(self.config['bucket_year'].get())
|
|
self.yearbounds = sorted([y for ys in yearranges for y in ys])
|
|
self.yearranges = [self.make_year_range(b) for b in yearranges]
|
|
self.alpharanges = [self.make_alpha_range(b) for b in
|
|
self.config['bucket_alpha'].get()]
|
|
|
|
def make_year_range(self, ys):
|
|
"""Express year-range as a list of years [from...to].
|
|
If input year-range only contains the 'from' year, the 'to' is
|
|
defined as the 'from' year of the next year-range minus one or is
|
|
set to current year if there is no next year-range.
|
|
"""
|
|
if len(ys) == 1: # miss upper bound
|
|
lb_idx = self.yearbounds.index(ys[0])
|
|
try:
|
|
ys.append(self.yearbounds[lb_idx + 1])
|
|
except:
|
|
ys.append(datetime.now().year)
|
|
return range(ys[0], ys[-1] + 1)
|
|
|
|
def make_alpha_range(self, s):
|
|
"""Extract alphanumerics from string and return sorted list of chars
|
|
[from...to]
|
|
"""
|
|
bucket = sorted([x for x in s.lower() if x.isalnum()])
|
|
beginIdx = string.ascii_lowercase.index(bucket[0])
|
|
endIdx = string.ascii_lowercase.index(bucket[-1])
|
|
return string.ascii_lowercase[beginIdx:endIdx + 1]
|
|
|
|
def find_bucket_timerange(self, date):
|
|
"""Return year-range bucket that matches given date or return the date
|
|
if no matching bucket.
|
|
"""
|
|
for (i, r) in enumerate(self.yearranges):
|
|
if int(date) in r:
|
|
return self.config['bucket_year'].get()[i]
|
|
return date
|
|
|
|
def find_bucket_alpha(self, s):
|
|
"""Return alpha-range bucket that matches given string or return the
|
|
string initial if no matching bucket.
|
|
"""
|
|
for (i, r) in enumerate(self.alpharanges):
|
|
if s.lower()[0] in r:
|
|
return self.config['bucket_alpha'].get()[i]
|
|
return s[0].upper()
|
|
|
|
def _tmpl_bucket(self, text, field=None):
|
|
if not field and text.isdigit():
|
|
field = 'year'
|
|
|
|
if field == 'year':
|
|
func = self.find_bucket_timerange
|
|
else:
|
|
func = self.find_bucket_alpha
|
|
return func(text)
|