Skip to content

fix: accept any run signature in Component protocol under Pyrefly strict - #13401

Open
Cha-Imaa wants to merge 2 commits into
deepset-ai:mainfrom
Cha-Imaa:fix/issue-13378
Open

Cha-Imaa wants to merge 2 commits into
deepset-ai:mainfrom
Cha-Imaa:fix/issue-13378

Conversation

@Cha-Imaa

Copy link
Copy Markdown
Contributor

Fixes #13378

Related Issues

Cause

The Component protocol declared run as def run(self, *args: Any, **kwargs: Any) -> Mapping[str, Any]. The typing spec says a (*args: Any, **kwargs: Any) signature should be treated like ... ("accepts any arguments"), and mypy, Pyright and Pyrefly's default preset follow that rule.

Pyrefly's --preset strict enables strict-callable-subtyping, which turns the rule off. Under that setting, a component whose run takes named parameters (for example, run(self, documents: list[Document])) no longer matches the protocol, so every Pipeline.add_component(...) call fails with bad-argument-type.

Fix

In haystack/core/component/component.py, type checkers and the runtime now get different definitions of run (an if TYPE_CHECKING: split):

  • Type checkers: See a read-only property returning Callable[..., Mapping[str, Any]]. A literal ... means "any signature" in every checker, including Pyrefly with strict-callable-subtyping. It is a property rather than a plain run: Callable[...] annotation because a plain annotation declares a settable attribute, and mypy rejects classes whose run is a (read-only) method.
  • Runtime: run stays a regular method, unchanged. A property would make run a non-method protocol member, and issubclass(SomeClass, Component) would then raise TypeError on the @runtime_checkable protocol.

isinstance() / issubclass() checks, the @component decorator, and pipelines therefore behave exactly as before.

Other changes

  • test/core/component/test_component.py: Added an issubclass(MockComponent, Component) assertion. It guards the runtime half of the fix: if someone later "simplifies" run into a plain property, this test fails.
  • test/core/pipeline/test_pipeline_base.py: test_add_invalid_component_name passed the class FakeComponent where an instance is expected. The old (*args, **kwargs) signature let mypy accept a class object; the new protocol correctly flags it, so the test now passes FakeComponent(). The test still checks the same name validation.
  • Added a release note.

How did you test it?

Issue reproduction

Reproduced the issue with the example from #13378 (a pipeline with DocumentWriter plus a custom @component):

  • Before: pyrefly check --preset strict (Pyrefly 1.4.0) reports bad-argument-type on every add_component call.
  • After: 0 errors with Pyrefly strict. The same file also passes Pyright (1.1.414) and mypy with no errors.

Type checking

  • hatch run test:types: No issues found in 566 source files.

Unit tests

  • hatch run test:unit (full unit suite, Python 3.11, Windows): 6966 passed, 1 failed, 49 skipped.

The single failure is test/dataclasses/test_byte_stream.py::test_from_file_path_guess_mime_type[spam.csv-...]. It is Windows-specific and unrelated: Windows' registry maps .csv to application/vnd.ms-excel instead of text/csv.

Lint and formatting

  • Lint/format (hatch run fmt-check), codespell and the release-note backtick check pass on the changed files.

Notes for the reviewer

  • The core change is the if TYPE_CHECKING: block in component.py. The comment above it explains why both branches are needed.
  • No automated Pyrefly check was added. Pyrefly is not a project dependency, and adding it to CI felt out of scope for this fix. Happy to add one if you'd like.
  • Side effect (also mentioned in the release note): mypy now reports passing a component class instead of an instance (add_component("name", MyComponent)), which previously type-checked silently.

Checklist

Fixes deepset-ai#13378

Co-authored-by: toobatehreem <51713056+toobatehreem@users.noreply.github.com>
@Cha-Imaa
Cha-Imaa requested a review from a team as a code owner October 22, 2026 18:39
@Cha-Imaa
Cha-Imaa requested review from julian-risch and removed request for a team October 22, 2026 18:39
@vercel

vercel Bot commented Oct 22, 2026

Copy link
Copy Markdown
Contributor

@Cha-Imaa is attempting to deploy a commit to the deepset Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions github-actions Bot added the type:documentation Improvements on the docs label Oct 22, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Coverage report

Click to see where and how coverage changed

FileStatementsMissingCoverageCoverage
(new stmts)
Lines missing
  haystack/core/component
  component.py
Project Total  

This report was generated by python-coverage-comment-action

This branch has not been deployed

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Pyrefly strict mode rejects Haystack components

1 participant