From 7956712fc4f0c17e07ed26af42b47ae3c158f737 Mon Sep 17 00:00:00 2001 From: bovlb <31326650+bovlb@users.noreply.github.com> Date: Tue, 15 Oct 2024 21:10:14 -0700 Subject: [PATCH] Bovlb patch 1 (#2931) * Update parser.py Fix SPARQL parsing bug * Add test for bug fix * Check imports * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * style * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- rdflib/plugins/sparql/parser.py | 12 +++++++++--- test/test_sparql/test_translate_algebra.py | 19 ++++++++++++++++++- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/rdflib/plugins/sparql/parser.py b/rdflib/plugins/sparql/parser.py index d2e9f2dee..68e6211ca 100644 --- a/rdflib/plugins/sparql/parser.py +++ b/rdflib/plugins/sparql/parser.py @@ -59,6 +59,7 @@ def expandTriples(terms: ParseResults) -> List[Any]: Expand ; and , syntax for repeat predicates, subjects """ # import pdb; pdb.set_trace() + last_subject, last_predicate = None, None # Used for ; and , try: res: List[Any] = [] if DEBUG: @@ -66,11 +67,11 @@ def expandTriples(terms: ParseResults) -> List[Any]: l_ = len(terms) for i, t in enumerate(terms): if t == ",": - res.extend([res[-3], res[-2]]) + res.extend([last_subject, last_predicate]) elif t == ";": if i + 1 == len(terms) or terms[i + 1] == ";" or terms[i + 1] == ".": continue # this semicolon is spurious - res.append(res[0]) + res.append(last_subject) elif isinstance(t, list): # BlankNodePropertyList # is this bnode the object of previous triples? @@ -78,14 +79,19 @@ def expandTriples(terms: ParseResults) -> List[Any]: res.append(t[0]) # is this a single [] ? if len(t) > 1: - res += t + res += t # Don't update last_subject/last_predicate # is this bnode the subject of more triples? if i + 1 < l_ and terms[i + 1] not in ".,;": + last_subject, last_predicate = t[0], None res.append(t[0]) elif isinstance(t, ParseResults): res += t.asList() elif t != ".": res.append(t) + if (len(res) % 3) == 1: + last_subject = t + elif (len(res) % 3) == 2: + last_predicate = t if DEBUG: print(len(res), t) if DEBUG: diff --git a/test/test_sparql/test_translate_algebra.py b/test/test_sparql/test_translate_algebra.py index 59e747f65..702509ebe 100644 --- a/test/test_sparql/test_translate_algebra.py +++ b/test/test_sparql/test_translate_algebra.py @@ -12,7 +12,7 @@ import rdflib.plugins.sparql.algebra as algebra import rdflib.plugins.sparql.parser as parser -from rdflib import Graph, Literal, URIRef +from rdflib import Graph, Literal, URIRef, Variable from rdflib.plugins.sparql.algebra import translateAlgebra from test.data import TEST_DATA_DIR @@ -329,3 +329,20 @@ def test_sparql_group_concat(): g = Graph() q = dict(g.query(query)) assert q[URIRef("http://example.org/pred")] == Literal("abc") + + +def test_sparql_blank_node_comma(): + """Tests if blank nodes separated by commas are correctly parsed""" + + query = """ + PREFIX : + + SELECT ?s WHERE { + ?s :hasIngredient [:name "chicken"], [:name "butter"] . + } LIMIT 10 + """ + + parse_results = parser.parseQuery(query) + triples = parse_results[1]["where"].part[0].triples[0] + s_count = sum(1 for i in range(0, len(triples), 3) if triples[i] == Variable("s")) + assert s_count == 2, f"Found ?s as subject {s_count} times, expected 2"