Describe the bug
The streaming type containers introduced in v1.6 (ninja.streaming.SSE,
ninja.streaming.JSONL) support SSE[Schema] syntax at runtime via
__class_getitem__, but the underlying StreamFormat base class does not
inherit from typing.Generic. As a result, mypy (and any other type checker
that doesn't special-case __class_getitem__) rejects the documented usage:
error: The type "type[SSE]" is not generic and not indexable [misc]
This forces users with strict mypy configurations to add # type: ignore[misc]
to every streaming endpoint, which weakens the type-safety story that
django-ninja otherwise has.
Versions
- django-ninja: 1.6.2
- mypy: 1.20.0
- Python: 3.14
Reproduction
from ninja import NinjaAPI, Schema
from ninja.streaming import SSE
api = NinjaAPI()
class Event(Schema):
message: str
@api.get("/events", response=SSE[Event]) # mypy error here
async def stream(request):
yield {"message": "hello"}
Run mypy on the file:
error: The type "type[SSE]" is not generic and not indexable [misc]
Runtime works correctly - only static type checking fails.
Root cause
In ninja/streaming.py:
class StreamFormat:
media_type: str
def __class_getitem__(cls, item_type: type) -> "_StreamAlias":
return _StreamAlias(cls, item_type)
__class_getitem__ enables the runtime syntax, but mypy only treats a class
as subscriptable when it inherits from typing.Generic[T] (or one of the
special-cased stdlib generics).
Suggested fix
Make StreamFormat generic over the item type. The change is small and
shouldn't affect runtime behavior:
from typing import Generic, TypeVar
T = TypeVar("T")
class StreamFormat(Generic[T]):
media_type: str
# ... rest unchanged
SSE and JSONL then inherit the generic parameter automatically, and
SSE[Event] becomes a valid parameterized type for mypy.
Happy to send a PR if this approach is acceptable.
Describe the bug
The streaming type containers introduced in v1.6 (
ninja.streaming.SSE,ninja.streaming.JSONL) supportSSE[Schema]syntax at runtime via__class_getitem__, but the underlyingStreamFormatbase class does notinherit from
typing.Generic. As a result, mypy (and any other type checkerthat doesn't special-case
__class_getitem__) rejects the documented usage:This forces users with strict mypy configurations to add
# type: ignore[misc]to every streaming endpoint, which weakens the type-safety story that
django-ninja otherwise has.
Versions
Reproduction
Run
mypyon the file:Runtime works correctly - only static type checking fails.
Root cause
In
ninja/streaming.py:__class_getitem__enables the runtime syntax, but mypy only treats a classas subscriptable when it inherits from
typing.Generic[T](or one of thespecial-cased stdlib generics).
Suggested fix
Make
StreamFormatgeneric over the item type. The change is small andshouldn't affect runtime behavior:
SSEandJSONLthen inherit the generic parameter automatically, andSSE[Event]becomes a valid parameterized type for mypy.Happy to send a PR if this approach is acceptable.