Skip to content

Commit 6ff4ba9

Browse files
committed
New query method and tests.
1 parent a1a1933 commit 6ff4ba9

2 files changed

Lines changed: 196 additions & 14 deletions

File tree

osdf.py

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,31 @@ def validate_node(self, json_data):
228228

229229
return (valid, error_msg)
230230

231+
def oql_query(self, namespace, query, page=1):
232+
"""
233+
Issue an OSDF Query Language (OQL) query against OSDF.
234+
235+
Returns the specified page of results.
236+
"""
237+
url = "/nodes/oql/%s/page/%s" % (namespace, str(page))
238+
239+
osdf_response = self._request.post(url, query)
240+
241+
if osdf_response["code"] != 200 and osdf_response["code"] != 206:
242+
headers = osdf_response["headers"]
243+
244+
if 'x-osdf-error' in headers:
245+
msg = "Unable to query namespace %s. Reason: %s" % (namespace, headers['x-osdf-error'])
246+
else:
247+
msg = "Unable to query namespace."
248+
249+
raise Exception(msg)
250+
251+
data = json.loads( osdf_response['content'] )
252+
253+
data = self._byteify(data)
254+
255+
return data
231256

232257
def query(self, namespace, query, page=1):
233258
"""
@@ -256,6 +281,33 @@ def query(self, namespace, query, page=1):
256281

257282
return data
258283

284+
def oql_query_all_pages(self, namespace, query):
285+
"""
286+
Issue an OSDF Query Language (OQL) query against OSDF, as in the
287+
oql_query() method, but retrieves ALL results by aggregating all
288+
the available pages of results. Use with caution, as this may
289+
consume a lot of memory with large result sets.
290+
"""
291+
more_results = True
292+
page = 1
293+
cumulative_results = []
294+
295+
while more_results:
296+
results = self.oql_query(namespace, query, page)
297+
298+
cumulative_results.extend(results['results'])
299+
300+
if results['result_count'] > 0:
301+
page += 1
302+
else:
303+
more_results = False
304+
305+
results['results'] = cumulative_results
306+
results['result_count'] = len(results['results'])
307+
del results['page']
308+
309+
return results;
310+
259311
def query_all_pages(self, namespace, query):
260312
"""
261313
Issue a query against OSDF, as in the query() method, but retrieves
@@ -291,7 +343,7 @@ def create_osdf_node(self, namespace, node_type, domain_json, linkage={}, read="
291343

292344
return node_json
293345

294-
def header_error(self, heades=[], method_type='retrieve',
346+
def header_error(self, headers=[], method_type='retrieve',
295347
document_type=None):
296348
if 'x-osdf-error' in headers:
297349
msg = "Unable to %s %s document. Reason: %s" \

test/test_osdf.py

Lines changed: 143 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,28 @@
33
import unittest
44
from osdf import OSDF
55

6+
def _get_osdf():
7+
osdf = OSDF(OsdfTest.server, OsdfTest.username, OsdfTest.password)
8+
return osdf
9+
610
class OsdfTest(unittest.TestCase):
711
server = "osdf-devel.igs.umaryland.edu"
812
username = "test"
913
password = "test"
1014

15+
test_node = {
16+
"ns": "test",
17+
"acl": { "read": [ "all" ], "write": [ "all" ] },
18+
"linkage": {},
19+
"node_type": "example",
20+
"meta": {
21+
"description": "something",
22+
"color": "blue"
23+
}
24+
}
25+
1126
def testGetInfo(self):
12-
osdf = OSDF(OsdfTest.server, OsdfTest.username, OsdfTest.password)
27+
osdf = _get_osdf()
1328

1429
info = None
1530

@@ -33,36 +48,151 @@ def testGetInfo(self):
3348

3449

3550
def testOqlQuery(self):
36-
osdf = OSDF(OsdfTest.server, OsdfTest.username, OsdfTest.password)
51+
osdf = _get_osdf()
3752

3853
query = '"project"[node_type]'
3954
namespace = "test"
4055

4156
results = osdf.oql_query(namespace, query)
4257

43-
self.assertIsNotNone(results, "OQL query result is not None.")
58+
self._examine_paged_results(results, "OQL")
59+
60+
def testOqlQueryAllPages(self):
61+
osdf = _get_osdf()
62+
63+
query = '"project"[node_type]'
64+
namespace = "test"
65+
66+
results = osdf.oql_query_all_pages(namespace, query)
67+
self._examine_all_results(results, "OQL")
68+
69+
def _examine_all_results(self, results, search_type):
70+
self.assertIsNotNone(results, "%s query result is not None." % search_type)
71+
72+
self.assertTrue(type(results) == dict, "%s query result is a list." % search_type)
73+
74+
self.assertTrue('result_count' in results,
75+
"%s result contains 'result_count' key." % search_type)
4476

45-
self.assertTrue(type(results) == dict, "OQL query result is a list.")
77+
self.assertTrue('results' in results,
78+
"%s result contains 'results' key." % search_type)
4679

47-
self.assertTrue('result_count' in results, "Result contains 'result_count' key.")
48-
self.assertTrue('results' in results, "Result contains 'results' key.")
49-
self.assertTrue('page' in results, "Result contains 'page' key.")
80+
def _examine_paged_results(self, results, search_type):
81+
self.assertIsNotNone(results,
82+
"%s query result is not None." % search_type)
83+
84+
self.assertTrue(type(results) == dict,
85+
"%s query result is a list." % search_type)
86+
87+
self.assertTrue('result_count' in results,
88+
"%s result contains 'result_count' key." % search_type)
89+
self.assertTrue('results' in results,
90+
"%s result contains 'results' key." % search_type)
91+
self.assertTrue('page' in results,
92+
"%s result contains 'page' key." % search_type)
5093

5194
def testQuery(self):
52-
osdf = OSDF(OsdfTest.server, OsdfTest.username, OsdfTest.password)
95+
osdf = _get_osdf()
5396

5497
query = '{ "term" : { "node_type" : "project" }}'
5598
namespace = "test"
5699

57100
results = osdf.query(namespace, query)
58101

59-
self.assertIsNotNone(results, "Query result is not None.")
102+
self._examine_paged_results(results, "ES QueryDSL")
103+
104+
def testInsertNode(self):
105+
106+
osdf = _get_osdf()
107+
108+
exception_thrown = False;
109+
node_id = None
110+
111+
try:
112+
node_id = osdf.insert_node(OsdfTest.test_node)
113+
except Exception as e:
114+
print(e)
115+
exception_thrown = True
116+
117+
# Check that the insertion did not raise an exception
118+
self.assertFalse(exception_thrown);
119+
self.assertIsNotNone(node_id,
120+
"Node ID for inserted data is not None.")
121+
self.assertTrue(type(node_id) == str,
122+
"Node ID for inserted data is a string.")
123+
124+
def testGetNode(self):
125+
osdf = _get_osdf()
126+
127+
exception_thrown = False;
128+
node_id = osdf.insert_node(OsdfTest.test_node)
129+
retrieved = None
130+
131+
try:
132+
retrieved = osdf.get_node(node_id)
133+
except Exception as e:
134+
exception_thrown = True
135+
136+
# Check that there were no issues
137+
self.assertFalse(exception_thrown);
138+
139+
# Check that the retrieval yeilded some data
140+
self.assertIsNotNone(retrieved);
141+
self.assertTrue(type(retrieved) == dict,
142+
"Node retrieved has correct type.")
143+
144+
# Check that the data has the right structure
145+
self.assertTrue('ns' in retrieved)
146+
self.assertTrue('meta' in retrieved)
147+
self.assertTrue('linkage' in retrieved)
148+
self.assertTrue('ver' in retrieved)
149+
self.assertTrue('acl' in retrieved)
150+
self.assertTrue('id' in retrieved)
151+
152+
self.assertEqual(retrieved['id'], node_id,
153+
"Retrieved node has the right ID.")
154+
155+
# Do some cleanup after ourselves
156+
try:
157+
osdf.delete_node(node_id)
158+
except:
159+
# ignore any problems as they are not relevant to this
160+
# particular test
161+
pass
162+
163+
def testDeleteNode(self):
164+
osdf = _get_osdf()
165+
166+
exception_thrown = False;
167+
node_id = osdf.insert_node(OsdfTest.test_node)
168+
169+
try:
170+
osdf.delete_node(node_id)
171+
except Exception as e:
172+
exception_thrown = True
173+
174+
# Check that the deletion did not raise an exception
175+
self.assertFalse(exception_thrown);
176+
177+
# Now verify that the deletion actually work. A node
178+
# retrieval on that node ID should faile...
179+
get_success = True
180+
try:
181+
osdf.get_node(node_id)
182+
except Exception as e:
183+
get_success = False
184+
185+
self.assertFalse(get_success, "Deletion persisted in OSDF.")
186+
187+
def testQueryAllPages(self):
188+
osdf = _get_osdf()
189+
190+
query = '{ "term" : { "node_type" : "project" }}'
191+
namespace = "test"
60192

61-
self.assertTrue(type(results) == dict, "Query result is a list.")
193+
results = osdf.query_all_pages(namespace, query)
62194

63-
self.assertTrue('result_count' in results, "Result contains 'result_count' key.")
64-
self.assertTrue('results' in results, "Result contains 'results' key.")
65-
self.assertTrue('page' in results, "Result contains 'page' key.")
195+
self._examine_all_results(results, "ES QueryDSL")
66196

67197

68198
if __name__ == "__main__":

0 commit comments

Comments
 (0)