echonest: set types for flexible fields

Conflicts:
	beetsplug/echonest.py
This commit is contained in:
Thomas Scholtes 2014-09-12 12:12:09 +02:00
parent aa24fa7c1b
commit d4f72f62eb
3 changed files with 33 additions and 3 deletions

View file

@ -23,6 +23,7 @@ from string import Template
import subprocess
from beets import util, config, plugins, ui
from beets.dbcore import types
import pyechonest
import pyechonest.song
import pyechonest.track
@ -38,7 +39,9 @@ DEVNULL = open(os.devnull, 'wb')
ALLOWED_FORMATS = ('MP3', 'OGG', 'AAC')
UPLOAD_MAX_SIZE = 50 * 1024 * 1024
# The attributes we can import and where to store them in beets fields.
# Maps attribute names from echonest to their field names in beets.
# The attributes are retrieved from a songs `audio_summary`. See:
# http://echonest.github.io/pyechonest/song.html#pyechonest.song.profile
ATTRIBUTES = {
'energy': 'energy',
'liveness': 'liveness',
@ -49,6 +52,16 @@ ATTRIBUTES = {
'tempo': 'bpm',
}
# Types for the flexible fields added by `ATTRIBUTES`
FIELD_TYPES = {
'energy': types.FLOAT,
'liveness': types.FLOAT,
'speechiness': types.FLOAT,
'acousticness': types.FLOAT,
'danceability': types.FLOAT,
'valence': types.FLOAT,
}
MUSICAL_SCALE = ['C', 'C#', 'D', 'D#', 'E' 'F',
'F#', 'G', 'G#', 'A', 'A#', 'B']
@ -104,6 +117,9 @@ def similar(lib, src_item, threshold=0.15, fmt='${difference}: ${path}'):
class EchonestMetadataPlugin(plugins.BeetsPlugin):
item_types = FIELD_TYPES
def __init__(self):
super(EchonestMetadataPlugin, self).__init__()
self.config.add({

View file

@ -43,7 +43,7 @@ from enum import Enum
import beets
from beets import config
import beets.plugins
from beets.library import Library, Item
from beets.library import Library, Item, Album
from beets import importer
from beets.autotag.hooks import AlbumInfo, TrackInfo
from beets.mediafile import MediaFile
@ -168,18 +168,24 @@ class TestHelper(object):
Similar setting a list of plugins in the configuration. Make
sure you call ``unload_plugins()`` afterwards.
"""
# FIXME this should eventually be handled by a plugin manager
beets.config['plugins'] = plugins
beets.plugins.load_plugins(plugins)
beets.plugins.find_plugins()
Item._types = beets.plugins.types(Item)
Album._types = beets.plugins.types(Album)
def unload_plugins(self):
"""Unload all plugins and remove the from the configuration.
"""
# FIXME this should eventually be handled by a plugin manager
beets.config['plugins'] = []
for plugin in beets.plugins._classes:
plugin.listeners = None
beets.plugins._classes = set()
beets.plugins._instances = {}
Item._types = {}
Album._types = {}
def create_importer(self, item_count=1, album_count=1):
"""Create files to import and return corresponding session.

View file

@ -70,9 +70,17 @@ class EchonestCliTest(unittest.TestCase, TestHelper):
self.run_command('echonest')
item.load()
self.assertEqual(item['danceability'], '0.5')
self.assertEqual(item['danceability'], 0.5)
self.assertEqual(item['liveness'], 0.5)
self.assertEqual(item['bpm'], 120)
self.assertEqual(item['initial_key'], 'C#m')
def test_custom_field_range_query(self):
item = Item(liveness=2.2)
item.add(self.lib)
item = self.lib.items('liveness:2.2..3').get()
self.assertEqual(item['liveness'], 2.2)
def suite():
return unittest.TestLoader().loadTestsFromName(__name__)