Commit 0ddc9733d010523531caf944d24fa474fb1d5042
Exists in
dev
Merge branch 'dev' of https://gitlab.irap.omp.eu/epallier/pyros into dev
Showing
4 changed files
with
224 additions
and
133 deletions
Show diff stats
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: |