annotate service/store/store.py @ 653:281be4651a2f

graph path now has 'store' in it Ignore-this: f20acfa66fa56e5b4e076e76cad140f6
author drewp@bigasterisk.com
date Wed, 25 Sep 2019 17:29:47 -0700
parents 92cb3245fdd1
children a93fbf0d0daa
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
411
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
1 """
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
2 persistent store of rdf statements, meant for stmts from users.
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
3
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
4 API is not typical rdf: putting statments replaces existing (s,o)
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
5 matches so there can be only one object at a time. Putting the special
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
6 object :unset clears the statement.
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
7 """
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
8
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
9 import sys, logging
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
10 from docopt import docopt
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
11 from patchablegraph import PatchableGraph, CycloneGraphHandler, CycloneGraphEventsHandler
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
12 from rdfdb.patch import Patch
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
13 from rdflib import Namespace, URIRef, Literal, Graph
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
14 from rdflib.parser import StringInputSource
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
15 from twisted.internet import reactor
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
16 from twisted.python.filepath import FilePath
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
17 import cyclone.web
652
92cb3245fdd1 index page is a data browser. support for -v
drewp@bigasterisk.com
parents: 458
diff changeset
18 from standardservice.logsetup import log, verboseLogging
411
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
19
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
20 ROOM = Namespace('http://projects.bigasterisk.com/room/')
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
21
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
22 CTX = ROOM['stored']
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
23
458
4c68b604c7ec change port, put to /values, build updates
drewp@bigasterisk.com
parents: 411
diff changeset
24 class ValuesResource(cyclone.web.RequestHandler):
411
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
25 def put(self):
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
26 arg = self.request.arguments
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
27 if arg.get('s') and arg.get('p'):
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
28 self._onQueryStringStatement(arg['s'][-1], arg['p'][-1], self.request.body)
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
29 else:
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
30 self._onGraphBodyStatements(self.request.body, self.request.headers)
458
4c68b604c7ec change port, put to /values, build updates
drewp@bigasterisk.com
parents: 411
diff changeset
31 post = put
411
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
32 def _onQueryStringStatement(self, s, p, body):
458
4c68b604c7ec change port, put to /values, build updates
drewp@bigasterisk.com
parents: 411
diff changeset
33 subj = URIRef(s)
4c68b604c7ec change port, put to /values, build updates
drewp@bigasterisk.com
parents: 411
diff changeset
34 pred = URIRef(p)
411
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
35 turtleLiteral = self.request.body
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
36 try:
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
37 obj = Literal(float(turtleLiteral))
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
38 except ValueError:
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
39 obj = Literal(turtleLiteral)
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
40 self._onStatements([(subj, pred, obj)])
652
92cb3245fdd1 index page is a data browser. support for -v
drewp@bigasterisk.com
parents: 458
diff changeset
41
411
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
42 def _onGraphBodyStatements(self, body, headers):
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
43 # maybe quads only so we can track who made the input and from what interface?
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
44 # Or your input of triples gets wrapped in a new quad in here?
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
45 g = Graph()
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
46 g.parse(StringInputSource(body), format='nt')
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
47 if not g:
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
48 raise ValueError("expected graph body")
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
49 self._onStatements(list(g.triples((None, None, None))))
652
92cb3245fdd1 index page is a data browser. support for -v
drewp@bigasterisk.com
parents: 458
diff changeset
50
411
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
51 def _onStatements(self, stmts):
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
52 g = self.settings.masterGraph
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
53 for s, p, o in stmts:
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
54 patch = g.getObjectPatch(CTX, s, p, o)
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
55 if o == ROOM['unset']:
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
56 patch = Patch(delQuads=patch.delQuads)
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
57 g.patch(patch)
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
58 nquads = g.serialize(None, format='nquads')
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
59 self.settings.dbFile.setContent(nquads)
652
92cb3245fdd1 index page is a data browser. support for -v
drewp@bigasterisk.com
parents: 458
diff changeset
60
411
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
61 if __name__ == '__main__':
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
62 arg = docopt("""
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
63 Usage: store.py [options]
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
64
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
65 -v Verbose
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
66 """)
652
92cb3245fdd1 index page is a data browser. support for -v
drewp@bigasterisk.com
parents: 458
diff changeset
67 verboseLogging(arg['-v'])
411
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
68
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
69 masterGraph = PatchableGraph()
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
70 dbFile = FilePath('/opt/homeauto_store/db.nquads')
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
71 if dbFile.exists():
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
72 masterGraph._graph.parse(dbFile.open(), format='nquads')
652
92cb3245fdd1 index page is a data browser. support for -v
drewp@bigasterisk.com
parents: 458
diff changeset
73
458
4c68b604c7ec change port, put to /values, build updates
drewp@bigasterisk.com
parents: 411
diff changeset
74 port = 10015
411
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
75 reactor.listenTCP(port, cyclone.web.Application([
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
76 (r"/()", cyclone.web.StaticFileHandler,
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
77 {"path": ".", "default_filename": "index.html"}),
653
281be4651a2f graph path now has 'store' in it
drewp@bigasterisk.com
parents: 652
diff changeset
78 (r"/store", CycloneGraphHandler, {'masterGraph': masterGraph}),
281be4651a2f graph path now has 'store' in it
drewp@bigasterisk.com
parents: 652
diff changeset
79 (r"/store/events", CycloneGraphEventsHandler,
411
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
80 {'masterGraph': masterGraph}),
458
4c68b604c7ec change port, put to /values, build updates
drewp@bigasterisk.com
parents: 411
diff changeset
81 (r'/values', ValuesResource),
411
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
82 ], masterGraph=masterGraph, dbFile=dbFile, debug=arg['-v']),
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
83 interface='::')
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
84 log.warn('serving on %s', port)
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
85
9fbd2d0193bf new 'store' service for user inputs
drewp@bigasterisk.com
parents:
diff changeset
86 reactor.run()