albumify plugin for upgrading old databases

This commit is contained in:
Adrian Sampson 2010-07-22 10:52:43 -07:00
parent adcaaf3a13
commit 5b2653bb53
4 changed files with 121 additions and 6 deletions

9
NEWS
View file

@ -29,11 +29,10 @@
item) granularity. Databases created with earlier versions of beets
should work fine, but they won't have any "albums" in them--they'll
just be a bag of items. This means that commands like "beet ls -a"
and "beet rm -a" won't match anything. "One way to "upgrade" your
database so it contains albums is to remove your old database file
and use "beet import -A" to import without autotagging. This will use
the existing tags on the files but use their location in the directory
tree to cluster items into albums.
and "beet rm -a" won't match anything. To "upgrade" your database,
you can use the included "albumify" plugin. Running "beets albumify"
with the plugin activated will group all your items into albums,
making beets behave more or less as it did before.
* Fixed some bugs with encoding paths on Windows. Also, : is now
replaced with - in path names (instead of _) for readability.
* MediaFiles now have a "format" attribute, so you can use $format in

49
beetsplug/albumify.py Normal file
View file

@ -0,0 +1,49 @@
# This file is part of beets.
# Copyright 2010, Adrian Sampson.
#
# 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.
"""Provides the albumify command, which "upgrades" databases created
with beets <1.0b3. It walks through the database and groups all items
not yet associated with albums into albums based on metadata.
"""
from collections import defaultdict
from beets.plugins import BeetsPlugin
import beets.ui
# Main functionality.
def albumify(lib):
# Associate every (albumless) item with a unique artist/album
# pair.
albums = defaultdict(list)
for item in lib.get():
if item.album_id is None:
albums[(item.artist, item.album)].append(item)
# Create an album for each group.
for (artist, album), items in albums.items():
beets.ui.print_('%s - %s (%i tracks)' % (artist, album, len(items)))
lib.add_album(items)
# Plugin hook.
class AlbumifyPlugin(BeetsPlugin):
def commands(self):
cmd = beets.ui.Subcommand('albumify', help='group items into albums')
def func(lib, config, opts, args):
if args:
raise beets.ui.UserError('albumify takes no arguments')
albumify(lib)
lib.save()
cmd.func = func
return [cmd]

View file

@ -120,4 +120,3 @@ class DevicePlugin(BeetsPlugin):
pod.save()
cmd.func = func
return [cmd]

68
test/test_albumify.py Normal file
View file

@ -0,0 +1,68 @@
# This file is part of beets.
# Copyright 2010, Adrian Sampson.
#
# 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.
"""Tests for the albumify upgrader plugin."""
import unittest
import sys
sys.path.append('..')
from beets import library
from beets import ui
from beetsplug.albumify import albumify
from test_db import item
# Silence UI output.
ui.print_ = lambda s: None
class AlbumifyTest(unittest.TestCase):
def setUp(self):
self.lib = library.Library(':memory:')
i1, i2, i3 = item(), item(), item()
i1.album = 'album1'
i2.album = 'album1'
i3.album = 'album2'
self.lib.add(i1)
self.lib.add(i2)
self.lib.add(i3)
def test_albumify_creates_albums(self):
albumify(self.lib)
albums = [a.album for a in self.lib.albums()]
self.assert_('album1' in albums)
self.assert_('album2' in albums)
def test_albumify_groups_items(self):
albumify(self.lib)
q = library.MatchQuery('album', 'album1')
album1 = self.lib.albums(query=q)[0]
self.assertEqual(len( list(album1.items()) ), 2)
q = library.MatchQuery('album', 'album2')
album2 = self.lib.albums(query=q)[0]
self.assertEqual(len( list(album2.items()) ), 1)
def test_albumify_does_not_duplicate_existing_albums(self):
i4 = item()
i4.album = 'album3'
self.lib.add_album([i4])
self.assertEqual(len( list(self.lib.albums()) ), 1)
albumify(self.lib)
self.assertEqual(len( list(self.lib.albums()) ), 3)
def suite():
return unittest.TestLoader().loadTestsFromName(__name__)
if __name__ == '__main__':
unittest.main(defaultTest='suite')