import re import os def compile(string): """Compile a string into a function which fills in correct values.""" # This function will extract all variables and functions from $string # and convert these to functions. That way, it is much faster to run # than parse everytime $string. # we will split the string into sections; a section is either a string # or a variable. str, params=format_parse_rec(string.replace("%", "%%"), 0) ps=merge(params) func='lambda params: "%s" %% (%s)' % (str.replace('"', '\\"').replace("\n", ""), ps) return eval(func) def merge(list): ret="" for l in list: ret="%s%s, "%(ret, l) return ret[:-2] func=re.compile('\$[a-z_]+', re.IGNORECASE) def format_parse_rec(string, start): """Compiles a function. Returns [special str, params].""" match=func.search(string, start) if not match: return string[start:], [] ret1="" # string ret2=[] # params # set fixed string ret1+=string[start:match.start()] name=string[match.start()+1:match.end()] # here are all functions defined if name in ['if', 'ifn', 'dirname']: try: end=match_bracket(string, string.find("(", match.start())) except: end=-1 if end<0: raise Exception("No matching brackets") if name=='if' or name=='ifn': # print if something is true/false # $if($expr-true, $output) # $ifn($expr-false, $output) body=string[match.end():end] comma=body.find(',') s1,p1=format_parse_rec(body[1:comma], 0) # get the if-part s2,p2=format_parse_rec(body[comma+1:-1], 0) # if true! ret1+="%s" if name=='if': ret2.append("('%s' %% (%s) if (%s) else '')"%(s2, merge(p2), merge(p1))) elif name=='ifn': ret2.append("('%s' %% (%s) if not(%s) else '')"%(s2, merge(p2), merge(p1))) elif name=='dirname': # get the dir of a path # $dirname(path) s,p=format_parse_rec(string[match.end()+1:end-1], 0) ret1+="%s" ret2.append('os.path.dirname("%s"%%(%s))'%(s, merge(p))) else: end=match.end() # variable ret1+="%s" ret2.append('params["%s"]'%(name)) ret=format_parse_rec(string, end) ret1+=ret[0] if len(ret[1]): ret2.extend(ret[1]) return ret1, ret2 def match_bracket(string, start): """Returns position of matching bracket.""" assert(string[start:start+1]=="(") balance=1 start+=1 while balance>0: if start<=0: raise Exception("No matching bracket found") l=string.find("(", start) r=string.find(")", start) if l<0: if r>0: balance-=1 else: return -1 start=r+1 else: if lr: balance-=1 start=min(l,r)+1 if balance==0: return r+1 return max(l,r)+1 def params(song, overwrite={}, ensure={"title":"", "artist":""\ , "album":"", "genre":"", "track":"", "length":"" \ , "date":"", "time":""}): params={} for param in ensure: params[param]=ensure[param] if song: for param in song._data: params[param]=song._data[param] for param in overwrite: params[param]=overwrite[param] return params #f=compile("$if($date, ($date) )") #f=compile("a$if($title,$title)b$if($artist,$artist)c") #f=compile('abc$dirname($title/$artist/$artist$state)ghi') #print f({'state':'playing', 'title':'martha', 'artist':'waits'}) #f=compile("$artist $if($title, titeltje:$artist, $artist $title!) $album") #print f({'artist':'artist', 'title':'title', 'album':'album'}) #print format_compile('now $title a $artist two'); #print format_compile('now $state$if($title,$if($artist, yeay$title $artist))check')