|
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