summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGunnar Aastrand Grimnes <gromgull@users.noreply.github.com>2017-01-19 15:42:21 +0100
committerGitHub <noreply@github.com>2017-01-19 15:42:21 +0100
commit89c49f673e87bbf63d024ddd39b5e04cda460a6a (patch)
tree4834a51bfdfff04307e5e9921ca649140d3b5d2c
parent9e4bc5fee3b4bedf641b54a8fe461b2b228f768a (diff)
parent4e96763f67de0d03381c560da2fc1a39ac9c44ae (diff)
downloadrdflib-89c49f673e87bbf63d024ddd39b5e04cda460a6a.tar.gz
Merge pull request #691 from RDFLib/fix_609
Added __iadd__ method to collections, much faster for adding multiple…
-rw-r--r--rdflib/collection.py62
-rw-r--r--rdflib/graph.py23
-rw-r--r--test/test_issue223.py4
3 files changed, 64 insertions, 25 deletions
diff --git a/rdflib/collection.py b/rdflib/collection.py
index 4fc3d1c8..babd4724 100644
--- a/rdflib/collection.py
+++ b/rdflib/collection.py
@@ -1,7 +1,6 @@
from rdflib.namespace import RDF
from rdflib.term import BNode
from rdflib.term import Literal
-from rdflib.graph import Graph
from rdflib.py3compat import format_doctest_out
__all__ = ['Collection']
@@ -43,8 +42,7 @@ class Collection(object):
def __init__(self, graph, uri, seq=[]):
self.graph = graph
self.uri = uri or BNode()
- for item in seq:
- self.append(item)
+ self += seq
def n3(self):
"""
@@ -184,6 +182,16 @@ class Collection(object):
"""Iterator over items in Collections"""
return self.graph.items(self.uri)
+ def _end(self):
+ # find end of list
+ container = self.uri
+ while True:
+ rest = self.graph.value(container, RDF.rest)
+ if rest == None or rest == RDF.nil:
+ return container
+ else:
+ container = rest
+
def append(self, item):
"""
>>> from rdflib.graph import Graph
@@ -192,29 +200,36 @@ class Collection(object):
>>> c = Collection(g,listName,[Literal(1),Literal(2)])
>>> links = [
... list(g.subjects(object=i, predicate=RDF.first))[0] for i in c]
- >>> len([i for i in links if (i,RDF.rest, RDF.nil) in g])
+ >>> len([i for i in links if (i, RDF.rest, RDF.nil) in g])
1
"""
- container = self.uri
- graph = self.graph
- # iterate to the end of the linked list
- rest = graph.value(container, RDF.rest)
- while rest:
- if rest == RDF.nil:
- # the end, append to the end of the linked list
- node = BNode()
- graph.set((container, RDF.rest, node))
- container = node
- break
- else:
- # move down one link
- if container != self.uri:
- rest = graph.value(rest, RDF.rest)
- if not rest == RDF.nil:
- container = rest
- graph.add((container, RDF.first, item))
- graph.add((container, RDF.rest, RDF.nil))
+
+ end = self._end()
+ if (end, RDF.first, None) in self.graph:
+ # append new node to the end of the linked list
+ node = BNode()
+ self.graph.set((end, RDF.rest, node))
+ end = node
+
+ self.graph.add((end, RDF.first, item))
+ self.graph.add((end, RDF.rest, RDF.nil))
+
+ def __iadd__(self, other):
+
+ end = self._end()
+ self.graph.remove((end, RDF.rest, None))
+
+ for item in other:
+ if (end, RDF.first, None) in self.graph:
+ nxt = BNode()
+ self.graph.add((end, RDF.rest, nxt))
+ end = nxt
+
+ self.graph.add((end, RDF.first, item))
+
+
+ self.graph.add((end, RDF.rest, RDF.nil))
def clear(self):
container = self.uri
@@ -233,6 +248,7 @@ def test():
if __name__ == "__main__":
test()
+ from rdflib import Graph
g = Graph()
c = Collection(g, BNode())
diff --git a/rdflib/graph.py b/rdflib/graph.py
index 012f63e6..bcfabd87 100644
--- a/rdflib/graph.py
+++ b/rdflib/graph.py
@@ -266,6 +266,7 @@ from rdflib.parser import Parser
from rdflib.parser import create_input_source
from rdflib.namespace import NamespaceManager
from rdflib.resource import Resource
+from rdflib.collection import Collection
from rdflib import py3compat
b = py3compat.b
@@ -1177,6 +1178,28 @@ class Graph(Node):
res.update(self.subjects())
return res
+ def collection(self, identifier):
+ """Create a new ``Collection`` instance.
+
+ Parameters:
+
+ - ``identifier``: a URIRef or BNode instance.
+
+ Example::
+
+ >>> graph = Graph()
+ >>> uri = URIRef("http://example.org/resource")
+ >>> collection = graph.collection(uri)
+ >>> assert isinstance(collection, Collection)
+ >>> assert collection.uri is uri
+ >>> assert collection.graph is graph
+ >>> collection += [ Literal(1), Literal(2) ]
+ """
+
+ return Collection(self, identifier)
+
+
+
def resource(self, identifier):
"""Create a new ``Resource`` instance.
diff --git a/test/test_issue223.py b/test/test_issue223.py
index 5b1761ea..c12f4fa1 100644
--- a/test/test_issue223.py
+++ b/test/test_issue223.py
@@ -11,9 +11,9 @@ def test_collection_with_duplicates():
g = Graph().parse(data=ttl, format="turtle")
for _,_,o in g.triples((URIRef("http://example.org/s"), URIRef("http://example.org/p"), None)):
break
- c = Collection(g, o)
+ c = g.collection(o)
assert list(c) == list(URIRef("http://example.org/" + x) for x in ["a", "b", "a"])
assert len(c) == 3
-
+
if __name__ == '__main__':
test_collection_with_duplicates()