Files
CoreRasurae 9753b31c7e
CI / quality (push) Successful in 36s
CI / lint (push) Successful in 38s
CI / typecheck (push) Successful in 49s
CI / security (push) Successful in 51s
CI / integration_tests (push) Successful in 55s
CI / unit_tests (push) Successful in 3m35s
CI / build (push) Successful in 33s
CI / coverage (push) Successful in 3m36s
CI / status-check (push) Successful in 3s
test: add coverage gap tests improving coverage from 81.4% to 96.90%
Add 13 BDD scenarios covering previously uncovered code paths:
- SAFE_BUILTINS validation (sandbox.py: 0% → 100%)
- ConfigurationError re-raise path (config.py: 99.3% → 100%)
- CLI hello/main functions (cli.py: 72.7% → 90.9%)
- GraphState message truncation (state.py: 98.7% → 100%)
- ProgressBarManager update/context rendering (progress.py: 0% → 87.7%)
- MessageRouter regex/exact/contains routing (message_router.py: 0% → 59.4%)
- RoutingAdapter parse_routing_command (routing_adapter.py)
- DynamicRouterNode pattern-based routing (dynamic_router.py)
- EnhancedTemplateRegistry unknown template type (enhanced_registry.py: 99.2%)
- CompositeAgent null-graph error path (composite.py: 97.8% → 98.6%)

Cover routing_adapter.py (17% → 100%): all GOTO/ROUTE patterns,
create_routing_node, create_conditional_router, dynamic config conversion.

Cover dynamic_router.py (21% → 87%): execute with empty/dict/string
messages, extract_message with colon parsing, config creation, graph
extension with edge generation.

Cover message_router.py (59% → 78%): regex, exact, contains, prefix,
suffix match types, invalid regex handling, non-string message, set_state.

Exercise Node._prepare_conversation_history with invalid configs,
_runtime error paths, _execute_message_router with rules,
_execute_agent with current_message and metadata propagation,
_execute_function with dynamic_router, and _execute_conditional
with content_contains/content_not_contains/content_starts_with
and custom condition types. Improves nodes.py from 71.3% to 72.5%.

Exercise PureGraphConfig, PureLangGraph init with dict/config,
RxPyLangGraphBridge registration/connection/lookup,
ReactiveStreamRouter operator creation and condition functions,
ReactiveConfigParser config/route/graph parsing,
ToolAgent tool execution with JSON, space-separated, single,
file_read, progress_bar invocations, and
ReactiveCleverAgentsApp init/dispose/visualization.
2026-06-02 20:02:01 +01:00

57 lines
1.6 KiB
Python

"""Shared async utilities for coverage step files — thread-safe event loop isolation."""
import asyncio
import threading
def _run(coro):
"""Run *coro* to completion in a **fresh, thread-local** event loop.
Every call creates a brand new loop and runs the coroutine on it.
After completion, the loop is closed and the previous asyncio state
is restored. This means tests can run in any order, in any thread,
without ever sharing or corrupting each other's event loop state.
Slipcover instruments the actual function calls inside the
coroutine, so coverage is tracked regardless of which loop
executes them.
"""
# Remember what was there before
old_loop = None
try:
old_loop = asyncio.get_running_loop()
except RuntimeError:
pass
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
try:
return loop.run_until_complete(coro)
finally:
_cancel_pending(loop)
loop.close()
# Restore the old loop if one was running
if old_loop and not old_loop.is_closed():
asyncio.set_event_loop(old_loop)
def _cancel_pending(loop):
try:
pending = asyncio.all_tasks(loop)
if not pending:
return
for t in pending:
t.cancel()
loop.run_until_complete(
asyncio.gather(*pending, return_exceptions=True),
)
except Exception:
pass
async def _catch(fn, *args, **kwargs):
try:
return await fn(*args, **kwargs)
except Exception as exc:
return f"{type(exc).__name__}: {exc}"