Skip to content

Commit 46e3d7d

Browse files
author
CI
committed
Merge branch 'review' into develop
2 parents f80c81b + e6fa8d8 commit 46e3d7d

File tree

4 files changed

+286
-11
lines changed

4 files changed

+286
-11
lines changed

adk/ADK.py

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -97,13 +97,13 @@ def create_exception(self, exception):
9797
error_type = exception.error_type
9898
else:
9999
error_type = "AlgorithmError"
100-
response = {
100+
response = json.dumps({
101101
"error": {
102102
"message": str(exception),
103103
"stacktrace": traceback.format_exc(),
104104
"error_type": error_type,
105105
}
106-
}
106+
})
107107
return response
108108

109109
def process_loop(self):
@@ -122,19 +122,30 @@ def process_loop(self):
122122
finally:
123123
self.write_to_pipe(response_obj)
124124

125-
def init(self, local_payload=None, pprint=print):
125+
def process_local(self, local_payload, pprint):
126+
if self.load_result:
127+
apply_result = self.apply_func(local_payload, self.load_result)
128+
else:
129+
apply_result = self.apply_func(local_payload)
130+
pprint(self.format_response(apply_result))
131+
132+
def loading_process(self, pprint):
126133
try:
127134
if self.load_func:
128135
self.load()
136+
return True
129137
except Exception as e:
130138
load_error = self.create_exception(e)
131-
self.write_to_pipe(load_error)
132-
if self.is_local and local_payload:
133-
if self.load_result:
134-
apply_result = self.apply_func(local_payload, self.load_result)
139+
if self.is_local:
140+
pprint(load_error)
135141
else:
136-
apply_result = self.apply_func(local_payload)
137-
pprint(self.format_response(apply_result))
142+
self.write_to_pipe(load_error)
143+
return False
138144

139-
else:
140-
self.process_loop()
145+
def init(self, local_payload=None, pprint=print):
146+
loading_result = self.loading_process(pprint)
147+
if loading_result:
148+
if self.is_local and local_payload:
149+
self.process_local(local_payload, pprint)
150+
else:
151+
self.process_loop()

tests/adk_algorithms.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import Algorithmia
2+
3+
4+
# -- Apply functions --- #
5+
def apply_basic(input):
6+
return "hello " + input
7+
8+
9+
def apply_input_or_context(input, globals=None):
10+
if isinstance(globals, dict):
11+
return globals
12+
else:
13+
return "hello " + input
14+
15+
16+
# -- Loading functions --- #
17+
def loading_text():
18+
context = dict()
19+
context['message'] = 'This message was loaded prior to runtime'
20+
return context
21+
22+
23+
def loading_exception():
24+
raise Exception("This exception was thrown in loading")
25+
26+
27+
def loading_file_from_algorithmia():
28+
context = dict()
29+
client = Algorithmia.client()
30+
context['data_url'] = 'data://demo/collection/somefile.json'
31+
context['data'] = client.file(context['data_url']).getJson()
32+
return context

tests/test_adk_local.py

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import sys
2+
import json
3+
import os
4+
import unittest
5+
from adk import ADK
6+
from adk_algorithms import *
7+
8+
9+
class LocalTest(unittest.TestCase):
10+
fifo_pipe_path = "/tmp/algoout"
11+
def setUp(self):
12+
try:
13+
os.remove(self.fifo_pipe_path)
14+
except:
15+
pass
16+
17+
def execute_example(self, input, apply, load=lambda: None):
18+
algo = ADK(apply, load)
19+
output = []
20+
algo.init(input, pprint=lambda x: output.append(x))
21+
return output[0]
22+
23+
def execute_without_load(self, input, apply):
24+
algo = ADK(apply)
25+
output = []
26+
algo.init(input, pprint=lambda x: output.append(x))
27+
return output[0]
28+
29+
30+
def test_basic(self):
31+
input = 'Algorithmia'
32+
expected_output = {"metadata":
33+
{
34+
"content_type": "text"
35+
},
36+
"result": "hello Algorithmia"
37+
}
38+
actual_output = json.loads(self.execute_example(input, apply_input_or_context))
39+
self.assertEqual(expected_output, actual_output)
40+
41+
def test_basic_2(self):
42+
input = 'Algorithmia'
43+
expected_output = {"metadata":
44+
{
45+
"content_type": "text"
46+
},
47+
"result": "hello Algorithmia"
48+
}
49+
actual_output = json.loads(self.execute_without_load(input, apply_basic))
50+
self.assertEqual(expected_output, actual_output)
51+
52+
53+
def test_algorithm_loading_basic(self):
54+
input = "ignore me"
55+
expected_output = {'metadata':
56+
{
57+
'content_type': 'json'
58+
},
59+
'result': {'message': 'This message was loaded prior to runtime'}
60+
}
61+
actual_output = json.loads(self.execute_example(input, apply_input_or_context, loading_text))
62+
self.assertEqual(expected_output, actual_output)
63+
64+
def test_algorithm_loading_algorithmia(self):
65+
input = "ignore me"
66+
expected_output = {'metadata':
67+
{
68+
'content_type': 'json'
69+
},
70+
'result': {
71+
'data_url': 'data://demo/collection/somefile.json',
72+
'data': {'foo': 'bar'}
73+
}
74+
}
75+
actual_output = json.loads(self.execute_example(input, apply_input_or_context, loading_file_from_algorithmia))
76+
self.assertEqual(expected_output, actual_output)
77+
78+
def test_error_loading(self):
79+
input = "Algorithmia"
80+
expected_output = {'error':
81+
{'message': 'This exception was thrown in loading',
82+
'error_type': 'AlgorithmError',
83+
'stacktrace': ''
84+
}
85+
}
86+
actual_output = json.loads(self.execute_example(input, apply_input_or_context, loading_exception))
87+
# beacuse the stacktrace is local path specific,
88+
# we're going to assume it's setup correctly and remove it from our equality check
89+
actual_output["error"]["stacktrace"] = ''
90+
self.assertEqual(expected_output, actual_output)
91+
92+
if __name__ == '__main__':
93+
unittest.main()

