Changeset - c1face79c0e1
[Not reviewed]
default
0 1 1
Drew Perttula - 11 years ago 2014-05-29 06:46:18
drewp@bigasterisk.com
fix rdfdb's filename<->uri mapping system
Ignore-this: 2236b295035273370138943857894699
2 files changed with 45 insertions and 37 deletions:
0 comments (0 inline, 0 general)
bin/rdfdb
Show inline comments
 
@@ -116,13 +116,13 @@ import cyclone.web, cyclone.httpclient, 
 
sys.path.append(".")
 
from light9 import networking, showconfig, prof
 
from rdflib import ConjunctiveGraph, URIRef, Graph
 
from light9.rdfdb.graphfile import GraphFile
 
from light9.rdfdb.patch import Patch, ALLSTMTS
 
from light9.rdfdb.rdflibpatch import patchQuads
 

	
 
from light9.rdfdb.file_vs_uri import correctToTopdirPrefix, fileForUri, uriFromFile
 
from light9.rdfdb.patchsender import sendPatch
 
from light9.rdfdb.patchreceiver import makePatchEndpointPutMethod
 

	
 
from twisted.internet.inotify import INotify
 
from run_local import log
 
log.setLevel(logging.DEBUG)
 
@@ -162,33 +162,27 @@ class Client(object):
 
class WatchedFiles(object):
 
    """
 
    find files, notice new files.
 

	
 
    This object watches directories. Each GraphFile watches its own file.
 
    """
 
    def __init__(self, topDirsToWatch, patch, getSubgraph):
 
        self.topDirsToWatch = topDirsToWatch
 
    def __init__(self, dirUriMap, patch, getSubgraph):
 
        self.dirUriMap = dirUriMap # {abspath : uri prefix}
 
        self.patch, self.getSubgraph = patch, getSubgraph
 
        
 
        # files from cwd become uris starting with this. *should* be
 
        # building uris from the show uri in $LIGHT9_SHOW/URI
 
        # instead. Who wants to keep their data in the same dir tree
 
        # as the source code?!
 
        self.topUri = URIRef("http://light9.bigasterisk.com/")
 

	
 
        self.graphFiles = {} # context uri : GraphFile
 
        
 
        self.notifier = INotify()
 
        self.notifier.startReading()
 
        
 
        self.findAndLoadFiles()
 

	
 
    def findAndLoadFiles(self):
 
        self.initialLoad = True
 
        try:
 
            for topdir in self.topDirsToWatch:
 
            for topdir in self.dirUriMap:
 
                for dirpath, dirnames, filenames in os.walk(topdir):
 
                    for base in filenames:
 
                        self.watchFile(os.path.join(dirpath, base))
 
                    self.notifier.watch(FilePath(dirpath), autoAdd=True,
 
                                        callbacks=[self.dirChange])
 
        finally:
 
@@ -206,21 +200,14 @@ class WatchedFiles(object):
 
        inFile needs to be a relative path, not an absolute (e.g. in a
 
        FilePath) because we use its exact relative form in the
 
        context URI
 
        """
 
        if not os.path.isfile(inFile):
 
            return
 
        if not any(inFile.startswith(prefix) for prefix in self.topDirsToWatch):
 
            for prefix in self.topDirsToWatch:
 
                prefixAbs = os.path.abspath(prefix)
 
                if inFile.startswith(prefixAbs):
 
                    inFile = prefix + inFile[len(prefixAbs):]
 
                    break
 
            else:
 
                raise ValueError("can't correct %s to start with one of %s" %
 
                                 (inFile, self.topDirsToWatch))
 

	
 
        inFile = correctToTopdirPrefix(self.dirUriMap, inFile)
 
        if os.path.splitext(inFile)[1] not in ['.n3']:
 
            return
 

	
 
        # an n3 file with rules makes it all the way past this reading
 
        # and the serialization. Then, on the receiving side, a
 
        # SyncedGraph calls graphFromNQuad on the incoming data and
 
@@ -232,13 +219,13 @@ class WatchedFiles(object):
 
        # for legacy versions, compile all the config stuff you want
 
        # read into one file called config.n3. New versions won't read
 
        # it.
 
        if inFile.endswith("config.n3"):
 
            return
 
            
 
        ctx = self.uriFromFile(inFile)
 
        ctx = uriFromFile(self.dirUriMap, inFile)
 
        gf = GraphFile(self.notifier, inFile, ctx,
 
                       self.patch, self.getSubgraph)
 
        self.graphFiles[ctx] = gf
 
        log.info("%s do initial read", inFile)
 
        gf.reread()
 

	
 
@@ -253,13 +240,13 @@ class WatchedFiles(object):
 
        the triples from a new file. Calling this before patching the
 
        graph is still a reasonable thing to do, though.
 
        """
 
        g = self.getSubgraph(ctx)
 

	
 
        if ctx not in self.graphFiles:
 
            outFile = self.fileForUri(ctx)
 
            outFile = fileForUri(self.dirUriMap, ctx)
 
            log.info("starting new file %r", outFile)
 
            self.graphFiles[ctx] = GraphFile(self.notifier, outFile, ctx,
 
                                             self.patch, self.getSubgraph)
 

	
 
    def dirtyFiles(self, ctxs):
 
        """mark dirty the files that we watch in these contexts.
 
@@ -271,36 +258,23 @@ class WatchedFiles(object):
 
        if it's a ctx with no file, error
 
        """
 
        for ctx in ctxs:
 
            g = self.getSubgraph(ctx)
 
            self.graphFiles[ctx].dirty(g)
 

	
 
    def uriFromFile(self, filename):
 
        assert filename.endswith('.n3'), filename
 
        if not any(filename.startswith(t) for t in self.topDirsToWatch):
 
            raise ValueError("filename %s doesn't start with any of %s" %
 
                             (filename, self.topDirsToWatch))
 
        return URIRef(self.topUri + filename[:-len('.n3')])
 

	
 
    def fileForUri(self, ctx):
 
        assert isinstance(ctx, URIRef), ctx
 
        if not ctx.startswith(self.topUri):
 
            raise ValueError("don't know what filename to use for %s" % ctx)
 
        return ctx[len(self.topUri):] + ".n3"
 

	
 
        
 
