Skip to content

Preserve row type when .annotate() is called on a generic QuerySet#3379

Merged
sobolevn merged 1 commit into
typeddjango:masterfrom
federicobond:fix-values-annotate-generic-queryset
May 12, 2026
Merged

Preserve row type when .annotate() is called on a generic QuerySet#3379
sobolevn merged 1 commit into
typeddjango:masterfrom
federicobond:fix-values-annotate-generic-queryset

Conversation

@federicobond
Copy link
Copy Markdown
Contributor

@federicobond federicobond commented May 12, 2026

The row type was not being preserved for the TypeVar branch, so I extracted a _resolve_annotate_row_type helper to reuse on both branches.

Refs #602 (comment) (I think it may solve your issue @delfick but I haven't confirmed).

AI Policy

  • I have read and agree to the AI Policy, removed any "Co-Authored-By" lines attributing coding agents, and manually reviewed the final result

Comment thread tests/typecheck/managers/querysets/test_annotate.yml Outdated
@federicobond federicobond force-pushed the fix-values-annotate-generic-queryset branch from 8c51be0 to 1331ce1 Compare May 12, 2026 09:16
Copy link
Copy Markdown
Member

@sobolevn sobolevn left a comment

Choose a reason for hiding this comment

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

Thank you!

@sobolevn sobolevn merged commit 5a3a4cd into typeddjango:master May 12, 2026
54 of 55 checks passed
@UnknownPlatypus
Copy link
Copy Markdown
Contributor

@federicobond have you tried the test case in the issue ?

@federicobond
Copy link
Copy Markdown
Contributor Author

Yes, I tried and they should both work now, in some cases with the right adjustments to the annotation types.

@sobolevn
Copy link
Copy Markdown
Member

@federicobond you can contribute these tests as well, more tests in the complex areas - the better.

@delfick
Copy link
Copy Markdown
Contributor

delfick commented May 12, 2026

oh cool, thanks @federicobond !!!

Seems this removes 7 of the errors for me, I still have 56 left, I hopefully should be able to do some more detective work on them :)

class FooModel(models.Model):
objects = FooManager()

- case: values_then_annotate_on_generic_queryset_typevar
Copy link
Copy Markdown
Contributor

@delfick delfick May 13, 2026

Choose a reason for hiding this comment

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

Seems here is another case that shows a problem

- case: values_are_carried_through
  main: |
    from typing import Any
    from typing_extensions import reveal_type, TypeVar
    from django.db import models
    import myapp.models

    with_annotate = myapp.models.Thing.objects.all().annotate(foo=models.Max("id"))

    reveal_type(with_annotate) # N: Revealed type is "django.db.models.query.QuerySet[myapp.models.Thing@AnnotatedWith[TypedDict({'foo': Any})], myapp.models.Thing@AnnotatedWith[TypedDict({'foo': Any})]]"

    with_values = with_annotate.values("id").distinct()

    reveal_type(with_values) # N: Revealed type is "django.db.models.query.QuerySet[myapp.models.Thing@AnnotatedWith[TypedDict({'foo': Any})], TypedDict({'id': int})]"
  installed_apps:
    - myapp
  files:
    - path: myapp/__init__.py
    - path: myapp/models.py
      content: |
        from django.db import models
        from typing import Self

        class Thing(models.Model):
            pass

If I change with_values = with_annotate.values("id").distinct() to not have the distinct() then it passes.

edit: and seems similar for doing a slice qs[:max_sample_results]

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.

also I've noticed that the .annotate will erase the custom queryset type if there is one.

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.

I've run out of time to investigate, but seems for that new test case above, the fix will be something to do with

return default_return_type.copy_modified(args=[annotated_type, annotated_type])

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, both cases should be fixed by #3383

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

Labels

None yet

Development

Successfully merging this pull request may close these issues.

4 participants