# HG changeset patch # User drewp@bigasterisk.com # Date 2023-05-31 07:13:50 # Node ID 972a54f99b2cce7f830553e69ec0bad05abdcfd5 # Parent 10dd81f20f4b869c44ada5de8ce9bf9fceea8681 reformat & clean up imports diff --git a/light9/effect/effect_function_library.py b/light9/effect/effect_function_library.py --- a/light9/effect/effect_function_library.py +++ b/light9/effect/effect_function_library.py @@ -1,18 +1,18 @@ """repo of the EffectFunctions in the graph. Includes URI->realPythonFunction""" import logging from dataclasses import dataclass, field -from typing import Callable, Dict, List, Optional, Tuple, cast +from typing import Callable, List, Optional, cast from rdfdb.syncedgraph.syncedgraph import SyncedGraph -from rdflib import RDF, RDFS, Literal, Namespace, URIRef +from rdflib import RDF, RDFS, Literal -from light9.namespaces import DEV, FUNC, L9 -from light9.newtypes import (DeviceAttr, DeviceUri, EffectAttr, EffectFunction, EffectUri, HexColor, VTUnion) +from light9.namespaces import FUNC, L9 +from light9.newtypes import EffectAttr, EffectFunction, VTUnion from light9.typedgraph import typedValue -log = logging.getLogger('effectfuncs') +from . import effect_functions -from . import effect_functions +log = logging.getLogger('effectfuncs') @dataclass @@ -56,12 +56,12 @@ class EffectFunctionLibrary: FUNC['scale']: effect_functions.effect_scale, FUNC['strobe']: effect_functions.effect_strobe, }[uri] - - def getDefaultValue(self, uri: EffectFunction, attr:EffectAttr) -> VTUnion: + + 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.effectAttr == attr: if i.defaultValue is not None: return i.defaultValue raise ValueError(f'no default for {uri} {attr}') \ No newline at end of file diff --git a/light9/effect/effect_function_library_test.py b/light9/effect/effect_function_library_test.py --- a/light9/effect/effect_function_library_test.py +++ b/light9/effect/effect_function_library_test.py @@ -1,7 +1,5 @@ from light9.effect.effect_function_library import EffectFunctionLibrary - from light9.mock_syncedgraph import MockSyncedGraph -from light9.namespaces import L9 PREFIXES = ''' @prefix : . @@ -17,23 +15,23 @@ GRAPH = PREFIXES + ''' func:scale a :EffectFunction; rdfs:label "a submaster- scales :deviceSettings"; - :input + :input [ :effectAttr :strength; :defaultValue 0.0 ], [ :effectAttr :deviceSettings; ] . # e.g. "par2 at color=red; par3 at color=white" func:strobe a :EffectFunction; rdfs:label "blink specified devices"; - :input + :input [ :effectAttr :strength; :defaultValue 0.0 ], [ :effectAttr :period; :defaultValue 0.5 ], [ :effectAttr :onTime; :defaultValue 0.1 ], [ :effectAttr :deviceSettings ] . +''' -''' +class TestParsesGraph: -class TestParsesGraph: def test(self): g = MockSyncedGraph(GRAPH) lib = EffectFunctionLibrary(g) diff --git a/light9/effect/effect_functions.py b/light9/effect/effect_functions.py --- a/light9/effect/effect_functions.py +++ b/light9/effect/effect_functions.py @@ -39,9 +39,9 @@ def effect_strobe( onTime: float, devs: DeviceSettings) -> DeviceSettings: if period == 0: - scl=0 + scl = 0 else: - scl = strength if (songTime % period) < onTime else 0 + scl = strength if (songTime % period) < onTime else 0 return effect_scale(scl, devs) diff --git a/light9/effect/effecteval.py b/light9/effect/effecteval.py --- a/light9/effect/effecteval.py +++ b/light9/effect/effecteval.py @@ -2,23 +2,14 @@ import logging import math import random from colorsys import hsv_to_rgb -from dataclasses import dataclass, field -import time -from typing import Callable, Dict, List, Optional, Tuple, cast -from light9.effect.effect_function_library import EffectFunctionLibrary -from light9.typedgraph import typedValue from noise import pnoise1 from PIL import Image -from rdfdb.syncedgraph.syncedgraph import SyncedGraph -from rdflib import RDF, RDFS, Literal, Namespace, URIRef +from rdflib import Literal, Namespace from webcolors import hex_to_rgb, rgb_to_hex from light9.effect.scale import scale -from light9.effect.settings import BareEffectSettings, DeviceSettings, EffectSettings -from light9.namespaces import DEV, L9, FUNC -from light9.newtypes import (DeviceAttr, DeviceUri, EffectAttr, - EffectFunction, EffectUri, HexColor, VTUnion) +from light9.namespaces import DEV, L9 SKY = Namespace('http://light9.bigasterisk.com/theater/skyline/device/') diff --git a/light9/effect/effecteval2.py b/light9/effect/effecteval2.py --- a/light9/effect/effecteval2.py +++ b/light9/effect/effecteval2.py @@ -1,28 +1,30 @@ import inspect import logging -from dataclasses import dataclass, field -from typing import Callable, Dict, List, Optional, Tuple, cast +from dataclasses import dataclass +from typing import Callable, List, Optional from rdfdb.syncedgraph.syncedgraph import SyncedGraph -from rdflib import RDF, RDFS, Literal, Namespace, URIRef +from rdflib import RDF +from rdflib.term import Node from light9.effect.effect_function_library import EffectFunctionLibrary -from light9.effect.settings import (BareEffectSettings, DeviceSettings, EffectSettings) -from light9.namespaces import DEV, FUNC, L9 -from light9.newtypes import (DeviceAttr, DeviceUri, EffectAttr, EffectFunction, EffectUri, HexColor, VTUnion) +from light9.effect.settings import DeviceSettings, EffectSettings +from light9.namespaces import L9 +from light9.newtypes import (DeviceAttr, DeviceUri, EffectAttr, EffectFunction, EffectUri, VTUnion) from light9.typedgraph import typedValue -from rdflib.term import Node log = logging.getLogger('effecteval') + @dataclass class Config: effectFunction: EffectFunction esettings: EffectSettings - devSettings: Optional[DeviceSettings]# the EffectSettings :effectAttr :devSettings item, if there was one + devSettings: Optional[DeviceSettings] # the EffectSettings :effectAttr :devSettings item, if there was one func: Callable funcArgs: List[inspect.Parameter] + @dataclass class EffectEval2: """Runs one effect code to turn EffectSettings (e.g. strength) into DeviceSettings""" @@ -30,7 +32,7 @@ class EffectEval2: uri: EffectUri lib: EffectFunctionLibrary - config:Optional[Config]=None + config: Optional[Config] = None def __post_init__(self): self.graph.addHandler(self._compile) @@ -75,11 +77,10 @@ class EffectEval2: log.error(f"while compiling {self.uri}") raise - def compute(self, songTime: float, inputs: EffectSettings) -> DeviceSettings: """ - calls our function using inputs (publishedAttr attrs, e.g. :strength) - and effect-level settings including a special attr called :deviceSettings + calls our function using inputs (publishedAttr attrs, e.g. :strength) + and effect-level settings including a special attr called :deviceSettings with DeviceSettings as its value """ if self.config is None: @@ -101,15 +102,15 @@ class EffectEval2: return c.func(**kw) def _getEffectAttrValue(self, attr: EffectAttr, inputs: EffectSettings) -> VTUnion: - c=self.config - if c is None: raise + c = self.config + if c is None: + raise try: return inputs.getValue(self.uri, attr, defaultToZero=False) except KeyError: pass try: - return c.esettings.getValue(self.uri, attr, defaultToZero=False) + return c.esettings.getValue(self.uri, attr, defaultToZero=False) except KeyError: pass return self.lib.getDefaultValue(c.effectFunction, attr) - \ No newline at end of file diff --git a/light9/effect/effecteval_test.py b/light9/effect/effecteval_test.py --- a/light9/effect/effecteval_test.py +++ b/light9/effect/effecteval_test.py @@ -1,11 +1,13 @@ from typing import List, Tuple + +import pytest + from light9.effect.effect_function_library import EffectFunctionLibrary from light9.effect.effecteval2 import EffectEval2 from light9.effect.settings import DeviceSettings, EffectSettings from light9.mock_syncedgraph import MockSyncedGraph from light9.namespaces import DEV, L9 from light9.newtypes import (DeviceAttr, DeviceUri, EffectAttr, EffectUri, HexColor, VTUnion) -import pytest PREFIX = ''' @prefix : . @@ -20,14 +22,14 @@ GRAPH = PREFIX + ''' func:scale a :EffectFunction; rdfs:label "a submaster- scales :deviceSettings"; - :input + :input [ :effectAttr :strength; :defaultValue 0.0 ], [ :effectAttr :deviceSettings; ] . # e.g. "par2 at color=red; par3 at color=white" func:strobe a :EffectFunction; rdfs:label "blink specified devices"; - :input + :input [ :effectAttr :strength; :defaultValue 0.0 ], [ :effectAttr :period; :defaultValue 0.5 ], [ :effectAttr :onTime; :defaultValue 0.1 ], @@ -41,7 +43,7 @@ GRAPH = PREFIX + ''' [ :effectAttr :period; :defaultValue 2.0 ], [ :effectAttr :image; :defaultValue "specks.png" ], [ :effectAttr :deviceSettings; rdfs:comment "these might have a :sort key or a :y value" ] . - + :effectSub a :Effect; @@ -56,12 +58,12 @@ GRAPH = PREFIX + ''' :publishAttr :strength; :setting [ :effectAttr :deviceSettings; :value [ :setting [ :device dev:light1; :deviceAttr :color; :value "#ff0000" ] ] ]. - + :effectCustomStrobe a :Effect; :effectFunction func:strobe; :publishAttr :strength; - :setting + :setting [ :effectAttr :period; :value 3.0], [ :effectAttr :onTime; :value 0.5], [ :effectAttr :deviceSettings; :value [ diff --git a/light9/effect/scale.py b/light9/effect/scale.py --- a/light9/effect/scale.py +++ b/light9/effect/scale.py @@ -1,10 +1,11 @@ from decimal import Decimal +from webcolors import hex_to_rgb, rgb_to_hex + from light9.newtypes import VTUnion -from webcolors import hex_to_rgb, rgb_to_hex -def scale(value:VTUnion, strength:float): +def scale(value: VTUnion, strength: float): if isinstance(value, Decimal): raise TypeError() diff --git a/light9/effect/sequencer/eval_faders.py b/light9/effect/sequencer/eval_faders.py --- a/light9/effect/sequencer/eval_faders.py +++ b/light9/effect/sequencer/eval_faders.py @@ -4,22 +4,21 @@ from dataclasses import dataclass from typing import List, Optional, cast from prometheus_client import Summary -from light9.effect.effect_function_library import EffectFunctionLibrary -from light9.effect.effecteval2 import EffectEval2 - from rdfdb import SyncedGraph from rdflib import URIRef from rdflib.term import Node +from light9.effect.effect_function_library import EffectFunctionLibrary +from light9.effect.effecteval2 import EffectEval2 from light9.effect.settings import DeviceSettings, EffectSettings -from light9.metrics import metrics from light9.namespaces import L9, RDF from light9.newtypes import EffectAttr, EffectUri, UnixTime from light9.typedgraph import typedValue log = logging.getLogger('seq.fader') -COMPILE=Summary('compile_graph_fader', '') +COMPILE = Summary('compile_graph_fader', '') + @dataclass class Fader: @@ -29,19 +28,18 @@ class Fader: effect: EffectUri setEffectAttr: EffectAttr - value: Optional[float]=None # mutable + value: Optional[float] = None # mutable def __post_init__(self): self.ee = EffectEval2(self.graph, self.effect, self.lib) + class FaderEval: """peer to Sequencer, but this one takes the current :Fader settings -> sendToCollector """ - def __init__(self, - graph: SyncedGraph, - lib: EffectFunctionLibrary - ): + + def __init__(self, graph: SyncedGraph, lib: EffectFunctionLibrary): self.graph = graph self.lib = lib self.faders: List[Fader] = [] @@ -56,12 +54,12 @@ class FaderEval: for fader in self.graph.subjects(RDF.type, L9['Fader']): effect = typedValue(EffectUri, self.graph, fader, L9['effect']) setting = typedValue(Node, self.graph, fader, L9['setting']) - setAttr = typedValue(EffectAttr, self.graph, setting, L9['effectAttr']) + setAttr = typedValue(EffectAttr, self.graph, setting, L9['effectAttr']) self.faders.append(Fader(self.graph, self.lib, cast(URIRef, fader), effect, setAttr)) # this could go in a second, smaller addHandler call to avoid rebuilding Fader objs constantly for f in self.faders: - setting = typedValue(Node, self.graph, f.uri, L9['setting']) + setting = typedValue(Node, self.graph, f.uri, L9['setting']) f.value = typedValue(float, self.graph, setting, L9['value']) def computeOutput(self) -> DeviceSettings: diff --git a/light9/effect/sequencer/eval_faders_test.py b/light9/effect/sequencer/eval_faders_test.py --- a/light9/effect/sequencer/eval_faders_test.py +++ b/light9/effect/sequencer/eval_faders_test.py @@ -1,6 +1,6 @@ from unittest import mock + from light9.effect.effect_function_library import EffectFunctionLibrary - from light9.effect.sequencer.eval_faders import FaderEval from light9.effect.settings import DeviceSettings from light9.mock_syncedgraph import MockSyncedGraph @@ -49,9 +49,9 @@ NOTE_GRAPH = PREFIXES + ''' effect:effect1 a :Effect; :effectFunction func:scale; - :setting [:effectAttr :deviceSettings; :value [ + :setting [:effectAttr :deviceSettings; :value [ :setting [ - :device :light1; :deviceAttr :brightness; :value 0.5 + :device :light1; :deviceAttr :brightness; :value 0.5 ] ] ] . diff --git a/light9/effect/sequencer/service.py b/light9/effect/sequencer/service.py --- a/light9/effect/sequencer/service.py +++ b/light9/effect/sequencer/service.py @@ -6,7 +6,6 @@ import asyncio import json import logging import time -from light9.effect.effect_function_library import EffectFunctionLibrary from louie import dispatcher from rdfdb.syncedgraph.syncedgraph import SyncedGraph @@ -18,6 +17,7 @@ from starlette_exporter import Prometheu from lib.background_loop import loop_forever from light9 import networking from light9.collector.collector_client_asyncio import sendToCollector +from light9.effect.effect_function_library import EffectFunctionLibrary from light9.effect.sequencer.eval_faders import FaderEval from light9.effect.sequencer.sequencer import Sequencer, StateUpdate from light9.run_local import log diff --git a/light9/effect/settings_test.py b/light9/effect/settings_test.py --- a/light9/effect/settings_test.py +++ b/light9/effect/settings_test.py @@ -13,6 +13,7 @@ from light9.newtypes import DeviceAttr, def decimalLiteral(value): return Literal(value, datatype='http://www.w3.org/2001/XMLSchema#decimal') + class TestDeviceSettings(unittest.TestCase): def setUp(self):