Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

## [Unreleased]

### Removed

- **Dead Executor Methods** — remove `Executor.execute_parallel()` and `Executor.execute_sequential()`, which had no production callers (the pipeline uses `Executor.gather()`); their only in-tree references were two dedicated unit tests (#52)

---

## [0.4.8] - 2026-07-24
Expand Down
83 changes: 1 addition & 82 deletions openagent_eval/core/executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import asyncio
from concurrent.futures import ThreadPoolExecutor
from typing import Any, Callable, Coroutine
from typing import Any, Callable

from openagent_eval.exceptions import MetricExecutionError

Expand All @@ -28,48 +28,6 @@ def __init__(self, max_workers: int = 4, timeout: float = 300.0) -> None:
self._semaphore = asyncio.Semaphore(max_workers)
self._thread_pool: ThreadPoolExecutor | None = None

async def execute_parallel(
self,
tasks: list[Callable[..., Coroutine[Any, Any, Any]]],
*args: Any,
**kwargs: Any,
) -> list[Any]:
"""Execute multiple tasks in parallel with concurrency limits.

Args:
tasks: List of async functions to execute.
*args: Positional arguments to pass to each task.
**kwargs: Keyword arguments to pass to each task.

Returns:
List of results from each task.

Raises:
MetricExecutionError: If a task fails or times out.
"""
async def _run_with_semaphore(
task: Callable[..., Coroutine[Any, Any, Any]],
) -> Any:
async with self._semaphore:
try:
return await asyncio.wait_for(
task(*args, **kwargs),
timeout=self.timeout,
)
except asyncio.TimeoutError:
raise MetricExecutionError(
message=f"Task timed out after {self.timeout}s",
details={"timeout": self.timeout},
)
except Exception as e:
raise MetricExecutionError(
message=f"Task failed: {e}",
original_error=e,
) from e

coroutines = [_run_with_semaphore(task) for task in tasks]
return await asyncio.gather(*coroutines)

async def gather(self, coroutines: list[Any]) -> list[Any]:
"""Run coroutines concurrently with the configured concurrency limit.

Expand Down Expand Up @@ -104,45 +62,6 @@ async def _run(coro: Any) -> Any:

return [t.result() for t in tasks]

async def execute_sequential(
self,
tasks: list[Callable[..., Coroutine[Any, Any, Any]]],
*args: Any,
**kwargs: Any,
) -> list[Any]:
"""Execute tasks sequentially.

Args:
tasks: List of async functions to execute.
*args: Positional arguments to pass to each task.
**kwargs: Keyword arguments to pass to each task.

Returns:
List of results from each task.

Raises:
MetricExecutionError: If a task fails.
"""
results: list[Any] = []
for task in tasks:
try:
result = await asyncio.wait_for(
task(*args, **kwargs),
timeout=self.timeout,
)
results.append(result)
except asyncio.TimeoutError:
raise MetricExecutionError(
message=f"Task timed out after {self.timeout}s",
details={"timeout": self.timeout},
)
except Exception as e:
raise MetricExecutionError(
message=f"Task failed: {e}",
original_error=e,
) from e
return results

async def run_in_thread(
self,
func: Callable[..., Any],
Expand Down
22 changes: 0 additions & 22 deletions tests/unit/test_core/test_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,28 +68,6 @@ def test_init(self) -> None:
assert executor.max_workers == 2
assert executor.timeout == 60.0

@pytest.mark.asyncio
async def test_execute_parallel(self) -> None:
"""Test parallel execution."""
executor = Executor(max_workers=2)

async def fake_task(x: int) -> int:
return x * 2

results = await executor.execute_parallel([fake_task, fake_task], 5)
assert results == [10, 10]

@pytest.mark.asyncio
async def test_execute_sequential(self) -> None:
"""Test sequential execution."""
executor = Executor(max_workers=2)

async def fake_task(x: int) -> int:
return x * 2

results = await executor.execute_sequential([fake_task, fake_task], 5)
assert results == [10, 10]


class TestPipeline:
"""Tests for the evaluation pipeline."""
Expand Down
Loading