changeset 1873:f001d689b3e2

more py3 and typing fixes Ignore-this: 3180bd966cac69de56b86ef6a308cad4
author Drew Perttula <drewp@bigasterisk.com>
date Mon, 27 May 2019 06:20:38 +0000
parents 5ebdb55e2ee6
children fc72f550ddcd
files bcf2000.py bin/keyboardcomposer bin/rdfdb light9/collector/collector_client.py light9/effect/effecteval.py light9/effect/sequencer.py light9/effect/settings.py light9/effect/simple_outputs.py light9/namespaces.py light9/networking.py light9/prof.py light9/showconfig.py light9/tkdnd.py light9/uihelpers.py light9/vidref/musictime.py light9/web/websocket.js requirements.txt tasks.py
diffstat 18 files changed, 95 insertions(+), 79 deletions(-) [+]
line wrap: on
line diff
--- a/bcf2000.py	Mon May 27 06:20:25 2019 +0000
+++ b/bcf2000.py	Mon May 27 06:20:38 2019 +0000
@@ -1,9 +1,10 @@
 #!/usr/bin/python
-from __future__ import division
+
 import math
 import twisted.internet.fdesc
 from twisted.internet import reactor
 from twisted.internet.task import LoopingCall
+from typing import Dict
 
 class BCF2000(object):
 
