django-stubs icon indicating copy to clipboard operation
django-stubs copied to clipboard

VSCode/Pylance and mypy emit error on valid consumption of the StreamingHttpResponse.streaming_content iterator

Open biblicabeebli opened this issue 6 months ago • 3 comments

Bug report

What's wrong

Getting an error on a reasonable line in my test suite involving a StreamingHttpResponse.streaming_content in vscode / pylance and mypy.

As long as the type is identified by the type checker it will emit the error, stick this anywhere:

from django.http import StreamingHttpResponse
g = (str(x).encode() for x in range(100))  # does not even matter if this is real....
response = StreamingHttpResponse(g, status_code=200)
content = b"".join(response.streaming_content)  # <- mypy/pylance error

The code iterates over it just fine, the join returns bytes.

mypy emits:

error: Argument 1 to "join" of "bytes" has incompatible type "Iterator[bytes] | AsyncIterator[bytes]"; expected "Iterable[Buffer]"  [arg-type]

in VSCode the Pylance popup states

Argument of type "Iterable[object] | AsyncIterable[object]" cannot be assigned to parameter "iterable_of_bytes" of type "Iterable[ReadableBuffer]" in function "join"
  Type "Iterable[object] | AsyncIterable[object]" is not assignable to type "Iterable[ReadableBuffer]"
    "AsyncIterable[object]" is incompatible with protocol "Iterable[ReadableBuffer]"
      "__iter__" is not presentPylance[reportArgumentType](https://github.com/microsoft/pyright/blob/main/docs/configuration.md#reportArgumentType)
(variable) streaming_content: Iterable[object] | AsyncIterable[object]

What would be correct

No type warning/error in the type checker there. (Maybe I'm missing something subtle about typing, but imo that code should pass type inspection.)

It seems likely that swapping bytes for buffer/Buffer fixes this, but I'm nowhere near fluent enough with this stuff to proceed further. The detail with async being incompatible seems like a different problem, but again, this just is not at my level.

System information

  • OS:
  • python version: 3.12.x
  • django version: 4.2.21
  • mypy version: 1.15.0
  • django-stubs version: 5.2.0
  • django-stubs-ext version: 5.2.0 Testing on the most recent version of pylance included with vscode, not the beta.

biblicabeebli avatar May 12 '25 22:05 biblicabeebli

I hit this as well a long while ago and here's how I fixed it https://github.com/getsentry/sentry/commit/194fefd0bd6deeb9363a7a6a5f5b162604e60d88

asottile-sentry avatar May 20 '25 17:05 asottile-sentry

~~Unless I am interpreting it incorrectly, that solution to this typing issue is different code that does not overlap with this issue.~~ I don't know what happened but I was reading the wrong code somehow. Using asserts to narrow the type is a kluge and makes mess.

The problem is the typing, not the code.

The correct solution to this one is to find a way to make the typing work on bytes.join(), which is unambiguously valid.

biblicabeebli avatar May 21 '25 01:05 biblicabeebli

it's not though -- bytes.join can't receive an async iterator

you're reading my patch backwards btw -- the fix is to use .getvalue()

asottile-sentry avatar May 21 '25 01:05 asottile-sentry