-
-
Notifications
You must be signed in to change notification settings - Fork 454
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
QuerySet.annotate improvements (#398)
* QuerySet.annotate returns self-type. Attribute access falls back to Any. - QuerySets that have an annotated model do not report errors during .filter() when called with invalid fields. - QuerySets that have an annotated model return ordinary dict rather than TypedDict for .values() - QuerySets that have an annotated model return Any rather than typed Tuple for .values_list() * Fix .annotate so it reuses existing annotated types. Fixes error in typechecking Django testsuite. * Fix self-typecheck error * Fix flake8 * Fix case of .values/.values_list before .annotate. * Extra ignores for Django 2.2 tests (false positives due to tests assuming QuerySet.first() won't return None) Fix mypy self-check. * More tests + more precise typing in case annotate called before values_list. Cleanup tests. * Test and fix annotate in combination with values/values_list with no params. * Remove line that does nothing :) * Formatting fixes * Address code review * Fix quoting in tests after mypy changed things * Use Final * Use typing_extensions.Final * Fixes after ValuesQuerySet -> _ValuesQuerySet refactor. Still not passing tests yet. * Fix inheritance of _ValuesQuerySet and remove unneeded type ignores. This allows the test "annotate_values_or_values_list_before_or_after_annotate_broadens_type" to pass. * Make it possible to annotate user code with "annotated models", using PEP 583 Annotated type. * Add docs * Make QuerySet[_T] an external alias to _QuerySet[_T, _T]. This currently has the drawback that error messages display the internal type _QuerySet, with both type arguments. See also discussion on #661 and #608. Fixes #635: QuerySet methods on Managers (like .all()) now return QuerySets rather than Managers. Address code review by @sobolevn. * Support passing TypedDicts to WithAnnotations * Add an example of an error to README regarding WithAnnotations + TypedDict. * Fix runtime behavior of ValuesQuerySet alias (you can't extend Any, for example). Fix some edge case with from_queryset after QuerySet changed to be an alias to _QuerySet. Can't make a minimal test case as this only occurred on a large internal codebase. * Fix issue when using from_queryset in some cases when having an argument with a type annotation on the QuerySet. The mypy docstring on anal_type says not to call defer() after it.
- Loading branch information
Showing
25 changed files
with
860 additions
and
123 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,6 @@ | ||
from .aliases import ValuesQuerySet as ValuesQuerySet | ||
from .annotations import Annotations as Annotations | ||
from .annotations import WithAnnotations as WithAnnotations | ||
from .patch import monkeypatch as monkeypatch | ||
|
||
__all__ = ["monkeypatch", "ValuesQuerySet"] | ||
__all__ = ["monkeypatch", "ValuesQuerySet", "WithAnnotations", "Annotations"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,10 @@ | ||
import typing | ||
|
||
if typing.TYPE_CHECKING: | ||
from django.db.models.query import _T, _Row, _ValuesQuerySet | ||
from django.db.models.query import _T, _QuerySet, _Row | ||
|
||
ValuesQuerySet = _ValuesQuerySet[_T, _Row] | ||
ValuesQuerySet = _QuerySet[_T, _Row] | ||
else: | ||
ValuesQuerySet = typing.Any | ||
from django.db.models.query import QuerySet | ||
|
||
ValuesQuerySet = QuerySet |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
from typing import Any, Generic, Mapping, TypeVar | ||
|
||
from django.db.models.base import Model | ||
from typing_extensions import Annotated | ||
|
||
# Really, we would like to use TypedDict as a bound, but it's not possible | ||
_Annotations = TypeVar("_Annotations", covariant=True, bound=Mapping[str, Any]) | ||
|
||
|
||
class Annotations(Generic[_Annotations]): | ||
"""Use as `Annotations[MyTypedDict]`""" | ||
|
||
pass | ||
|
||
|
||
_T = TypeVar("_T", bound=Model) | ||
|
||
WithAnnotations = Annotated[_T, Annotations[_Annotations]] | ||
"""Alias to make it easy to annotate the model `_T` as having annotations `_Annotations` (a `TypedDict` or `Any` if not provided). | ||
Use as `WithAnnotations[MyModel]` or `WithAnnotations[MyModel, MyTypedDict]`. | ||
""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
from typing import Any | ||
|
||
from django_stubs_ext import ValuesQuerySet | ||
|
||
|
||
def test_extends_values_queryset() -> None: | ||
class MyQS(ValuesQuerySet[Any, Any]): | ||
pass |
Oops, something went wrong.