Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix issue 1808 #1821

Merged
merged 13 commits into from
Apr 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions rdflib/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
from urllib.request import url2pathname
from warnings import warn

import rdflib.term
import rdflib.util # avoid circular dependency
from rdflib import exceptions, namespace, plugin, query
from rdflib.collection import Collection
Expand All @@ -34,7 +33,7 @@
from rdflib.resource import Resource
from rdflib.serializer import Serializer
from rdflib.store import Store
from rdflib.term import BNode, Genid, IdentifiedNode, Literal, Node, URIRef
from rdflib.term import BNode, Genid, IdentifiedNode, Literal, Node, RDFLibGenid, URIRef

assert Literal # avoid warning
assert Namespace # avoid warning
Expand Down Expand Up @@ -1510,10 +1509,17 @@ def do_de_skolemize(uriref, t):

def do_de_skolemize2(t):
(s, p, o) = t
if isinstance(s, Genid):
s = s.de_skolemize()
if isinstance(o, Genid):
o = o.de_skolemize()

if RDFLibGenid._is_rdflib_skolem(s):
s = RDFLibGenid(s).de_skolemize()
elif Genid._is_external_skolem(s):
s = Genid(s).de_skolemize()

if RDFLibGenid._is_rdflib_skolem(o):
o = RDFLibGenid(o).de_skolemize()
elif Genid._is_external_skolem(o):
o = Genid(o).de_skolemize()

return s, p, o

