Skip to content

Provide more precise type hints for Table.get#602

Merged
msiemens merged 3 commits intomsiemens:masterfrom
alex-ball:patch-1
Jan 17, 2026
Merged

Provide more precise type hints for Table.get#602
msiemens merged 3 commits intomsiemens:masterfrom
alex-ball:patch-1

Conversation

@alex-ball
Copy link
Contributor

When working with pyright (at least), the return value from calls to Table.get is the declared type Document | list[Document] | None. To avoid type errors when using the return value, one therefore has do one of the following:

  • Exclude the line from type checking
  • Introduce an assertion, e.g. assert isinstance(obj, Document)
  • Test, say, if instance(obj, Document) instead of if obj is not None or if obj

It would be highly convenient if static type checkers could understand the logic of the method, and knew that it returns a list if and only if doc_id is None and a list is passed to doc_ids.

Here are the typing overloads that do the trick. I've confirmed that pytest and mypy remain happy with these in place. I haven't covered the case that passing no arguments leads to a NoReturn return type, as that's adding more information than was already there, but I could if you wanted.

I could provide some assert_type tests if you like but I'm not so familiar with the best place to put them (and they would involve a typing_extensions dependency on older Pythons).

@msiemens
Copy link
Owner

Hey, thanks for the PR! It seems like the type checking unit tests fail:

381: error: All overload variants of "get" of "Table" require at least one argument  [call-overload]
381: note: Possible overload variants:
381: note:     def get(self, cond: QueryLike, doc_id: None = ..., doc_ids: None = ...) -> Optional[Document]
381: note:     def get(self, *, cond: QueryLike, doc_id: None = ..., doc_ids: None = ...) -> Optional[Document]
381: note:     def get(self, cond: Optional[QueryLike], doc_id: int, doc_ids: Optional[List[Any]] = ...) -> Optional[Document]
381: note:     def get(self, *, cond: Optional[QueryLike] = ..., doc_id: int, doc_ids: Optional[List[Any]] = ...) -> Optional[Document]
381: note:     def get(self, cond: Optional[QueryLike], doc_id: None, doc_ids: List[Any]) -> List[Document]
381: note:     def get(self, cond: Optional[QueryLike], *, doc_id: None = ..., doc_ids: List[Any]) -> List[Document]
381: note:     def get(self, *, cond: Optional[QueryLike] = ..., doc_id: None = ..., doc_ids: List[Any]) -> List[Document]

Can you take a closer look at that? See eg. https://github.com/msiemens/tinydb/actions/runs/20165183963/job/59009114221?pr=602

@alex-ball
Copy link
Contributor Author

alex-ball commented Jan 5, 2026

Ah, this looks like it relates to the comment I made:

I haven't covered the case that passing no arguments leads to a NoReturn return type, as that's adding more information than was already there, but I could if you wanted.

I've now added that missing case, and the error no longer occurs.

@msiemens msiemens merged commit 3517ddc into msiemens:master Jan 17, 2026
4 of 19 checks passed
@msiemens
Copy link
Owner

Seems like the CI failures are unrelated to this PR. Thanks for contributing!

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