Changeset - 60cc3a504377
[Not reviewed]
default
0 6 0
Drew Perttula - 8 years ago 2017-05-22 04:37:28
drewp@bigasterisk.com
more settings.py coverage. Zeros are now dropped from Settings lists.
Ignore-this: cc61e2f12ad9b41daa126ccfb58b4f09
6 files changed with 135 insertions and 30 deletions:
0 comments (0 inline, 0 general)
light9/collector/collector.py
Show inline comments
 
@@ -49,7 +49,7 @@ def outputMap(graph, outputs):
 
        
 
class Collector(Generic[ClientType, ClientSessionType]):
 
    def __init__(self, graph, outputs, listeners=None, clientTimeoutSec=10):
 
        # type: (Graph, List[Output], float) -> None
 
        # type: (Graph, List[Output], List[Listener], float) -> None
 
        self.graph = graph
 
        self.outputs = outputs
 
        self.listeners = listeners
light9/effect/settings.py
Show inline comments
 
@@ -17,13 +17,51 @@ def getVal(graph, subj):
 
    return ret
 

	
 
class _Settings(object):
 
    """
 
    default values are 0. Internal rep must not store zeros or some
 
    comparisons will break.
 
    """
 
    def __init__(self, graph, settingsList):
 
        self.graph = graph # for looking up all possible attrs
 
        self._compiled = {} # dev: { attr: val }
 
        for row in settingsList:
 
            self._compiled.setdefault(row[0], {})[row[1]] = row[2]
 
        # self._compiled may not be final yet- see _fromCompiled
 
        self._delZeros()
 
        
 
    @classmethod
 
    def _fromCompiled(cls, graph, compiled):
 
        obj = cls(graph, [])
 
        obj._compiled = compiled
 
        obj._delZeros()
 
        return obj
 
            
 
    @classmethod
 
    def fromResource(cls, graph, subj):
 
        settingsList = []
 
        with graph.currentState() as g:
 
            for s in g.objects(subj, L9['setting']):
 
                d = g.value(s, L9['device'])
 
                da = g.value(s, L9['deviceAttr'])
 
                v = getVal(g, s)
 
                settingsList.append((d, da, v))
 
        return cls(graph, settingsList)
 

	
 
    @classmethod
 
    def fromVector(cls, graph, vector):
 
        compiled = {}
 
        for (d, a), v in zip(cls(graph, [])._vectorKeys(), vector):
 
            compiled.setdefault(d, {})[a] = v
 
        return cls._fromCompiled(graph, compiled)
 

	
 
    def _delZeros(self):
 
        for dev, av in self._compiled.items():
 
            for attr, val in av.items():
 
                if val == 0:
 
                    del av[attr]
 
            if not av:
 
                del self._compiled[dev]
 
        
 
    def __hash__(self):
 
        itemed = tuple([(d, tuple([(a, v) for a, v in sorted(av.items())]))
 
                        for d, av in sorted(self._compiled.items())])
 
@@ -54,30 +92,6 @@ class _Settings(object):
 
        
 
    def getValue(self, dev, attr):
 
        return self._compiled.get(dev, {}).get(attr, 0)
 
        
 
    @classmethod
 
    def _fromCompiled(cls, graph, compiled):
 
        obj = cls(graph, [])
 
        obj._compiled = compiled
 
        return obj
 
            
 
    @classmethod
 
    def fromResource(cls, graph, subj):
 
        settingsList = []
 
        with graph.currentState() as g:
 
            for s in g.objects(subj, L9['setting']):
 
                d = g.value(s, L9['device'])
 
                da = g.value(s, L9['deviceAttr'])
 
                v = getVal(g, s)
 
                settingsList.append((d, da, v))
 
        return cls(graph, settingsList)
 

	
 
    @classmethod
 
    def fromVector(cls, graph, vector):
 
        compiled = {}
 
        for (d, a), v in zip(cls(graph, [])._vectorKeys(), vector):
 
            compiled.setdefault(d, {})[a] = v
 
        return cls._fromCompiled(graph, compiled)
 

	
 
    def _vectorKeys(self):
 
        """stable order of all the dev,attr pairs for this type of settings"""
 
