mirror of
https://github.com/beetbox/beets.git
synced 2025-12-29 03:52:51 +01:00
albumify plugin for upgrading old databases
This commit is contained in:
parent
adcaaf3a13
commit
5b2653bb53
4 changed files with 121 additions and 6 deletions
9
NEWS
9
NEWS
|
|
@ -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
49
beetsplug/albumify.py
Normal 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]
|
||||
|
|
@ -120,4 +120,3 @@ class DevicePlugin(BeetsPlugin):
|
|||
pod.save()
|
||||
cmd.func = func
|
||||
return [cmd]
|
||||
|
||||
|
|
|
|||
68
test/test_albumify.py
Normal file
68
test/test_albumify.py
Normal 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')
|
||||
Loading…
Reference in a new issue