Mercurial > code > home > repos > light9
view light9/effecteval/effect.py @ 1179:65405b3311f6
dead code
Ignore-this: 19fc9344a2ffe34598ccccd5738bd1a6
author | Drew Perttula <drewp@bigasterisk.com> |
---|---|
date | Sun, 15 Jun 2014 07:42:51 +0000 |
parents | da006651b531 |
children | 92ffad96fd8a |
line wrap: on
line source
import re, logging import toposort from rdflib import URIRef from light9.namespaces import L9, RDF from light9.curvecalc.curve import CurveResource from light9 import prof from light9 import Submaster from light9 import Effects # gets reload() later log = logging.getLogger('effect') # consider http://waxeye.org/ for a parser that can be used in py and js class CouldNotConvert(TypeError): pass class CodeLine(object): """code string is immutable""" def __init__(self, graph, code): self.graph, self.code = graph, code self.outName, self.inExpr, self.expr, self.resources = self._asPython() self.pyResources = self._resourcesAsPython(self.resources) self.possibleVars = self.findVars(self.inExpr) @prof.logTime def _asPython(self): """ out = sub(<uri1>, intensity=<curveuri2>) becomes 'out', 'sub(_u1, intensity=curve(_u2, t))', {'_u1': URIRef('uri1'), '_u2': URIRef('uri2')} """ lname, expr = [s.strip() for s in self.code.split('=', 1)] self.uriCounter = 0 resources = {} def alreadyInCurveFunc(s, i): prefix = 'curve(' return i >= len(prefix) and s[i-len(prefix):i] == prefix def repl(m): v = '_res%s' % self.uriCounter self.uriCounter += 1 r = resources[v] = URIRef(m.group(1)) if self._uriIsCurve(r): if not alreadyInCurveFunc(m.string, m.start()): return 'curve(%s, t)' % v return v outExpr = re.sub(r'<(http\S*?)>', repl, expr) return lname, expr, outExpr, resources def findVars(self, expr): """may return some more strings than just the vars""" withoutUris = re.sub(r'<(http\S*?)>', 'None', expr) tokens = set(re.findall(r'\b([a-zA-Z_]\w*)\b', withoutUris)) tokens.discard('None') return tokens def _uriIsCurve(self, uri): # this result could vary with graph changes (rare) return self.graph.contains((uri, RDF.type, L9['Curve'])) @prof.logTime def _resourcesAsPython(self, resources): """ mapping of the local names for uris in the code to high-level objects (Submaster, Curve) """ out = {} subs = prof.logTime(Submaster.get_global_submasters)(self.graph) for localVar, uri in resources.items(): for rdfClass in self.graph.objects(uri, RDF.type): if rdfClass == L9['Curve']: cr = CurveResource(self.graph, uri) # this is slow- pool these curves somewhere, maybe just with curveset prof.logTime(cr.loadCurve)() out[localVar] = cr.curve break elif rdfClass == L9['Submaster']: out[localVar] = subs.get_sub_by_uri(uri) break else: out[localVar] = CouldNotConvert(uri) break else: out[localVar] = CouldNotConvert(uri) return out class EffectNode(object): def __init__(self, graph, uri): self.graph, self.uri = graph, uri # this is not expiring at the right time, when an effect goes away self.graph.addHandler(self.prepare) @prof.logTime def prepare(self): log.info("prepare effect %s", self.uri) # maybe there can be multiple lines of code as multiple # objects here, and we sort them by dependencies codeStrs = list(self.graph.objects(self.uri, L9['code'])) if not codeStrs: raise ValueError("effect %s has no code" % self.uri) self.codes = [CodeLine(self.graph, s) for s in codeStrs] self.sortCodes() #reload(Effects) self.otherFuncs = prof.logTime(Effects.configExprGlobals)() def sortCodes(self): """put self.codes in a working evaluation order""" codeFromOutput = dict((c.outName, c) for c in self.codes) deps = {} for c in self.codes: outName = c.outName inNames = c.possibleVars.intersection(codeFromOutput.keys()) inNames.discard(outName) deps[outName] = inNames self.codes = [codeFromOutput[n] for n in toposort.toposort_flatten(deps)] def eval(self, songTime): ns = {'t': songTime} ns.update(self.otherFuncs) ns.update(dict( curve=lambda c, t: c.eval(t), )) for c in self.codes: codeNs = ns.copy() codeNs.update(c.pyResources) lineOut = eval(c.expr, codeNs) ns[c.outName] = lineOut if 'out' not in ns: log.error("ran code for %s, didn't make an 'out' value", self.uri) return ns['out']