Skip to content

Commit 5cd80fc

Browse files
authored
Merge pull request #102 from casework/HotFix-sparql-query-result-types
Add SPARQL query result type assertions
2 parents bb18283 + 6b9e77b commit 5cd80fc

File tree

10 files changed

+78
-35
lines changed

10 files changed

+78
-35
lines changed

.pre-commit-config.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
repos:
22
- repo: https://github.com/psf/black
3-
rev: 22.10.0
3+
rev: 23.1.0
44
hooks:
55
- id: black
66
- repo: https://github.com/pycqa/flake8
7-
rev: 5.0.4
7+
rev: 6.0.0
88
hooks:
99
- id: flake8
1010
- repo: https://github.com/pycqa/isort
11-
rev: 5.10.1
11+
rev: 5.12.0
1212
hooks:
1313
- id: isort
1414
name: isort (python)

case_utils/case_file/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939

4040
DEFAULT_PREFIX = "http://example.org/kb/"
4141

42+
4243
# Shortcut syntax for defining an immutable named tuple is noted here:
4344
# https://docs.python.org/3/library/typing.html#typing.NamedTuple
4445
# via the "See also" box here: https://docs.python.org/3/library/collections.html#collections.namedtuple

case_utils/case_sparql_construct/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,11 @@ def main() -> None:
9898
construct_query_result = in_graph.query(construct_query_object)
9999
_logger.debug("type(construct_query_result) = %r." % type(construct_query_result))
100100
_logger.debug("len(construct_query_result) = %d." % len(construct_query_result))
101-
for (row_no, row) in enumerate(construct_query_result):
101+
for row_no, row in enumerate(construct_query_result):
102+
assert isinstance(row, tuple)
102103
if row_no == 0:
103104
_logger.debug("row[0] = %r." % (row,))
104-
out_graph.add(row)
105+
out_graph.add((row[0], row[1], row[2]))
105106

106107
output_format = None
107108
if args.output_format is None:

