Skip to content

test: enable mypy typing checks for test/components/retrievers - #12481

Open
ShousenZHANG wants to merge 2 commits into
deepset-ai:mainfrom
ShousenZHANG:test/type-check-retriever-tests
Open

test: enable mypy typing checks for test/components/retrievers#12481
ShousenZHANG wants to merge 2 commits into
deepset-ai:mainfrom
ShousenZHANG:test/type-check-retriever-tests

Conversation

@ShousenZHANG

Copy link
Copy Markdown
Contributor

Related Issues

Proposed Changes:

test/components/retrievers/ is not in the repository mypy target, so its 16 test modules are not checked by hatch run test:types. This is the next disjoint increment for #10396, claimed in this comment. It does not overlap fetchers/ (#12435), the only increment still in flight.

The baseline was 78 errors across 11 modules. Nothing here changes what a test asserts:

  • 40 call-overload / assignment in test_auto_merging_retriever.py and its async twin. docs was bound three times in the same test — first to the input list[Document], then to the dict returned by HierarchicalDocumentSplitter.run, then to the retriever's result — so mypy had no single type for it. Fixed by naming the three values docs, split_docs and merged. No suppressions were needed for this group.
  • 16 no-untyped-def on the mock retrievers' run / run_async and on parametrised pipeline tests that took unannotated fixtures.
  • 7 type-var on sorted(scores, ...), where Document.score is float | None. I added assert all(doc.score is not None for doc in docs) before the ordering assertion and kept a narrow # type: ignore[type-var] on the sorted call, since mypy doesn't narrow through the list comprehension. I deliberately avoided filtering the Nones out of scores, because that would let a document with no score slip past the ordering check instead of failing it.
  • 9 arg-type / 4 method-assign where a test double is passed where the component asks for the real protocol type, or a method is monkeypatched onto a store. Narrow ignores.

Per AGENTS.md I kept type: ignore to the cases where it is necessary — the largest group (the auto-merging tests) is fixed structurally instead. mypy --warn-unused-ignores reports no unused suppressions.

How did you test it?

Red/green against the repository configuration:

  • Before: mypy test/components/retrievers/ reported 78 errors in 11 files.
  • After: Success: no issues found in 16 source files.
  • Full target: hatch run test:types -> Success: no issues found in 479 source files (461 before).
  • hatch run test:unit test/components/retrievers/ -> 194 passed, 30 deselected.
  • hatch run fmt-check -> clean across the repo (6785 files).

Notes for the reviewer

The renaming in the auto-merging tests is the part worth a look. Three assertions there were checking docs["documents"] after docs had been rebound to the retriever result, so they now read merged["documents"]; the objects being asserted on are the same ones as before, and both tests still pass. The assert all(doc.score is not None ...) lines are new checks rather than relaxations.

No release note: this is test-only, which AGENTS.md excludes from the release-note requirement.

This PR was fully generated with an AI assistant. I have reviewed the changes and run the relevant tests.

Checklist

  • I have read the contributors guidelines and the code of conduct.
  • I have updated the related issue with new insights and changes.
  • I have added unit tests and updated the docstrings.
  • I've used one of the conventional commit types for my PR title.
  • I have documented my code.
  • I have added a release note file - not needed here: AGENTS.md scopes the requirement to user-facing changes, and this is test-only.
  • I have run pre-commit hooks and fixed any issue.

@ShousenZHANG
ShousenZHANG requested a review from a team as a code owner August 27, 2026 02:15
@ShousenZHANG
ShousenZHANG requested review from julian-risch and a lite review from Copilot and removed request for a team August 27, 2026 02:15
@vercel

vercel Bot commented Aug 27, 2026

Copy link
Copy Markdown

@ShousenZHANG is attempting to deploy a commit to the deepset Team on Vercel.

