# HG changeset patch # User Drew Perttula # Date 2017-05-30 07:36:42 # Node ID 30c79f1dc4f869bd09bbfe287d05734a7a80cf0a # Parent 1db548d395fb632e05bf108bff54afe7f3077b28 fix suggestPrefixes to send suggestions to rdfdb Ignore-this: 637142dcc1de97c9046d75d1396a9446 diff --git a/bin/effecteval b/bin/effecteval --- a/bin/effecteval +++ b/bin/effecteval @@ -72,7 +72,7 @@ class SongEffects(PrettyErrorHandler, cy note, p = yield songNotePatch(self.settings.graph, dropped, song, event, ctx=song, note=note) self.settings.graph.patch(p) - self.settings.graph.suggestPrefixes({'song': URIRef(song + '/')}) + self.settings.graph.suggestPrefixes(song, {'song': URIRef(song + '/')}) self.write(json.dumps({'note': note})) class SongEffectsUpdates(cyclone.websocket.WebSocketHandler): diff --git a/bin/rdfdb b/bin/rdfdb --- a/bin/rdfdb +++ b/bin/rdfdb @@ -180,7 +180,7 @@ class WatchedFiles(object): This object watches directories. Each GraphFile watches its own file. """ - def __init__(self, dirUriMap, patch, getSubgraph, addlPrefixes=None): + def __init__(self, dirUriMap, patch, getSubgraph, addlPrefixes): self.dirUriMap = dirUriMap # {abspath : uri prefix} self.patch, self.getSubgraph = patch, getSubgraph self.addlPrefixes = addlPrefixes @@ -239,10 +239,7 @@ class WatchedFiles(object): return ctx = uriFromFile(self.dirUriMap, inFile) - gf = GraphFile(self.notifier, inFile, ctx, - self.patch, self.getSubgraph, - addlPrefixes=self.addlPrefixes) - self.graphFiles[ctx] = gf + gf = self._addGraphFile(ctx, inFile) log.info("%s do initial read", inFile) gf.reread() @@ -263,10 +260,19 @@ class WatchedFiles(object): outFile = fileForUri(self.dirUriMap, ctx) assert '//' not in outFile, (outFile, self.dirUriMap, ctx) log.info("starting new file %r", outFile) - self.graphFiles[ctx] = GraphFile(self.notifier, outFile, ctx, - self.patch, self.getSubgraph, - addlPrefixes=self.addlPrefixes) + self._addGraphFile(ctx, outFile) + def _addGraphFile(self, ctx, path): + self.addlPrefixes.setdefault(ctx, {}) + self.addlPrefixes.setdefault(None, {}) + gf = GraphFile(self.notifier, path, ctx, + self.patch, self.getSubgraph, + globalPrefixes=self.addlPrefixes[None], + ctxPrefixes=self.addlPrefixes[ctx]) + self.graphFiles[ctx] = gf + return gf + + def dirtyFiles(self, ctxs): """mark dirty the files that we watch in these contexts. @@ -285,13 +291,14 @@ class Db(object): """ the master graph, all the connected clients, all the files we're watching """ - def __init__(self, dirUriMap, addlPrefixes=None): + def __init__(self, dirUriMap, addlPrefixes): self.clients = [] self.graph = ConjunctiveGraph() self.watchedFiles = WatchedFiles(dirUriMap, - self.patch, self.getSubgraph, addlPrefixes) + self.patch, self.getSubgraph, + addlPrefixes) self.summarizeToLog() @@ -403,6 +410,12 @@ class GraphClients(PrettyErrorHandler, c traceback.print_exc() raise +class Prefixes(PrettyErrorHandler, cyclone.web.RequestHandler): + def post(self): + suggestion = json.loads(self.request.body) + addlPrefixes = self.settings.db.watchedFiles.addlPrefixes + addlPrefixes.setdefault(URIRef(suggestion['ctx']), {}).update(suggestion['prefixes']) + _wsClientSerial = 0 class WebsocketClient(cyclone.websocket.WebSocketHandler): @@ -457,6 +470,8 @@ class NoExts(cyclone.web.StaticFileHandl path = path + ".html" cyclone.web.StaticFileHandler.get(self, path, *args, **kw) + + if __name__ == "__main__": logging.basicConfig() log = logging.getLogger() @@ -470,7 +485,15 @@ if __name__ == "__main__": db = Db(dirUriMap={os.environ['LIGHT9_SHOW'].rstrip('/') + '/': showconfig.showUri() + '/'}, - addlPrefixes={'show': URIRef(showconfig.showUri() + '/')}) + addlPrefixes={None: { + '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/', + }}) from twisted.python import log as twlog twlog.startLogging(sys.stdout) @@ -481,6 +504,7 @@ if __name__ == "__main__": (r'/patches', Patches), (r'/graphClients', GraphClients), (r'/syncedGraph', WebsocketClient), + (r'/prefixes', Prefixes), (r'/(.*)', NoExts, {"path" : "light9/rdfdb/web", diff --git a/light9/paint/capture.py b/light9/paint/capture.py --- a/light9/paint/capture.py +++ b/light9/paint/capture.py @@ -15,7 +15,8 @@ def writeCaptureDescription(graph, ctx, (uri, RDF.type, L9['LightSample'], ctx), (uri, L9['imagePath'], URIRef('/'.join([showconfig.showUri(), relOutPath])), ctx), ])) - graph.suggestPrefixes('cap', URIRef(uri.rsplit('/', 1)[0] + '/')) + graph.suggestPrefixes(ctx, {'cap': uri.rsplit('/', 1)[0] + '/', + 'showcap': showconfig.showUri() + '/capture/'}) class CaptureLoader(object): def __init__(self, graph): diff --git a/light9/rdfdb/graphfile.py b/light9/rdfdb/graphfile.py --- a/light9/rdfdb/graphfile.py +++ b/light9/rdfdb/graphfile.py @@ -9,7 +9,7 @@ from light9.rdfdb.rdflibpatch import inC log = logging.getLogger('graphfile') iolog = logging.getLogger('io') -def patchN3SerializerToUseLessWhitespace(): +def patchN3SerializerToUseLessWhitespace(cutColumn=65): # todo: make a n3serializer subclass with whitespace settings from rdflib.plugins.serializers.turtle import TurtleSerializer, OBJECT originalWrite = TurtleSerializer.write @@ -31,7 +31,7 @@ def patchN3SerializerToUseLessWhitespace for predicate in propList[1:]: self.write(';') # can't do proper wrapping since we don't know how much is coming - if self._column > 50: + if self._column > cutColumn: self.write('\n' + self.indent(1)) self.verb(predicate, newline=False) self.objectList(properties[predicate]) @@ -63,29 +63,24 @@ class GraphFile(object): """ one rdf file that we read from, write to, and notice external changes to """ - def __init__(self, notifier, path, uri, patch, getSubgraph, addlPrefixes=None): + def __init__(self, notifier, path, uri, patch, getSubgraph, globalPrefixes, ctxPrefixes): """ uri is the context for the triples in this file. We assume sometimes that we're the only ones with triples in this context. this does not include an initial reread() call + + Prefixes are mutable dicts. The caller may add to them later. """ self.path, self.uri = path, uri self.patch, self.getSubgraph = patch, getSubgraph self.lastWriteTimestamp = 0 # mtime from the last time _we_ wrote - self.namespaces = { - '': '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/', - } - if addlPrefixes: - self.namespaces.update(addlPrefixes) + self.globalPrefixes = globalPrefixes + self.ctxPrefixes = ctxPrefixes + self.readPrefixes = {} if not os.path.exists(path): # can't start notify until file exists @@ -187,7 +182,7 @@ class GraphFile(object): return new.parse(location=self.path, format='n3') - self.namespaces.update(dict(new.namespaces())) + self.readPrefixes = dict(new.namespaces()) except SyntaxError as e: print e traceback.print_exc() @@ -239,7 +234,9 @@ class GraphFile(object): tmpOut = self.path + ".rdfdb-temp" f = open(tmpOut, 'w') t1 = time.time() - for p, n in self.namespaces.items(): + for p, n in (self.globalPrefixes.items() + + self.readPrefixes.items() + + self.ctxPrefixes.items()): self.graphToWrite.bind(p, n) self.graphToWrite.serialize(destination=f, format='n3') serializeTime = time.time() - t1 diff --git a/light9/rdfdb/syncedgraph.py b/light9/rdfdb/syncedgraph.py --- a/light9/rdfdb/syncedgraph.py +++ b/light9/rdfdb/syncedgraph.py @@ -19,6 +19,7 @@ PatchSender - collects and transmits you from rdflib import ConjunctiveGraph import logging, cyclone.httpclient, traceback from twisted.internet import defer +import treq, json log = logging.getLogger('syncedgraph') from light9.rdfdb.rdflibpatch import patchQuads @@ -125,10 +126,13 @@ class SyncedGraph(CurrentStateGraphApi, self._sender.sendPatch(p).addErrback(self.sendFailed) log.debug('patch is done %s', debugKey) - def suggestPrefixes(self, prefixes): - if not hasattr(self, 'addlPrefixes'): - self.addlPrefixes = {} - self.addlPrefixes.update(prefixes) + def suggestPrefixes(self, ctx, prefixes): + """ + when writing files for this ctx, try to use these n3 + prefixes. async, not guaranteed to finish before any + particular file flush + """ + treq.post(self.rdfdbRoot + 'prefixes', json.dumps({'ctx': ctx, 'prefixes': prefixes})) def sendFailed(self, result): """