Merge branch 'RDFLib:master' into fix-for-issue1429 · RDFLib/rdflib@72f5b59 (original) (raw)
``
1
`+
#!/usr/bin/env python3
`
``
2
+
``
3
`+
This software was developed at the National Institute of Standards
`
``
4
`+
and Technology by employees of the Federal Government in the course
`
``
5
`+
of their official duties. Pursuant to title 17 Section 105 of the
`
``
6
`+
United States Code this software is not subject to copyright
`
``
7
`+
protection and is in the public domain. NIST assumes no
`
``
8
`+
responsibility whatsoever for its use by other parties, and makes
`
``
9
`+
no guarantees, expressed or implied, about its quality,
`
``
10
`+
reliability, or any other characteristic.
`
``
11
`+
`
``
12
`+
We would appreciate acknowledgement if the software is used.
`
``
13
+
``
14
`+
"""
`
``
15
`+
This test-set demonstrates usage of identifier prefixing and the
`
``
16
`+
forward-slash character in Turtle, JSON-LD, and SPARQL. The motivating
`
``
17
`+
use case originated with attempts to interact with IANA Media Types as
`
``
18
`+
prefixed concepts, e.g. "application/json" somehow being
`
``
19
`+
"mime:application/json".
`
``
20
`+
"""
`
``
21
+
``
22
`+
from test.data import TEST_DATA_DIR
`
``
23
`+
from test.utils.graph import cached_graph
`
``
24
`+
from typing import Set
`
``
25
+
``
26
`+
import pytest
`
``
27
+
``
28
`+
from rdflib import Graph
`
``
29
`+
from rdflib.plugins.sparql.processor import prepareQuery
`
``
30
`+
from rdflib.plugins.sparql.sparql import Query
`
``
31
+
``
32
`+
query_string_expanded = r"""
`
``
33
`+
SELECT ?nIndividual
`
``
34
`+
WHERE {
`
``
35
`+
?nIndividual a http://example.org/ontology/core/MyClassB .
`
``
36
`+
}"""
`
``
37
+
``
38
`+
NOTE: This is expected to fail. The SPARQL grammar production rules
`
``
39
`+
for prefixed IRIs, especially at production rule PN_LOCAL, have no way
`
``
40
`+
to reach the forward-slash or backslash characters.
`
``
41
`+
https://www.w3.org/TR/rdf-sparql-query/#grammar
`
``
42
`+
query_string_prefixed = r"""
`
``
43
`+
PREFIX ex: http://example.org/ontology/
`
``
44
`+
SELECT ?nIndividual
`
``
45
`+
WHERE {
`
``
46
`+
NOTE: Syntax is incorrect - forward slash cannot be included in
`
``
47
`+
local component of name.
`
``
48
`+
?nIndividual a ex:core/MyClassB .
`
``
49
`+
}"""
`
``
50
+
``
51
`+
PN_LOCAL_BACKSLASH_XFAIL_REASON = """
`
``
52
`+
Contrary to the ratified SPARQL 1.1 grammar, the RDFlib SPARQL propcessor
`
``
53
`+
accepts backslashes as part of PN_LOCAL which it treats as escape
`
``
54
`+
characters.
`
``
55
+
``
56
`+
There should be a way to instruct the SPARQL parser to operate in strict
`
``
57
`+
mode, and in strict mode backslashes should not be permitted in PN_LOCAL.
`
``
58
+
``
59
`+
See https://github.com/RDFLib/rdflib/issues/1871
`
``
60
`+
"""
`
``
61
+
``
62
+
``
63
`+
def _test_query_prepares(query_string: str) -> None:
`
``
64
`+
"""
`
``
65
`+
Confirm parse behavior of SPARQL engine when a concept would be
`
``
66
`+
prefixed at a point that leaves a forward-slash character in the
`
``
67
`+
suffix.
`
``
68
`+
"""
`
``
69
`+
nsdict = {
`
``
70
`+
"ex": "http://example.org/ontology/",
`
``
71
`+
"kb": "http://example.org/kb/",
`
``
72
`+
"owl": "http://www.w3.org/2002/07/owl#",
`
``
73
`+
}
`
``
74
`+
TODO: A 'strict' flag for prepareQuery is under consideration to
`
``
75
`+
adjust parse behavior around backslash characters.
`
``
76
`+
query_object = prepareQuery(query_string, initNs=nsdict)
`
``
77
`+
assert isinstance(query_object, Query)
`
``
78
+
``
79
+
``
80
`+
def test_query_prepares_expanded() -> None:
`
``
81
`+
_test_query_prepares(query_string_expanded)
`
``
82
+
``
83
+
``
84
`+
@pytest.mark.xfail(reason=PN_LOCAL_BACKSLASH_XFAIL_REASON)
`
``
85
`+
def test_query_prepares_prefixed() -> None:
`
``
86
`+
with pytest.raises(ValueError):
`
``
87
`+
_test_query_prepares(query_string_prefixed)
`
``
88
+
``
89
+
``
90
`+
def _test_escapes_and_query(
`
``
91
`+
graph: Graph, query_string: str, expected_query_compiled: bool
`
``
92
`+
) -> None:
`
``
93
`+
"""
`
``
94
`+
Confirm search-results behavior of SPARQL engine when a concept
`
``
95
`+
would be prefixed at a point that leaves a forward-slash character
`
``
96
`+
in the suffix.
`
``
97
+
``
98
`+
Note that _test_query_prepares also exercises the expected parse
`
``
99
`+
failure. This parameterized test is more for demonstrating that
`
``
100
`+
searching can work without prefixes.
`
``
101
`+
"""
`
``
102
`+
expected: Set[str] = {
`
``
103
`+
"http://example.org/kb/individual-b",
`
``
104
`+
}
`
``
105
`+
computed: Set[str] = set()
`
``
106
+
``
107
`+
query_compiled: bool = False
`
``
108
`+
try:
`
``
109
`+
query_object = prepareQuery(query_string)
`
``
110
`+
query_compiled = True
`
``
111
`+
except Exception:
`
``
112
`+
pass
`
``
113
`+
assert expected_query_compiled == query_compiled
`
``
114
+
``
115
`+
for result in graph.query(query_object):
`
``
116
`+
computed.add(str(result[0]))
`
``
117
+
``
118
`+
assert expected == computed
`
``
119
+
``
120
+
``
121
`+
def test_escapes_and_query_turtle_expanded() -> None:
`
``
122
`+
graph = cached_graph((TEST_DATA_DIR / "variants/forward_slash.ttl",))
`
``
123
`+
_test_escapes_and_query(graph, query_string_expanded, True)
`
``
124
+
``
125
+
``
126
`+
@pytest.mark.xfail(reason=PN_LOCAL_BACKSLASH_XFAIL_REASON, raises=AssertionError)
`
``
127
`+
def test_escapes_and_query_turtle_prefixed() -> None:
`
``
128
`+
graph = cached_graph((TEST_DATA_DIR / "variants/forward_slash.ttl",))
`
``
129
`+
_test_escapes_and_query(graph, query_string_prefixed, False)
`
``
130
+
``
131
+
``
132
`+
def test_escapes_and_query_jsonld_expanded() -> None:
`
``
133
`+
graph = cached_graph((TEST_DATA_DIR / "variants/forward_slash.jsonld",))
`
``
134
`+
_test_escapes_and_query(graph, query_string_expanded, True)
`
``
135
+
``
136
+
``
137
`+
@pytest.mark.xfail(reason=PN_LOCAL_BACKSLASH_XFAIL_REASON, raises=AssertionError)
`
``
138
`+
def test_escapes_and_query_jsonld_prefixed() -> None:
`
``
139
`+
graph = cached_graph((TEST_DATA_DIR / "variants/forward_slash.jsonld",))
`
``
140
`+
_test_escapes_and_query(graph, query_string_prefixed, False)
`