Skip to content

feat: annotate HttpRequest as readable, HttpResponse as writable#3218

Open
alexei wants to merge 1 commit intotypeddjango:masterfrom
alexei:feat-readable_request_writable_response
Open

feat: annotate HttpRequest as readable, HttpResponse as writable#3218
alexei wants to merge 1 commit intotypeddjango:masterfrom
alexei:feat-readable_request_writable_response

Conversation

@alexei
Copy link
Contributor

@alexei alexei commented Mar 24, 2026

HttpRequests are readable, while HttpResponses are writable. It's insufficient that they have read and write methods respectively, as one would have to use a Protocol. However Reader and Writer are already available in the io package and are better suited.

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.

you don't have to inherit from a protocol to make use of it. HttpRequest already should be compatible with Readable and HttpResponse should be compatible with Writable.

If you want, you can submit a test case for that.

@alexei
Copy link
Contributor Author

alexei commented Mar 24, 2026

It's my fault for not explaining this. I found this while writing to a response with a function that accepted a writable file-thing i.e. write_to_resp(content: bytes, output: Writer). I tried both IO and Writer on it and ty complained -- "Expected Writer, found HttpResponse". For file-like objects the Internet says to use IO, but the somewhat official recommendation is to use a Protocol, and that worked. Under these circumstances it should be reasonable to expect everyone to use IO or better yet Writer as they exist in the standard library.

@sobolevn
Copy link
Member

io.Reader or typing_extensions.Reader is just:

@runtime_checkable
class Reader(Protocol[T_co]):
    """Protocol for simple I/O reader instances.

    This protocol only supports blocking I/O.
    """

    __slots__ = ()

    @abc.abstractmethod
    def read(self, size: int = ..., /) -> T_co:
        """Read data from the input stream and return it.

        If *size* is specified, at most *size* items (bytes/characters) will be
        read.
        """

So, you don't need to modify HttpRequest to use it. Because it is already supported, HttpRequest.read exists here

def read(self, n: int | None = -1, /) -> bytes: ...
and matches the Reader protocol.

As I said before you can add a test case to typesafety/assert_type that they indeed match:

to_read: Reader = HttpRequest()

And the same for HttpResponse.

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