Skip to content

Commit eacf513

Browse files
committed
bug fix: allow steps with no parameters
1 parent 0d0cd57 commit eacf513

File tree

2 files changed

+138
-11
lines changed

2 files changed

+138
-11
lines changed

src/sasctl/_services/microanalytic_score.py

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -227,8 +227,8 @@ def define_steps(self, module):
227227
step = self.get_module_step(module, id)
228228

229229
# Method should have an argument for each parameter of the step
230-
arguments = [k['name'] for k in step.inputs]
231-
arg_types = [k['type'] for k in step.inputs]
230+
arguments = [k['name'] for k in step.get('inputs', [])]
231+
arg_types = [k['type'] for k in step.get('inputs', [])]
232232

233233
# Format call to execute_module_step()
234234
call_params = ['{}={}'.format(i, i) for i in arguments]
@@ -237,28 +237,31 @@ def define_steps(self, module):
237237
type_string = ' # type: ({})'.format(', '.join(arg_types))
238238

239239
# Method signature
240-
signature = 'def _%s_%s(%s, **kwargs):' \
240+
input_params = [a for a in arguments] + ['**kwargs']
241+
signature = 'def _%s_%s(%s):' \
241242
% (module.name,
242243
step.id,
243-
', '.join(a for a in arguments))
244+
', '.join(input_params))
244245

245246
# MAS always lower-cases variable names
246247
# Since the original Python variables may have a different case,
247248
# allow kwargs to be used to input alternative caps
248-
arg_checks = ['for k in kwargs.keys():']
249-
for arg in arguments:
250-
arg_checks.append(" if k.lower() == '%s':" % arg.lower())
251-
arg_checks.append(" %s = kwargs[k]" % arg)
252-
arg_checks.append(" continue")
249+
if len(arguments):
250+
arg_checks = ['for k in kwargs.keys():']
251+
for arg in arguments:
252+
arg_checks.append(" if k.lower() == '%s':" % arg.lower())
253+
arg_checks.append(" %s = kwargs[k]" % arg)
254+
arg_checks.append(" continue")
255+
else:
256+
arg_checks = []
253257

254258
# Full method source code
255259
# Drops 'rc' and 'msg' from return values
256260
code = (signature,
257261
type_string,
258262
' """Execute step %s of module %s."""' % (step, module),
259263
'\n'.join([' %s' % a for a in arg_checks]),
260-
' r = execute_module_step(module, step, {})'.format(
261-
', '.join(call_params)),
264+
' r = execute_module_step(%s)' % ', '.join(['module', 'step'] + call_params),
262265
' r.pop("rc", None)',
263266
' r.pop("msg", None)',
264267
' if len(r) == 1:',

tests/unit/test_microanalytic_score.py

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from sasctl.services import microanalytic_score as mas
1111

1212
from sasctl import current_session
13+
from sasctl.core import RestObj
1314

1415
with mock.patch('sasctl.core.requests.Session.request'):
1516
current_session('example.com', 'username', 'password')
@@ -46,3 +47,126 @@ def test_delete_module(caplog):
4647
assert mas.delete_module('spam') is None
4748
assert any("Object 'spam' not found" in r.msg for r in caplog.records)
4849

50+
51+
def test_define_steps():
52+
53+
# Mock module to be returned
54+
module = RestObj(name='unittestmodule',
55+
stepIds=['step1', 'step2'])
56+
57+
# Mock module step with no inputs
58+
step1 = RestObj(id='post')
59+
60+
# Mock module step with multiple inputs
61+
step2 = RestObj({
62+
"id": "score",
63+
"inputs": [
64+
{
65+
"name": "age",
66+
"type": "decimal",
67+
"dim": 0,
68+
"size": 0
69+
},
70+
{
71+
"name": "b",
72+
"type": "decimal",
73+
"dim": 0,
74+
"size": 0
75+
},
76+
{
77+
"name": "chas",
78+
"type": "decimal",
79+
"dim": 0,
80+
"size": 0
81+
},
82+
{
83+
"name": "crim",
84+
"type": "decimal",
85+
"dim": 0,
86+
"size": 0
87+
},
88+
{
89+
"name": "dis",
90+
"type": "decimal",
91+
"dim": 0,
92+
"size": 0
93+
},
94+
{
95+
"name": "indus",
96+
"type": "decimal",
97+
"dim": 0,
98+
"size": 0
99+
},
100+
{
101+
"name": "lstat",
102+
"type": "decimal",
103+
"dim": 0,
104+
"size": 0
105+
},
106+
{
107+
"name": "nox",
108+
"type": "decimal",
109+
"dim": 0,
110+
"size": 0
111+
},
112+
{
113+
"name": "ptratio",
114+
"type": "decimal",
115+
"dim": 0,
116+
"size": 0
117+
},
118+
{
119+
"name": "rad",
120+
"type": "decimal",
121+
"dim": 0,
122+
"size": 0
123+
},
124+
{
125+
"name": "rm",
126+
"type": "decimal",
127+
"dim": 0,
128+
"size": 0
129+
},
130+
{
131+
"name": "tax",
132+
"type": "decimal",
133+
"dim": 0,
134+
"size": 0
135+
},
136+
{
137+
"name": "zn",
138+
"type": "decimal",
139+
"dim": 0,
140+
"size": 0
141+
}
142+
],
143+
"outputs": [
144+
{
145+
"name": "em_prediction",
146+
"type": "decimal",
147+
"dim": 0,
148+
"size": 0
149+
},
150+
{
151+
"name": "p_price",
152+
"type": "decimal",
153+
"dim": 0,
154+
"size": 0
155+
},
156+
{
157+
"name": "_warn_",
158+
"type": "string",
159+
"dim": 0,
160+
"size": 4
161+
}
162+
]
163+
})
164+
165+
with mock.patch('sasctl._services.microanalytic_score.MicroAnalyticScore.get_module') as get_module:
166+
with mock.patch('sasctl._services.microanalytic_score.MicroAnalyticScore''.get_module_step') as get_step:
167+
get_module.return_value = module
168+
get_step.side_effect = [step1, step2]
169+
result = mas.define_steps(None)
170+
171+
for step in get_step.side_effect:
172+
assert hasattr(result, step.id)

0 commit comments

Comments
 (0)