Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more method signatures for _ValuesQuerySet #661

Merged

Conversation

MichaelAquilina
Copy link
Contributor

@MichaelAquilina MichaelAquilina commented Jul 3, 2021

I have made things!

Follow up from #657 - I found more cases in my codebase where method signatures where incorrectly missing.

Looking at #608 it seems like this issue has been discussed at length already about why this is an issue.

My initial thoughts was that maybe there was a way of having:

  • an internal _QuerySet[_T, _Row] type
  • an external facing alias QuerySet[_T] which is equivalent to _QuerySet[_T, _T]
  • values list would then return _QuerySet[_T, _Row] as appropriate.

But based on the conversation you've had it seems like this might be harder than I assume it is?

The downside of keeping it in the current way is that we essentially need to redefine all QuerySet method signatures twice: Once for QuerySet and once for _ValuesQuerySet

query = MyUser.objects.values_list('name')
reveal_type(query.order_by("name").get()) # N: Revealed type is "Tuple[builtins.str]"
reveal_type(query.distinct("name").get()) # N: Revealed type is "Tuple[builtins.str]"
reveal_type(query.distinct().get()) # N: Revealed type is "Tuple[builtins.str]"
reveal_type(query.all().get()) # N: Revealed type is "Tuple[builtins.str]"
reveal_type(query.filter(age__gt=16).get()) # N: Revealed type is "Tuple[builtins.str]"
reveal_type(query.exclude(age__lte=16).get()) # N: Revealed type is "Tuple[builtins.str]"
reveal_type(query.annotate(name_length=Length("name")).get()) # N: Revealed type is "Any"
Copy link
Contributor Author

Choose a reason for hiding this comment

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

might be worth checking this one is correct - I wasnt 100% sure about the approach for annotate

Copy link
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.

Ok, let's keep Any for now, but after #398 we would need to change that!

@@ -154,6 +154,9 @@ class _ValuesQuerySet(Generic[_T, _Row], Collection[_Row], Reversible[_Row], Que
def distinct(self, *field_names: Any) -> _ValuesQuerySet[_T, _Row]: ... # type: ignore
def order_by(self, *field_names: Any) -> _ValuesQuerySet[_T, _Row]: ... # type: ignore
def all(self) -> _ValuesQuerySet[_T, _Row]: ... # type: ignore
def annotate(self, *args: Any, **kwargs: Any) -> _ValuesQuerySet[_T, Any]: ...
Copy link
Member

Choose a reason for hiding this comment

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

Please, see #398

We are working on fixing Any there

@sobolevn sobolevn merged commit 5c3ce17 into typeddjango:master Jul 3, 2021
@sobolevn
Copy link
Member

sobolevn commented Jul 3, 2021

My initial thoughts was that maybe there was a way of having

Do you have some free time to try this out? 🙂
I would love to have this ValuesQuerySet removed for good!

@MichaelAquilina
Copy link
Contributor Author

Do you have some free time to try this out? slightly_smiling_face
I would love to have this ValuesQuerySet removed for good!

I'd definitely want to give it a try at the very least :) is there anything in particular I should be aware of before diving in?

@MichaelAquilina MichaelAquilina deleted the feat/more-method-stubs branch July 4, 2021 11:47
@sobolevn
Copy link
Member

sobolevn commented Jul 4, 2021

See #608 and #144 and #33

syastrov added a commit to syastrov/django-stubs that referenced this pull request Jul 7, 2021
This currently has the drawback that error messages display the internal type _QuerySet, with both type arguments.

See also discussion on typeddjango#661 and typeddjango#608.

Fixes typeddjango#635: QuerySet methods on Managers (like .all()) now return QuerySets rather than Managers.

Address code review by @sobolevn.
sobolevn pushed a commit that referenced this pull request Jul 23, 2021
* 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.
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.

2 participants