case_utils/case_sparql_select/__init__.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -86,26 +86,27 @@ def graph_and_query_to_data_frame(
8686
select_query_object = rdflib.plugins.sparql.processor.prepareQuery(
8787
select_query_text, initNs=nsdict
8888
)
89-
for (row_no, row) in enumerate(_graph.query(select_query_object)):
89+
for row_no, row in enumerate(_graph.query(select_query_object)):
90+
assert isinstance(row, rdflib.query.ResultRow)
9091
tally = row_no + 1
9192
record = []
92-
for (column_no, column) in enumerate(row):
93+
for column_no, column in enumerate(row):
9394
if column is None:
9495
column_value = ""
95-
elif (
96-
isinstance(column, rdflib.term.Literal)
97-
and column.datatype == NS_XSD.hexBinary
98-
):
99-
# Use hexlify to convert xsd:hexBinary to ASCII.
100-
# The render to ASCII is in support of this script rendering results for website viewing.
101-
# .decode() is because hexlify returns bytes.
102-
column_value = binascii.hexlify(column.toPython()).decode()
96+
elif isinstance(column, rdflib.term.Literal):
97+
if column.datatype == NS_XSD.hexBinary:
98+
# Use hexlify to convert xsd:hexBinary to ASCII.
99+
# The render to ASCII is in support of this script rendering results for website viewing.
100+
# .decode() is because hexlify returns bytes.
101+
column_value = binascii.hexlify(column.toPython()).decode()
102+
else:
103+
column_value = column.toPython()
103104
elif isinstance(column, rdflib.URIRef):
104105
if use_prefixes:
105106
column_value = graph.namespace_manager.qname(column.toPython())
106107
else:
107108
column_value = column.toPython()
108-
else:
109+
elif isinstance(column, rdflib.BNode):
109110
column_value = column.toPython()
110111
if row_no == 0:
111112
_logger.debug("row[0]column[%d] = %r." % (column_no, column_value))

case_utils/ontology/src/ontology_and_version_iris.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@
2828

2929
def concept_is_cdo_concept(n_concept: rdflib.URIRef) -> bool:
3030
"""
31-
This function is purposefully distinct from the function used in case_validate. Within this script, the publishing history of CASE and UCO is reviewed."""
31+
This function is purposefully distinct from the function used in case_validate. Within this script, the publishing history of CASE and UCO is reviewed.
32+
"""
3233
concept_iri = str(n_concept)
3334
return (
3435
concept_iri.startswith("https://ontology.unifiedcyberontology.org/")

tests/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,13 @@ check-isomorphic_diff: \
8181
--directory isomorphic_diff \
8282
check
8383

84-
# TODO - Fix type signatures in UCO test.
84+
# TODO - Add and strict-check type signatures for CASE and UCO tests.
8585
check-mypy: \
8686
.venv.done.log
8787
source venv/bin/activate \
8888
&& mypy \
8989
--exclude case_utils/case_validate/case_test_examples/test_case_validation.py \
90+
--exclude case_utils/case_validate/uco_test_examples/test_uco_validation.py \
9091
--exclude venv \
9192
--strict \
9293
$(top_srcdir)/case_utils \

tests/case_utils/case_file/test_case_file.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,11 @@ def test_confirm_hashes(graph_case_file: rdflib.Graph) -> None:
8585
)
8686

8787
for result in graph_case_file.query(query_object):
88-
(l_hash_method, l_hash_value) = result
88+
assert isinstance(result, rdflib.query.ResultRow)
89+
assert isinstance(result[0], rdflib.Literal)
90+
assert isinstance(result[1], rdflib.Literal)
91+
l_hash_method = result[0]
92+
l_hash_value = result[1]
8993
# .toPython() with the non-XSD datatype returns the original Literal object again. Hence, str().
9094
hash_method = str(l_hash_method)
9195
hash_value = binascii.hexlify(l_hash_value.toPython()).decode().upper()
@@ -117,13 +121,15 @@ def test_confirm_mtime(
117121

118122
n_observable_object = None
119123
for result in graph_case_file_disable_hashes.query(query_object):
124+
assert isinstance(result, rdflib.query.ResultRow)
120125
(n_observable_object,) = result
121126
assert (
122127
n_observable_object is not None
123128
), "File object with expected mtime not found in hashless graph."
124129

125130
n_observable_object = None
126131
for result in graph_case_file.query(query_object):
132+
assert isinstance(result, rdflib.query.ResultRow)
127133
(n_observable_object,) = result
128134
assert (
129135
n_observable_object is not None

tests/case_utils/case_sparql_construct/test_case_sparql_construct.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ def _test_subclass_templates_result(filename: str, expected: typing.Set[str]) ->
3030
}
3131
"""
3232
for result in graph.query(query_string):
33+
assert isinstance(result, rdflib.query.ResultRow)
34+
assert isinstance(result[0], rdflib.URIRef)
3335
n_entity = result[0]
3436
computed.add(n_entity.toPython())
3537
assert expected == computed
@@ -54,7 +56,11 @@ def _test_w3_templates_with_blank_nodes_result(filename: str) -> None:
5456
}
5557
"""
5658
for result in graph.query(query_string):
57-
(l_given_name, l_family_name) = result
59+
assert isinstance(result, rdflib.query.ResultRow)
60+
assert isinstance(result[0], rdflib.Literal)
61+
assert isinstance(result[1], rdflib.term.Literal)
62+
l_given_name = result[0]
63+
l_family_name = result[1]
5864
computed.add((l_given_name.toPython(), l_family_name.toPython()))
5965
assert expected == computed
6066

tests/case_utils/case_sparql_select/test_data_frame_to_table_text_json.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@
3636
)
3737

3838

39-
def make_data_frame_to_json_table_text_parameters() -> typing.Iterator[
40-
typing.Tuple[str, str, bool, bool]
41-
]:
39+
def make_data_frame_to_json_table_text_parameters() -> (
40+
typing.Iterator[typing.Tuple[str, str, bool, bool]]
41+
):
4242
for use_header in [False, True]:
4343
for use_index in [False, True]:
4444
for output_mode in ["csv", "html", "json", "md", "tsv"]:

tests/hexbinary/test_hexbinary.py

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,9 @@ def test_sparql_syntax_bind_boolean() -> None:
8080
}
8181
"""
8282
):
83-
(l_value,) = result
83+
assert isinstance(result, rdflib.query.ResultRow)
84+
assert isinstance(result[0], rdflib.Literal)
85+
l_value = result[0]
8486
confirmed = l_value.toPython()
8587
assert confirmed
8688

