Skip to content

Commit 99fcc15

Browse files
aditik0303claude
andcommitted
test(openai-agents): make test_hooks mypy-clean (fix CI lint)
CI runs mypy on the whole package incl. tests; the migration-era test file wasn't type-clean, so 'lint / Lint uipath-openai-agents' was red (pre-existing). - FakeEvaluator evaluate_* now (self, *args, **kwargs) -> Any so it structurally satisfies EvaluatorProtocol (was **kwargs-only + -> None, which mypy rejected on both signature and AuditRecord return). - bare dict -> dict[str, Any]. - type: ignore[assignment] on the RecordingHooks test double assigned to the real Agent.hooks slot; type: ignore[func-returns-value] on the return-None pass-through asserts. mypy . clean (34 files); ruff + 60 tests green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 697f321 commit 99fcc15

1 file changed

Lines changed: 18 additions & 15 deletions

File tree

packages/uipath-openai-agents/tests/governance/test_hooks.py

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -38,29 +38,29 @@ class FakeEvaluator:
3838

3939
def __init__(self, block_on: str | None = None) -> None:
4040
self.block_on = block_on
41-
self.calls: List[tuple[str, dict]] = []
41+
self.calls: List[tuple[str, dict[str, Any]]] = []
4242

4343
def _record(self, hook: str, **kwargs: Any) -> None:
4444
self.calls.append((hook, kwargs))
4545
if self.block_on == hook:
4646
raise GovernanceBlockException("blocked") # type: ignore[call-arg]
4747

48-
def evaluate_before_agent(self, **kwargs: Any) -> None:
48+
def evaluate_before_agent(self, *args: Any, **kwargs: Any) -> Any:
4949
self._record("before_agent", **kwargs)
5050

51-
def evaluate_after_agent(self, **kwargs: Any) -> None:
51+
def evaluate_after_agent(self, *args: Any, **kwargs: Any) -> Any:
5252
self._record("after_agent", **kwargs)
5353

54-
def evaluate_before_model(self, **kwargs: Any) -> None:
54+
def evaluate_before_model(self, *args: Any, **kwargs: Any) -> Any:
5555
self._record("before_model", **kwargs)
5656

57-
def evaluate_after_model(self, **kwargs: Any) -> None:
57+
def evaluate_after_model(self, *args: Any, **kwargs: Any) -> Any:
5858
self._record("after_model", **kwargs)
5959

60-
def evaluate_tool_call(self, **kwargs: Any) -> None:
60+
def evaluate_tool_call(self, *args: Any, **kwargs: Any) -> Any:
6161
self._record("tool_call", **kwargs)
6262

63-
def evaluate_after_tool(self, **kwargs: Any) -> None:
63+
def evaluate_after_tool(self, *args: Any, **kwargs: Any) -> Any:
6464
self._record("after_tool", **kwargs)
6565

6666

@@ -98,17 +98,17 @@ async def on_tool_end(self, *_a: Any) -> None:
9898
self.seen.append("on_tool_end")
9999

100100

101-
def _msg(text: str, role: str = "user") -> dict:
101+
def _msg(text: str, role: str = "user") -> dict[str, Any]:
102102
"""A response input item carrying plain string content."""
103103
return {"role": role, "content": text}
104104

105105

106-
def _msg_parts(*texts: str, role: str = "user") -> dict:
106+
def _msg_parts(*texts: str, role: str = "user") -> dict[str, Any]:
107107
"""A response input item carrying a list of text parts."""
108108
return {"role": role, "content": [{"type": "input_text", "text": t} for t in texts]}
109109

110110

111-
def _function_call(name: str, arguments: str) -> dict:
111+
def _function_call(name: str, arguments: str) -> dict[str, Any]:
112112
return {"type": "function_call", "name": name, "arguments": arguments}
113113

114114

@@ -161,7 +161,7 @@ def test_install_governance_is_idempotent():
161161
def test_install_governance_chains_existing_hooks():
162162
agent = FakeAgent()
163163
user_hooks = RecordingHooks()
164-
agent.hooks = user_hooks
164+
agent.hooks = user_hooks # type: ignore[assignment] # test double, not a real AgentHooks
165165
install_governance(agent, FakeEvaluator(), agent_name="x", session_id="s")
166166
assert isinstance(agent.hooks, GovernanceAgentHooks)
167167
assert agent.hooks._inner is user_hooks
@@ -385,11 +385,14 @@ def evaluate_before_model(self, **_: Any) -> None:
385385

386386

387387
async def test_hooks_return_none():
388+
# hooks are pass-through (return None) — they never short-circuit the run.
389+
# (the inline type: ignores below silence mypy's func-returns-value on the
390+
# None-returning hooks; the runtime assert documents the contract.)
388391
cb = _make_hooks(FakeEvaluator())
389-
assert await cb.on_llm_start(None, FakeAgent(), None, []) is None
390-
assert await cb.on_llm_end(None, FakeAgent(), SimpleNamespace(output=[])) is None
391-
assert await cb.on_tool_start(None, FakeAgent(), FakeTool("t")) is None
392-
assert await cb.on_tool_end(None, FakeAgent(), FakeTool("t"), {}) is None
392+
assert await cb.on_llm_start(None, FakeAgent(), None, []) is None # type: ignore[func-returns-value]
393+
assert await cb.on_llm_end(None, FakeAgent(), SimpleNamespace(output=[])) is None # type: ignore[func-returns-value]
394+
assert await cb.on_tool_start(None, FakeAgent(), FakeTool("t")) is None # type: ignore[func-returns-value]
395+
assert await cb.on_tool_end(None, FakeAgent(), FakeTool("t"), {}) is None # type: ignore[func-returns-value]
393396

394397

395398
# --------------------------------------------------------------------------

0 commit comments

Comments
 (0)