Skip to content

Commit c9234d5

Browse files
Add binding result streaming to client
1 parent 8c260be commit c9234d5

File tree

3 files changed

+56
-18
lines changed

3 files changed

+56
-18
lines changed

terminusdb_client/client/Client.py

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,34 @@
3030
# license Apache Version 2
3131
# summary Python module for accessing the Terminus DB API
3232

33+
class WoqlResult:
34+
"""Iterator for streaming WOQL results."""
35+
def __init__(self, lines):
36+
preface = json.loads(next(lines))
37+
if not ('@type' in preface and preface['@type'] == 'PrefaceRecord'):
38+
raise DatabaseError(response=preface)
39+
self.preface=preface
40+
self.postscript={}
41+
self.lines=lines
42+
43+
def _check_error(self, document):
44+
if ('@type' in document):
45+
if document['@type'] == 'Binding':
46+
return document
47+
if document['@type'] == 'PostscriptRecord':
48+
self.postscript = document
49+
raise StopIteration()
50+
51+
raise DatabaseError(response=document)
52+
53+
def variable_names(self):
54+
return self.preface['names']
55+
56+
def __iter__(self):
57+
return self
58+
59+
def __next__(self):
60+
return self._check_error(json.loads(next(self.lines)))
3361

3462
class JWTAuth(requests.auth.AuthBase):
3563
"""Class for JWT Authentication in requests"""
@@ -1500,8 +1528,9 @@ def query(
15001528
commit_msg: Optional[str] = None,
15011529
get_data_version: bool = False,
15021530
last_data_version: Optional[str] = None,
1531+
streaming: bool = False,
15031532
# file_dict: Optional[dict] = None,
1504-
) -> Union[dict, str]:
1533+
) -> Union[dict, str, WoqlResult]:
15051534
"""Updates the contents of the specified graph with the triples encoded in turtle format Replaces the entire graph contents
15061535
15071536
Parameters
@@ -1537,6 +1566,7 @@ def query(
15371566
else:
15381567
request_woql_query = woql_query
15391568
query_obj["query"] = request_woql_query
1569+
query_obj["streaming"] = streaming
15401570

15411571
headers = self._default_headers.copy()
15421572
if last_data_version is not None:
@@ -1547,7 +1577,12 @@ def query(
15471577
headers=headers,
15481578
json=query_obj,
15491579
auth=self._auth(),
1580+
stream=streaming
15501581
)
1582+
1583+
if streaming:
1584+
return WoqlResult(lines=_finish_response(result, streaming=True))
1585+
15511586
if get_data_version:
15521587
result, version = _finish_response(result, get_data_version)
15531588
result = json.loads(result)

terminusdb_client/woql_utils.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
from .errors import DatabaseError
55

6-
76
def _result2stream(result):
87
"""turning JSON string into a interable that give you a stream of dictionary"""
98
decoder = json.JSONDecoder()
@@ -24,7 +23,7 @@ def _args_as_payload(args: dict) -> dict:
2423
return {k: v for k, v in args.items() if v}
2524

2625

27-
def _finish_response(request_response, get_version=False):
26+
def _finish_response(request_response, get_version=False, streaming=False):
2827
"""Get the response text
2928
3029
Parameters
@@ -43,11 +42,14 @@ def _finish_response(request_response, get_version=False):
4342
4443
"""
4544
if request_response.status_code == 200:
46-
if get_version:
45+
if get_version and not streaming:
4746
return request_response.text, request_response.headers.get(
4847
"Terminusdb-Data-Version"
4948
)
50-
return request_response.text # if not a json it raises an error
49+
if streaming:
50+
return request_response.iter_lines()
51+
else:
52+
return request_response.text # if not a json it raises an error
5153
elif request_response.status_code > 399 and request_response.status_code < 599:
5254
raise DatabaseError(request_response)
5355

terminusdb_client/woqlquery/woql_query.py

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -367,21 +367,22 @@ def _clean_subject(self, obj):
367367
return self._expand_node_variable(obj)
368368
raise ValueError("Subject must be a URI string")
369369

370-
def _clean_predicate(self, predicate):
370+
def _clean_predicate(self, obj):
371371
"""Transforms whatever is passed in as the predicate (id or variable) into the appropriate json-ld form"""
372372
pred = False
373-
if isinstance(predicate, dict):
374-
return predicate
375-
if not isinstance(predicate, str):
376-
raise ValueError("Predicate must be a URI string")
377-
return str(predicate)
378-
if ":" in predicate:
379-
pred = predicate
380-
elif self._vocab and (predicate in self._vocab):
381-
pred = self._vocab[predicate]
382-
else:
383-
pred = predicate
384-
return self._expand_node_variable(pred)
373+
if type(obj) is dict:
374+
return obj
375+
elif type(obj) is str:
376+
if ":" in obj:
377+
pred = obj
378+
elif self._vocab and (obj in self._vocab):
379+
pred = self._vocab[obj]
380+
else:
381+
pred = obj
382+
return self._expand_node_variable(pred)
383+
elif isinstance(obj, Var):
384+
return self._expand_node_variable(obj)
385+
raise ValueError("Predicate must be a URI string")
385386

386387
def _clean_path_predicate(self, predicate=None):
387388
pred = False

0 commit comments

Comments
 (0)