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

QueryDict __getitem__ wrong type #1010

Closed
StefanBrand opened this issue Jun 21, 2022 · 3 comments · Fixed by typeddjango/djangorestframework-stubs#237
Closed

QueryDict __getitem__ wrong type #1010

StefanBrand opened this issue Jun 21, 2022 · 3 comments · Fixed by typeddjango/djangorestframework-stubs#237
Labels
bug Something isn't working

Comments

@StefanBrand
Copy link

Bug report

What's wrong

In our code base I get Type of "self.request.query_params["start_date"]" is "str | List[object]" after upgrading django-stubs from 1.8.0 to 1.12.0.

Reproducible example:

from django.http import QueryDict


query_params = QueryDict()
reveal_type(query_params["foo"])

Type of "query_params["foo"]" is "str | List[object]"

According to Django docs, QueryDict.__getitem__ always returns one value, never a list:

Returns the value for the given key. If the key has more than one value, it returns the last value.

How is that should be

Type of "query_params["foo"]" should be "str"

System information

  • OS: python:3.9.1 Docker image
  • python version: 3.9.1
  • django version: 4.0.1
  • mypy version: 0.931
  • django-stubs version: 1.12.0
    - django-stubs-ext version:
@StefanBrand StefanBrand added the bug Something isn't working label Jun 21, 2022
@sobolevn
Copy link
Member

СС @intgr

@intgr
Copy link
Collaborator

intgr commented Jun 22, 2022

According to Django docs, QueryDict.__getitem__ always returns one value, never a list:

Returns the value for the given key. If the key has more than one value, it returns the last value.

You would think so, but actually:

In [6]: from django.http.request import QueryDict
In [7]: q = QueryDict(mutable=True)

In [8]: q.setlist('foo', ['value'])
In [9]: q['foo']
Out[9]: 'value'

In [10]: q.setlist('bar', [])
In [11]: q['bar']
Out[11]: []                # <-- !?!?

I would argue this is a bug in Django, but I don't think this has been reported upstream.

#909 added the hint that QueryDict.__getattr__ may return list, and #925 added the _ImmutableQueryDict hack to work around the common usages where lists shouldn't occur. See #925 (comment) for relevant discussion.

Type of "self.request.query_params["start_date"]" is "str | List[object]"

It looks like you're using django-rest-framework, query_params comes from djangorestframework-stubs.

This can be fixed by using _ImmutableQueryDict there. I have opened a pull request: typeddjango/djangorestframework-stubs#237

(But if this continues to cause problems, personally I'm not opposed to reverting the complexity created for _ImmutableQueryDict and going back to the un-pedantic but "wrong" type hint that __getattr__ returns str.)

@intgr
Copy link
Collaborator

intgr commented Jun 22, 2022

Cc: @sterliakov

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Development

Successfully merging a pull request may close this issue.

3 participants