@@ -118,7 +132,7 @@ class _Settings(object):
 
                dist += abs(attrs1[key] - attrs2[key])
 
        return dist
 

	
 
    def addStatements(self, subj, ctx, settingRoot, settingsSubgraphCache):
 
    def statements(self, subj, ctx, settingRoot, settingsSubgraphCache):
 
        """
 
        settingRoot can be shared across images (or even wider if you want)
 
        """
 
@@ -141,7 +155,7 @@ class _Settings(object):
 
                ])
 
            settingsSubgraphCache.add(setting)
 
            
 
        self.graph.patch(Patch(addQuads=add))
 
        return add
 

	
 

	
 
class DeviceSettings(_Settings):
light9/effect/settings_test.py
Show inline comments
 
import unittest
 
from rdflib import Literal
 
from light9.rdfdb.patch import Patch
 
from light9.rdfdb.localsyncedgraph import LocalSyncedGraph
 
from light9.namespaces import RDF, L9, DEV
 
from light9.effect.settings import DeviceSettings
 
@@ -11,3 +13,84 @@ class TestDeviceSettings(unittest.TestCa
 
    def testToVectorZero(self):
 
        ds = DeviceSettings(self.graph, [])
 
        self.assertEqual([0] * 20, ds.toVector())
 

	
 
    def testEq(self):
 
        s1 = DeviceSettings(self.graph, [
 
            (L9['light1'], L9['attr1'], 0.5),
 
            (L9['light1'], L9['attr2'], 0.3),
 
        ])
 
        s2 = DeviceSettings(self.graph, [
 
            (L9['light1'], L9['attr2'], 0.3),
 
            (L9['light1'], L9['attr1'], 0.5),
 
        ])
 
        self.assertTrue(s1 == s2)
 
        self.assertFalse(s1 != s2)
 

	
 
    def testMissingFieldsEqZero(self):
 
        self.assertEqual(
 
            DeviceSettings(self.graph, [(L9['aura1'], L9['rx'], 0),]),
 
            DeviceSettings(self.graph, []))
 
        
 
    def testFromResource(self):
 
        ctx = L9['']
 
        self.graph.patch(Patch(addQuads=[
 
            (L9['foo'], L9['setting'], L9['foo_set0'], ctx),
 
            (L9['foo_set0'], L9['device'], L9['light1'], ctx),
 
            (L9['foo_set0'], L9['deviceAttr'], L9['brightness'], ctx),
 
            (L9['foo_set0'], L9['value'], Literal(0.1), ctx),
 
            (L9['foo'], L9['setting'], L9['foo_set1'], ctx),
 
            (L9['foo_set1'], L9['device'], L9['light1'], ctx),
 
            (L9['foo_set1'], L9['deviceAttr'], L9['speed'], ctx),
 
            (L9['foo_set1'], L9['scaledValue'], Literal(0.2), ctx),
 
        ]))
 
        s = DeviceSettings.fromResource(self.graph, L9['foo'])
 

	
 
        self.assertEqual(DeviceSettings(self.graph, [
 
            (L9['light1'], L9['brightness'], 0.1),
 
            (L9['light1'], L9['speed'], 0.2),
 
        ]), s)
 

	
 
    def testToVector(self):
 
        v = DeviceSettings(self.graph, [
 
            (DEV['aura1'], L9['rx'], 0.5),
 
        ]).toVector()
 
        self.assertEqual(
 
            [0, 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], v)
 
        
 
    def testFromVector(self):
 
        s = DeviceSettings.fromVector(
 
            self.graph,
 
            [0, 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
 
        
 
        self.assertEqual(DeviceSettings(self.graph, [
 
            (DEV['aura1'], L9['rx'], 0.5),
 
        ]), s)                            
 

	
 
    def testAsList(self):
 
        sets = [
 
            (L9['light1'], L9['attr2'], 0.3),
 
            (L9['light1'], L9['attr1'], 0.5),
 
        ]
 
        self.assertItemsEqual(sets, DeviceSettings(self.graph, sets).asList())
 

	
 
    def testDevices(self):
 
        s = DeviceSettings(self.graph, [
 
            (L9['aura1'], L9['rx'], 0),
 
            (L9['aura2'], L9['rx'], 0.1),
 
            ])
 
        # aura1 is all defaults (zeros), so it doesn't get listed
 
        self.assertItemsEqual([L9['aura2']], s.devices())
 

	
 
    def testAddStatements(self):
 
        s = DeviceSettings(self.graph, [
 
            (L9['aura2'], L9['rx'], 0.1),
 
            ])
 
        stmts = s.statements(L9['foo'], L9['ctx1'], L9['s_'], set())
 
        self.maxDiff=None
 
        self.assertItemsEqual([
 
            (L9['foo'], L9['setting'], L9['s_set8011962'], L9['ctx1']),
 
            (L9['s_set8011962'], L9['device'], L9['aura2'], L9['ctx1']),
 
            (L9['s_set8011962'], L9['deviceAttr'], L9['rx'], L9['ctx1']),
 
            (L9['s_set8011962'], L9['value'], Literal(0.1), L9['ctx1']),
 
        ], stmts)
 
        
light9/paint/capture.py
Show inline comments
 
@@ -6,10 +6,10 @@ from light9.namespaces import L9
 
from light9.paint.solve import loadNumPy
 

	
 
def writeCaptureDescription(graph, ctx, uri, dev, relOutPath, settingsSubgraphCache, settings):
 
    settings.addStatements(
 
    graph.patch(Patch(addQuads=settings.statements(
 
        uri, ctx=ctx,
 
        settingRoot=URIRef('/'.join([showconfig.showUri(), 'capture', dev.rsplit('/')[1]])),
 
        settingsSubgraphCache=settingsSubgraphCache)
 
        settingsSubgraphCache=settingsSubgraphCache)))
 
    graph.patch(Patch(addQuads=[
 
        (dev, L9['capture'], uri, ctx),
 
        (uri, L9['imagePath'], URIRef('/'.join([showconfig.showUri(), relOutPath])), ctx),
light9/paint/solve.py
Show inline comments
 
@@ -149,7 +149,7 @@ class Solver(object):
 
                    settings.append((dev, attr, toHex(rgb)))
 
                else:
 
                    settings.append((dev, attr, xLeft.pop()))
 
            return settings
 
            return DeviceSettings(self.graph, settings)
 

	
 
        
 
        def drawError(x):
light9/rdfdb/localsyncedgraph.py
Show inline comments
 
@@ -3,6 +3,7 @@ from rdflib import ConjunctiveGraph
 
from light9.rdfdb.currentstategraphapi import CurrentStateGraphApi
 
from light9.rdfdb.autodepgraphapi import AutoDepGraphApi
 
from light9.rdfdb.grapheditapi import GraphEditApi
 
from light9.rdfdb.rdflibpatch import patchQuads
 

	
 
class LocalSyncedGraph(CurrentStateGraphApi, AutoDepGraphApi, GraphEditApi):
 
    """for tests"""
 
@@ -11,3 +12,10 @@ class LocalSyncedGraph(CurrentStateGraph
 
        for f in files or []:
 
            self._graph.parse(f, format='n3')
 
            
 

	
 
    def patch(self, p):
 
        patchQuads(self._graph,
 
                   deleteQuads=p.delQuads,
 
                   addQuads=p.addQuads,
 
                   perfect=True)
 
        # no deps
0 comments (0 inline, 0 general)