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)

`