From 9fd10c01869b23117658ecc839aaaf63d73a62bc Mon Sep 17 00:00:00 2001 From: kraymer Date: Tue, 11 Oct 2011 00:16:57 +0200 Subject: [PATCH] add genres canonicalization: when a last.fm tag is found but rejected (because not in user whitelist), try to found a parent tag that is accepted --HG-- extra : transplant_source : %C6%F2%F9%EDY%C4%1B%FD%BDV/%E5%041I%CB4%00%0A%07 --- beetsplug/lastgenre/__init__.py | 52 +++- beetsplug/lastgenre/genres-tree.yaml | 426 +++++++++++++++++++++++++++ 2 files changed, 476 insertions(+), 2 deletions(-) create mode 100644 beetsplug/lastgenre/genres-tree.yaml diff --git a/beetsplug/lastgenre/__init__.py b/beetsplug/lastgenre/__init__.py index c28ba3ec8..59a688227 100644 --- a/beetsplug/lastgenre/__init__.py +++ b/beetsplug/lastgenre/__init__.py @@ -29,14 +29,17 @@ from __future__ import with_statement import logging import pylast import os +from yaml import load from beets import plugins from beets import ui from beets.util import normpath log = logging.getLogger('beets') + LASTFM = pylast.LastFMNetwork(api_key=plugins.LASTFM_KEY) DEFAULT_WHITELIST = os.path.join(os.path.dirname(__file__), 'genres.txt') +C14N_TREE = os.path.join(os.path.dirname(__file__), 'genres-tree.yaml') def _tags_for(obj): """Given a pylast entity (album or track), returns a list of @@ -67,11 +70,49 @@ def _tags_to_genre(tags): return tags[0].title() for tag in tags: - if tag.lower() in options['whitelist']: - return tag.title() + genre = find_allowed( + find_parents(tag.lower(), options['branches'])) + if genre: + return genre return None +def flatten_tree(elem, path, branches): + """Flatten nested lists/dictionaries into lists of strings (branches). + """ + if not path: + path = [] + + if isinstance(elem, dict): + for (k, v) in elem.items() : + flatten_tree(v, path + [k], branches) + elif isinstance(elem, list): + for sub in elem: + flatten_tree(sub, path, branches) + else: + branches.append(path + [elem]) + +def find_parents(candidate, branches): + """Find parents genre of a given genre, ordered from the closest to the + further parent. + """ + for branch in branches: + try: + idx = branch.index(candidate) + return list(reversed(branch[:idx+1])) + except ValueError: + continue + return [candidate] + +def find_allowed(genres): + """Returns the first genre that is present in the genre whitelist or + None if no genre is suitable. + """ + for g in list(genres): + if g in options['whitelist']: + return g.title() + return None + options = { 'whitelist': None, } @@ -92,6 +133,13 @@ class LastGenrePlugin(plugins.BeetsPlugin): if line: whitelist.add(line) options['whitelist'] = whitelist + + # Read the genres tree for canonicalization + genres_tree = load(open(C14N_TREE, 'r')) + branches = [] + flatten_tree(genres_tree, [], branches) + options['branches'] = branches + @LastGenrePlugin.listen('album_imported') def album_imported(lib, album): diff --git a/beetsplug/lastgenre/genres-tree.yaml b/beetsplug/lastgenre/genres-tree.yaml new file mode 100644 index 000000000..50601ba36 --- /dev/null +++ b/beetsplug/lastgenre/genres-tree.yaml @@ -0,0 +1,426 @@ +- blues: + - african blues + - blues rock: + - punk blues + - country blues + - british blues + - classic female blues + - country blues: + - delta blues: + - electric blues: + - blues rock + - east coast blues + - hill country blues + - jump blues + - swamp blues + - new orleans blues + - dirty blues + - fife and drum blues + - gospel blues + - harmonica blues + - indian blues + - piano blues: + - boogie-woogie: + - boogie rock + - soul blues + - west coast blues +- country: + - alternative country: + - americana + - blues country + - cowpunk + - country rock + - country folk + - country rap: + - country crunk: + - country psycrunk + - deathcountry + - gothic americana + - hellbilly + - nashville sound: + - country pop + - outlaw country + - psychobilly + - punkabilly + - psydeco + - red dirt + - rockabilly + - rock country + - soul country + - techno-country + - texas country: + - progressive country + - bakersfield sound + - bluegrass: + - heavy metal bluegrass + - nu-grass + - old-time bluegrass + - progressive bluegrass + - reactionary bluegrass + - christian country music + - neotraditional country + - western music: + - honky tonk +- easy listening: + - background music + - beautiful music + - elevator music + - furniture music + - lounge music +- electronic: + - ambient: + - ambient house + - ambient techno + - dark ambient + - drone music + - illbient + - isolationism + - lowercase + - breakbeat: + - acid breaks + - baltimore club + - big beat + - breakbeat hardcore + - broken beat + - florida breaks + - nu skool breaks + - 4-beat + - dance: + - eurodance + - hi-nrg + - house: + - acid house + - autumn house + - chicago house + - deep house + - diva house + - fidget house + - french house + - freestyle house + - funky house + - ghetto house + - hardbag + - hip house + - italo house + - latin house + - minimal house + - microhouse + - rave music + - swing house + - tech house + - tribal house + - uk hard house + - us garage + - vocal house + - electronica: + - berlin school + - bitpop + - chip + - chillwave + - downtempo: + - acid jazz + - balearic beat + - chill out + - dubtronica + - ethnic electronica + - moombahton + - new age music + - nu jazz + - trip hop + - folktronica + - glitch + - idm + - plinkerpop + - hardcore techno: + - bouncy house + - bouncy techno + - breakcore + - darkcore + - digital hardcore + - doomcore + - gabba + - happy hardcore + - hardstyle + - jumpstyle + - makina + - speedcore + - terrorcore + - uk hardcore + - jungle: + - drum and bass: + - clownstep + - darkcore + - darkstep + - drumfunk + - drumstep + - hardstep + - intelligent drum and bass + - jump-up + - liquid funk + - neurofunk + - oldschool jungle: + - darkside jungle + - ragga-jungle + - raggacore + - sambass + - trancestep + - progressive: + - progressive breaks + - progressive drum & bass + - progressive house: + - disco house + - dream house + - space house + - progressive techno + - techno: + - acid techno + - detroit techno + - free tekno + - ghettotech + - minimal + - nortec + - rotterdam techno + - schranz / hardtechno + - symphonic techno + - tecno brega + - techno-dnb + - techstep + - toytown techno + - trance: + - acid trance + - classic trance + - dream trance + - euro-trance + - goa trance: + - dark psytrance + - full on + - psyprog + - psybient + - psybreaks + - hard trance + - neo-trance + - tech trance + - uplifting trance: + - orchestral uplifting + - vocal trance: + - nightcore + - uk garage: + - 2-step + - 4x4 + - bassline + - breakstep + - dubstep + - funky + - grime + - speed garage +- folk: + - folk punk + - indie folk + - neofolk + - progressive folk + - anti-folk +- hip hop & rap: + - hip hop: + - alternative hip hop: + - jazz rap + - abstract hip hop + - british hip hop: + - grime + - political hip hop + - turntablism + - us hip hop: + - east coast hip hop: + - conscious rap + - midwest hip hop: + - ghetto house + - ghettotech + - horrorcore + - southern hip hop: + - snap music + - bounce music + - crunk + - chopped and screwed + - west coast hip hop: + - gangsta rap: + - g-funk + - latin rap + - g-funk + - hyphy + - jerkin' + - rap: + - bass rap + - dirty rap + - hardcore rap + - mafioso rap + - party rap + - porn rap + - rap metal + - rap rock + - rapcore +- latin: + - bachata + - brazilian music: + - samba: + - bossa nova: + - tropicalismo + - calypso + - chutney: + - chutney soca + - cuban music: + - salsa + - son cubano + - cumbia + - kompa + - mambo: + - cha-cha-cha + - pachanga + - merengue + - salsa + - soca + - tejano + - zouk +- pop: + - electro pop + - new romantic + - operatic pop + - pop rap + - psychedelic pop + - sunshine pop + - surf pop + - synthpop + - teen pop + - traditional pop music + - turkish pop + - world: + - europop + - indian pop + - latin pop +- r&b: + - contemporary r&b + - doo wop + - funkd: + - deep funk + - disco: + - eurodisco + - disco polo + - post disco + - space disco + - boogie + - go-go + - nu-funk + - p-funk + - new jack swing + - soul: + - blue-eyed soul + - brown-eyed soul + - hip hop soul + - motown sound + - neo soul + - northern soul + - psychedelic soul + - smooth soul + - quiet storm +- rock: + - alternative rock: + - britpop: + - post-britpop + - dream pop + - grunge: + - post-grunge + - indie pop + - indie rock + - industrial rock + - noise pop + - post-rock + - shoegazer + - slowcore + - blues-rock + - chinese rock + - dark cabaret + - desert rock + - electronic rock + - folk rock + - garage rock + - glam rock + - hard rock + - heavy metal: + - black metal + - christian metal + - death metal: + - brutal death metal + - melodic death metal + - technical death metal + - progressive death metal + - doom metal + - drone metal + - folk metal + - funk metal + - glam metal + - gothic metal + - grindcore + - groove metal + - industrial metal + - metalcore: + - deathcore + - mathcore + - melodic metalcore + - djent + - nu metal + - power metal + - progressive metal + - rap metal + - sludge metal + - speed metal + - stoner rock + - symphonic metal + - thrash metal: + - crossover thrash metal + - thrashcore + - weld + - unblack metal + - jazz-rock + - j-rock + - math rock + - new wave: + - world fusion + - paisley underground + - pop rock + - power pop + - progressive rock: + - new prog + - space rock + - psychedelic rock: + - acid rock + - punk rock: + - anarcho punk: + - crust punk + - deathrock + - hardcore punk: + - post-hardcore + - emo: + - screamo + - pop punk + - post-punk: + - gothic rock + - psychobilly + - rap rock: + - rapcore + - rock and roll + - soft rock + - southern rock + - surf rock +- ska: + - 2 tone + - reggae: + - early reggae + - dub: + - dub poetry + - afro-dub + - rockers + - lovers rock + - dancehall: + - ragga + - reggaeton + - raggamuffin + - roots reggae + - rocksteady