@@ -35,7 +36,7 @@
         once as C0D0. It should be autodetected"""
         self.devPath = dev
         self.dev = None
-        self.lastValue = {} # control name : value
+        self.lastValue: Dict[str, int] = {} # control name : value
         self.reopen()
         self.packet = ""
         loop = LoopingCall(self.poll)
@@ -47,7 +48,7 @@
         except (IOError, AttributeError):
             return
         if len(bytes) == 0:
-            print "midi stall, reopen slider device"
+            print("midi stall, reopen slider device")
             self.reopen()
             return
         self.packet += bytes
@@ -67,7 +68,7 @@
             self.lastValue[name] = value
             self.valueIn(name, value)
         else:
-            print "unknown control %s to %s" % (which, value)
+            print("unknown control %s to %s" % (which, value))
 
     def reopen(self):
         if self.dev is not None:
@@ -83,7 +84,7 @@
     def valueIn(self, name, value):
         """override this with your handler for when events come in
         from the hardware"""
-        print "slider %s to %s" % (name, value)
+        print("slider %s to %s" % (name, value))
         if name == 'slider1':
             for x in range(2,8+1):
                 v2 = int(64 + 64 * math.sin(x / 3 + value / 10))
@@ -101,7 +102,7 @@
         if self.lastValue.get(name) == value:
             return
         self.lastValue[name] = value
-        which = [k for k,v in self.control.items() if v == name]
+        which = [k for k,v in list(self.control.items()) if v == name]
         assert len(which) == 1, "unknown control name %r" % name
         if name.startswith('button-'):
             value = value * 127
--- a/bin/keyboardcomposer	Mon May 27 06:20:25 2019 +0000
+++ b/bin/keyboardcomposer	Mon May 27 06:20:38 2019 +0000
@@ -9,6 +9,7 @@
 from twisted.web import resource
 from rdflib import URIRef, Literal
 import tkinter.tix as tk
+from typing import Dict, Tuple, List
 
 from light9.Fadable import Fadable
 from light9.subclient import SubClient
@@ -84,7 +85,7 @@
         self.sub = sub
         self.session = session
         self.col, self.row = col, row
-        bg = self.graph.value(sub, L9.color, default='#000000')
+        bg = self.graph.value(sub, L9['color'], default='#000000')
         rgb = webcolors.hex_to_rgb(bg)
         hsv = colorsys.rgb_to_hsv(*[x / 255 for x in rgb])
         darkBg = webcolors.rgb_to_hex(
@@ -186,9 +187,9 @@
         self.graph = graph
         self.session = session
 
-        self.subbox = {}  # sub uri : SubmasterBox
-        self.slider_table = {}  # coords : SubmasterBox
-        self.rows = []  # this holds Tk Frames for each row
+        self.subbox: Dict[URIRef, SubmasterBox] = {}  # sub uri : SubmasterBox
+        self.slider_table: Dict[Tuple[int, int], SubmasterBox] = {}  # coords : SubmasterBox
+        self.rows: List[tk.Frame] = []  # this holds Tk Frames for each row
 
         self.current_row = 0  # should come from session graph
 
@@ -270,7 +271,7 @@
 
         log.info("withgroups %s", withgroups)
 
-        self.effectEval = {}
+        self.effectEval: Dict[URIRef, light9.effect.effecteval.EffectEval] = {}
         imp.reload(light9.effect.effecteval)
         simpleOutputs = SimpleOutputs(self.graph)
         for group, order, sortLabel, effect in withgroups:
--- a/bin/rdfdb	Mon May 27 06:20:25 2019 +0000
+++ b/bin/rdfdb	Mon May 27 06:20:38 2019 +0000
@@ -1,21 +1,23 @@
 #!bin/python
 import run_local  # noqa
 import os
+from rdflib import URIRef
 from light9 import networking, showconfig
 import rdfdb.service
 
 rdfdb.service.main(
     dirUriMap={
-        os.environ['LIGHT9_SHOW'].rstrip('/') + '/': showconfig.showUri() + '/'
+        os.environ['LIGHT9_SHOW'].encode('ascii').rstrip(b'/') + b'/':
+        URIRef(showconfig.showUri() + '/')
     },
     prefixes={
-        'show': showconfig.showUri() + '/',
-        '': 'http://light9.bigasterisk.com/',
-        'rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
-        'rdfs': 'http://www.w3.org/2000/01/rdf-schema#',
-        'xsd': 'http://www.w3.org/2001/XMLSchema#',
-        'effect': 'http://light9.bigasterisk.com/effect/',
-        'dev': 'http://light9.bigasterisk.com/device/',
+        'show': URIRef(showconfig.showUri() + '/'),
+        '': URIRef('http://light9.bigasterisk.com/'),
+        'rdf': URIRef('http://www.w3.org/1999/02/22-rdf-syntax-ns#'),
+        'rdfs': URIRef('http://www.w3.org/2000/01/rdf-schema#'),
+        'xsd': URIRef('http://www.w3.org/2001/XMLSchema#'),
+        'effect': URIRef('http://light9.bigasterisk.com/effect/'),
+        'dev': URIRef('http://light9.bigasterisk.com/device/'),
     },
     port=networking.rdfdb.port,
 )
--- a/light9/collector/collector_client.py	Mon May 27 06:20:25 2019 +0000
+++ b/light9/collector/collector_client.py	Mon May 27 06:20:38 2019 +0000
@@ -11,7 +11,6 @@
 
 
 class TwistedZmqClient(object):
-
     def __init__(self, service):
         zf = ZmqFactory()
         e = ZmqEndpoint('connect', 'tcp://%s:%s' % (service.host, service.port))
--- a/light9/effect/effecteval.py	Mon May 27 06:20:25 2019 +0000
+++ b/light9/effect/effecteval.py	Mon May 27 06:20:38 2019 +0000
@@ -1,4 +1,4 @@
-from rdflib import Literal
+from rdflib import Literal, URIRef
 from light9.namespaces import L9, DEV
 from webcolors import rgb_to_hex, hex_to_rgb
 from colorsys import hsv_to_rgb
@@ -7,6 +7,7 @@
 import logging
 from light9.effect.settings import DeviceSettings
 from light9.effect.scale import scale
+from typing import Dict, Tuple, Any
 import random
 random.seed(0)
 print("reload effecteval")
@@ -76,7 +77,7 @@
             return DeviceSettings(self.graph, []), {'zero': True}
 
         report = {}
-        out = {}  # (dev, attr): value
+        out: Dict[Tuple[URIRef, URIRef], Any] = {}  # (dev, attr): value
 
         out.update(
             self.simpleOutputs.values(
--- a/light9/effect/sequencer.py	Mon May 27 06:20:25 2019 +0000
+++ b/light9/effect/sequencer.py	Mon May 27 06:20:38 2019 +0000
@@ -11,12 +11,14 @@
 import cyclone.sse
 import logging, bisect, time
 import traceback
+from typing import Any, Callable, Dict, List, Tuple
 
 from light9.namespaces import L9, RDF
 from light9.vidref.musictime import MusicTime
 from light9.effect import effecteval
 from light9.effect.settings import DeviceSettings
 from light9.effect.simple_outputs import SimpleOutputs
+from rdfdb.syncedgraph import SyncedGraph
 
 from greplin import scales
 import imp
@@ -38,7 +40,7 @@
         self.uri = uri
         self.effectEval = effectevalModule.EffectEval(
             graph, g.value(uri, L9['effectClass']), simpleOutputs)
-        self.baseEffectSettings = {}  # {effectAttr: value}
+        self.baseEffectSettings: Dict[URIRef, Any] = {}  # {effectAttr: value}
         for s in g.objects(uri, L9['setting']):
             settingValues = dict(g.predicate_objects(s))
             ea = settingValues[L9['effectAttr']]
@@ -48,13 +50,13 @@
             return float(g.value(s, p).toPython())
 
         originTime = floatVal(uri, L9['originTime'])
-        self.points = []
+        self.points: List[Tuple[float, float]] = []
         for curve in g.objects(uri, L9['curve']):
             self.points.extend(
                 self.getCurvePoints(curve, L9['strength'], originTime))
         self.points.sort()
 
-    def getCurvePoints(self, curve, attr, originTime):
+    def getCurvePoints(self, curve, attr, originTime) -> List[Tuple[float, float]]:
         points = []
         po = list(self.graph.predicate_objects(curve))
         if dict(po).get(L9['attr'], None) != attr:
@@ -129,16 +131,17 @@
 
 class Sequencer(object):
 
-    def __init__(self, graph, sendToCollector, fps=40):
+    def __init__(self, graph: SyncedGraph, sendToCollector: Callable[[DeviceSettings], None],
+                 fps=40):
         self.graph = graph
         self.fps = fps
         self.sendToCollector = sendToCollector
         self.music = MusicTime(period=.2, pollCurvecalc=False)
 
-        self.recentUpdateTimes = []
-        self.lastStatLog = 0
+        self.recentUpdateTimes: List[float] = []
+        self.lastStatLog = 0.0
         self._compileGraphCall = None
-        self.notes = {}  # song: [notes]
+        self.notes: Dict[URIRef, List[Note]] = {}  # song: [notes]
         self.simpleOutputs = SimpleOutputs(self.graph)
         self.graph.addHandler(self.compileGraph)
         self.updateLoop()
@@ -166,7 +169,7 @@
                 Note(self.graph, note, effecteval, self.simpleOutputs))
         log.info('  compile %s took %.2f ms', song, 1000 * (time.time() - t1))
 
-    def updateLoop(self):
+    def updateLoop(self) -> None:
         # print "updateLoop"
         now = time.time()
         self.recentUpdateTimes = self.recentUpdateTimes[-40:] + [now]
@@ -232,7 +235,7 @@
 
     def __init__(self, application, request, **kwargs):
         cyclone.sse.SSEHandler.__init__(self, application, request, **kwargs)
-        self.state = {}
+        self.state: Dict = {}
         dispatcher.connect(self.updateState, 'state')
         self.numConnected = 0
 
--- a/light9/effect/settings.py	Mon May 27 06:20:25 2019 +0000
+++ b/light9/effect/settings.py	Mon May 27 06:20:38 2019 +0000
@@ -10,7 +10,7 @@
 import logging
 log = logging.getLogger('settings')
 from light9.collector.device import resolve
-
+from typing import Sequence, Dict, Union, List
 
 def parseHex(h):
     if h[0] != '#': raise ValueError(h)
@@ -21,9 +21,10 @@
     return [x / 255 for x in parseHex(h)]
 
 
-def toHex(rgbFloat):
-    return '#%02x%02x%02x' % tuple(
-        max(0, min(255, int(v * 255))) for v in rgbFloat)
+def toHex(rgbFloat: Sequence[float]) -> str:
+    assert len(rgbFloat) == 3
+    scaled = (max(0, min(255, int(v * 255))) for v in rgbFloat)
+    return '#%02x%02x%02x' % tuple(scaled) # type: ignore
 
 
 def getVal(graph, subj):
@@ -42,7 +43,7 @@
 
     def __init__(self, graph, settingsList):
         self.graph = graph  # for looking up all possible attrs
-        self._compiled = {}  # dev: { attr: val }; val is number or colorhex
+        self._compiled: Dict[URIRef, Dict[URIRef, Union[float, str]]] = {}  # dev: { attr: val }; val is number or colorhex
         for row in settingsList:
             self._compiled.setdefault(row[0], {})[row[1]] = row[2]
         # self._compiled may not be final yet- see _fromCompiled
@@ -68,7 +69,7 @@
 
     @classmethod
     def fromVector(cls, graph, vector, deviceAttrFilter=None):
-        compiled = {}
+        compiled: Dict[URIRef, Dict[URIRef, Union[float, str]]] = {}
         i = 0
         for (d, a) in cls(graph, [])._vectorKeys(deviceAttrFilter):
             if a == L9['color']:
@@ -186,7 +187,7 @@
         return list(self._compiled.keys())
 
     def toVector(self, deviceAttrFilter=None):
-        out = []
+        out: List[float] = []
         for dev, attr in self._vectorKeys(deviceAttrFilter):
             v = self.getValue(dev, attr)
             if attr == L9['color']:
--- a/light9/effect/simple_outputs.py	Mon May 27 06:20:25 2019 +0000
+++ b/light9/effect/simple_outputs.py	Mon May 27 06:20:38 2019 +0000
@@ -1,7 +1,8 @@
 import traceback
 from light9.namespaces import L9, RDF
 from light9.effect.scale import scale
-
+from typing import Dict, List, Tuple, Any
+from rdflib import URIRef
 
 class SimpleOutputs(object):
 
@@ -9,7 +10,7 @@
         self.graph = graph
 
         # effect : [(dev, attr, value, isScaled)]
-        self.effectOutputs = {}
+        self.effectOutputs: Dict[URIRef, List[Tuple[URIRef, URIRef, Any, bool]]] = {}
 
         self.graph.addHandler(self.updateEffectsFromGraph)
 
--- a/light9/namespaces.py	Mon May 27 06:20:25 2019 +0000
+++ b/light9/namespaces.py	Mon May 27 06:20:38 2019 +0000
@@ -1,4 +1,5 @@
 from rdflib import Namespace, RDF, RDFS  # noqa
+from typing import Dict
 
 
 # Namespace was showing up in profiles
@@ -6,7 +7,7 @@
 
     def __init__(self, base):
         self.ns = Namespace(base)
-        self.cache = {}
+        self.cache: Dict[str, Namespace] = {}
 
     def __getitem__(self, term):
         if term not in self.cache:
--- a/light9/networking.py	Mon May 27 06:20:25 2019 +0000
+++ b/light9/networking.py	Mon May 27 06:20:38 2019 +0000
@@ -1,5 +1,4 @@
 from urllib.parse import urlparse
-from urllib.parse import splitport
 from .showconfig import getGraph, showUri
 from .namespaces import L9
 
@@ -20,15 +19,11 @@
 
     @property
     def port(self):
-        _, netloc, _, _, _, _ = urlparse(self._url())
-        host, port = splitport(netloc)
-        return int(port)
+        return urlparse(self._url()).port
 
     @property
     def host(self):
-        _, netloc, _, _, _, _ = urlparse(self._url())
-        host, port = splitport(netloc)
-        return host
+        return urlparse(self._url()).hostname
 
     @property
     def url(self):
--- a/light9/prof.py	Mon May 27 06:20:25 2019 +0000
+++ b/light9/prof.py	Mon May 27 06:20:38 2019 +0000
@@ -1,4 +1,5 @@
 import sys, traceback, time, logging
+from typing import Any, Dict
 log = logging.getLogger()
 
 
@@ -30,7 +31,7 @@
 
     Switch to 'line' to match lines inside functions. Execution speed
     will be much slower."""