@@ -100,7 +102,9 @@ def test_pytest_syntax_xfail() -> None:
100102
}
101103
"""
102104
):
103-
(l_value,) = result
105+
assert isinstance(result, rdflib.query.ResultRow)
106+
assert isinstance(result[0], rdflib.Literal)
107+
l_value = result[0]
104108
confirmed = l_value.toPython()
105109
assert confirmed
106110

@@ -119,7 +123,9 @@ def test_sparql_syntax_integer_coercion() -> None:
119123
}
120124
"""
121125
):
122-
(l_value,) = result
126+
assert isinstance(result, rdflib.query.ResultRow)
127+
assert isinstance(result[0], rdflib.Literal)
128+
l_value = result[0]
123129
confirmed = l_value.toPython()
124130
assert confirmed
125131

@@ -138,7 +144,9 @@ def test_sparql_syntax_integer_cast() -> None:
138144
}
139145
"""
140146
):
141-
(l_value,) = result
147+
assert isinstance(result, rdflib.query.ResultRow)
148+
assert isinstance(result[0], rdflib.Literal)
149+
l_value = result[0]
142150
confirmed = l_value.toPython()
143151
assert confirmed
144152

@@ -158,7 +166,9 @@ def test_sparql_cast_custom_type() -> None:
158166
}
159167
"""
160168
):
161-
(l_value,) = result
169+
assert isinstance(result, rdflib.query.ResultRow)
170+
assert isinstance(result[0], rdflib.Literal)
171+
l_value = result[0]
162172
confirmed = l_value.toPython()
163173
assert confirmed
164174

@@ -174,7 +184,9 @@ def test_sparql_compare_hexbinary_mixcase() -> None:
174184
}
175185
"""
176186
):
177-
(l_value,) = result
187+
assert isinstance(result, rdflib.query.ResultRow)
188+
assert isinstance(result[0], rdflib.Literal)
189+
l_value = result[0]
178190
confirmed = l_value.toPython()
179191
assert confirmed
180192

@@ -190,7 +202,9 @@ def test_sparql_compare_hexbinary_matchcase() -> None:
190202
}
191203
"""
192204
):
193-
(l_value,) = result
205+
assert isinstance(result, rdflib.query.ResultRow)
206+
assert isinstance(result[0], rdflib.Literal)
207+
l_value = result[0]
194208
confirmed = l_value.toPython()
195209
assert confirmed
196210

@@ -206,7 +220,9 @@ def test_sparql_compare_hexbinarycanonical_matchcase() -> None:
206220
}
207221
"""
208222
):
209-
(l_value,) = result
223+
assert isinstance(result, rdflib.query.ResultRow)
224+
assert isinstance(result[0], rdflib.Literal)
225+
l_value = result[0]
210226
confirmed = l_value.toPython()
211227
assert confirmed
212228

@@ -226,7 +242,9 @@ def test_sparql_compare_hexbinarycanonical_mixcase() -> None:
226242
}
227243
"""
228244
):
229-
(l_value,) = result
245+
assert isinstance(result, rdflib.query.ResultRow)
246+
assert isinstance(result[0], rdflib.Literal)
247+
l_value = result[0]
230248
confirmed = l_value.toPython()
231249
assert confirmed
232250

@@ -246,7 +264,9 @@ def test_sparql_compare_hb_hbc_mixcase() -> None:
246264
}
247265
"""
248266
):
249-
(l_value,) = result
267+
assert isinstance(result, rdflib.query.ResultRow)
268+
assert isinstance(result[0], rdflib.Literal)
269+
l_value = result[0]
250270
confirmed = l_value.toPython()
251271
assert confirmed
252272

@@ -266,7 +286,9 @@ def test_sparql_compare_hb_hbc_mixcase_cast() -> None:
266286
}
267287
"""
268288
):
269-
(l_value,) = result
289+
assert isinstance(result, rdflib.query.ResultRow)
290+
assert isinstance(result[0], rdflib.Literal)
291+
l_value = result[0]
270292
confirmed = l_value.toPython()
271293
assert confirmed
272294

@@ -315,7 +337,11 @@ def _query_all_value_matches(graph: rdflib.Graph) -> typing.Set[str]:
315337
FILTER ( ?nNode1 != ?nNode2 )
316338
}"""
317339
):
318-
(n_node1, n_node2) = result
340+
assert isinstance(result, rdflib.query.ResultRow)
341+
assert isinstance(result[0], rdflib.URIRef)
342+
assert isinstance(result[1], rdflib.URIRef)
343+
n_node1 = result[0]
344+
n_node2 = result[1]
319345
computed.add(n_node1.toPython())
320346
computed.add(n_node2.toPython())
321347
return computed

0 commit comments

Comments
 (0)