Skip to content

Commit 272a47a

Browse files
author
DvirDukhan
committed
fixed PR comments
1 parent 6de3a1c commit 272a47a

File tree

8 files changed

+179
-187
lines changed

8 files changed

+179
-187
lines changed

docs/commands.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,7 @@ OK
456456
```
457457

458458
## AI.SCRIPTSET
459-
_This command is deprecated and will not be available in future versions. consider using AI.MODELSTORE command instead._
459+
_This command is deprecated and will not be available in future versions. consider using AI.SCRIPTSTORE command instead._
460460
The **`AI.SCRIPTSET`** command stores a [TorchScript](https://pytorch.org/docs/stable/jit.html) as the value of a key.
461461

462462
**Redis API**

src/backends/libtorch_c/torch_c.cpp

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -613,24 +613,12 @@ extern "C" const char* torchScript_FunctionName(void* scriptCtx, size_t fn_index
613613
return functions[fn_index]->name().c_str();
614614
}
615615

616-
extern "C" size_t torchScript_FunctionArgumentCount(void* scriptCtx, size_t fn_index) {
617-
ModuleContext *ctx = (ModuleContext *)scriptCtx;
618-
std::vector<torch::jit::Function*> functions = ctx->cu->get_functions();
619-
return functions[fn_index]->getSchema().arguments().size();
620-
}
621-
622616
extern "C" size_t torchScript_FunctionArgumentCountByFunctionName(void *scriptCtx, const char* functionName) {
623617
ModuleContext *ctx = (ModuleContext *)scriptCtx;
624618
torch::jit::Function* function = ctx->cu->find_function(functionName);
625619
return function->getSchema().arguments().size();
626620
}
627621

628-
extern "C" TorchScriptFunctionArgumentType torchScript_FunctionArgumentType(void* scriptCtx, size_t fn_index, size_t arg_index) {
629-
ModuleContext *ctx = (ModuleContext *)scriptCtx;
630-
std::vector<torch::jit::Function*> functions = ctx->cu->get_functions();
631-
return getArgumentType(ctx->cu->get_functions()[fn_index]->getSchema().arguments()[arg_index]);
632-
}
633-
634622
extern "C" TorchScriptFunctionArgumentType torchScript_FunctionArgumentTypeByFunctionName(void *scriptCtx, const char* functionName,
635623
size_t arg_index) {
636624
ModuleContext *ctx = (ModuleContext *)scriptCtx;

src/backends/libtorch_c/torch_c.h

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -147,15 +147,6 @@ size_t torchScript_FunctionCount(void *scriptCtx);
147147
*/
148148
const char *torchScript_FunctionName(void *scriptCtx, size_t fn_index);
149149

150-
/**
151-
* @brief Return the number of arguments in the fuction numbered fn_index in the script.
152-
*
153-
* @param scriptCtx Script context.
154-
* @param fn_index Function number.
155-
* @return size_t Number of arguments.
156-
*/
157-
size_t torchScript_FunctionArgumentCount(void *scriptCtx, size_t fn_index);
158-
159150
/**
160151
* @brief Return the number of arguments of a given fuction in the script.
161152
*
@@ -165,18 +156,6 @@ size_t torchScript_FunctionArgumentCount(void *scriptCtx, size_t fn_index);
165156
*/
166157
size_t torchScript_FunctionArgumentCountByFunctionName(void *scriptCtx, const char *functionName);
167158

168-
/**
169-
* @brief Returns the type of the argument at arg_index of function numbered fn_index in the
170-
* script.
171-
*
172-
* @param scriptCtx Script context.
173-
* @param fn_index Function number.
174-
* @param arg_index Argument number.
175-
* @return TorchScriptFunctionArgumentType The type of the argument in RedisAI enum format.
176-
*/
177-
TorchScriptFunctionArgumentType torchScript_FunctionArgumentType(void *scriptCtx, size_t fn_index,
178-
size_t arg_index);
179-
180159
/**
181160
* @brief Returns the type of the argument at arg_index of a given function in the
182161
* script.

tests/flow/test_data/redis_scripts.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,17 +87,17 @@ def test_del_key(tensors: List[Tensor], keys: List[str], args: List[str]):
8787
redis.execute("DEL", [key])
8888

8989

90-
def test_model_execute(keys:List[str]):
90+
def test_model_execute(tensors: List[Tensor], keys: List[str], args: List[str]):
9191
a = torch.tensor([[2.0, 3.0], [2.0, 3.0]])
9292
b = torch.tensor([[2.0, 3.0], [2.0, 3.0]])
9393
return redisAI.model_execute(keys[0], [a, b], 1) # assume keys[0] is the model key name saved in redis
9494

9595

96-
def test_model_execute_onnx(keys:List[str]):
96+
def test_model_execute_onnx(tensors: List[Tensor], keys: List[str], args: List[str]):
9797
a = torch.tensor([[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]])
9898
return redisAI.model_execute(keys[0], [a], 1) # assume keys[0] is the model key name saved in redis
9999

100100

101-
def test_model_execute_onnx_bad_input(keys:List[str]):
101+
def test_model_execute_onnx_bad_input(tensors: List[Tensor], keys: List[str], args: List[str]):
102102
a = torch.tensor([1.0, 2.0, 3.0, 4.0, 5.0, 6.0])
103103
return redisAI.model_execute(keys[0], [a], 1) # assume keys[0] is the model key name saved in redis

tests/flow/test_torchscript_extensions.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def __init__(self):
2121
self.con = self.env.getConnection()
2222
script = load_file_content('redis_scripts.py')
2323
ret = self.con.execute_command(
24-
'AI.SCRIPTSTORE', 'redis_scripts{1}', DEVICE, 'ENTRY_POINTS', 8, 'test_redis_error', 'test_set_key', 'test_int_set_get', 'test_int_set_incr', 'test_float_set_get', 'test_int_list', 'test_str_list', 'test_hash', 'SOURCE', script)
24+
'AI.SCRIPTSTORE', 'redis_scripts{1}', DEVICE, 'ENTRY_POINTS', 11, 'test_redis_error', 'test_set_key', 'test_int_set_get', 'test_int_set_incr', 'test_float_set_get', 'test_int_list', 'test_str_list', 'test_hash', 'test_model_execute', 'test_model_execute_onnx', 'test_model_execute_onnx_bad_input', 'SOURCE', script)
2525
self.env.assertEqual(ret, b'OK')
2626
model_tf = load_file_content('graph.pb')
2727
ret = self.con.execute_command('AI.MODELSTORE', 'model_tf{1}', 'TF', DEVICE, 'INPUTS', 2, 'a', 'b', 'OUTPUTS', 1,
@@ -86,30 +86,30 @@ def test_hash(self):
8686
def test_execute_model_via_script(self):
8787
# run torch model
8888
self.con.execute_command('AI.SCRIPTEXECUTE', 'redis_scripts{1}', 'test_model_execute', 'KEYS', 1, "model_torch{1}",
89-
'LIST_INPUTS', 1, 'model_torch{1}', 'OUTPUTS', 1, 'y{1}')
89+
'OUTPUTS', 1, 'y{1}')
9090
y = self.con.execute_command('AI.TENSORGET', 'y{1}', 'meta', 'VALUES')
9191
self.env.assertEqual(y, [b"dtype", b"FLOAT", b"shape", [2, 2], b"values", [b'4', b'6', b'4', b'6']])
9292

9393
# run tf model
9494
self.con.execute_command('AI.SCRIPTEXECUTE', 'redis_scripts{1}', 'test_model_execute', 'KEYS', 1, "model_tf{1}",
95-
'LIST_INPUTS', 1, 'model_tf{1}', 'OUTPUTS', 1, 'y{1}')
95+
'OUTPUTS', 1, 'y{1}')
9696
y = self.con.execute_command('AI.TENSORGET', 'y{1}', 'meta', 'VALUES')
9797
self.env.assertEqual(y, [b"dtype", b"FLOAT", b"shape", [2, 2], b"values", [b'4', b'9', b'4', b'9']])
9898

9999
# run onnx model
100100
self.con.execute_command('AI.SCRIPTEXECUTE', 'redis_scripts{1}', 'test_model_execute_onnx', 'KEYS', 1, "model_onnx{1}",
101-
'LIST_INPUTS', 1, 'model_onnx{1}', 'OUTPUTS', 1, 'y{1}')
101+
'OUTPUTS', 1, 'y{1}')
102102
y = self.con.execute_command('AI.TENSORGET', 'y{1}', 'meta', 'VALUES')
103103
self.env.assertEqual(y, [b"dtype", b"FLOAT", b"shape", [3, 2], b"values", [b'1', b'4', b'9', b'16', b'25', b'36']])
104104

105105
def test_execute_model_via_script_errors(self):
106106
# Trying to run a non-existing model
107107
check_error_message(self.env, self.con, "ERR model key is empty",
108-
'AI.SCRIPTEXECUTE', 'redis_scripts{1}', 'test_model_execute_onnx', 'KEYS', 1, "{1}",
109-
'LIST_INPUTS', 1, 'bad_model{1}', 'OUTPUTS', 1, 'y{1}', error_msg_is_substr=True)
108+
'AI.SCRIPTEXECUTE', 'redis_scripts{1}', 'test_model_execute_onnx', 'KEYS', 1, "bad_model{1}",
109+
'OUTPUTS', 1, 'y{1}', error_msg_is_substr=True)
110110

111111
# Runtime error while executing the model - input tensor's dim is not compatible with model.
112112
check_error_message(self.env, self.con,
113113
"Invalid rank for input: X Got: 1 Expected: 2 Please fix either the inputs or the model",
114-
'AI.SCRIPTEXECUTE', 'redis_scripts{1}', 'test_model_execute_onnx_bad_input', 'KEYS', 1, "{1}",
115-
'LIST_INPUTS', 1, 'model_onnx{1}', 'OUTPUTS', 1, 'y{1}', error_msg_is_substr=True)
114+
'AI.SCRIPTEXECUTE', 'redis_scripts{1}', 'test_model_execute_onnx_bad_input', 'KEYS', 1, "model_onnx{1}",
115+
'OUTPUTS', 1, 'y{1}', error_msg_is_substr=True)

tests/flow/tests_commands.py

Lines changed: 164 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,9 +170,172 @@ def test_keys_syntax(env):
170170
# "AI.DAGEXECUTE KEYS 1 a{1} |> AI.SCRIPTEXECUTE script{1} bar KEYS 1 a{1}")
171171

172172

173-
# Todo: this test should change once the script store command is implemented.
174173
def test_scriptstore(env):
174+
if not TEST_PT:
175+
env.debugPrint("skipping {} since TEST_PT=0".format(sys._getframe().f_code.co_name), force=True)
176+
return
177+
178+
con = env.getConnection()
179+
script = load_file_content('script.txt')
180+
181+
ret = con.execute_command('AI.SCRIPTSTORE', 'ket{1}', DEVICE, 'ENTRY_POINTS', 2, 'bar', 'bar_variadic', 'SOURCE', script)
182+
env.assertEqual(ret, b'OK')
183+
184+
ensureSlaveSynced(con, env)
185+
186+
ret = con.execute_command('AI.SCRIPTSTORE', 'ket{1}', DEVICE, 'TAG', 'asdf', 'ENTRY_POINTS', 2, 'bar', 'bar_variadic', 'SOURCE', script)
187+
env.assertEqual(ret, b'OK')
188+
189+
ensureSlaveSynced(con, env)
190+
191+
def test_scriptstore_errors(env):
192+
if not TEST_PT:
193+
env.debugPrint("skipping {} since TEST_PT=0".format(sys._getframe().f_code.co_name), force=True)
194+
return
195+
196+
con = env.getConnection()
197+
script = load_file_content('script.txt')
198+
old_script = load_file_content('old_script.txt')
199+
bad_script = load_file_content('script_bad.txt')
200+
201+
check_error_message(env, con, "wrong number of arguments for 'AI.SCRIPTSTORE' command", 'AI.SCRIPTSTORE', 'ket{1}', DEVICE, 'SOURCE', 'return 1')
202+
203+
check_error_message(env, con, "wrong number of arguments for 'AI.SCRIPTSTORE' command", 'AI.SCRIPTSTORE', 'nope')
204+
205+
check_error_message(env, con, "wrong number of arguments for 'AI.SCRIPTSTORE' command", 'AI.SCRIPTSTORE', 'nope', 'SOURCE')
206+
207+
check_error_message(env, con, "wrong number of arguments for 'AI.SCRIPTSTORE' command", 'AI.SCRIPTSTORE', 'more', DEVICE)
208+
209+
check_error_message(env, con, "Insufficient arguments, missing script entry points", 'AI.SCRIPTSTORE', 'ket{1}', DEVICE, 'NO_ENTRY_POINTS', 2, 'bar', 'bar_variadic', 'SOURCE', script)
210+
211+
check_error_message(env, con, "Non numeric entry points number provided to AI.SCRIPTSTORE command", 'AI.SCRIPTSTORE', 'ket{1}', DEVICE, 'ENTRY_POINTS', 'ENTRY_POINTS', 'bar', 'bar_variadic', 'SOURCE', script)
212+
213+
check_error_message(env, con, "Function bar1 does not exist in the given script.", 'AI.SCRIPTSTORE', 'ket{1}', DEVICE, 'ENTRY_POINTS', 2, 'bar', 'bar1', 'SOURCE', script)
214+
215+
check_error_message(env, con, "Insufficient arguments, missing script SOURCE", 'AI.SCRIPTSTORE', 'ket{1}', DEVICE, 'ENTRY_POINTS', 2, 'bar', 'bar_variadic', 'SOURCE')
216+
217+
check_error_message(env, con, "Wrong number of inputs in function bar. Expected 3 but was 2", 'AI.SCRIPTSTORE', 'ket{1}', DEVICE, 'ENTRY_POINTS', 2, 'bar', 'bar_variadic', 'SOURCE', old_script)
218+
219+
check_error_message(env, con, "Wrong inputs type in function bar. Expected signature similar to: def bar(tensors: List[Tensor], keys: List[str], args: List[str])", 'AI.SCRIPTSTORE', 'ket{1}', DEVICE, 'ENTRY_POINTS', 2, 'bar', 'bar_variadic', 'SOURCE', bad_script)
220+
221+
check_error_message(env, con, "Insufficient arguments, missing script entry points", 'AI.SCRIPTSTORE', 'ket{1}', DEVICE, 'ENTRY_POINTS', 5 , 'bar', 'bar_variadic', 'SOURCE', script)
222+
223+
224+
def test_pytrorch_scriptget_errors(env):
225+
if not TEST_PT:
226+
env.debugPrint("skipping {} since TEST_PT=0".format(sys._getframe().f_code.co_name), force=True)
227+
return
228+
229+
con = env.getConnection()
230+
231+
script = load_file_content('script.txt')
232+
233+
ret = con.execute_command('AI.SCRIPTSTORE', 'ket{1}', DEVICE, 'ENTRY_POINTS', 2, 'bar', 'bar_variadic', 'SOURCE', script)
234+
env.assertEqual(ret, b'OK')
235+
236+
ret = con.execute_command('AI.TENSORSET', 'a{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3)
237+
env.assertEqual(ret, b'OK')
238+
ret = con.execute_command('AI.TENSORSET', 'b{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3)
239+
env.assertEqual(ret, b'OK')
240+
241+
ensureSlaveSynced(con, env)
242+
243+
# ERR no script at key from SCRIPTGET
244+
check_error_message(env, con, "script key is empty", 'AI.SCRIPTGET', 'EMPTY{1}')
245+
246+
con.execute_command('SET', 'NOT_SCRIPT{1}', 'BAR')
247+
# ERR wrong type from SCRIPTGET
248+
check_error_message(env, con, "WRONGTYPE Operation against a key holding the wrong kind of value", 'AI.SCRIPTGET', 'NOT_SCRIPT{1}')
249+
250+
251+
def test_pytorch_scriptexecute_errors(env):
252+
if not TEST_PT:
253+
env.debugPrint("skipping {} since TEST_PT=0".format(sys._getframe().f_code.co_name), force=True)
254+
return
255+
175256
con = env.getConnection()
257+
176258
script = load_file_content('script.txt')
259+
177260
ret = con.execute_command('AI.SCRIPTSTORE', 'ket{1}', DEVICE, 'ENTRY_POINTS', 2, 'bar', 'bar_variadic', 'SOURCE', script)
178261
env.assertEqual(ret, b'OK')
262+
263+
ret = con.execute_command('AI.TENSORSET', 'a{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3)
264+
env.assertEqual(ret, b'OK')
265+
ret = con.execute_command('AI.TENSORSET', 'b{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3)
266+
env.assertEqual(ret, b'OK')
267+
268+
ensureSlaveSynced(con, env)
269+
270+
con.execute_command('DEL', 'EMPTY{1}')
271+
# ERR no script at key from SCRIPTEXECUTE
272+
check_error_message(env, con, "script key is empty", 'AI.SCRIPTEXECUTE', 'EMPTY{1}', 'bar', 'KEYS', 1 , '{1}', 'INPUTS', 1, 'b{1}', 'OUTPUTS', 1, 'c{1}')
273+
274+
con.execute_command('SET', 'NOT_SCRIPT{1}', 'BAR')
275+
# ERR wrong type from SCRIPTEXECUTE
276+
check_error_message(env, con, "WRONGTYPE Operation against a key holding the wrong kind of value", 'AI.SCRIPTEXECUTE', 'NOT_SCRIPT{1}', 'bar', 'KEYS', 1 , '{1}', 'INPUTS', 1, 'b{1}', 'OUTPUTS', 1, 'c{1}')
277+
278+
con.execute_command('DEL', 'EMPTY{1}')
279+
# ERR Input key is empty
280+
check_error_message(env, con, "tensor key is empty or in a different shard", 'AI.SCRIPTEXECUTE', 'ket{1}', 'bar', 'KEYS', 1 , '{1}', 'INPUTS', 2, 'EMPTY{1}', 'b{1}', 'OUTPUTS', 1, 'c{1}')
281+
282+
con.execute_command('SET', 'NOT_TENSOR{1}', 'BAR')
283+
# ERR Input key not tensor
284+
check_error_message(env, con, "WRONGTYPE Operation against a key holding the wrong kind of value", 'AI.SCRIPTEXECUTE', 'ket{1}', 'bar', 'KEYS', 1 , '{1}', 'INPUTS', 2, 'NOT_TENSOR{1}', 'b{1}', 'OUTPUTS', 1, 'c{1}')
285+
286+
check_error(env, con, 'AI.SCRIPTEXECUTE', 'ket{1}', 'bar', 'KEYS', 1 , '{1}', 'INPUTS', 1, 'b{1}', 'OUTPUTS', 1, 'c{1}')
287+
288+
check_error(env, con, 'AI.SCRIPTEXECUTE', 'ket{1}', 'KEYS', 1 , '{1}', 'INPUTS', 2, 'a{1}', 'b{1}', 'OUTPUTS', 1, 'c{1}')
289+
290+
check_error(env, con, 'AI.SCRIPTEXECUTE', 'ket{1}', 'bar', 'KEYS', 1 , '{1}', 'INPUTS', 1, 'b{1}', 'OUTPUTS')
291+
292+
check_error(env, con, 'AI.SCRIPTEXECUTE', 'ket{1}', 'bar', 'KEYS', 1 , '{1}', 'INPUTS', 'OUTPUTS')
293+
294+
check_error_message(env, con, "Invalid arguments provided to AI.SCRIPTEXECUTE", 'AI.SCRIPTEXECUTE', 'ket{1}', 'bar', 'KEYS', 1, '{1}', 'ARGS')
295+
296+
check_error_message(env, con, "KEYS scope must be provided first for AI.SCRIPTEXECUTE command", 'AI.SCRIPTEXECUTE', 'ket{1}', 'bar', 'INPUTS', 'OUTPUTS')
297+
298+
check_error_message(env, con, "Invalid value for TIMEOUT",'AI.SCRIPTEXECUTE', 'ket{1}', 'bar', 'KEYS', 1, '{1}', 'INPUTS', 2, 'a{1}', 'b{1}', 'OUTPUTS', 1, 'c{1}', 'TIMEOUT', 'TIMEOUT')
299+
300+
301+
if env.isCluster():
302+
# cross shard
303+
check_error_message(env, con, "CROSSSLOT Keys in request don't hash to the same slot", 'AI.SCRIPTEXECUTE', 'ket{1}', 'bar', 'KEYS', 1 , '{2}', 'INPUTS', 2, 'a{1}', 'b{1}', 'OUTPUTS', 1, 'c{1}')
304+
305+
# key doesn't exist
306+
check_error_message(env, con, "CROSSSLOT Keys in request don't hash to the same slot", 'AI.SCRIPTEXECUTE', 'ket{1}', 'bar', 'KEYS', 1 , '{1}', 'INPUTS', 2, 'a{1}', 'b{2}', 'OUTPUTS', 1, 'c{1}')
307+
308+
309+
def test_pytorch_scriptexecute_variadic_errors(env):
310+
if not TEST_PT:
311+
env.debugPrint("skipping {} since TEST_PT=0".format(sys._getframe().f_code.co_name), force=True)
312+
return
313+
314+
con = env.getConnection()
315+
316+
script = load_file_content('script.txt')
317+
318+
ret = con.execute_command('AI.SCRIPTSTORE', 'ket{$}', DEVICE, 'ENTRY_POINTS', 2, 'bar', 'bar_variadic', 'SOURCE', script)
319+
env.assertEqual(ret, b'OK')
320+
321+
ret = con.execute_command('AI.TENSORSET', 'a{$}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3)
322+
env.assertEqual(ret, b'OK')
323+
ret = con.execute_command('AI.TENSORSET', 'b{$}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3)
324+
env.assertEqual(ret, b'OK')
325+
326+
ensureSlaveSynced(con, env)
327+
328+
con.execute_command('DEL', 'EMPTY{$}')
329+
# ERR Variadic input key is empty
330+
check_error_message(env, con, "tensor key is empty or in a different shard", 'AI.SCRIPTEXECUTE', 'ket{$}', 'bar_variadic', 'KEYS', 1 , '{$}', 'INPUTS', 3, 'a{$}', 'EMPTY{$}', 'b{$}', 'OUTPUTS', 1, 'c{$}')
331+
332+
con.execute_command('SET', 'NOT_TENSOR{$}', 'BAR')
333+
# ERR Variadic input key not tensor
334+
check_error_message(env, con, "WRONGTYPE Operation against a key holding the wrong kind of value", 'AI.SCRIPTEXECUTE', 'ket{$}', 'bar_variadic', 'KEYS', 1 , '{$}', 'INPUTS', 3, 'a{$}', 'NOT_TENSOR{$}', 'b{$}', 'OUTPUTS', 1, 'c{$}')
335+
336+
check_error(env, con, 'AI.SCRIPTEXECUTE', 'ket{$}', 'bar_variadic', 'KEYS', 1 , '{$}', 'INPUTS', 2, 'b{$}', '${$}', 'OUTPUTS', 1, 'c{$}')
337+
338+
check_error(env, con, 'AI.SCRIPTEXECUTE', 'ket{$}', 'bar_variadic', 'KEYS', 1 , '{$}', 'INPUTS', 1, 'b{$}', 'OUTPUTS')
339+
340+
check_error(env, con, 'AI.SCRIPTEXECUTE', 'ket{$}', 'bar_variadic', 'KEYS', 1 , '{$}', 'INPUTS', 'OUTPUTS')
341+

tests/flow/tests_deprecated_commands.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,9 @@ def test_pytorch_scriptset(env):
227227
check_error(env, con, 'AI.SCRIPTSET', 'nope', 'SOURCE')
228228

229229
check_error(env, con, 'AI.SCRIPTSET', 'more', DEVICE)
230-
230+
231+
check_error(env, con, 'AI.SCRIPTSET', 'ket{1}', DEVICE, 'TAG', 'asdf')
232+
231233
script = load_file_content('script.txt')
232234

233235
ret = con.execute_command('AI.SCRIPTSET', 'ket{1}', DEVICE, 'SOURCE', script)

0 commit comments

Comments
 (0)