A member of the Team first needs to authorize it.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

  • Purpose: extend repository-wide mypy coverage to test/components/retrievers/ (incremental step of #10396) by fixing typing issues in the retriever test modules without changing test intent/assertions.

Changes:

  • Add test/components/retrievers/ to the hatch run test:types mypy target list.
  • Make retriever test doubles and parametrized tests mypy-friendly via explicit return types/annotations and narrowly-scoped # type: ignore[...] where needed.
  • Tighten score-ordering assertions with score is not None checks before comparing sort order.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
pyproject.toml Adds test/components/retrievers/ to the mypy types script target set.
test/components/retrievers/test_text_embedding_retriever.py Refines score ordering assertion to satisfy mypy (and adds score is not None guard).
test/components/retrievers/test_text_embedding_retriever_async.py Async equivalent typing + score ordering assertion adjustments.
test/components/retrievers/test_multi_retriever.py Adds return types for local components/test doubles; updates ordering asserts to satisfy mypy.
test/components/retrievers/test_multi_query_text_retriever_async.py Adds narrow ignore for protocol/type mismatch in async test double wiring.
test/components/retrievers/test_multi_query_embedding_retriever_async.py Adds score None guard + ordering typing fix; narrow ignore for protocol/type mismatch.
test/components/retrievers/test_in_memory_embedding_retriever.py Adds narrow ignores for method monkeypatching and dynamic store class typing.
test/components/retrievers/test_in_memory_bm25_retriever.py Adds narrow ignores for method monkeypatching and annotates pipeline tests for mypy.
test/components/retrievers/test_filter_retriever.py Adds narrow ignore for monkeypatch; simplifies a pipeline call to avoid mypy friction.
test/components/retrievers/test_filter_retriever_async.py Removes an annotation that confused mypy while keeping runtime behavior the same.
test/components/retrievers/test_auto_merging_retriever.py Renames rebound variables to keep stable types across assertions.
test/components/retrievers/test_auto_merging_retriever_async.py Async equivalent variable rebinding fix for mypy.
Suppressed comments (3)

test/components/retrievers/test_multi_retriever.py:237

  • scores is inferred as list[float | None], which forces # type: ignore[type-var] on the ordering assertion. You can avoid the ignore while still failing the test if any score is None by building a list[float] with an explicit loop and per-document assertion.
        scores = [doc.score for doc in result["documents"]]
        assert all(score is not None for score in scores)
        assert scores == sorted(scores, reverse=True)  # type: ignore[type-var]

test/components/retrievers/test_multi_retriever.py:452

  • scores is inferred as list[float | None], which forces # type: ignore[type-var] on the ordering assertion. You can avoid the ignore while still failing the test if any score is None by building a list[float] with an explicit loop and per-document assertion.
        assert all(doc.score is not None for doc in result["documents"])
        scores = [doc.score for doc in result["documents"]]
        assert scores == sorted(scores, reverse=True)  # type: ignore[type-var]

test/components/retrievers/test_multi_retriever.py:519

  • scores is inferred as list[float | None], which forces # type: ignore[type-var] on the ordering assertion. You can avoid the ignore while still failing the test if any score is None by building a list[float] with an explicit loop and per-document assertion.
        scores = [doc.score for doc in result["documents"]]
        assert all(score is not None for score in scores)
        assert scores == sorted(scores, reverse=True)  # type: ignore[type-var]

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +73 to +76
docs = result["documents"]
assert all(doc.score is not None for doc in docs)
scores = [doc.score for doc in docs]
assert scores == sorted(scores, reverse=True) # type: ignore[type-var]
Comment on lines +50 to +53
docs = result["documents"]
assert all(doc.score is not None for doc in docs)
scores = [doc.score for doc in docs]
assert scores == sorted(scores, reverse=True) # type: ignore[type-var]
Comment on lines +59 to +62
docs = result["documents"]
assert all(doc.score is not None for doc in docs)
scores = [doc.score for doc in docs]
assert scores == sorted(scores, reverse=True) # type: ignore[type-var]
Comment on lines +137 to +139
assert all(doc.score is not None for doc in result["documents"])
scores = [doc.score for doc in result["documents"]]
assert scores == sorted(scores, reverse=True)
assert scores == sorted(scores, reverse=True) # type: ignore[type-var]
@github-actions

Copy link
Copy Markdown
Contributor

Coverage report

This PR does not seem to contain any modification to coverable code.

@ShousenZHANG

Copy link
Copy Markdown
Contributor Author

Good call — done in b17cb41, and it removed all seven type-var ignores rather than just the four you flagged.

Each site now collects the scores in an explicit loop:

docs = result["documents"]
scores: list[float] = []
for doc in docs:
    assert doc.score is not None
    scores.append(doc.score)
assert scores == sorted(scores, reverse=True)

scores is a list[float] from the annotation, so sorted type-checks on its own. The runtime check is also sharper than the all(...) version it replaces: a failure now points at the specific document whose score is missing instead of just reporting that one of them was.

That takes the suppressions in this PR from 20 down to 13, and the remaining ones are all arg-type / method-assign on test doubles.

Re-verified: hatch run test:types -> Success: no issues found in 479 source files, mypy --warn-unused-ignores on the directory is clean, hatch run test:unit test/components/retrievers/ -> 194 passed, and hatch run fmt-check is clean across the repo.

Adds the directory to the `types` target and clears the 78 errors that
surfaced, without changing what any test asserts:

- In the auto-merging retriever tests, `docs` was bound first to the list of
  input documents, then to the splitter's dict result, then to the retriever's.
  Give each value its own name (`docs`, `split_docs`, `merged`) so mypy can
  keep one type per variable. This removes 40 of the errors on its own.
- Annotate the mock retrievers' `run` / `run_async` and the parametrised
  pipeline tests, which were missing parameter and return types.
- Assert that every document has a score before ordering them, then keep a
  narrow `# type: ignore[type-var]` on the `sorted` call: `Document.score` is
  `float | None` and mypy does not narrow through the list comprehension.
- Add narrow ignores where a test double is passed where the component asks
  for the real protocol type, and where a method is monkeypatched.
Follows the review suggestion: collecting the scores in an explicit loop with
a per-document assertion narrows the list to `list[float]`, so the ordering
assertions no longer need `# type: ignore[type-var]`. The runtime check is
also sharper, since a failure now names the document whose score is missing.
@ShousenZHANG
ShousenZHANG force-pushed the test/type-check-retriever-tests branch from b17cb41 to ba03755 Compare August 28, 2026 02:31
@ShousenZHANG

Copy link
Copy Markdown
Contributor Author

Rebased — this was conflicting against main after #12483 landed, since both increments edit the same types = "..." line. Resolved by keeping both entries in alphabetical order, so the target now covers extractors/ and retrievers/ alongside everything else.

Re-verified on the rebased branch: hatch run test:types -> Success: no issues found in 484 source files, hatch run test:unit test/components/retrievers/ -> 194 passed, hatch run fmt-check clean across the repo.

Worth flagging for whoever picks up the next increment: with extractors/, builders/, evaluators/ and retrievers/ now merged or queued, only fetchers/ (#12435) and preprocessors/ are left, and every one of these PRs contends on that single line. #12435 has been conflicting since 22 Aug for the same reason and just needs a one-line rebase.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants