Changeset - 717774b8a4a6
[Not reviewed]
default
0 1 0
Drew Perttula - 11 years ago 2014-05-28 05:55:58
drewp@bigasterisk.com
syncedgraph gets items() method for fetching an rdf list
Ignore-this: c97d4718ab1cede9c196464053c9ab47
1 file changed with 14 insertions and 0 deletions:
0 comments (0 inline, 0 general)
light9/rdfdb/autodepgraphapi.py
Show inline comments
 
@@ -54,96 +54,110 @@ class AutoDepGraphApi(object):
 
        might care, and then notice what data they depend on now
 
        """
 
        for func in self._watchers.whoCares(p):
 
            # todo: forget the old handlers for this func
 
            self.addHandler(func)
 

	
 
    def _getCurrentFunc(self):
 
        if not self.currentFuncs:
 
            # this may become a warning later
 
            raise ValueError("asked for graph data outside of a handler")
 

	
 
        # we add the watcher to the deepest function, since that
 
        # should be the cheapest way to update when this part of the
 
        # data changes
 
        return self.currentFuncs[-1]
 

	
 
    # these just call through to triples() so it might be possible to
 
    # watch just that one.
 

	
 
    # if you get a bnode in your response, maybe the answer to
 
    # dependency tracking is to say that you depended on the triple
 
    # that got you that bnode, since it is likely to change to another
 
    # bnode later. This won't work if the receiver stores bnodes
 
    # between calls, but probably most of them don't do that (they
 
    # work from a starting uri)
 

	
 
    def value(self, subject=None, predicate=RDF.value, object=None,
 
              default=None, any=True):
 
        if object is not None:
 
            raise NotImplementedError()
 
        func = self._getCurrentFunc()
 
        self._watchers.addSubjPredWatcher(func, subject, predicate)
 
        return self._graph.value(subject, predicate, object=object,
 
                                 default=default, any=any)
 

	
 
    def objects(self, subject=None, predicate=None):
 
        func = self._getCurrentFunc()
 
        self._watchers.addSubjPredWatcher(func, subject, predicate)
 
        return self._graph.objects(subject, predicate)
 

	
 
    def label(self, uri):
 
        return self.value(uri, RDFS.label)
 

	
 
    def subjects(self, predicate=None, object=None):
 
        func = self._getCurrentFunc()
 
        self._watchers.addPredObjWatcher(func, predicate, object)
 
        return self._graph.subjects(predicate, object)
 

	
 
    def items(self, listUri):
 
        """generator. Having a chain of watchers on the results is not
 
        well-tested yet"""
 
        chain = set([listUri])
 
        while listUri:
 
            item = self.value(listUri, RDF.first)
 
            if item:
 
                yield item
 
            listUri = self.value(listUri, RDF.rest)
 
            if listUri in chain:
 
                raise ValueError("List contains a recursive rdf:rest reference")
 
            chain.add(listUri)
 

	
 
        
 
    def contains(self, triple):
 
        func = self._getCurrentFunc()
 
        self._watchers.addTripleWatcher(func, triple)
 
        return triple in self._graph
 
        
 
    def contextsForStatement(self, triple):
 
        """currently this needs to be in an addHandler section, but it
 
        sets no watchers so it won't actually update if the statement
 
        was added or dropped from contexts"""
 
        func = self._getCurrentFunc()
 
        return contextsForStatementNoWildcards(self._graph, triple)
 

	
 
    # i find myself wanting 'patch' (aka enter/leave) versions of these calls that tell
 
    # you only what results have just appeared or disappeared. I think
 
    # I'm going to be repeating that logic a lot. Maybe just for the
 
    # subjects(RDF.type, t) call
 

	
 

	
 
class _GraphWatchers(object):
 
    """
 
    store the current handlers that care about graph changes
 
    """
 
    def __init__(self):
 
        self._handlersSp = {} # (s,p): set(handlers)
 
        self._handlersPo = {} # (p,o): set(handlers)
 
        self._handlersSpo = {} # (s,p,o): set(handlers)
 

	
 
    def addSubjPredWatcher(self, func, s, p):
 
        if func is None:
 
            return
 
        key = s, p
 
        try:
 
            self._handlersSp.setdefault(key, set()).add(func)
 
        except Exception:
 
            log.error("with key %r and func %r" % (key, func))
 
            raise
 

	
 
    def addPredObjWatcher(self, func, p, o):
 
        self._handlersPo.setdefault((p, o), set()).add(func)
 

	
 
    def addTripleWatcher(self, func, triple):
 
        self._handlersSpo.setdefault(triple, set()).add(func)
 

	
 
    def whoCares(self, patch):
 
        """what handler functions would care about the changes in this patch?
 

	
 
        this removes the handlers that it gives you
 
        """
0 comments (0 inline, 0 general)