Commit 0ddc9733d010523531caf944d24fa474fb1d5042

Authored by Alexis Koralewski
2 parents 5299f92b 0f0a8970
Exists in dev

Merge branch 'dev' of https://gitlab.irap.omp.eu/epallier/pyros into dev

privatedev/plugin/agent/AgentBasic.py
@@ -9,7 +9,7 @@ import sys @@ -9,7 +9,7 @@ import sys
9 ##sys.path.append("..") 9 ##sys.path.append("..")
10 ###from agent.Agent import Agent, build_agent 10 ###from agent.Agent import Agent, build_agent
11 sys.path.append("../../../..") 11 sys.path.append("../../../..")
12 -from src.core.pyros_django.agent.Agent import Agent, build_agent 12 +from src.core.pyros_django.agent.Agent import Agent, CmdExceptionExecError, build_agent
13 13
14 from typing import List, Tuple, Union, Any 14 from typing import List, Tuple, Union, Any
15 15
@@ -37,9 +37,16 @@ class AgentBasic(Agent): @@ -37,9 +37,16 @@ class AgentBasic(Agent):
37 ("do_specific10", 10, 0), 37 ("do_specific10", 10, 0),
38 #("set_specific2", 5, 0), 38 #("set_specific2", 5, 0),
39 ("do_specific30", 3, 0), 39 ("do_specific30", 3, 0),
40 - ###("existing_but_unimplemented_cmd", 3, 0), 40 + ##("cmd_existing_but_unimplemented", 3, 0),
  41 + ("cmd_raising_error_exec", 3, 0)
41 ] 42 ]
42 43
  44 + # Deactivate some tests, so that test scenario runs faster during DEV
  45 + # on DEV
  46 + #COMMIT_ONLY = False
  47 + # on commit only
  48 + COMMIT_ONLY = True
  49 +