-    seenTraces = {}  # trace contents : count
+    seenTraces: Dict[Any, int] = {}  # trace contents : count
 
     def trace(frame, ev, arg):
         if ev == event:
--- a/light9/showconfig.py	Mon May 27 06:20:25 2019 +0000
+++ b/light9/showconfig.py	Mon May 27 06:20:38 2019 +0000
@@ -2,14 +2,15 @@
 from twisted.python.filepath import FilePath
 from os import path, getenv
 from rdflib import Graph
-from rdflib import URIRef
+from rdflib import URIRef, Literal
 from .namespaces import L9
+from typing import List, cast
 log = logging.getLogger('showconfig')
 
 _config = None  # graph
 
 
-def getGraph():
+def getGraph() -> Graph:
     warnings.warn(
         "code that's using showconfig.getGraph should be "
         "converted to use the sync graph",
@@ -27,26 +28,26 @@
     return _config
 
 
-def root():
+def root() -> bytes:
     r = getenv("LIGHT9_SHOW")
     if r is None:
         raise OSError(
             "LIGHT9_SHOW env variable has not been set to the show root")
-    return r
+    return r.encode('ascii')
 
 
 _showUri = None
 
 
-def showUri():
+def showUri() -> URIRef:
     """Return the show URI associated with $LIGHT9_SHOW."""
     global _showUri
     if _showUri is None:
-        _showUri = URIRef(open(path.join(root(), 'URI')).read().strip())
+        _showUri = URIRef(open(path.join(root(), b'URI')).read().strip())
     return _showUri
 
 
-def songOnDisk(song):
+def songOnDisk(song: URIRef) -> bytes:
     """given a song URI, where's the on-disk file that mpd would read?"""
     graph = getGraph()
     root = graph.value(showUri(), L9['musicRoot'])
@@ -57,20 +58,22 @@
     if not name:
         raise ValueError("Song %r has no :songFilename" % song)
 
-    return path.abspath(path.join(root, name))
+    return path.abspath(path.join(
+        cast(Literal, root).toPython(),
+        cast(Literal, name).toPython()))
 
 
-def songFilenameFromURI(uri):
+def songFilenameFromURI(uri: URIRef) -> bytes:
     """
     'http://light9.bigasterisk.com/show/dance2007/song8' -> 'song8'
 
     everything that uses this should be deprecated for real URIs
     everywhere"""
     assert isinstance(uri, URIRef)
-    return uri.split('/')[-1]
+    return str(uri).split('/')[-1].encode('ascii')
 
 
-def getSongsFromShow(graph, show):
+def getSongsFromShow(graph: Graph, show: URIRef) -> List[URIRef]:
     playList = graph.value(show, L9['playList'])
     if not playList:
         raise ValueError("%r has no l9:playList" % show)
@@ -82,12 +85,12 @@
 
 
 def curvesDir():
-    return path.join(root(), "curves")
+    return path.join(root(), b"curves")
 
 
 def subFile(subname):
-    return path.join(root(), "subs", subname)
+    return path.join(root(), b"subs", subname)
 
 
 def subsDir():
-    return path.join(root(), 'subs')
+    return path.join(root(), b'subs')
--- a/light9/tkdnd.py	Mon May 27 06:20:25 2019 +0000
+++ b/light9/tkdnd.py	Mon May 27 06:20:38 2019 +0000
@@ -1,6 +1,6 @@
 from glob import glob
 from os.path import join, basename
-
+from typing import Dict, Any
 
 class TkdndEvent(object):
     """
@@ -45,7 +45,7 @@
 
     def __init__(self, widget, style):
         self.widget, self.style = widget, style
-        self.oldStyle = {}
+        self.oldStyle: Dict[Any, Any] = {}
 
     def set(self, ev):
         for k, v in list(self.style.items()):
--- a/light9/uihelpers.py	Mon May 27 06:20:25 2019 +0000
+++ b/light9/uihelpers.py	Mon May 27 06:20:38 2019 +0000
@@ -6,6 +6,7 @@
 from tkinter.tix import Button, Toplevel, Tk, IntVar, Entry, DoubleVar
 import tkinter
 from light9.namespaces import L9
+from typing import Dict
 
 log = logging.getLogger("toplevel")
 
@@ -44,7 +45,7 @@
 
     lastSaved = [None]
     setOnce = [False]
-    graphSetTime = [0]
+    graphSetTime = [0.0]
 
     def setPosFromGraphOnce():
         """
@@ -53,7 +54,7 @@
         """
         if setOnce[0]:
             return
-        geo = graph.value(session, L9.windowGeometry)
+        geo = graph.value(session, L9['windowGeometry'])
         log.debug("setPosFromGraphOnce %s", geo)
 
         setOnce[0] = True
@@ -76,7 +77,7 @@
             return
         lastSaved[0] = geo
         log.debug("saving position %s", geo)
-        graph.patchObject(session, session, L9.windowGeometry, Literal(geo))
+        graph.patchObject(session, session, L9['windowGeometry'], Literal(geo))
 
     if graph is not None and session is not None:
         graph.addHandler(setPosFromGraphOnce)
@@ -142,7 +143,7 @@
     low = (80, 80, 180)
     high = (255, 55, 0o50)
     out = [int(l + lev * (h - l)) for h, l in zip(high, low)]
-    col = "#%02X%02X%02X" % tuple(out)
+    col = "#%02X%02X%02X" % tuple(out) # type: ignore
     label.config(bg=col)
 
 
@@ -150,7 +151,7 @@
 def colorfade(low, high, percent):
     '''not foolproof.  make sure 0 < percent < 1'''
     out = [int(l + percent * (h - l)) for h, l in zip(high, low)]
-    col = "#%02X%02X%02X" % tuple(out)
+    col = "#%02X%02X%02X" % tuple(out) # type: ignore
     return col
 
 
@@ -216,8 +217,8 @@
 
     def __init__(self, master=None):
         DoubleVar.__init__(self, master)
-        self.callbacklist = {}  # cbname : mode
-        self.namedtraces = {}  # name : cbname
+        self.callbacklist: Dict[str, str] = {}  # cbname : mode
+        self.namedtraces: Dict[str, str] = {}  # name : cbname
 
     def trace_variable(self, mode, callback):
         """Define a trace callback for the variable.
--- a/light9/vidref/musictime.py	Mon May 27 06:20:25 2019 +0000
+++ b/light9/vidref/musictime.py	Mon May 27 06:20:38 2019 +0000
@@ -2,6 +2,7 @@
 from light9 import networking
 from twisted.internet import reactor
 from cyclone.httpclient import fetch
+from typing import Dict
 log = logging.getLogger()
 
 
@@ -28,7 +29,7 @@
         self.hoverPeriod = .05
         self.onChange = onChange
 
-        self.position = {}
+        self.position: Dict[str, float] = {}
         # driven by our pollCurvecalcTime and also by Gui.incomingTime
         self.lastHoverTime = None  # None means "no recent value"
         self.pollMusicTime()
@@ -125,6 +126,6 @@
         fetch(
             method=b'POST',
             url=networking.musicPlayer.path('time'),
-            body=json.dumps({"t": t}),
+            postdata=json.dumps({"t": t}).encode('utf8'),
             headers={b"content-type": [b"application/json"]},
         )
--- a/light9/web/websocket.js	Mon May 27 06:20:25 2019 +0000
+++ b/light9/web/websocket.js	Mon May 27 06:20:38 2019 +0000
@@ -1,5 +1,6 @@
 /*
-  url is now relative to the window location
+  url is now relative to the window location. Note that nginx may drop
+  the connection after 60sec of inactivity.
 */
 function reconnectingWebSocket(url, onMessage) {
     var pong = 0;
--- a/requirements.txt	Mon May 27 06:20:25 2019 +0000
+++ b/requirements.txt	Mon May 27 06:20:38 2019 +0000
@@ -31,6 +31,7 @@
 ipython==5.3.0
 mypy==0.701
 flake8
+typing_extensions
 
 git+http://github.com/drewp/scales.git@448d59fb491b7631877528e7695a93553bfaaa93#egg=scales
 git+http://github.com/11craft/louie.git@f18bb71010c114eca9c6b88c96453340e3b39454#egg=louie
--- a/tasks.py	Mon May 27 06:20:25 2019 +0000
+++ b/tasks.py	Mon May 27 06:20:38 2019 +0000
@@ -30,18 +30,21 @@
 
 @task
 def mypy(ctx):
+    print('\n\n')
     def run(sources):
         ss = ' '.join(sources)
-        ctx.run(f'MYPYPATH=stubs env/bin/mypy --check-untyped-defs {ss}',
+        ctx.run(f'MYPYPATH=stubs:/my/proj/rdfdb env/bin/mypy --check-untyped-defs {ss}',
                 pty=True, warn=True)
 
     sources = ' '.join(bin_sources + pkg_sources())
     ctx.run(f'env/bin/flake8 --ignore=E115,E123,E124,E126,E225,E231,E261,E262,E265,E301,E302,E303,E305,E306,E401,E402,E501,E701,E731,W291,W293,W391,W504 {sources}', warn=True)
 
     sources = ' '.join(pkg_sources())
-    for src in bin_sources:
-        print(f"mypy {src}")
-        run([src])# + pkg_sources())
+    run(['bin/rdfdb'])
+    run(['bin/keyboardcomposer'])
+    #for src in bin_sources:
+    #    print(f"mypy {src}")
+    #    run([src])# + pkg_sources())
 @task
 def reformat(ctx):
     ctx.run("env/bin/yapf --verbose --parallel --in-place --style google light9/**/*.py `file --no-pad  bin/* | grep 'Python script' | perl -lpe 's/:.*//'`")