fix: bound the waits that could freeze the learn loop (tests/test_voyager_skillmanager_bounds.py)
Browse files
tests/test_voyager_skillmanager_bounds.py
CHANGED
|
@@ -46,6 +46,32 @@ def check(label: str, condition: bool, detail: str = "", skip: bool = False) ->
|
|
| 46 |
FAILURES.append(label)
|
| 47 |
|
| 48 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
def _patch_literals() -> dict[str, str]:
|
| 50 |
"""Pull the string constants the skill patch is built from."""
|
| 51 |
source = (ROOT / "voyager_stack.py").read_text(encoding="utf-8")
|
|
@@ -94,8 +120,15 @@ def main() -> None:
|
|
| 94 |
check("bloco de helpers existe", bool(helpers))
|
| 95 |
check("VECTORDB_OPEN_SECONDS definido", "VECTORDB_OPEN_SECONDS" in helpers)
|
| 96 |
check(
|
| 97 |
-
"a abertura roda em
|
| 98 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 99 |
)
|
| 100 |
check(
|
| 101 |
"o timeout vira RuntimeError (o runner pode retentar)",
|
|
|
|
| 46 |
FAILURES.append(label)
|
| 47 |
|
| 48 |
|
| 49 |
+
def _executor_join_absent(helpers: str) -> bool:
|
| 50 |
+
"""True when no LIVE line joins a worker or awaits a future.
|
| 51 |
+
|
| 52 |
+
The helper docstrings name `ThreadPoolExecutor` and `shutdown(wait=True)`
|
| 53 |
+
on purpose, to warn the next reader off them. A substring search therefore
|
| 54 |
+
reports the opposite of the truth. Strip string literals and look at the
|
| 55 |
+
code that actually runs.
|
| 56 |
+
"""
|
| 57 |
+
try:
|
| 58 |
+
tree = ast.parse("class _Probe:\n" + "\n".join(
|
| 59 |
+
" " + line for line in helpers.splitlines()))
|
| 60 |
+
except SyntaxError:
|
| 61 |
+
return False
|
| 62 |
+
spans = [
|
| 63 |
+
(node.lineno, node.end_lineno)
|
| 64 |
+
for node in ast.walk(tree)
|
| 65 |
+
if isinstance(node, ast.Constant) and isinstance(node.value, str)
|
| 66 |
+
]
|
| 67 |
+
for i, line in enumerate(helpers.splitlines(), 1):
|
| 68 |
+
if any(a <= i <= b for a, b in spans):
|
| 69 |
+
continue
|
| 70 |
+
if "shutdown(wait" in line or "future.result" in line:
|
| 71 |
+
return False
|
| 72 |
+
return True
|
| 73 |
+
|
| 74 |
+
|
| 75 |
def _patch_literals() -> dict[str, str]:
|
| 76 |
"""Pull the string constants the skill patch is built from."""
|
| 77 |
source = (ROOT / "voyager_stack.py").read_text(encoding="utf-8")
|
|
|
|
| 120 |
check("bloco de helpers existe", bool(helpers))
|
| 121 |
check("VECTORDB_OPEN_SECONDS definido", "VECTORDB_OPEN_SECONDS" in helpers)
|
| 122 |
check(
|
| 123 |
+
"a abertura roda em thread daemon sob deadline",
|
| 124 |
+
"_open_with_deadline" in helpers and "daemon=True" in helpers,
|
| 125 |
+
)
|
| 126 |
+
check(
|
| 127 |
+
"o deadline nao faz join no worker que travou",
|
| 128 |
+
# Nao basta procurar a substring: o docstring do helper cita
|
| 129 |
+
# `shutdown(wait=True)` e `ThreadPoolExecutor` justamente para avisar
|
| 130 |
+
# contra eles. Grep daria falso positivo; olhamos so o codigo vivo.
|
| 131 |
+
_executor_join_absent(helpers),
|
| 132 |
)
|
| 133 |
check(
|
| 134 |
"o timeout vira RuntimeError (o runner pode retentar)",
|