class Db(object):
 
    """
 
    the master graph, all the connected clients, all the files we're watching
 
    """
 
    def __init__(self, topDirsToWatch):
 
    def __init__(self, dirUriMap):
 
      
 
        self.clients = []
 
        self.graph = ConjunctiveGraph()
 

	
 
        self.watchedFiles = WatchedFiles(topDirsToWatch,
 
        self.watchedFiles = WatchedFiles(dirUriMap,
 
                                         self.patch, self.getSubgraph)
 
        
 
        self.summarizeToLog()
 

	
 
    def patch(self, p, dueToFileChange=False):
 
        """
 
@@ -441,13 +415,14 @@ if __name__ == "__main__":
 
    parser.add_option("-v", "--verbose", action="store_true",
 
                      help="logging.DEBUG")
 
    (options, args) = parser.parse_args()
 

	
 
    log.setLevel(logging.DEBUG if options.verbose else logging.INFO)
 

	
 
    db = Db(topDirsToWatch=[os.environ['LIGHT9_SHOW']])
 
    db = Db(dirUriMap={os.environ['LIGHT9_SHOW'].rstrip('/') + '/':
 
                       URIRef('http://light9.bigasterisk.com/show/dance2014/')})
 

	
 
    from twisted.python import log as twlog
 
    twlog.startLogging(sys.stdout)
 

	
 
    port = 8051
 
    reactor.listenTCP(port, cyclone.web.Application(handlers=[
light9/rdfdb/file_vs_uri.py
Show inline comments
 
new file 100644
 
"""
 
note that if there are ambiguities in dirUriMap, you'll get
 
undefined results that depend on python's items() order.
 
"""
 
import os
 
from rdflib import URIRef
 

	
 
def uriFromFile(dirUriMap, filename):
 
    assert filename.endswith('.n3'), filename
 
    for d, prefix in dirUriMap.items():
 
        if filename.startswith(d):
 
            return URIRef(prefix + filename[len(d):-len('.n3')])
 
    raise ValueError("filename %s doesn't start with any of %s" %
 
                     (filename, dirUriMap.keys()))
 

	
 
def fileForUri(dirUriMap, ctx):
 
    assert isinstance(ctx, URIRef), ctx
 
    for d, prefix in dirUriMap.items():
 
        if ctx.startswith(prefix):
 
            return d + ctx[len(prefix):] + '.n3'
 
    raise ValueError("don't know what filename to use for %s" % ctx)
 

	
 
def correctToTopdirPrefix(dirUriMap, inFile):
 
    if not any(inFile.startswith(prefix) for prefix in dirUriMap):
 
        for prefix in dirUriMap:
 
            prefixAbs = os.path.abspath(prefix)
 
            if inFile.startswith(prefixAbs):
 
                inFile = prefix + inFile[len(prefixAbs):]
 
                break
 
        else:
 
            raise ValueError("can't correct %s to start with one of %s" %
 
                             (inFile, dirUriMap.keys()))
 
    return inFile
0 comments (0 inline, 0 general)