tests/test_adk_remote.py

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
import sys
2+
import json
3+
import unittest
4+
import os
5+
from adk import ADK
6+
from adk_algorithms import *
7+
8+
9+
class RemoteTest(unittest.TestCase):
10+
if os.name == "posix":
11+
fifo_pipe_path = "/tmp/algoout"
12+
fifo_pipe = None
13+
14+
def setUp(self):
15+
try:
16+
os.mkfifo(self.fifo_pipe_path)
17+
except Exception:
18+
pass
19+
20+
def tearDown(self):
21+
if os.name == "posix":
22+
os.remove(self.fifo_pipe_path)
23+
24+
def read_in(self):
25+
if os.name == "posix":
26+
return self.read_from_pipe()
27+
if os.name == "nt":
28+
return self.read_from_stdin()
29+
30+
def read_from_stdin(self):
31+
return json.loads(sys.stdin)
32+
33+
def read_from_pipe(self):
34+
read_obj = os.read(self.fifo_pipe, 10000)
35+
if isinstance(read_obj, bytes):
36+
read_obj = read_obj.decode("utf-8")
37+
actual_output = json.loads(read_obj)
38+
os.close(self.fifo_pipe)
39+
return actual_output
40+
41+
def open_pipe(self):
42+
if os.name == "posix":
43+
self.fifo_pipe = os.open(self.fifo_pipe_path, os.O_RDONLY | os.O_NONBLOCK)
44+
45+
def execute_example(self, input, apply, load=lambda: None):
46+
self.open_pipe()
47+
algo = ADK(apply, load)
48+
sys.stdin = input
49+
algo.init()
50+
output = self.read_in()
51+
return output
52+
53+
def execute_without_load(self, input, apply):
54+
self.open_pipe()
55+
algo = ADK(apply)
56+
sys.stdin = input
57+
algo.init()
58+
output = self.read_in()
59+
return output
60+
61+
def execute_example_local(self, input, apply, load=lambda: None):
62+
algo = ADK(apply, load)
63+
output = algo.init(input, pprint=lambda x: x)
64+
return output
65+
66+
67+
68+
# ----- Tests ----- #
69+
70+
def test_basic(self):
71+
input = {'content_type': 'json', 'data': 'Algorithmia'}
72+
expected_output = {"metadata":
73+
{
74+
"content_type": "text"
75+
},
76+
"result": "hello Algorithmia"
77+
}
78+
input = [str(json.dumps(input))]
79+
actual_output = self.execute_example(input, apply_input_or_context)
80+
self.assertEqual(expected_output, actual_output)
81+
82+
def test_basic_2(self):
83+
input = {'content_type': 'json', 'data': 'Algorithmia'}
84+
expected_output = {"metadata":
85+
{
86+
"content_type": "text"
87+
},
88+
"result": "hello Algorithmia"
89+
}
90+
input = [str(json.dumps(input))]
91+
actual_output = self.execute_without_load(input, apply_basic)
92+
self.assertEqual(expected_output, actual_output)
93+
94+
95+
def test_algorithm_loading_basic(self):
96+
input = {'content_type': 'json', 'data': 'ignore me'}
97+
expected_output = {'metadata':
98+
{
99+
'content_type': 'json'
100+
},
101+
'result': {'message': 'This message was loaded prior to runtime'}
102+
}
103+
input = [str(json.dumps(input))]
104+
actual_output = self.execute_example(input, apply_input_or_context, loading_text)
105+
self.assertEqual(expected_output, actual_output)
106+
107+
def test_algorithm_loading_algorithmia(self):
108+
input = {'content_type': 'json', 'data': 'ignore me'}
109+
expected_output = {'metadata':
110+
{
111+
'content_type': 'json'
112+
},
113+
'result': {
114+
'data_url': 'data://demo/collection/somefile.json',
115+
'data': {'foo': 'bar'}
116+
}
117+
}
118+
input = [str(json.dumps(input))]
119+
actual_output = self.execute_example(input, apply_input_or_context, loading_file_from_algorithmia)
120+
self.assertEqual(expected_output, actual_output)
121+
122+
def test_error_loading(self):
123+
input = {'content_type': 'json', 'data': 'Algorithmia'}
124+
expected_output = {'error':
125+
{'message': 'This exception was thrown in loading',
126+
'error_type': 'AlgorithmError',
127+
'stacktrace': ''
128+
}
129+
}
130+
input = [str(json.dumps(input))]
131+
actual_output = self.execute_example(input, apply_input_or_context, loading_exception)
132+
# beacuse the stacktrace is local path specific,
133+
# we're going to assume it's setup correctly and remove it from our equality check
134+
actual_output["error"]["stacktrace"] = ''
135+
self.assertEqual(expected_output, actual_output)
136+
137+
138+
if __name__ == '__main__':
139+
unittest.main()

0 commit comments

Comments
 (0)