maloja/cleanup.py

144 lines
4.3 KiB
Python
Raw Normal View History

2018-11-24 18:29:24 +03:00
import re
2018-11-28 19:45:52 +03:00
import utilities
2018-11-24 18:29:24 +03:00
2018-11-28 19:45:52 +03:00
# need to do this as a class so it can retain loaded settings from file
class CleanerAgent:
2018-11-26 18:21:07 +03:00
2018-11-28 19:45:52 +03:00
def __init__(self):
self.updateRules()
def updateRules(self):
raw = utilities.parseAllTSV("rules","string","string","string")
self.rules_belongtogether = [b for [a,b,c] in raw if a=="belongtogether"]
self.rules_notanartist = [b for [a,b,c] in raw if a=="notanartist"]
self.rules_replacetitle = {b:c for [a,b,c] in raw if a=="replacetitle"}
self.rules_replaceartist = {b:c for [a,b,c] in raw if a=="replaceartist"}
def fullclean(self,artist,title):
artists = self.parseArtists(self.removespecial(artist))
title = self.parseTitle(self.removespecial(title))
(title,moreartists) = self.parseTitleForArtists(title)
artists += moreartists
return (list(set(artists)),title)
2018-11-26 18:21:07 +03:00
2018-11-28 19:45:52 +03:00
def removespecial(self,s):
return s.replace("\t","").replace("","").replace("\n","")
2018-11-26 18:21:07 +03:00
2018-11-24 18:29:24 +03:00
2018-11-28 20:44:33 +03:00
delimiters_feat = ["ft.","ft","feat.","feat","featuring","Ft.","Ft","Feat.","Feat","Featuring"] #Delimiters used for extra artists, even when in the title field
delimiters = ["vs.","vs","&"] #Delimiters in informal artist strings, spaces expected around them
2018-12-04 21:17:44 +03:00
delimiters_formal = ["; ",";","/"] #Delimiters used specifically to tag multiple artists when only one tag field is available, no spaces used
2018-11-24 18:29:24 +03:00
2018-11-28 17:33:30 +03:00
2018-11-28 19:45:52 +03:00
def parseArtists(self,a):
2018-11-28 17:33:30 +03:00
2018-11-28 19:45:52 +03:00
if a.strip() == "":
return []
if a.strip() in self.rules_belongtogether:
return [a.strip()]
if a.strip() in self.rules_replaceartist:
2018-11-29 16:45:31 +03:00
return self.rules_replaceartist[a.strip()].split("")
2018-11-28 17:33:30 +03:00
2018-11-24 18:29:24 +03:00
2018-11-28 19:45:52 +03:00
for d in self.delimiters_feat:
if re.match(r"(.*) \(" + d + " (.*)\)",a) is not None:
return self.parseArtists(re.sub(r"(.*) \(" + d + " (.*)\)",r"\1",a)) + self.parseArtists(re.sub(r"(.*) \(" + d + " (.*)\)",r"\2",a))
for d in (self.delimiters_feat + self.delimiters):
if ((" " + d + " ") in a):
ls = []
for i in a.split(" " + d + " "):
ls += self.parseArtists(i)
return ls
for d in self.delimiters_formal:
if (d in a):
ls = []
for i in a.split(d):
ls += self.parseArtists(i)
return ls
return [a.strip()]
2018-11-24 18:29:24 +03:00
2018-11-28 19:45:52 +03:00
def parseTitle(self,t):
if t.strip() in self.rules_replacetitle:
return self.rules_replacetitle[t.strip()]
2018-11-24 18:29:24 +03:00
2018-11-28 19:45:52 +03:00
t = t.replace("[","(").replace("]",")")
t = re.sub(r" \(as made famous by .*?\)","",t)
t = re.sub(r" \(originally by .*?\)","",t)
return t.strip()
2018-11-28 17:33:30 +03:00
2018-11-28 19:45:52 +03:00
def parseTitleForArtists(self,t):
for d in self.delimiters_feat:
if re.match(r"(.*) \(" + d + " (.*?)\)",t) is not None:
(title,artists) = self.parseTitleForArtists(re.sub(r"(.*) \(" + d + " (.*?)\)",r"\1",t))
artists += self.parseArtists(re.sub(r"(.*) \(" + d + " (.*?)\).*",r"\2",t))
return (title,artists)
return (t,[])
2018-12-04 20:43:48 +03:00
#this is for all the runtime changes (counting Trouble Maker as HyunA for charts etc)
class CollectorAgent:
def __init__(self):
self.updateRules()
def updateRules(self):
raw = utilities.parseAllTSV("rules","string","string","string")
self.rules_countas = {b:c for [a,b,c] in raw if a=="countas"}
self.rules_include = {} #Twice the memory, double the performance! (Yes, we're saving redundant information here, but it's not unelegant if it's within a closed object!)
for a in self.rules_countas:
self.rules_include[self.rules_countas[a]] = self.rules_include.setdefault(self.rules_countas[a],[]) + [a]
# this agent needs to be aware of the current id assignment in the main program. but unelegant, but the best way i can think of
def updateIDs(self,artistlist):
self.rules_countas_id = {artistlist.index(a):artistlist.index(self.rules_countas[a]) for a in self.rules_countas}
#self.rules_include_id = {artistlist.index(a):artistlist.index(self.rules_include[a]) for a in self.rules_include}
#this needs to take lists into account
def getCredited(self,artist):
if artist in self.rules_countas_id:
return self.rules_countas_id[artist]
if artist in self.rules_countas:
return self.rules_countas[artist]
else:
return artist
2018-11-28 19:45:52 +03:00
2018-12-04 20:43:48 +03:00
def getCreditedList(self,artists):
updatedArtists = []
for artist in artists:
updatedArtists.append(self.getCredited(artist))
return list(set(updatedArtists))
2018-11-28 19:45:52 +03:00
2018-11-24 18:29:24 +03:00
def flatten(lis):
newlist = []
2018-11-28 19:45:52 +03:00
2018-11-24 18:29:24 +03:00
for l in lis:
if isinstance(l, str):
newlist.append(l)
else:
newlist = newlist + l
2018-11-28 19:45:52 +03:00
2018-11-24 18:29:24 +03:00
return list(set(newlist))