-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathapi_lock.py
More file actions
38 lines (29 loc) · 1.14 KB
/
Copy pathapi_lock.py
File metadata and controls
38 lines (29 loc) · 1.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
"""Shared simulation API lock and safe optional snapshots."""
from __future__ import annotations
import contextlib
from typing import Any, Callable, Dict, Optional, Tuple
def sim_api_lock(sim) -> contextlib.AbstractContextManager:
lock = getattr(sim, "api_lock", None)
if lock is None:
return contextlib.nullcontext()
return lock
def handler_sim_lock(handler) -> contextlib.AbstractContextManager:
return sim_api_lock(getattr(handler, "sim_ref", None))
def safe_optional(label: str, fn: Callable[[], Any],
*, default: Any = None) -> Tuple[Any, Optional[str]]:
try:
return fn(), None
except Exception as exc:
return default, f"{label}: {type(exc).__name__}: {exc}"
def safe_dict(label: str, fn: Callable[[], Dict[str, Any]],
*, default: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
out: Dict[str, Any] = dict(default or {})
result, err = safe_optional(label, fn, default=None)
if err:
out["error"] = err
return out
if isinstance(result, dict):
return result
if result is not None:
out["value"] = result
return out