retval = Graph() if new_graph is None else new_graph
Expand Down
2 changes: 1 addition & 1 deletion rdflib/term.py
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,7 @@ def skolemize(
if basepath is None:
basepath = rdflib_skolem_genid
skolem = "%s%s" % (basepath, str(self))
return RDFLibGenid(urljoin(authority, skolem))
return URIRef(urljoin(authority, skolem))


class Literal(Identifier):
Expand Down
93 changes: 93 additions & 0 deletions test/test_graph/test_skolemization.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import logging
import re
from test.testutils import GraphHelper
from typing import Pattern, Union

import pytest

from rdflib import Graph
from rdflib.namespace import Namespace
from rdflib.term import BNode, Literal, URIRef

EG = Namespace("http://example.com/")

base_triples = {
(EG.subject, EG.predicate, EG.object0),
(EG.subject, EG.predicate, EG.object1),
}


@pytest.mark.parametrize(
["node", "expected_uri"],
[
(URIRef("http://example.com"), None),
(Literal("some string in here ..."), None),
(BNode("GMeng4V7"), "http://rdlib.net/.well-known/genid/rdflib/GMeng4V7"),
(
BNode(),
re.compile("^" + re.escape("http://rdlib.net/.well-known/genid/rdflib/")),
),
],
)
def test_skolemization(
node: Union[BNode, URIRef, Literal], expected_uri: Union[Pattern[str], str, None]
) -> None:
g = Graph()
for triple in base_triples:
g.add(triple)
g.add((EG.scheck, EG.pcheck, node))
assert len(g) == 3
dsg = g.skolemize()
if expected_uri is None:
GraphHelper.assert_sets_equals(g, dsg)
else:
assert len(dsg) == len(g)
iset = GraphHelper.triple_or_quad_set(dsg)
logging.debug("iset = %s", iset)
assert iset.issuperset(base_triples)
check_triples = list(dsg.triples((EG.scheck, EG.pcheck, None)))
assert len(check_triples) == 1
sbnode = check_triples[0][2]
logging.debug("sbnode = %s, sbnode_value = %s", sbnode, f"{sbnode}")
assert isinstance(sbnode, URIRef)
if isinstance(expected_uri, str):
assert expected_uri == f"{sbnode}"
else:
assert expected_uri.match(f"{sbnode}") is not None


@pytest.mark.parametrize(
["iri", "expected_bnode_value"],
[
("http://example.com", None),
("http://example.com/not/.well-known/genid/1", None),
("http://rdlib.net/not/.well-known/genid/1", None),
("http://example.com/.well-known/genid/1", re.compile("^N")),
("http://rdlib.net/.well-known/genid/rdflib/GMeng4V7", "GMeng4V7"),
],
)
def test_deskolemization(
iri: str, expected_bnode_value: Union[str, None, Pattern[str]]
) -> None:
g = Graph()
for triple in base_triples:
g.add(triple)
g.add((EG.scheck, EG.pcheck, URIRef(iri)))
assert len(g) == 3
dsg = g.de_skolemize()
if expected_bnode_value is None:
GraphHelper.assert_sets_equals(g, dsg)
else:
assert len(dsg) == len(g)
iset = GraphHelper.triple_or_quad_set(dsg)
logging.debug("iset = %s", iset)
assert iset.issuperset(base_triples)
check_triples = list(dsg.triples((EG.scheck, EG.pcheck, None)))
assert len(check_triples) == 1
bnode = check_triples[0][2]
logging.debug("bnode = %s, bnode_value = %s", bnode, f"{bnode}")
assert isinstance(bnode, BNode)
if isinstance(expected_bnode_value, str):
assert expected_bnode_value == f"{bnode}"
else:
assert expected_bnode_value.match(f"{bnode}") is not None
5 changes: 2 additions & 3 deletions test/test_issues/test_issue1404.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from rdflib import FOAF, Graph, URIRef
from rdflib.compare import isomorphic
from rdflib.term import RDFLibGenid


def test_skolem_de_skolem_roundtrip():
Expand Down Expand Up @@ -30,9 +29,9 @@ def test_skolem_de_skolem_roundtrip():

skolemized_graph = graph.skolemize()

# Check the BNode is now an RDFLibGenid after skolemization.
# Check the BNode is now a URIRef after skolemization.
skolem_bnode = skolemized_graph.value(**query)
assert type(skolem_bnode) == RDFLibGenid
assert type(skolem_bnode) == URIRef

# Check that the original bnode id exists somewhere in the uri.
assert bnode_id in skolem_bnode
Expand Down
44 changes: 44 additions & 0 deletions test/test_issues/test_issue1808.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from rdflib import Graph
from rdflib.term import BNode, URIRef, rdflib_skolem_genid
aucampia marked this conversation as resolved.
Show resolved Hide resolved


def test():
"""Test skolemised URI query retrieves expected results.

Issue: https://github.com/RDFLib/rdflib/issues/1808
"""

g = Graph()
g.parse(data='[] <urn:prop> "val" .', format="turtle")
for s, p, o in g:
assert isinstance(s, BNode)

gs = g.skolemize()
for s, p, o in gs:
assert isinstance(s, URIRef) and s.__contains__(rdflib_skolem_genid)

query_with_iri = 'select ?p ?o {{ <{}> ?p ?o }}'.format(s)
query_for_all = 'select ?s ?p ?o { ?s ?p ?o }'

count = 0
for row in gs.query(query_with_iri):
count += 1
assert count == 1

count = 0
for row in gs.query(query_for_all):
count += 1
assert count == 1

gp = Graph()
gp.parse(data=gs.serialize(format='turtle'), format='turtle')

count = 0
for row in gp.query(query_with_iri):
count += 1
assert count == 1

count = 0
for row in gp.query(query_for_all):
count += 1
assert count == 1
17 changes: 17 additions & 0 deletions test/test_skolem_genid.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from rdflib import URIRef
from rdflib.term import Genid, RDFLibGenid


def test_skolem_genid_and_rdflibgenid():
rdflib_genid = URIRef(
"http://rdflib.net/.well-known/genid/rdflib/N97c39b957bc444949a82793519348dc2"
)
custom_genid = URIRef(
"http://example.com/.well-known/genid/example/Ne864c0e3684044f381d518fdac652f2e"
)

assert RDFLibGenid._is_rdflib_skolem(rdflib_genid) is True
assert Genid._is_external_skolem(rdflib_genid) is True

assert RDFLibGenid._is_rdflib_skolem(custom_genid) is False
assert Genid._is_external_skolem(custom_genid) is True