43 # @override 50 # @override
44 TEST_COMMANDS_LIST = [ 51 TEST_COMMANDS_LIST = [
45 52
@@ -54,52 +61,58 @@ class AgentBasic(Agent): @@ -54,52 +61,58 @@ class AgentBasic(Agent):
54 61
55 # do_restart 62 # do_restart
56 63
57 - ("self do_restart now", 200, 'RESTARTING now', Agent.CMD_STATUS.CMD_EXECUTED), 64 + (COMMIT_ONLY, "self do_restart now", 200, 'RESTARTING now', Agent.CMD_STATUS.CMD_EXECUTED),
58 #("self do_stop", 200, 'STOPPING asap', Agent.CMD_STATUS.CMD_EXECUTED), 65 #("self do_stop", 200, 'STOPPING asap', Agent.CMD_STATUS.CMD_EXECUTED),
59 66
60 - # ------------------------------  
61 - # ------ A - ERROR CASES -------  
62 - # ------------------------------ 67 + # ----------------------------------------------------
  68 + # ------ A - ERROR CASES - from PENDING status -------
  69 + # ----------------------------------------------------
63 70
64 # - Error case 1 - unimplemented command in agent specific commands list 71 # - Error case 1 - unimplemented command in agent specific commands list
65 - # get_specific_cmds KO (with existing_but_unimplemented_cmd)  
66 - #("self get_specific_cmds", 200, 'EXCEPTION - One specific cmd is unimplemented: existing_but_unimplemented_cmd', Agent.CMD_STATUS.CMD_EXEC_ERROR), 72 + # get_specific_cmds KO (with cmd_existing_but_unimplemented)
  73 + ##("self get_specific_cmds", 200, 'EXCEPTION - One specific cmd is unimplemented: cmd_existing_but_unimplemented', Agent.CMD_STATUS.CMD_EXEC_ERROR),
67 # get_specific_cmds OK (all commands implemented) 74 # get_specific_cmds OK (all commands implemented)
68 - ("self get_specific_cmds", 200, 'do_specific10(arg1:int,arg2:int,arg3:float,arg4:str,arg5:typing.Tuple[int, str, int],arg6:typing.List[int]);do_specific30()', Agent.CMD_STATUS.CMD_EXECUTED), 75 + (COMMIT_ONLY, " self get_specific_cmds ", 200, 'do_specific10(arg1:int,arg2:int,arg3:float,arg4:str,arg5:typing.Tuple[int, str, int],arg6:typing.List[int]);do_specific30();cmd_raising_error_exec()', Agent.CMD_STATUS.CMD_EXECUTED),
69 76
70 # - Error case 2 - CMD_INVALID 77 # - Error case 2 - CMD_INVALID
71 # unknwon command 78 # unknwon command
72 ##FIXME: ("self unexisting_cmd", 200, '', Agent.CMD_STATUS.CMD_UNKNOWN), 79 ##FIXME: ("self unexisting_cmd", 200, '', Agent.CMD_STATUS.CMD_UNKNOWN),
73 - ("self unexisting_cmd", 200, '', Agent.CMD_STATUS.CMD_INVALID), 80 + (COMMIT_ONLY, "self cmd_unexisting", 200, 'EXCEPTION on command cmd_unexisting: Unknown command', Agent.CMD_STATUS.CMD_INVALID),
74 # bad parameters (missing or too many, or bad type) 81 # bad parameters (missing or too many, or bad type)
75 # missing args 82 # missing args
76 - ("self do_specific10", 200, '', Agent.CMD_STATUS.CMD_INVALID), 83 + (COMMIT_ONLY, "self do_specific10", 200, 'EXCEPTION on command do_specific10: Command has bad, missing, or too many argument(s)', Agent.CMD_STATUS.CMD_INVALID),
77 # missing args 84 # missing args
78 - ("self do_specific10 2", 200, '', Agent.CMD_STATUS.CMD_INVALID), 85 + (COMMIT_ONLY, "self do_specific10 2 ", 200, None, Agent.CMD_STATUS.CMD_INVALID),
79 # - too many args 86 # - too many args
80 - ("self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9] 4", 200, '', Agent.CMD_STATUS.CMD_INVALID), 87 + (COMMIT_ONLY, "self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9] 4", 200, None, Agent.CMD_STATUS.CMD_INVALID),
81 # - bad type 88 # - bad type
82 - ("self do_specific10 'toto' 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, '', Agent.CMD_STATUS.CMD_INVALID), 89 + (COMMIT_ONLY, "self do_specific10 'toto' 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, None, Agent.CMD_STATUS.CMD_INVALID),
83 # - OK 90 # - OK
84 #("self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, '16.5', Agent.CMD_STATUS.CMD_EXECUTED), 91 #("self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, '16.5', Agent.CMD_STATUS.CMD_EXECUTED),
85 92
86 # - Error case 3 - CMD_UNIMPLEMENTED 93 # - Error case 3 - CMD_UNIMPLEMENTED
87 - ("self existing_but_unimplemented_cmd", 200, '', Agent.CMD_STATUS.CMD_UNIMPLEMENTED), 94 + ##("self cmd_existing_but_unimplemented", 200, None, Agent.CMD_STATUS.CMD_UNIMPLEMENTED),
88 95
89 # - Error case 4 - CMD_EXPIRED 96 # - Error case 4 - CMD_EXPIRED
90 # This command has a validity of 0s and thus should be tagged as "expired" 97 # This command has a validity of 0s and thus should be tagged as "expired"
91 - ("self set_mode ATTENTIVE", 0, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXPIRED), 98 + (COMMIT_ONLY, "self set_mode ATTENTIVE", 0, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXPIRED),
92 99
93 # - Error case 5 - CMD_SKIPPED 100 # - Error case 5 - CMD_SKIPPED
94 # a) In mode ROUTINE, SPECIFIC commands should be skipped as the agent is not ATTENTIVE 101 # a) In mode ROUTINE, SPECIFIC commands should be skipped as the agent is not ATTENTIVE
95 - ("self set_mode ROUTINE", 200, "MODE is ROUTINE", Agent.CMD_STATUS.CMD_EXECUTED),  
96 - ("self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, None, Agent.CMD_STATUS.CMD_SKIPPED), 102 + (COMMIT_ONLY, "self set_mode ROUTINE", 200, "MODE is ROUTINE", Agent.CMD_STATUS.CMD_EXECUTED),
  103 + (COMMIT_ONLY, "self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, None, Agent.CMD_STATUS.CMD_SKIPPED),
97 # b) Back to mode ATTENTIVE, SPECIFIC commands should be executed 104 # b) Back to mode ATTENTIVE, SPECIFIC commands should be executed
98 - ("self set_mode ATTENTIVE", 200, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXECUTED),  
99 - ("self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, '16.5', Agent.CMD_STATUS.CMD_EXECUTED), 105 + (COMMIT_ONLY, "self set_mode ATTENTIVE", 200, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXECUTED),
  106 + (COMMIT_ONLY, "self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, '16.5', Agent.CMD_STATUS.CMD_EXECUTED),
  107 +
  108 + # ----------------------------------------------------
  109 + # ------ B - ERROR CASES - from RUNNING status -------
  110 + # ----------------------------------------------------
  111 +
  112 + (True, "self cmd_raising_error_exec", 200, "EXCEPTION on command cmd_raising_error_exec: Error during Execution", Agent.CMD_STATUS.CMD_EXEC_ERROR),
100 113
101 # ------------------------------ 114 # ------------------------------
102 - # ------ B - NORMAL CASES ------- 115 + # ------ C - NORMAL CASES -------
103 # ------------------------------ 116 # ------------------------------
104 117
105 # do_restart => #iteration should restart at 1 (so at least it should be <= 4) 118 # do_restart => #iteration should restart at 1 (so at least it should be <= 4)
@@ -129,13 +142,13 @@ class AgentBasic(Agent): @@ -129,13 +142,13 @@ class AgentBasic(Agent):
129 # ------------------------------- 142 # -------------------------------
130 143
131 # Agent general command 144 # Agent general command
132 - ("self set_mode ROUTINE", 200, "MODE is ROUTINE", Agent.CMD_STATUS.CMD_EXECUTED),  
133 - ("self get_mode", 200, "MODE is ROUTINE", Agent.CMD_STATUS.CMD_EXECUTED),  
134 - ("self set_mode ATTENTIVE", 200, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXECUTED),  
135 - ("self get_mode", 200, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXECUTED), 145 + (COMMIT_ONLY, "self set_mode ROUTINE", 200, "MODE is ROUTINE", Agent.CMD_STATUS.CMD_EXECUTED),
  146 + (COMMIT_ONLY, "self get_mode", 200, "MODE is ROUTINE", Agent.CMD_STATUS.CMD_EXECUTED),
  147 + (COMMIT_ONLY, "self set_mode ATTENTIVE", 200, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXECUTED),
  148 + (COMMIT_ONLY, "self get_mode", 200, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXECUTED),
136 149
137 # End test 150 # End test
138 - ("self do_stop", 200, 'STOPPING asap', Agent.CMD_STATUS.CMD_EXECUTED), 151 + (True, "self do_stop", 200, 'STOPPING asap', Agent.CMD_STATUS.CMD_EXECUTED),
139 152
140 ] 153 ]
141 154
@@ -324,6 +337,9 @@ class AgentBasic(Agent): @@ -324,6 +337,9 @@ class AgentBasic(Agent):
324 #def do_specific1(self, arg1:int, arg2:int=2, arg3:int=3) -> int: 337 #def do_specific1(self, arg1:int, arg2:int=2, arg3:int=3) -> int:
325 #def do_specific1(self, arg1:int, arg2:int=2, arg3:float=3.1, arg4:list=[1,2,3]) -> float: 338 #def do_specific1(self, arg1:int, arg2:int=2, arg3:float=3.1, arg4:list=[1,2,3]) -> float:
326 339
  340 + def cmd_raising_error_exec(self):
  341 + raise CmdExceptionExecError(self.CURRENT_CMD)
  342 +
327 def do_specific10(self, 343 def do_specific10(self,
328 arg1:int, 344 arg1:int,
329 arg2:int, 345 arg2:int,
src/core/pyros_django/agent/Agent.py
@@ -41,7 +41,7 @@ and execute them on reception at each iteration : @@ -41,7 +41,7 @@ and execute them on reception at each iteration :
41 41
42 # For cmd parsing 42 # For cmd parsing
43 from array import array 43 from array import array
44 -from typing import List, Tuple, Union, Any 44 +from typing import List, Tuple, Union, Any, Optional
45 import ast 45 import ast
46 from inspect import signature 46 from inspect import signature
47 47
@@ -127,6 +127,7 @@ import random @@ -127,6 +127,7 @@ import random
127 import threading 127 import threading
128 #import multiprocessing 128 #import multiprocessing
129 import time 129 import time
  130 +import re
130 ''' 131 '''
131 from threading import Thread 132 from threading import Thread
132 import socket 133 import socket
@@ -259,9 +260,21 @@ class StoppableThreadEvenWhenSleeping(threading.Thread): @@ -259,9 +260,21 @@ class StoppableThreadEvenWhenSleeping(threading.Thread):
259 class CmdException(Exception): 260 class CmdException(Exception):
260 ''' Base class for all Agent command exceptions ''' 261 ''' Base class for all Agent command exceptions '''
261 # pass 262 # pass
262 - def __init__( self, cmd: Union[AgentCmd,str] ): 263 + def __init__( self, cmd:Union[AgentCmd,str], msg:str=None):
263 self.cmd = cmd 264 self.cmd = cmd
  265 + self._msg = msg
264 self.cmd_name = cmd if isinstance(cmd,str) else cmd.name 266 self.cmd_name = cmd if isinstance(cmd,str) else cmd.name
  267 + @property
  268 + def msg(self):
  269 + msg = "EXCEPTION on command "+self.cmd_name
  270 + return msg if not self._msg else msg+': '+self._msg
  271 + # Default message if print exception
  272 + def __str__(self):
  273 + return self.msg
  274 + '''
  275 + msg = "EXCEPTION on command "+self.cmd_name
  276 + return msg if not self.msg else msg+': '+self.msg
  277 + '''
265 ''' 278 '''
266 def __str__(self): 279 def __str__(self):
267 return f"The Agent command '{self.cmd.name}' is unknown to the agent" 280 return f"The Agent command '{self.cmd.name}' is unknown to the agent"
@@ -269,41 +282,57 @@ class CmdException(Exception): @@ -269,41 +282,57 @@ class CmdException(Exception):
269 ''' 282 '''
270 283
271 # --- CMD PENDING (non running) EXCEPTIONS --- 284 # --- CMD PENDING (non running) EXCEPTIONS ---
272 -class CmdUnknownException(CmdException): 285 +
  286 +# @Override
  287 +class CmdExceptionUnknown(CmdException):
273 ''' Raised when a PENDING (non running) Agent (specific) cmd is NOT known by the agent ''' 288 ''' Raised when a PENDING (non running) Agent (specific) cmd is NOT known by the agent '''
274 - def __str__(self):  
275 - return f"The Agent command '{self.cmd_name}' is unknown to the agent"  
276 - #return f"({type(self).__name__}): Device Generic command has no implementation in the controller" 289 + # @Override
  290 + def __init__( self, cmd, msg:str=None):
  291 + super().__init__(cmd, msg if msg else "Unknown command")
  292 + #def __str__(self): return self.msg if self.msg else f"The Agent command '{self.cmd_name}' is unknown to the agent"
277 293
278 -class CmdUnimplementedException(CmdException): 294 +# @Override
  295 +class CmdExceptionUnimplemented(CmdException):
279 ''' Raised when a PENDING (non running) Agent Specific cmd is known by the agent but not implemented ''' 296 ''' Raised when a PENDING (non running) Agent Specific cmd is known by the agent but not implemented '''
280 - def __str__(self):  
281 - return f"The Agent command '{self.cmd_name}' is known by the agent but not implemented"  
282 - #return f"({type(self).__name__}): Device Generic command has no implementation in the controller" 297 + # @Override
  298 + def __init__( self, cmd, msg:str=None):
  299 + super().__init__(cmd, msg if msg else "Command is known by the agent but not implemented")
  300 + #def __str__(self): return f"The Agent command '{self.cmd_name}' is known by the agent but not implemented"
283 301
284 -class CmdBadArgsException(CmdException): 302 +# @Override
  303 +class CmdExceptionBadArgs(CmdException):
285 ''' Raised when a PENDING (non running) Agent cmd has bad, missing, or too many argument(s) ''' 304 ''' Raised when a PENDING (non running) Agent cmd has bad, missing, or too many argument(s) '''
286 - def __str__(self):  
287 - return f"The Agent command '{self.cmd_name}' has bad, missing, or too many argument(s)"  
288 - #return f"({type(self).__name__}): Device Generic command has no implementation in the controller" 305 + # @Override
  306 + def __init__( self, cmd, msg:str=None):
  307 + super().__init__(cmd, msg if msg else "Command has bad, missing, or too many argument(s)")
  308 + #def __str__(self): return f"The Agent command '{self.cmd_name}' has bad, missing, or too many argument(s)"
289 309
290 310
291 # --- CMD RUNNING EXCEPTIONS --- 311 # --- CMD RUNNING EXCEPTIONS ---
292 312
293 -class CmdExecErrorException(CmdException): 313 +# @Override
  314 +class CmdExceptionExecError(CmdException):
294 ''' Raised when a RUNNING Agent cmd has had a running error ''' 315 ''' Raised when a RUNNING Agent cmd has had a running error '''
295 - def __str__(self):  
296 - return f"The running Agent command '{self.cmd_name}' has had an error (during execution)" 316 + # @Override
  317 + def __init__( self, cmd, msg:str=None):
  318 + super().__init__(cmd, msg if msg else "Error during Execution")
  319 + #def __str__(self): return f"The running Agent command '{self.cmd_name}' has had an error (during execution)"
297 320
298 -class CmdExecTimeoutException(CmdException): 321 +# @Override
  322 +class CmdExceptionExecTimeout(CmdException):
299 ''' Raised when a RUNNING Agent cmd is timeout ''' 323 ''' Raised when a RUNNING Agent cmd is timeout '''
300 - def __str__(self):  
301 - return f"The running Agent command '{self.cmd_name}' is timeout" 324 + # @Override
  325 + def __init__( self, cmd, msg:str=None):
  326 + super().__init__(cmd, msg if msg else "Execution is TIMEOUT")
  327 + #def __str__(self): return f"The running Agent command '{self.cmd_name}' is timeout"
302 328
303 -class CmdExecKilledException(CmdException): 329 +# @Override
  330 +class CmdExceptionExecKilled(CmdException):
304 ''' Raised when a RUNNING Agent cmd has been aborted (by another agent) ''' 331 ''' Raised when a RUNNING Agent cmd has been aborted (by another agent) '''
305 - def __str__(self):  
306 - return f"The running Agent command '{self.cmd_name}' has been killed (by another agent)" 332 + # @Override
  333 + def __init__( self, cmd, msg:str=None):
  334 + super().__init__(cmd, msg if msg else "Command was KILLED during Execution (by another agent")
  335 + #def __str__(self): return f"The running Agent command '{self.cmd_name}' has been killed (by another agent)"
307 336
308 ### 337 ###
309 # ================================================================= 338 # =================================================================
@@ -390,6 +419,8 @@ class Agent: @@ -390,6 +419,8 @@ class Agent:
390 # 419 #
391 # Format : List of tuples (command, validity, expected_res, expected_status), with : 420 # Format : List of tuples (command, validity, expected_res, expected_status), with :
392 # 421 #
  422 + # - DO_IT : execute this command yes (true) or no (false) ? (yes by default)
  423 +
393 # - command : the format is "recipient cmd args", with : 424 # - command : the format is "recipient cmd args", with :
394 # - recipient : name of the Agent that the command is to be sent to (use "self" to mean himself) 425 # - recipient : name of the Agent that the command is to be sent to (use "self" to mean himself)
395 # - cmd : the command name 426 # - cmd : the command name
@@ -407,11 +438,12 @@ class Agent: @@ -407,11 +438,12 @@ class Agent:
407 # - "self set_state ATTENTIVE" => means to send the command "set_state ATTENTIVE" to MYSELF 438 # - "self set_state ATTENTIVE" => means to send the command "set_state ATTENTIVE" to MYSELF
408 # - "self do_restart_loop" => means to send the command "do_restart_loop" to MYSELF (no args) 439 # - "self do_restart_loop" => means to send the command "do_restart_loop" to MYSELF (no args)
409 # 440 #
410 - TEST_COMMANDS_LIST: List[ Tuple[ str, int, Union[str,None], Union[int,None] ] ] = [ 441 + #TEST_COMMANDS_LIST: List[ Tuple[ str, int, Union[str,None], Union[int,None], Optional[bool] ] ] = [
  442 + TEST_COMMANDS_LIST: List[ Tuple[bool, str, int, Optional[str], Optional[int]] ] = [
411 443
412 # Format : ("self cmd_name cmd_args", timeout, "expected_result", expected_status), 444 # Format : ("self cmd_name cmd_args", timeout, "expected_result", expected_status),
413 #("self do_stop now", 200, '15.5', None), 445 #("self do_stop now", 200, '15.5', None),
414 - ("self do_specific1 1 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, '15.5', None), 446 + (True, "self do_specific1 1 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, '15.5', None),
415 447
416 # 1) First, 3 EXCEPTION CASES (uncomment to activate exception) 448 # 1) First, 3 EXCEPTION CASES (uncomment to activate exception)
417 # Each of these lines will stop execution with an exception 449 # Each of these lines will stop execution with an exception
@@ -435,38 +467,38 @@ class Agent: @@ -435,38 +467,38 @@ class Agent:
435 # ------------------------------- 467 # -------------------------------
436 468
437 # This command has a validity of 0s and thus should be tagged as "expired" 469 # This command has a validity of 0s and thus should be tagged as "expired"
438 - ("self set_mode ATTENTIVE", 0, "MODE is ATTENTIVE", CMD_STATUS.CMD_EXPIRED), 470 + (True, "self set_mode ATTENTIVE", 0, "MODE is ATTENTIVE", CMD_STATUS.CMD_EXPIRED),
439 471
440 # Agent general command 472 # Agent general command
441 - ("self set_mode ATTENTIVE", 200, "MODE is ATTENTIVE", CMD_STATUS.CMD_EXECUTED), 473 + (True, "self set_mode ATTENTIVE", 200, "MODE is ATTENTIVE", CMD_STATUS.CMD_EXECUTED),
442 # => should get "ATTENTIVE" 474 # => should get "ATTENTIVE"
443 - ("self get_mode", 100, "MODE is ATTENTIVE", None), 475 + (True, "self get_mode", 100, "MODE is ATTENTIVE", None),
444 476
445 # => should get "7" 477 # => should get "7"
446 - ("self do_eval 3+5-1", 200, '7', None), 478 + (True, "self do_eval 3+5-1", 200, '7', None),
447 479
448 # END, will not go further 480 # END, will not go further
449 #("self do_exit", 2, "STOPPING"), 481 #("self do_exit", 2, "STOPPING"),
450 482
451 # Agent specific commands => should be executed 483 # Agent specific commands => should be executed
452 - ("self do_specific3", 200, '', None),  
453 - ("self do_exit", 500, "STOPPING", None),  
454 - ("self do_specific1 1 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, '15.5', None), 484 + (True, "self do_specific3", 200, '', None),
  485 + (True, "self do_exit", 500, "STOPPING", None),
  486 + (True, "self do_specific1 1 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, '15.5', None),
455 487
456 488
457 - ("self set_mode ROUTINE", 200, "MODE is ROUTINE", None), 489 + (True, "self set_mode ROUTINE", 200, "MODE is ROUTINE", None),
458 # => should get "ROUTINE" 490 # => should get "ROUTINE"
459 - ("self get_mode", 200, "MODE is ROUTINE", None), 491 + (True, "self get_mode", 200, "MODE is ROUTINE", None),
460 # Agent specific command => should be skipped (because not ATTENTIVE) 492 # Agent specific command => should be skipped (because not ATTENTIVE)
461 - ("self do_specific1 1 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, "SKIPPED", None), 493 + (True, "self do_specific1 1 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, "SKIPPED", None),
462 494
463 # From now on, should not run anymore process_before/after 495 # From now on, should not run anymore process_before/after
464 # => and should skip next specific commands 496 # => and should skip next specific commands
465 - ("self set_mode IDLE", 200, "MODE is IDLE", None), 497 + (True, "self set_mode IDLE", 200, "MODE is IDLE", None),
466 # => should get "IDLE" 498 # => should get "IDLE"
467 - ("self get_mode", 200, "MODE is IDLE", None), 499 + (True, "self get_mode", 200, "MODE is IDLE", None),
468 # Agent specific command => should be skipped (because not ATTENTIVE) 500 # Agent specific command => should be skipped (because not ATTENTIVE)
469 - ("self do_specific1 1 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, 'SKIPPED', None), 501 + (True, "self do_specific1 1 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, 'SKIPPED', None),
470 502
471 # TODO: test priority commands : do_abort, do_flush_cmds, ... 503 # TODO: test priority commands : do_abort, do_flush_cmds, ...
472 # - Stop executing new commands (just let them accumulate) 504 # - Stop executing new commands (just let them accumulate)
@@ -483,10 +515,10 @@ class Agent: @@ -483,10 +515,10 @@ class Agent:
483 ##("self do_resume_exec",), 515 ##("self do_resume_exec",),
484 516
485 # Restart the restart loop (from init()) 517 # Restart the restart loop (from init())
486 - ("self do_restart", 200, "RESTARTING", None), 518 + (True, "self do_restart", 200, "RESTARTING", None),
487 519
488 # Now stop 520 # Now stop
489 - ("self do_exit", 200, "STOPPING", None), 521 + (True, "self do_exit", 200, "STOPPING", None),
490 522
491 ''' 523 '''
492 # specific0 not_executed_because_idle 524 # specific0 not_executed_because_idle
@@ -1082,27 +1114,41 @@ class Agent: @@ -1082,27 +1114,41 @@ class Agent:
1082 #print(cmd) 1114 #print(cmd)
1083 except ( 1115 except (
1084 # PENDING (non running) cmd exceptions 1116 # PENDING (non running) cmd exceptions
1085 - CmdUnimplementedException, CmdBadArgsException, CmdUnknownException, 1117 + CmdExceptionUnknown, CmdExceptionUnimplemented, CmdExceptionBadArgs,
1086 # RUNNING cmd exceptions 1118 # RUNNING cmd exceptions
1087 - CmdExecErrorException, CmdExecTimeoutException, CmdExecKilledException 1119 + CmdExceptionExecError, CmdExceptionExecKilled, CmdExceptionExecTimeout,
1088 ) as e : 1120 ) as e :
1089 - #print(e)  
1090 - log.error(f"EXCEPTION on Agent command '{e.cmd_name}'") 1121 + print(e)
  1122 + log.error(e)
  1123 + #log.error(f"EXCEPTION on Agent command '{e.cmd_name}'")
1091 if isinstance(e.cmd, AgentCmd) : 1124 if isinstance(e.cmd, AgentCmd) :
1092 cmd = e.cmd 1125 cmd = e.cmd
1093 - if type(e) is CmdUnimplementedException:  
1094 - if cmd.name != "get_specific_cmds":  
1095 - cmd.set_as_unimplemented("EXCEPTION: command known but unimplemented")  
1096 - elif type(e) in (CmdBadArgsException, CmdUnknownException):  
1097 - # set back to "pending" if ever was wrongly marked "running"  
1098 - #cmd.set_as_pending()  
1099 - cmd.set_as_invalid("EXCEPTION: command unknown or bad args")  
1100 - # Execution Exception  
1101 - elif type(e) != CmdExecErrorException:  
1102 - cmd.set_result("EXCEPTION: Problem during execution") 1126 + # - Exception from PENGING
  1127 + if type(e) in (CmdExceptionUnknown, CmdExceptionUnimplemented, CmdExceptionBadArgs):
  1128 + if type(e) is CmdExceptionUnimplemented:
  1129 + if cmd.name != "get_specific_cmds":
  1130 + cmd.set_as_unimplemented(e.msg)
  1131 + #cmd.set_as_unimplemented("EXCEPTION: Command known but unimplemented")
  1132 + else:
  1133 + # set back to "pending" if ever was wrongly marked "running"
  1134 + #cmd.set_as_pending()
  1135 + cmd.set_as_invalid(e.msg)
  1136 + #cmd.set_as_invalid("EXCEPTION: Command unknown or bad args")
  1137 + # - Exception from RUNNING (Execution Exception)
  1138 + else:
  1139 + if type(e) == CmdExceptionExecError:
  1140 + print(e)
  1141 + cmd.set_as_exec_error(e.msg)
  1142 + print(e)
  1143 + #cmd.set_as_exec_error(e.msg if e.msg else "EXCEPTION: Error during execution")
  1144 + else:
  1145 + #FIXME: S'assurer que cmd.set_as_killed() or cmd.set_as_timeout() a bien รฉtรฉ fait !!!
  1146 + cmd.set_result(e.msg)
  1147 + #cmd.set_result("EXCEPTION: Problem during execution")
1103 # isinstance(e.cmd, str) 1148 # isinstance(e.cmd, str)
1104 else: 1149 else:
1105 - raise Exception("Abnormal error case...") 1150 + raise CmdException(cmd, "EXCEPTION: Abnormal error case...")
  1151 + #raise Exception("EXCEPTION: Abnormal error case...")
1106 1152
1107 1153
1108 1154
@@ -1251,7 +1297,7 @@ class Agent: @@ -1251,7 +1297,7 @@ class Agent:
1251 if self._is_agent_general_cmd(cmd): 1297 if self._is_agent_general_cmd(cmd):
1252 try: 1298 try:
1253 self._process_agent_general_cmd(cmd) 1299 self._process_agent_general_cmd(cmd)
1254 - except (CmdUnimplementedException, CmdBadArgsException) : 1300 + except (CmdExceptionUnimplemented, CmdExceptionBadArgs) :
1255 # cmd should not be set as "running" 1301 # cmd should not be set as "running"
1256 cmd.set_as_pending() 1302 cmd.set_as_pending()
1257 # These exceptions are managed at higher level : 1303 # These exceptions are managed at higher level :
@@ -1269,7 +1315,7 @@ class Agent: @@ -1269,7 +1315,7 @@ class Agent:
1269 self._process_agent_specific_cmd(cmd) 1315 self._process_agent_specific_cmd(cmd)
1270 #self._exec_agent_cmd(cmd) 1316 #self._exec_agent_cmd(cmd)
1271 #except AttributeError as e: 1317 #except AttributeError as e:
1272 - except (CmdUnimplementedException, CmdBadArgsException) as e: 1318 + except (CmdExceptionUnimplemented, CmdExceptionBadArgs) as e:
1273 # cmd should not be set as "running" 1319 # cmd should not be set as "running"
1274 #cmd.set_as_pending() 1320 #cmd.set_as_pending()
1275 # These exceptions are managed at higher level : 1321 # These exceptions are managed at higher level :
@@ -1291,7 +1337,7 @@ class Agent: @@ -1291,7 +1337,7 @@ class Agent:
1291 ##cmd.set_as_skipped("ERROR: INVALID AGENT COMMAND") 1337 ##cmd.set_as_skipped("ERROR: INVALID AGENT COMMAND")
1292 ##self._cleanup_before_exit() 1338 ##self._cleanup_before_exit()
1293 ##raise UnknownCmdException(cmd.name) 1339 ##raise UnknownCmdException(cmd.name)
1294 - raise CmdUnknownException(cmd) 1340 + raise CmdExceptionUnknown(cmd)
1295 1341
1296 #print() 1342 #print()
1297 #log.info("*"*10 + " NEXT COMMAND PROCESSING (END) " + "*"*10 + "\n") 1343 #log.info("*"*10 + " NEXT COMMAND PROCESSING (END) " + "*"*10 + "\n")
@@ -1447,7 +1493,7 @@ class Agent: @@ -1447,7 +1493,7 @@ class Agent:
1447 try: 1493 try:
1448 f = getattr(self, cmd_name) 1494 f = getattr(self, cmd_name)
1449 except AttributeError: 1495 except AttributeError:
1450 - raise CmdUnimplementedException(cmd_name) from None 1496 + raise CmdExceptionUnimplemented(cmd_name) from None
1451 args = signature(f) 1497 args = signature(f)
1452 #specific_commands += str(args) 1498 #specific_commands += str(args)
1453 specific_commands += "(" 1499 specific_commands += "("
@@ -1485,9 +1531,9 @@ class Agent: @@ -1485,9 +1531,9 @@ class Agent:
1485 1531
1486 def get_status(self): 1532 def get_status(self):
1487 return self.status 1533 return self.status
1488 - # @deprecated 1534 +
1489 def get_state(self): 1535 def get_state(self):
1490 - return self.get_status() 1536 + return f"MODE {self.get_mode()} ; STATUS {self.get_status()} ; ITERATION #{self._iter_num}"
1491 1537
1492 def _set_status(self, status:str): 1538 def _set_status(self, status:str):
1493 #self.printd(f"[{status}] (switching from status {self.status})") 1539 #self.printd(f"[{status}] (switching from status {self.status})")
@@ -1797,7 +1843,7 @@ class Agent: @@ -1797,7 +1843,7 @@ class Agent:
1797 which is relevant to this agent. 1843 which is relevant to this agent.
1798 Commands are read in chronological order 1844 Commands are read in chronological order
1799 """ 1845 """
1800 - self._set_status(self.AGT_STATUS.IN_GET_NEXT_CMD) 1846 + self._set_and_log_status(self.AGT_STATUS.IN_GET_NEXT_CMD)
1801 log.info("Looking for a new command to process (sent by another agent):") 1847 log.info("Looking for a new command to process (sent by another agent):")
1802 1848
1803 # 1) Get all pending commands for me (return if None) 1849 # 1) Get all pending commands for me (return if None)
@@ -2046,12 +2092,12 @@ class Agent: @@ -2046,12 +2092,12 @@ class Agent:
2046 2092
2047 elif cmd_name == "set_mode": 2093 elif cmd_name == "set_mode":
2048 #if not cmd_args: raise ValueError() 2094 #if not cmd_args: raise ValueError()
2049 - if not cmd_args: raise CmdBadArgsException(cmd) 2095 + if not cmd_args: raise CmdExceptionBadArgs(cmd)
2050 mode = cmd_args[0] 2096 mode = cmd_args[0]
2051 if mode == "IDLE": self.set_idle() 2097 if mode == "IDLE": self.set_idle()
2052 elif mode == "ROUTINE": self.set_routine() 2098 elif mode == "ROUTINE": self.set_routine()
2053 elif mode == "ATTENTIVE": self.set_attentive() 2099 elif mode == "ATTENTIVE": self.set_attentive()
2054 - else: raise CmdBadArgsException(cmd) 2100 + else: raise CmdExceptionBadArgs(cmd)
2055 #cmd.set_result("I am now " + state) 2101 #cmd.set_result("I am now " + state)
2056 result = "MODE is " + mode 2102 result = "MODE is " + mode
2057 #time.sleep(1) 2103 #time.sleep(1)
@@ -2066,7 +2112,7 @@ class Agent: @@ -2066,7 +2112,7 @@ class Agent:
2066 2112
2067 elif cmd_name == "do_eval": 2113 elif cmd_name == "do_eval":
2068 #if not cmd_args: raise ValueError() 2114 #if not cmd_args: raise ValueError()
2069 - if not cmd_args: raise CmdBadArgsException(cmd) 2115 + if not cmd_args: raise CmdExceptionBadArgs(cmd)
2070 #cmd.set_result(eval(cmd_args)) 2116 #cmd.set_result(eval(cmd_args))
2071 #result = eval(cmd_args) 2117 #result = eval(cmd_args)
2072 result = self.do_eval(cmd_args[0]) 2118 result = self.do_eval(cmd_args[0])
@@ -2075,10 +2121,10 @@ class Agent: @@ -2075,10 +2121,10 @@ class Agent:
2075 # CmdUnimplementedException if one specific command (in the list) is unknown 2121 # CmdUnimplementedException if one specific command (in the list) is unknown
2076 try: 2122 try:
2077 result = self.get_specific_cmds() 2123 result = self.get_specific_cmds()
2078 - except CmdUnimplementedException as e: 2124 + except CmdExceptionUnimplemented as e:
2079 # raise CmdUnimplementedException("get_specific_cmds.unknown_cmd_name") 2125 # raise CmdUnimplementedException("get_specific_cmds.unknown_cmd_name")
2080 - cmd.set_as_exec_error("EXCEPTION - One specific cmd is unimplemented: "+e.cmd_name)  
2081 - raise CmdExecErrorException(cmd) from None 2126 + #cmd.set_as_exec_error("EXCEPTION - One specific cmd is unimplemented: "+e.cmd_name)
  2127 + raise CmdExceptionExecError(cmd, "EXCEPTION - One specific cmd is unimplemented => "+e.cmd_name) from None
2082 2128
2083 cmd.set_as_processed(result) 2129 cmd.set_as_processed(result)
2084 log.info("...Agent level GENERAL cmd has been executed") 2130 log.info("...Agent level GENERAL cmd has been executed")
@@ -2114,7 +2160,7 @@ class Agent: @@ -2114,7 +2160,7 @@ class Agent:
2114 # This can raise an exception (caught by this method caller) 2160 # This can raise an exception (caught by this method caller)
2115 try: 2161 try:
2116 res = self._exec_cmd_from_its_name(cmd) 2162 res = self._exec_cmd_from_its_name(cmd)
2117 - except (CmdUnimplementedException, CmdBadArgsException) as e: 2163 + except (CmdExceptionUnimplemented, CmdExceptionBadArgs) as e:
2118 ##cmd.set_as_pending() 2164 ##cmd.set_as_pending()
2119 # These exceptions are managed at higher level : 2165 # These exceptions are managed at higher level :
2120 raise 2166 raise
@@ -2160,7 +2206,7 @@ class Agent: @@ -2160,7 +2206,7 @@ class Agent:
2160 methods_list = [method for method in dir(self) if callable(getattr(self, method))] 2206 methods_list = [method for method in dir(self) if callable(getattr(self, method))]
2161 #print(methodsList) 2207 #print(methodsList)
2162 func = cmd.name 2208 func = cmd.name
2163 - if func not in methods_list: raise CmdUnimplementedException(cmd) 2209 + if func not in methods_list: raise CmdExceptionUnimplemented(cmd)
2164 ##f = getattr(self, func) 2210 ##f = getattr(self, func)
2165 ###print(func, ' => ', signature(f)) 2211 ###print(func, ' => ', signature(f))
2166 2212
@@ -2188,9 +2234,10 @@ class Agent: @@ -2188,9 +2234,10 @@ class Agent:
2188 return getattr(self, func)(*args) 2234 return getattr(self, func)(*args)
2189 ''' 2235 '''
2190 args = [] 2236 args = []
  2237 + print(cmd.args)
2191 # Convert all args to their real type 2238 # Convert all args to their real type
2192 for arg in cmd.args: 2239 for arg in cmd.args:
2193 - #print(arg) 2240 + print(arg)
2194 #try: 2241 #try:
2195 # Evaluate arg only if it is not a word (letters) : 2242 # Evaluate arg only if it is not a word (letters) :
2196 # - a word like "toto" is not evaluated => stays as is (=str) 2243 # - a word like "toto" is not evaluated => stays as is (=str)
@@ -2217,7 +2264,7 @@ class Agent: @@ -2217,7 +2264,7 @@ class Agent:
2217 cmd.set_as_pending() 2264 cmd.set_as_pending()
2218 #raise e 2265 #raise e
2219 # "from None" pour ne pas afficher l'exception AttributeError (car interne) 2266 # "from None" pour ne pas afficher l'exception AttributeError (car interne)
2220 - raise CmdBadArgsException(cmd) from None 2267 + raise CmdExceptionBadArgs(cmd) from None
2221 #print("I know this specific command but it is not yet implemented : ", func) 2268 #print("I know this specific command but it is not yet implemented : ", func)
2222 ##tb = sys.exc_info()[2] 2269 ##tb = sys.exc_info()[2]
2223 ##raise AgentCmdUnimplementedException(cmd).with_traceback(tb) 2270 ##raise AgentCmdUnimplementedException(cmd).with_traceback(tb)
@@ -2287,7 +2334,7 @@ class Agent: @@ -2287,7 +2334,7 @@ class Agent:
2287 # NOT PRIO 2334 # NOT PRIO
2288 if what == "noprio": pass 2335 if what == "noprio": pass
2289 # Bad arg 2336 # Bad arg
2290 - raise CmdBadArgsException(self.CURRENT_CMD) 2337 + raise CmdExceptionBadArgs(self.CURRENT_CMD)
2291 2338
2292 # Stop currently running cmd or routine 2339 # Stop currently running cmd or routine
2293 def do_stop_current(self, what:str): 2340 def do_stop_current(self, what:str):
@@ -2297,7 +2344,7 @@ class Agent: @@ -2297,7 +2344,7 @@ class Agent:
2297 self.do_stop_current_cmd() 2344 self.do_stop_current_cmd()
2298 self.do_stop_current_routine() 2345 self.do_stop_current_routine()
2299 # Bad arg 2346 # Bad arg
2300 - raise CmdBadArgsException(self.CURRENT_CMD) 2347 + raise CmdExceptionBadArgs(self.CURRENT_CMD)
2301 def do_stop_current_cmd(self): 2348 def do_stop_current_cmd(self):
2302 pass 2349 pass
2303 def do_stop_current_routine(self): 2350 def do_stop_current_routine(self):
@@ -2309,7 +2356,7 @@ class Agent: @@ -2309,7 +2356,7 @@ class Agent:
2309 def do_stop(self, when:str='asap'): self.do_stop_or_restart(False, when) 2356 def do_stop(self, when:str='asap'): self.do_stop_or_restart(False, when)
2310 def do_restart(self, when:str='asap'): self.do_stop_or_restart(True, when) 2357 def do_restart(self, when:str='asap'): self.do_stop_or_restart(True, when)
2311 def do_stop_or_restart(self, restart:bool=False, when:str='asap'): 2358 def do_stop_or_restart(self, restart:bool=False, when:str='asap'):
2312 - if when not in ('asap','now','noprio'): raise CmdBadArgsException(self.CURRENT_CMD) 2359 + if when not in ('asap','now','noprio'): raise CmdExceptionBadArgs(self.CURRENT_CMD)
2313 # NOT PRIO 2360 # NOT PRIO
2314 if when == "noprio": 2361 if when == "noprio":
2315 pass 2362 pass
@@ -2419,13 +2466,14 @@ class Agent: @@ -2419,13 +2466,14 @@ class Agent:
2419 2466
2420 def _TEST_get_next_command_to_send(self)->AgentCmd: 2467 def _TEST_get_next_command_to_send(self)->AgentCmd:
2421 #cmd_full_name, validity, res_expected, after_status = next(self.TEST_COMMANDS, (None,None,None,None)) 2468 #cmd_full_name, validity, res_expected, after_status = next(self.TEST_COMMANDS, (None,None,None,None))
2422 - cmd_full_name, validity, expected_res, expected_status = next(self.TEST_COMMANDS, (None,None,None,None)) 2469 + DO_IT = False
  2470 + while not DO_IT:
  2471 + DO_IT, cmd_full_name, validity, expected_res, expected_status = next(self.TEST_COMMANDS, (False,None,None,None,None))
2423 #print(expected_final_status) 2472 #print(expected_final_status)
2424 #print(cmd_full_name, res_expected) 2473 #print(cmd_full_name, res_expected)
2425 #return cmd_name 2474 #return cmd_name
2426 if cmd_full_name is None: return None 2475 if cmd_full_name is None: return None
2427 - # Remove excessive spaces  
2428 - import re 2476 + # Remove excessive spaces => already done in AgentCmd.create()
2429 cmd_full_name = re.sub(r"\s+", " ", cmd_full_name).strip() 2477 cmd_full_name = re.sub(r"\s+", " ", cmd_full_name).strip()
2430 if ' ' not in cmd_full_name: raise Exception('Command is malformed:', cmd_full_name) 2478 if ' ' not in cmd_full_name: raise Exception('Command is malformed:', cmd_full_name)
2431 agent_recipient, cmd_name_and_args = cmd_full_name.split(' ', 1) 2479 agent_recipient, cmd_name_and_args = cmd_full_name.split(' ', 1)
src/core/pyros_django/agent/AgentBasic.py
@@ -9,7 +9,7 @@ import sys @@ -9,7 +9,7 @@ import sys
9 ##sys.path.append("..") 9 ##sys.path.append("..")
10 ###from agent.Agent import Agent, build_agent 10 ###from agent.Agent import Agent, build_agent
11 sys.path.append("../../../..") 11 sys.path.append("../../../..")
12 -from src.core.pyros_django.agent.Agent import Agent, build_agent 12 +from src.core.pyros_django.agent.Agent import Agent, CmdExceptionExecError, build_agent
13 13
14 from typing import List, Tuple, Union, Any 14 from typing import List, Tuple, Union, Any
15 15
@@ -37,9 +37,16 @@ class AgentBasic(Agent): @@ -37,9 +37,16 @@ class AgentBasic(Agent):
37 ("do_specific10", 10, 0), 37 ("do_specific10", 10, 0),
38 #("set_specific2", 5, 0), 38 #("set_specific2", 5, 0),
39 ("do_specific30", 3, 0), 39 ("do_specific30", 3, 0),
40 - ###("existing_but_unimplemented_cmd", 3, 0), 40 + ##("cmd_existing_but_unimplemented", 3, 0),
  41 + ("cmd_raising_error_exec", 3, 0)
41 ] 42 ]
42 43
  44 + # Deactivate some tests, so that test scenario runs faster during DEV
  45 + # on DEV
  46 + #COMMIT_ONLY = False
  47 + # on commit only
  48 + COMMIT_ONLY = True
  49 +
43 # @override 50 # @override
44 TEST_COMMANDS_LIST = [ 51 TEST_COMMANDS_LIST = [
45 52
@@ -54,52 +61,58 @@ class AgentBasic(Agent): @@ -54,52 +61,58 @@ class AgentBasic(Agent):
54 61
55 # do_restart 62 # do_restart
56 63
57 - ("self do_restart now", 200, 'RESTARTING now', Agent.CMD_STATUS.CMD_EXECUTED), 64 + (COMMIT_ONLY, "self do_restart now", 200, 'RESTARTING now', Agent.CMD_STATUS.CMD_EXECUTED),
58 #("self do_stop", 200, 'STOPPING asap', Agent.CMD_STATUS.CMD_EXECUTED), 65 #("self do_stop", 200, 'STOPPING asap', Agent.CMD_STATUS.CMD_EXECUTED),
59 66
60 - # ------------------------------  
61 - # ------ A - ERROR CASES -------  
62 - # ------------------------------ 67 + # ----------------------------------------------------
  68 + # ------ A - ERROR CASES - from PENDING status -------
  69 + # ----------------------------------------------------
63 70
64 # - Error case 1 - unimplemented command in agent specific commands list 71 # - Error case 1 - unimplemented command in agent specific commands list
65 - # get_specific_cmds KO (with existing_but_unimplemented_cmd)  
66 - #("self get_specific_cmds", 200, 'EXCEPTION - One specific cmd is unimplemented: existing_but_unimplemented_cmd', Agent.CMD_STATUS.CMD_EXEC_ERROR), 72 + # get_specific_cmds KO (with cmd_existing_but_unimplemented)
  73 + ##("self get_specific_cmds", 200, 'EXCEPTION - One specific cmd is unimplemented: cmd_existing_but_unimplemented', Agent.CMD_STATUS.CMD_EXEC_ERROR),
67 # get_specific_cmds OK (all commands implemented) 74 # get_specific_cmds OK (all commands implemented)
68 - ("self get_specific_cmds", 200, 'do_specific10(arg1:int,arg2:int,arg3:float,arg4:str,arg5:typing.Tuple[int, str, int],arg6:typing.List[int]);do_specific30()', Agent.CMD_STATUS.CMD_EXECUTED), 75 + (COMMIT_ONLY, " self get_specific_cmds ", 200, 'do_specific10(arg1:int,arg2:int,arg3:float,arg4:str,arg5:typing.Tuple[int, str, int],arg6:typing.List[int]);do_specific30();cmd_raising_error_exec()', Agent.CMD_STATUS.CMD_EXECUTED),
69 76
70 # - Error case 2 - CMD_INVALID 77 # - Error case 2 - CMD_INVALID
71 # unknwon command 78 # unknwon command
72 ##FIXME: ("self unexisting_cmd", 200, '', Agent.CMD_STATUS.CMD_UNKNOWN), 79 ##FIXME: ("self unexisting_cmd", 200, '', Agent.CMD_STATUS.CMD_UNKNOWN),
73 - ("self unexisting_cmd", 200, '', Agent.CMD_STATUS.CMD_INVALID), 80 + (COMMIT_ONLY, "self cmd_unexisting", 200, 'EXCEPTION on command cmd_unexisting: Unknown command', Agent.CMD_STATUS.CMD_INVALID),
74 # bad parameters (missing or too many, or bad type) 81 # bad parameters (missing or too many, or bad type)
75 # missing args 82 # missing args
76 - ("self do_specific10", 200, '', Agent.CMD_STATUS.CMD_INVALID), 83 + (COMMIT_ONLY, "self do_specific10", 200, 'EXCEPTION on command do_specific10: Command has bad, missing, or too many argument(s)', Agent.CMD_STATUS.CMD_INVALID),
77 # missing args 84 # missing args
78 - ("self do_specific10 2", 200, '', Agent.CMD_STATUS.CMD_INVALID), 85 + (COMMIT_ONLY, "self do_specific10 2 ", 200, None, Agent.CMD_STATUS.CMD_INVALID),
79 # - too many args 86 # - too many args
80 - ("self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9] 4", 200, '', Agent.CMD_STATUS.CMD_INVALID), 87 + (COMMIT_ONLY, "self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9] 4", 200, None, Agent.CMD_STATUS.CMD_INVALID),
81 # - bad type 88 # - bad type
82 - ("self do_specific10 'toto' 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, '', Agent.CMD_STATUS.CMD_INVALID), 89 + (COMMIT_ONLY, "self do_specific10 'toto' 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, None, Agent.CMD_STATUS.CMD_INVALID),
83 # - OK 90 # - OK
84 #("self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, '16.5', Agent.CMD_STATUS.CMD_EXECUTED), 91 #("self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, '16.5', Agent.CMD_STATUS.CMD_EXECUTED),
85 92
86 # - Error case 3 - CMD_UNIMPLEMENTED 93 # - Error case 3 - CMD_UNIMPLEMENTED
87 - ("self existing_but_unimplemented_cmd", 200, '', Agent.CMD_STATUS.CMD_UNIMPLEMENTED), 94 + ##("self cmd_existing_but_unimplemented", 200, None, Agent.CMD_STATUS.CMD_UNIMPLEMENTED),
88 95
89 # - Error case 4 - CMD_EXPIRED 96 # - Error case 4 - CMD_EXPIRED
90 # This command has a validity of 0s and thus should be tagged as "expired" 97 # This command has a validity of 0s and thus should be tagged as "expired"
91 - ("self set_mode ATTENTIVE", 0, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXPIRED), 98 + (COMMIT_ONLY, "self set_mode ATTENTIVE", 0, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXPIRED),
92 99
93 # - Error case 5 - CMD_SKIPPED 100 # - Error case 5 - CMD_SKIPPED
94 # a) In mode ROUTINE, SPECIFIC commands should be skipped as the agent is not ATTENTIVE 101 # a) In mode ROUTINE, SPECIFIC commands should be skipped as the agent is not ATTENTIVE
95 - ("self set_mode ROUTINE", 200, "MODE is ROUTINE", Agent.CMD_STATUS.CMD_EXECUTED),  
96 - ("self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, None, Agent.CMD_STATUS.CMD_SKIPPED), 102 + (COMMIT_ONLY, "self set_mode ROUTINE", 200, "MODE is ROUTINE", Agent.CMD_STATUS.CMD_EXECUTED),
  103 + (COMMIT_ONLY, "self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, None, Agent.CMD_STATUS.CMD_SKIPPED),
97 # b) Back to mode ATTENTIVE, SPECIFIC commands should be executed 104 # b) Back to mode ATTENTIVE, SPECIFIC commands should be executed
98 - ("self set_mode ATTENTIVE", 200, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXECUTED),  
99 - ("self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, '16.5', Agent.CMD_STATUS.CMD_EXECUTED), 105 + (COMMIT_ONLY, "self set_mode ATTENTIVE", 200, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXECUTED),
  106 + (COMMIT_ONLY, "self do_specific10 2 2 3.5 titi (3,'titi',5) [1,3,5,7,9]", 200, '16.5', Agent.CMD_STATUS.CMD_EXECUTED),
  107 +
  108 + # ----------------------------------------------------
  109 + # ------ B - ERROR CASES - from RUNNING status -------
  110 + # ----------------------------------------------------
  111 +
  112 + (True, "self cmd_raising_error_exec", 200, "EXCEPTION on command cmd_raising_error_exec: Error during Execution", Agent.CMD_STATUS.CMD_EXEC_ERROR),
100 113
101 # ------------------------------ 114 # ------------------------------
102 - # ------ B - NORMAL CASES ------- 115 + # ------ C - NORMAL CASES -------
103 # ------------------------------ 116 # ------------------------------
104 117
105 # do_restart => #iteration should restart at 1 (so at least it should be <= 4) 118 # do_restart => #iteration should restart at 1 (so at least it should be <= 4)
@@ -129,13 +142,13 @@ class AgentBasic(Agent): @@ -129,13 +142,13 @@ class AgentBasic(Agent):
129 # ------------------------------- 142 # -------------------------------
130 143
131 # Agent general command 144 # Agent general command
132 - ("self set_mode ROUTINE", 200, "MODE is ROUTINE", Agent.CMD_STATUS.CMD_EXECUTED),  
133 - ("self get_mode", 200, "MODE is ROUTINE", Agent.CMD_STATUS.CMD_EXECUTED),  
134 - ("self set_mode ATTENTIVE", 200, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXECUTED),  
135 - ("self get_mode", 200, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXECUTED), 145 + (COMMIT_ONLY, "self set_mode ROUTINE", 200, "MODE is ROUTINE", Agent.CMD_STATUS.CMD_EXECUTED),
  146 + (COMMIT_ONLY, "self get_mode", 200, "MODE is ROUTINE", Agent.CMD_STATUS.CMD_EXECUTED),
  147 + (COMMIT_ONLY, "self set_mode ATTENTIVE", 200, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXECUTED),
  148 + (COMMIT_ONLY, "self get_mode", 200, "MODE is ATTENTIVE", Agent.CMD_STATUS.CMD_EXECUTED),
136 149
137 # End test 150 # End test
138 - ("self do_stop", 200, 'STOPPING asap', Agent.CMD_STATUS.CMD_EXECUTED), 151 + (True, "self do_stop", 200, 'STOPPING asap', Agent.CMD_STATUS.CMD_EXECUTED),
139 152
140 ] 153 ]
141 154
@@ -324,6 +337,9 @@ class AgentBasic(Agent): @@ -324,6 +337,9 @@ class AgentBasic(Agent):
324 #def do_specific1(self, arg1:int, arg2:int=2, arg3:int=3) -> int: 337 #def do_specific1(self, arg1:int, arg2:int=2, arg3:int=3) -> int:
325 #def do_specific1(self, arg1:int, arg2:int=2, arg3:float=3.1, arg4:list=[1,2,3]) -> float: 338 #def do_specific1(self, arg1:int, arg2:int=2, arg3:float=3.1, arg4:list=[1,2,3]) -> float:
326 339
  340 + def cmd_raising_error_exec(self):
  341 + raise CmdExceptionExecError(self.CURRENT_CMD)
  342 +
327 def do_specific10(self, 343 def do_specific10(self,
328 arg1:int, 344 arg1:int,
329 arg2:int, 345 arg2:int,
src/core/pyros_django/common/models.py
@@ -12,6 +12,9 @@ from dateutil.relativedelta import relativedelta @@ -12,6 +12,9 @@ from dateutil.relativedelta import relativedelta
12 import os 12 import os
13 import sys 13 import sys
14 from typing import Any, List, Tuple 14 from typing import Any, List, Tuple
  15 +import re
  16 +
  17 +# Django imports
15 from django.core.validators import MaxValueValidator, MinValueValidator 18 from django.core.validators import MaxValueValidator, MinValueValidator
16 19
17 # DJANGO imports 20 # DJANGO imports
@@ -575,8 +578,10 @@ class AgentCmd(models.Model): @@ -575,8 +578,10 @@ class AgentCmd(models.Model):
575 # GET commands 578 # GET commands
576 # ------------ 579 # ------------
577 580
578 - # - Get agent current STATE (IN_MAIN_LOOP, ...) 581 + # - Get agent current STATUS or STEP (IN_MAIN_LOOP, ...)
  582 + "get_status",
579 ##"get_current_state", 583 ##"get_current_state",
  584 + # @deprecated
580 "get_state", 585 "get_state",
581 586
582 # - Get agent current MODE (idle, routine, attentive) 587 # - Get agent current MODE (idle, routine, attentive)
@@ -644,6 +649,7 @@ class AgentCmd(models.Model): @@ -644,6 +649,7 @@ class AgentCmd(models.Model):
644 # Priority commands, executed as soon as in the received commands list (BEFORE any other pending command) 649 # Priority commands, executed as soon as in the received commands list (BEFORE any other pending command)
645 # NB : must be a subset of _AGENT_GENERAL_COMMANDS 650 # NB : must be a subset of _AGENT_GENERAL_COMMANDS
646 _AGENT_GENERAL_PRIORITY_COMMANDS = [ 651 _AGENT_GENERAL_PRIORITY_COMMANDS = [
  652 + "get_specific_cmds",
647 #"do_exit", 653 #"do_exit",
648 "do_flush_commands", 654 "do_flush_commands",
649 "do_exec_commands" 655 "do_exec_commands"
@@ -666,7 +672,10 @@ class AgentCmd(models.Model): @@ -666,7 +672,10 @@ class AgentCmd(models.Model):
666 if '.' in agent_to: 672 if '.' in agent_to:
667 agent_to, component_name = agent_to.split('.') 673 agent_to, component_name = agent_to.split('.')
668 cmd_name = component_name+'.'+cmd_name 674 cmd_name = component_name+'.'+cmd_name
  675 + # remove all excessive spaces
  676 + print(cmd_args)
669 if cmd_args: 677 if cmd_args:
  678 + cmd_args = re.sub(r"\s+", " ", cmd_args).strip()
670 cmd_name += ' ' + cmd_args 679 cmd_name += ' ' + cmd_args
671 # cls._device_command=DeviceCommand(cmd_name) 680 # cls._device_command=DeviceCommand(cmd_name)
672 if cmd_validity is None: cmd_validity = cls.DEFAULT_VALIDITY_DURATION 681 if cmd_validity is None: cmd_validity = cls.DEFAULT_VALIDITY_DURATION
@@ -1091,13 +1100,15 @@ class AgentCmd(models.Model): @@ -1091,13 +1100,15 @@ class AgentCmd(models.Model):
1091 if result: 1100 if result:
1092 self.set_result(result, False) 1101 self.set_result(result, False)
1093 1102
  1103 + '''
1094 # - Changing state to PENDING (from None) 1104 # - Changing state to PENDING (from None)
1095 if status_new == self.CMD_STATUS_CODES.CMD_PENDING: 1105 if status_new == self.CMD_STATUS_CODES.CMD_PENDING:
1096 self.s_deposit_time = now_time 1106 self.s_deposit_time = now_time
  1107 + '''
1097 1108
1098 # - Changing state from PENDING 1109 # - Changing state from PENDING
1099 #if status_new in (self.CMD_STATUS_CODES.CMD_RUNNING, self.CMD_STATUS_CODES.CMD_SKIPPED, self.CMD_STATUS_CODES.CMD_EXPIRED): 1110 #if status_new in (self.CMD_STATUS_CODES.CMD_RUNNING, self.CMD_STATUS_CODES.CMD_SKIPPED, self.CMD_STATUS_CODES.CMD_EXPIRED):
1100 - elif status_new in ( 1111 + if status_new in (
1101 # Errors cases 1112 # Errors cases
1102 self.CMD_STATUS_CODES.CMD_INVALID, 1113 self.CMD_STATUS_CODES.CMD_INVALID,
1103 self.CMD_STATUS_CODES.CMD_UNIMPLEMENTED, 1114 self.CMD_STATUS_CODES.CMD_UNIMPLEMENTED,
@@ -1119,7 +1130,7 @@ class AgentCmd(models.Model): @@ -1119,7 +1130,7 @@ class AgentCmd(models.Model):
1119 1130
1120 # - Changing state from RUNNING (CMD_EXECUTED, CMD_EXEC_...) 1131 # - Changing state from RUNNING (CMD_EXECUTED, CMD_EXEC_...)
1121 #elif status_new in (self.CMD_STATUS_CODES.CMD_EXECUTED, self.CMD_STATUS_CODES.CMD_EXEC_KILLED): 1132 #elif status_new in (self.CMD_STATUS_CODES.CMD_EXECUTED, self.CMD_STATUS_CODES.CMD_EXEC_KILLED):
1122 - else: 1133 + elif status_new != self.CMD_STATUS_CODES.CMD_PENDING:
1123 assert self.is_running() 1134 assert self.is_running()
1124 self.r_end_time = now_time 1135 self.r_end_time = now_time
1125 if status_new == self.CMD_STATUS_CODES.CMD_EXEC_KILLED: 1136 if status_new == self.CMD_STATUS_CODES.CMD_EXEC_KILLED: