diff options
-rw-r--r-- | rdflib/graph.py | 33 | ||||
-rw-r--r-- | test/test_dataset.py | 31 |
2 files changed, 59 insertions, 5 deletions
diff --git a/rdflib/graph.py b/rdflib/graph.py index a689b35a..b25765ac 100644 --- a/rdflib/graph.py +++ b/rdflib/graph.py @@ -1,4 +1,4 @@ -from typing import Optional, Union, Type, cast, overload +from typing import Optional, Union, Type, cast, overload, Generator, Tuple import logging from warnings import warn import random @@ -29,6 +29,9 @@ assert Namespace # avoid warning logger = logging.getLogger(__name__) +# Type aliases to make unpacking what's going on a little more human friendly +ContextNode = Union[BNode, URIRef] +DatasetQuad = Tuple[Node, URIRef, Node, Optional[ContextNode]] __doc__ = """\ @@ -1759,8 +1762,8 @@ class Dataset(ConjunctiveGraph): rdflib.term.URIRef("http://example.org/y"), rdflib.term.Literal("bar")) >>> - >>> # querying quads return quads; the fourth argument can be unrestricted - >>> # or restricted to a graph + >>> # querying quads() return quads; the fourth argument can be unrestricted + >>> # (None) or restricted to a graph >>> for q in ds.quads((None, None, None, None)): # doctest: +SKIP ... print(q) # doctest: +NORMALIZE_WHITESPACE (rdflib.term.URIRef("http://example.org/a"), @@ -1776,7 +1779,24 @@ class Dataset(ConjunctiveGraph): rdflib.term.Literal("foo-bar"), rdflib.term.URIRef("http://www.example.com/gr")) >>> - >>> for q in ds.quads((None,None,None,g)): # doctest: +SKIP + >>> # unrestricted looping is equivalent to iterating over the entire Dataset + >>> for q in ds: # doctest: +SKIP + ... print(q) # doctest: +NORMALIZE_WHITESPACE + (rdflib.term.URIRef("http://example.org/a"), + rdflib.term.URIRef("http://www.example.org/b"), + rdflib.term.Literal("foo"), + None) + (rdflib.term.URIRef("http://example.org/x"), + rdflib.term.URIRef("http://example.org/y"), + rdflib.term.Literal("bar"), + rdflib.term.URIRef("http://www.example.com/gr")) + (rdflib.term.URIRef("http://example.org/x"), + rdflib.term.URIRef("http://example.org/z"), + rdflib.term.Literal("foo-bar"), + rdflib.term.URIRef("http://www.example.com/gr")) + >>> + >>> # resticting iteration to a graph: + >>> for q in ds.quads((None, None, None, g)): # doctest: +SKIP ... print(q) # doctest: +NORMALIZE_WHITESPACE (rdflib.term.URIRef("http://example.org/x"), rdflib.term.URIRef("http://example.org/y"), @@ -1896,6 +1916,11 @@ class Dataset(ConjunctiveGraph): else: yield s, p, o, c.identifier + def __iter__(self) -> Generator[DatasetQuad, None, None]: + """Iterates over all quads in the store""" + return self.quads((None, None, None, None)) + + class QuotedGraph(Graph): """ diff --git a/test/test_dataset.py b/test/test_dataset.py index 734b58cd..4860b9c3 100644 --- a/test/test_dataset.py +++ b/test/test_dataset.py @@ -167,7 +167,36 @@ class DatasetTestCase(unittest.TestCase): self.assertEqual(list(self.graph.objects(self.tarek, None)), []) self.assertEqual(list(g1.objects(self.tarek, None)), [self.pizza]) - + def testIter(self): + """PR 1382: adds __iter__ to Dataset""" + d = Dataset() + uri_a = URIRef("https://example.com/a") + uri_b = URIRef("https://example.com/b") + uri_c = URIRef("https://example.com/c") + uri_d = URIRef("https://example.com/d") + + d.add_graph(URIRef("https://example.com/g1")) + d.add((uri_a, uri_b, uri_c, URIRef("https://example.com/g1"))) + d.add((uri_a, uri_b, uri_c, URIRef( + "https://example.com/g1"))) # pointless addition: duplicates above + + d.add_graph(URIRef("https://example.com/g2")) + d.add((uri_a, uri_b, uri_c, URIRef("https://example.com/g2"))) + d.add((uri_a, uri_b, uri_d, URIRef("https://example.com/g1"))) # new, uri_d + + # traditional iterator + i_trad = 0 + for t in d.quads((None, None, None)): + i_trad += 1 + + # new Dataset.__iter__ iterator + i_new = 0 + for t in d: + i_new += 1 + + self.assertEqual(i_new, i_trad) # both should be 3 + + # dynamically create classes for each registered Store pluginname = None |