|
11 | 11 | from pathlib import Path, PurePath |
12 | 12 | from typing import ( |
13 | 13 | Any, |
| 14 | + Callable, |
14 | 15 | Deque, |
15 | 16 | Dict, |
16 | 17 | Generator, |
@@ -223,8 +224,6 @@ def __new__(cls, *args: Any, **kwargs: Any) -> Any: |
223 | 224 | raise RuntimeError(f"Attempt to create a '{cls.__qualname__}' instance outside of instance()") |
224 | 225 |
|
225 | 226 | def __init__(self) -> None: |
226 | | - from robot.running.model import Keyword |
227 | | - |
228 | 227 | self.breakpoints: Dict[pathlib.PurePath, BreakpointsEntry] = {} |
229 | 228 |
|
230 | 229 | self.exception_breakpoints: Set[ExceptionBreakpointsEntry] = set() |
@@ -254,10 +253,12 @@ def __init__(self) -> None: |
254 | 253 | self.attached = False |
255 | 254 | self.path_mappings: List[PathMapping] = [] |
256 | 255 |
|
257 | | - self.run_keyword: Optional[Keyword] = None |
258 | | - self.run_keyword_event = threading.Event() |
259 | | - self.run_keyword_event.set() |
260 | | - self.after_run_keyword_event_state: Optional[State] = None |
| 256 | + self._keyword_to_evaluate: Optional[Callable[..., Any]] = None |
| 257 | + self._evaluated_keyword_result: Any = None |
| 258 | + self._evaluate_keyword_event = threading.Event() |
| 259 | + self._evaluate_keyword_event.set() |
| 260 | + self._after_evaluate_keyword_event = threading.Event() |
| 261 | + self._after_evaluate_keyword_event.set() |
261 | 262 |
|
262 | 263 | @property |
263 | 264 | def debug(self) -> bool: |
@@ -604,13 +605,26 @@ def process_end_state(self, status: str, filter_id: Set[str], description: str, |
604 | 605 | @_logger.call |
605 | 606 | def wait_for_running(self) -> None: |
606 | 607 | if self.attached: |
607 | | - with self.condition: |
608 | | - while True: |
| 608 | + while True: |
| 609 | + with self.condition: |
609 | 610 | self.condition.wait_for(lambda: self.state in [State.Running, State.Stopped, State.CallKeyword]) |
610 | 611 |
|
611 | | - if self.state == State.CallKeyword: |
612 | | - continue |
613 | | - break |
| 612 | + if self.state == State.CallKeyword: |
| 613 | + self._evaluated_keyword_result = None |
| 614 | + try: |
| 615 | + if self._keyword_to_evaluate is not None: |
| 616 | + self._evaluated_keyword_result = self._keyword_to_evaluate() |
| 617 | + self._keyword_to_evaluate = None |
| 618 | + except (SystemExit, KeyboardInterrupt): |
| 619 | + raise |
| 620 | + except BaseException as e: |
| 621 | + self._evaluated_keyword_result = e |
| 622 | + finally: |
| 623 | + self._evaluate_keyword_event.set() |
| 624 | + self._after_evaluate_keyword_event.wait(60) |
| 625 | + |
| 626 | + continue |
| 627 | + break |
614 | 628 |
|
615 | 629 | def start_output_group(self, name: str, attributes: Dict[str, Any], type: Optional[str] = None) -> None: |
616 | 630 | if self.group_output: |
@@ -1225,13 +1239,35 @@ def evaluate( |
1225 | 1239 | variables.append(var) |
1226 | 1240 |
|
1227 | 1241 | if splitted: |
1228 | | - kw = Keyword(name=splitted[0], args=tuple(splitted[1:]), assign=tuple(variables)) |
1229 | | - old_state = self.state |
1230 | | - self.state = State.CallKeyword |
1231 | 1242 |
|
1232 | | - result = kw.run(evaluate_context) |
| 1243 | + def run_kw() -> Any: |
| 1244 | + kw = Keyword(name=splitted[0], args=tuple(splitted[1:]), assign=tuple(variables)) |
| 1245 | + return kw.run(evaluate_context) |
| 1246 | + |
| 1247 | + with self.condition: |
| 1248 | + self._keyword_to_evaluate = run_kw |
| 1249 | + self._evaluated_keyword_result = None |
| 1250 | + |
| 1251 | + self._evaluate_keyword_event.clear() |
| 1252 | + self._after_evaluate_keyword_event.clear() |
| 1253 | + |
| 1254 | + old_state = self.state |
| 1255 | + self.state = State.CallKeyword |
| 1256 | + self.condition.notify_all() |
| 1257 | + |
| 1258 | + try: |
| 1259 | + self._evaluate_keyword_event.wait(60) |
| 1260 | + finally: |
| 1261 | + result = self._evaluated_keyword_result |
| 1262 | + |
| 1263 | + with self.condition: |
| 1264 | + self._keyword_to_evaluate = None |
| 1265 | + self._evaluated_keyword_result = None |
| 1266 | + |
| 1267 | + self.state = old_state |
| 1268 | + self.condition.notify_all() |
1233 | 1269 |
|
1234 | | - self.state = old_state |
| 1270 | + self._after_evaluate_keyword_event.set() |
1235 | 1271 |
|
1236 | 1272 | elif self.IS_VARIABLE_RE.match(expression.strip()): |
1237 | 1273 | try: |
|
0 commit comments