"""repo of the EffectFunctions in the graph. Includes URI->realPythonFunction"""
import logging
from dataclasses import dataclass, field
from typing import Callable, List, Optional, cast
from rdfdb.syncedgraph.syncedgraph import SyncedGraph
from rdflib import RDF, RDFS, Literal
from light9.namespaces import FUNC, L9
from light9.newtypes import EffectAttr, EffectFunction, VTUnion
from light9.typedgraph import typedValue
from . import effect_functions
log = logging.getLogger('effectfuncs')
@dataclass
class _EffectFunctionInput:
effectAttr: EffectAttr
defaultValue: Optional[VTUnion]
@dataclass
class _RdfEffectFunction:
uri: EffectFunction
label: Optional[Literal]
inputs: List[_EffectFunctionInput]
@dataclass
class EffectFunctionLibrary:
"""parses :EffectFunction structures"""
graph: SyncedGraph
funcs: List[_RdfEffectFunction] = field(default_factory=list)
def __post_init__(self):
self.graph.addHandler(self._compile)
def _compile(self):
self.funcs = []
for subj in self.graph.subjects(RDF.type, L9['EffectFunction']):
label = typedValue(Literal | None, self.graph, subj, RDFS.label)
inputs = []
for inp in self.graph.objects(subj, L9['input']):
inputs.append(
_EffectFunctionInput( #
typedValue(EffectAttr, self.graph, inp, L9['effectAttr']), #
typedValue(VTUnion | None, self.graph, inp, L9['defaultValue'])))
self.funcs.append(_RdfEffectFunction(cast(EffectFunction, subj), label, inputs))
def getFunc(self, uri: EffectFunction) -> Callable:
return {
FUNC['scale']: effect_functions.effect_scale,
FUNC['strobe']: effect_functions.effect_strobe,
}[uri]
def getDefaultValue(self, uri: EffectFunction, attr: EffectAttr) -> VTUnion:
for f in self.funcs:
if f.uri == uri:
for i in f.inputs:
if i.effectAttr == attr:
if i.defaultValue is not None:
return i.defaultValue
raise ValueError(f'no default for {uri} {attr}')