{
    "file_diffs": [
        {
            "old_file_content": "",
            "new_file_content": "Rejected `\\n` in `reason` values to avoid sending broken HTTP messages -- by :user:`Dreamsorcerer`.\n",
            "header": {
                "file": {
                    "path": "CHANGES/9167.bugfix.rst"
                },
                "misc_line": "new file mode 100644"
            },
            "index_line": {
                "old_commit_hash": "00000000",
                "new_commit_hash": "4c33c8ad",
                "mode": ""
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "/dev/null"
            },
            "plus_file": {
                "path": "b/CHANGES/9167.bugfix.rst"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 0,
                            "length": 0
                        },
                        "new_range": {
                            "start": 1,
                            "length": null
                        },
                        "section": ""
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "Rejected `\\n` in `reason` values to avoid sending broken HTTP messages -- by :user:`Dreamsorcerer`.",
                                "type": "added"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "import asyncio\nimport collections.abc\nimport datetime\nimport enum\nimport json\nimport math\nimport time\nimport warnings\nimport zlib\nfrom concurrent.futures import Executor\nfrom http import HTTPStatus\nfrom http.cookies import SimpleCookie\nfrom typing import (\n    TYPE_CHECKING,\n    Any,\n    Dict,\n    Iterator,\n    MutableMapping,\n    Optional,\n    Union,\n    cast,\n)\n\nfrom multidict import CIMultiDict, istr\n\nfrom . import hdrs, payload\nfrom .abc import AbstractStreamWriter\nfrom .compression_utils import ZLibCompressor\nfrom .helpers import (\n    ETAG_ANY,\n    QUOTED_ETAG_RE,\n    ETag,\n    HeadersMixin,\n    must_be_empty_body,\n    parse_http_date,\n    rfc822_formatted_time,\n    sentinel,\n    should_remove_content_length,\n    validate_etag_value,\n)\nfrom .http import SERVER_SOFTWARE, HttpVersion10, HttpVersion11\nfrom .payload import Payload\nfrom .typedefs import JSONEncoder, LooseHeaders\n\n__all__ = (\"ContentCoding\", \"StreamResponse\", \"Response\", \"json_response\")\n\n\nif TYPE_CHECKING:\n    from .web_request import BaseRequest\n\n    BaseClass = MutableMapping[str, Any]\nelse:\n    BaseClass = collections.abc.MutableMapping\n\n\n# TODO(py311): Convert to StrEnum for wider use\nclass ContentCoding(enum.Enum):\n    # The content codings that we have support for.\n    #\n    # Additional registered codings are listed at:\n    # https://www.iana.org/assignments/http-parameters/http-parameters.xhtml#content-coding\n    deflate = \"deflate\"\n    gzip = \"gzip\"\n    identity = \"identity\"\n\n\n############################################################\n# HTTP Response classes\n############################################################\n\n\nclass StreamResponse(BaseClass, HeadersMixin):\n\n    _length_check = True\n\n    _body: Union[None, bytes, bytearray, Payload]\n\n    def __init__(\n        self,\n        *,\n        status: int = 200,\n        reason: Optional[str] = None,\n        headers: Optional[LooseHeaders] = None,\n    ) -> None:\n        self._body = None\n        self._keep_alive: Optional[bool] = None\n        self._chunked = False\n        self._compression = False\n        self._compression_strategy: int = zlib.Z_DEFAULT_STRATEGY\n        self._compression_force: Optional[ContentCoding] = None\n        self._cookies = SimpleCookie()\n\n        self._req: Optional[BaseRequest] = None\n        self._payload_writer: Optional[AbstractStreamWriter] = None\n        self._eof_sent = False\n        self._must_be_empty_body: Optional[bool] = None\n        self._body_length = 0\n        self._state: Dict[str, Any] = {}\n\n        if headers is not None:\n            self._headers: CIMultiDict[str] = CIMultiDict(headers)\n        else:\n            self._headers = CIMultiDict()\n\n        self.set_status(status, reason)\n\n    @property\n    def prepared(self) -> bool:\n        return self._eof_sent or self._payload_writer is not None\n\n    @property\n    def task(self) -> \"Optional[asyncio.Task[None]]\":\n        if self._req:\n            return self._req.task\n        else:\n            return None\n\n    @property\n    def status(self) -> int:\n        return self._status\n\n    @property\n    def chunked(self) -> bool:\n        return self._chunked\n\n    @property\n    def compression(self) -> bool:\n        return self._compression\n\n    @property\n    def reason(self) -> str:\n        return self._reason\n\n    def set_status(\n        self,\n        status: int,\n        reason: Optional[str] = None,\n    ) -> None:\n        assert (\n            not self.prepared\n        ), \"Cannot change the response status code after the headers have been sent\"\n        self._status = int(status)\n        if reason is None:\n            try:\n                reason = HTTPStatus(self._status).phrase\n            except ValueError:\n                reason = \"\"\n        self._reason = reason\n\n    @property\n    def keep_alive(self) -> Optional[bool]:\n        return self._keep_alive\n\n    def force_close(self) -> None:\n        self._keep_alive = False\n\n    @property\n    def body_length(self) -> int:\n        return self._body_length\n\n    @property\n    def output_length(self) -> int:\n        warnings.warn(\"output_length is deprecated\", DeprecationWarning)\n        assert self._payload_writer\n        return self._payload_writer.buffer_size\n\n    def enable_chunked_encoding(self, chunk_size: Optional[int] = None) -> None:\n        \"\"\"Enables automatic chunked transfer encoding.\"\"\"\n        self._chunked = True\n\n        if hdrs.CONTENT_LENGTH in self._headers:\n            raise RuntimeError(\n                \"You can't enable chunked encoding when a content length is set\"\n            )\n        if chunk_size is not None:\n            warnings.warn(\"Chunk size is deprecated #1615\", DeprecationWarning)\n\n    def enable_compression(\n        self,\n        force: Optional[Union[bool, ContentCoding]] = None,\n        strategy: int = zlib.Z_DEFAULT_STRATEGY,\n    ) -> None:\n        \"\"\"Enables response compression encoding.\"\"\"\n        # Backwards compatibility for when force was a bool <0.17.\n        if isinstance(force, bool):\n            force = ContentCoding.deflate if force else ContentCoding.identity\n            warnings.warn(\n                \"Using boolean for force is deprecated #3318\", DeprecationWarning\n            )\n        elif force is not None:\n            assert isinstance(\n                force, ContentCoding\n            ), \"force should one of None, bool or ContentEncoding\"\n\n        self._compression = True\n        self._compression_force = force\n        self._compression_strategy = strategy\n\n    @property\n    def headers(self) -> \"CIMultiDict[str]\":\n        return self._headers\n\n    @property\n    def cookies(self) -> SimpleCookie:\n        return self._cookies\n\n    def set_cookie(\n        self,\n        name: str,\n        value: str,\n        *,\n        expires: Optional[str] = None,\n        domain: Optional[str] = None,\n        max_age: Optional[Union[int, str]] = None,\n        path: str = \"/\",\n        secure: Optional[bool] = None,\n        httponly: Optional[bool] = None,\n        version: Optional[str] = None,\n        samesite: Optional[str] = None,\n    ) -> None:\n        \"\"\"Set or update response cookie.\n\n        Sets new cookie or updates existent with new value.\n        Also updates only those params which are not None.\n        \"\"\"\n        old = self._cookies.get(name)\n        if old is not None and old.coded_value == \"\":\n            # deleted cookie\n            self._cookies.pop(name, None)\n\n        self._cookies[name] = value\n        c = self._cookies[name]\n\n        if expires is not None:\n            c[\"expires\"] = expires\n        elif c.get(\"expires\") == \"Thu, 01 Jan 1970 00:00:00 GMT\":\n            del c[\"expires\"]\n\n        if domain is not None:\n            c[\"domain\"] = domain\n\n        if max_age is not None:\n            c[\"max-age\"] = str(max_age)\n        elif \"max-age\" in c:\n            del c[\"max-age\"]\n\n        c[\"path\"] = path\n\n        if secure is not None:\n            c[\"secure\"] = secure\n        if httponly is not None:\n            c[\"httponly\"] = httponly\n        if version is not None:\n            c[\"version\"] = version\n        if samesite is not None:\n            c[\"samesite\"] = samesite\n\n    def del_cookie(\n        self,\n        name: str,\n        *,\n        domain: Optional[str] = None,\n        path: str = \"/\",\n        secure: Optional[bool] = None,\n        httponly: Optional[bool] = None,\n        samesite: Optional[str] = None,\n    ) -> None:\n        \"\"\"Delete cookie.\n\n        Creates new empty expired cookie.\n        \"\"\"\n        # TODO: do we need domain/path here?\n        self._cookies.pop(name, None)\n        self.set_cookie(\n            name,\n            \"\",\n            max_age=0,\n            expires=\"Thu, 01 Jan 1970 00:00:00 GMT\",\n            domain=domain,\n            path=path,\n            secure=secure,\n            httponly=httponly,\n            samesite=samesite,\n        )\n\n    @property\n    def content_length(self) -> Optional[int]:\n        # Just a placeholder for adding setter\n        return super().content_length\n\n    @content_length.setter\n    def content_length(self, value: Optional[int]) -> None:\n        if value is not None:\n            value = int(value)\n            if self._chunked:\n                raise RuntimeError(\n                    \"You can't set content length when chunked encoding is enable\"\n                )\n            self._headers[hdrs.CONTENT_LENGTH] = str(value)\n        else:\n            self._headers.pop(hdrs.CONTENT_LENGTH, None)\n\n    @property\n    def content_type(self) -> str:\n        # Just a placeholder for adding setter\n        return super().content_type\n\n    @content_type.setter\n    def content_type(self, value: str) -> None:\n        self.content_type  # read header values if needed\n        self._content_type = str(value)\n        self._generate_content_type_header()\n\n    @property\n    def charset(self) -> Optional[str]:\n        # Just a placeholder for adding setter\n        return super().charset\n\n    @charset.setter\n    def charset(self, value: Optional[str]) -> None:\n        ctype = self.content_type  # read header values if needed\n        if ctype == \"application/octet-stream\":\n            raise RuntimeError(\n                \"Setting charset for application/octet-stream \"\n                \"doesn't make sense, setup content_type first\"\n            )\n        assert self._content_dict is not None\n        if value is None:\n            self._content_dict.pop(\"charset\", None)\n        else:\n            self._content_dict[\"charset\"] = str(value).lower()\n        self._generate_content_type_header()\n\n    @property\n    def last_modified(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of Last-Modified HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self._headers.get(hdrs.LAST_MODIFIED))\n\n    @last_modified.setter\n    def last_modified(\n        self, value: Optional[Union[int, float, datetime.datetime, str]]\n    ) -> None:\n        if value is None:\n            self._headers.pop(hdrs.LAST_MODIFIED, None)\n        elif isinstance(value, (int, float)):\n            self._headers[hdrs.LAST_MODIFIED] = time.strftime(\n                \"%a, %d %b %Y %H:%M:%S GMT\", time.gmtime(math.ceil(value))\n            )\n        elif isinstance(value, datetime.datetime):\n            self._headers[hdrs.LAST_MODIFIED] = time.strftime(\n                \"%a, %d %b %Y %H:%M:%S GMT\", value.utctimetuple()\n            )\n        elif isinstance(value, str):\n            self._headers[hdrs.LAST_MODIFIED] = value\n\n    @property\n    def etag(self) -> Optional[ETag]:\n        quoted_value = self._headers.get(hdrs.ETAG)\n        if not quoted_value:\n            return None\n        elif quoted_value == ETAG_ANY:\n            return ETag(value=ETAG_ANY)\n        match = QUOTED_ETAG_RE.fullmatch(quoted_value)\n        if not match:\n            return None\n        is_weak, value = match.group(1, 2)\n        return ETag(\n            is_weak=bool(is_weak),\n            value=value,\n        )\n\n    @etag.setter\n    def etag(self, value: Optional[Union[ETag, str]]) -> None:\n        if value is None:\n            self._headers.pop(hdrs.ETAG, None)\n        elif (isinstance(value, str) and value == ETAG_ANY) or (\n            isinstance(value, ETag) and value.value == ETAG_ANY\n        ):\n            self._headers[hdrs.ETAG] = ETAG_ANY\n        elif isinstance(value, str):\n            validate_etag_value(value)\n            self._headers[hdrs.ETAG] = f'\"{value}\"'\n        elif isinstance(value, ETag) and isinstance(value.value, str):\n            validate_etag_value(value.value)\n            hdr_value = f'W/\"{value.value}\"' if value.is_weak else f'\"{value.value}\"'\n            self._headers[hdrs.ETAG] = hdr_value\n        else:\n            raise ValueError(\n                f\"Unsupported etag type: {type(value)}. \"\n                f\"etag must be str, ETag or None\"\n            )\n\n    def _generate_content_type_header(\n        self, CONTENT_TYPE: istr = hdrs.CONTENT_TYPE\n    ) -> None:\n        assert self._content_dict is not None\n        assert self._content_type is not None\n        params = \"; \".join(f\"{k}={v}\" for k, v in self._content_dict.items())\n        if params:\n            ctype = self._content_type + \"; \" + params\n        else:\n            ctype = self._content_type\n        self._headers[CONTENT_TYPE] = ctype\n\n    async def _do_start_compression(self, coding: ContentCoding) -> None:\n        if coding != ContentCoding.identity:\n            assert self._payload_writer is not None\n            self._headers[hdrs.CONTENT_ENCODING] = coding.value\n            self._payload_writer.enable_compression(\n                coding.value, self._compression_strategy\n            )\n            # Compressed payload may have different content length,\n            # remove the header\n            self._headers.popall(hdrs.CONTENT_LENGTH, None)\n\n    async def _start_compression(self, request: \"BaseRequest\") -> None:\n        if self._compression_force:\n            await self._do_start_compression(self._compression_force)\n        else:\n            # Encoding comparisons should be case-insensitive\n            # https://www.rfc-editor.org/rfc/rfc9110#section-8.4.1\n            accept_encoding = request.headers.get(hdrs.ACCEPT_ENCODING, \"\").lower()\n            for coding in ContentCoding:\n                if coding.value in accept_encoding:\n                    await self._do_start_compression(coding)\n                    return\n\n    async def prepare(self, request: \"BaseRequest\") -> Optional[AbstractStreamWriter]:\n        if self._eof_sent:\n            return None\n        if self._payload_writer is not None:\n            return self._payload_writer\n        self._must_be_empty_body = must_be_empty_body(request.method, self.status)\n        return await self._start(request)\n\n    async def _start(self, request: \"BaseRequest\") -> AbstractStreamWriter:\n        self._req = request\n        writer = self._payload_writer = request._payload_writer\n\n        await self._prepare_headers()\n        await request._prepare_hook(self)\n        await self._write_headers()\n\n        return writer\n\n    async def _prepare_headers(self) -> None:\n        request = self._req\n        assert request is not None\n        writer = self._payload_writer\n        assert writer is not None\n        keep_alive = self._keep_alive\n        if keep_alive is None:\n            keep_alive = request.keep_alive\n        self._keep_alive = keep_alive\n\n        version = request.version\n\n        headers = self._headers\n        for cookie in self._cookies.values():\n            value = cookie.output(header=\"\")[1:]\n            headers.add(hdrs.SET_COOKIE, value)\n\n        if self._compression:\n            await self._start_compression(request)\n\n        if self._chunked:\n            if version != HttpVersion11:\n                raise RuntimeError(\n                    \"Using chunked encoding is forbidden \"\n                    \"for HTTP/{0.major}.{0.minor}\".format(request.version)\n                )\n            if not self._must_be_empty_body:\n                writer.enable_chunking()\n                headers[hdrs.TRANSFER_ENCODING] = \"chunked\"\n            if hdrs.CONTENT_LENGTH in headers:\n                del headers[hdrs.CONTENT_LENGTH]\n        elif self._length_check:\n            writer.length = self.content_length\n            if writer.length is None:\n                if version >= HttpVersion11:\n                    if not self._must_be_empty_body:\n                        writer.enable_chunking()\n                        headers[hdrs.TRANSFER_ENCODING] = \"chunked\"\n                elif not self._must_be_empty_body:\n                    keep_alive = False\n\n        # HTTP 1.1: https://tools.ietf.org/html/rfc7230#section-3.3.2\n        # HTTP 1.0: https://tools.ietf.org/html/rfc1945#section-10.4\n        if self._must_be_empty_body:\n            if hdrs.CONTENT_LENGTH in headers and should_remove_content_length(\n                request.method, self.status\n            ):\n                del headers[hdrs.CONTENT_LENGTH]\n            # https://datatracker.ietf.org/doc/html/rfc9112#section-6.1-10\n            # https://datatracker.ietf.org/doc/html/rfc9112#section-6.1-13\n            if hdrs.TRANSFER_ENCODING in headers:\n                del headers[hdrs.TRANSFER_ENCODING]\n        elif self.content_length != 0:\n            # https://www.rfc-editor.org/rfc/rfc9110#section-8.3-5\n            headers.setdefault(hdrs.CONTENT_TYPE, \"application/octet-stream\")\n        headers.setdefault(hdrs.DATE, rfc822_formatted_time())\n        headers.setdefault(hdrs.SERVER, SERVER_SOFTWARE)\n\n        # connection header\n        if hdrs.CONNECTION not in headers:\n            if keep_alive:\n                if version == HttpVersion10:\n                    headers[hdrs.CONNECTION] = \"keep-alive\"\n            else:\n                if version == HttpVersion11:\n                    headers[hdrs.CONNECTION] = \"close\"\n\n    async def _write_headers(self) -> None:\n        request = self._req\n        assert request is not None\n        writer = self._payload_writer\n        assert writer is not None\n        # status line\n        version = request.version\n        status_line = f\"HTTP/{version[0]}.{version[1]} {self._status} {self._reason}\"\n        await writer.write_headers(status_line, self._headers)\n\n    async def write(self, data: bytes) -> None:\n        assert isinstance(\n            data, (bytes, bytearray, memoryview)\n        ), \"data argument must be byte-ish (%r)\" % type(data)\n\n        if self._eof_sent:\n            raise RuntimeError(\"Cannot call write() after write_eof()\")\n        if self._payload_writer is None:\n            raise RuntimeError(\"Cannot call write() before prepare()\")\n\n        await self._payload_writer.write(data)\n\n    async def drain(self) -> None:\n        assert not self._eof_sent, \"EOF has already been sent\"\n        assert self._payload_writer is not None, \"Response has not been started\"\n        warnings.warn(\n            \"drain method is deprecated, use await resp.write()\",\n            DeprecationWarning,\n            stacklevel=2,\n        )\n        await self._payload_writer.drain()\n\n    async def write_eof(self, data: bytes = b\"\") -> None:\n        assert isinstance(\n            data, (bytes, bytearray, memoryview)\n        ), \"data argument must be byte-ish (%r)\" % type(data)\n\n        if self._eof_sent:\n            return\n\n        assert self._payload_writer is not None, \"Response has not been started\"\n\n        await self._payload_writer.write_eof(data)\n        self._eof_sent = True\n        self._req = None\n        self._body_length = self._payload_writer.output_size\n        self._payload_writer = None\n\n    def __repr__(self) -> str:\n        if self._eof_sent:\n            info = \"eof\"\n        elif self.prepared:\n            assert self._req is not None\n            info = f\"{self._req.method} {self._req.path} \"\n        else:\n            info = \"not prepared\"\n        return f\"<{self.__class__.__name__} {self.reason} {info}>\"\n\n    def __getitem__(self, key: str) -> Any:\n        return self._state[key]\n\n    def __setitem__(self, key: str, value: Any) -> None:\n        self._state[key] = value\n\n    def __delitem__(self, key: str) -> None:\n        del self._state[key]\n\n    def __len__(self) -> int:\n        return len(self._state)\n\n    def __iter__(self) -> Iterator[str]:\n        return iter(self._state)\n\n    def __hash__(self) -> int:\n        return hash(id(self))\n\n    def __eq__(self, other: object) -> bool:\n        return self is other\n\n\nclass Response(StreamResponse):\n    def __init__(\n        self,\n        *,\n        body: Any = None,\n        status: int = 200,\n        reason: Optional[str] = None,\n        text: Optional[str] = None,\n        headers: Optional[LooseHeaders] = None,\n        content_type: Optional[str] = None,\n        charset: Optional[str] = None,\n        zlib_executor_size: Optional[int] = None,\n        zlib_executor: Optional[Executor] = None,\n    ) -> None:\n        if body is not None and text is not None:\n            raise ValueError(\"body and text are not allowed together\")\n\n        if headers is None:\n            real_headers: CIMultiDict[str] = CIMultiDict()\n        elif not isinstance(headers, CIMultiDict):\n            real_headers = CIMultiDict(headers)\n        else:\n            real_headers = headers  # = cast('CIMultiDict[str]', headers)\n\n        if content_type is not None and \"charset\" in content_type:\n            raise ValueError(\"charset must not be in content_type argument\")\n\n        if text is not None:\n            if hdrs.CONTENT_TYPE in real_headers:\n                if content_type or charset:\n                    raise ValueError(\n                        \"passing both Content-Type header and \"\n                        \"content_type or charset params \"\n                        \"is forbidden\"\n                    )\n            else:\n                # fast path for filling headers\n                if not isinstance(text, str):\n                    raise TypeError(\"text argument must be str (%r)\" % type(text))\n                if content_type is None:\n                    content_type = \"text/plain\"\n                if charset is None:\n                    charset = \"utf-8\"\n                real_headers[hdrs.CONTENT_TYPE] = content_type + \"; charset=\" + charset\n                body = text.encode(charset)\n                text = None\n        else:\n            if hdrs.CONTENT_TYPE in real_headers:\n                if content_type is not None or charset is not None:\n                    raise ValueError(\n                        \"passing both Content-Type header and \"\n                        \"content_type or charset params \"\n                        \"is forbidden\"\n                    )\n            else:\n                if content_type is not None:\n                    if charset is not None:\n                        content_type += \"; charset=\" + charset\n                    real_headers[hdrs.CONTENT_TYPE] = content_type\n\n        super().__init__(status=status, reason=reason, headers=real_headers)\n\n        if text is not None:\n            self.text = text\n        else:\n            self.body = body\n\n        self._compressed_body: Optional[bytes] = None\n        self._zlib_executor_size = zlib_executor_size\n        self._zlib_executor = zlib_executor\n\n    @property\n    def body(self) -> Optional[Union[bytes, Payload]]:\n        return self._body\n\n    @body.setter\n    def body(self, body: Any) -> None:\n        if body is None:\n            self._body = None\n        elif isinstance(body, (bytes, bytearray)):\n            self._body = body\n        else:\n            try:\n                self._body = body = payload.PAYLOAD_REGISTRY.get(body)\n            except payload.LookupError:\n                raise ValueError(\"Unsupported body type %r\" % type(body))\n\n            headers = self._headers\n\n            # set content-type\n            if hdrs.CONTENT_TYPE not in headers:\n                headers[hdrs.CONTENT_TYPE] = body.content_type\n\n            # copy payload headers\n            if body.headers:\n                for key, value in body.headers.items():\n                    if key not in headers:\n                        headers[key] = value\n\n        self._compressed_body = None\n\n    @property\n    def text(self) -> Optional[str]:\n        if self._body is None:\n            return None\n        return self._body.decode(self.charset or \"utf-8\")\n\n    @text.setter\n    def text(self, text: str) -> None:\n        assert text is None or isinstance(\n            text, str\n        ), \"text argument must be str (%r)\" % type(text)\n\n        if self.content_type == \"application/octet-stream\":\n            self.content_type = \"text/plain\"\n        if self.charset is None:\n            self.charset = \"utf-8\"\n\n        self._body = text.encode(self.charset)\n        self._compressed_body = None\n\n    @property\n    def content_length(self) -> Optional[int]:\n        if self._chunked:\n            return None\n\n        if hdrs.CONTENT_LENGTH in self._headers:\n            return super().content_length\n\n        if self._compressed_body is not None:\n            # Return length of the compressed body\n            return len(self._compressed_body)\n        elif isinstance(self._body, Payload):\n            # A payload without content length, or a compressed payload\n            return None\n        elif self._body is not None:\n            return len(self._body)\n        else:\n            return 0\n\n    @content_length.setter\n    def content_length(self, value: Optional[int]) -> None:\n        raise RuntimeError(\"Content length is set automatically\")\n\n    async def write_eof(self, data: bytes = b\"\") -> None:\n        if self._eof_sent:\n            return\n        if self._compressed_body is None:\n            body: Optional[Union[bytes, Payload]] = self._body\n        else:\n            body = self._compressed_body\n        assert not data, f\"data arg is not supported, got {data!r}\"\n        assert self._req is not None\n        assert self._payload_writer is not None\n        if body is not None:\n            if self._must_be_empty_body:\n                await super().write_eof()\n            elif isinstance(self._body, Payload):\n                await self._body.write(self._payload_writer)\n                await super().write_eof()\n            else:\n                await super().write_eof(cast(bytes, body))\n        else:\n            await super().write_eof()\n\n    async def _start(self, request: \"BaseRequest\") -> AbstractStreamWriter:\n        if hdrs.CONTENT_LENGTH in self._headers:\n            if should_remove_content_length(request.method, self.status):\n                del self._headers[hdrs.CONTENT_LENGTH]\n        elif not self._chunked:\n            if isinstance(self._body, Payload):\n                if self._body.size is not None:\n                    self._headers[hdrs.CONTENT_LENGTH] = str(self._body.size)\n            else:\n                body_len = len(self._body) if self._body else \"0\"\n                # https://www.rfc-editor.org/rfc/rfc9110.html#section-8.6-7\n                if body_len != \"0\" or (\n                    self.status != 304 and request.method.upper() != hdrs.METH_HEAD\n                ):\n                    self._headers[hdrs.CONTENT_LENGTH] = str(body_len)\n\n        return await super()._start(request)\n\n    async def _do_start_compression(self, coding: ContentCoding) -> None:\n        if self._chunked or isinstance(self._body, Payload):\n            return await super()._do_start_compression(coding)\n\n        if coding != ContentCoding.identity:\n            # Instead of using _payload_writer.enable_compression,\n            # compress the whole body\n            compressor = ZLibCompressor(\n                encoding=str(coding.value),\n                max_sync_chunk_size=self._zlib_executor_size,\n                executor=self._zlib_executor,\n            )\n            assert self._body is not None\n            if self._zlib_executor_size is None and len(self._body) > 1024 * 1024:\n                warnings.warn(\n                    \"Synchronous compression of large response bodies \"\n                    f\"({len(self._body)} bytes) might block the async event loop. \"\n                    \"Consider providing a custom value to zlib_executor_size/\"\n                    \"zlib_executor response properties or disabling compression on it.\"\n                )\n            self._compressed_body = (\n                await compressor.compress(self._body) + compressor.flush()\n            )\n            assert self._compressed_body is not None\n\n            self._headers[hdrs.CONTENT_ENCODING] = coding.value\n            self._headers[hdrs.CONTENT_LENGTH] = str(len(self._compressed_body))\n\n\ndef json_response(\n    data: Any = sentinel,\n    *,\n    text: Optional[str] = None,\n    body: Optional[bytes] = None,\n    status: int = 200,\n    reason: Optional[str] = None,\n    headers: Optional[LooseHeaders] = None,\n    content_type: str = \"application/json\",\n    dumps: JSONEncoder = json.dumps,\n) -> Response:\n    if data is not sentinel:\n        if text or body:\n            raise ValueError(\"only one of data, text, or body should be specified\")\n        else:\n            text = dumps(data)\n    return Response(\n        text=text,\n        body=body,\n        status=status,\n        reason=reason,\n        headers=headers,\n        content_type=content_type,\n    )\n",
            "new_file_content": "import asyncio\nimport collections.abc\nimport datetime\nimport enum\nimport json\nimport math\nimport time\nimport warnings\nimport zlib\nfrom concurrent.futures import Executor\nfrom http import HTTPStatus\nfrom http.cookies import SimpleCookie\nfrom typing import (\n    TYPE_CHECKING,\n    Any,\n    Dict,\n    Iterator,\n    MutableMapping,\n    Optional,\n    Union,\n    cast,\n)\n\nfrom multidict import CIMultiDict, istr\n\nfrom . import hdrs, payload\nfrom .abc import AbstractStreamWriter\nfrom .compression_utils import ZLibCompressor\nfrom .helpers import (\n    ETAG_ANY,\n    QUOTED_ETAG_RE,\n    ETag,\n    HeadersMixin,\n    must_be_empty_body,\n    parse_http_date,\n    rfc822_formatted_time,\n    sentinel,\n    should_remove_content_length,\n    validate_etag_value,\n)\nfrom .http import SERVER_SOFTWARE, HttpVersion10, HttpVersion11\nfrom .payload import Payload\nfrom .typedefs import JSONEncoder, LooseHeaders\n\n__all__ = (\"ContentCoding\", \"StreamResponse\", \"Response\", \"json_response\")\n\n\nif TYPE_CHECKING:\n    from .web_request import BaseRequest\n\n    BaseClass = MutableMapping[str, Any]\nelse:\n    BaseClass = collections.abc.MutableMapping\n\n\n# TODO(py311): Convert to StrEnum for wider use\nclass ContentCoding(enum.Enum):\n    # The content codings that we have support for.\n    #\n    # Additional registered codings are listed at:\n    # https://www.iana.org/assignments/http-parameters/http-parameters.xhtml#content-coding\n    deflate = \"deflate\"\n    gzip = \"gzip\"\n    identity = \"identity\"\n\n\n############################################################\n# HTTP Response classes\n############################################################\n\n\nclass StreamResponse(BaseClass, HeadersMixin):\n\n    _length_check = True\n\n    _body: Union[None, bytes, bytearray, Payload]\n\n    def __init__(\n        self,\n        *,\n        status: int = 200,\n        reason: Optional[str] = None,\n        headers: Optional[LooseHeaders] = None,\n    ) -> None:\n        self._body = None\n        self._keep_alive: Optional[bool] = None\n        self._chunked = False\n        self._compression = False\n        self._compression_strategy: int = zlib.Z_DEFAULT_STRATEGY\n        self._compression_force: Optional[ContentCoding] = None\n        self._cookies = SimpleCookie()\n\n        self._req: Optional[BaseRequest] = None\n        self._payload_writer: Optional[AbstractStreamWriter] = None\n        self._eof_sent = False\n        self._must_be_empty_body: Optional[bool] = None\n        self._body_length = 0\n        self._state: Dict[str, Any] = {}\n\n        if headers is not None:\n            self._headers: CIMultiDict[str] = CIMultiDict(headers)\n        else:\n            self._headers = CIMultiDict()\n\n        self.set_status(status, reason)\n\n    @property\n    def prepared(self) -> bool:\n        return self._eof_sent or self._payload_writer is not None\n\n    @property\n    def task(self) -> \"Optional[asyncio.Task[None]]\":\n        if self._req:\n            return self._req.task\n        else:\n            return None\n\n    @property\n    def status(self) -> int:\n        return self._status\n\n    @property\n    def chunked(self) -> bool:\n        return self._chunked\n\n    @property\n    def compression(self) -> bool:\n        return self._compression\n\n    @property\n    def reason(self) -> str:\n        return self._reason\n\n    def set_status(\n        self,\n        status: int,\n        reason: Optional[str] = None,\n    ) -> None:\n        assert (\n            not self.prepared\n        ), \"Cannot change the response status code after the headers have been sent\"\n        self._status = int(status)\n        if reason is None:\n            try:\n                reason = HTTPStatus(self._status).phrase\n            except ValueError:\n                reason = \"\"\n        if \"\\n\" in reason:\n            raise ValueError(\"Reason cannot contain \\\\n\")\n        self._reason = reason\n\n    @property\n    def keep_alive(self) -> Optional[bool]:\n        return self._keep_alive\n\n    def force_close(self) -> None:\n        self._keep_alive = False\n\n    @property\n    def body_length(self) -> int:\n        return self._body_length\n\n    @property\n    def output_length(self) -> int:\n        warnings.warn(\"output_length is deprecated\", DeprecationWarning)\n        assert self._payload_writer\n        return self._payload_writer.buffer_size\n\n    def enable_chunked_encoding(self, chunk_size: Optional[int] = None) -> None:\n        \"\"\"Enables automatic chunked transfer encoding.\"\"\"\n        self._chunked = True\n\n        if hdrs.CONTENT_LENGTH in self._headers:\n            raise RuntimeError(\n                \"You can't enable chunked encoding when a content length is set\"\n            )\n        if chunk_size is not None:\n            warnings.warn(\"Chunk size is deprecated #1615\", DeprecationWarning)\n\n    def enable_compression(\n        self,\n        force: Optional[Union[bool, ContentCoding]] = None,\n        strategy: int = zlib.Z_DEFAULT_STRATEGY,\n    ) -> None:\n        \"\"\"Enables response compression encoding.\"\"\"\n        # Backwards compatibility for when force was a bool <0.17.\n        if isinstance(force, bool):\n            force = ContentCoding.deflate if force else ContentCoding.identity\n            warnings.warn(\n                \"Using boolean for force is deprecated #3318\", DeprecationWarning\n            )\n        elif force is not None:\n            assert isinstance(\n                force, ContentCoding\n            ), \"force should one of None, bool or ContentEncoding\"\n\n        self._compression = True\n        self._compression_force = force\n        self._compression_strategy = strategy\n\n    @property\n    def headers(self) -> \"CIMultiDict[str]\":\n        return self._headers\n\n    @property\n    def cookies(self) -> SimpleCookie:\n        return self._cookies\n\n    def set_cookie(\n        self,\n        name: str,\n        value: str,\n        *,\n        expires: Optional[str] = None,\n        domain: Optional[str] = None,\n        max_age: Optional[Union[int, str]] = None,\n        path: str = \"/\",\n        secure: Optional[bool] = None,\n        httponly: Optional[bool] = None,\n        version: Optional[str] = None,\n        samesite: Optional[str] = None,\n    ) -> None:\n        \"\"\"Set or update response cookie.\n\n        Sets new cookie or updates existent with new value.\n        Also updates only those params which are not None.\n        \"\"\"\n        old = self._cookies.get(name)\n        if old is not None and old.coded_value == \"\":\n            # deleted cookie\n            self._cookies.pop(name, None)\n\n        self._cookies[name] = value\n        c = self._cookies[name]\n\n        if expires is not None:\n            c[\"expires\"] = expires\n        elif c.get(\"expires\") == \"Thu, 01 Jan 1970 00:00:00 GMT\":\n            del c[\"expires\"]\n\n        if domain is not None:\n            c[\"domain\"] = domain\n\n        if max_age is not None:\n            c[\"max-age\"] = str(max_age)\n        elif \"max-age\" in c:\n            del c[\"max-age\"]\n\n        c[\"path\"] = path\n\n        if secure is not None:\n            c[\"secure\"] = secure\n        if httponly is not None:\n            c[\"httponly\"] = httponly\n        if version is not None:\n            c[\"version\"] = version\n        if samesite is not None:\n            c[\"samesite\"] = samesite\n\n    def del_cookie(\n        self,\n        name: str,\n        *,\n        domain: Optional[str] = None,\n        path: str = \"/\",\n        secure: Optional[bool] = None,\n        httponly: Optional[bool] = None,\n        samesite: Optional[str] = None,\n    ) -> None:\n        \"\"\"Delete cookie.\n\n        Creates new empty expired cookie.\n        \"\"\"\n        # TODO: do we need domain/path here?\n        self._cookies.pop(name, None)\n        self.set_cookie(\n            name,\n            \"\",\n            max_age=0,\n            expires=\"Thu, 01 Jan 1970 00:00:00 GMT\",\n            domain=domain,\n            path=path,\n            secure=secure,\n            httponly=httponly,\n            samesite=samesite,\n        )\n\n    @property\n    def content_length(self) -> Optional[int]:\n        # Just a placeholder for adding setter\n        return super().content_length\n\n    @content_length.setter\n    def content_length(self, value: Optional[int]) -> None:\n        if value is not None:\n            value = int(value)\n            if self._chunked:\n                raise RuntimeError(\n                    \"You can't set content length when chunked encoding is enable\"\n                )\n            self._headers[hdrs.CONTENT_LENGTH] = str(value)\n        else:\n            self._headers.pop(hdrs.CONTENT_LENGTH, None)\n\n    @property\n    def content_type(self) -> str:\n        # Just a placeholder for adding setter\n        return super().content_type\n\n    @content_type.setter\n    def content_type(self, value: str) -> None:\n        self.content_type  # read header values if needed\n        self._content_type = str(value)\n        self._generate_content_type_header()\n\n    @property\n    def charset(self) -> Optional[str]:\n        # Just a placeholder for adding setter\n        return super().charset\n\n    @charset.setter\n    def charset(self, value: Optional[str]) -> None:\n        ctype = self.content_type  # read header values if needed\n        if ctype == \"application/octet-stream\":\n            raise RuntimeError(\n                \"Setting charset for application/octet-stream \"\n                \"doesn't make sense, setup content_type first\"\n            )\n        assert self._content_dict is not None\n        if value is None:\n            self._content_dict.pop(\"charset\", None)\n        else:\n            self._content_dict[\"charset\"] = str(value).lower()\n        self._generate_content_type_header()\n\n    @property\n    def last_modified(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of Last-Modified HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self._headers.get(hdrs.LAST_MODIFIED))\n\n    @last_modified.setter\n    def last_modified(\n        self, value: Optional[Union[int, float, datetime.datetime, str]]\n    ) -> None:\n        if value is None:\n            self._headers.pop(hdrs.LAST_MODIFIED, None)\n        elif isinstance(value, (int, float)):\n            self._headers[hdrs.LAST_MODIFIED] = time.strftime(\n                \"%a, %d %b %Y %H:%M:%S GMT\", time.gmtime(math.ceil(value))\n            )\n        elif isinstance(value, datetime.datetime):\n            self._headers[hdrs.LAST_MODIFIED] = time.strftime(\n                \"%a, %d %b %Y %H:%M:%S GMT\", value.utctimetuple()\n            )\n        elif isinstance(value, str):\n            self._headers[hdrs.LAST_MODIFIED] = value\n\n    @property\n    def etag(self) -> Optional[ETag]:\n        quoted_value = self._headers.get(hdrs.ETAG)\n        if not quoted_value:\n            return None\n        elif quoted_value == ETAG_ANY:\n            return ETag(value=ETAG_ANY)\n        match = QUOTED_ETAG_RE.fullmatch(quoted_value)\n        if not match:\n            return None\n        is_weak, value = match.group(1, 2)\n        return ETag(\n            is_weak=bool(is_weak),\n            value=value,\n        )\n\n    @etag.setter\n    def etag(self, value: Optional[Union[ETag, str]]) -> None:\n        if value is None:\n            self._headers.pop(hdrs.ETAG, None)\n        elif (isinstance(value, str) and value == ETAG_ANY) or (\n            isinstance(value, ETag) and value.value == ETAG_ANY\n        ):\n            self._headers[hdrs.ETAG] = ETAG_ANY\n        elif isinstance(value, str):\n            validate_etag_value(value)\n            self._headers[hdrs.ETAG] = f'\"{value}\"'\n        elif isinstance(value, ETag) and isinstance(value.value, str):\n            validate_etag_value(value.value)\n            hdr_value = f'W/\"{value.value}\"' if value.is_weak else f'\"{value.value}\"'\n            self._headers[hdrs.ETAG] = hdr_value\n        else:\n            raise ValueError(\n                f\"Unsupported etag type: {type(value)}. \"\n                f\"etag must be str, ETag or None\"\n            )\n\n    def _generate_content_type_header(\n        self, CONTENT_TYPE: istr = hdrs.CONTENT_TYPE\n    ) -> None:\n        assert self._content_dict is not None\n        assert self._content_type is not None\n        params = \"; \".join(f\"{k}={v}\" for k, v in self._content_dict.items())\n        if params:\n            ctype = self._content_type + \"; \" + params\n        else:\n            ctype = self._content_type\n        self._headers[CONTENT_TYPE] = ctype\n\n    async def _do_start_compression(self, coding: ContentCoding) -> None:\n        if coding != ContentCoding.identity:\n            assert self._payload_writer is not None\n            self._headers[hdrs.CONTENT_ENCODING] = coding.value\n            self._payload_writer.enable_compression(\n                coding.value, self._compression_strategy\n            )\n            # Compressed payload may have different content length,\n            # remove the header\n            self._headers.popall(hdrs.CONTENT_LENGTH, None)\n\n    async def _start_compression(self, request: \"BaseRequest\") -> None:\n        if self._compression_force:\n            await self._do_start_compression(self._compression_force)\n        else:\n            # Encoding comparisons should be case-insensitive\n            # https://www.rfc-editor.org/rfc/rfc9110#section-8.4.1\n            accept_encoding = request.headers.get(hdrs.ACCEPT_ENCODING, \"\").lower()\n            for coding in ContentCoding:\n                if coding.value in accept_encoding:\n                    await self._do_start_compression(coding)\n                    return\n\n    async def prepare(self, request: \"BaseRequest\") -> Optional[AbstractStreamWriter]:\n        if self._eof_sent:\n            return None\n        if self._payload_writer is not None:\n            return self._payload_writer\n        self._must_be_empty_body = must_be_empty_body(request.method, self.status)\n        return await self._start(request)\n\n    async def _start(self, request: \"BaseRequest\") -> AbstractStreamWriter:\n        self._req = request\n        writer = self._payload_writer = request._payload_writer\n\n        await self._prepare_headers()\n        await request._prepare_hook(self)\n        await self._write_headers()\n\n        return writer\n\n    async def _prepare_headers(self) -> None:\n        request = self._req\n        assert request is not None\n        writer = self._payload_writer\n        assert writer is not None\n        keep_alive = self._keep_alive\n        if keep_alive is None:\n            keep_alive = request.keep_alive\n        self._keep_alive = keep_alive\n\n        version = request.version\n\n        headers = self._headers\n        for cookie in self._cookies.values():\n            value = cookie.output(header=\"\")[1:]\n            headers.add(hdrs.SET_COOKIE, value)\n\n        if self._compression:\n            await self._start_compression(request)\n\n        if self._chunked:\n            if version != HttpVersion11:\n                raise RuntimeError(\n                    \"Using chunked encoding is forbidden \"\n                    \"for HTTP/{0.major}.{0.minor}\".format(request.version)\n                )\n            if not self._must_be_empty_body:\n                writer.enable_chunking()\n                headers[hdrs.TRANSFER_ENCODING] = \"chunked\"\n            if hdrs.CONTENT_LENGTH in headers:\n                del headers[hdrs.CONTENT_LENGTH]\n        elif self._length_check:\n            writer.length = self.content_length\n            if writer.length is None:\n                if version >= HttpVersion11:\n                    if not self._must_be_empty_body:\n                        writer.enable_chunking()\n                        headers[hdrs.TRANSFER_ENCODING] = \"chunked\"\n                elif not self._must_be_empty_body:\n                    keep_alive = False\n\n        # HTTP 1.1: https://tools.ietf.org/html/rfc7230#section-3.3.2\n        # HTTP 1.0: https://tools.ietf.org/html/rfc1945#section-10.4\n        if self._must_be_empty_body:\n            if hdrs.CONTENT_LENGTH in headers and should_remove_content_length(\n                request.method, self.status\n            ):\n                del headers[hdrs.CONTENT_LENGTH]\n            # https://datatracker.ietf.org/doc/html/rfc9112#section-6.1-10\n            # https://datatracker.ietf.org/doc/html/rfc9112#section-6.1-13\n            if hdrs.TRANSFER_ENCODING in headers:\n                del headers[hdrs.TRANSFER_ENCODING]\n        elif self.content_length != 0:\n            # https://www.rfc-editor.org/rfc/rfc9110#section-8.3-5\n            headers.setdefault(hdrs.CONTENT_TYPE, \"application/octet-stream\")\n        headers.setdefault(hdrs.DATE, rfc822_formatted_time())\n        headers.setdefault(hdrs.SERVER, SERVER_SOFTWARE)\n\n        # connection header\n        if hdrs.CONNECTION not in headers:\n            if keep_alive:\n                if version == HttpVersion10:\n                    headers[hdrs.CONNECTION] = \"keep-alive\"\n            else:\n                if version == HttpVersion11:\n                    headers[hdrs.CONNECTION] = \"close\"\n\n    async def _write_headers(self) -> None:\n        request = self._req\n        assert request is not None\n        writer = self._payload_writer\n        assert writer is not None\n        # status line\n        version = request.version\n        status_line = f\"HTTP/{version[0]}.{version[1]} {self._status} {self._reason}\"\n        await writer.write_headers(status_line, self._headers)\n\n    async def write(self, data: bytes) -> None:\n        assert isinstance(\n            data, (bytes, bytearray, memoryview)\n        ), \"data argument must be byte-ish (%r)\" % type(data)\n\n        if self._eof_sent:\n            raise RuntimeError(\"Cannot call write() after write_eof()\")\n        if self._payload_writer is None:\n            raise RuntimeError(\"Cannot call write() before prepare()\")\n\n        await self._payload_writer.write(data)\n\n    async def drain(self) -> None:\n        assert not self._eof_sent, \"EOF has already been sent\"\n        assert self._payload_writer is not None, \"Response has not been started\"\n        warnings.warn(\n            \"drain method is deprecated, use await resp.write()\",\n            DeprecationWarning,\n            stacklevel=2,\n        )\n        await self._payload_writer.drain()\n\n    async def write_eof(self, data: bytes = b\"\") -> None:\n        assert isinstance(\n            data, (bytes, bytearray, memoryview)\n        ), \"data argument must be byte-ish (%r)\" % type(data)\n\n        if self._eof_sent:\n            return\n\n        assert self._payload_writer is not None, \"Response has not been started\"\n\n        await self._payload_writer.write_eof(data)\n        self._eof_sent = True\n        self._req = None\n        self._body_length = self._payload_writer.output_size\n        self._payload_writer = None\n\n    def __repr__(self) -> str:\n        if self._eof_sent:\n            info = \"eof\"\n        elif self.prepared:\n            assert self._req is not None\n            info = f\"{self._req.method} {self._req.path} \"\n        else:\n            info = \"not prepared\"\n        return f\"<{self.__class__.__name__} {self.reason} {info}>\"\n\n    def __getitem__(self, key: str) -> Any:\n        return self._state[key]\n\n    def __setitem__(self, key: str, value: Any) -> None:\n        self._state[key] = value\n\n    def __delitem__(self, key: str) -> None:\n        del self._state[key]\n\n    def __len__(self) -> int:\n        return len(self._state)\n\n    def __iter__(self) -> Iterator[str]:\n        return iter(self._state)\n\n    def __hash__(self) -> int:\n        return hash(id(self))\n\n    def __eq__(self, other: object) -> bool:\n        return self is other\n\n\nclass Response(StreamResponse):\n    def __init__(\n        self,\n        *,\n        body: Any = None,\n        status: int = 200,\n        reason: Optional[str] = None,\n        text: Optional[str] = None,\n        headers: Optional[LooseHeaders] = None,\n        content_type: Optional[str] = None,\n        charset: Optional[str] = None,\n        zlib_executor_size: Optional[int] = None,\n        zlib_executor: Optional[Executor] = None,\n    ) -> None:\n        if body is not None and text is not None:\n            raise ValueError(\"body and text are not allowed together\")\n\n        if headers is None:\n            real_headers: CIMultiDict[str] = CIMultiDict()\n        elif not isinstance(headers, CIMultiDict):\n            real_headers = CIMultiDict(headers)\n        else:\n            real_headers = headers  # = cast('CIMultiDict[str]', headers)\n\n        if content_type is not None and \"charset\" in content_type:\n            raise ValueError(\"charset must not be in content_type argument\")\n\n        if text is not None:\n            if hdrs.CONTENT_TYPE in real_headers:\n                if content_type or charset:\n                    raise ValueError(\n                        \"passing both Content-Type header and \"\n                        \"content_type or charset params \"\n                        \"is forbidden\"\n                    )\n            else:\n                # fast path for filling headers\n                if not isinstance(text, str):\n                    raise TypeError(\"text argument must be str (%r)\" % type(text))\n                if content_type is None:\n                    content_type = \"text/plain\"\n                if charset is None:\n                    charset = \"utf-8\"\n                real_headers[hdrs.CONTENT_TYPE] = content_type + \"; charset=\" + charset\n                body = text.encode(charset)\n                text = None\n        else:\n            if hdrs.CONTENT_TYPE in real_headers:\n                if content_type is not None or charset is not None:\n                    raise ValueError(\n                        \"passing both Content-Type header and \"\n                        \"content_type or charset params \"\n                        \"is forbidden\"\n                    )\n            else:\n                if content_type is not None:\n                    if charset is not None:\n                        content_type += \"; charset=\" + charset\n                    real_headers[hdrs.CONTENT_TYPE] = content_type\n\n        super().__init__(status=status, reason=reason, headers=real_headers)\n\n        if text is not None:\n            self.text = text\n        else:\n            self.body = body\n\n        self._compressed_body: Optional[bytes] = None\n        self._zlib_executor_size = zlib_executor_size\n        self._zlib_executor = zlib_executor\n\n    @property\n    def body(self) -> Optional[Union[bytes, Payload]]:\n        return self._body\n\n    @body.setter\n    def body(self, body: Any) -> None:\n        if body is None:\n            self._body = None\n        elif isinstance(body, (bytes, bytearray)):\n            self._body = body\n        else:\n            try:\n                self._body = body = payload.PAYLOAD_REGISTRY.get(body)\n            except payload.LookupError:\n                raise ValueError(\"Unsupported body type %r\" % type(body))\n\n            headers = self._headers\n\n            # set content-type\n            if hdrs.CONTENT_TYPE not in headers:\n                headers[hdrs.CONTENT_TYPE] = body.content_type\n\n            # copy payload headers\n            if body.headers:\n                for key, value in body.headers.items():\n                    if key not in headers:\n                        headers[key] = value\n\n        self._compressed_body = None\n\n    @property\n    def text(self) -> Optional[str]:\n        if self._body is None:\n            return None\n        return self._body.decode(self.charset or \"utf-8\")\n\n    @text.setter\n    def text(self, text: str) -> None:\n        assert text is None or isinstance(\n            text, str\n        ), \"text argument must be str (%r)\" % type(text)\n\n        if self.content_type == \"application/octet-stream\":\n            self.content_type = \"text/plain\"\n        if self.charset is None:\n            self.charset = \"utf-8\"\n\n        self._body = text.encode(self.charset)\n        self._compressed_body = None\n\n    @property\n    def content_length(self) -> Optional[int]:\n        if self._chunked:\n            return None\n\n        if hdrs.CONTENT_LENGTH in self._headers:\n            return super().content_length\n\n        if self._compressed_body is not None:\n            # Return length of the compressed body\n            return len(self._compressed_body)\n        elif isinstance(self._body, Payload):\n            # A payload without content length, or a compressed payload\n            return None\n        elif self._body is not None:\n            return len(self._body)\n        else:\n            return 0\n\n    @content_length.setter\n    def content_length(self, value: Optional[int]) -> None:\n        raise RuntimeError(\"Content length is set automatically\")\n\n    async def write_eof(self, data: bytes = b\"\") -> None:\n        if self._eof_sent:\n            return\n        if self._compressed_body is None:\n            body: Optional[Union[bytes, Payload]] = self._body\n        else:\n            body = self._compressed_body\n        assert not data, f\"data arg is not supported, got {data!r}\"\n        assert self._req is not None\n        assert self._payload_writer is not None\n        if body is not None:\n            if self._must_be_empty_body:\n                await super().write_eof()\n            elif isinstance(self._body, Payload):\n                await self._body.write(self._payload_writer)\n                await super().write_eof()\n            else:\n                await super().write_eof(cast(bytes, body))\n        else:\n            await super().write_eof()\n\n    async def _start(self, request: \"BaseRequest\") -> AbstractStreamWriter:\n        if hdrs.CONTENT_LENGTH in self._headers:\n            if should_remove_content_length(request.method, self.status):\n                del self._headers[hdrs.CONTENT_LENGTH]\n        elif not self._chunked:\n            if isinstance(self._body, Payload):\n                if self._body.size is not None:\n                    self._headers[hdrs.CONTENT_LENGTH] = str(self._body.size)\n            else:\n                body_len = len(self._body) if self._body else \"0\"\n                # https://www.rfc-editor.org/rfc/rfc9110.html#section-8.6-7\n                if body_len != \"0\" or (\n                    self.status != 304 and request.method.upper() != hdrs.METH_HEAD\n                ):\n                    self._headers[hdrs.CONTENT_LENGTH] = str(body_len)\n\n        return await super()._start(request)\n\n    async def _do_start_compression(self, coding: ContentCoding) -> None:\n        if self._chunked or isinstance(self._body, Payload):\n            return await super()._do_start_compression(coding)\n\n        if coding != ContentCoding.identity:\n            # Instead of using _payload_writer.enable_compression,\n            # compress the whole body\n            compressor = ZLibCompressor(\n                encoding=str(coding.value),\n                max_sync_chunk_size=self._zlib_executor_size,\n                executor=self._zlib_executor,\n            )\n            assert self._body is not None\n            if self._zlib_executor_size is None and len(self._body) > 1024 * 1024:\n                warnings.warn(\n                    \"Synchronous compression of large response bodies \"\n                    f\"({len(self._body)} bytes) might block the async event loop. \"\n                    \"Consider providing a custom value to zlib_executor_size/\"\n                    \"zlib_executor response properties or disabling compression on it.\"\n                )\n            self._compressed_body = (\n                await compressor.compress(self._body) + compressor.flush()\n            )\n            assert self._compressed_body is not None\n\n            self._headers[hdrs.CONTENT_ENCODING] = coding.value\n            self._headers[hdrs.CONTENT_LENGTH] = str(len(self._compressed_body))\n\n\ndef json_response(\n    data: Any = sentinel,\n    *,\n    text: Optional[str] = None,\n    body: Optional[bytes] = None,\n    status: int = 200,\n    reason: Optional[str] = None,\n    headers: Optional[LooseHeaders] = None,\n    content_type: str = \"application/json\",\n    dumps: JSONEncoder = json.dumps,\n) -> Response:\n    if data is not sentinel:\n        if text or body:\n            raise ValueError(\"only one of data, text, or body should be specified\")\n        else:\n            text = dumps(data)\n    return Response(\n        text=text,\n        body=body,\n        status=status,\n        reason=reason,\n        headers=headers,\n        content_type=content_type,\n    )\n",
            "header": {
                "file": {
                    "path": "aiohttp/web_response.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "2ba135f5",
                "new_commit_hash": "bf184980",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/aiohttp/web_response.py"
            },
            "plus_file": {
                "path": "b/aiohttp/web_response.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 145,
                            "length": 6
                        },
                        "new_range": {
                            "start": 145,
                            "length": 8
                        },
                        "section": "class StreamResponse(BaseClass, HeadersMixin):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "                reason = HTTPStatus(self._status).phrase",
                                "type": "context"
                            },
                            {
                                "content": "            except ValueError:",
                                "type": "context"
                            },
                            {
                                "content": "                reason = \"\"",
                                "type": "context"
                            },
                            {
                                "content": "        if \"\\n\" in reason:",
                                "type": "added"
                            },
                            {
                                "content": "            raise ValueError(\"Reason cannot contain \\\\n\")",
                                "type": "added"
                            },
                            {
                                "content": "        self._reason = reason",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    @property",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "aiohttp/web_response.py",
                            "type": "class",
                            "name": "StreamResponse",
                            "content": "class StreamResponse(BaseClass, HeadersMixin):\n\n    _length_check = True\n\n    _body: Union[None, bytes, bytearray, Payload]\n\n    def __init__(\n        self,\n        *,\n        status: int = 200,\n        reason: Optional[str] = None,\n        headers: Optional[LooseHeaders] = None,\n    ) -> None:\n        self._body = None\n        self._keep_alive: Optional[bool] = None\n        self._chunked = False\n        self._compression = False\n        self._compression_strategy: int = zlib.Z_DEFAULT_STRATEGY\n        self._compression_force: Optional[ContentCoding] = None\n        self._cookies = SimpleCookie()\n\n        self._req: Optional[BaseRequest] = None\n        self._payload_writer: Optional[AbstractStreamWriter] = None\n        self._eof_sent = False\n        self._must_be_empty_body: Optional[bool] = None\n        self._body_length = 0\n        self._state: Dict[str, Any] = {}\n\n        if headers is not None:\n            self._headers: CIMultiDict[str] = CIMultiDict(headers)\n        else:\n            self._headers = CIMultiDict()\n\n        self.set_status(status, reason)\n\n    @property\n    def prepared(self) -> bool:\n        return self._eof_sent or self._payload_writer is not None\n\n    @property\n    def task(self) -> \"Optional[asyncio.Task[None]]\":\n        if self._req:\n            return self._req.task\n        else:\n            return None\n\n    @property\n    def status(self) -> int:\n        return self._status\n\n    @property\n    def chunked(self) -> bool:\n        return self._chunked\n\n    @property\n    def compression(self) -> bool:\n        return self._compression\n\n    @property\n    def reason(self) -> str:\n        return self._reason\n\n    def set_status(\n        self,\n        status: int,\n        reason: Optional[str] = None,\n    ) -> None:\n        assert (\n            not self.prepared\n        ), \"Cannot change the response status code after the headers have been sent\"\n        self._status = int(status)\n        if reason is None:\n            try:\n                reason = HTTPStatus(self._status).phrase\n            except ValueError:\n                reason = \"\"\n        if \"\\n\" in reason:\n            raise ValueError(\"Reason cannot contain \\\\n\")\n        self._reason = reason\n\n    @property\n    def keep_alive(self) -> Optional[bool]:\n        return self._keep_alive\n\n    def force_close(self) -> None:\n        self._keep_alive = False\n\n    @property\n    def body_length(self) -> int:\n        return self._body_length\n\n    @property\n    def output_length(self) -> int:\n        warnings.warn(\"output_length is deprecated\", DeprecationWarning)\n        assert self._payload_writer\n        return self._payload_writer.buffer_size\n\n    def enable_chunked_encoding(self, chunk_size: Optional[int] = None) -> None:\n        \"\"\"Enables automatic chunked transfer encoding.\"\"\"\n        self._chunked = True\n\n        if hdrs.CONTENT_LENGTH in self._headers:\n            raise RuntimeError(\n                \"You can't enable chunked encoding when a content length is set\"\n            )\n        if chunk_size is not None:\n            warnings.warn(\"Chunk size is deprecated #1615\", DeprecationWarning)\n\n    def enable_compression(\n        self,\n        force: Optional[Union[bool, ContentCoding]] = None,\n        strategy: int = zlib.Z_DEFAULT_STRATEGY,\n    ) -> None:\n        \"\"\"Enables response compression encoding.\"\"\"\n        # Backwards compatibility for when force was a bool <0.17.\n        if isinstance(force, bool):\n            force = ContentCoding.deflate if force else ContentCoding.identity\n            warnings.warn(\n                \"Using boolean for force is deprecated #3318\", DeprecationWarning\n            )\n        elif force is not None:\n            assert isinstance(\n                force, ContentCoding\n            ), \"force should one of None, bool or ContentEncoding\"\n\n        self._compression = True\n        self._compression_force = force\n        self._compression_strategy = strategy\n\n    @property\n    def headers(self) -> \"CIMultiDict[str]\":\n        return self._headers\n\n    @property\n    def cookies(self) -> SimpleCookie:\n        return self._cookies\n\n    def set_cookie(\n        self,\n        name: str,\n        value: str,\n        *,\n        expires: Optional[str] = None,\n        domain: Optional[str] = None,\n        max_age: Optional[Union[int, str]] = None,\n        path: str = \"/\",\n        secure: Optional[bool] = None,\n        httponly: Optional[bool] = None,\n        version: Optional[str] = None,\n        samesite: Optional[str] = None,\n    ) -> None:\n        \"\"\"Set or update response cookie.\n\n        Sets new cookie or updates existent with new value.\n        Also updates only those params which are not None.\n        \"\"\"\n        old = self._cookies.get(name)\n        if old is not None and old.coded_value == \"\":\n            # deleted cookie\n            self._cookies.pop(name, None)\n\n        self._cookies[name] = value\n        c = self._cookies[name]\n\n        if expires is not None:\n            c[\"expires\"] = expires\n        elif c.get(\"expires\") == \"Thu, 01 Jan 1970 00:00:00 GMT\":\n            del c[\"expires\"]\n\n        if domain is not None:\n            c[\"domain\"] = domain\n\n        if max_age is not None:\n            c[\"max-age\"] = str(max_age)\n        elif \"max-age\" in c:\n            del c[\"max-age\"]\n\n        c[\"path\"] = path\n\n        if secure is not None:\n            c[\"secure\"] = secure\n        if httponly is not None:\n            c[\"httponly\"] = httponly\n        if version is not None:\n            c[\"version\"] = version\n        if samesite is not None:\n            c[\"samesite\"] = samesite\n\n    def del_cookie(\n        self,\n        name: str,\n        *,\n        domain: Optional[str] = None,\n        path: str = \"/\",\n        secure: Optional[bool] = None,\n        httponly: Optional[bool] = None,\n        samesite: Optional[str] = None,\n    ) -> None:\n        \"\"\"Delete cookie.\n\n        Creates new empty expired cookie.\n        \"\"\"\n        # TODO: do we need domain/path here?\n        self._cookies.pop(name, None)\n        self.set_cookie(\n            name,\n            \"\",\n            max_age=0,\n            expires=\"Thu, 01 Jan 1970 00:00:00 GMT\",\n            domain=domain,\n            path=path,\n            secure=secure,\n            httponly=httponly,\n            samesite=samesite,\n        )\n\n    @property\n    def content_length(self) -> Optional[int]:\n        # Just a placeholder for adding setter\n        return super().content_length\n\n    @content_length.setter\n    def content_length(self, value: Optional[int]) -> None:\n        if value is not None:\n            value = int(value)\n            if self._chunked:\n                raise RuntimeError(\n                    \"You can't set content length when chunked encoding is enable\"\n                )\n            self._headers[hdrs.CONTENT_LENGTH] = str(value)\n        else:\n            self._headers.pop(hdrs.CONTENT_LENGTH, None)\n\n    @property\n    def content_type(self) -> str:\n        # Just a placeholder for adding setter\n        return super().content_type\n\n    @content_type.setter\n    def content_type(self, value: str) -> None:\n        self.content_type  # read header values if needed\n        self._content_type = str(value)\n        self._generate_content_type_header()\n\n    @property\n    def charset(self) -> Optional[str]:\n        # Just a placeholder for adding setter\n        return super().charset\n\n    @charset.setter\n    def charset(self, value: Optional[str]) -> None:\n        ctype = self.content_type  # read header values if needed\n        if ctype == \"application/octet-stream\":\n            raise RuntimeError(\n                \"Setting charset for application/octet-stream \"\n                \"doesn't make sense, setup content_type first\"\n            )\n        assert self._content_dict is not None\n        if value is None:\n            self._content_dict.pop(\"charset\", None)\n        else:\n            self._content_dict[\"charset\"] = str(value).lower()\n        self._generate_content_type_header()\n\n    @property\n    def last_modified(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of Last-Modified HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self._headers.get(hdrs.LAST_MODIFIED))\n\n    @last_modified.setter\n    def last_modified(\n        self, value: Optional[Union[int, float, datetime.datetime, str]]\n    ) -> None:\n        if value is None:\n            self._headers.pop(hdrs.LAST_MODIFIED, None)\n        elif isinstance(value, (int, float)):\n            self._headers[hdrs.LAST_MODIFIED] = time.strftime(\n                \"%a, %d %b %Y %H:%M:%S GMT\", time.gmtime(math.ceil(value))\n            )\n        elif isinstance(value, datetime.datetime):\n            self._headers[hdrs.LAST_MODIFIED] = time.strftime(\n                \"%a, %d %b %Y %H:%M:%S GMT\", value.utctimetuple()\n            )\n        elif isinstance(value, str):\n            self._headers[hdrs.LAST_MODIFIED] = value\n\n    @property\n    def etag(self) -> Optional[ETag]:\n        quoted_value = self._headers.get(hdrs.ETAG)\n        if not quoted_value:\n            return None\n        elif quoted_value == ETAG_ANY:\n            return ETag(value=ETAG_ANY)\n        match = QUOTED_ETAG_RE.fullmatch(quoted_value)\n        if not match:\n            return None\n        is_weak, value = match.group(1, 2)\n        return ETag(\n            is_weak=bool(is_weak),\n            value=value,\n        )\n\n    @etag.setter\n    def etag(self, value: Optional[Union[ETag, str]]) -> None:\n        if value is None:\n            self._headers.pop(hdrs.ETAG, None)\n        elif (isinstance(value, str) and value == ETAG_ANY) or (\n            isinstance(value, ETag) and value.value == ETAG_ANY\n        ):\n            self._headers[hdrs.ETAG] = ETAG_ANY\n        elif isinstance(value, str):\n            validate_etag_value(value)\n            self._headers[hdrs.ETAG] = f'\"{value}\"'\n        elif isinstance(value, ETag) and isinstance(value.value, str):\n            validate_etag_value(value.value)\n            hdr_value = f'W/\"{value.value}\"' if value.is_weak else f'\"{value.value}\"'\n            self._headers[hdrs.ETAG] = hdr_value\n        else:\n            raise ValueError(\n                f\"Unsupported etag type: {type(value)}. \"\n                f\"etag must be str, ETag or None\"\n            )\n\n    def _generate_content_type_header(\n        self, CONTENT_TYPE: istr = hdrs.CONTENT_TYPE\n    ) -> None:\n        assert self._content_dict is not None\n        assert self._content_type is not None\n        params = \"; \".join(f\"{k}={v}\" for k, v in self._content_dict.items())\n        if params:\n            ctype = self._content_type + \"; \" + params\n        else:\n            ctype = self._content_type\n        self._headers[CONTENT_TYPE] = ctype\n\n    async def _do_start_compression(self, coding: ContentCoding) -> None:\n        if coding != ContentCoding.identity:\n            assert self._payload_writer is not None\n            self._headers[hdrs.CONTENT_ENCODING] = coding.value\n            self._payload_writer.enable_compression(\n                coding.value, self._compression_strategy\n            )\n            # Compressed payload may have different content length,\n            # remove the header\n            self._headers.popall(hdrs.CONTENT_LENGTH, None)\n\n    async def _start_compression(self, request: \"BaseRequest\") -> None:\n        if self._compression_force:\n            await self._do_start_compression(self._compression_force)\n        else:\n            # Encoding comparisons should be case-insensitive\n            # https://www.rfc-editor.org/rfc/rfc9110#section-8.4.1\n            accept_encoding = request.headers.get(hdrs.ACCEPT_ENCODING, \"\").lower()\n            for coding in ContentCoding:\n                if coding.value in accept_encoding:\n                    await self._do_start_compression(coding)\n                    return\n\n    async def prepare(self, request: \"BaseRequest\") -> Optional[AbstractStreamWriter]:\n        if self._eof_sent:\n            return None\n        if self._payload_writer is not None:\n            return self._payload_writer\n        self._must_be_empty_body = must_be_empty_body(request.method, self.status)\n        return await self._start(request)\n\n    async def _start(self, request: \"BaseRequest\") -> AbstractStreamWriter:\n        self._req = request\n        writer = self._payload_writer = request._payload_writer\n\n        await self._prepare_headers()\n        await request._prepare_hook(self)\n        await self._write_headers()\n\n        return writer\n\n    async def _prepare_headers(self) -> None:\n        request = self._req\n        assert request is not None\n        writer = self._payload_writer\n        assert writer is not None\n        keep_alive = self._keep_alive\n        if keep_alive is None:\n            keep_alive = request.keep_alive\n        self._keep_alive = keep_alive\n\n        version = request.version\n\n        headers = self._headers\n        for cookie in self._cookies.values():\n            value = cookie.output(header=\"\")[1:]\n            headers.add(hdrs.SET_COOKIE, value)\n\n        if self._compression:\n            await self._start_compression(request)\n\n        if self._chunked:\n            if version != HttpVersion11:\n                raise RuntimeError(\n                    \"Using chunked encoding is forbidden \"\n                    \"for HTTP/{0.major}.{0.minor}\".format(request.version)\n                )\n            if not self._must_be_empty_body:\n                writer.enable_chunking()\n                headers[hdrs.TRANSFER_ENCODING] = \"chunked\"\n            if hdrs.CONTENT_LENGTH in headers:\n                del headers[hdrs.CONTENT_LENGTH]\n        elif self._length_check:\n            writer.length = self.content_length\n            if writer.length is None:\n                if version >= HttpVersion11:\n                    if not self._must_be_empty_body:\n                        writer.enable_chunking()\n                        headers[hdrs.TRANSFER_ENCODING] = \"chunked\"\n                elif not self._must_be_empty_body:\n                    keep_alive = False\n\n        # HTTP 1.1: https://tools.ietf.org/html/rfc7230#section-3.3.2\n        # HTTP 1.0: https://tools.ietf.org/html/rfc1945#section-10.4\n        if self._must_be_empty_body:\n            if hdrs.CONTENT_LENGTH in headers and should_remove_content_length(\n                request.method, self.status\n            ):\n                del headers[hdrs.CONTENT_LENGTH]\n            # https://datatracker.ietf.org/doc/html/rfc9112#section-6.1-10\n            # https://datatracker.ietf.org/doc/html/rfc9112#section-6.1-13\n            if hdrs.TRANSFER_ENCODING in headers:\n                del headers[hdrs.TRANSFER_ENCODING]\n        elif self.content_length != 0:\n            # https://www.rfc-editor.org/rfc/rfc9110#section-8.3-5\n            headers.setdefault(hdrs.CONTENT_TYPE, \"application/octet-stream\")\n        headers.setdefault(hdrs.DATE, rfc822_formatted_time())\n        headers.setdefault(hdrs.SERVER, SERVER_SOFTWARE)\n\n        # connection header\n        if hdrs.CONNECTION not in headers:\n            if keep_alive:\n                if version == HttpVersion10:\n                    headers[hdrs.CONNECTION] = \"keep-alive\"\n            else:\n                if version == HttpVersion11:\n                    headers[hdrs.CONNECTION] = \"close\"\n\n    async def _write_headers(self) -> None:\n        request = self._req\n        assert request is not None\n        writer = self._payload_writer\n        assert writer is not None\n        # status line\n        version = request.version\n        status_line = f\"HTTP/{version[0]}.{version[1]} {self._status} {self._reason}\"\n        await writer.write_headers(status_line, self._headers)\n\n    async def write(self, data: bytes) -> None:\n        assert isinstance(\n            data, (bytes, bytearray, memoryview)\n        ), \"data argument must be byte-ish (%r)\" % type(data)\n\n        if self._eof_sent:\n            raise RuntimeError(\"Cannot call write() after write_eof()\")\n        if self._payload_writer is None:\n            raise RuntimeError(\"Cannot call write() before prepare()\")\n\n        await self._payload_writer.write(data)\n\n    async def drain(self) -> None:\n        assert not self._eof_sent, \"EOF has already been sent\"\n        assert self._payload_writer is not None, \"Response has not been started\"\n        warnings.warn(\n            \"drain method is deprecated, use await resp.write()\",\n            DeprecationWarning,\n            stacklevel=2,\n        )\n        await self._payload_writer.drain()\n\n    async def write_eof(self, data: bytes = b\"\") -> None:\n        assert isinstance(\n            data, (bytes, bytearray, memoryview)\n        ), \"data argument must be byte-ish (%r)\" % type(data)\n\n        if self._eof_sent:\n            return\n\n        assert self._payload_writer is not None, \"Response has not been started\"\n\n        await self._payload_writer.write_eof(data)\n        self._eof_sent = True\n        self._req = None\n        self._body_length = self._payload_writer.output_size\n        self._payload_writer = None\n\n    def __repr__(self) -> str:\n        if self._eof_sent:\n            info = \"eof\"\n        elif self.prepared:\n            assert self._req is not None\n            info = f\"{self._req.method} {self._req.path} \"\n        else:\n            info = \"not prepared\"\n        return f\"<{self.__class__.__name__} {self.reason} {info}>\"\n\n    def __getitem__(self, key: str) -> Any:\n        return self._state[key]\n\n    def __setitem__(self, key: str, value: Any) -> None:\n        self._state[key] = value\n\n    def __delitem__(self, key: str) -> None:\n        del self._state[key]\n\n    def __len__(self) -> int:\n        return len(self._state)\n\n    def __iter__(self) -> Iterator[str]:\n        return iter(self._state)\n\n    def __hash__(self) -> int:\n        return hash(id(self))\n\n    def __eq__(self, other: object) -> bool:\n        return self is other",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 72,
                            "end_lineno": 595,
                            "parent": null
                        },
                        {
                            "file_name": "aiohttp/web_response.py",
                            "type": "method",
                            "name": "StreamResponse.set_status",
                            "content": "class StreamResponse(BaseClass, HeadersMixin):\n\n    _length_check = True\n\n    _body: Union[None, bytes, bytearray, Payload]\n\n    def __init__(\n        self,\n        *,\n        status: int = 200,\n        reason: Optional[str] = None,\n        headers: Optional[LooseHeaders] = None,\n    ) -> None:\n        self._body = None\n        self._keep_alive: Optional[bool] = None\n        self._chunked = False\n        self._compression = False\n        self._compression_strategy: int = zlib.Z_DEFAULT_STRATEGY\n        self._compression_force: Optional[ContentCoding] = None\n        self._cookies = SimpleCookie()\n\n        self._req: Optional[BaseRequest] = None\n        self._payload_writer: Optional[AbstractStreamWriter] = None\n        self._eof_sent = False\n        self._must_be_empty_body: Optional[bool] = None\n        self._body_length = 0\n        self._state: Dict[str, Any] = {}\n\n        if headers is not None:\n            self._headers: CIMultiDict[str] = CIMultiDict(headers)\n        else:\n            self._headers = CIMultiDict()\n\n        self.set_status(status, reason)\n\n    @property\n    def prepared(self) -> bool:\n        return self._eof_sent or self._payload_writer is not None\n\n    @property\n    def task(self) -> \"Optional[asyncio.Task[None]]\":\n        if self._req:\n            return self._req.task\n        else:\n            return None\n\n    @property\n    def status(self) -> int:\n        return self._status\n\n    @property\n    def chunked(self) -> bool:\n        return self._chunked\n\n    @property\n    def compression(self) -> bool:\n        return self._compression\n\n    @property\n    def reason(self) -> str:\n        return self._reason\n\n    def set_status(\n        self,\n        status: int,\n        reason: Optional[str] = None,\n    ) -> None:\n        assert (\n            not self.prepared\n        ), \"Cannot change the response status code after the headers have been sent\"\n        self._status = int(status)\n        if reason is None:\n            try:\n                reason = HTTPStatus(self._status).phrase\n            except ValueError:\n                reason = \"\"\n        if \"\\n\" in reason:\n            raise ValueError(\"Reason cannot contain \\\\n\")\n        self._reason = reason\n\n    @property\n    def keep_alive(self) -> Optional[bool]:\n        return self._keep_alive\n\n    def force_close(self) -> None:\n        self._keep_alive = False\n\n    @property\n    def body_length(self) -> int:\n        return self._body_length\n\n    @property\n    def output_length(self) -> int:\n        warnings.warn(\"output_length is deprecated\", DeprecationWarning)\n        assert self._payload_writer\n        return self._payload_writer.buffer_size\n\n    def enable_chunked_encoding(self, chunk_size: Optional[int] = None) -> None:\n        \"\"\"Enables automatic chunked transfer encoding.\"\"\"\n        self._chunked = True\n\n        if hdrs.CONTENT_LENGTH in self._headers:\n            raise RuntimeError(\n                \"You can't enable chunked encoding when a content length is set\"\n            )\n        if chunk_size is not None:\n            warnings.warn(\"Chunk size is deprecated #1615\", DeprecationWarning)\n\n    def enable_compression(\n        self,\n        force: Optional[Union[bool, ContentCoding]] = None,\n        strategy: int = zlib.Z_DEFAULT_STRATEGY,\n    ) -> None:\n        \"\"\"Enables response compression encoding.\"\"\"\n        # Backwards compatibility for when force was a bool <0.17.\n        if isinstance(force, bool):\n            force = ContentCoding.deflate if force else ContentCoding.identity\n            warnings.warn(\n                \"Using boolean for force is deprecated #3318\", DeprecationWarning\n            )\n        elif force is not None:\n            assert isinstance(\n                force, ContentCoding\n            ), \"force should one of None, bool or ContentEncoding\"\n\n        self._compression = True\n        self._compression_force = force\n        self._compression_strategy = strategy\n\n    @property\n    def headers(self) -> \"CIMultiDict[str]\":\n        return self._headers\n\n    @property\n    def cookies(self) -> SimpleCookie:\n        return self._cookies\n\n    def set_cookie(\n        self,\n        name: str,\n        value: str,\n        *,\n        expires: Optional[str] = None,\n        domain: Optional[str] = None,\n        max_age: Optional[Union[int, str]] = None,\n        path: str = \"/\",\n        secure: Optional[bool] = None,\n        httponly: Optional[bool] = None,\n        version: Optional[str] = None,\n        samesite: Optional[str] = None,\n    ) -> None:\n        \"\"\"Set or update response cookie.\n\n        Sets new cookie or updates existent with new value.\n        Also updates only those params which are not None.\n        \"\"\"\n        old = self._cookies.get(name)\n        if old is not None and old.coded_value == \"\":\n            # deleted cookie\n            self._cookies.pop(name, None)\n\n        self._cookies[name] = value\n        c = self._cookies[name]\n\n        if expires is not None:\n            c[\"expires\"] = expires\n        elif c.get(\"expires\") == \"Thu, 01 Jan 1970 00:00:00 GMT\":\n            del c[\"expires\"]\n\n        if domain is not None:\n            c[\"domain\"] = domain\n\n        if max_age is not None:\n            c[\"max-age\"] = str(max_age)\n        elif \"max-age\" in c:\n            del c[\"max-age\"]\n\n        c[\"path\"] = path\n\n        if secure is not None:\n            c[\"secure\"] = secure\n        if httponly is not None:\n            c[\"httponly\"] = httponly\n        if version is not None:\n            c[\"version\"] = version\n        if samesite is not None:\n            c[\"samesite\"] = samesite\n\n    def del_cookie(\n        self,\n        name: str,\n        *,\n        domain: Optional[str] = None,\n        path: str = \"/\",\n        secure: Optional[bool] = None,\n        httponly: Optional[bool] = None,\n        samesite: Optional[str] = None,\n    ) -> None:\n        \"\"\"Delete cookie.\n\n        Creates new empty expired cookie.\n        \"\"\"\n        # TODO: do we need domain/path here?\n        self._cookies.pop(name, None)\n        self.set_cookie(\n            name,\n            \"\",\n            max_age=0,\n            expires=\"Thu, 01 Jan 1970 00:00:00 GMT\",\n            domain=domain,\n            path=path,\n            secure=secure,\n            httponly=httponly,\n            samesite=samesite,\n        )\n\n    @property\n    def content_length(self) -> Optional[int]:\n        # Just a placeholder for adding setter\n        return super().content_length\n\n    @content_length.setter\n    def content_length(self, value: Optional[int]) -> None:\n        if value is not None:\n            value = int(value)\n            if self._chunked:\n                raise RuntimeError(\n                    \"You can't set content length when chunked encoding is enable\"\n                )\n            self._headers[hdrs.CONTENT_LENGTH] = str(value)\n        else:\n            self._headers.pop(hdrs.CONTENT_LENGTH, None)\n\n    @property\n    def content_type(self) -> str:\n        # Just a placeholder for adding setter\n        return super().content_type\n\n    @content_type.setter\n    def content_type(self, value: str) -> None:\n        self.content_type  # read header values if needed\n        self._content_type = str(value)\n        self._generate_content_type_header()\n\n    @property\n    def charset(self) -> Optional[str]:\n        # Just a placeholder for adding setter\n        return super().charset\n\n    @charset.setter\n    def charset(self, value: Optional[str]) -> None:\n        ctype = self.content_type  # read header values if needed\n        if ctype == \"application/octet-stream\":\n            raise RuntimeError(\n                \"Setting charset for application/octet-stream \"\n                \"doesn't make sense, setup content_type first\"\n            )\n        assert self._content_dict is not None\n        if value is None:\n            self._content_dict.pop(\"charset\", None)\n        else:\n            self._content_dict[\"charset\"] = str(value).lower()\n        self._generate_content_type_header()\n\n    @property\n    def last_modified(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of Last-Modified HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self._headers.get(hdrs.LAST_MODIFIED))\n\n    @last_modified.setter\n    def last_modified(\n        self, value: Optional[Union[int, float, datetime.datetime, str]]\n    ) -> None:\n        if value is None:\n            self._headers.pop(hdrs.LAST_MODIFIED, None)\n        elif isinstance(value, (int, float)):\n            self._headers[hdrs.LAST_MODIFIED] = time.strftime(\n                \"%a, %d %b %Y %H:%M:%S GMT\", time.gmtime(math.ceil(value))\n            )\n        elif isinstance(value, datetime.datetime):\n            self._headers[hdrs.LAST_MODIFIED] = time.strftime(\n                \"%a, %d %b %Y %H:%M:%S GMT\", value.utctimetuple()\n            )\n        elif isinstance(value, str):\n            self._headers[hdrs.LAST_MODIFIED] = value\n\n    @property\n    def etag(self) -> Optional[ETag]:\n        quoted_value = self._headers.get(hdrs.ETAG)\n        if not quoted_value:\n            return None\n        elif quoted_value == ETAG_ANY:\n            return ETag(value=ETAG_ANY)\n        match = QUOTED_ETAG_RE.fullmatch(quoted_value)\n        if not match:\n            return None\n        is_weak, value = match.group(1, 2)\n        return ETag(\n            is_weak=bool(is_weak),\n            value=value,\n        )\n\n    @etag.setter\n    def etag(self, value: Optional[Union[ETag, str]]) -> None:\n        if value is None:\n            self._headers.pop(hdrs.ETAG, None)\n        elif (isinstance(value, str) and value == ETAG_ANY) or (\n            isinstance(value, ETag) and value.value == ETAG_ANY\n        ):\n            self._headers[hdrs.ETAG] = ETAG_ANY\n        elif isinstance(value, str):\n            validate_etag_value(value)\n            self._headers[hdrs.ETAG] = f'\"{value}\"'\n        elif isinstance(value, ETag) and isinstance(value.value, str):\n            validate_etag_value(value.value)\n            hdr_value = f'W/\"{value.value}\"' if value.is_weak else f'\"{value.value}\"'\n            self._headers[hdrs.ETAG] = hdr_value\n        else:\n            raise ValueError(\n                f\"Unsupported etag type: {type(value)}. \"\n                f\"etag must be str, ETag or None\"\n            )\n\n    def _generate_content_type_header(\n        self, CONTENT_TYPE: istr = hdrs.CONTENT_TYPE\n    ) -> None:\n        assert self._content_dict is not None\n        assert self._content_type is not None\n        params = \"; \".join(f\"{k}={v}\" for k, v in self._content_dict.items())\n        if params:\n            ctype = self._content_type + \"; \" + params\n        else:\n            ctype = self._content_type\n        self._headers[CONTENT_TYPE] = ctype\n\n    async def _do_start_compression(self, coding: ContentCoding) -> None:\n        if coding != ContentCoding.identity:\n            assert self._payload_writer is not None\n            self._headers[hdrs.CONTENT_ENCODING] = coding.value\n            self._payload_writer.enable_compression(\n                coding.value, self._compression_strategy\n            )\n            # Compressed payload may have different content length,\n            # remove the header\n            self._headers.popall(hdrs.CONTENT_LENGTH, None)\n\n    async def _start_compression(self, request: \"BaseRequest\") -> None:\n        if self._compression_force:\n            await self._do_start_compression(self._compression_force)\n        else:\n            # Encoding comparisons should be case-insensitive\n            # https://www.rfc-editor.org/rfc/rfc9110#section-8.4.1\n            accept_encoding = request.headers.get(hdrs.ACCEPT_ENCODING, \"\").lower()\n            for coding in ContentCoding:\n                if coding.value in accept_encoding:\n                    await self._do_start_compression(coding)\n                    return\n\n    async def prepare(self, request: \"BaseRequest\") -> Optional[AbstractStreamWriter]:\n        if self._eof_sent:\n            return None\n        if self._payload_writer is not None:\n            return self._payload_writer\n        self._must_be_empty_body = must_be_empty_body(request.method, self.status)\n        return await self._start(request)\n\n    async def _start(self, request: \"BaseRequest\") -> AbstractStreamWriter:\n        self._req = request\n        writer = self._payload_writer = request._payload_writer\n\n        await self._prepare_headers()\n        await request._prepare_hook(self)\n        await self._write_headers()\n\n        return writer\n\n    async def _prepare_headers(self) -> None:\n        request = self._req\n        assert request is not None\n        writer = self._payload_writer\n        assert writer is not None\n        keep_alive = self._keep_alive\n        if keep_alive is None:\n            keep_alive = request.keep_alive\n        self._keep_alive = keep_alive\n\n        version = request.version\n\n        headers = self._headers\n        for cookie in self._cookies.values():\n            value = cookie.output(header=\"\")[1:]\n            headers.add(hdrs.SET_COOKIE, value)\n\n        if self._compression:\n            await self._start_compression(request)\n\n        if self._chunked:\n            if version != HttpVersion11:\n                raise RuntimeError(\n                    \"Using chunked encoding is forbidden \"\n                    \"for HTTP/{0.major}.{0.minor}\".format(request.version)\n                )\n            if not self._must_be_empty_body:\n                writer.enable_chunking()\n                headers[hdrs.TRANSFER_ENCODING] = \"chunked\"\n            if hdrs.CONTENT_LENGTH in headers:\n                del headers[hdrs.CONTENT_LENGTH]\n        elif self._length_check:\n            writer.length = self.content_length\n            if writer.length is None:\n                if version >= HttpVersion11:\n                    if not self._must_be_empty_body:\n                        writer.enable_chunking()\n                        headers[hdrs.TRANSFER_ENCODING] = \"chunked\"\n                elif not self._must_be_empty_body:\n                    keep_alive = False\n\n        # HTTP 1.1: https://tools.ietf.org/html/rfc7230#section-3.3.2\n        # HTTP 1.0: https://tools.ietf.org/html/rfc1945#section-10.4\n        if self._must_be_empty_body:\n            if hdrs.CONTENT_LENGTH in headers and should_remove_content_length(\n                request.method, self.status\n            ):\n                del headers[hdrs.CONTENT_LENGTH]\n            # https://datatracker.ietf.org/doc/html/rfc9112#section-6.1-10\n            # https://datatracker.ietf.org/doc/html/rfc9112#section-6.1-13\n            if hdrs.TRANSFER_ENCODING in headers:\n                del headers[hdrs.TRANSFER_ENCODING]\n        elif self.content_length != 0:\n            # https://www.rfc-editor.org/rfc/rfc9110#section-8.3-5\n            headers.setdefault(hdrs.CONTENT_TYPE, \"application/octet-stream\")\n        headers.setdefault(hdrs.DATE, rfc822_formatted_time())\n        headers.setdefault(hdrs.SERVER, SERVER_SOFTWARE)\n\n        # connection header\n        if hdrs.CONNECTION not in headers:\n            if keep_alive:\n                if version == HttpVersion10:\n                    headers[hdrs.CONNECTION] = \"keep-alive\"\n            else:\n                if version == HttpVersion11:\n                    headers[hdrs.CONNECTION] = \"close\"\n\n    async def _write_headers(self) -> None:\n        request = self._req\n        assert request is not None\n        writer = self._payload_writer\n        assert writer is not None\n        # status line\n        version = request.version\n        status_line = f\"HTTP/{version[0]}.{version[1]} {self._status} {self._reason}\"\n        await writer.write_headers(status_line, self._headers)\n\n    async def write(self, data: bytes) -> None:\n        assert isinstance(\n            data, (bytes, bytearray, memoryview)\n        ), \"data argument must be byte-ish (%r)\" % type(data)\n\n        if self._eof_sent:\n            raise RuntimeError(\"Cannot call write() after write_eof()\")\n        if self._payload_writer is None:\n            raise RuntimeError(\"Cannot call write() before prepare()\")\n\n        await self._payload_writer.write(data)\n\n    async def drain(self) -> None:\n        assert not self._eof_sent, \"EOF has already been sent\"\n        assert self._payload_writer is not None, \"Response has not been started\"\n        warnings.warn(\n            \"drain method is deprecated, use await resp.write()\",\n            DeprecationWarning,\n            stacklevel=2,\n        )\n        await self._payload_writer.drain()\n\n    async def write_eof(self, data: bytes = b\"\") -> None:\n        assert isinstance(\n            data, (bytes, bytearray, memoryview)\n        ), \"data argument must be byte-ish (%r)\" % type(data)\n\n        if self._eof_sent:\n            return\n\n        assert self._payload_writer is not None, \"Response has not been started\"\n\n        await self._payload_writer.write_eof(data)\n        self._eof_sent = True\n        self._req = None\n        self._body_length = self._payload_writer.output_size\n        self._payload_writer = None\n\n    def __repr__(self) -> str:\n        if self._eof_sent:\n            info = \"eof\"\n        elif self.prepared:\n            assert self._req is not None\n            info = f\"{self._req.method} {self._req.path} \"\n        else:\n            info = \"not prepared\"\n        return f\"<{self.__class__.__name__} {self.reason} {info}>\"\n\n    def __getitem__(self, key: str) -> Any:\n        return self._state[key]\n\n    def __setitem__(self, key: str, value: Any) -> None:\n        self._state[key] = value\n\n    def __delitem__(self, key: str) -> None:\n        del self._state[key]\n\n    def __len__(self) -> int:\n        return len(self._state)\n\n    def __iter__(self) -> Iterator[str]:\n        return iter(self._state)\n\n    def __hash__(self) -> int:\n        return hash(id(self))\n\n    def __eq__(self, other: object) -> bool:\n        return self is other",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 134,
                            "end_lineno": 150,
                            "parent": {
                                "file_name": "aiohttp/web_response.py",
                                "type": "class",
                                "name": "StreamResponse",
                                "content": "class StreamResponse(BaseClass, HeadersMixin):\n\n    _length_check = True\n\n    _body: Union[None, bytes, bytearray, Payload]\n\n    def __init__(\n        self,\n        *,\n        status: int = 200,\n        reason: Optional[str] = None,\n        headers: Optional[LooseHeaders] = None,\n    ) -> None:\n        self._body = None\n        self._keep_alive: Optional[bool] = None\n        self._chunked = False\n        self._compression = False\n        self._compression_strategy: int = zlib.Z_DEFAULT_STRATEGY\n        self._compression_force: Optional[ContentCoding] = None\n        self._cookies = SimpleCookie()\n\n        self._req: Optional[BaseRequest] = None\n        self._payload_writer: Optional[AbstractStreamWriter] = None\n        self._eof_sent = False\n        self._must_be_empty_body: Optional[bool] = None\n        self._body_length = 0\n        self._state: Dict[str, Any] = {}\n\n        if headers is not None:\n            self._headers: CIMultiDict[str] = CIMultiDict(headers)\n        else:\n            self._headers = CIMultiDict()\n\n        self.set_status(status, reason)\n\n    @property\n    def prepared(self) -> bool:\n        return self._eof_sent or self._payload_writer is not None\n\n    @property\n    def task(self) -> \"Optional[asyncio.Task[None]]\":\n        if self._req:\n            return self._req.task\n        else:\n            return None\n\n    @property\n    def status(self) -> int:\n        return self._status\n\n    @property\n    def chunked(self) -> bool:\n        return self._chunked\n\n    @property\n    def compression(self) -> bool:\n        return self._compression\n\n    @property\n    def reason(self) -> str:\n        return self._reason\n\n    def set_status(\n        self,\n        status: int,\n        reason: Optional[str] = None,\n    ) -> None:\n        assert (\n            not self.prepared\n        ), \"Cannot change the response status code after the headers have been sent\"\n        self._status = int(status)\n        if reason is None:\n            try:\n                reason = HTTPStatus(self._status).phrase\n            except ValueError:\n                reason = \"\"\n        if \"\\n\" in reason:\n            raise ValueError(\"Reason cannot contain \\\\n\")\n        self._reason = reason\n\n    @property\n    def keep_alive(self) -> Optional[bool]:\n        return self._keep_alive\n\n    def force_close(self) -> None:\n        self._keep_alive = False\n\n    @property\n    def body_length(self) -> int:\n        return self._body_length\n\n    @property\n    def output_length(self) -> int:\n        warnings.warn(\"output_length is deprecated\", DeprecationWarning)\n        assert self._payload_writer\n        return self._payload_writer.buffer_size\n\n    def enable_chunked_encoding(self, chunk_size: Optional[int] = None) -> None:\n        \"\"\"Enables automatic chunked transfer encoding.\"\"\"\n        self._chunked = True\n\n        if hdrs.CONTENT_LENGTH in self._headers:\n            raise RuntimeError(\n                \"You can't enable chunked encoding when a content length is set\"\n            )\n        if chunk_size is not None:\n            warnings.warn(\"Chunk size is deprecated #1615\", DeprecationWarning)\n\n    def enable_compression(\n        self,\n        force: Optional[Union[bool, ContentCoding]] = None,\n        strategy: int = zlib.Z_DEFAULT_STRATEGY,\n    ) -> None:\n        \"\"\"Enables response compression encoding.\"\"\"\n        # Backwards compatibility for when force was a bool <0.17.\n        if isinstance(force, bool):\n            force = ContentCoding.deflate if force else ContentCoding.identity\n            warnings.warn(\n                \"Using boolean for force is deprecated #3318\", DeprecationWarning\n            )\n        elif force is not None:\n            assert isinstance(\n                force, ContentCoding\n            ), \"force should one of None, bool or ContentEncoding\"\n\n        self._compression = True\n        self._compression_force = force\n        self._compression_strategy = strategy\n\n    @property\n    def headers(self) -> \"CIMultiDict[str]\":\n        return self._headers\n\n    @property\n    def cookies(self) -> SimpleCookie:\n        return self._cookies\n\n    def set_cookie(\n        self,\n        name: str,\n        value: str,\n        *,\n        expires: Optional[str] = None,\n        domain: Optional[str] = None,\n        max_age: Optional[Union[int, str]] = None,\n        path: str = \"/\",\n        secure: Optional[bool] = None,\n        httponly: Optional[bool] = None,\n        version: Optional[str] = None,\n        samesite: Optional[str] = None,\n    ) -> None:\n        \"\"\"Set or update response cookie.\n\n        Sets new cookie or updates existent with new value.\n        Also updates only those params which are not None.\n        \"\"\"\n        old = self._cookies.get(name)\n        if old is not None and old.coded_value == \"\":\n            # deleted cookie\n            self._cookies.pop(name, None)\n\n        self._cookies[name] = value\n        c = self._cookies[name]\n\n        if expires is not None:\n            c[\"expires\"] = expires\n        elif c.get(\"expires\") == \"Thu, 01 Jan 1970 00:00:00 GMT\":\n            del c[\"expires\"]\n\n        if domain is not None:\n            c[\"domain\"] = domain\n\n        if max_age is not None:\n            c[\"max-age\"] = str(max_age)\n        elif \"max-age\" in c:\n            del c[\"max-age\"]\n\n        c[\"path\"] = path\n\n        if secure is not None:\n            c[\"secure\"] = secure\n        if httponly is not None:\n            c[\"httponly\"] = httponly\n        if version is not None:\n            c[\"version\"] = version\n        if samesite is not None:\n            c[\"samesite\"] = samesite\n\n    def del_cookie(\n        self,\n        name: str,\n        *,\n        domain: Optional[str] = None,\n        path: str = \"/\",\n        secure: Optional[bool] = None,\n        httponly: Optional[bool] = None,\n        samesite: Optional[str] = None,\n    ) -> None:\n        \"\"\"Delete cookie.\n\n        Creates new empty expired cookie.\n        \"\"\"\n        # TODO: do we need domain/path here?\n        self._cookies.pop(name, None)\n        self.set_cookie(\n            name,\n            \"\",\n            max_age=0,\n            expires=\"Thu, 01 Jan 1970 00:00:00 GMT\",\n            domain=domain,\n            path=path,\n            secure=secure,\n            httponly=httponly,\n            samesite=samesite,\n        )\n\n    @property\n    def content_length(self) -> Optional[int]:\n        # Just a placeholder for adding setter\n        return super().content_length\n\n    @content_length.setter\n    def content_length(self, value: Optional[int]) -> None:\n        if value is not None:\n            value = int(value)\n            if self._chunked:\n                raise RuntimeError(\n                    \"You can't set content length when chunked encoding is enable\"\n                )\n            self._headers[hdrs.CONTENT_LENGTH] = str(value)\n        else:\n            self._headers.pop(hdrs.CONTENT_LENGTH, None)\n\n    @property\n    def content_type(self) -> str:\n        # Just a placeholder for adding setter\n        return super().content_type\n\n    @content_type.setter\n    def content_type(self, value: str) -> None:\n        self.content_type  # read header values if needed\n        self._content_type = str(value)\n        self._generate_content_type_header()\n\n    @property\n    def charset(self) -> Optional[str]:\n        # Just a placeholder for adding setter\n        return super().charset\n\n    @charset.setter\n    def charset(self, value: Optional[str]) -> None:\n        ctype = self.content_type  # read header values if needed\n        if ctype == \"application/octet-stream\":\n            raise RuntimeError(\n                \"Setting charset for application/octet-stream \"\n                \"doesn't make sense, setup content_type first\"\n            )\n        assert self._content_dict is not None\n        if value is None:\n            self._content_dict.pop(\"charset\", None)\n        else:\n            self._content_dict[\"charset\"] = str(value).lower()\n        self._generate_content_type_header()\n\n    @property\n    def last_modified(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of Last-Modified HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self._headers.get(hdrs.LAST_MODIFIED))\n\n    @last_modified.setter\n    def last_modified(\n        self, value: Optional[Union[int, float, datetime.datetime, str]]\n    ) -> None:\n        if value is None:\n            self._headers.pop(hdrs.LAST_MODIFIED, None)\n        elif isinstance(value, (int, float)):\n            self._headers[hdrs.LAST_MODIFIED] = time.strftime(\n                \"%a, %d %b %Y %H:%M:%S GMT\", time.gmtime(math.ceil(value))\n            )\n        elif isinstance(value, datetime.datetime):\n            self._headers[hdrs.LAST_MODIFIED] = time.strftime(\n                \"%a, %d %b %Y %H:%M:%S GMT\", value.utctimetuple()\n            )\n        elif isinstance(value, str):\n            self._headers[hdrs.LAST_MODIFIED] = value\n\n    @property\n    def etag(self) -> Optional[ETag]:\n        quoted_value = self._headers.get(hdrs.ETAG)\n        if not quoted_value:\n            return None\n        elif quoted_value == ETAG_ANY:\n            return ETag(value=ETAG_ANY)\n        match = QUOTED_ETAG_RE.fullmatch(quoted_value)\n        if not match:\n            return None\n        is_weak, value = match.group(1, 2)\n        return ETag(\n            is_weak=bool(is_weak),\n            value=value,\n        )\n\n    @etag.setter\n    def etag(self, value: Optional[Union[ETag, str]]) -> None:\n        if value is None:\n            self._headers.pop(hdrs.ETAG, None)\n        elif (isinstance(value, str) and value == ETAG_ANY) or (\n            isinstance(value, ETag) and value.value == ETAG_ANY\n        ):\n            self._headers[hdrs.ETAG] = ETAG_ANY\n        elif isinstance(value, str):\n            validate_etag_value(value)\n            self._headers[hdrs.ETAG] = f'\"{value}\"'\n        elif isinstance(value, ETag) and isinstance(value.value, str):\n            validate_etag_value(value.value)\n            hdr_value = f'W/\"{value.value}\"' if value.is_weak else f'\"{value.value}\"'\n            self._headers[hdrs.ETAG] = hdr_value\n        else:\n            raise ValueError(\n                f\"Unsupported etag type: {type(value)}. \"\n                f\"etag must be str, ETag or None\"\n            )\n\n    def _generate_content_type_header(\n        self, CONTENT_TYPE: istr = hdrs.CONTENT_TYPE\n    ) -> None:\n        assert self._content_dict is not None\n        assert self._content_type is not None\n        params = \"; \".join(f\"{k}={v}\" for k, v in self._content_dict.items())\n        if params:\n            ctype = self._content_type + \"; \" + params\n        else:\n            ctype = self._content_type\n        self._headers[CONTENT_TYPE] = ctype\n\n    async def _do_start_compression(self, coding: ContentCoding) -> None:\n        if coding != ContentCoding.identity:\n            assert self._payload_writer is not None\n            self._headers[hdrs.CONTENT_ENCODING] = coding.value\n            self._payload_writer.enable_compression(\n                coding.value, self._compression_strategy\n            )\n            # Compressed payload may have different content length,\n            # remove the header\n            self._headers.popall(hdrs.CONTENT_LENGTH, None)\n\n    async def _start_compression(self, request: \"BaseRequest\") -> None:\n        if self._compression_force:\n            await self._do_start_compression(self._compression_force)\n        else:\n            # Encoding comparisons should be case-insensitive\n            # https://www.rfc-editor.org/rfc/rfc9110#section-8.4.1\n            accept_encoding = request.headers.get(hdrs.ACCEPT_ENCODING, \"\").lower()\n            for coding in ContentCoding:\n                if coding.value in accept_encoding:\n                    await self._do_start_compression(coding)\n                    return\n\n    async def prepare(self, request: \"BaseRequest\") -> Optional[AbstractStreamWriter]:\n        if self._eof_sent:\n            return None\n        if self._payload_writer is not None:\n            return self._payload_writer\n        self._must_be_empty_body = must_be_empty_body(request.method, self.status)\n        return await self._start(request)\n\n    async def _start(self, request: \"BaseRequest\") -> AbstractStreamWriter:\n        self._req = request\n        writer = self._payload_writer = request._payload_writer\n\n        await self._prepare_headers()\n        await request._prepare_hook(self)\n        await self._write_headers()\n\n        return writer\n\n    async def _prepare_headers(self) -> None:\n        request = self._req\n        assert request is not None\n        writer = self._payload_writer\n        assert writer is not None\n        keep_alive = self._keep_alive\n        if keep_alive is None:\n            keep_alive = request.keep_alive\n        self._keep_alive = keep_alive\n\n        version = request.version\n\n        headers = self._headers\n        for cookie in self._cookies.values():\n            value = cookie.output(header=\"\")[1:]\n            headers.add(hdrs.SET_COOKIE, value)\n\n        if self._compression:\n            await self._start_compression(request)\n\n        if self._chunked:\n            if version != HttpVersion11:\n                raise RuntimeError(\n                    \"Using chunked encoding is forbidden \"\n                    \"for HTTP/{0.major}.{0.minor}\".format(request.version)\n                )\n            if not self._must_be_empty_body:\n                writer.enable_chunking()\n                headers[hdrs.TRANSFER_ENCODING] = \"chunked\"\n            if hdrs.CONTENT_LENGTH in headers:\n                del headers[hdrs.CONTENT_LENGTH]\n        elif self._length_check:\n            writer.length = self.content_length\n            if writer.length is None:\n                if version >= HttpVersion11:\n                    if not self._must_be_empty_body:\n                        writer.enable_chunking()\n                        headers[hdrs.TRANSFER_ENCODING] = \"chunked\"\n                elif not self._must_be_empty_body:\n                    keep_alive = False\n\n        # HTTP 1.1: https://tools.ietf.org/html/rfc7230#section-3.3.2\n        # HTTP 1.0: https://tools.ietf.org/html/rfc1945#section-10.4\n        if self._must_be_empty_body:\n            if hdrs.CONTENT_LENGTH in headers and should_remove_content_length(\n                request.method, self.status\n            ):\n                del headers[hdrs.CONTENT_LENGTH]\n            # https://datatracker.ietf.org/doc/html/rfc9112#section-6.1-10\n            # https://datatracker.ietf.org/doc/html/rfc9112#section-6.1-13\n            if hdrs.TRANSFER_ENCODING in headers:\n                del headers[hdrs.TRANSFER_ENCODING]\n        elif self.content_length != 0:\n            # https://www.rfc-editor.org/rfc/rfc9110#section-8.3-5\n            headers.setdefault(hdrs.CONTENT_TYPE, \"application/octet-stream\")\n        headers.setdefault(hdrs.DATE, rfc822_formatted_time())\n        headers.setdefault(hdrs.SERVER, SERVER_SOFTWARE)\n\n        # connection header\n        if hdrs.CONNECTION not in headers:\n            if keep_alive:\n                if version == HttpVersion10:\n                    headers[hdrs.CONNECTION] = \"keep-alive\"\n            else:\n                if version == HttpVersion11:\n                    headers[hdrs.CONNECTION] = \"close\"\n\n    async def _write_headers(self) -> None:\n        request = self._req\n        assert request is not None\n        writer = self._payload_writer\n        assert writer is not None\n        # status line\n        version = request.version\n        status_line = f\"HTTP/{version[0]}.{version[1]} {self._status} {self._reason}\"\n        await writer.write_headers(status_line, self._headers)\n\n    async def write(self, data: bytes) -> None:\n        assert isinstance(\n            data, (bytes, bytearray, memoryview)\n        ), \"data argument must be byte-ish (%r)\" % type(data)\n\n        if self._eof_sent:\n            raise RuntimeError(\"Cannot call write() after write_eof()\")\n        if self._payload_writer is None:\n            raise RuntimeError(\"Cannot call write() before prepare()\")\n\n        await self._payload_writer.write(data)\n\n    async def drain(self) -> None:\n        assert not self._eof_sent, \"EOF has already been sent\"\n        assert self._payload_writer is not None, \"Response has not been started\"\n        warnings.warn(\n            \"drain method is deprecated, use await resp.write()\",\n            DeprecationWarning,\n            stacklevel=2,\n        )\n        await self._payload_writer.drain()\n\n    async def write_eof(self, data: bytes = b\"\") -> None:\n        assert isinstance(\n            data, (bytes, bytearray, memoryview)\n        ), \"data argument must be byte-ish (%r)\" % type(data)\n\n        if self._eof_sent:\n            return\n\n        assert self._payload_writer is not None, \"Response has not been started\"\n\n        await self._payload_writer.write_eof(data)\n        self._eof_sent = True\n        self._req = None\n        self._body_length = self._payload_writer.output_size\n        self._payload_writer = None\n\n    def __repr__(self) -> str:\n        if self._eof_sent:\n            info = \"eof\"\n        elif self.prepared:\n            assert self._req is not None\n            info = f\"{self._req.method} {self._req.path} \"\n        else:\n            info = \"not prepared\"\n        return f\"<{self.__class__.__name__} {self.reason} {info}>\"\n\n    def __getitem__(self, key: str) -> Any:\n        return self._state[key]\n\n    def __setitem__(self, key: str, value: Any) -> None:\n        self._state[key] = value\n\n    def __delitem__(self, key: str) -> None:\n        del self._state[key]\n\n    def __len__(self) -> int:\n        return len(self._state)\n\n    def __iter__(self) -> Iterator[str]:\n        return iter(self._state)\n\n    def __hash__(self) -> int:\n        return hash(id(self))\n\n    def __eq__(self, other: object) -> bool:\n        return self is other",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 72,
                                "end_lineno": 595,
                                "parent": null
                            }
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "import collections\nimport re\nfrom traceback import format_exception\nfrom unittest import mock\n\nimport aiosignal\nimport pytest\nfrom yarl import URL\n\nfrom aiohttp import helpers, web\nfrom aiohttp.pytest_plugin import AiohttpClient\nfrom aiohttp.test_utils import make_mocked_request\n\n\n@pytest.fixture\ndef buf() -> bytearray:\n    return bytearray()\n\n\n@pytest.fixture\ndef http_request(buf):\n    method = \"GET\"\n    path = \"/\"\n    writer = mock.Mock()\n    writer.drain.return_value = ()\n\n    def append(data=b\"\"):\n        buf.extend(data)\n        return helpers.noop()\n\n    async def write_headers(status_line, headers):\n        headers = (\n            status_line\n            + \"\\r\\n\"\n            + \"\".join([k + \": \" + v + \"\\r\\n\" for k, v in headers.items()])\n        )\n        headers = headers.encode(\"utf-8\") + b\"\\r\\n\"\n        buf.extend(headers)\n\n    writer.buffer_data.side_effect = append\n    writer.write.side_effect = append\n    writer.write_eof.side_effect = append\n    writer.write_headers.side_effect = write_headers\n\n    app = mock.Mock()\n    app._debug = False\n    app.on_response_prepare = aiosignal.Signal(app)\n    app.on_response_prepare.freeze()\n    req = make_mocked_request(method, path, app=app, writer=writer)\n    return req\n\n\ndef test_all_http_exceptions_exported() -> None:\n    assert \"HTTPException\" in web.__all__\n    for name in dir(web):\n        if name.startswith(\"_\"):\n            continue\n        obj = getattr(web, name)\n        if isinstance(obj, type) and issubclass(obj, web.HTTPException):\n            assert name in web.__all__\n\n\nasync def test_HTTPOk(buf, http_request) -> None:\n    resp = web.HTTPOk()\n    await resp.prepare(http_request)\n    await resp.write_eof()\n    txt = buf.decode(\"utf8\")\n    assert re.match(\n        (\n            \"HTTP/1.1 200 OK\\r\\n\"\n            \"Content-Type: text/plain; charset=utf-8\\r\\n\"\n            \"Content-Length: 7\\r\\n\"\n            \"Date: .+\\r\\n\"\n            \"Server: .+\\r\\n\\r\\n\"\n            \"200: OK\"\n        ),\n        txt,\n    )\n\n\ndef test_terminal_classes_has_status_code() -> None:\n    terminals = set()\n    for name in dir(web):\n        obj = getattr(web, name)\n        if isinstance(obj, type) and issubclass(obj, web.HTTPException):\n            terminals.add(obj)\n\n    dup = frozenset(terminals)\n    for cls1 in dup:\n        for cls2 in dup:\n            if cls1 in cls2.__bases__:\n                terminals.discard(cls1)\n\n    for cls in terminals:\n        assert cls.status_code is not None\n    codes = collections.Counter(cls.status_code for cls in terminals)\n    assert None not in codes\n    assert 1 == codes.most_common(1)[0][1]\n\n\nasync def test_HTTPFound(buf, http_request) -> None:\n    resp = web.HTTPFound(location=\"/redirect\")\n    assert \"/redirect\" == resp.location\n    assert \"/redirect\" == resp.headers[\"location\"]\n    await resp.prepare(http_request)\n    await resp.write_eof()\n    txt = buf.decode(\"utf8\")\n    assert re.match(\n        \"HTTP/1.1 302 Found\\r\\n\"\n        \"Content-Type: text/plain; charset=utf-8\\r\\n\"\n        \"Location: /redirect\\r\\n\"\n        \"Content-Length: 10\\r\\n\"\n        \"Date: .+\\r\\n\"\n        \"Server: .+\\r\\n\\r\\n\"\n        \"302: Found\",\n        txt,\n    )\n\n\ndef test_HTTPFound_empty_location() -> None:\n    with pytest.raises(ValueError):\n        web.HTTPFound(location=\"\")\n\n    with pytest.raises(ValueError):\n        web.HTTPFound(location=None)\n\n\ndef test_HTTPFound_location_CRLF() -> None:\n    exc = web.HTTPFound(location=\"/redirect\\r\\n\")\n    assert \"\\r\\n\" not in exc.headers[\"Location\"]\n\n\nasync def test_HTTPMethodNotAllowed(buf, http_request) -> None:\n    resp = web.HTTPMethodNotAllowed(\"get\", [\"POST\", \"PUT\"])\n    assert \"GET\" == resp.method\n    assert {\"POST\", \"PUT\"} == resp.allowed_methods\n    assert \"POST,PUT\" == resp.headers[\"allow\"]\n    await resp.prepare(http_request)\n    await resp.write_eof()\n    txt = buf.decode(\"utf8\")\n    assert re.match(\n        \"HTTP/1.1 405 Method Not Allowed\\r\\n\"\n        \"Content-Type: text/plain; charset=utf-8\\r\\n\"\n        \"Allow: POST,PUT\\r\\n\"\n        \"Content-Length: 23\\r\\n\"\n        \"Date: .+\\r\\n\"\n        \"Server: .+\\r\\n\\r\\n\"\n        \"405: Method Not Allowed\",\n        txt,\n    )\n\n\ndef test_override_body_with_text() -> None:\n    resp = web.HTTPNotFound(text=\"Page not found\")\n    assert 404 == resp.status\n    assert b\"Page not found\" == resp.body\n    assert \"Page not found\" == resp.text\n    assert \"text/plain\" == resp.content_type\n    assert \"utf-8\" == resp.charset\n\n\ndef test_override_body_with_binary() -> None:\n    txt = \"<html><body>Page not found</body></html>\"\n    with pytest.warns(DeprecationWarning):\n        resp = web.HTTPNotFound(body=txt.encode(\"utf-8\"), content_type=\"text/html\")\n    assert 404 == resp.status\n    assert txt.encode(\"utf-8\") == resp.body\n    assert txt == resp.text\n    assert \"text/html\" == resp.content_type\n    assert resp.charset is None\n\n\ndef test_default_body() -> None:\n    resp = web.HTTPOk()\n    assert b\"200: OK\" == resp.body\n\n\ndef test_empty_body_204() -> None:\n    resp = web.HTTPNoContent()\n    assert resp.body is None\n\n\ndef test_empty_body_205() -> None:\n    resp = web.HTTPNoContent()\n    assert resp.body is None\n\n\ndef test_empty_body_304() -> None:\n    resp = web.HTTPNoContent()\n    resp.body is None\n\n\ndef test_no_link_451() -> None:\n    with pytest.raises(TypeError):\n        web.HTTPUnavailableForLegalReasons()  # type: ignore[call-arg]\n\n\ndef test_link_none_451() -> None:\n    resp = web.HTTPUnavailableForLegalReasons(link=None)\n    assert resp.link is None\n    assert \"Link\" not in resp.headers\n\n\ndef test_link_empty_451() -> None:\n    resp = web.HTTPUnavailableForLegalReasons(link=\"\")\n    assert resp.link is None\n    assert \"Link\" not in resp.headers\n\n\ndef test_link_str_451() -> None:\n    resp = web.HTTPUnavailableForLegalReasons(link=\"http://warning.or.kr/\")\n    assert resp.link == URL(\"http://warning.or.kr/\")\n    assert resp.headers[\"Link\"] == '<http://warning.or.kr/>; rel=\"blocked-by\"'\n\n\ndef test_link_url_451() -> None:\n    resp = web.HTTPUnavailableForLegalReasons(link=URL(\"http://warning.or.kr/\"))\n    assert resp.link == URL(\"http://warning.or.kr/\")\n    assert resp.headers[\"Link\"] == '<http://warning.or.kr/>; rel=\"blocked-by\"'\n\n\ndef test_link_CRLF_451() -> None:\n    resp = web.HTTPUnavailableForLegalReasons(link=\"http://warning.or.kr/\\r\\n\")\n    assert \"\\r\\n\" not in resp.headers[\"Link\"]\n\n\ndef test_HTTPException_retains_cause() -> None:\n    with pytest.raises(web.HTTPException) as ei:\n        try:\n            raise Exception(\"CustomException\")\n        except Exception as exc:\n            raise web.HTTPException() from exc\n    tb = \"\".join(format_exception(ei.type, ei.value, ei.tb))\n    assert \"CustomException\" in tb\n    assert \"direct cause\" in tb\n\n\nasync def test_HTTPException_retains_cookie(aiohttp_client: AiohttpClient) -> None:\n    @web.middleware\n    async def middleware(request, handler):\n        try:\n            return await handler(request)\n        except web.HTTPException as exc:\n            exc.set_cookie(\"foo\", request[\"foo\"])\n            raise exc\n\n    async def save(request):\n        request[\"foo\"] = \"works\"\n        raise web.HTTPFound(\"/show\")\n\n    async def show(request):\n        return web.Response(text=request.cookies[\"foo\"])\n\n    app = web.Application(middlewares=[middleware])\n    app.router.add_route(\"GET\", \"/save\", save)\n    app.router.add_route(\"GET\", \"/show\", show)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/save\")\n    assert resp.status == 200\n    assert str(resp.url)[-5:] == \"/show\"\n    text = await resp.text()\n    assert text == \"works\"\n\n\ndef test_unicode_text_body_unauthorized() -> None:\n    \"\"\"Test that HTTPUnauthorized can be initialized with a string.\"\"\"\n    with pytest.warns(\n        DeprecationWarning, match=\"body argument is deprecated for http web exceptions\"\n    ):\n        resp = web.HTTPUnauthorized(body=\"text\")\n    assert resp.status == 401\n",
            "new_file_content": "import collections\nimport re\nfrom traceback import format_exception\nfrom unittest import mock\n\nimport aiosignal\nimport pytest\nfrom yarl import URL\n\nfrom aiohttp import helpers, web\nfrom aiohttp.pytest_plugin import AiohttpClient\nfrom aiohttp.test_utils import make_mocked_request\n\n\n@pytest.fixture\ndef buf() -> bytearray:\n    return bytearray()\n\n\n@pytest.fixture\ndef http_request(buf):\n    method = \"GET\"\n    path = \"/\"\n    writer = mock.Mock()\n    writer.drain.return_value = ()\n\n    def append(data=b\"\"):\n        buf.extend(data)\n        return helpers.noop()\n\n    async def write_headers(status_line, headers):\n        headers = (\n            status_line\n            + \"\\r\\n\"\n            + \"\".join([k + \": \" + v + \"\\r\\n\" for k, v in headers.items()])\n        )\n        headers = headers.encode(\"utf-8\") + b\"\\r\\n\"\n        buf.extend(headers)\n\n    writer.buffer_data.side_effect = append\n    writer.write.side_effect = append\n    writer.write_eof.side_effect = append\n    writer.write_headers.side_effect = write_headers\n\n    app = mock.Mock()\n    app._debug = False\n    app.on_response_prepare = aiosignal.Signal(app)\n    app.on_response_prepare.freeze()\n    req = make_mocked_request(method, path, app=app, writer=writer)\n    return req\n\n\ndef test_all_http_exceptions_exported() -> None:\n    assert \"HTTPException\" in web.__all__\n    for name in dir(web):\n        if name.startswith(\"_\"):\n            continue\n        obj = getattr(web, name)\n        if isinstance(obj, type) and issubclass(obj, web.HTTPException):\n            assert name in web.__all__\n\n\nasync def test_HTTPOk(buf, http_request) -> None:\n    resp = web.HTTPOk()\n    await resp.prepare(http_request)\n    await resp.write_eof()\n    txt = buf.decode(\"utf8\")\n    assert re.match(\n        (\n            \"HTTP/1.1 200 OK\\r\\n\"\n            \"Content-Type: text/plain; charset=utf-8\\r\\n\"\n            \"Content-Length: 7\\r\\n\"\n            \"Date: .+\\r\\n\"\n            \"Server: .+\\r\\n\\r\\n\"\n            \"200: OK\"\n        ),\n        txt,\n    )\n\n\ndef test_terminal_classes_has_status_code() -> None:\n    terminals = set()\n    for name in dir(web):\n        obj = getattr(web, name)\n        if isinstance(obj, type) and issubclass(obj, web.HTTPException):\n            terminals.add(obj)\n\n    dup = frozenset(terminals)\n    for cls1 in dup:\n        for cls2 in dup:\n            if cls1 in cls2.__bases__:\n                terminals.discard(cls1)\n\n    for cls in terminals:\n        assert cls.status_code is not None\n    codes = collections.Counter(cls.status_code for cls in terminals)\n    assert None not in codes\n    assert 1 == codes.most_common(1)[0][1]\n\n\nasync def test_HTTPFound(buf, http_request) -> None:\n    resp = web.HTTPFound(location=\"/redirect\")\n    assert \"/redirect\" == resp.location\n    assert \"/redirect\" == resp.headers[\"location\"]\n    await resp.prepare(http_request)\n    await resp.write_eof()\n    txt = buf.decode(\"utf8\")\n    assert re.match(\n        \"HTTP/1.1 302 Found\\r\\n\"\n        \"Content-Type: text/plain; charset=utf-8\\r\\n\"\n        \"Location: /redirect\\r\\n\"\n        \"Content-Length: 10\\r\\n\"\n        \"Date: .+\\r\\n\"\n        \"Server: .+\\r\\n\\r\\n\"\n        \"302: Found\",\n        txt,\n    )\n\n\ndef test_HTTPFound_empty_location() -> None:\n    with pytest.raises(ValueError):\n        web.HTTPFound(location=\"\")\n\n    with pytest.raises(ValueError):\n        web.HTTPFound(location=None)\n\n\ndef test_HTTPFound_location_CRLF() -> None:\n    exc = web.HTTPFound(location=\"/redirect\\r\\n\")\n    assert \"\\r\\n\" not in exc.headers[\"Location\"]\n\n\nasync def test_HTTPMethodNotAllowed(buf, http_request) -> None:\n    resp = web.HTTPMethodNotAllowed(\"get\", [\"POST\", \"PUT\"])\n    assert \"GET\" == resp.method\n    assert {\"POST\", \"PUT\"} == resp.allowed_methods\n    assert \"POST,PUT\" == resp.headers[\"allow\"]\n    await resp.prepare(http_request)\n    await resp.write_eof()\n    txt = buf.decode(\"utf8\")\n    assert re.match(\n        \"HTTP/1.1 405 Method Not Allowed\\r\\n\"\n        \"Content-Type: text/plain; charset=utf-8\\r\\n\"\n        \"Allow: POST,PUT\\r\\n\"\n        \"Content-Length: 23\\r\\n\"\n        \"Date: .+\\r\\n\"\n        \"Server: .+\\r\\n\\r\\n\"\n        \"405: Method Not Allowed\",\n        txt,\n    )\n\n\ndef test_override_body_with_text() -> None:\n    resp = web.HTTPNotFound(text=\"Page not found\")\n    assert 404 == resp.status\n    assert b\"Page not found\" == resp.body\n    assert \"Page not found\" == resp.text\n    assert \"text/plain\" == resp.content_type\n    assert \"utf-8\" == resp.charset\n\n\ndef test_override_body_with_binary() -> None:\n    txt = \"<html><body>Page not found</body></html>\"\n    with pytest.warns(DeprecationWarning):\n        resp = web.HTTPNotFound(body=txt.encode(\"utf-8\"), content_type=\"text/html\")\n    assert 404 == resp.status\n    assert txt.encode(\"utf-8\") == resp.body\n    assert txt == resp.text\n    assert \"text/html\" == resp.content_type\n    assert resp.charset is None\n\n\ndef test_default_body() -> None:\n    resp = web.HTTPOk()\n    assert b\"200: OK\" == resp.body\n\n\ndef test_empty_body_204() -> None:\n    resp = web.HTTPNoContent()\n    assert resp.body is None\n\n\ndef test_empty_body_205() -> None:\n    resp = web.HTTPNoContent()\n    assert resp.body is None\n\n\ndef test_empty_body_304() -> None:\n    resp = web.HTTPNoContent()\n    resp.body is None\n\n\ndef test_no_link_451() -> None:\n    with pytest.raises(TypeError):\n        web.HTTPUnavailableForLegalReasons()  # type: ignore[call-arg]\n\n\ndef test_link_none_451() -> None:\n    resp = web.HTTPUnavailableForLegalReasons(link=None)\n    assert resp.link is None\n    assert \"Link\" not in resp.headers\n\n\ndef test_link_empty_451() -> None:\n    resp = web.HTTPUnavailableForLegalReasons(link=\"\")\n    assert resp.link is None\n    assert \"Link\" not in resp.headers\n\n\ndef test_link_str_451() -> None:\n    resp = web.HTTPUnavailableForLegalReasons(link=\"http://warning.or.kr/\")\n    assert resp.link == URL(\"http://warning.or.kr/\")\n    assert resp.headers[\"Link\"] == '<http://warning.or.kr/>; rel=\"blocked-by\"'\n\n\ndef test_link_url_451() -> None:\n    resp = web.HTTPUnavailableForLegalReasons(link=URL(\"http://warning.or.kr/\"))\n    assert resp.link == URL(\"http://warning.or.kr/\")\n    assert resp.headers[\"Link\"] == '<http://warning.or.kr/>; rel=\"blocked-by\"'\n\n\ndef test_link_CRLF_451() -> None:\n    resp = web.HTTPUnavailableForLegalReasons(link=\"http://warning.or.kr/\\r\\n\")\n    assert \"\\r\\n\" not in resp.headers[\"Link\"]\n\n\ndef test_HTTPException_retains_cause() -> None:\n    with pytest.raises(web.HTTPException) as ei:\n        try:\n            raise Exception(\"CustomException\")\n        except Exception as exc:\n            raise web.HTTPException() from exc\n    tb = \"\".join(format_exception(ei.type, ei.value, ei.tb))\n    assert \"CustomException\" in tb\n    assert \"direct cause\" in tb\n\n\nasync def test_HTTPException_retains_cookie(aiohttp_client: AiohttpClient) -> None:\n    @web.middleware\n    async def middleware(request, handler):\n        try:\n            return await handler(request)\n        except web.HTTPException as exc:\n            exc.set_cookie(\"foo\", request[\"foo\"])\n            raise exc\n\n    async def save(request):\n        request[\"foo\"] = \"works\"\n        raise web.HTTPFound(\"/show\")\n\n    async def show(request):\n        return web.Response(text=request.cookies[\"foo\"])\n\n    app = web.Application(middlewares=[middleware])\n    app.router.add_route(\"GET\", \"/save\", save)\n    app.router.add_route(\"GET\", \"/show\", show)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/save\")\n    assert resp.status == 200\n    assert str(resp.url)[-5:] == \"/show\"\n    text = await resp.text()\n    assert text == \"works\"\n\n\ndef test_unicode_text_body_unauthorized() -> None:\n    \"\"\"Test that HTTPUnauthorized can be initialized with a string.\"\"\"\n    with pytest.warns(\n        DeprecationWarning, match=\"body argument is deprecated for http web exceptions\"\n    ):\n        resp = web.HTTPUnauthorized(body=\"text\")\n    assert resp.status == 401\n\n\ndef test_multiline_reason() -> None:\n    with pytest.raises(ValueError, match=r\"Reason cannot contain \\\\n\"):\n        web.HTTPOk(reason=\"Bad\\r\\nInjected-header: foo\")\n",
            "header": {
                "file": {
                    "path": "tests/test_web_exceptions.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "69deb27a",
                "new_commit_hash": "3358a947",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/tests/test_web_exceptions.py"
            },
            "plus_file": {
                "path": "b/tests/test_web_exceptions.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 270,
                            "length": 3
                        },
                        "new_range": {
                            "start": 270,
                            "length": 8
                        },
                        "section": "def test_unicode_text_body_unauthorized() -> None:"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "    ):",
                                "type": "context"
                            },
                            {
                                "content": "        resp = web.HTTPUnauthorized(body=\"text\")",
                                "type": "context"
                            },
                            {
                                "content": "    assert resp.status == 401",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "def test_multiline_reason() -> None:",
                                "type": "added"
                            },
                            {
                                "content": "    with pytest.raises(ValueError, match=r\"Reason cannot contain \\\\n\"):",
                                "type": "added"
                            },
                            {
                                "content": "        web.HTTPOk(reason=\"Bad\\r\\nInjected-header: foo\")",
                                "type": "added"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [
                        {
                            "file_name": "tests/test_web_exceptions.py",
                            "type": "function",
                            "name": "test_multiline_reason",
                            "content": "def test_multiline_reason() -> None:\n    with pytest.raises(ValueError, match=r\"Reason cannot contain \\\\n\"):\n        web.HTTPOk(reason=\"Bad\\r\\nInjected-header: foo\")",
                            "ast_type_str": "FunctionDef",
                            "start_lineno": 275,
                            "end_lineno": 277,
                            "parent": null
                        }
                    ],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "import collections.abc\nimport datetime\nimport gzip\nimport io\nimport json\nimport zlib\nfrom concurrent.futures import ThreadPoolExecutor\nfrom typing import AsyncIterator, Optional\nfrom unittest import mock\n\nimport aiosignal\nimport pytest\nfrom multidict import CIMultiDict, CIMultiDictProxy\nfrom re_assert import Matches\n\nfrom aiohttp import HttpVersion, HttpVersion10, HttpVersion11, hdrs\nfrom aiohttp.helpers import ETag\nfrom aiohttp.http_writer import StreamWriter, _serialize_headers\nfrom aiohttp.multipart import BodyPartReader, MultipartWriter\nfrom aiohttp.payload import BytesPayload, StringPayload\nfrom aiohttp.test_utils import make_mocked_coro, make_mocked_request\nfrom aiohttp.web import ContentCoding, Response, StreamResponse, json_response\n\n\ndef make_request(\n    method,\n    path,\n    headers=CIMultiDict(),\n    version=HttpVersion11,\n    on_response_prepare=None,\n    **kwargs,\n):\n    app = kwargs.pop(\"app\", None) or mock.Mock()\n    app._debug = False\n    if on_response_prepare is None:\n        on_response_prepare = aiosignal.Signal(app)\n    app.on_response_prepare = on_response_prepare\n    app.on_response_prepare.freeze()\n    protocol = kwargs.pop(\"protocol\", None) or mock.Mock()\n    return make_mocked_request(\n        method, path, headers, version=version, protocol=protocol, app=app, **kwargs\n    )\n\n\n@pytest.fixture\ndef buf():\n    return bytearray()\n\n\n@pytest.fixture\ndef writer(buf):\n    writer = mock.Mock()\n\n    def acquire(cb):\n        cb(writer.transport)\n\n    def buffer_data(chunk):\n        buf.extend(chunk)\n\n    def write(chunk):\n        buf.extend(chunk)\n\n    async def write_headers(status_line, headers):\n        headers = _serialize_headers(status_line, headers)\n        buf.extend(headers)\n\n    async def write_eof(chunk=b\"\"):\n        buf.extend(chunk)\n\n    writer.acquire.side_effect = acquire\n    writer.transport.write.side_effect = write\n    writer.write.side_effect = write\n    writer.write_eof.side_effect = write_eof\n    writer.write_headers.side_effect = write_headers\n    writer.buffer_data.side_effect = buffer_data\n    writer.drain.return_value = ()\n\n    return writer\n\n\ndef test_stream_response_ctor() -> None:\n    resp = StreamResponse()\n    assert 200 == resp.status\n    assert resp.keep_alive is None\n\n    assert resp.task is None\n\n    req = mock.Mock()\n    resp._req = req\n    assert resp.task is req.task\n\n\ndef test_stream_response_hashable() -> None:\n    # should not raise exception\n    hash(StreamResponse())\n\n\ndef test_stream_response_eq() -> None:\n    resp1 = StreamResponse()\n    resp2 = StreamResponse()\n\n    assert resp1 == resp1\n    assert not resp1 == resp2\n\n\ndef test_stream_response_is_mutable_mapping() -> None:\n    resp = StreamResponse()\n    assert isinstance(resp, collections.abc.MutableMapping)\n    resp[\"key\"] = \"value\"\n    assert \"value\" == resp[\"key\"]\n\n\ndef test_stream_response_delitem() -> None:\n    resp = StreamResponse()\n    resp[\"key\"] = \"value\"\n    del resp[\"key\"]\n    assert \"key\" not in resp\n\n\ndef test_stream_response_len() -> None:\n    resp = StreamResponse()\n    assert len(resp) == 0\n    resp[\"key\"] = \"value\"\n    assert len(resp) == 1\n\n\ndef test_request_iter() -> None:\n    resp = StreamResponse()\n    resp[\"key\"] = \"value\"\n    resp[\"key2\"] = \"value2\"\n    assert set(resp) == {\"key\", \"key2\"}\n\n\ndef test_content_length() -> None:\n    resp = StreamResponse()\n    assert resp.content_length is None\n\n\ndef test_content_length_setter() -> None:\n    resp = StreamResponse()\n\n    resp.content_length = 234\n    assert 234 == resp.content_length\n\n\ndef test_content_length_setter_with_enable_chunked_encoding() -> None:\n    resp = StreamResponse()\n\n    resp.enable_chunked_encoding()\n    with pytest.raises(RuntimeError):\n        resp.content_length = 234\n\n\ndef test_drop_content_length_header_on_setting_len_to_None() -> None:\n    resp = StreamResponse()\n\n    resp.content_length = 1\n    assert \"1\" == resp.headers[\"Content-Length\"]\n    resp.content_length = None\n    assert \"Content-Length\" not in resp.headers\n\n\ndef test_set_content_length_to_None_on_non_set() -> None:\n    resp = StreamResponse()\n\n    resp.content_length = None\n    assert \"Content-Length\" not in resp.headers\n    resp.content_length = None\n    assert \"Content-Length\" not in resp.headers\n\n\ndef test_setting_content_type() -> None:\n    resp = StreamResponse()\n\n    resp.content_type = \"text/html\"\n    assert \"text/html\" == resp.headers[\"content-type\"]\n\n\ndef test_setting_charset() -> None:\n    resp = StreamResponse()\n\n    resp.content_type = \"text/html\"\n    resp.charset = \"koi8-r\"\n    assert \"text/html; charset=koi8-r\" == resp.headers[\"content-type\"]\n\n\ndef test_default_charset() -> None:\n    resp = StreamResponse()\n\n    assert resp.charset is None\n\n\ndef test_reset_charset() -> None:\n    resp = StreamResponse()\n\n    resp.content_type = \"text/html\"\n    resp.charset = None\n    assert resp.charset is None\n\n\ndef test_reset_charset_after_setting() -> None:\n    resp = StreamResponse()\n\n    resp.content_type = \"text/html\"\n    resp.charset = \"koi8-r\"\n    resp.charset = None\n    assert resp.charset is None\n\n\ndef test_charset_without_content_type() -> None:\n    resp = StreamResponse()\n\n    with pytest.raises(RuntimeError):\n        resp.charset = \"koi8-r\"\n\n\ndef test_last_modified_initial() -> None:\n    resp = StreamResponse()\n    assert resp.last_modified is None\n\n\ndef test_last_modified_string() -> None:\n    resp = StreamResponse()\n\n    dt = datetime.datetime(1990, 1, 2, 3, 4, 5, 0, datetime.timezone.utc)\n    resp.last_modified = \"Mon, 2 Jan 1990 03:04:05 GMT\"\n    assert resp.last_modified == dt\n\n\ndef test_last_modified_timestamp() -> None:\n    resp = StreamResponse()\n\n    dt = datetime.datetime(1970, 1, 1, 0, 0, 0, 0, datetime.timezone.utc)\n\n    resp.last_modified = 0\n    assert resp.last_modified == dt\n\n    resp.last_modified = 0.0\n    assert resp.last_modified == dt\n\n\ndef test_last_modified_datetime() -> None:\n    resp = StreamResponse()\n\n    dt = datetime.datetime(2001, 2, 3, 4, 5, 6, 0, datetime.timezone.utc)\n    resp.last_modified = dt\n    assert resp.last_modified == dt\n\n\ndef test_last_modified_reset() -> None:\n    resp = StreamResponse()\n\n    resp.last_modified = 0\n    resp.last_modified = None\n    assert resp.last_modified is None\n\n\n@pytest.mark.parametrize(\n    [\"header_val\", \"expected\"],\n    [\n        pytest.param(\"xxyyzz\", None),\n        pytest.param(\"Tue, 08 Oct 4446413 00:56:40 GMT\", None),\n        pytest.param(\"Tue, 08 Oct 2000 00:56:80 GMT\", None),\n    ],\n)\ndef test_last_modified_string_invalid(header_val, expected) -> None:\n    resp = StreamResponse(headers={\"Last-Modified\": header_val})\n    assert resp.last_modified == expected\n\n\ndef test_etag_initial() -> None:\n    resp = StreamResponse()\n    assert resp.etag is None\n\n\ndef test_etag_string() -> None:\n    resp = StreamResponse()\n    value = \"0123-kotik\"\n    resp.etag = value\n    assert resp.etag == ETag(value=value)\n    assert resp.headers[hdrs.ETAG] == f'\"{value}\"'\n\n\n@pytest.mark.parametrize(\n    [\"etag\", \"expected_header\"],\n    (\n        (ETag(value=\"0123-weak-kotik\", is_weak=True), 'W/\"0123-weak-kotik\"'),\n        (ETag(value=\"0123-strong-kotik\", is_weak=False), '\"0123-strong-kotik\"'),\n    ),\n)\ndef test_etag_class(etag, expected_header) -> None:\n    resp = StreamResponse()\n    resp.etag = etag\n    assert resp.etag == etag\n    assert resp.headers[hdrs.ETAG] == expected_header\n\n\ndef test_etag_any() -> None:\n    resp = StreamResponse()\n    resp.etag = \"*\"\n    assert resp.etag == ETag(value=\"*\")\n    assert resp.headers[hdrs.ETAG] == \"*\"\n\n\n@pytest.mark.parametrize(\n    \"invalid_value\",\n    (\n        '\"invalid\"',\n        \"повинен бути ascii\",\n        ETag(value='\"invalid\"', is_weak=True),\n        ETag(value=\"bad ©®\"),\n    ),\n)\ndef test_etag_invalid_value_set(invalid_value) -> None:\n    resp = StreamResponse()\n    with pytest.raises(ValueError, match=\"is not a valid etag\"):\n        resp.etag = invalid_value\n\n\n@pytest.mark.parametrize(\n    \"header\",\n    (\n        \"forgotten quotes\",\n        '\"∀ x ∉ ascii\"',\n    ),\n)\ndef test_etag_invalid_value_get(header) -> None:\n    resp = StreamResponse()\n    resp.headers[\"ETag\"] = header\n    assert resp.etag is None\n\n\n@pytest.mark.parametrize(\"invalid\", (123, ETag(value=123, is_weak=True)))\ndef test_etag_invalid_value_class(invalid) -> None:\n    resp = StreamResponse()\n    with pytest.raises(ValueError, match=\"Unsupported etag type\"):\n        resp.etag = invalid\n\n\ndef test_etag_reset() -> None:\n    resp = StreamResponse()\n    resp.etag = \"*\"\n    resp.etag = None\n    assert resp.etag is None\n\n\nasync def test_start() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = StreamResponse()\n    assert resp.keep_alive is None\n\n    msg = await resp.prepare(req)\n\n    assert msg.write_headers.called\n    msg2 = await resp.prepare(req)\n    assert msg is msg2\n\n    assert resp.keep_alive\n\n    req2 = make_request(\"GET\", \"/\")\n    # with pytest.raises(RuntimeError):\n    msg3 = await resp.prepare(req2)\n    assert msg is msg3\n\n\nasync def test_chunked_encoding() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = StreamResponse()\n    assert not resp.chunked\n\n    resp.enable_chunked_encoding()\n    assert resp.chunked\n\n    msg = await resp.prepare(req)\n    assert msg.chunked\n\n\ndef test_enable_chunked_encoding_with_content_length() -> None:\n    resp = StreamResponse()\n\n    resp.content_length = 234\n    with pytest.raises(RuntimeError):\n        resp.enable_chunked_encoding()\n\n\nasync def test_chunk_size() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = StreamResponse()\n    assert not resp.chunked\n\n    with pytest.warns(DeprecationWarning):\n        resp.enable_chunked_encoding(chunk_size=8192)\n    assert resp.chunked\n\n    msg = await resp.prepare(req)\n    assert msg.chunked\n    assert msg.enable_chunking.called\n    assert msg.filter is not None\n\n\nasync def test_chunked_encoding_forbidden_for_http_10() -> None:\n    req = make_request(\"GET\", \"/\", version=HttpVersion10)\n    resp = StreamResponse()\n    resp.enable_chunked_encoding()\n\n    with pytest.raises(RuntimeError) as ctx:\n        await resp.prepare(req)\n    assert Matches(\"Using chunked encoding is forbidden for HTTP/1.0\") == str(ctx.value)\n\n\nasync def test_compression_no_accept() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = StreamResponse()\n    assert not resp.chunked\n\n    assert not resp.compression\n    resp.enable_compression()\n    assert resp.compression\n\n    msg = await resp.prepare(req)\n    assert not msg.enable_compression.called\n\n\nasync def test_force_compression_no_accept_backwards_compat() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = StreamResponse()\n    assert not resp.chunked\n\n    assert not resp.compression\n    with pytest.warns(DeprecationWarning):\n        resp.enable_compression(force=True)\n    assert resp.compression\n\n    msg = await resp.prepare(req)\n    assert msg.enable_compression.called\n    assert msg.filter is not None\n\n\nasync def test_force_compression_false_backwards_compat() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = StreamResponse()\n\n    assert not resp.compression\n    with pytest.warns(DeprecationWarning):\n        resp.enable_compression(force=False)\n    assert resp.compression\n\n    msg = await resp.prepare(req)\n    assert not msg.enable_compression.called\n\n\nasync def test_compression_default_coding() -> None:\n    req = make_request(\n        \"GET\", \"/\", headers=CIMultiDict({hdrs.ACCEPT_ENCODING: \"gzip, deflate\"})\n    )\n    resp = StreamResponse()\n    assert not resp.chunked\n\n    assert not resp.compression\n    resp.enable_compression()\n    assert resp.compression\n\n    msg = await resp.prepare(req)\n\n    msg.enable_compression.assert_called_with(\"deflate\", zlib.Z_DEFAULT_STRATEGY)\n    assert \"deflate\" == resp.headers.get(hdrs.CONTENT_ENCODING)\n    assert msg.filter is not None\n\n\nasync def test_force_compression_deflate() -> None:\n    req = make_request(\n        \"GET\", \"/\", headers=CIMultiDict({hdrs.ACCEPT_ENCODING: \"gzip, deflate\"})\n    )\n    resp = StreamResponse()\n\n    resp.enable_compression(ContentCoding.deflate)\n    assert resp.compression\n\n    msg = await resp.prepare(req)\n    msg.enable_compression.assert_called_with(\"deflate\", zlib.Z_DEFAULT_STRATEGY)\n    assert \"deflate\" == resp.headers.get(hdrs.CONTENT_ENCODING)\n\n\nasync def test_force_compression_no_accept_deflate() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = StreamResponse()\n\n    resp.enable_compression(ContentCoding.deflate)\n    assert resp.compression\n\n    msg = await resp.prepare(req)\n    msg.enable_compression.assert_called_with(\"deflate\", zlib.Z_DEFAULT_STRATEGY)\n    assert \"deflate\" == resp.headers.get(hdrs.CONTENT_ENCODING)\n\n\nasync def test_force_compression_gzip() -> None:\n    req = make_request(\n        \"GET\", \"/\", headers=CIMultiDict({hdrs.ACCEPT_ENCODING: \"gzip, deflate\"})\n    )\n    resp = StreamResponse()\n\n    resp.enable_compression(ContentCoding.gzip)\n    assert resp.compression\n\n    msg = await resp.prepare(req)\n    msg.enable_compression.assert_called_with(\"gzip\", zlib.Z_DEFAULT_STRATEGY)\n    assert \"gzip\" == resp.headers.get(hdrs.CONTENT_ENCODING)\n\n\nasync def test_force_compression_no_accept_gzip() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = StreamResponse()\n\n    resp.enable_compression(ContentCoding.gzip)\n    assert resp.compression\n\n    msg = await resp.prepare(req)\n    msg.enable_compression.assert_called_with(\"gzip\", zlib.Z_DEFAULT_STRATEGY)\n    assert \"gzip\" == resp.headers.get(hdrs.CONTENT_ENCODING)\n\n\nasync def test_change_content_threaded_compression_enabled() -> None:\n    req = make_request(\"GET\", \"/\")\n    body_thread_size = 1024\n    body = b\"answer\" * body_thread_size\n    resp = Response(body=body, zlib_executor_size=body_thread_size)\n    resp.enable_compression(ContentCoding.gzip)\n\n    await resp.prepare(req)\n    assert gzip.decompress(resp._compressed_body) == body\n\n\nasync def test_change_content_threaded_compression_enabled_explicit() -> None:\n    req = make_request(\"GET\", \"/\")\n    body_thread_size = 1024\n    body = b\"answer\" * body_thread_size\n    with ThreadPoolExecutor(1) as executor:\n        resp = Response(\n            body=body, zlib_executor_size=body_thread_size, zlib_executor=executor\n        )\n        resp.enable_compression(ContentCoding.gzip)\n\n        await resp.prepare(req)\n        assert gzip.decompress(resp._compressed_body) == body\n\n\nasync def test_change_content_length_if_compression_enabled() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = Response(body=b\"answer\")\n    resp.enable_compression(ContentCoding.gzip)\n\n    await resp.prepare(req)\n    assert resp.content_length is not None and resp.content_length != len(b\"answer\")\n\n\nasync def test_set_content_length_if_compression_enabled() -> None:\n    writer = mock.Mock()\n\n    async def write_headers(status_line, headers):\n        assert hdrs.CONTENT_LENGTH in headers\n        assert headers[hdrs.CONTENT_LENGTH] == \"26\"\n        assert hdrs.TRANSFER_ENCODING not in headers\n\n    writer.write_headers.side_effect = write_headers\n    req = make_request(\"GET\", \"/\", writer=writer)\n    resp = Response(body=b\"answer\")\n    resp.enable_compression(ContentCoding.gzip)\n\n    await resp.prepare(req)\n    assert resp.content_length == 26\n    del resp.headers[hdrs.CONTENT_LENGTH]\n    assert resp.content_length == 26\n\n\nasync def test_remove_content_length_if_compression_enabled_http11() -> None:\n    writer = mock.Mock()\n\n    async def write_headers(status_line, headers):\n        assert hdrs.CONTENT_LENGTH not in headers\n        assert headers.get(hdrs.TRANSFER_ENCODING, \"\") == \"chunked\"\n\n    writer.write_headers.side_effect = write_headers\n    req = make_request(\"GET\", \"/\", writer=writer)\n    resp = StreamResponse()\n    resp.content_length = 123\n    resp.enable_compression(ContentCoding.gzip)\n    await resp.prepare(req)\n    assert resp.content_length is None\n\n\nasync def test_remove_content_length_if_compression_enabled_http10() -> None:\n    writer = mock.Mock()\n\n    async def write_headers(status_line, headers):\n        assert hdrs.CONTENT_LENGTH not in headers\n        assert hdrs.TRANSFER_ENCODING not in headers\n\n    writer.write_headers.side_effect = write_headers\n    req = make_request(\"GET\", \"/\", version=HttpVersion10, writer=writer)\n    resp = StreamResponse()\n    resp.content_length = 123\n    resp.enable_compression(ContentCoding.gzip)\n    await resp.prepare(req)\n    assert resp.content_length is None\n\n\nasync def test_force_compression_identity() -> None:\n    writer = mock.Mock()\n\n    async def write_headers(status_line, headers):\n        assert hdrs.CONTENT_LENGTH in headers\n        assert hdrs.TRANSFER_ENCODING not in headers\n\n    writer.write_headers.side_effect = write_headers\n    req = make_request(\"GET\", \"/\", writer=writer)\n    resp = StreamResponse()\n    resp.content_length = 123\n    resp.enable_compression(ContentCoding.identity)\n    await resp.prepare(req)\n    assert resp.content_length == 123\n\n\nasync def test_force_compression_identity_response() -> None:\n    writer = mock.Mock()\n\n    async def write_headers(status_line, headers):\n        assert headers[hdrs.CONTENT_LENGTH] == \"6\"\n        assert hdrs.TRANSFER_ENCODING not in headers\n\n    writer.write_headers.side_effect = write_headers\n    req = make_request(\"GET\", \"/\", writer=writer)\n    resp = Response(body=b\"answer\")\n    resp.enable_compression(ContentCoding.identity)\n    await resp.prepare(req)\n    assert resp.content_length == 6\n\n\nasync def test_rm_content_length_if_compression_http11() -> None:\n    writer = mock.Mock()\n\n    async def write_headers(status_line, headers):\n        assert hdrs.CONTENT_LENGTH not in headers\n        assert headers.get(hdrs.TRANSFER_ENCODING, \"\") == \"chunked\"\n\n    writer.write_headers.side_effect = write_headers\n    req = make_request(\"GET\", \"/\", writer=writer)\n    payload = BytesPayload(b\"answer\", headers={\"X-Test-Header\": \"test\"})\n    resp = Response(body=payload)\n    resp.body = payload\n    resp.enable_compression(ContentCoding.gzip)\n    await resp.prepare(req)\n    assert resp.content_length is None\n\n\nasync def test_rm_content_length_if_compression_http10() -> None:\n    writer = mock.Mock()\n\n    async def write_headers(status_line, headers):\n        assert hdrs.CONTENT_LENGTH not in headers\n        assert hdrs.TRANSFER_ENCODING not in headers\n\n    writer.write_headers.side_effect = write_headers\n    req = make_request(\"GET\", \"/\", version=HttpVersion10, writer=writer)\n    resp = Response(body=BytesPayload(b\"answer\"))\n    resp.enable_compression(ContentCoding.gzip)\n    await resp.prepare(req)\n    assert resp.content_length is None\n\n\nasync def test_rm_content_length_if_204() -> None:\n    \"\"\"Ensure content-length is removed for 204 responses.\"\"\"\n    writer = mock.create_autospec(StreamWriter, spec_set=True, instance=True)\n\n    async def write_headers(status_line, headers):\n        assert hdrs.CONTENT_LENGTH not in headers\n\n    writer.write_headers.side_effect = write_headers\n    req = make_request(\"GET\", \"/\", writer=writer)\n    payload = BytesPayload(b\"answer\", headers={\"Content-Length\": \"6\"})\n    resp = Response(body=payload, status=204)\n    resp.body = payload\n    await resp.prepare(req)\n    assert resp.content_length is None\n\n\n@pytest.mark.parametrize(\"status\", (100, 101, 204, 304))\nasync def test_rm_transfer_encoding_rfc_9112_6_3_http_11(status: int) -> None:\n    \"\"\"Remove transfer encoding for RFC 9112 sec 6.3 with HTTP/1.1.\"\"\"\n    writer = mock.create_autospec(StreamWriter, spec_set=True, instance=True)\n    req = make_request(\"GET\", \"/\", version=HttpVersion11, writer=writer)\n    resp = Response(status=status, headers={hdrs.TRANSFER_ENCODING: \"chunked\"})\n    await resp.prepare(req)\n    assert resp.content_length == 0\n    assert not resp.chunked\n    assert hdrs.CONTENT_LENGTH not in resp.headers\n    assert hdrs.TRANSFER_ENCODING not in resp.headers\n\n\n@pytest.mark.parametrize(\"status\", (100, 101, 102, 204, 304))\nasync def test_rm_content_length_1xx_204_304_responses(status: int) -> None:\n    \"\"\"Remove content length for 1xx, 204, and 304 responses.\n\n    Content-Length is forbidden for 1xx and 204\n    https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.2\n\n    Content-Length is discouraged for 304.\n    https://datatracker.ietf.org/doc/html/rfc7232#section-4.1\n    \"\"\"\n    writer = mock.create_autospec(StreamWriter, spec_set=True, instance=True)\n    req = make_request(\"GET\", \"/\", version=HttpVersion11, writer=writer)\n    resp = Response(status=status, body=\"answer\")\n    await resp.prepare(req)\n    assert not resp.chunked\n    assert hdrs.CONTENT_LENGTH not in resp.headers\n    assert hdrs.TRANSFER_ENCODING not in resp.headers\n\n\nasync def test_head_response_keeps_content_length_of_original_body() -> None:\n    \"\"\"Verify HEAD response keeps the content length of the original body HTTP/1.1.\"\"\"\n    writer = mock.create_autospec(StreamWriter, spec_set=True, instance=True)\n    req = make_request(\"HEAD\", \"/\", version=HttpVersion11, writer=writer)\n    resp = Response(status=200, body=b\"answer\")\n    await resp.prepare(req)\n    assert resp.content_length == 6\n    assert not resp.chunked\n    assert resp.headers[hdrs.CONTENT_LENGTH] == \"6\"\n    assert hdrs.TRANSFER_ENCODING not in resp.headers\n\n\nasync def test_head_response_omits_content_length_when_body_unset() -> None:\n    \"\"\"Verify HEAD response omits content-length body when its unset.\"\"\"\n    writer = mock.create_autospec(StreamWriter, spec_set=True, instance=True)\n    req = make_request(\"HEAD\", \"/\", version=HttpVersion11, writer=writer)\n    resp = Response(status=200)\n    await resp.prepare(req)\n    assert resp.content_length == 0\n    assert not resp.chunked\n    assert hdrs.CONTENT_LENGTH not in resp.headers\n    assert hdrs.TRANSFER_ENCODING not in resp.headers\n\n\nasync def test_304_response_omits_content_length_when_body_unset() -> None:\n    \"\"\"Verify 304 response omits content-length body when its unset.\"\"\"\n    writer = mock.create_autospec(StreamWriter, spec_set=True, instance=True)\n    req = make_request(\"GET\", \"/\", version=HttpVersion11, writer=writer)\n    resp = Response(status=304)\n    await resp.prepare(req)\n    assert resp.content_length == 0\n    assert not resp.chunked\n    assert hdrs.CONTENT_LENGTH not in resp.headers\n    assert hdrs.TRANSFER_ENCODING not in resp.headers\n\n\nasync def test_content_length_on_chunked() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = Response(body=b\"answer\")\n    assert resp.content_length == 6\n    resp.enable_chunked_encoding()\n    assert resp.content_length is None\n    await resp.prepare(req)\n\n\nasync def test_write_non_byteish() -> None:\n    resp = StreamResponse()\n    await resp.prepare(make_request(\"GET\", \"/\"))\n\n    with pytest.raises(AssertionError):\n        await resp.write(123)\n\n\nasync def test_write_before_start() -> None:\n    resp = StreamResponse()\n\n    with pytest.raises(RuntimeError):\n        await resp.write(b\"data\")\n\n\nasync def test_cannot_write_after_eof() -> None:\n    resp = StreamResponse()\n    req = make_request(\"GET\", \"/\")\n    await resp.prepare(req)\n\n    await resp.write(b\"data\")\n    await resp.write_eof()\n    req.writer.write.reset_mock()\n\n    with pytest.raises(RuntimeError):\n        await resp.write(b\"next data\")\n    assert not req.writer.write.called\n\n\nasync def test___repr___after_eof() -> None:\n    resp = StreamResponse()\n    await resp.prepare(make_request(\"GET\", \"/\"))\n\n    await resp.write(b\"data\")\n    await resp.write_eof()\n    resp_repr = repr(resp)\n    assert resp_repr == \"<StreamResponse OK eof>\"\n\n\nasync def test_cannot_write_eof_before_headers() -> None:\n    resp = StreamResponse()\n\n    with pytest.raises(AssertionError):\n        await resp.write_eof()\n\n\nasync def test_cannot_write_eof_twice() -> None:\n    resp = StreamResponse()\n    writer = mock.Mock()\n    resp_impl = await resp.prepare(make_request(\"GET\", \"/\"))\n    resp_impl.write = make_mocked_coro(None)\n    resp_impl.write_eof = make_mocked_coro(None)\n\n    await resp.write(b\"data\")\n    assert resp_impl.write.called\n\n    await resp.write_eof()\n\n    resp_impl.write.reset_mock()\n    await resp.write_eof()\n    assert not writer.write.called\n\n\ndef test_force_close() -> None:\n    resp = StreamResponse()\n\n    assert resp.keep_alive is None\n    resp.force_close()\n    assert resp.keep_alive is False\n\n\nasync def test_response_output_length() -> None:\n    resp = StreamResponse()\n    await resp.prepare(make_request(\"GET\", \"/\"))\n    with pytest.warns(DeprecationWarning):\n        assert resp.output_length\n\n\ndef test_response_cookies() -> None:\n    resp = StreamResponse()\n\n    assert resp.cookies == {}\n    assert str(resp.cookies) == \"\"\n\n    resp.set_cookie(\"name\", \"value\")\n    assert str(resp.cookies) == \"Set-Cookie: name=value; Path=/\"\n    resp.set_cookie(\"name\", \"other_value\")\n    assert str(resp.cookies) == \"Set-Cookie: name=other_value; Path=/\"\n\n    resp.cookies[\"name\"] = \"another_other_value\"\n    resp.cookies[\"name\"][\"max-age\"] = 10\n    assert (\n        str(resp.cookies) == \"Set-Cookie: name=another_other_value; Max-Age=10; Path=/\"\n    )\n\n    resp.del_cookie(\"name\")\n    expected = (\n        'Set-Cookie: name=(\"\")?; '\n        \"expires=Thu, 01 Jan 1970 00:00:00 GMT; Max-Age=0; Path=/\"\n    )\n    assert Matches(expected) == str(resp.cookies)\n\n    resp.set_cookie(\"name\", \"value\", domain=\"local.host\")\n    expected = \"Set-Cookie: name=value; Domain=local.host; Path=/\"\n    assert str(resp.cookies) == expected\n\n\ndef test_response_cookie_path() -> None:\n    resp = StreamResponse()\n\n    assert resp.cookies == {}\n\n    resp.set_cookie(\"name\", \"value\", path=\"/some/path\")\n    assert str(resp.cookies) == \"Set-Cookie: name=value; Path=/some/path\"\n    resp.set_cookie(\"name\", \"value\", expires=\"123\")\n    assert str(resp.cookies) == \"Set-Cookie: name=value; expires=123; Path=/\"\n    resp.set_cookie(\n        \"name\",\n        \"value\",\n        domain=\"example.com\",\n        path=\"/home\",\n        expires=\"123\",\n        max_age=\"10\",\n        secure=True,\n        httponly=True,\n        version=\"2.0\",\n        samesite=\"lax\",\n    )\n    assert (\n        str(resp.cookies).lower() == \"set-cookie: name=value; \"\n        \"domain=example.com; \"\n        \"expires=123; \"\n        \"httponly; \"\n        \"max-age=10; \"\n        \"path=/home; \"\n        \"samesite=lax; \"\n        \"secure; \"\n        \"version=2.0\"\n    )\n\n\ndef test_response_cookie__issue_del_cookie() -> None:\n    resp = StreamResponse()\n\n    assert resp.cookies == {}\n    assert str(resp.cookies) == \"\"\n\n    resp.del_cookie(\"name\")\n    expected = (\n        'Set-Cookie: name=(\"\")?; '\n        \"expires=Thu, 01 Jan 1970 00:00:00 GMT; Max-Age=0; Path=/\"\n    )\n    assert Matches(expected) == str(resp.cookies)\n\n\ndef test_cookie_set_after_del() -> None:\n    resp = StreamResponse()\n\n    resp.del_cookie(\"name\")\n    resp.set_cookie(\"name\", \"val\")\n    # check for Max-Age dropped\n    expected = \"Set-Cookie: name=val; Path=/\"\n    assert str(resp.cookies) == expected\n\n\ndef test_set_status_with_reason() -> None:\n    resp = StreamResponse()\n\n    resp.set_status(200, \"Everything is fine!\")\n    assert 200 == resp.status\n    assert \"Everything is fine!\" == resp.reason\n\n\nasync def test_start_force_close() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = StreamResponse()\n    resp.force_close()\n    assert not resp.keep_alive\n\n    await resp.prepare(req)\n    assert not resp.keep_alive\n\n\nasync def test___repr__() -> None:\n    req = make_request(\"GET\", \"/path/to\")\n    resp = StreamResponse(reason=301)\n    await resp.prepare(req)\n    assert \"<StreamResponse 301 GET /path/to >\" == repr(resp)\n\n\ndef test___repr___not_prepared() -> None:\n    resp = StreamResponse(reason=301)\n    assert \"<StreamResponse 301 not prepared>\" == repr(resp)\n\n\nasync def test_keep_alive_http10_default() -> None:\n    req = make_request(\"GET\", \"/\", version=HttpVersion10)\n    resp = StreamResponse()\n    await resp.prepare(req)\n    assert not resp.keep_alive\n\n\nasync def test_keep_alive_http10_switched_on() -> None:\n    headers = CIMultiDict(Connection=\"keep-alive\")\n    req = make_request(\"GET\", \"/\", version=HttpVersion10, headers=headers)\n    req._message = req._message._replace(should_close=False)\n    resp = StreamResponse()\n    await resp.prepare(req)\n    assert resp.keep_alive\n\n\nasync def test_keep_alive_http09() -> None:\n    headers = CIMultiDict(Connection=\"keep-alive\")\n    req = make_request(\"GET\", \"/\", version=HttpVersion(0, 9), headers=headers)\n    resp = StreamResponse()\n    await resp.prepare(req)\n    assert not resp.keep_alive\n\n\nasync def test_prepare_twice() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = StreamResponse()\n\n    impl1 = await resp.prepare(req)\n    impl2 = await resp.prepare(req)\n    assert impl1 is impl2\n\n\nasync def test_prepare_calls_signal() -> None:\n    app = mock.Mock()\n    sig = make_mocked_coro()\n    on_response_prepare = aiosignal.Signal(app)\n    on_response_prepare.append(sig)\n    req = make_request(\"GET\", \"/\", app=app, on_response_prepare=on_response_prepare)\n    resp = StreamResponse()\n\n    await resp.prepare(req)\n\n    sig.assert_called_with(req, resp)\n\n\n# Response class\n\n\ndef test_response_ctor() -> None:\n    resp = Response()\n\n    assert 200 == resp.status\n    assert \"OK\" == resp.reason\n    assert resp.body is None\n    assert resp.content_length == 0\n    assert \"CONTENT-LENGTH\" not in resp.headers\n\n\nasync def test_ctor_with_headers_and_status() -> None:\n    resp = Response(body=b\"body\", status=201, headers={\"Age\": \"12\", \"DATE\": \"date\"})\n\n    assert 201 == resp.status\n    assert b\"body\" == resp.body\n    assert resp.headers[\"AGE\"] == \"12\"\n\n    req = make_mocked_request(\"GET\", \"/\")\n    await resp._start(req)\n    assert 4 == resp.content_length\n    assert resp.headers[\"CONTENT-LENGTH\"] == \"4\"\n\n\ndef test_ctor_content_type() -> None:\n    resp = Response(content_type=\"application/json\")\n\n    assert 200 == resp.status\n    assert \"OK\" == resp.reason\n    assert 0 == resp.content_length\n    assert CIMultiDict([(\"CONTENT-TYPE\", \"application/json\")]) == resp.headers\n\n\ndef test_ctor_text_body_combined() -> None:\n    with pytest.raises(ValueError):\n        Response(body=b\"123\", text=\"test text\")\n\n\nasync def test_ctor_text() -> None:\n    resp = Response(text=\"test text\")\n\n    assert 200 == resp.status\n    assert \"OK\" == resp.reason\n    assert 9 == resp.content_length\n    assert CIMultiDict([(\"CONTENT-TYPE\", \"text/plain; charset=utf-8\")]) == resp.headers\n\n    assert resp.body == b\"test text\"\n    assert resp.text == \"test text\"\n\n    resp.headers[\"DATE\"] = \"date\"\n    req = make_mocked_request(\"GET\", \"/\", version=HttpVersion11)\n    await resp._start(req)\n    assert resp.headers[\"CONTENT-LENGTH\"] == \"9\"\n\n\ndef test_ctor_charset() -> None:\n    resp = Response(text=\"текст\", charset=\"koi8-r\")\n\n    assert \"текст\".encode(\"koi8-r\") == resp.body\n    assert \"koi8-r\" == resp.charset\n\n\ndef test_ctor_charset_default_utf8() -> None:\n    resp = Response(text=\"test test\", charset=None)\n\n    assert \"utf-8\" == resp.charset\n\n\ndef test_ctor_charset_in_content_type() -> None:\n    with pytest.raises(ValueError):\n        Response(text=\"test test\", content_type=\"text/plain; charset=utf-8\")\n\n\ndef test_ctor_charset_without_text() -> None:\n    resp = Response(content_type=\"text/plain\", charset=\"koi8-r\")\n\n    assert \"koi8-r\" == resp.charset\n\n\ndef test_ctor_content_type_with_extra() -> None:\n    resp = Response(text=\"test test\", content_type=\"text/plain; version=0.0.4\")\n\n    assert resp.content_type == \"text/plain\"\n    assert resp.headers[\"content-type\"] == \"text/plain; version=0.0.4; charset=utf-8\"\n\n\ndef test_ctor_both_content_type_param_and_header_with_text() -> None:\n    with pytest.raises(ValueError):\n        Response(\n            headers={\"Content-Type\": \"application/json\"},\n            content_type=\"text/html\",\n            text=\"text\",\n        )\n\n\ndef test_ctor_both_charset_param_and_header_with_text() -> None:\n    with pytest.raises(ValueError):\n        Response(\n            headers={\"Content-Type\": \"application/json\"}, charset=\"koi8-r\", text=\"text\"\n        )\n\n\ndef test_ctor_both_content_type_param_and_header() -> None:\n    with pytest.raises(ValueError):\n        Response(headers={\"Content-Type\": \"application/json\"}, content_type=\"text/html\")\n\n\ndef test_ctor_both_charset_param_and_header() -> None:\n    with pytest.raises(ValueError):\n        Response(headers={\"Content-Type\": \"application/json\"}, charset=\"koi8-r\")\n\n\nasync def test_assign_nonbyteish_body() -> None:\n    resp = Response(body=b\"data\")\n\n    with pytest.raises(ValueError):\n        resp.body = 123\n    assert b\"data\" == resp.body\n    assert 4 == resp.content_length\n\n    resp.headers[\"DATE\"] = \"date\"\n    req = make_mocked_request(\"GET\", \"/\", version=HttpVersion11)\n    await resp._start(req)\n    assert resp.headers[\"CONTENT-LENGTH\"] == \"4\"\n    assert 4 == resp.content_length\n\n\ndef test_assign_nonstr_text() -> None:\n    resp = Response(text=\"test\")\n\n    with pytest.raises(AssertionError):\n        resp.text = b\"123\"\n    assert b\"test\" == resp.body\n    assert 4 == resp.content_length\n\n\nmpwriter = MultipartWriter(boundary=\"x\")\nmpwriter.append_payload(StringPayload(\"test\"))\n\n\nasync def async_iter() -> AsyncIterator[str]:\n    yield \"foo\"  # pragma: no cover\n\n\nclass CustomIO(io.IOBase):\n    def __init__(self):\n        self._lines = [b\"\", b\"\", b\"test\"]\n\n    def read(self, size: int = -1) -> bytes:\n        return self._lines.pop()\n\n\n@pytest.mark.parametrize(\n    \"payload,expected\",\n    (\n        (\"test\", \"test\"),\n        (CustomIO(), \"test\"),\n        (io.StringIO(\"test\"), \"test\"),\n        (io.TextIOWrapper(io.BytesIO(b\"test\")), \"test\"),\n        (io.BytesIO(b\"test\"), \"test\"),\n        (io.BufferedReader(io.BytesIO(b\"test\")), \"test\"),\n        (async_iter(), None),\n        (BodyPartReader(\"x\", CIMultiDictProxy(CIMultiDict()), mock.Mock()), None),\n        (\n            mpwriter,\n            \"--x\\nContent-Type: text/plain; charset=utf-8\\r\\nContent-Length: 4\\r\\n\\r\\ntest\",\n        ),\n    ),\n)\ndef test_payload_body_get_text(payload, expected: Optional[str]) -> None:\n    resp = Response(body=payload)\n    if expected is None:\n        with pytest.raises(TypeError):\n            resp.text\n    else:\n        assert resp.text == expected\n\n\ndef test_response_set_content_length() -> None:\n    resp = Response()\n    with pytest.raises(RuntimeError):\n        resp.content_length = 1\n\n\nasync def test_send_headers_for_empty_body(buf, writer) -> None:\n    req = make_request(\"GET\", \"/\", writer=writer)\n    resp = Response()\n\n    await resp.prepare(req)\n    await resp.write_eof()\n    txt = buf.decode(\"utf8\")\n    assert (\n        Matches(\n            \"HTTP/1.1 200 OK\\r\\n\"\n            \"Content-Length: 0\\r\\n\"\n            \"Date: .+\\r\\n\"\n            \"Server: .+\\r\\n\\r\\n\"\n        )\n        == txt\n    )\n\n\nasync def test_render_with_body(buf, writer) -> None:\n    req = make_request(\"GET\", \"/\", writer=writer)\n    resp = Response(body=b\"data\")\n\n    await resp.prepare(req)\n    await resp.write_eof()\n\n    txt = buf.decode(\"utf8\")\n    assert (\n        Matches(\n            \"HTTP/1.1 200 OK\\r\\n\"\n            \"Content-Length: 4\\r\\n\"\n            \"Content-Type: application/octet-stream\\r\\n\"\n            \"Date: .+\\r\\n\"\n            \"Server: .+\\r\\n\\r\\n\"\n            \"data\"\n        )\n        == txt\n    )\n\n\nasync def test_send_set_cookie_header(buf, writer) -> None:\n    resp = Response()\n    resp.cookies[\"name\"] = \"value\"\n    req = make_request(\"GET\", \"/\", writer=writer)\n\n    await resp.prepare(req)\n    await resp.write_eof()\n\n    txt = buf.decode(\"utf8\")\n    assert (\n        Matches(\n            \"HTTP/1.1 200 OK\\r\\n\"\n            \"Content-Length: 0\\r\\n\"\n            \"Set-Cookie: name=value\\r\\n\"\n            \"Date: .+\\r\\n\"\n            \"Server: .+\\r\\n\\r\\n\"\n        )\n        == txt\n    )\n\n\nasync def test_consecutive_write_eof() -> None:\n    writer = mock.Mock()\n    writer.write_eof = make_mocked_coro()\n    writer.write_headers = make_mocked_coro()\n    req = make_request(\"GET\", \"/\", writer=writer)\n    data = b\"data\"\n    resp = Response(body=data)\n\n    await resp.prepare(req)\n    await resp.write_eof()\n    await resp.write_eof()\n    writer.write_eof.assert_called_once_with(data)\n\n\ndef test_set_text_with_content_type() -> None:\n    resp = Response()\n    resp.content_type = \"text/html\"\n    resp.text = \"text\"\n\n    assert \"text\" == resp.text\n    assert b\"text\" == resp.body\n    assert \"text/html\" == resp.content_type\n\n\ndef test_set_text_with_charset() -> None:\n    resp = Response()\n    resp.content_type = \"text/plain\"\n    resp.charset = \"KOI8-R\"\n    resp.text = \"текст\"\n\n    assert \"текст\" == resp.text\n    assert \"текст\".encode(\"koi8-r\") == resp.body\n    assert \"koi8-r\" == resp.charset\n\n\ndef test_default_content_type_in_stream_response() -> None:\n    resp = StreamResponse()\n    assert resp.content_type == \"application/octet-stream\"\n\n\ndef test_default_content_type_in_response() -> None:\n    resp = Response()\n    assert resp.content_type == \"application/octet-stream\"\n\n\ndef test_content_type_with_set_text() -> None:\n    resp = Response(text=\"text\")\n    assert resp.content_type == \"text/plain\"\n\n\ndef test_content_type_with_set_body() -> None:\n    resp = Response(body=b\"body\")\n    assert resp.content_type == \"application/octet-stream\"\n\n\ndef test_prepared_when_not_started() -> None:\n    resp = StreamResponse()\n    assert not resp.prepared\n\n\nasync def test_prepared_when_started() -> None:\n    resp = StreamResponse()\n    await resp.prepare(make_request(\"GET\", \"/\"))\n    assert resp.prepared\n\n\nasync def test_prepared_after_eof() -> None:\n    resp = StreamResponse()\n    await resp.prepare(make_request(\"GET\", \"/\"))\n    await resp.write(b\"data\")\n    await resp.write_eof()\n    assert resp.prepared\n\n\nasync def test_drain_before_start() -> None:\n    resp = StreamResponse()\n    with pytest.raises(AssertionError):\n        await resp.drain()\n\n\nasync def test_changing_status_after_prepare_raises() -> None:\n    resp = StreamResponse()\n    await resp.prepare(make_request(\"GET\", \"/\"))\n    with pytest.raises(AssertionError):\n        resp.set_status(400)\n\n\ndef test_nonstr_text_in_ctor() -> None:\n    with pytest.raises(TypeError):\n        Response(text=b\"data\")\n\n\ndef test_text_in_ctor_with_content_type() -> None:\n    resp = Response(text=\"data\", content_type=\"text/html\")\n    assert \"data\" == resp.text\n    assert \"text/html\" == resp.content_type\n\n\ndef test_text_in_ctor_with_content_type_header() -> None:\n    resp = Response(text=\"текст\", headers={\"Content-Type\": \"text/html; charset=koi8-r\"})\n    assert \"текст\".encode(\"koi8-r\") == resp.body\n    assert \"text/html\" == resp.content_type\n    assert \"koi8-r\" == resp.charset\n\n\ndef test_text_in_ctor_with_content_type_header_multidict() -> None:\n    headers = CIMultiDict({\"Content-Type\": \"text/html; charset=koi8-r\"})\n    resp = Response(text=\"текст\", headers=headers)\n    assert \"текст\".encode(\"koi8-r\") == resp.body\n    assert \"text/html\" == resp.content_type\n    assert \"koi8-r\" == resp.charset\n\n\ndef test_body_in_ctor_with_content_type_header_multidict() -> None:\n    headers = CIMultiDict({\"Content-Type\": \"text/html; charset=koi8-r\"})\n    resp = Response(body=\"текст\".encode(\"koi8-r\"), headers=headers)\n    assert \"текст\".encode(\"koi8-r\") == resp.body\n    assert \"text/html\" == resp.content_type\n    assert \"koi8-r\" == resp.charset\n\n\ndef test_text_with_empty_payload() -> None:\n    resp = Response(status=200)\n    assert resp.body is None\n    assert resp.text is None\n\n\ndef test_response_with_content_length_header_without_body() -> None:\n    resp = Response(headers={\"Content-Length\": 123})\n    assert resp.content_length == 123\n\n\ndef test_response_with_immutable_headers() -> None:\n    resp = Response(\n        text=\"text\", headers=CIMultiDictProxy(CIMultiDict({\"Header\": \"Value\"}))\n    )\n    assert resp.headers == {\n        \"Header\": \"Value\",\n        \"Content-Type\": \"text/plain; charset=utf-8\",\n    }\n\n\nasync def test_response_prepared_after_header_preparation() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = StreamResponse()\n    await resp.prepare(req)\n\n    assert type(resp.headers[\"Server\"]) is str\n\n    async def _strip_server(req, res):\n        assert \"Server\" in res.headers\n\n        if \"Server\" in res.headers:\n            del res.headers[\"Server\"]\n\n    app = mock.Mock()\n    sig = aiosignal.Signal(app)\n    sig.append(_strip_server)\n\n    req = make_request(\"GET\", \"/\", on_response_prepare=sig, app=app)\n    resp = StreamResponse()\n    await resp.prepare(req)\n\n    assert \"Server\" not in resp.headers\n\n\nclass TestJSONResponse:\n    def test_content_type_is_application_json_by_default(self) -> None:\n        resp = json_response(\"\")\n        assert \"application/json\" == resp.content_type\n\n    def test_passing_text_only(self) -> None:\n        resp = json_response(text=json.dumps(\"jaysawn\"))\n        assert resp.text == json.dumps(\"jaysawn\")\n\n    def test_data_and_text_raises_value_error(self) -> None:\n        with pytest.raises(ValueError) as excinfo:\n            json_response(data=\"foo\", text=\"bar\")\n        expected_message = \"only one of data, text, or body should be specified\"\n        assert expected_message == excinfo.value.args[0]\n\n    def test_data_and_body_raises_value_error(self) -> None:\n        with pytest.raises(ValueError) as excinfo:\n            json_response(data=\"foo\", body=b\"bar\")\n        expected_message = \"only one of data, text, or body should be specified\"\n        assert expected_message == excinfo.value.args[0]\n\n    def test_text_is_json_encoded(self) -> None:\n        resp = json_response({\"foo\": 42})\n        assert json.dumps({\"foo\": 42}) == resp.text\n\n    def test_content_type_is_overrideable(self) -> None:\n        resp = json_response({\"foo\": 42}, content_type=\"application/vnd.json+api\")\n        assert \"application/vnd.json+api\" == resp.content_type\n",
            "new_file_content": "import collections.abc\nimport datetime\nimport gzip\nimport io\nimport json\nimport zlib\nfrom concurrent.futures import ThreadPoolExecutor\nfrom typing import AsyncIterator, Optional\nfrom unittest import mock\n\nimport aiosignal\nimport pytest\nfrom multidict import CIMultiDict, CIMultiDictProxy\nfrom re_assert import Matches\n\nfrom aiohttp import HttpVersion, HttpVersion10, HttpVersion11, hdrs\nfrom aiohttp.helpers import ETag\nfrom aiohttp.http_writer import StreamWriter, _serialize_headers\nfrom aiohttp.multipart import BodyPartReader, MultipartWriter\nfrom aiohttp.payload import BytesPayload, StringPayload\nfrom aiohttp.test_utils import make_mocked_coro, make_mocked_request\nfrom aiohttp.web import ContentCoding, Response, StreamResponse, json_response\n\n\ndef make_request(\n    method,\n    path,\n    headers=CIMultiDict(),\n    version=HttpVersion11,\n    on_response_prepare=None,\n    **kwargs,\n):\n    app = kwargs.pop(\"app\", None) or mock.Mock()\n    app._debug = False\n    if on_response_prepare is None:\n        on_response_prepare = aiosignal.Signal(app)\n    app.on_response_prepare = on_response_prepare\n    app.on_response_prepare.freeze()\n    protocol = kwargs.pop(\"protocol\", None) or mock.Mock()\n    return make_mocked_request(\n        method, path, headers, version=version, protocol=protocol, app=app, **kwargs\n    )\n\n\n@pytest.fixture\ndef buf():\n    return bytearray()\n\n\n@pytest.fixture\ndef writer(buf):\n    writer = mock.Mock()\n\n    def acquire(cb):\n        cb(writer.transport)\n\n    def buffer_data(chunk):\n        buf.extend(chunk)\n\n    def write(chunk):\n        buf.extend(chunk)\n\n    async def write_headers(status_line, headers):\n        headers = _serialize_headers(status_line, headers)\n        buf.extend(headers)\n\n    async def write_eof(chunk=b\"\"):\n        buf.extend(chunk)\n\n    writer.acquire.side_effect = acquire\n    writer.transport.write.side_effect = write\n    writer.write.side_effect = write\n    writer.write_eof.side_effect = write_eof\n    writer.write_headers.side_effect = write_headers\n    writer.buffer_data.side_effect = buffer_data\n    writer.drain.return_value = ()\n\n    return writer\n\n\ndef test_stream_response_ctor() -> None:\n    resp = StreamResponse()\n    assert 200 == resp.status\n    assert resp.keep_alive is None\n\n    assert resp.task is None\n\n    req = mock.Mock()\n    resp._req = req\n    assert resp.task is req.task\n\n\ndef test_stream_response_hashable() -> None:\n    # should not raise exception\n    hash(StreamResponse())\n\n\ndef test_stream_response_eq() -> None:\n    resp1 = StreamResponse()\n    resp2 = StreamResponse()\n\n    assert resp1 == resp1\n    assert not resp1 == resp2\n\n\ndef test_stream_response_is_mutable_mapping() -> None:\n    resp = StreamResponse()\n    assert isinstance(resp, collections.abc.MutableMapping)\n    resp[\"key\"] = \"value\"\n    assert \"value\" == resp[\"key\"]\n\n\ndef test_stream_response_delitem() -> None:\n    resp = StreamResponse()\n    resp[\"key\"] = \"value\"\n    del resp[\"key\"]\n    assert \"key\" not in resp\n\n\ndef test_stream_response_len() -> None:\n    resp = StreamResponse()\n    assert len(resp) == 0\n    resp[\"key\"] = \"value\"\n    assert len(resp) == 1\n\n\ndef test_request_iter() -> None:\n    resp = StreamResponse()\n    resp[\"key\"] = \"value\"\n    resp[\"key2\"] = \"value2\"\n    assert set(resp) == {\"key\", \"key2\"}\n\n\ndef test_content_length() -> None:\n    resp = StreamResponse()\n    assert resp.content_length is None\n\n\ndef test_content_length_setter() -> None:\n    resp = StreamResponse()\n\n    resp.content_length = 234\n    assert 234 == resp.content_length\n\n\ndef test_content_length_setter_with_enable_chunked_encoding() -> None:\n    resp = StreamResponse()\n\n    resp.enable_chunked_encoding()\n    with pytest.raises(RuntimeError):\n        resp.content_length = 234\n\n\ndef test_drop_content_length_header_on_setting_len_to_None() -> None:\n    resp = StreamResponse()\n\n    resp.content_length = 1\n    assert \"1\" == resp.headers[\"Content-Length\"]\n    resp.content_length = None\n    assert \"Content-Length\" not in resp.headers\n\n\ndef test_set_content_length_to_None_on_non_set() -> None:\n    resp = StreamResponse()\n\n    resp.content_length = None\n    assert \"Content-Length\" not in resp.headers\n    resp.content_length = None\n    assert \"Content-Length\" not in resp.headers\n\n\ndef test_setting_content_type() -> None:\n    resp = StreamResponse()\n\n    resp.content_type = \"text/html\"\n    assert \"text/html\" == resp.headers[\"content-type\"]\n\n\ndef test_setting_charset() -> None:\n    resp = StreamResponse()\n\n    resp.content_type = \"text/html\"\n    resp.charset = \"koi8-r\"\n    assert \"text/html; charset=koi8-r\" == resp.headers[\"content-type\"]\n\n\ndef test_default_charset() -> None:\n    resp = StreamResponse()\n\n    assert resp.charset is None\n\n\ndef test_reset_charset() -> None:\n    resp = StreamResponse()\n\n    resp.content_type = \"text/html\"\n    resp.charset = None\n    assert resp.charset is None\n\n\ndef test_reset_charset_after_setting() -> None:\n    resp = StreamResponse()\n\n    resp.content_type = \"text/html\"\n    resp.charset = \"koi8-r\"\n    resp.charset = None\n    assert resp.charset is None\n\n\ndef test_charset_without_content_type() -> None:\n    resp = StreamResponse()\n\n    with pytest.raises(RuntimeError):\n        resp.charset = \"koi8-r\"\n\n\ndef test_last_modified_initial() -> None:\n    resp = StreamResponse()\n    assert resp.last_modified is None\n\n\ndef test_last_modified_string() -> None:\n    resp = StreamResponse()\n\n    dt = datetime.datetime(1990, 1, 2, 3, 4, 5, 0, datetime.timezone.utc)\n    resp.last_modified = \"Mon, 2 Jan 1990 03:04:05 GMT\"\n    assert resp.last_modified == dt\n\n\ndef test_last_modified_timestamp() -> None:\n    resp = StreamResponse()\n\n    dt = datetime.datetime(1970, 1, 1, 0, 0, 0, 0, datetime.timezone.utc)\n\n    resp.last_modified = 0\n    assert resp.last_modified == dt\n\n    resp.last_modified = 0.0\n    assert resp.last_modified == dt\n\n\ndef test_last_modified_datetime() -> None:\n    resp = StreamResponse()\n\n    dt = datetime.datetime(2001, 2, 3, 4, 5, 6, 0, datetime.timezone.utc)\n    resp.last_modified = dt\n    assert resp.last_modified == dt\n\n\ndef test_last_modified_reset() -> None:\n    resp = StreamResponse()\n\n    resp.last_modified = 0\n    resp.last_modified = None\n    assert resp.last_modified is None\n\n\n@pytest.mark.parametrize(\n    [\"header_val\", \"expected\"],\n    [\n        pytest.param(\"xxyyzz\", None),\n        pytest.param(\"Tue, 08 Oct 4446413 00:56:40 GMT\", None),\n        pytest.param(\"Tue, 08 Oct 2000 00:56:80 GMT\", None),\n    ],\n)\ndef test_last_modified_string_invalid(header_val, expected) -> None:\n    resp = StreamResponse(headers={\"Last-Modified\": header_val})\n    assert resp.last_modified == expected\n\n\ndef test_etag_initial() -> None:\n    resp = StreamResponse()\n    assert resp.etag is None\n\n\ndef test_etag_string() -> None:\n    resp = StreamResponse()\n    value = \"0123-kotik\"\n    resp.etag = value\n    assert resp.etag == ETag(value=value)\n    assert resp.headers[hdrs.ETAG] == f'\"{value}\"'\n\n\n@pytest.mark.parametrize(\n    [\"etag\", \"expected_header\"],\n    (\n        (ETag(value=\"0123-weak-kotik\", is_weak=True), 'W/\"0123-weak-kotik\"'),\n        (ETag(value=\"0123-strong-kotik\", is_weak=False), '\"0123-strong-kotik\"'),\n    ),\n)\ndef test_etag_class(etag, expected_header) -> None:\n    resp = StreamResponse()\n    resp.etag = etag\n    assert resp.etag == etag\n    assert resp.headers[hdrs.ETAG] == expected_header\n\n\ndef test_etag_any() -> None:\n    resp = StreamResponse()\n    resp.etag = \"*\"\n    assert resp.etag == ETag(value=\"*\")\n    assert resp.headers[hdrs.ETAG] == \"*\"\n\n\n@pytest.mark.parametrize(\n    \"invalid_value\",\n    (\n        '\"invalid\"',\n        \"повинен бути ascii\",\n        ETag(value='\"invalid\"', is_weak=True),\n        ETag(value=\"bad ©®\"),\n    ),\n)\ndef test_etag_invalid_value_set(invalid_value) -> None:\n    resp = StreamResponse()\n    with pytest.raises(ValueError, match=\"is not a valid etag\"):\n        resp.etag = invalid_value\n\n\n@pytest.mark.parametrize(\n    \"header\",\n    (\n        \"forgotten quotes\",\n        '\"∀ x ∉ ascii\"',\n    ),\n)\ndef test_etag_invalid_value_get(header) -> None:\n    resp = StreamResponse()\n    resp.headers[\"ETag\"] = header\n    assert resp.etag is None\n\n\n@pytest.mark.parametrize(\"invalid\", (123, ETag(value=123, is_weak=True)))\ndef test_etag_invalid_value_class(invalid) -> None:\n    resp = StreamResponse()\n    with pytest.raises(ValueError, match=\"Unsupported etag type\"):\n        resp.etag = invalid\n\n\ndef test_etag_reset() -> None:\n    resp = StreamResponse()\n    resp.etag = \"*\"\n    resp.etag = None\n    assert resp.etag is None\n\n\nasync def test_start() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = StreamResponse()\n    assert resp.keep_alive is None\n\n    msg = await resp.prepare(req)\n\n    assert msg.write_headers.called\n    msg2 = await resp.prepare(req)\n    assert msg is msg2\n\n    assert resp.keep_alive\n\n    req2 = make_request(\"GET\", \"/\")\n    # with pytest.raises(RuntimeError):\n    msg3 = await resp.prepare(req2)\n    assert msg is msg3\n\n\nasync def test_chunked_encoding() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = StreamResponse()\n    assert not resp.chunked\n\n    resp.enable_chunked_encoding()\n    assert resp.chunked\n\n    msg = await resp.prepare(req)\n    assert msg.chunked\n\n\ndef test_enable_chunked_encoding_with_content_length() -> None:\n    resp = StreamResponse()\n\n    resp.content_length = 234\n    with pytest.raises(RuntimeError):\n        resp.enable_chunked_encoding()\n\n\nasync def test_chunk_size() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = StreamResponse()\n    assert not resp.chunked\n\n    with pytest.warns(DeprecationWarning):\n        resp.enable_chunked_encoding(chunk_size=8192)\n    assert resp.chunked\n\n    msg = await resp.prepare(req)\n    assert msg.chunked\n    assert msg.enable_chunking.called\n    assert msg.filter is not None\n\n\nasync def test_chunked_encoding_forbidden_for_http_10() -> None:\n    req = make_request(\"GET\", \"/\", version=HttpVersion10)\n    resp = StreamResponse()\n    resp.enable_chunked_encoding()\n\n    with pytest.raises(RuntimeError) as ctx:\n        await resp.prepare(req)\n    assert Matches(\"Using chunked encoding is forbidden for HTTP/1.0\") == str(ctx.value)\n\n\nasync def test_compression_no_accept() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = StreamResponse()\n    assert not resp.chunked\n\n    assert not resp.compression\n    resp.enable_compression()\n    assert resp.compression\n\n    msg = await resp.prepare(req)\n    assert not msg.enable_compression.called\n\n\nasync def test_force_compression_no_accept_backwards_compat() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = StreamResponse()\n    assert not resp.chunked\n\n    assert not resp.compression\n    with pytest.warns(DeprecationWarning):\n        resp.enable_compression(force=True)\n    assert resp.compression\n\n    msg = await resp.prepare(req)\n    assert msg.enable_compression.called\n    assert msg.filter is not None\n\n\nasync def test_force_compression_false_backwards_compat() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = StreamResponse()\n\n    assert not resp.compression\n    with pytest.warns(DeprecationWarning):\n        resp.enable_compression(force=False)\n    assert resp.compression\n\n    msg = await resp.prepare(req)\n    assert not msg.enable_compression.called\n\n\nasync def test_compression_default_coding() -> None:\n    req = make_request(\n        \"GET\", \"/\", headers=CIMultiDict({hdrs.ACCEPT_ENCODING: \"gzip, deflate\"})\n    )\n    resp = StreamResponse()\n    assert not resp.chunked\n\n    assert not resp.compression\n    resp.enable_compression()\n    assert resp.compression\n\n    msg = await resp.prepare(req)\n\n    msg.enable_compression.assert_called_with(\"deflate\", zlib.Z_DEFAULT_STRATEGY)\n    assert \"deflate\" == resp.headers.get(hdrs.CONTENT_ENCODING)\n    assert msg.filter is not None\n\n\nasync def test_force_compression_deflate() -> None:\n    req = make_request(\n        \"GET\", \"/\", headers=CIMultiDict({hdrs.ACCEPT_ENCODING: \"gzip, deflate\"})\n    )\n    resp = StreamResponse()\n\n    resp.enable_compression(ContentCoding.deflate)\n    assert resp.compression\n\n    msg = await resp.prepare(req)\n    msg.enable_compression.assert_called_with(\"deflate\", zlib.Z_DEFAULT_STRATEGY)\n    assert \"deflate\" == resp.headers.get(hdrs.CONTENT_ENCODING)\n\n\nasync def test_force_compression_no_accept_deflate() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = StreamResponse()\n\n    resp.enable_compression(ContentCoding.deflate)\n    assert resp.compression\n\n    msg = await resp.prepare(req)\n    msg.enable_compression.assert_called_with(\"deflate\", zlib.Z_DEFAULT_STRATEGY)\n    assert \"deflate\" == resp.headers.get(hdrs.CONTENT_ENCODING)\n\n\nasync def test_force_compression_gzip() -> None:\n    req = make_request(\n        \"GET\", \"/\", headers=CIMultiDict({hdrs.ACCEPT_ENCODING: \"gzip, deflate\"})\n    )\n    resp = StreamResponse()\n\n    resp.enable_compression(ContentCoding.gzip)\n    assert resp.compression\n\n    msg = await resp.prepare(req)\n    msg.enable_compression.assert_called_with(\"gzip\", zlib.Z_DEFAULT_STRATEGY)\n    assert \"gzip\" == resp.headers.get(hdrs.CONTENT_ENCODING)\n\n\nasync def test_force_compression_no_accept_gzip() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = StreamResponse()\n\n    resp.enable_compression(ContentCoding.gzip)\n    assert resp.compression\n\n    msg = await resp.prepare(req)\n    msg.enable_compression.assert_called_with(\"gzip\", zlib.Z_DEFAULT_STRATEGY)\n    assert \"gzip\" == resp.headers.get(hdrs.CONTENT_ENCODING)\n\n\nasync def test_change_content_threaded_compression_enabled() -> None:\n    req = make_request(\"GET\", \"/\")\n    body_thread_size = 1024\n    body = b\"answer\" * body_thread_size\n    resp = Response(body=body, zlib_executor_size=body_thread_size)\n    resp.enable_compression(ContentCoding.gzip)\n\n    await resp.prepare(req)\n    assert gzip.decompress(resp._compressed_body) == body\n\n\nasync def test_change_content_threaded_compression_enabled_explicit() -> None:\n    req = make_request(\"GET\", \"/\")\n    body_thread_size = 1024\n    body = b\"answer\" * body_thread_size\n    with ThreadPoolExecutor(1) as executor:\n        resp = Response(\n            body=body, zlib_executor_size=body_thread_size, zlib_executor=executor\n        )\n        resp.enable_compression(ContentCoding.gzip)\n\n        await resp.prepare(req)\n        assert gzip.decompress(resp._compressed_body) == body\n\n\nasync def test_change_content_length_if_compression_enabled() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = Response(body=b\"answer\")\n    resp.enable_compression(ContentCoding.gzip)\n\n    await resp.prepare(req)\n    assert resp.content_length is not None and resp.content_length != len(b\"answer\")\n\n\nasync def test_set_content_length_if_compression_enabled() -> None:\n    writer = mock.Mock()\n\n    async def write_headers(status_line, headers):\n        assert hdrs.CONTENT_LENGTH in headers\n        assert headers[hdrs.CONTENT_LENGTH] == \"26\"\n        assert hdrs.TRANSFER_ENCODING not in headers\n\n    writer.write_headers.side_effect = write_headers\n    req = make_request(\"GET\", \"/\", writer=writer)\n    resp = Response(body=b\"answer\")\n    resp.enable_compression(ContentCoding.gzip)\n\n    await resp.prepare(req)\n    assert resp.content_length == 26\n    del resp.headers[hdrs.CONTENT_LENGTH]\n    assert resp.content_length == 26\n\n\nasync def test_remove_content_length_if_compression_enabled_http11() -> None:\n    writer = mock.Mock()\n\n    async def write_headers(status_line, headers):\n        assert hdrs.CONTENT_LENGTH not in headers\n        assert headers.get(hdrs.TRANSFER_ENCODING, \"\") == \"chunked\"\n\n    writer.write_headers.side_effect = write_headers\n    req = make_request(\"GET\", \"/\", writer=writer)\n    resp = StreamResponse()\n    resp.content_length = 123\n    resp.enable_compression(ContentCoding.gzip)\n    await resp.prepare(req)\n    assert resp.content_length is None\n\n\nasync def test_remove_content_length_if_compression_enabled_http10() -> None:\n    writer = mock.Mock()\n\n    async def write_headers(status_line, headers):\n        assert hdrs.CONTENT_LENGTH not in headers\n        assert hdrs.TRANSFER_ENCODING not in headers\n\n    writer.write_headers.side_effect = write_headers\n    req = make_request(\"GET\", \"/\", version=HttpVersion10, writer=writer)\n    resp = StreamResponse()\n    resp.content_length = 123\n    resp.enable_compression(ContentCoding.gzip)\n    await resp.prepare(req)\n    assert resp.content_length is None\n\n\nasync def test_force_compression_identity() -> None:\n    writer = mock.Mock()\n\n    async def write_headers(status_line, headers):\n        assert hdrs.CONTENT_LENGTH in headers\n        assert hdrs.TRANSFER_ENCODING not in headers\n\n    writer.write_headers.side_effect = write_headers\n    req = make_request(\"GET\", \"/\", writer=writer)\n    resp = StreamResponse()\n    resp.content_length = 123\n    resp.enable_compression(ContentCoding.identity)\n    await resp.prepare(req)\n    assert resp.content_length == 123\n\n\nasync def test_force_compression_identity_response() -> None:\n    writer = mock.Mock()\n\n    async def write_headers(status_line, headers):\n        assert headers[hdrs.CONTENT_LENGTH] == \"6\"\n        assert hdrs.TRANSFER_ENCODING not in headers\n\n    writer.write_headers.side_effect = write_headers\n    req = make_request(\"GET\", \"/\", writer=writer)\n    resp = Response(body=b\"answer\")\n    resp.enable_compression(ContentCoding.identity)\n    await resp.prepare(req)\n    assert resp.content_length == 6\n\n\nasync def test_rm_content_length_if_compression_http11() -> None:\n    writer = mock.Mock()\n\n    async def write_headers(status_line, headers):\n        assert hdrs.CONTENT_LENGTH not in headers\n        assert headers.get(hdrs.TRANSFER_ENCODING, \"\") == \"chunked\"\n\n    writer.write_headers.side_effect = write_headers\n    req = make_request(\"GET\", \"/\", writer=writer)\n    payload = BytesPayload(b\"answer\", headers={\"X-Test-Header\": \"test\"})\n    resp = Response(body=payload)\n    resp.body = payload\n    resp.enable_compression(ContentCoding.gzip)\n    await resp.prepare(req)\n    assert resp.content_length is None\n\n\nasync def test_rm_content_length_if_compression_http10() -> None:\n    writer = mock.Mock()\n\n    async def write_headers(status_line, headers):\n        assert hdrs.CONTENT_LENGTH not in headers\n        assert hdrs.TRANSFER_ENCODING not in headers\n\n    writer.write_headers.side_effect = write_headers\n    req = make_request(\"GET\", \"/\", version=HttpVersion10, writer=writer)\n    resp = Response(body=BytesPayload(b\"answer\"))\n    resp.enable_compression(ContentCoding.gzip)\n    await resp.prepare(req)\n    assert resp.content_length is None\n\n\nasync def test_rm_content_length_if_204() -> None:\n    \"\"\"Ensure content-length is removed for 204 responses.\"\"\"\n    writer = mock.create_autospec(StreamWriter, spec_set=True, instance=True)\n\n    async def write_headers(status_line, headers):\n        assert hdrs.CONTENT_LENGTH not in headers\n\n    writer.write_headers.side_effect = write_headers\n    req = make_request(\"GET\", \"/\", writer=writer)\n    payload = BytesPayload(b\"answer\", headers={\"Content-Length\": \"6\"})\n    resp = Response(body=payload, status=204)\n    resp.body = payload\n    await resp.prepare(req)\n    assert resp.content_length is None\n\n\n@pytest.mark.parametrize(\"status\", (100, 101, 204, 304))\nasync def test_rm_transfer_encoding_rfc_9112_6_3_http_11(status: int) -> None:\n    \"\"\"Remove transfer encoding for RFC 9112 sec 6.3 with HTTP/1.1.\"\"\"\n    writer = mock.create_autospec(StreamWriter, spec_set=True, instance=True)\n    req = make_request(\"GET\", \"/\", version=HttpVersion11, writer=writer)\n    resp = Response(status=status, headers={hdrs.TRANSFER_ENCODING: \"chunked\"})\n    await resp.prepare(req)\n    assert resp.content_length == 0\n    assert not resp.chunked\n    assert hdrs.CONTENT_LENGTH not in resp.headers\n    assert hdrs.TRANSFER_ENCODING not in resp.headers\n\n\n@pytest.mark.parametrize(\"status\", (100, 101, 102, 204, 304))\nasync def test_rm_content_length_1xx_204_304_responses(status: int) -> None:\n    \"\"\"Remove content length for 1xx, 204, and 304 responses.\n\n    Content-Length is forbidden for 1xx and 204\n    https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.2\n\n    Content-Length is discouraged for 304.\n    https://datatracker.ietf.org/doc/html/rfc7232#section-4.1\n    \"\"\"\n    writer = mock.create_autospec(StreamWriter, spec_set=True, instance=True)\n    req = make_request(\"GET\", \"/\", version=HttpVersion11, writer=writer)\n    resp = Response(status=status, body=\"answer\")\n    await resp.prepare(req)\n    assert not resp.chunked\n    assert hdrs.CONTENT_LENGTH not in resp.headers\n    assert hdrs.TRANSFER_ENCODING not in resp.headers\n\n\nasync def test_head_response_keeps_content_length_of_original_body() -> None:\n    \"\"\"Verify HEAD response keeps the content length of the original body HTTP/1.1.\"\"\"\n    writer = mock.create_autospec(StreamWriter, spec_set=True, instance=True)\n    req = make_request(\"HEAD\", \"/\", version=HttpVersion11, writer=writer)\n    resp = Response(status=200, body=b\"answer\")\n    await resp.prepare(req)\n    assert resp.content_length == 6\n    assert not resp.chunked\n    assert resp.headers[hdrs.CONTENT_LENGTH] == \"6\"\n    assert hdrs.TRANSFER_ENCODING not in resp.headers\n\n\nasync def test_head_response_omits_content_length_when_body_unset() -> None:\n    \"\"\"Verify HEAD response omits content-length body when its unset.\"\"\"\n    writer = mock.create_autospec(StreamWriter, spec_set=True, instance=True)\n    req = make_request(\"HEAD\", \"/\", version=HttpVersion11, writer=writer)\n    resp = Response(status=200)\n    await resp.prepare(req)\n    assert resp.content_length == 0\n    assert not resp.chunked\n    assert hdrs.CONTENT_LENGTH not in resp.headers\n    assert hdrs.TRANSFER_ENCODING not in resp.headers\n\n\nasync def test_304_response_omits_content_length_when_body_unset() -> None:\n    \"\"\"Verify 304 response omits content-length body when its unset.\"\"\"\n    writer = mock.create_autospec(StreamWriter, spec_set=True, instance=True)\n    req = make_request(\"GET\", \"/\", version=HttpVersion11, writer=writer)\n    resp = Response(status=304)\n    await resp.prepare(req)\n    assert resp.content_length == 0\n    assert not resp.chunked\n    assert hdrs.CONTENT_LENGTH not in resp.headers\n    assert hdrs.TRANSFER_ENCODING not in resp.headers\n\n\nasync def test_content_length_on_chunked() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = Response(body=b\"answer\")\n    assert resp.content_length == 6\n    resp.enable_chunked_encoding()\n    assert resp.content_length is None\n    await resp.prepare(req)\n\n\nasync def test_write_non_byteish() -> None:\n    resp = StreamResponse()\n    await resp.prepare(make_request(\"GET\", \"/\"))\n\n    with pytest.raises(AssertionError):\n        await resp.write(123)\n\n\nasync def test_write_before_start() -> None:\n    resp = StreamResponse()\n\n    with pytest.raises(RuntimeError):\n        await resp.write(b\"data\")\n\n\nasync def test_cannot_write_after_eof() -> None:\n    resp = StreamResponse()\n    req = make_request(\"GET\", \"/\")\n    await resp.prepare(req)\n\n    await resp.write(b\"data\")\n    await resp.write_eof()\n    req.writer.write.reset_mock()\n\n    with pytest.raises(RuntimeError):\n        await resp.write(b\"next data\")\n    assert not req.writer.write.called\n\n\nasync def test___repr___after_eof() -> None:\n    resp = StreamResponse()\n    await resp.prepare(make_request(\"GET\", \"/\"))\n\n    await resp.write(b\"data\")\n    await resp.write_eof()\n    resp_repr = repr(resp)\n    assert resp_repr == \"<StreamResponse OK eof>\"\n\n\nasync def test_cannot_write_eof_before_headers() -> None:\n    resp = StreamResponse()\n\n    with pytest.raises(AssertionError):\n        await resp.write_eof()\n\n\nasync def test_cannot_write_eof_twice() -> None:\n    resp = StreamResponse()\n    writer = mock.Mock()\n    resp_impl = await resp.prepare(make_request(\"GET\", \"/\"))\n    resp_impl.write = make_mocked_coro(None)\n    resp_impl.write_eof = make_mocked_coro(None)\n\n    await resp.write(b\"data\")\n    assert resp_impl.write.called\n\n    await resp.write_eof()\n\n    resp_impl.write.reset_mock()\n    await resp.write_eof()\n    assert not writer.write.called\n\n\ndef test_force_close() -> None:\n    resp = StreamResponse()\n\n    assert resp.keep_alive is None\n    resp.force_close()\n    assert resp.keep_alive is False\n\n\nasync def test_response_output_length() -> None:\n    resp = StreamResponse()\n    await resp.prepare(make_request(\"GET\", \"/\"))\n    with pytest.warns(DeprecationWarning):\n        assert resp.output_length\n\n\ndef test_response_cookies() -> None:\n    resp = StreamResponse()\n\n    assert resp.cookies == {}\n    assert str(resp.cookies) == \"\"\n\n    resp.set_cookie(\"name\", \"value\")\n    assert str(resp.cookies) == \"Set-Cookie: name=value; Path=/\"\n    resp.set_cookie(\"name\", \"other_value\")\n    assert str(resp.cookies) == \"Set-Cookie: name=other_value; Path=/\"\n\n    resp.cookies[\"name\"] = \"another_other_value\"\n    resp.cookies[\"name\"][\"max-age\"] = 10\n    assert (\n        str(resp.cookies) == \"Set-Cookie: name=another_other_value; Max-Age=10; Path=/\"\n    )\n\n    resp.del_cookie(\"name\")\n    expected = (\n        'Set-Cookie: name=(\"\")?; '\n        \"expires=Thu, 01 Jan 1970 00:00:00 GMT; Max-Age=0; Path=/\"\n    )\n    assert Matches(expected) == str(resp.cookies)\n\n    resp.set_cookie(\"name\", \"value\", domain=\"local.host\")\n    expected = \"Set-Cookie: name=value; Domain=local.host; Path=/\"\n    assert str(resp.cookies) == expected\n\n\ndef test_response_cookie_path() -> None:\n    resp = StreamResponse()\n\n    assert resp.cookies == {}\n\n    resp.set_cookie(\"name\", \"value\", path=\"/some/path\")\n    assert str(resp.cookies) == \"Set-Cookie: name=value; Path=/some/path\"\n    resp.set_cookie(\"name\", \"value\", expires=\"123\")\n    assert str(resp.cookies) == \"Set-Cookie: name=value; expires=123; Path=/\"\n    resp.set_cookie(\n        \"name\",\n        \"value\",\n        domain=\"example.com\",\n        path=\"/home\",\n        expires=\"123\",\n        max_age=\"10\",\n        secure=True,\n        httponly=True,\n        version=\"2.0\",\n        samesite=\"lax\",\n    )\n    assert (\n        str(resp.cookies).lower() == \"set-cookie: name=value; \"\n        \"domain=example.com; \"\n        \"expires=123; \"\n        \"httponly; \"\n        \"max-age=10; \"\n        \"path=/home; \"\n        \"samesite=lax; \"\n        \"secure; \"\n        \"version=2.0\"\n    )\n\n\ndef test_response_cookie__issue_del_cookie() -> None:\n    resp = StreamResponse()\n\n    assert resp.cookies == {}\n    assert str(resp.cookies) == \"\"\n\n    resp.del_cookie(\"name\")\n    expected = (\n        'Set-Cookie: name=(\"\")?; '\n        \"expires=Thu, 01 Jan 1970 00:00:00 GMT; Max-Age=0; Path=/\"\n    )\n    assert Matches(expected) == str(resp.cookies)\n\n\ndef test_cookie_set_after_del() -> None:\n    resp = StreamResponse()\n\n    resp.del_cookie(\"name\")\n    resp.set_cookie(\"name\", \"val\")\n    # check for Max-Age dropped\n    expected = \"Set-Cookie: name=val; Path=/\"\n    assert str(resp.cookies) == expected\n\n\ndef test_set_status_with_reason() -> None:\n    resp = StreamResponse()\n\n    resp.set_status(200, \"Everything is fine!\")\n    assert 200 == resp.status\n    assert \"Everything is fine!\" == resp.reason\n\n\nasync def test_start_force_close() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = StreamResponse()\n    resp.force_close()\n    assert not resp.keep_alive\n\n    await resp.prepare(req)\n    assert not resp.keep_alive\n\n\nasync def test___repr__() -> None:\n    req = make_request(\"GET\", \"/path/to\")\n    resp = StreamResponse(reason=\"foo\")\n    await resp.prepare(req)\n    assert \"<StreamResponse foo GET /path/to >\" == repr(resp)\n\n\ndef test___repr___not_prepared() -> None:\n    resp = StreamResponse(reason=\"foo\")\n    assert \"<StreamResponse foo not prepared>\" == repr(resp)\n\n\nasync def test_keep_alive_http10_default() -> None:\n    req = make_request(\"GET\", \"/\", version=HttpVersion10)\n    resp = StreamResponse()\n    await resp.prepare(req)\n    assert not resp.keep_alive\n\n\nasync def test_keep_alive_http10_switched_on() -> None:\n    headers = CIMultiDict(Connection=\"keep-alive\")\n    req = make_request(\"GET\", \"/\", version=HttpVersion10, headers=headers)\n    req._message = req._message._replace(should_close=False)\n    resp = StreamResponse()\n    await resp.prepare(req)\n    assert resp.keep_alive\n\n\nasync def test_keep_alive_http09() -> None:\n    headers = CIMultiDict(Connection=\"keep-alive\")\n    req = make_request(\"GET\", \"/\", version=HttpVersion(0, 9), headers=headers)\n    resp = StreamResponse()\n    await resp.prepare(req)\n    assert not resp.keep_alive\n\n\nasync def test_prepare_twice() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = StreamResponse()\n\n    impl1 = await resp.prepare(req)\n    impl2 = await resp.prepare(req)\n    assert impl1 is impl2\n\n\nasync def test_prepare_calls_signal() -> None:\n    app = mock.Mock()\n    sig = make_mocked_coro()\n    on_response_prepare = aiosignal.Signal(app)\n    on_response_prepare.append(sig)\n    req = make_request(\"GET\", \"/\", app=app, on_response_prepare=on_response_prepare)\n    resp = StreamResponse()\n\n    await resp.prepare(req)\n\n    sig.assert_called_with(req, resp)\n\n\n# Response class\n\n\ndef test_response_ctor() -> None:\n    resp = Response()\n\n    assert 200 == resp.status\n    assert \"OK\" == resp.reason\n    assert resp.body is None\n    assert resp.content_length == 0\n    assert \"CONTENT-LENGTH\" not in resp.headers\n\n\nasync def test_ctor_with_headers_and_status() -> None:\n    resp = Response(body=b\"body\", status=201, headers={\"Age\": \"12\", \"DATE\": \"date\"})\n\n    assert 201 == resp.status\n    assert b\"body\" == resp.body\n    assert resp.headers[\"AGE\"] == \"12\"\n\n    req = make_mocked_request(\"GET\", \"/\")\n    await resp._start(req)\n    assert 4 == resp.content_length\n    assert resp.headers[\"CONTENT-LENGTH\"] == \"4\"\n\n\ndef test_ctor_content_type() -> None:\n    resp = Response(content_type=\"application/json\")\n\n    assert 200 == resp.status\n    assert \"OK\" == resp.reason\n    assert 0 == resp.content_length\n    assert CIMultiDict([(\"CONTENT-TYPE\", \"application/json\")]) == resp.headers\n\n\ndef test_ctor_text_body_combined() -> None:\n    with pytest.raises(ValueError):\n        Response(body=b\"123\", text=\"test text\")\n\n\nasync def test_ctor_text() -> None:\n    resp = Response(text=\"test text\")\n\n    assert 200 == resp.status\n    assert \"OK\" == resp.reason\n    assert 9 == resp.content_length\n    assert CIMultiDict([(\"CONTENT-TYPE\", \"text/plain; charset=utf-8\")]) == resp.headers\n\n    assert resp.body == b\"test text\"\n    assert resp.text == \"test text\"\n\n    resp.headers[\"DATE\"] = \"date\"\n    req = make_mocked_request(\"GET\", \"/\", version=HttpVersion11)\n    await resp._start(req)\n    assert resp.headers[\"CONTENT-LENGTH\"] == \"9\"\n\n\ndef test_ctor_charset() -> None:\n    resp = Response(text=\"текст\", charset=\"koi8-r\")\n\n    assert \"текст\".encode(\"koi8-r\") == resp.body\n    assert \"koi8-r\" == resp.charset\n\n\ndef test_ctor_charset_default_utf8() -> None:\n    resp = Response(text=\"test test\", charset=None)\n\n    assert \"utf-8\" == resp.charset\n\n\ndef test_ctor_charset_in_content_type() -> None:\n    with pytest.raises(ValueError):\n        Response(text=\"test test\", content_type=\"text/plain; charset=utf-8\")\n\n\ndef test_ctor_charset_without_text() -> None:\n    resp = Response(content_type=\"text/plain\", charset=\"koi8-r\")\n\n    assert \"koi8-r\" == resp.charset\n\n\ndef test_ctor_content_type_with_extra() -> None:\n    resp = Response(text=\"test test\", content_type=\"text/plain; version=0.0.4\")\n\n    assert resp.content_type == \"text/plain\"\n    assert resp.headers[\"content-type\"] == \"text/plain; version=0.0.4; charset=utf-8\"\n\n\ndef test_ctor_both_content_type_param_and_header_with_text() -> None:\n    with pytest.raises(ValueError):\n        Response(\n            headers={\"Content-Type\": \"application/json\"},\n            content_type=\"text/html\",\n            text=\"text\",\n        )\n\n\ndef test_ctor_both_charset_param_and_header_with_text() -> None:\n    with pytest.raises(ValueError):\n        Response(\n            headers={\"Content-Type\": \"application/json\"}, charset=\"koi8-r\", text=\"text\"\n        )\n\n\ndef test_ctor_both_content_type_param_and_header() -> None:\n    with pytest.raises(ValueError):\n        Response(headers={\"Content-Type\": \"application/json\"}, content_type=\"text/html\")\n\n\ndef test_ctor_both_charset_param_and_header() -> None:\n    with pytest.raises(ValueError):\n        Response(headers={\"Content-Type\": \"application/json\"}, charset=\"koi8-r\")\n\n\nasync def test_assign_nonbyteish_body() -> None:\n    resp = Response(body=b\"data\")\n\n    with pytest.raises(ValueError):\n        resp.body = 123\n    assert b\"data\" == resp.body\n    assert 4 == resp.content_length\n\n    resp.headers[\"DATE\"] = \"date\"\n    req = make_mocked_request(\"GET\", \"/\", version=HttpVersion11)\n    await resp._start(req)\n    assert resp.headers[\"CONTENT-LENGTH\"] == \"4\"\n    assert 4 == resp.content_length\n\n\ndef test_assign_nonstr_text() -> None:\n    resp = Response(text=\"test\")\n\n    with pytest.raises(AssertionError):\n        resp.text = b\"123\"\n    assert b\"test\" == resp.body\n    assert 4 == resp.content_length\n\n\nmpwriter = MultipartWriter(boundary=\"x\")\nmpwriter.append_payload(StringPayload(\"test\"))\n\n\nasync def async_iter() -> AsyncIterator[str]:\n    yield \"foo\"  # pragma: no cover\n\n\nclass CustomIO(io.IOBase):\n    def __init__(self):\n        self._lines = [b\"\", b\"\", b\"test\"]\n\n    def read(self, size: int = -1) -> bytes:\n        return self._lines.pop()\n\n\n@pytest.mark.parametrize(\n    \"payload,expected\",\n    (\n        (\"test\", \"test\"),\n        (CustomIO(), \"test\"),\n        (io.StringIO(\"test\"), \"test\"),\n        (io.TextIOWrapper(io.BytesIO(b\"test\")), \"test\"),\n        (io.BytesIO(b\"test\"), \"test\"),\n        (io.BufferedReader(io.BytesIO(b\"test\")), \"test\"),\n        (async_iter(), None),\n        (BodyPartReader(\"x\", CIMultiDictProxy(CIMultiDict()), mock.Mock()), None),\n        (\n            mpwriter,\n            \"--x\\nContent-Type: text/plain; charset=utf-8\\r\\nContent-Length: 4\\r\\n\\r\\ntest\",\n        ),\n    ),\n)\ndef test_payload_body_get_text(payload, expected: Optional[str]) -> None:\n    resp = Response(body=payload)\n    if expected is None:\n        with pytest.raises(TypeError):\n            resp.text\n    else:\n        assert resp.text == expected\n\n\ndef test_response_set_content_length() -> None:\n    resp = Response()\n    with pytest.raises(RuntimeError):\n        resp.content_length = 1\n\n\nasync def test_send_headers_for_empty_body(buf, writer) -> None:\n    req = make_request(\"GET\", \"/\", writer=writer)\n    resp = Response()\n\n    await resp.prepare(req)\n    await resp.write_eof()\n    txt = buf.decode(\"utf8\")\n    assert (\n        Matches(\n            \"HTTP/1.1 200 OK\\r\\n\"\n            \"Content-Length: 0\\r\\n\"\n            \"Date: .+\\r\\n\"\n            \"Server: .+\\r\\n\\r\\n\"\n        )\n        == txt\n    )\n\n\nasync def test_render_with_body(buf, writer) -> None:\n    req = make_request(\"GET\", \"/\", writer=writer)\n    resp = Response(body=b\"data\")\n\n    await resp.prepare(req)\n    await resp.write_eof()\n\n    txt = buf.decode(\"utf8\")\n    assert (\n        Matches(\n            \"HTTP/1.1 200 OK\\r\\n\"\n            \"Content-Length: 4\\r\\n\"\n            \"Content-Type: application/octet-stream\\r\\n\"\n            \"Date: .+\\r\\n\"\n            \"Server: .+\\r\\n\\r\\n\"\n            \"data\"\n        )\n        == txt\n    )\n\n\nasync def test_multiline_reason(buf, writer) -> None:\n    with pytest.raises(ValueError, match=r\"Reason cannot contain \\\\n\"):\n        Response(reason=\"Bad\\r\\nInjected-header: foo\")\n\n\nasync def test_send_set_cookie_header(buf, writer) -> None:\n    resp = Response()\n    resp.cookies[\"name\"] = \"value\"\n    req = make_request(\"GET\", \"/\", writer=writer)\n\n    await resp.prepare(req)\n    await resp.write_eof()\n\n    txt = buf.decode(\"utf8\")\n    assert (\n        Matches(\n            \"HTTP/1.1 200 OK\\r\\n\"\n            \"Content-Length: 0\\r\\n\"\n            \"Set-Cookie: name=value\\r\\n\"\n            \"Date: .+\\r\\n\"\n            \"Server: .+\\r\\n\\r\\n\"\n        )\n        == txt\n    )\n\n\nasync def test_consecutive_write_eof() -> None:\n    writer = mock.Mock()\n    writer.write_eof = make_mocked_coro()\n    writer.write_headers = make_mocked_coro()\n    req = make_request(\"GET\", \"/\", writer=writer)\n    data = b\"data\"\n    resp = Response(body=data)\n\n    await resp.prepare(req)\n    await resp.write_eof()\n    await resp.write_eof()\n    writer.write_eof.assert_called_once_with(data)\n\n\ndef test_set_text_with_content_type() -> None:\n    resp = Response()\n    resp.content_type = \"text/html\"\n    resp.text = \"text\"\n\n    assert \"text\" == resp.text\n    assert b\"text\" == resp.body\n    assert \"text/html\" == resp.content_type\n\n\ndef test_set_text_with_charset() -> None:\n    resp = Response()\n    resp.content_type = \"text/plain\"\n    resp.charset = \"KOI8-R\"\n    resp.text = \"текст\"\n\n    assert \"текст\" == resp.text\n    assert \"текст\".encode(\"koi8-r\") == resp.body\n    assert \"koi8-r\" == resp.charset\n\n\ndef test_default_content_type_in_stream_response() -> None:\n    resp = StreamResponse()\n    assert resp.content_type == \"application/octet-stream\"\n\n\ndef test_default_content_type_in_response() -> None:\n    resp = Response()\n    assert resp.content_type == \"application/octet-stream\"\n\n\ndef test_content_type_with_set_text() -> None:\n    resp = Response(text=\"text\")\n    assert resp.content_type == \"text/plain\"\n\n\ndef test_content_type_with_set_body() -> None:\n    resp = Response(body=b\"body\")\n    assert resp.content_type == \"application/octet-stream\"\n\n\ndef test_prepared_when_not_started() -> None:\n    resp = StreamResponse()\n    assert not resp.prepared\n\n\nasync def test_prepared_when_started() -> None:\n    resp = StreamResponse()\n    await resp.prepare(make_request(\"GET\", \"/\"))\n    assert resp.prepared\n\n\nasync def test_prepared_after_eof() -> None:\n    resp = StreamResponse()\n    await resp.prepare(make_request(\"GET\", \"/\"))\n    await resp.write(b\"data\")\n    await resp.write_eof()\n    assert resp.prepared\n\n\nasync def test_drain_before_start() -> None:\n    resp = StreamResponse()\n    with pytest.raises(AssertionError):\n        await resp.drain()\n\n\nasync def test_changing_status_after_prepare_raises() -> None:\n    resp = StreamResponse()\n    await resp.prepare(make_request(\"GET\", \"/\"))\n    with pytest.raises(AssertionError):\n        resp.set_status(400)\n\n\ndef test_nonstr_text_in_ctor() -> None:\n    with pytest.raises(TypeError):\n        Response(text=b\"data\")\n\n\ndef test_text_in_ctor_with_content_type() -> None:\n    resp = Response(text=\"data\", content_type=\"text/html\")\n    assert \"data\" == resp.text\n    assert \"text/html\" == resp.content_type\n\n\ndef test_text_in_ctor_with_content_type_header() -> None:\n    resp = Response(text=\"текст\", headers={\"Content-Type\": \"text/html; charset=koi8-r\"})\n    assert \"текст\".encode(\"koi8-r\") == resp.body\n    assert \"text/html\" == resp.content_type\n    assert \"koi8-r\" == resp.charset\n\n\ndef test_text_in_ctor_with_content_type_header_multidict() -> None:\n    headers = CIMultiDict({\"Content-Type\": \"text/html; charset=koi8-r\"})\n    resp = Response(text=\"текст\", headers=headers)\n    assert \"текст\".encode(\"koi8-r\") == resp.body\n    assert \"text/html\" == resp.content_type\n    assert \"koi8-r\" == resp.charset\n\n\ndef test_body_in_ctor_with_content_type_header_multidict() -> None:\n    headers = CIMultiDict({\"Content-Type\": \"text/html; charset=koi8-r\"})\n    resp = Response(body=\"текст\".encode(\"koi8-r\"), headers=headers)\n    assert \"текст\".encode(\"koi8-r\") == resp.body\n    assert \"text/html\" == resp.content_type\n    assert \"koi8-r\" == resp.charset\n\n\ndef test_text_with_empty_payload() -> None:\n    resp = Response(status=200)\n    assert resp.body is None\n    assert resp.text is None\n\n\ndef test_response_with_content_length_header_without_body() -> None:\n    resp = Response(headers={\"Content-Length\": 123})\n    assert resp.content_length == 123\n\n\ndef test_response_with_immutable_headers() -> None:\n    resp = Response(\n        text=\"text\", headers=CIMultiDictProxy(CIMultiDict({\"Header\": \"Value\"}))\n    )\n    assert resp.headers == {\n        \"Header\": \"Value\",\n        \"Content-Type\": \"text/plain; charset=utf-8\",\n    }\n\n\nasync def test_response_prepared_after_header_preparation() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = StreamResponse()\n    await resp.prepare(req)\n\n    assert type(resp.headers[\"Server\"]) is str\n\n    async def _strip_server(req, res):\n        assert \"Server\" in res.headers\n\n        if \"Server\" in res.headers:\n            del res.headers[\"Server\"]\n\n    app = mock.Mock()\n    sig = aiosignal.Signal(app)\n    sig.append(_strip_server)\n\n    req = make_request(\"GET\", \"/\", on_response_prepare=sig, app=app)\n    resp = StreamResponse()\n    await resp.prepare(req)\n\n    assert \"Server\" not in resp.headers\n\n\nclass TestJSONResponse:\n    def test_content_type_is_application_json_by_default(self) -> None:\n        resp = json_response(\"\")\n        assert \"application/json\" == resp.content_type\n\n    def test_passing_text_only(self) -> None:\n        resp = json_response(text=json.dumps(\"jaysawn\"))\n        assert resp.text == json.dumps(\"jaysawn\")\n\n    def test_data_and_text_raises_value_error(self) -> None:\n        with pytest.raises(ValueError) as excinfo:\n            json_response(data=\"foo\", text=\"bar\")\n        expected_message = \"only one of data, text, or body should be specified\"\n        assert expected_message == excinfo.value.args[0]\n\n    def test_data_and_body_raises_value_error(self) -> None:\n        with pytest.raises(ValueError) as excinfo:\n            json_response(data=\"foo\", body=b\"bar\")\n        expected_message = \"only one of data, text, or body should be specified\"\n        assert expected_message == excinfo.value.args[0]\n\n    def test_text_is_json_encoded(self) -> None:\n        resp = json_response({\"foo\": 42})\n        assert json.dumps({\"foo\": 42}) == resp.text\n\n    def test_content_type_is_overrideable(self) -> None:\n        resp = json_response({\"foo\": 42}, content_type=\"application/vnd.json+api\")\n        assert \"application/vnd.json+api\" == resp.content_type\n",
            "header": {
                "file": {
                    "path": "tests/test_web_response.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "264ca5e9",
                "new_commit_hash": "ec9522b0",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/tests/test_web_response.py"
            },
            "plus_file": {
                "path": "b/tests/test_web_response.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 945,
                            "length": 14
                        },
                        "new_range": {
                            "start": 945,
                            "length": 14
                        },
                        "section": "async def test_start_force_close() -> None:"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "async def test___repr__() -> None:",
                                "type": "context"
                            },
                            {
                                "content": "    req = make_request(\"GET\", \"/path/to\")",
                                "type": "context"
                            },
                            {
                                "content": "    resp = StreamResponse(reason=301)",
                                "type": "deleted"
                            },
                            {
                                "content": "    resp = StreamResponse(reason=\"foo\")",
                                "type": "added"
                            },
                            {
                                "content": "    await resp.prepare(req)",
                                "type": "context"
                            },
                            {
                                "content": "    assert \"<StreamResponse 301 GET /path/to >\" == repr(resp)",
                                "type": "deleted"
                            },
                            {
                                "content": "    assert \"<StreamResponse foo GET /path/to >\" == repr(resp)",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "def test___repr___not_prepared() -> None:",
                                "type": "context"
                            },
                            {
                                "content": "    resp = StreamResponse(reason=301)",
                                "type": "deleted"
                            },
                            {
                                "content": "    assert \"<StreamResponse 301 not prepared>\" == repr(resp)",
                                "type": "deleted"
                            },
                            {
                                "content": "    resp = StreamResponse(reason=\"foo\")",
                                "type": "added"
                            },
                            {
                                "content": "    assert \"<StreamResponse foo not prepared>\" == repr(resp)",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "async def test_keep_alive_http10_default() -> None:",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "tests/test_web_response.py",
                            "type": "function",
                            "name": "test___repr__",
                            "content": "async def test___repr__() -> None:\n    req = make_request(\"GET\", \"/path/to\")\n    resp = StreamResponse(reason=301)\n    await resp.prepare(req)\n    assert \"<StreamResponse 301 GET /path/to >\" == repr(resp)",
                            "ast_type_str": "AsyncFunctionDef",
                            "start_lineno": 946,
                            "end_lineno": 950,
                            "parent": null
                        },
                        {
                            "file_name": "tests/test_web_response.py",
                            "type": "function",
                            "name": "test___repr___not_prepared",
                            "content": "def test___repr___not_prepared() -> None:\n    resp = StreamResponse(reason=301)\n    assert \"<StreamResponse 301 not prepared>\" == repr(resp)",
                            "ast_type_str": "FunctionDef",
                            "start_lineno": 953,
                            "end_lineno": 955,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 1226,
                            "length": 6
                        },
                        "new_range": {
                            "start": 1226,
                            "length": 11
                        },
                        "section": "async def test_render_with_body(buf, writer) -> None:"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "    )",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "async def test_multiline_reason(buf, writer) -> None:",
                                "type": "added"
                            },
                            {
                                "content": "    with pytest.raises(ValueError, match=r\"Reason cannot contain \\\\n\"):",
                                "type": "added"
                            },
                            {
                                "content": "        Response(reason=\"Bad\\r\\nInjected-header: foo\")",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "async def test_send_set_cookie_header(buf, writer) -> None:",
                                "type": "context"
                            },
                            {
                                "content": "    resp = Response()",
                                "type": "context"
                            },
                            {
                                "content": "    resp.cookies[\"name\"] = \"value\"",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [
                        {
                            "file_name": "tests/test_web_response.py",
                            "type": "function",
                            "name": "test_multiline_reason",
                            "content": "async def test_multiline_reason(buf, writer) -> None:\n    with pytest.raises(ValueError, match=r\"Reason cannot contain \\\\n\"):\n        Response(reason=\"Bad\\r\\nInjected-header: foo\")",
                            "ast_type_str": "AsyncFunctionDef",
                            "start_lineno": 1229,
                            "end_lineno": 1231,
                            "parent": null
                        }
                    ],
                    "deleted_entities": []
                }
            ]
        }
    ],
    "old_commit_hash": "e9609ad14aef19dfd62e29f99c01a25294ff8d6b^",
    "new_commit_hash": "e9609ad14aef19dfd62e29f99c01a25294ff8d6b",
    "commit_message": "Disallow newlines in reason (#9167) (#9198)\n\n(cherry picked from commit 88f383427e918360fd2762a9a3256897159e2d6b)",
    "commit_date": "2024-09-19T13:28:31+01:00",
    "metadata": {}
}
{
    "repo_name": "aiohttp",
    "new_commit_hash": "e9609ad14aef19dfd62e29f99c01a25294ff8d6b",
    "test_file_codes": [
        "import collections\nimport re\nfrom traceback import format_exception\nfrom unittest import mock\n\nimport aiosignal\nimport pytest\nfrom yarl import URL\n\nfrom aiohttp import helpers, web\nfrom aiohttp.pytest_plugin import AiohttpClient\nfrom aiohttp.test_utils import make_mocked_request\n\n\n@pytest.fixture\ndef buf() -> bytearray:\n    return bytearray()\n\n\n@pytest.fixture\ndef http_request(buf):\n    method = \"GET\"\n    path = \"/\"\n    writer = mock.Mock()\n    writer.drain.return_value = ()\n\n    def append(data=b\"\"):\n        buf.extend(data)\n        return helpers.noop()\n\n    async def write_headers(status_line, headers):\n        headers = (\n            status_line\n            + \"\\r\\n\"\n            + \"\".join([k + \": \" + v + \"\\r\\n\" for k, v in headers.items()])\n        )\n        headers = headers.encode(\"utf-8\") + b\"\\r\\n\"\n        buf.extend(headers)\n\n    writer.buffer_data.side_effect = append\n    writer.write.side_effect = append\n    writer.write_eof.side_effect = append\n    writer.write_headers.side_effect = write_headers\n\n    app = mock.Mock()\n    app._debug = False\n    app.on_response_prepare = aiosignal.Signal(app)\n    app.on_response_prepare.freeze()\n    req = make_mocked_request(method, path, app=app, writer=writer)\n    return req\n\n\ndef test_all_http_exceptions_exported() -> None:\n    assert \"HTTPException\" in web.__all__\n    for name in dir(web):\n        if name.startswith(\"_\"):\n            continue\n        obj = getattr(web, name)\n        if isinstance(obj, type) and issubclass(obj, web.HTTPException):\n            assert name in web.__all__\n\n\nasync def test_HTTPOk(buf, http_request) -> None:\n    resp = web.HTTPOk()\n    await resp.prepare(http_request)\n    await resp.write_eof()\n    txt = buf.decode(\"utf8\")\n    assert re.match(\n        (\n            \"HTTP/1.1 200 OK\\r\\n\"\n            \"Content-Type: text/plain; charset=utf-8\\r\\n\"\n            \"Content-Length: 7\\r\\n\"\n            \"Date: .+\\r\\n\"\n            \"Server: .+\\r\\n\\r\\n\"\n            \"200: OK\"\n        ),\n        txt,\n    )\n\n\ndef test_terminal_classes_has_status_code() -> None:\n    terminals = set()\n    for name in dir(web):\n        obj = getattr(web, name)\n        if isinstance(obj, type) and issubclass(obj, web.HTTPException):\n            terminals.add(obj)\n\n    dup = frozenset(terminals)\n    for cls1 in dup:\n        for cls2 in dup:\n            if cls1 in cls2.__bases__:\n                terminals.discard(cls1)\n\n    for cls in terminals:\n        assert cls.status_code is not None\n    codes = collections.Counter(cls.status_code for cls in terminals)\n    assert None not in codes\n    assert 1 == codes.most_common(1)[0][1]\n\n\nasync def test_HTTPFound(buf, http_request) -> None:\n    resp = web.HTTPFound(location=\"/redirect\")\n    assert \"/redirect\" == resp.location\n    assert \"/redirect\" == resp.headers[\"location\"]\n    await resp.prepare(http_request)\n    await resp.write_eof()\n    txt = buf.decode(\"utf8\")\n    assert re.match(\n        \"HTTP/1.1 302 Found\\r\\n\"\n        \"Content-Type: text/plain; charset=utf-8\\r\\n\"\n        \"Location: /redirect\\r\\n\"\n        \"Content-Length: 10\\r\\n\"\n        \"Date: .+\\r\\n\"\n        \"Server: .+\\r\\n\\r\\n\"\n        \"302: Found\",\n        txt,\n    )\n\n\ndef test_HTTPFound_empty_location() -> None:\n    with pytest.raises(ValueError):\n        web.HTTPFound(location=\"\")\n\n    with pytest.raises(ValueError):\n        web.HTTPFound(location=None)\n\n\ndef test_HTTPFound_location_CRLF() -> None:\n    exc = web.HTTPFound(location=\"/redirect\\r\\n\")\n    assert \"\\r\\n\" not in exc.headers[\"Location\"]\n\n\nasync def test_HTTPMethodNotAllowed(buf, http_request) -> None:\n    resp = web.HTTPMethodNotAllowed(\"get\", [\"POST\", \"PUT\"])\n    assert \"GET\" == resp.method\n    assert {\"POST\", \"PUT\"} == resp.allowed_methods\n    assert \"POST,PUT\" == resp.headers[\"allow\"]\n    await resp.prepare(http_request)\n    await resp.write_eof()\n    txt = buf.decode(\"utf8\")\n    assert re.match(\n        \"HTTP/1.1 405 Method Not Allowed\\r\\n\"\n        \"Content-Type: text/plain; charset=utf-8\\r\\n\"\n        \"Allow: POST,PUT\\r\\n\"\n        \"Content-Length: 23\\r\\n\"\n        \"Date: .+\\r\\n\"\n        \"Server: .+\\r\\n\\r\\n\"\n        \"405: Method Not Allowed\",\n        txt,\n    )\n\n\ndef test_override_body_with_text() -> None:\n    resp = web.HTTPNotFound(text=\"Page not found\")\n    assert 404 == resp.status\n    assert b\"Page not found\" == resp.body\n    assert \"Page not found\" == resp.text\n    assert \"text/plain\" == resp.content_type\n    assert \"utf-8\" == resp.charset\n\n\ndef test_override_body_with_binary() -> None:\n    txt = \"<html><body>Page not found</body></html>\"\n    with pytest.warns(DeprecationWarning):\n        resp = web.HTTPNotFound(body=txt.encode(\"utf-8\"), content_type=\"text/html\")\n    assert 404 == resp.status\n    assert txt.encode(\"utf-8\") == resp.body\n    assert txt == resp.text\n    assert \"text/html\" == resp.content_type\n    assert resp.charset is None\n\n\ndef test_default_body() -> None:\n    resp = web.HTTPOk()\n    assert b\"200: OK\" == resp.body\n\n\ndef test_empty_body_204() -> None:\n    resp = web.HTTPNoContent()\n    assert resp.body is None\n\n\ndef test_empty_body_205() -> None:\n    resp = web.HTTPNoContent()\n    assert resp.body is None\n\n\ndef test_empty_body_304() -> None:\n    resp = web.HTTPNoContent()\n    resp.body is None\n\n\ndef test_no_link_451() -> None:\n    with pytest.raises(TypeError):\n        web.HTTPUnavailableForLegalReasons()  # type: ignore[call-arg]\n\n\ndef test_link_none_451() -> None:\n    resp = web.HTTPUnavailableForLegalReasons(link=None)\n    assert resp.link is None\n    assert \"Link\" not in resp.headers\n\n\ndef test_link_empty_451() -> None:\n    resp = web.HTTPUnavailableForLegalReasons(link=\"\")\n    assert resp.link is None\n    assert \"Link\" not in resp.headers\n\n\ndef test_link_str_451() -> None:\n    resp = web.HTTPUnavailableForLegalReasons(link=\"http://warning.or.kr/\")\n    assert resp.link == URL(\"http://warning.or.kr/\")\n    assert resp.headers[\"Link\"] == '<http://warning.or.kr/>; rel=\"blocked-by\"'\n\n\ndef test_link_url_451() -> None:\n    resp = web.HTTPUnavailableForLegalReasons(link=URL(\"http://warning.or.kr/\"))\n    assert resp.link == URL(\"http://warning.or.kr/\")\n    assert resp.headers[\"Link\"] == '<http://warning.or.kr/>; rel=\"blocked-by\"'\n\n\ndef test_link_CRLF_451() -> None:\n    resp = web.HTTPUnavailableForLegalReasons(link=\"http://warning.or.kr/\\r\\n\")\n    assert \"\\r\\n\" not in resp.headers[\"Link\"]\n\n\ndef test_HTTPException_retains_cause() -> None:\n    with pytest.raises(web.HTTPException) as ei:\n        try:\n            raise Exception(\"CustomException\")\n        except Exception as exc:\n            raise web.HTTPException() from exc\n    tb = \"\".join(format_exception(ei.type, ei.value, ei.tb))\n    assert \"CustomException\" in tb\n    assert \"direct cause\" in tb\n\n\nasync def test_HTTPException_retains_cookie(aiohttp_client: AiohttpClient) -> None:\n    @web.middleware\n    async def middleware(request, handler):\n        try:\n            return await handler(request)\n        except web.HTTPException as exc:\n            exc.set_cookie(\"foo\", request[\"foo\"])\n            raise exc\n\n    async def save(request):\n        request[\"foo\"] = \"works\"\n        raise web.HTTPFound(\"/show\")\n\n    async def show(request):\n        return web.Response(text=request.cookies[\"foo\"])\n\n    app = web.Application(middlewares=[middleware])\n    app.router.add_route(\"GET\", \"/save\", save)\n    app.router.add_route(\"GET\", \"/show\", show)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/save\")\n    assert resp.status == 200\n    assert str(resp.url)[-5:] == \"/show\"\n    text = await resp.text()\n    assert text == \"works\"\n\n\ndef test_unicode_text_body_unauthorized() -> None:\n    \"\"\"Test that HTTPUnauthorized can be initialized with a string.\"\"\"\n    with pytest.warns(\n        DeprecationWarning, match=\"body argument is deprecated for http web exceptions\"\n    ):\n        resp = web.HTTPUnauthorized(body=\"text\")\n    assert resp.status == 401\n\n\ndef test_multiline_reason() -> None:\n    with pytest.raises(ValueError, match=r\"Reason cannot contain \\\\n\"):\n        web.HTTPOk(reason=\"Bad\\r\\nInjected-header: foo\")\n",
        "import collections.abc\nimport datetime\nimport gzip\nimport io\nimport json\nimport zlib\nfrom concurrent.futures import ThreadPoolExecutor\nfrom typing import AsyncIterator, Optional\nfrom unittest import mock\n\nimport aiosignal\nimport pytest\nfrom multidict import CIMultiDict, CIMultiDictProxy\nfrom re_assert import Matches\n\nfrom aiohttp import HttpVersion, HttpVersion10, HttpVersion11, hdrs\nfrom aiohttp.helpers import ETag\nfrom aiohttp.http_writer import StreamWriter, _serialize_headers\nfrom aiohttp.multipart import BodyPartReader, MultipartWriter\nfrom aiohttp.payload import BytesPayload, StringPayload\nfrom aiohttp.test_utils import make_mocked_coro, make_mocked_request\nfrom aiohttp.web import ContentCoding, Response, StreamResponse, json_response\n\n\ndef make_request(\n    method,\n    path,\n    headers=CIMultiDict(),\n    version=HttpVersion11,\n    on_response_prepare=None,\n    **kwargs,\n):\n    app = kwargs.pop(\"app\", None) or mock.Mock()\n    app._debug = False\n    if on_response_prepare is None:\n        on_response_prepare = aiosignal.Signal(app)\n    app.on_response_prepare = on_response_prepare\n    app.on_response_prepare.freeze()\n    protocol = kwargs.pop(\"protocol\", None) or mock.Mock()\n    return make_mocked_request(\n        method, path, headers, version=version, protocol=protocol, app=app, **kwargs\n    )\n\n\n@pytest.fixture\ndef buf():\n    return bytearray()\n\n\n@pytest.fixture\ndef writer(buf):\n    writer = mock.Mock()\n\n    def acquire(cb):\n        cb(writer.transport)\n\n    def buffer_data(chunk):\n        buf.extend(chunk)\n\n    def write(chunk):\n        buf.extend(chunk)\n\n    async def write_headers(status_line, headers):\n        headers = _serialize_headers(status_line, headers)\n        buf.extend(headers)\n\n    async def write_eof(chunk=b\"\"):\n        buf.extend(chunk)\n\n    writer.acquire.side_effect = acquire\n    writer.transport.write.side_effect = write\n    writer.write.side_effect = write\n    writer.write_eof.side_effect = write_eof\n    writer.write_headers.side_effect = write_headers\n    writer.buffer_data.side_effect = buffer_data\n    writer.drain.return_value = ()\n\n    return writer\n\n\ndef test_stream_response_ctor() -> None:\n    resp = StreamResponse()\n    assert 200 == resp.status\n    assert resp.keep_alive is None\n\n    assert resp.task is None\n\n    req = mock.Mock()\n    resp._req = req\n    assert resp.task is req.task\n\n\ndef test_stream_response_hashable() -> None:\n    # should not raise exception\n    hash(StreamResponse())\n\n\ndef test_stream_response_eq() -> None:\n    resp1 = StreamResponse()\n    resp2 = StreamResponse()\n\n    assert resp1 == resp1\n    assert not resp1 == resp2\n\n\ndef test_stream_response_is_mutable_mapping() -> None:\n    resp = StreamResponse()\n    assert isinstance(resp, collections.abc.MutableMapping)\n    resp[\"key\"] = \"value\"\n    assert \"value\" == resp[\"key\"]\n\n\ndef test_stream_response_delitem() -> None:\n    resp = StreamResponse()\n    resp[\"key\"] = \"value\"\n    del resp[\"key\"]\n    assert \"key\" not in resp\n\n\ndef test_stream_response_len() -> None:\n    resp = StreamResponse()\n    assert len(resp) == 0\n    resp[\"key\"] = \"value\"\n    assert len(resp) == 1\n\n\ndef test_request_iter() -> None:\n    resp = StreamResponse()\n    resp[\"key\"] = \"value\"\n    resp[\"key2\"] = \"value2\"\n    assert set(resp) == {\"key\", \"key2\"}\n\n\ndef test_content_length() -> None:\n    resp = StreamResponse()\n    assert resp.content_length is None\n\n\ndef test_content_length_setter() -> None:\n    resp = StreamResponse()\n\n    resp.content_length = 234\n    assert 234 == resp.content_length\n\n\ndef test_content_length_setter_with_enable_chunked_encoding() -> None:\n    resp = StreamResponse()\n\n    resp.enable_chunked_encoding()\n    with pytest.raises(RuntimeError):\n        resp.content_length = 234\n\n\ndef test_drop_content_length_header_on_setting_len_to_None() -> None:\n    resp = StreamResponse()\n\n    resp.content_length = 1\n    assert \"1\" == resp.headers[\"Content-Length\"]\n    resp.content_length = None\n    assert \"Content-Length\" not in resp.headers\n\n\ndef test_set_content_length_to_None_on_non_set() -> None:\n    resp = StreamResponse()\n\n    resp.content_length = None\n    assert \"Content-Length\" not in resp.headers\n    resp.content_length = None\n    assert \"Content-Length\" not in resp.headers\n\n\ndef test_setting_content_type() -> None:\n    resp = StreamResponse()\n\n    resp.content_type = \"text/html\"\n    assert \"text/html\" == resp.headers[\"content-type\"]\n\n\ndef test_setting_charset() -> None:\n    resp = StreamResponse()\n\n    resp.content_type = \"text/html\"\n    resp.charset = \"koi8-r\"\n    assert \"text/html; charset=koi8-r\" == resp.headers[\"content-type\"]\n\n\ndef test_default_charset() -> None:\n    resp = StreamResponse()\n\n    assert resp.charset is None\n\n\ndef test_reset_charset() -> None:\n    resp = StreamResponse()\n\n    resp.content_type = \"text/html\"\n    resp.charset = None\n    assert resp.charset is None\n\n\ndef test_reset_charset_after_setting() -> None:\n    resp = StreamResponse()\n\n    resp.content_type = \"text/html\"\n    resp.charset = \"koi8-r\"\n    resp.charset = None\n    assert resp.charset is None\n\n\ndef test_charset_without_content_type() -> None:\n    resp = StreamResponse()\n\n    with pytest.raises(RuntimeError):\n        resp.charset = \"koi8-r\"\n\n\ndef test_last_modified_initial() -> None:\n    resp = StreamResponse()\n    assert resp.last_modified is None\n\n\ndef test_last_modified_string() -> None:\n    resp = StreamResponse()\n\n    dt = datetime.datetime(1990, 1, 2, 3, 4, 5, 0, datetime.timezone.utc)\n    resp.last_modified = \"Mon, 2 Jan 1990 03:04:05 GMT\"\n    assert resp.last_modified == dt\n\n\ndef test_last_modified_timestamp() -> None:\n    resp = StreamResponse()\n\n    dt = datetime.datetime(1970, 1, 1, 0, 0, 0, 0, datetime.timezone.utc)\n\n    resp.last_modified = 0\n    assert resp.last_modified == dt\n\n    resp.last_modified = 0.0\n    assert resp.last_modified == dt\n\n\ndef test_last_modified_datetime() -> None:\n    resp = StreamResponse()\n\n    dt = datetime.datetime(2001, 2, 3, 4, 5, 6, 0, datetime.timezone.utc)\n    resp.last_modified = dt\n    assert resp.last_modified == dt\n\n\ndef test_last_modified_reset() -> None:\n    resp = StreamResponse()\n\n    resp.last_modified = 0\n    resp.last_modified = None\n    assert resp.last_modified is None\n\n\n@pytest.mark.parametrize(\n    [\"header_val\", \"expected\"],\n    [\n        pytest.param(\"xxyyzz\", None),\n        pytest.param(\"Tue, 08 Oct 4446413 00:56:40 GMT\", None),\n        pytest.param(\"Tue, 08 Oct 2000 00:56:80 GMT\", None),\n    ],\n)\ndef test_last_modified_string_invalid(header_val, expected) -> None:\n    resp = StreamResponse(headers={\"Last-Modified\": header_val})\n    assert resp.last_modified == expected\n\n\ndef test_etag_initial() -> None:\n    resp = StreamResponse()\n    assert resp.etag is None\n\n\ndef test_etag_string() -> None:\n    resp = StreamResponse()\n    value = \"0123-kotik\"\n    resp.etag = value\n    assert resp.etag == ETag(value=value)\n    assert resp.headers[hdrs.ETAG] == f'\"{value}\"'\n\n\n@pytest.mark.parametrize(\n    [\"etag\", \"expected_header\"],\n    (\n        (ETag(value=\"0123-weak-kotik\", is_weak=True), 'W/\"0123-weak-kotik\"'),\n        (ETag(value=\"0123-strong-kotik\", is_weak=False), '\"0123-strong-kotik\"'),\n    ),\n)\ndef test_etag_class(etag, expected_header) -> None:\n    resp = StreamResponse()\n    resp.etag = etag\n    assert resp.etag == etag\n    assert resp.headers[hdrs.ETAG] == expected_header\n\n\ndef test_etag_any() -> None:\n    resp = StreamResponse()\n    resp.etag = \"*\"\n    assert resp.etag == ETag(value=\"*\")\n    assert resp.headers[hdrs.ETAG] == \"*\"\n\n\n@pytest.mark.parametrize(\n    \"invalid_value\",\n    (\n        '\"invalid\"',\n        \"повинен бути ascii\",\n        ETag(value='\"invalid\"', is_weak=True),\n        ETag(value=\"bad ©®\"),\n    ),\n)\ndef test_etag_invalid_value_set(invalid_value) -> None:\n    resp = StreamResponse()\n    with pytest.raises(ValueError, match=\"is not a valid etag\"):\n        resp.etag = invalid_value\n\n\n@pytest.mark.parametrize(\n    \"header\",\n    (\n        \"forgotten quotes\",\n        '\"∀ x ∉ ascii\"',\n    ),\n)\ndef test_etag_invalid_value_get(header) -> None:\n    resp = StreamResponse()\n    resp.headers[\"ETag\"] = header\n    assert resp.etag is None\n\n\n@pytest.mark.parametrize(\"invalid\", (123, ETag(value=123, is_weak=True)))\ndef test_etag_invalid_value_class(invalid) -> None:\n    resp = StreamResponse()\n    with pytest.raises(ValueError, match=\"Unsupported etag type\"):\n        resp.etag = invalid\n\n\ndef test_etag_reset() -> None:\n    resp = StreamResponse()\n    resp.etag = \"*\"\n    resp.etag = None\n    assert resp.etag is None\n\n\nasync def test_start() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = StreamResponse()\n    assert resp.keep_alive is None\n\n    msg = await resp.prepare(req)\n\n    assert msg.write_headers.called\n    msg2 = await resp.prepare(req)\n    assert msg is msg2\n\n    assert resp.keep_alive\n\n    req2 = make_request(\"GET\", \"/\")\n    # with pytest.raises(RuntimeError):\n    msg3 = await resp.prepare(req2)\n    assert msg is msg3\n\n\nasync def test_chunked_encoding() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = StreamResponse()\n    assert not resp.chunked\n\n    resp.enable_chunked_encoding()\n    assert resp.chunked\n\n    msg = await resp.prepare(req)\n    assert msg.chunked\n\n\ndef test_enable_chunked_encoding_with_content_length() -> None:\n    resp = StreamResponse()\n\n    resp.content_length = 234\n    with pytest.raises(RuntimeError):\n        resp.enable_chunked_encoding()\n\n\nasync def test_chunk_size() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = StreamResponse()\n    assert not resp.chunked\n\n    with pytest.warns(DeprecationWarning):\n        resp.enable_chunked_encoding(chunk_size=8192)\n    assert resp.chunked\n\n    msg = await resp.prepare(req)\n    assert msg.chunked\n    assert msg.enable_chunking.called\n    assert msg.filter is not None\n\n\nasync def test_chunked_encoding_forbidden_for_http_10() -> None:\n    req = make_request(\"GET\", \"/\", version=HttpVersion10)\n    resp = StreamResponse()\n    resp.enable_chunked_encoding()\n\n    with pytest.raises(RuntimeError) as ctx:\n        await resp.prepare(req)\n    assert Matches(\"Using chunked encoding is forbidden for HTTP/1.0\") == str(ctx.value)\n\n\nasync def test_compression_no_accept() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = StreamResponse()\n    assert not resp.chunked\n\n    assert not resp.compression\n    resp.enable_compression()\n    assert resp.compression\n\n    msg = await resp.prepare(req)\n    assert not msg.enable_compression.called\n\n\nasync def test_force_compression_no_accept_backwards_compat() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = StreamResponse()\n    assert not resp.chunked\n\n    assert not resp.compression\n    with pytest.warns(DeprecationWarning):\n        resp.enable_compression(force=True)\n    assert resp.compression\n\n    msg = await resp.prepare(req)\n    assert msg.enable_compression.called\n    assert msg.filter is not None\n\n\nasync def test_force_compression_false_backwards_compat() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = StreamResponse()\n\n    assert not resp.compression\n    with pytest.warns(DeprecationWarning):\n        resp.enable_compression(force=False)\n    assert resp.compression\n\n    msg = await resp.prepare(req)\n    assert not msg.enable_compression.called\n\n\nasync def test_compression_default_coding() -> None:\n    req = make_request(\n        \"GET\", \"/\", headers=CIMultiDict({hdrs.ACCEPT_ENCODING: \"gzip, deflate\"})\n    )\n    resp = StreamResponse()\n    assert not resp.chunked\n\n    assert not resp.compression\n    resp.enable_compression()\n    assert resp.compression\n\n    msg = await resp.prepare(req)\n\n    msg.enable_compression.assert_called_with(\"deflate\", zlib.Z_DEFAULT_STRATEGY)\n    assert \"deflate\" == resp.headers.get(hdrs.CONTENT_ENCODING)\n    assert msg.filter is not None\n\n\nasync def test_force_compression_deflate() -> None:\n    req = make_request(\n        \"GET\", \"/\", headers=CIMultiDict({hdrs.ACCEPT_ENCODING: \"gzip, deflate\"})\n    )\n    resp = StreamResponse()\n\n    resp.enable_compression(ContentCoding.deflate)\n    assert resp.compression\n\n    msg = await resp.prepare(req)\n    msg.enable_compression.assert_called_with(\"deflate\", zlib.Z_DEFAULT_STRATEGY)\n    assert \"deflate\" == resp.headers.get(hdrs.CONTENT_ENCODING)\n\n\nasync def test_force_compression_no_accept_deflate() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = StreamResponse()\n\n    resp.enable_compression(ContentCoding.deflate)\n    assert resp.compression\n\n    msg = await resp.prepare(req)\n    msg.enable_compression.assert_called_with(\"deflate\", zlib.Z_DEFAULT_STRATEGY)\n    assert \"deflate\" == resp.headers.get(hdrs.CONTENT_ENCODING)\n\n\nasync def test_force_compression_gzip() -> None:\n    req = make_request(\n        \"GET\", \"/\", headers=CIMultiDict({hdrs.ACCEPT_ENCODING: \"gzip, deflate\"})\n    )\n    resp = StreamResponse()\n\n    resp.enable_compression(ContentCoding.gzip)\n    assert resp.compression\n\n    msg = await resp.prepare(req)\n    msg.enable_compression.assert_called_with(\"gzip\", zlib.Z_DEFAULT_STRATEGY)\n    assert \"gzip\" == resp.headers.get(hdrs.CONTENT_ENCODING)\n\n\nasync def test_force_compression_no_accept_gzip() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = StreamResponse()\n\n    resp.enable_compression(ContentCoding.gzip)\n    assert resp.compression\n\n    msg = await resp.prepare(req)\n    msg.enable_compression.assert_called_with(\"gzip\", zlib.Z_DEFAULT_STRATEGY)\n    assert \"gzip\" == resp.headers.get(hdrs.CONTENT_ENCODING)\n\n\nasync def test_change_content_threaded_compression_enabled() -> None:\n    req = make_request(\"GET\", \"/\")\n    body_thread_size = 1024\n    body = b\"answer\" * body_thread_size\n    resp = Response(body=body, zlib_executor_size=body_thread_size)\n    resp.enable_compression(ContentCoding.gzip)\n\n    await resp.prepare(req)\n    assert gzip.decompress(resp._compressed_body) == body\n\n\nasync def test_change_content_threaded_compression_enabled_explicit() -> None:\n    req = make_request(\"GET\", \"/\")\n    body_thread_size = 1024\n    body = b\"answer\" * body_thread_size\n    with ThreadPoolExecutor(1) as executor:\n        resp = Response(\n            body=body, zlib_executor_size=body_thread_size, zlib_executor=executor\n        )\n        resp.enable_compression(ContentCoding.gzip)\n\n        await resp.prepare(req)\n        assert gzip.decompress(resp._compressed_body) == body\n\n\nasync def test_change_content_length_if_compression_enabled() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = Response(body=b\"answer\")\n    resp.enable_compression(ContentCoding.gzip)\n\n    await resp.prepare(req)\n    assert resp.content_length is not None and resp.content_length != len(b\"answer\")\n\n\nasync def test_set_content_length_if_compression_enabled() -> None:\n    writer = mock.Mock()\n\n    async def write_headers(status_line, headers):\n        assert hdrs.CONTENT_LENGTH in headers\n        assert headers[hdrs.CONTENT_LENGTH] == \"26\"\n        assert hdrs.TRANSFER_ENCODING not in headers\n\n    writer.write_headers.side_effect = write_headers\n    req = make_request(\"GET\", \"/\", writer=writer)\n    resp = Response(body=b\"answer\")\n    resp.enable_compression(ContentCoding.gzip)\n\n    await resp.prepare(req)\n    assert resp.content_length == 26\n    del resp.headers[hdrs.CONTENT_LENGTH]\n    assert resp.content_length == 26\n\n\nasync def test_remove_content_length_if_compression_enabled_http11() -> None:\n    writer = mock.Mock()\n\n    async def write_headers(status_line, headers):\n        assert hdrs.CONTENT_LENGTH not in headers\n        assert headers.get(hdrs.TRANSFER_ENCODING, \"\") == \"chunked\"\n\n    writer.write_headers.side_effect = write_headers\n    req = make_request(\"GET\", \"/\", writer=writer)\n    resp = StreamResponse()\n    resp.content_length = 123\n    resp.enable_compression(ContentCoding.gzip)\n    await resp.prepare(req)\n    assert resp.content_length is None\n\n\nasync def test_remove_content_length_if_compression_enabled_http10() -> None:\n    writer = mock.Mock()\n\n    async def write_headers(status_line, headers):\n        assert hdrs.CONTENT_LENGTH not in headers\n        assert hdrs.TRANSFER_ENCODING not in headers\n\n    writer.write_headers.side_effect = write_headers\n    req = make_request(\"GET\", \"/\", version=HttpVersion10, writer=writer)\n    resp = StreamResponse()\n    resp.content_length = 123\n    resp.enable_compression(ContentCoding.gzip)\n    await resp.prepare(req)\n    assert resp.content_length is None\n\n\nasync def test_force_compression_identity() -> None:\n    writer = mock.Mock()\n\n    async def write_headers(status_line, headers):\n        assert hdrs.CONTENT_LENGTH in headers\n        assert hdrs.TRANSFER_ENCODING not in headers\n\n    writer.write_headers.side_effect = write_headers\n    req = make_request(\"GET\", \"/\", writer=writer)\n    resp = StreamResponse()\n    resp.content_length = 123\n    resp.enable_compression(ContentCoding.identity)\n    await resp.prepare(req)\n    assert resp.content_length == 123\n\n\nasync def test_force_compression_identity_response() -> None:\n    writer = mock.Mock()\n\n    async def write_headers(status_line, headers):\n        assert headers[hdrs.CONTENT_LENGTH] == \"6\"\n        assert hdrs.TRANSFER_ENCODING not in headers\n\n    writer.write_headers.side_effect = write_headers\n    req = make_request(\"GET\", \"/\", writer=writer)\n    resp = Response(body=b\"answer\")\n    resp.enable_compression(ContentCoding.identity)\n    await resp.prepare(req)\n    assert resp.content_length == 6\n\n\nasync def test_rm_content_length_if_compression_http11() -> None:\n    writer = mock.Mock()\n\n    async def write_headers(status_line, headers):\n        assert hdrs.CONTENT_LENGTH not in headers\n        assert headers.get(hdrs.TRANSFER_ENCODING, \"\") == \"chunked\"\n\n    writer.write_headers.side_effect = write_headers\n    req = make_request(\"GET\", \"/\", writer=writer)\n    payload = BytesPayload(b\"answer\", headers={\"X-Test-Header\": \"test\"})\n    resp = Response(body=payload)\n    resp.body = payload\n    resp.enable_compression(ContentCoding.gzip)\n    await resp.prepare(req)\n    assert resp.content_length is None\n\n\nasync def test_rm_content_length_if_compression_http10() -> None:\n    writer = mock.Mock()\n\n    async def write_headers(status_line, headers):\n        assert hdrs.CONTENT_LENGTH not in headers\n        assert hdrs.TRANSFER_ENCODING not in headers\n\n    writer.write_headers.side_effect = write_headers\n    req = make_request(\"GET\", \"/\", version=HttpVersion10, writer=writer)\n    resp = Response(body=BytesPayload(b\"answer\"))\n    resp.enable_compression(ContentCoding.gzip)\n    await resp.prepare(req)\n    assert resp.content_length is None\n\n\nasync def test_rm_content_length_if_204() -> None:\n    \"\"\"Ensure content-length is removed for 204 responses.\"\"\"\n    writer = mock.create_autospec(StreamWriter, spec_set=True, instance=True)\n\n    async def write_headers(status_line, headers):\n        assert hdrs.CONTENT_LENGTH not in headers\n\n    writer.write_headers.side_effect = write_headers\n    req = make_request(\"GET\", \"/\", writer=writer)\n    payload = BytesPayload(b\"answer\", headers={\"Content-Length\": \"6\"})\n    resp = Response(body=payload, status=204)\n    resp.body = payload\n    await resp.prepare(req)\n    assert resp.content_length is None\n\n\n@pytest.mark.parametrize(\"status\", (100, 101, 204, 304))\nasync def test_rm_transfer_encoding_rfc_9112_6_3_http_11(status: int) -> None:\n    \"\"\"Remove transfer encoding for RFC 9112 sec 6.3 with HTTP/1.1.\"\"\"\n    writer = mock.create_autospec(StreamWriter, spec_set=True, instance=True)\n    req = make_request(\"GET\", \"/\", version=HttpVersion11, writer=writer)\n    resp = Response(status=status, headers={hdrs.TRANSFER_ENCODING: \"chunked\"})\n    await resp.prepare(req)\n    assert resp.content_length == 0\n    assert not resp.chunked\n    assert hdrs.CONTENT_LENGTH not in resp.headers\n    assert hdrs.TRANSFER_ENCODING not in resp.headers\n\n\n@pytest.mark.parametrize(\"status\", (100, 101, 102, 204, 304))\nasync def test_rm_content_length_1xx_204_304_responses(status: int) -> None:\n    \"\"\"Remove content length for 1xx, 204, and 304 responses.\n\n    Content-Length is forbidden for 1xx and 204\n    https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.2\n\n    Content-Length is discouraged for 304.\n    https://datatracker.ietf.org/doc/html/rfc7232#section-4.1\n    \"\"\"\n    writer = mock.create_autospec(StreamWriter, spec_set=True, instance=True)\n    req = make_request(\"GET\", \"/\", version=HttpVersion11, writer=writer)\n    resp = Response(status=status, body=\"answer\")\n    await resp.prepare(req)\n    assert not resp.chunked\n    assert hdrs.CONTENT_LENGTH not in resp.headers\n    assert hdrs.TRANSFER_ENCODING not in resp.headers\n\n\nasync def test_head_response_keeps_content_length_of_original_body() -> None:\n    \"\"\"Verify HEAD response keeps the content length of the original body HTTP/1.1.\"\"\"\n    writer = mock.create_autospec(StreamWriter, spec_set=True, instance=True)\n    req = make_request(\"HEAD\", \"/\", version=HttpVersion11, writer=writer)\n    resp = Response(status=200, body=b\"answer\")\n    await resp.prepare(req)\n    assert resp.content_length == 6\n    assert not resp.chunked\n    assert resp.headers[hdrs.CONTENT_LENGTH] == \"6\"\n    assert hdrs.TRANSFER_ENCODING not in resp.headers\n\n\nasync def test_head_response_omits_content_length_when_body_unset() -> None:\n    \"\"\"Verify HEAD response omits content-length body when its unset.\"\"\"\n    writer = mock.create_autospec(StreamWriter, spec_set=True, instance=True)\n    req = make_request(\"HEAD\", \"/\", version=HttpVersion11, writer=writer)\n    resp = Response(status=200)\n    await resp.prepare(req)\n    assert resp.content_length == 0\n    assert not resp.chunked\n    assert hdrs.CONTENT_LENGTH not in resp.headers\n    assert hdrs.TRANSFER_ENCODING not in resp.headers\n\n\nasync def test_304_response_omits_content_length_when_body_unset() -> None:\n    \"\"\"Verify 304 response omits content-length body when its unset.\"\"\"\n    writer = mock.create_autospec(StreamWriter, spec_set=True, instance=True)\n    req = make_request(\"GET\", \"/\", version=HttpVersion11, writer=writer)\n    resp = Response(status=304)\n    await resp.prepare(req)\n    assert resp.content_length == 0\n    assert not resp.chunked\n    assert hdrs.CONTENT_LENGTH not in resp.headers\n    assert hdrs.TRANSFER_ENCODING not in resp.headers\n\n\nasync def test_content_length_on_chunked() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = Response(body=b\"answer\")\n    assert resp.content_length == 6\n    resp.enable_chunked_encoding()\n    assert resp.content_length is None\n    await resp.prepare(req)\n\n\nasync def test_write_non_byteish() -> None:\n    resp = StreamResponse()\n    await resp.prepare(make_request(\"GET\", \"/\"))\n\n    with pytest.raises(AssertionError):\n        await resp.write(123)\n\n\nasync def test_write_before_start() -> None:\n    resp = StreamResponse()\n\n    with pytest.raises(RuntimeError):\n        await resp.write(b\"data\")\n\n\nasync def test_cannot_write_after_eof() -> None:\n    resp = StreamResponse()\n    req = make_request(\"GET\", \"/\")\n    await resp.prepare(req)\n\n    await resp.write(b\"data\")\n    await resp.write_eof()\n    req.writer.write.reset_mock()\n\n    with pytest.raises(RuntimeError):\n        await resp.write(b\"next data\")\n    assert not req.writer.write.called\n\n\nasync def test___repr___after_eof() -> None:\n    resp = StreamResponse()\n    await resp.prepare(make_request(\"GET\", \"/\"))\n\n    await resp.write(b\"data\")\n    await resp.write_eof()\n    resp_repr = repr(resp)\n    assert resp_repr == \"<StreamResponse OK eof>\"\n\n\nasync def test_cannot_write_eof_before_headers() -> None:\n    resp = StreamResponse()\n\n    with pytest.raises(AssertionError):\n        await resp.write_eof()\n\n\nasync def test_cannot_write_eof_twice() -> None:\n    resp = StreamResponse()\n    writer = mock.Mock()\n    resp_impl = await resp.prepare(make_request(\"GET\", \"/\"))\n    resp_impl.write = make_mocked_coro(None)\n    resp_impl.write_eof = make_mocked_coro(None)\n\n    await resp.write(b\"data\")\n    assert resp_impl.write.called\n\n    await resp.write_eof()\n\n    resp_impl.write.reset_mock()\n    await resp.write_eof()\n    assert not writer.write.called\n\n\ndef test_force_close() -> None:\n    resp = StreamResponse()\n\n    assert resp.keep_alive is None\n    resp.force_close()\n    assert resp.keep_alive is False\n\n\nasync def test_response_output_length() -> None:\n    resp = StreamResponse()\n    await resp.prepare(make_request(\"GET\", \"/\"))\n    with pytest.warns(DeprecationWarning):\n        assert resp.output_length\n\n\ndef test_response_cookies() -> None:\n    resp = StreamResponse()\n\n    assert resp.cookies == {}\n    assert str(resp.cookies) == \"\"\n\n    resp.set_cookie(\"name\", \"value\")\n    assert str(resp.cookies) == \"Set-Cookie: name=value; Path=/\"\n    resp.set_cookie(\"name\", \"other_value\")\n    assert str(resp.cookies) == \"Set-Cookie: name=other_value; Path=/\"\n\n    resp.cookies[\"name\"] = \"another_other_value\"\n    resp.cookies[\"name\"][\"max-age\"] = 10\n    assert (\n        str(resp.cookies) == \"Set-Cookie: name=another_other_value; Max-Age=10; Path=/\"\n    )\n\n    resp.del_cookie(\"name\")\n    expected = (\n        'Set-Cookie: name=(\"\")?; '\n        \"expires=Thu, 01 Jan 1970 00:00:00 GMT; Max-Age=0; Path=/\"\n    )\n    assert Matches(expected) == str(resp.cookies)\n\n    resp.set_cookie(\"name\", \"value\", domain=\"local.host\")\n    expected = \"Set-Cookie: name=value; Domain=local.host; Path=/\"\n    assert str(resp.cookies) == expected\n\n\ndef test_response_cookie_path() -> None:\n    resp = StreamResponse()\n\n    assert resp.cookies == {}\n\n    resp.set_cookie(\"name\", \"value\", path=\"/some/path\")\n    assert str(resp.cookies) == \"Set-Cookie: name=value; Path=/some/path\"\n    resp.set_cookie(\"name\", \"value\", expires=\"123\")\n    assert str(resp.cookies) == \"Set-Cookie: name=value; expires=123; Path=/\"\n    resp.set_cookie(\n        \"name\",\n        \"value\",\n        domain=\"example.com\",\n        path=\"/home\",\n        expires=\"123\",\n        max_age=\"10\",\n        secure=True,\n        httponly=True,\n        version=\"2.0\",\n        samesite=\"lax\",\n    )\n    assert (\n        str(resp.cookies).lower() == \"set-cookie: name=value; \"\n        \"domain=example.com; \"\n        \"expires=123; \"\n        \"httponly; \"\n        \"max-age=10; \"\n        \"path=/home; \"\n        \"samesite=lax; \"\n        \"secure; \"\n        \"version=2.0\"\n    )\n\n\ndef test_response_cookie__issue_del_cookie() -> None:\n    resp = StreamResponse()\n\n    assert resp.cookies == {}\n    assert str(resp.cookies) == \"\"\n\n    resp.del_cookie(\"name\")\n    expected = (\n        'Set-Cookie: name=(\"\")?; '\n        \"expires=Thu, 01 Jan 1970 00:00:00 GMT; Max-Age=0; Path=/\"\n    )\n    assert Matches(expected) == str(resp.cookies)\n\n\ndef test_cookie_set_after_del() -> None:\n    resp = StreamResponse()\n\n    resp.del_cookie(\"name\")\n    resp.set_cookie(\"name\", \"val\")\n    # check for Max-Age dropped\n    expected = \"Set-Cookie: name=val; Path=/\"\n    assert str(resp.cookies) == expected\n\n\ndef test_set_status_with_reason() -> None:\n    resp = StreamResponse()\n\n    resp.set_status(200, \"Everything is fine!\")\n    assert 200 == resp.status\n    assert \"Everything is fine!\" == resp.reason\n\n\nasync def test_start_force_close() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = StreamResponse()\n    resp.force_close()\n    assert not resp.keep_alive\n\n    await resp.prepare(req)\n    assert not resp.keep_alive\n\n\nasync def test___repr__() -> None:\n    req = make_request(\"GET\", \"/path/to\")\n    resp = StreamResponse(reason=\"foo\")\n    await resp.prepare(req)\n    assert \"<StreamResponse foo GET /path/to >\" == repr(resp)\n\n\ndef test___repr___not_prepared() -> None:\n    resp = StreamResponse(reason=\"foo\")\n    assert \"<StreamResponse foo not prepared>\" == repr(resp)\n\n\nasync def test_keep_alive_http10_default() -> None:\n    req = make_request(\"GET\", \"/\", version=HttpVersion10)\n    resp = StreamResponse()\n    await resp.prepare(req)\n    assert not resp.keep_alive\n\n\nasync def test_keep_alive_http10_switched_on() -> None:\n    headers = CIMultiDict(Connection=\"keep-alive\")\n    req = make_request(\"GET\", \"/\", version=HttpVersion10, headers=headers)\n    req._message = req._message._replace(should_close=False)\n    resp = StreamResponse()\n    await resp.prepare(req)\n    assert resp.keep_alive\n\n\nasync def test_keep_alive_http09() -> None:\n    headers = CIMultiDict(Connection=\"keep-alive\")\n    req = make_request(\"GET\", \"/\", version=HttpVersion(0, 9), headers=headers)\n    resp = StreamResponse()\n    await resp.prepare(req)\n    assert not resp.keep_alive\n\n\nasync def test_prepare_twice() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = StreamResponse()\n\n    impl1 = await resp.prepare(req)\n    impl2 = await resp.prepare(req)\n    assert impl1 is impl2\n\n\nasync def test_prepare_calls_signal() -> None:\n    app = mock.Mock()\n    sig = make_mocked_coro()\n    on_response_prepare = aiosignal.Signal(app)\n    on_response_prepare.append(sig)\n    req = make_request(\"GET\", \"/\", app=app, on_response_prepare=on_response_prepare)\n    resp = StreamResponse()\n\n    await resp.prepare(req)\n\n    sig.assert_called_with(req, resp)\n\n\n# Response class\n\n\ndef test_response_ctor() -> None:\n    resp = Response()\n\n    assert 200 == resp.status\n    assert \"OK\" == resp.reason\n    assert resp.body is None\n    assert resp.content_length == 0\n    assert \"CONTENT-LENGTH\" not in resp.headers\n\n\nasync def test_ctor_with_headers_and_status() -> None:\n    resp = Response(body=b\"body\", status=201, headers={\"Age\": \"12\", \"DATE\": \"date\"})\n\n    assert 201 == resp.status\n    assert b\"body\" == resp.body\n    assert resp.headers[\"AGE\"] == \"12\"\n\n    req = make_mocked_request(\"GET\", \"/\")\n    await resp._start(req)\n    assert 4 == resp.content_length\n    assert resp.headers[\"CONTENT-LENGTH\"] == \"4\"\n\n\ndef test_ctor_content_type() -> None:\n    resp = Response(content_type=\"application/json\")\n\n    assert 200 == resp.status\n    assert \"OK\" == resp.reason\n    assert 0 == resp.content_length\n    assert CIMultiDict([(\"CONTENT-TYPE\", \"application/json\")]) == resp.headers\n\n\ndef test_ctor_text_body_combined() -> None:\n    with pytest.raises(ValueError):\n        Response(body=b\"123\", text=\"test text\")\n\n\nasync def test_ctor_text() -> None:\n    resp = Response(text=\"test text\")\n\n    assert 200 == resp.status\n    assert \"OK\" == resp.reason\n    assert 9 == resp.content_length\n    assert CIMultiDict([(\"CONTENT-TYPE\", \"text/plain; charset=utf-8\")]) == resp.headers\n\n    assert resp.body == b\"test text\"\n    assert resp.text == \"test text\"\n\n    resp.headers[\"DATE\"] = \"date\"\n    req = make_mocked_request(\"GET\", \"/\", version=HttpVersion11)\n    await resp._start(req)\n    assert resp.headers[\"CONTENT-LENGTH\"] == \"9\"\n\n\ndef test_ctor_charset() -> None:\n    resp = Response(text=\"текст\", charset=\"koi8-r\")\n\n    assert \"текст\".encode(\"koi8-r\") == resp.body\n    assert \"koi8-r\" == resp.charset\n\n\ndef test_ctor_charset_default_utf8() -> None:\n    resp = Response(text=\"test test\", charset=None)\n\n    assert \"utf-8\" == resp.charset\n\n\ndef test_ctor_charset_in_content_type() -> None:\n    with pytest.raises(ValueError):\n        Response(text=\"test test\", content_type=\"text/plain; charset=utf-8\")\n\n\ndef test_ctor_charset_without_text() -> None:\n    resp = Response(content_type=\"text/plain\", charset=\"koi8-r\")\n\n    assert \"koi8-r\" == resp.charset\n\n\ndef test_ctor_content_type_with_extra() -> None:\n    resp = Response(text=\"test test\", content_type=\"text/plain; version=0.0.4\")\n\n    assert resp.content_type == \"text/plain\"\n    assert resp.headers[\"content-type\"] == \"text/plain; version=0.0.4; charset=utf-8\"\n\n\ndef test_ctor_both_content_type_param_and_header_with_text() -> None:\n    with pytest.raises(ValueError):\n        Response(\n            headers={\"Content-Type\": \"application/json\"},\n            content_type=\"text/html\",\n            text=\"text\",\n        )\n\n\ndef test_ctor_both_charset_param_and_header_with_text() -> None:\n    with pytest.raises(ValueError):\n        Response(\n            headers={\"Content-Type\": \"application/json\"}, charset=\"koi8-r\", text=\"text\"\n        )\n\n\ndef test_ctor_both_content_type_param_and_header() -> None:\n    with pytest.raises(ValueError):\n        Response(headers={\"Content-Type\": \"application/json\"}, content_type=\"text/html\")\n\n\ndef test_ctor_both_charset_param_and_header() -> None:\n    with pytest.raises(ValueError):\n        Response(headers={\"Content-Type\": \"application/json\"}, charset=\"koi8-r\")\n\n\nasync def test_assign_nonbyteish_body() -> None:\n    resp = Response(body=b\"data\")\n\n    with pytest.raises(ValueError):\n        resp.body = 123\n    assert b\"data\" == resp.body\n    assert 4 == resp.content_length\n\n    resp.headers[\"DATE\"] = \"date\"\n    req = make_mocked_request(\"GET\", \"/\", version=HttpVersion11)\n    await resp._start(req)\n    assert resp.headers[\"CONTENT-LENGTH\"] == \"4\"\n    assert 4 == resp.content_length\n\n\ndef test_assign_nonstr_text() -> None:\n    resp = Response(text=\"test\")\n\n    with pytest.raises(AssertionError):\n        resp.text = b\"123\"\n    assert b\"test\" == resp.body\n    assert 4 == resp.content_length\n\n\nmpwriter = MultipartWriter(boundary=\"x\")\nmpwriter.append_payload(StringPayload(\"test\"))\n\n\nasync def async_iter() -> AsyncIterator[str]:\n    yield \"foo\"  # pragma: no cover\n\n\nclass CustomIO(io.IOBase):\n    def __init__(self):\n        self._lines = [b\"\", b\"\", b\"test\"]\n\n    def read(self, size: int = -1) -> bytes:\n        return self._lines.pop()\n\n\n@pytest.mark.parametrize(\n    \"payload,expected\",\n    (\n        (\"test\", \"test\"),\n        (CustomIO(), \"test\"),\n        (io.StringIO(\"test\"), \"test\"),\n        (io.TextIOWrapper(io.BytesIO(b\"test\")), \"test\"),\n        (io.BytesIO(b\"test\"), \"test\"),\n        (io.BufferedReader(io.BytesIO(b\"test\")), \"test\"),\n        (async_iter(), None),\n        (BodyPartReader(\"x\", CIMultiDictProxy(CIMultiDict()), mock.Mock()), None),\n        (\n            mpwriter,\n            \"--x\\nContent-Type: text/plain; charset=utf-8\\r\\nContent-Length: 4\\r\\n\\r\\ntest\",\n        ),\n    ),\n)\ndef test_payload_body_get_text(payload, expected: Optional[str]) -> None:\n    resp = Response(body=payload)\n    if expected is None:\n        with pytest.raises(TypeError):\n            resp.text\n    else:\n        assert resp.text == expected\n\n\ndef test_response_set_content_length() -> None:\n    resp = Response()\n    with pytest.raises(RuntimeError):\n        resp.content_length = 1\n\n\nasync def test_send_headers_for_empty_body(buf, writer) -> None:\n    req = make_request(\"GET\", \"/\", writer=writer)\n    resp = Response()\n\n    await resp.prepare(req)\n    await resp.write_eof()\n    txt = buf.decode(\"utf8\")\n    assert (\n        Matches(\n            \"HTTP/1.1 200 OK\\r\\n\"\n            \"Content-Length: 0\\r\\n\"\n            \"Date: .+\\r\\n\"\n            \"Server: .+\\r\\n\\r\\n\"\n        )\n        == txt\n    )\n\n\nasync def test_render_with_body(buf, writer) -> None:\n    req = make_request(\"GET\", \"/\", writer=writer)\n    resp = Response(body=b\"data\")\n\n    await resp.prepare(req)\n    await resp.write_eof()\n\n    txt = buf.decode(\"utf8\")\n    assert (\n        Matches(\n            \"HTTP/1.1 200 OK\\r\\n\"\n            \"Content-Length: 4\\r\\n\"\n            \"Content-Type: application/octet-stream\\r\\n\"\n            \"Date: .+\\r\\n\"\n            \"Server: .+\\r\\n\\r\\n\"\n            \"data\"\n        )\n        == txt\n    )\n\n\nasync def test_multiline_reason(buf, writer) -> None:\n    with pytest.raises(ValueError, match=r\"Reason cannot contain \\\\n\"):\n        Response(reason=\"Bad\\r\\nInjected-header: foo\")\n\n\nasync def test_send_set_cookie_header(buf, writer) -> None:\n    resp = Response()\n    resp.cookies[\"name\"] = \"value\"\n    req = make_request(\"GET\", \"/\", writer=writer)\n\n    await resp.prepare(req)\n    await resp.write_eof()\n\n    txt = buf.decode(\"utf8\")\n    assert (\n        Matches(\n            \"HTTP/1.1 200 OK\\r\\n\"\n            \"Content-Length: 0\\r\\n\"\n            \"Set-Cookie: name=value\\r\\n\"\n            \"Date: .+\\r\\n\"\n            \"Server: .+\\r\\n\\r\\n\"\n        )\n        == txt\n    )\n\n\nasync def test_consecutive_write_eof() -> None:\n    writer = mock.Mock()\n    writer.write_eof = make_mocked_coro()\n    writer.write_headers = make_mocked_coro()\n    req = make_request(\"GET\", \"/\", writer=writer)\n    data = b\"data\"\n    resp = Response(body=data)\n\n    await resp.prepare(req)\n    await resp.write_eof()\n    await resp.write_eof()\n    writer.write_eof.assert_called_once_with(data)\n\n\ndef test_set_text_with_content_type() -> None:\n    resp = Response()\n    resp.content_type = \"text/html\"\n    resp.text = \"text\"\n\n    assert \"text\" == resp.text\n    assert b\"text\" == resp.body\n    assert \"text/html\" == resp.content_type\n\n\ndef test_set_text_with_charset() -> None:\n    resp = Response()\n    resp.content_type = \"text/plain\"\n    resp.charset = \"KOI8-R\"\n    resp.text = \"текст\"\n\n    assert \"текст\" == resp.text\n    assert \"текст\".encode(\"koi8-r\") == resp.body\n    assert \"koi8-r\" == resp.charset\n\n\ndef test_default_content_type_in_stream_response() -> None:\n    resp = StreamResponse()\n    assert resp.content_type == \"application/octet-stream\"\n\n\ndef test_default_content_type_in_response() -> None:\n    resp = Response()\n    assert resp.content_type == \"application/octet-stream\"\n\n\ndef test_content_type_with_set_text() -> None:\n    resp = Response(text=\"text\")\n    assert resp.content_type == \"text/plain\"\n\n\ndef test_content_type_with_set_body() -> None:\n    resp = Response(body=b\"body\")\n    assert resp.content_type == \"application/octet-stream\"\n\n\ndef test_prepared_when_not_started() -> None:\n    resp = StreamResponse()\n    assert not resp.prepared\n\n\nasync def test_prepared_when_started() -> None:\n    resp = StreamResponse()\n    await resp.prepare(make_request(\"GET\", \"/\"))\n    assert resp.prepared\n\n\nasync def test_prepared_after_eof() -> None:\n    resp = StreamResponse()\n    await resp.prepare(make_request(\"GET\", \"/\"))\n    await resp.write(b\"data\")\n    await resp.write_eof()\n    assert resp.prepared\n\n\nasync def test_drain_before_start() -> None:\n    resp = StreamResponse()\n    with pytest.raises(AssertionError):\n        await resp.drain()\n\n\nasync def test_changing_status_after_prepare_raises() -> None:\n    resp = StreamResponse()\n    await resp.prepare(make_request(\"GET\", \"/\"))\n    with pytest.raises(AssertionError):\n        resp.set_status(400)\n\n\ndef test_nonstr_text_in_ctor() -> None:\n    with pytest.raises(TypeError):\n        Response(text=b\"data\")\n\n\ndef test_text_in_ctor_with_content_type() -> None:\n    resp = Response(text=\"data\", content_type=\"text/html\")\n    assert \"data\" == resp.text\n    assert \"text/html\" == resp.content_type\n\n\ndef test_text_in_ctor_with_content_type_header() -> None:\n    resp = Response(text=\"текст\", headers={\"Content-Type\": \"text/html; charset=koi8-r\"})\n    assert \"текст\".encode(\"koi8-r\") == resp.body\n    assert \"text/html\" == resp.content_type\n    assert \"koi8-r\" == resp.charset\n\n\ndef test_text_in_ctor_with_content_type_header_multidict() -> None:\n    headers = CIMultiDict({\"Content-Type\": \"text/html; charset=koi8-r\"})\n    resp = Response(text=\"текст\", headers=headers)\n    assert \"текст\".encode(\"koi8-r\") == resp.body\n    assert \"text/html\" == resp.content_type\n    assert \"koi8-r\" == resp.charset\n\n\ndef test_body_in_ctor_with_content_type_header_multidict() -> None:\n    headers = CIMultiDict({\"Content-Type\": \"text/html; charset=koi8-r\"})\n    resp = Response(body=\"текст\".encode(\"koi8-r\"), headers=headers)\n    assert \"текст\".encode(\"koi8-r\") == resp.body\n    assert \"text/html\" == resp.content_type\n    assert \"koi8-r\" == resp.charset\n\n\ndef test_text_with_empty_payload() -> None:\n    resp = Response(status=200)\n    assert resp.body is None\n    assert resp.text is None\n\n\ndef test_response_with_content_length_header_without_body() -> None:\n    resp = Response(headers={\"Content-Length\": 123})\n    assert resp.content_length == 123\n\n\ndef test_response_with_immutable_headers() -> None:\n    resp = Response(\n        text=\"text\", headers=CIMultiDictProxy(CIMultiDict({\"Header\": \"Value\"}))\n    )\n    assert resp.headers == {\n        \"Header\": \"Value\",\n        \"Content-Type\": \"text/plain; charset=utf-8\",\n    }\n\n\nasync def test_response_prepared_after_header_preparation() -> None:\n    req = make_request(\"GET\", \"/\")\n    resp = StreamResponse()\n    await resp.prepare(req)\n\n    assert type(resp.headers[\"Server\"]) is str\n\n    async def _strip_server(req, res):\n        assert \"Server\" in res.headers\n\n        if \"Server\" in res.headers:\n            del res.headers[\"Server\"]\n\n    app = mock.Mock()\n    sig = aiosignal.Signal(app)\n    sig.append(_strip_server)\n\n    req = make_request(\"GET\", \"/\", on_response_prepare=sig, app=app)\n    resp = StreamResponse()\n    await resp.prepare(req)\n\n    assert \"Server\" not in resp.headers\n\n\nclass TestJSONResponse:\n    def test_content_type_is_application_json_by_default(self) -> None:\n        resp = json_response(\"\")\n        assert \"application/json\" == resp.content_type\n\n    def test_passing_text_only(self) -> None:\n        resp = json_response(text=json.dumps(\"jaysawn\"))\n        assert resp.text == json.dumps(\"jaysawn\")\n\n    def test_data_and_text_raises_value_error(self) -> None:\n        with pytest.raises(ValueError) as excinfo:\n            json_response(data=\"foo\", text=\"bar\")\n        expected_message = \"only one of data, text, or body should be specified\"\n        assert expected_message == excinfo.value.args[0]\n\n    def test_data_and_body_raises_value_error(self) -> None:\n        with pytest.raises(ValueError) as excinfo:\n            json_response(data=\"foo\", body=b\"bar\")\n        expected_message = \"only one of data, text, or body should be specified\"\n        assert expected_message == excinfo.value.args[0]\n\n    def test_text_is_json_encoded(self) -> None:\n        resp = json_response({\"foo\": 42})\n        assert json.dumps({\"foo\": 42}) == resp.text\n\n    def test_content_type_is_overrideable(self) -> None:\n        resp = json_response({\"foo\": 42}, content_type=\"application/vnd.json+api\")\n        assert \"application/vnd.json+api\" == resp.content_type\n",
        "import asyncio\nimport base64\nimport os\nimport socket\nimport ssl\nimport sys\nfrom hashlib import md5, sha1, sha256\nfrom pathlib import Path\nfrom tempfile import TemporaryDirectory\nfrom typing import Any\nfrom unittest import mock\nfrom uuid import uuid4\n\nimport pytest\n\nfrom aiohttp.client_proto import ResponseHandler\nfrom aiohttp.http import WS_KEY\nfrom aiohttp.test_utils import loop_context\n\ntry:\n    import trustme\n\n    # Check if the CA is available in runtime, MacOS on Py3.10 fails somehow\n    trustme.CA()\n\n    TRUSTME: bool = True\nexcept ImportError:\n    TRUSTME = False\n\npytest_plugins = [\"aiohttp.pytest_plugin\", \"pytester\"]\n\nIS_HPUX = sys.platform.startswith(\"hp-ux\")\nIS_LINUX = sys.platform.startswith(\"linux\")\n\n\n@pytest.fixture\ndef tls_certificate_authority():\n    if not TRUSTME:\n        pytest.xfail(\"trustme is not supported\")\n    return trustme.CA()\n\n\n@pytest.fixture\ndef tls_certificate(tls_certificate_authority):\n    return tls_certificate_authority.issue_cert(\n        \"localhost\",\n        \"xn--prklad-4va.localhost\",\n        \"127.0.0.1\",\n        \"::1\",\n    )\n\n\n@pytest.fixture\ndef ssl_ctx(tls_certificate):\n    ssl_ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)\n    tls_certificate.configure_cert(ssl_ctx)\n    return ssl_ctx\n\n\n@pytest.fixture\ndef client_ssl_ctx(tls_certificate_authority):\n    ssl_ctx = ssl.create_default_context(purpose=ssl.Purpose.SERVER_AUTH)\n    tls_certificate_authority.configure_trust(ssl_ctx)\n    return ssl_ctx\n\n\n@pytest.fixture\ndef tls_ca_certificate_pem_path(tls_certificate_authority):\n    with tls_certificate_authority.cert_pem.tempfile() as ca_cert_pem:\n        yield ca_cert_pem\n\n\n@pytest.fixture\ndef tls_certificate_pem_path(tls_certificate):\n    with tls_certificate.private_key_and_cert_chain_pem.tempfile() as cert_pem:\n        yield cert_pem\n\n\n@pytest.fixture\ndef tls_certificate_pem_bytes(tls_certificate):\n    return tls_certificate.cert_chain_pems[0].bytes()\n\n\n@pytest.fixture\ndef tls_certificate_fingerprint_sha256(tls_certificate_pem_bytes):\n    tls_cert_der = ssl.PEM_cert_to_DER_cert(tls_certificate_pem_bytes.decode())\n    return sha256(tls_cert_der).digest()\n\n\n@pytest.fixture\ndef unix_sockname(tmp_path, tmp_path_factory):\n    \"\"\"Generate an fs path to the UNIX domain socket for testing.\n\n    N.B. Different OS kernels have different fs path length limitations\n    for it. For Linux, it's 108, for HP-UX it's 92 (or higher) depending\n    on its version. For for most of the BSDs (Open, Free, macOS) it's\n    mostly 104 but sometimes it can be down to 100.\n\n    Ref: https://github.com/aio-libs/aiohttp/issues/3572\n    \"\"\"\n    if not hasattr(socket, \"AF_UNIX\"):\n        pytest.skip(\"requires UNIX sockets\")\n\n    max_sock_len = 92 if IS_HPUX else 108 if IS_LINUX else 100\n    \"\"\"Amount of bytes allocated for the UNIX socket path by OS kernel.\n\n    Ref: https://unix.stackexchange.com/a/367012/27133\n    \"\"\"\n\n    sock_file_name = \"unix.sock\"\n    unique_prefix = f\"{uuid4()!s}-\"\n    unique_prefix_len = len(unique_prefix.encode())\n\n    root_tmp_dir = Path(\"/tmp\").resolve()\n    os_tmp_dir = Path(os.getenv(\"TMPDIR\", \"/tmp\")).resolve()\n    original_base_tmp_path = Path(\n        str(tmp_path_factory.getbasetemp()),\n    ).resolve()\n\n    original_base_tmp_path_hash = md5(\n        str(original_base_tmp_path).encode(),\n    ).hexdigest()\n\n    def make_tmp_dir(base_tmp_dir):\n        return TemporaryDirectory(\n            dir=str(base_tmp_dir),\n            prefix=\"pt-\",\n            suffix=f\"-{original_base_tmp_path_hash!s}\",\n        )\n\n    def assert_sock_fits(sock_path):\n        sock_path_len = len(sock_path.encode())\n        # exit-check to verify that it's correct and simplify debugging\n        # in the future\n        assert sock_path_len <= max_sock_len, (\n            \"Suggested UNIX socket ({sock_path}) is {sock_path_len} bytes \"\n            \"long but the current kernel only has {max_sock_len} bytes \"\n            \"allocated to hold it so it must be shorter. \"\n            \"See https://github.com/aio-libs/aiohttp/issues/3572 \"\n            \"for more info.\"\n        ).format_map(locals())\n\n    paths = original_base_tmp_path, os_tmp_dir, root_tmp_dir\n    unique_paths = [p for n, p in enumerate(paths) if p not in paths[:n]]\n    paths_num = len(unique_paths)\n\n    for num, tmp_dir_path in enumerate(paths, 1):\n        with make_tmp_dir(tmp_dir_path) as tmpd:\n            tmpd = Path(tmpd).resolve()\n            sock_path = str(tmpd / sock_file_name)\n            sock_path_len = len(sock_path.encode())\n\n            if num >= paths_num:\n                # exit-check to verify that it's correct and simplify\n                # debugging in the future\n                assert_sock_fits(sock_path)\n\n            if sock_path_len <= max_sock_len:\n                if max_sock_len - sock_path_len >= unique_prefix_len:\n                    # If we're lucky to have extra space in the path,\n                    # let's also make it more unique\n                    sock_path = str(tmpd / \"\".join((unique_prefix, sock_file_name)))\n                    # Double-checking it:\n                    assert_sock_fits(sock_path)\n                yield sock_path\n                return\n\n\n@pytest.fixture\ndef pipe_name():\n    name = rf\"\\\\.\\pipe\\{uuid4().hex}\"\n    return name\n\n\n@pytest.fixture\ndef create_mocked_conn(loop: Any):\n    def _proto_factory(conn_closing_result=None, **kwargs):\n        proto = mock.create_autospec(ResponseHandler, **kwargs)\n        proto.closed = loop.create_future()\n        proto.closed.set_result(conn_closing_result)\n        return proto\n\n    yield _proto_factory\n\n\n@pytest.fixture\ndef selector_loop():\n    policy = asyncio.WindowsSelectorEventLoopPolicy()\n    asyncio.set_event_loop_policy(policy)\n\n    with loop_context(policy.new_event_loop) as _loop:\n        asyncio.set_event_loop(_loop)\n        yield _loop\n\n\n@pytest.fixture\ndef netrc_contents(\n    tmp_path: Path,\n    monkeypatch: pytest.MonkeyPatch,\n    request: pytest.FixtureRequest,\n):\n    \"\"\"\n    Prepare :file:`.netrc` with given contents.\n\n    Monkey-patches :envvar:`NETRC` to point to created file.\n    \"\"\"\n    netrc_contents = getattr(request, \"param\", None)\n\n    netrc_file_path = tmp_path / \".netrc\"\n    if netrc_contents is not None:\n        netrc_file_path.write_text(netrc_contents)\n\n    monkeypatch.setenv(\"NETRC\", str(netrc_file_path))\n\n    return netrc_file_path\n\n\n@pytest.fixture\ndef start_connection():\n    with mock.patch(\n        \"aiohttp.connector.aiohappyeyeballs.start_connection\",\n        autospec=True,\n        spec_set=True,\n    ) as start_connection_mock:\n        yield start_connection_mock\n\n\n@pytest.fixture\ndef key_data():\n    return os.urandom(16)\n\n\n@pytest.fixture\ndef key(key_data: Any):\n    return base64.b64encode(key_data)\n\n\n@pytest.fixture\ndef ws_key(key: Any):\n    return base64.b64encode(sha1(key + WS_KEY).digest()).decode()\n"
    ],
    "test_file_names": [
        "test_1.py",
        "test_2.py",
        "conftest.py"
    ],
    "setup_res_code": 0,
    "setup_res_stdout": "re-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/requirements/cython.txt\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/tools/gen.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/hdrs.py\n./tools/gen.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/_helpers.pyx\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/_http_parser.pyx\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/_http_writer.pyx\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/_websocket.pyx\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/_helpers.pyi\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/_cparser.pxd\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/_find_header.pxd\ncython -3 -o aiohttp/_helpers.c aiohttp/_helpers.pyx -I aiohttp -Werror\ncython -3 -o aiohttp/_http_parser.c aiohttp/_http_parser.pyx -I aiohttp -Werror\ncython -3 -o aiohttp/_http_writer.c aiohttp/_http_writer.pyx -I aiohttp -Werror\ncython -3 -o aiohttp/_websocket.c aiohttp/_websocket.pyx -I aiohttp -Werror\ncd vendor/llhttp; npm ci\n\n> llhttp@9.2.1 prepare\n> npm run clean && npm run build-ts\n\n\n> llhttp@9.2.1 clean\n> rm -rf lib && rm -rf test/tmp\n\n\n> llhttp@9.2.1 build-ts\n> tsc\n\n\nadded 213 packages, and audited 214 packages in 6s\n\n41 packages are looking for funding\n  run `npm fund` for details\n\n5 vulnerabilities (3 moderate, 2 high)\n\nTo address issues that do not require attention, run:\n  npm audit fix\n\nSome issues need review, and may require choosing\na different dependency.\n\nRun `npm audit` for details.\nmake -C vendor/llhttp generate\nmake[1]: Entering directory '/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/vendor/llhttp'\nnpx ts-node bin/generate.ts\nmake[1]: Leaving directory '/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/vendor/llhttp'\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/__init__.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/abc.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/base_protocol.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/client.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/client_exceptions.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/client_proto.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/client_reqrep.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/client_ws.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/compression_utils.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/connector.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/cookiejar.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/formdata.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/helpers.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/http.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/http_exceptions.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/http_parser.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/http_websocket.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/http_writer.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/locks.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/log.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/multipart.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/payload.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/payload_streamer.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/pytest_plugin.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/resolver.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/streams.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/tcp_helpers.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/test_utils.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/tracing.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/typedefs.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/web.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/web_app.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/web_exceptions.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/web_fileresponse.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/web_log.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/web_middlewares.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/web_protocol.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/web_request.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/web_response.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/web_routedef.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/web_runner.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/web_server.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/web_urldispatcher.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/web_ws.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/worker.py\nuv pip install -e . -c requirements/runtime-deps.txt\n",
    "setup_res_stderr": "Using CPython 3.9.21\nCreating virtual environment at: .venv\nActivate with: source .venv/bin/activate\nResolved 1 package in 2ms\nPrepared 1 package in 0.35ms\nInstalled 1 package in 15ms\n + pip==24.3.1\nResolved 3 packages in 7ms\nInstalled 3 packages in 21ms\n + cython==3.0.11\n + multidict==6.1.0\n + typing-extensions==4.12.2\nResolved 100 packages in 44ms\nUninstalled 1 package in 41ms\nInstalled 98 packages in 178ms\n + aiodns==3.2.0\n + aiohappyeyeballs==2.4.0\n + aiohttp-theme==0.1.6\n + aioredis==2.0.1\n + aiosignal==1.3.1\n + alabaster==0.7.13\n + annotated-types==0.7.0\n + async-timeout==4.0.3\n + attrs==24.2.0\n + babel==2.16.0\n + blockdiag==3.0.0\n + brotli==1.1.0\n + build==1.2.2\n + certifi==2024.8.30\n + cffi==1.17.1\n + cfgv==3.4.0\n + charset-normalizer==3.3.2\n + cherry-picker==2.2.0\n + click==8.1.7\n + coverage==7.6.1\n + cryptography==43.0.1\n + distlib==0.3.8\n + docutils==0.20.1\n + exceptiongroup==1.2.2\n + filelock==3.16.1\n + freezegun==1.5.1\n + frozenlist==1.4.1\n + funcparserlib==1.0.1\n + gidgethub==5.3.0\n + gunicorn==23.0.0\n + identify==2.6.1\n + idna==3.4\n + imagesize==1.4.1\n + importlib-metadata==8.5.0\n + importlib-resources==6.4.5\n + incremental==24.7.2\n + iniconfig==2.0.0\n + jinja2==3.1.4\n + markdown-it-py==3.0.0\n + markupsafe==2.1.5\n + mdurl==0.1.2\n + mypy==1.11.2\n + mypy-extensions==1.0.0\n + nodeenv==1.9.1\n + packaging==24.1\n + pillow==9.5.0\n - pip==24.3.1\n + pip==24.2\n + pip-tools==7.4.1\n + platformdirs==4.3.6\n + pluggy==1.5.0\n + pre-commit==3.5.0\n + proxy-py==2.4.7\n + pycares==4.4.0\n + pycparser==2.22\n + pydantic==2.9.2\n + pydantic-core==2.23.4\n + pygments==2.18.0\n + pyjwt==2.8.0\n + pyproject-hooks==1.1.0\n + pytest==8.3.3\n + pytest-cov==5.0.0\n + pytest-mock==3.14.0\n + python-dateutil==2.9.0.post0\n + python-on-whales==0.73.0\n + pyyaml==6.0.2\n + re-assert==1.1.0\n + regex==2024.9.11\n + requests==2.32.3\n + rich==13.8.1\n + setuptools==75.1.0\n + setuptools-git==1.2\n + shellingham==1.5.4\n + six==1.16.0\n + slotscheck==0.19.0\n + snowballstemmer==2.2.0\n + sphinx==7.1.2\n + sphinxcontrib-applehelp==1.0.4\n + sphinxcontrib-blockdiag==3.0.0\n + sphinxcontrib-devhelp==1.0.2\n + sphinxcontrib-htmlhelp==2.0.1\n + sphinxcontrib-jsmath==1.0.1\n + sphinxcontrib-qthelp==1.0.3\n + sphinxcontrib-serializinghtml==1.1.5\n + sphinxcontrib-towncrier==0.4.0a0\n + tomli==2.0.1\n + towncrier==23.11.0\n + tqdm==4.66.5\n + trustme==1.1.0\n + typer==0.12.5\n + uritemplate==4.1.1\n + urllib3==2.2.3\n + uvloop==0.20.0\n + virtualenv==20.26.5\n + wait-for-it==2.2.2\n + webcolors==24.8.0\n + wheel==0.44.0\n + yarl==1.11.1\n + zipp==3.20.2\nResolved 10 packages in 1.77s\nPrepared 1 package in 16.87s\nInstalled 1 package in 0.50ms\n + aiohttp==3.11.0.dev0 (from file:///home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b)\nResolved 25 packages in 16ms\nInstalled 5 packages in 5ms\n + async-generator==1.10\n + brotlipy==0.7.0\n + chardet==5.2.0\n + multdict==0.0.5\n + pytest-asyncio==0.25.1\n",
    "new_commit_res_code": 0,
    "new_commit_res_stdout": "============================= test session starts ==============================\nplatform linux -- Python 3.9.21, pytest-8.3.3, pluggy-1.5.0 -- /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/.venv/bin/python\ncachedir: .pytest_cache\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b\nconfigfile: setup.cfg\nplugins: cov-5.0.0, mock-3.14.0, asyncio-0.25.1\nasyncio: mode=strict, asyncio_default_fixture_loop_scope=None\ncollecting ... collected 178 items\n\nr2e_tests/test_1.py::test_all_http_exceptions_exported PASSED            [  0%]\nr2e_tests/test_1.py::test_HTTPOk PASSED                                  [  1%]\nr2e_tests/test_1.py::test_terminal_classes_has_status_code PASSED        [  1%]\nr2e_tests/test_1.py::test_HTTPFound PASSED                               [  2%]\nr2e_tests/test_1.py::test_HTTPFound_empty_location PASSED                [  2%]\nr2e_tests/test_1.py::test_HTTPFound_location_CRLF PASSED                 [  3%]\nr2e_tests/test_1.py::test_HTTPMethodNotAllowed PASSED                    [  3%]\nr2e_tests/test_1.py::test_override_body_with_text PASSED                 [  4%]\nr2e_tests/test_1.py::test_override_body_with_binary PASSED               [  5%]\nr2e_tests/test_1.py::test_default_body PASSED                            [  5%]\nr2e_tests/test_1.py::test_empty_body_204 PASSED                          [  6%]\nr2e_tests/test_1.py::test_empty_body_205 PASSED                          [  6%]\nr2e_tests/test_1.py::test_empty_body_304 PASSED                          [  7%]\nr2e_tests/test_1.py::test_no_link_451 PASSED                             [  7%]\nr2e_tests/test_1.py::test_link_none_451 PASSED                           [  8%]\nr2e_tests/test_1.py::test_link_empty_451 PASSED                          [  8%]\nr2e_tests/test_1.py::test_link_str_451 PASSED                            [  9%]\nr2e_tests/test_1.py::test_link_url_451 PASSED                            [ 10%]\nr2e_tests/test_1.py::test_link_CRLF_451 PASSED                           [ 10%]\nr2e_tests/test_1.py::test_HTTPException_retains_cause PASSED             [ 11%]\nr2e_tests/test_1.py::test_HTTPException_retains_cookie[pyloop] PASSED    [ 11%]\nr2e_tests/test_1.py::test_unicode_text_body_unauthorized PASSED          [ 12%]\nr2e_tests/test_1.py::test_multiline_reason PASSED                        [ 12%]\nr2e_tests/test_2.py::test_stream_response_ctor PASSED                    [ 13%]\nr2e_tests/test_2.py::test_stream_response_hashable PASSED                [ 14%]\nr2e_tests/test_2.py::test_stream_response_eq PASSED                      [ 14%]\nr2e_tests/test_2.py::test_stream_response_is_mutable_mapping PASSED      [ 15%]\nr2e_tests/test_2.py::test_stream_response_delitem PASSED                 [ 15%]\nr2e_tests/test_2.py::test_stream_response_len PASSED                     [ 16%]\nr2e_tests/test_2.py::test_request_iter PASSED                            [ 16%]\nr2e_tests/test_2.py::test_content_length PASSED                          [ 17%]\nr2e_tests/test_2.py::test_content_length_setter PASSED                   [ 17%]\nr2e_tests/test_2.py::test_content_length_setter_with_enable_chunked_encoding PASSED [ 18%]\nr2e_tests/test_2.py::test_drop_content_length_header_on_setting_len_to_None PASSED [ 19%]\nr2e_tests/test_2.py::test_set_content_length_to_None_on_non_set PASSED   [ 19%]\nr2e_tests/test_2.py::test_setting_content_type PASSED                    [ 20%]\nr2e_tests/test_2.py::test_setting_charset PASSED                         [ 20%]\nr2e_tests/test_2.py::test_default_charset PASSED                         [ 21%]\nr2e_tests/test_2.py::test_reset_charset PASSED                           [ 21%]\nr2e_tests/test_2.py::test_reset_charset_after_setting PASSED             [ 22%]\nr2e_tests/test_2.py::test_charset_without_content_type PASSED            [ 23%]\nr2e_tests/test_2.py::test_last_modified_initial PASSED                   [ 23%]\nr2e_tests/test_2.py::test_last_modified_string PASSED                    [ 24%]\nr2e_tests/test_2.py::test_last_modified_timestamp PASSED                 [ 24%]\nr2e_tests/test_2.py::test_last_modified_datetime PASSED                  [ 25%]\nr2e_tests/test_2.py::test_last_modified_reset PASSED                     [ 25%]\nr2e_tests/test_2.py::test_last_modified_string_invalid[xxyyzz-None] PASSED [ 26%]\nr2e_tests/test_2.py::test_last_modified_string_invalid[Tue, 08 Oct 4446413 00:56:40 GMT-None] PASSED [ 26%]\nr2e_tests/test_2.py::test_last_modified_string_invalid[Tue, 08 Oct 2000 00:56:80 GMT-None] PASSED [ 27%]\nr2e_tests/test_2.py::test_etag_initial PASSED                            [ 28%]\nr2e_tests/test_2.py::test_etag_string PASSED                             [ 28%]\nr2e_tests/test_2.py::test_etag_class[etag0-W/\"0123-weak-kotik\"] PASSED   [ 29%]\nr2e_tests/test_2.py::test_etag_class[etag1-\"0123-strong-kotik\"] PASSED   [ 29%]\nr2e_tests/test_2.py::test_etag_any PASSED                                [ 30%]\nr2e_tests/test_2.py::test_etag_invalid_value_set[\"invalid\"] PASSED       [ 30%]\nr2e_tests/test_2.py::test_etag_invalid_value_set[\\u043f\\u043e\\u0432\\u0438\\u043d\\u0435\\u043d \\u0431\\u0443\\u0442\\u0438 ascii] PASSED [ 31%]\nr2e_tests/test_2.py::test_etag_invalid_value_set[invalid_value2] PASSED  [ 32%]\nr2e_tests/test_2.py::test_etag_invalid_value_set[invalid_value3] PASSED  [ 32%]\nr2e_tests/test_2.py::test_etag_invalid_value_get[forgotten quotes] PASSED [ 33%]\nr2e_tests/test_2.py::test_etag_invalid_value_get[\"\\u2200 x \\u2209 ascii\"] PASSED [ 33%]\nr2e_tests/test_2.py::test_etag_invalid_value_class[123] PASSED           [ 34%]\nr2e_tests/test_2.py::test_etag_invalid_value_class[invalid1] PASSED      [ 34%]\nr2e_tests/test_2.py::test_etag_reset PASSED                              [ 35%]\nr2e_tests/test_2.py::test_start PASSED                                   [ 35%]\nr2e_tests/test_2.py::test_chunked_encoding PASSED                        [ 36%]\nr2e_tests/test_2.py::test_enable_chunked_encoding_with_content_length PASSED [ 37%]\nr2e_tests/test_2.py::test_chunk_size PASSED                              [ 37%]\nr2e_tests/test_2.py::test_chunked_encoding_forbidden_for_http_10 PASSED  [ 38%]\nr2e_tests/test_2.py::test_compression_no_accept PASSED                   [ 38%]\nr2e_tests/test_2.py::test_force_compression_no_accept_backwards_compat PASSED [ 39%]\nr2e_tests/test_2.py::test_force_compression_false_backwards_compat PASSED [ 39%]\nr2e_tests/test_2.py::test_compression_default_coding PASSED              [ 40%]\nr2e_tests/test_2.py::test_force_compression_deflate PASSED               [ 41%]\nr2e_tests/test_2.py::test_force_compression_no_accept_deflate PASSED     [ 41%]\nr2e_tests/test_2.py::test_force_compression_gzip PASSED                  [ 42%]\nr2e_tests/test_2.py::test_force_compression_no_accept_gzip PASSED        [ 42%]\nr2e_tests/test_2.py::test_change_content_threaded_compression_enabled PASSED [ 43%]\nr2e_tests/test_2.py::test_change_content_threaded_compression_enabled_explicit PASSED [ 43%]\nr2e_tests/test_2.py::test_change_content_length_if_compression_enabled PASSED [ 44%]\nr2e_tests/test_2.py::test_set_content_length_if_compression_enabled PASSED [ 44%]\nr2e_tests/test_2.py::test_remove_content_length_if_compression_enabled_http11 PASSED [ 45%]\nr2e_tests/test_2.py::test_remove_content_length_if_compression_enabled_http10 PASSED [ 46%]\nr2e_tests/test_2.py::test_force_compression_identity PASSED              [ 46%]\nr2e_tests/test_2.py::test_force_compression_identity_response PASSED     [ 47%]\nr2e_tests/test_2.py::test_rm_content_length_if_compression_http11 PASSED [ 47%]\nr2e_tests/test_2.py::test_rm_content_length_if_compression_http10 PASSED [ 48%]\nr2e_tests/test_2.py::test_rm_content_length_if_204 PASSED                [ 48%]\nr2e_tests/test_2.py::test_rm_transfer_encoding_rfc_9112_6_3_http_11[100] PASSED [ 49%]\nr2e_tests/test_2.py::test_rm_transfer_encoding_rfc_9112_6_3_http_11[101] PASSED [ 50%]\nr2e_tests/test_2.py::test_rm_transfer_encoding_rfc_9112_6_3_http_11[204] PASSED [ 50%]\nr2e_tests/test_2.py::test_rm_transfer_encoding_rfc_9112_6_3_http_11[304] PASSED [ 51%]\nr2e_tests/test_2.py::test_rm_content_length_1xx_204_304_responses[100] PASSED [ 51%]\nr2e_tests/test_2.py::test_rm_content_length_1xx_204_304_responses[101] PASSED [ 52%]\nr2e_tests/test_2.py::test_rm_content_length_1xx_204_304_responses[102] PASSED [ 52%]\nr2e_tests/test_2.py::test_rm_content_length_1xx_204_304_responses[204] PASSED [ 53%]\nr2e_tests/test_2.py::test_rm_content_length_1xx_204_304_responses[304] PASSED [ 53%]\nr2e_tests/test_2.py::test_head_response_keeps_content_length_of_original_body PASSED [ 54%]\nr2e_tests/test_2.py::test_head_response_omits_content_length_when_body_unset PASSED [ 55%]\nr2e_tests/test_2.py::test_304_response_omits_content_length_when_body_unset PASSED [ 55%]\nr2e_tests/test_2.py::test_content_length_on_chunked PASSED               [ 56%]\nr2e_tests/test_2.py::test_write_non_byteish PASSED                       [ 56%]\nr2e_tests/test_2.py::test_write_before_start PASSED                      [ 57%]\nr2e_tests/test_2.py::test_cannot_write_after_eof PASSED                  [ 57%]\nr2e_tests/test_2.py::test___repr___after_eof PASSED                      [ 58%]\nr2e_tests/test_2.py::test_cannot_write_eof_before_headers PASSED         [ 58%]\nr2e_tests/test_2.py::test_cannot_write_eof_twice PASSED                  [ 59%]\nr2e_tests/test_2.py::test_force_close PASSED                             [ 60%]\nr2e_tests/test_2.py::test_response_output_length PASSED                  [ 60%]\nr2e_tests/test_2.py::test_response_cookies PASSED                        [ 61%]\nr2e_tests/test_2.py::test_response_cookie_path PASSED                    [ 61%]\nr2e_tests/test_2.py::test_response_cookie__issue_del_cookie PASSED       [ 62%]\nr2e_tests/test_2.py::test_cookie_set_after_del PASSED                    [ 62%]\nr2e_tests/test_2.py::test_set_status_with_reason PASSED                  [ 63%]\nr2e_tests/test_2.py::test_start_force_close PASSED                       [ 64%]\nr2e_tests/test_2.py::test___repr__ PASSED                                [ 64%]\nr2e_tests/test_2.py::test___repr___not_prepared PASSED                   [ 65%]\nr2e_tests/test_2.py::test_keep_alive_http10_default PASSED               [ 65%]\nr2e_tests/test_2.py::test_keep_alive_http10_switched_on PASSED           [ 66%]\nr2e_tests/test_2.py::test_keep_alive_http09 PASSED                       [ 66%]\nr2e_tests/test_2.py::test_prepare_twice PASSED                           [ 67%]\nr2e_tests/test_2.py::test_prepare_calls_signal PASSED                    [ 67%]\nr2e_tests/test_2.py::test_response_ctor PASSED                           [ 68%]\nr2e_tests/test_2.py::test_ctor_with_headers_and_status PASSED            [ 69%]\nr2e_tests/test_2.py::test_ctor_content_type PASSED                       [ 69%]\nr2e_tests/test_2.py::test_ctor_text_body_combined PASSED                 [ 70%]\nr2e_tests/test_2.py::test_ctor_text PASSED                               [ 70%]\nr2e_tests/test_2.py::test_ctor_charset PASSED                            [ 71%]\nr2e_tests/test_2.py::test_ctor_charset_default_utf8 PASSED               [ 71%]\nr2e_tests/test_2.py::test_ctor_charset_in_content_type PASSED            [ 72%]\nr2e_tests/test_2.py::test_ctor_charset_without_text PASSED               [ 73%]\nr2e_tests/test_2.py::test_ctor_content_type_with_extra PASSED            [ 73%]\nr2e_tests/test_2.py::test_ctor_both_content_type_param_and_header_with_text PASSED [ 74%]\nr2e_tests/test_2.py::test_ctor_both_charset_param_and_header_with_text PASSED [ 74%]\nr2e_tests/test_2.py::test_ctor_both_content_type_param_and_header PASSED [ 75%]\nr2e_tests/test_2.py::test_ctor_both_charset_param_and_header PASSED      [ 75%]\nr2e_tests/test_2.py::test_assign_nonbyteish_body PASSED                  [ 76%]\nr2e_tests/test_2.py::test_assign_nonstr_text PASSED                      [ 76%]\nr2e_tests/test_2.py::test_payload_body_get_text[test-test] PASSED        [ 77%]\nr2e_tests/test_2.py::test_payload_body_get_text[payload1-test] PASSED    [ 78%]\nr2e_tests/test_2.py::test_payload_body_get_text[payload2-test] PASSED    [ 78%]\nr2e_tests/test_2.py::test_payload_body_get_text[payload3-test] PASSED    [ 79%]\nr2e_tests/test_2.py::test_payload_body_get_text[payload4-test] PASSED    [ 79%]\nr2e_tests/test_2.py::test_payload_body_get_text[payload5-test] PASSED    [ 80%]\nr2e_tests/test_2.py::test_payload_body_get_text[async_iter-None] PASSED  [ 80%]\nr2e_tests/test_2.py::test_payload_body_get_text[payload7-None] PASSED    [ 81%]\nr2e_tests/test_2.py::test_payload_body_get_text[payload8---x\\nContent-Type: text/plain; charset=utf-8\\r\\nContent-Length: 4\\r\\n\\r\\ntest] PASSED [ 82%]\nr2e_tests/test_2.py::test_response_set_content_length PASSED             [ 82%]\nr2e_tests/test_2.py::test_send_headers_for_empty_body PASSED             [ 83%]\nr2e_tests/test_2.py::test_render_with_body PASSED                        [ 83%]\nr2e_tests/test_2.py::test_multiline_reason PASSED                        [ 84%]\nr2e_tests/test_2.py::test_send_set_cookie_header PASSED                  [ 84%]\nr2e_tests/test_2.py::test_consecutive_write_eof PASSED                   [ 85%]\nr2e_tests/test_2.py::test_set_text_with_content_type PASSED              [ 85%]\nr2e_tests/test_2.py::test_set_text_with_charset PASSED                   [ 86%]\nr2e_tests/test_2.py::test_default_content_type_in_stream_response PASSED [ 87%]\nr2e_tests/test_2.py::test_default_content_type_in_response PASSED        [ 87%]\nr2e_tests/test_2.py::test_content_type_with_set_text PASSED              [ 88%]\nr2e_tests/test_2.py::test_content_type_with_set_body PASSED              [ 88%]\nr2e_tests/test_2.py::test_prepared_when_not_started PASSED               [ 89%]\nr2e_tests/test_2.py::test_prepared_when_started PASSED                   [ 89%]\nr2e_tests/test_2.py::test_prepared_after_eof PASSED                      [ 90%]\nr2e_tests/test_2.py::test_drain_before_start PASSED                      [ 91%]\nr2e_tests/test_2.py::test_changing_status_after_prepare_raises PASSED    [ 91%]\nr2e_tests/test_2.py::test_nonstr_text_in_ctor PASSED                     [ 92%]\nr2e_tests/test_2.py::test_text_in_ctor_with_content_type PASSED          [ 92%]\nr2e_tests/test_2.py::test_text_in_ctor_with_content_type_header PASSED   [ 93%]\nr2e_tests/test_2.py::test_text_in_ctor_with_content_type_header_multidict PASSED [ 93%]\nr2e_tests/test_2.py::test_body_in_ctor_with_content_type_header_multidict PASSED [ 94%]\nr2e_tests/test_2.py::test_text_with_empty_payload PASSED                 [ 94%]\nr2e_tests/test_2.py::test_response_with_content_length_header_without_body PASSED [ 95%]\nr2e_tests/test_2.py::test_response_with_immutable_headers PASSED         [ 96%]\nr2e_tests/test_2.py::test_response_prepared_after_header_preparation PASSED [ 96%]\nr2e_tests/test_2.py::TestJSONResponse::test_content_type_is_application_json_by_default PASSED [ 97%]\nr2e_tests/test_2.py::TestJSONResponse::test_passing_text_only PASSED     [ 97%]\nr2e_tests/test_2.py::TestJSONResponse::test_data_and_text_raises_value_error PASSED [ 98%]\nr2e_tests/test_2.py::TestJSONResponse::test_data_and_body_raises_value_error PASSED [ 98%]\nr2e_tests/test_2.py::TestJSONResponse::test_text_is_json_encoded PASSED  [ 99%]\nr2e_tests/test_2.py::TestJSONResponse::test_content_type_is_overrideable PASSED [100%]\n\n==================================== PASSES ====================================\n\n---------- coverage: platform linux, python 3.9.21-final-0 -----------\nName                                     Stmts   Miss Branch BrPart  Cover\n--------------------------------------------------------------------------\naiohttp/__init__.py                         27     10      2      0    59%\naiohttp/abc.py                              98      2      0      0    98%\naiohttp/base_protocol.py                    68     36     22      3    39%\naiohttp/client.py                          554    252    202     57    48%\naiohttp/client_exceptions.py               154     65     20      1    52%\naiohttp/client_proto.py                    163     53     56     19    60%\naiohttp/client_reqrep.py                   693    270    300     78    52%\naiohttp/client_ws.py                       264    211     82      1    16%\naiohttp/compression_utils.py                70     21     14      2    63%\naiohttp/connector.py                       761    420    323     52    37%\naiohttp/cookiejar.py                       255    128    118     24    44%\naiohttp/formdata.py                         97     79     46      0    13%\naiohttp/hdrs.py                             90      0      0      0   100%\naiohttp/helpers.py                         502    213    178     27    51%\naiohttp/http.py                             11      0      2      0   100%\naiohttp/http_exceptions.py                  50     20      4      0    56%\naiohttp/http_parser.py                     504    404    208      1    14%\naiohttp/http_websocket.py                  394    287    152      0    20%\naiohttp/http_writer.py                     119     45     50     13    53%\naiohttp/locks.py                            24     16      4      0    29%\naiohttp/log.py                               7      0      0      0   100%\naiohttp/multipart.py                       623    447    266     13    22%\naiohttp/payload.py                         237     61     58     13    70%\naiohttp/payload_streamer.py                 31     11      4      0    69%\naiohttp/pytest_plugin.py                   162     61     42      6    60%\naiohttp/resolver.py                         79     55     26      2    25%\naiohttp/streams.py                         398    211    146     25    40%\naiohttp/tcp_helpers.py                      19      2      6      3    80%\naiohttp/test_utils.py                      318     62     52     18    78%\naiohttp/tracing.py                         191     69     32      0    69%\naiohttp/typedefs.py                         24      0      0      0   100%\naiohttp/web.py                             122     84     52      0    23%\naiohttp/web_app.py                         294     99     82     20    60%\naiohttp/web_exceptions.py                  157      2      8      0    99%\naiohttp/web_fileresponse.py                160    126     52      0    18%\naiohttp/web_log.py                         102     37     20      2    58%\naiohttp/web_middlewares.py                  55     35     20      0    27%\naiohttp/web_protocol.py                    354    129    155     49    54%\naiohttp/web_request.py                     446    245    140      8    37%\naiohttp/web_response.py                    484     12    222     16    96%\naiohttp/web_routedef.py                    100     44     10      0    55%\naiohttp/web_runner.py                      213     72     36     11    62%\naiohttp/web_server.py                       42      6     12      2    78%\naiohttp/web_urldispatcher.py               743    381    161     21    43%\naiohttp/web_ws.py                          382    310    132      1    15%\naiohttp/worker.py                          126    126     30      0     0%\ntests/conftest.py                          131    131     16      0     0%\ntests/test_base_protocol.py                198    198      2      0     0%\ntests/test_circular_imports.py              29     29     13      0     0%\ntests/test_classbasedview.py                39     39      0      0     0%\ntests/test_client_connection.py             94     94      2      0     0%\ntests/test_client_exceptions.py            199    199     14      0     0%\ntests/test_client_fingerprint.py            59     59      0      0     0%\ntests/test_client_functional.py           2553   2553     86      0     0%\ntests/test_client_proto.py                  99     99      0      0     0%\ntests/test_client_request.py               808    808     18      0     0%\ntests/test_client_response.py              480    480      6      0     0%\ntests/test_client_session.py               566    566     29      0     0%\ntests/test_client_ws.py                    487    487      2      0     0%\ntests/test_client_ws_functional.py         788    788     32      0     0%\ntests/test_connector.py                   1703   1703     88      0     0%\ntests/test_cookiejar.py                    350    350     24      0     0%\ntests/test_flowcontrol_streams.py          100    100      0      0     0%\ntests/test_formdata.py                      81     81      6      0     0%\ntests/test_helpers.py                      470    470     24      0     0%\ntests/test_http_exceptions.py              109    109     10      0     0%\ntests/test_http_parser.py                 1088   1088     66      0     0%\ntests/test_http_writer.py                  182    182     10      0     0%\ntests/test_imports.py                       34     34      6      0     0%\ntests/test_locks.py                         39     39      0      0     0%\ntests/test_loop.py                          36     36      0      0     0%\ntests/test_multipart.py                    826    826     32      0     0%\ntests/test_multipart_helpers.py            446    446      0      0     0%\ntests/test_payload.py                       95     95      0      0     0%\ntests/test_proxy.py                        302    302      0      0     0%\ntests/test_proxy_functional.py             459    459     18      0     0%\ntests/test_pytest_plugin.py                 27     27      0      0     0%\ntests/test_resolver.py                     197    197     20      0     0%\ntests/test_route_def.py                    210    210      0      0     0%\ntests/test_run_app.py                      563    563     30      0     0%\ntests/test_streams.py                     1077   1077     38      0     0%\ntests/test_tcp_helpers.py                   52     52      2      0     0%\ntests/test_test_utils.py                   251    251      6      0     0%\ntests/test_tracing.py                       48     48      0      0     0%\ntests/test_urldispatch.py                  851    851     24      0     0%\ntests/test_web_app.py                      454    454      6      0     0%\ntests/test_web_cli.py                       75     75      0      0     0%\ntests/test_web_exceptions.py               179    179     22      0     0%\ntests/test_web_functional.py              1580   1580     36      0     0%\ntests/test_web_log.py                      116    116      2      0     0%\ntests/test_web_middleware.py               268    268     16      0     0%\ntests/test_web_request.py                  507    507      8      0     0%\ntests/test_web_request_handler.py           42     42      0      0     0%\ntests/test_web_response.py                 900    900      6      0     0%\ntests/test_web_runner.py                   151    151      4      0     0%\ntests/test_web_sendfile.py                  84     84      0      0     0%\ntests/test_web_sendfile_functional.py      655    655     18      0     0%\ntests/test_web_server.py                   162    162      0      0     0%\ntests/test_web_urldispatcher.py            517    517     24      0     0%\ntests/test_web_websocket.py                401    401      8      0     0%\ntests/test_web_websocket_functional.py     799    799     28      0     0%\ntests/test_websocket_handshake.py          152    152     12      0     0%\ntests/test_websocket_parser.py             300    300     12      0     0%\ntests/test_websocket_writer.py              95     95      6      0     0%\ntests/test_worker.py                       191    191      2      0     0%\n--------------------------------------------------------------------------\nTOTAL                                    34521  28973   4381    488    17%\n\n============================= slowest 10 durations =============================\n0.03s call     r2e_tests/test_2.py::test_rm_content_length_1xx_204_304_responses[102]\n0.03s call     r2e_tests/test_2.py::test_rm_content_length_1xx_204_304_responses[304]\n0.03s call     r2e_tests/test_2.py::test_write_non_byteish\n0.03s call     r2e_tests/test_2.py::test_head_response_omits_content_length_when_body_unset\n0.03s call     r2e_tests/test_2.py::test_rm_content_length_if_204\n0.03s call     r2e_tests/test_2.py::test_head_response_keeps_content_length_of_original_body\n0.03s call     r2e_tests/test_2.py::test_304_response_omits_content_length_when_body_unset\n0.03s call     r2e_tests/test_2.py::test_rm_content_length_1xx_204_304_responses[101]\n0.03s call     r2e_tests/test_2.py::test_rm_content_length_1xx_204_304_responses[204]\n0.03s call     r2e_tests/test_2.py::test_rm_content_length_1xx_204_304_responses[100]\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::test_all_http_exceptions_exported\nPASSED r2e_tests/test_1.py::test_HTTPOk\nPASSED r2e_tests/test_1.py::test_terminal_classes_has_status_code\nPASSED r2e_tests/test_1.py::test_HTTPFound\nPASSED r2e_tests/test_1.py::test_HTTPFound_empty_location\nPASSED r2e_tests/test_1.py::test_HTTPFound_location_CRLF\nPASSED r2e_tests/test_1.py::test_HTTPMethodNotAllowed\nPASSED r2e_tests/test_1.py::test_override_body_with_text\nPASSED r2e_tests/test_1.py::test_override_body_with_binary\nPASSED r2e_tests/test_1.py::test_default_body\nPASSED r2e_tests/test_1.py::test_empty_body_204\nPASSED r2e_tests/test_1.py::test_empty_body_205\nPASSED r2e_tests/test_1.py::test_empty_body_304\nPASSED r2e_tests/test_1.py::test_no_link_451\nPASSED r2e_tests/test_1.py::test_link_none_451\nPASSED r2e_tests/test_1.py::test_link_empty_451\nPASSED r2e_tests/test_1.py::test_link_str_451\nPASSED r2e_tests/test_1.py::test_link_url_451\nPASSED r2e_tests/test_1.py::test_link_CRLF_451\nPASSED r2e_tests/test_1.py::test_HTTPException_retains_cause\nPASSED r2e_tests/test_1.py::test_HTTPException_retains_cookie[pyloop]\nPASSED r2e_tests/test_1.py::test_unicode_text_body_unauthorized\nPASSED r2e_tests/test_1.py::test_multiline_reason\nPASSED r2e_tests/test_2.py::test_stream_response_ctor\nPASSED r2e_tests/test_2.py::test_stream_response_hashable\nPASSED r2e_tests/test_2.py::test_stream_response_eq\nPASSED r2e_tests/test_2.py::test_stream_response_is_mutable_mapping\nPASSED r2e_tests/test_2.py::test_stream_response_delitem\nPASSED r2e_tests/test_2.py::test_stream_response_len\nPASSED r2e_tests/test_2.py::test_request_iter\nPASSED r2e_tests/test_2.py::test_content_length\nPASSED r2e_tests/test_2.py::test_content_length_setter\nPASSED r2e_tests/test_2.py::test_content_length_setter_with_enable_chunked_encoding\nPASSED r2e_tests/test_2.py::test_drop_content_length_header_on_setting_len_to_None\nPASSED r2e_tests/test_2.py::test_set_content_length_to_None_on_non_set\nPASSED r2e_tests/test_2.py::test_setting_content_type\nPASSED r2e_tests/test_2.py::test_setting_charset\nPASSED r2e_tests/test_2.py::test_default_charset\nPASSED r2e_tests/test_2.py::test_reset_charset\nPASSED r2e_tests/test_2.py::test_reset_charset_after_setting\nPASSED r2e_tests/test_2.py::test_charset_without_content_type\nPASSED r2e_tests/test_2.py::test_last_modified_initial\nPASSED r2e_tests/test_2.py::test_last_modified_string\nPASSED r2e_tests/test_2.py::test_last_modified_timestamp\nPASSED r2e_tests/test_2.py::test_last_modified_datetime\nPASSED r2e_tests/test_2.py::test_last_modified_reset\nPASSED r2e_tests/test_2.py::test_last_modified_string_invalid[xxyyzz-None]\nPASSED r2e_tests/test_2.py::test_last_modified_string_invalid[Tue, 08 Oct 4446413 00:56:40 GMT-None]\nPASSED r2e_tests/test_2.py::test_last_modified_string_invalid[Tue, 08 Oct 2000 00:56:80 GMT-None]\nPASSED r2e_tests/test_2.py::test_etag_initial\nPASSED r2e_tests/test_2.py::test_etag_string\nPASSED r2e_tests/test_2.py::test_etag_class[etag0-W/\"0123-weak-kotik\"]\nPASSED r2e_tests/test_2.py::test_etag_class[etag1-\"0123-strong-kotik\"]\nPASSED r2e_tests/test_2.py::test_etag_any\nPASSED r2e_tests/test_2.py::test_etag_invalid_value_set[\"invalid\"]\nPASSED r2e_tests/test_2.py::test_etag_invalid_value_set[\\u043f\\u043e\\u0432\\u0438\\u043d\\u0435\\u043d \\u0431\\u0443\\u0442\\u0438 ascii]\nPASSED r2e_tests/test_2.py::test_etag_invalid_value_set[invalid_value2]\nPASSED r2e_tests/test_2.py::test_etag_invalid_value_set[invalid_value3]\nPASSED r2e_tests/test_2.py::test_etag_invalid_value_get[forgotten quotes]\nPASSED r2e_tests/test_2.py::test_etag_invalid_value_get[\"\\u2200 x \\u2209 ascii\"]\nPASSED r2e_tests/test_2.py::test_etag_invalid_value_class[123]\nPASSED r2e_tests/test_2.py::test_etag_invalid_value_class[invalid1]\nPASSED r2e_tests/test_2.py::test_etag_reset\nPASSED r2e_tests/test_2.py::test_start\nPASSED r2e_tests/test_2.py::test_chunked_encoding\nPASSED r2e_tests/test_2.py::test_enable_chunked_encoding_with_content_length\nPASSED r2e_tests/test_2.py::test_chunk_size\nPASSED r2e_tests/test_2.py::test_chunked_encoding_forbidden_for_http_10\nPASSED r2e_tests/test_2.py::test_compression_no_accept\nPASSED r2e_tests/test_2.py::test_force_compression_no_accept_backwards_compat\nPASSED r2e_tests/test_2.py::test_force_compression_false_backwards_compat\nPASSED r2e_tests/test_2.py::test_compression_default_coding\nPASSED r2e_tests/test_2.py::test_force_compression_deflate\nPASSED r2e_tests/test_2.py::test_force_compression_no_accept_deflate\nPASSED r2e_tests/test_2.py::test_force_compression_gzip\nPASSED r2e_tests/test_2.py::test_force_compression_no_accept_gzip\nPASSED r2e_tests/test_2.py::test_change_content_threaded_compression_enabled\nPASSED r2e_tests/test_2.py::test_change_content_threaded_compression_enabled_explicit\nPASSED r2e_tests/test_2.py::test_change_content_length_if_compression_enabled\nPASSED r2e_tests/test_2.py::test_set_content_length_if_compression_enabled\nPASSED r2e_tests/test_2.py::test_remove_content_length_if_compression_enabled_http11\nPASSED r2e_tests/test_2.py::test_remove_content_length_if_compression_enabled_http10\nPASSED r2e_tests/test_2.py::test_force_compression_identity\nPASSED r2e_tests/test_2.py::test_force_compression_identity_response\nPASSED r2e_tests/test_2.py::test_rm_content_length_if_compression_http11\nPASSED r2e_tests/test_2.py::test_rm_content_length_if_compression_http10\nPASSED r2e_tests/test_2.py::test_rm_content_length_if_204\nPASSED r2e_tests/test_2.py::test_rm_transfer_encoding_rfc_9112_6_3_http_11[100]\nPASSED r2e_tests/test_2.py::test_rm_transfer_encoding_rfc_9112_6_3_http_11[101]\nPASSED r2e_tests/test_2.py::test_rm_transfer_encoding_rfc_9112_6_3_http_11[204]\nPASSED r2e_tests/test_2.py::test_rm_transfer_encoding_rfc_9112_6_3_http_11[304]\nPASSED r2e_tests/test_2.py::test_rm_content_length_1xx_204_304_responses[100]\nPASSED r2e_tests/test_2.py::test_rm_content_length_1xx_204_304_responses[101]\nPASSED r2e_tests/test_2.py::test_rm_content_length_1xx_204_304_responses[102]\nPASSED r2e_tests/test_2.py::test_rm_content_length_1xx_204_304_responses[204]\nPASSED r2e_tests/test_2.py::test_rm_content_length_1xx_204_304_responses[304]\nPASSED r2e_tests/test_2.py::test_head_response_keeps_content_length_of_original_body\nPASSED r2e_tests/test_2.py::test_head_response_omits_content_length_when_body_unset\nPASSED r2e_tests/test_2.py::test_304_response_omits_content_length_when_body_unset\nPASSED r2e_tests/test_2.py::test_content_length_on_chunked\nPASSED r2e_tests/test_2.py::test_write_non_byteish\nPASSED r2e_tests/test_2.py::test_write_before_start\nPASSED r2e_tests/test_2.py::test_cannot_write_after_eof\nPASSED r2e_tests/test_2.py::test___repr___after_eof\nPASSED r2e_tests/test_2.py::test_cannot_write_eof_before_headers\nPASSED r2e_tests/test_2.py::test_cannot_write_eof_twice\nPASSED r2e_tests/test_2.py::test_force_close\nPASSED r2e_tests/test_2.py::test_response_output_length\nPASSED r2e_tests/test_2.py::test_response_cookies\nPASSED r2e_tests/test_2.py::test_response_cookie_path\nPASSED r2e_tests/test_2.py::test_response_cookie__issue_del_cookie\nPASSED r2e_tests/test_2.py::test_cookie_set_after_del\nPASSED r2e_tests/test_2.py::test_set_status_with_reason\nPASSED r2e_tests/test_2.py::test_start_force_close\nPASSED r2e_tests/test_2.py::test___repr__\nPASSED r2e_tests/test_2.py::test___repr___not_prepared\nPASSED r2e_tests/test_2.py::test_keep_alive_http10_default\nPASSED r2e_tests/test_2.py::test_keep_alive_http10_switched_on\nPASSED r2e_tests/test_2.py::test_keep_alive_http09\nPASSED r2e_tests/test_2.py::test_prepare_twice\nPASSED r2e_tests/test_2.py::test_prepare_calls_signal\nPASSED r2e_tests/test_2.py::test_response_ctor\nPASSED r2e_tests/test_2.py::test_ctor_with_headers_and_status\nPASSED r2e_tests/test_2.py::test_ctor_content_type\nPASSED r2e_tests/test_2.py::test_ctor_text_body_combined\nPASSED r2e_tests/test_2.py::test_ctor_text\nPASSED r2e_tests/test_2.py::test_ctor_charset\nPASSED r2e_tests/test_2.py::test_ctor_charset_default_utf8\nPASSED r2e_tests/test_2.py::test_ctor_charset_in_content_type\nPASSED r2e_tests/test_2.py::test_ctor_charset_without_text\nPASSED r2e_tests/test_2.py::test_ctor_content_type_with_extra\nPASSED r2e_tests/test_2.py::test_ctor_both_content_type_param_and_header_with_text\nPASSED r2e_tests/test_2.py::test_ctor_both_charset_param_and_header_with_text\nPASSED r2e_tests/test_2.py::test_ctor_both_content_type_param_and_header\nPASSED r2e_tests/test_2.py::test_ctor_both_charset_param_and_header\nPASSED r2e_tests/test_2.py::test_assign_nonbyteish_body\nPASSED r2e_tests/test_2.py::test_assign_nonstr_text\nPASSED r2e_tests/test_2.py::test_payload_body_get_text[test-test]\nPASSED r2e_tests/test_2.py::test_payload_body_get_text[payload1-test]\nPASSED r2e_tests/test_2.py::test_payload_body_get_text[payload2-test]\nPASSED r2e_tests/test_2.py::test_payload_body_get_text[payload3-test]\nPASSED r2e_tests/test_2.py::test_payload_body_get_text[payload4-test]\nPASSED r2e_tests/test_2.py::test_payload_body_get_text[payload5-test]\nPASSED r2e_tests/test_2.py::test_payload_body_get_text[async_iter-None]\nPASSED r2e_tests/test_2.py::test_payload_body_get_text[payload7-None]\nPASSED r2e_tests/test_2.py::test_payload_body_get_text[payload8---x\\nContent-Type: text/plain; charset=utf-8\\r\\nContent-Length: 4\\r\\n\\r\\ntest]\nPASSED r2e_tests/test_2.py::test_response_set_content_length\nPASSED r2e_tests/test_2.py::test_send_headers_for_empty_body\nPASSED r2e_tests/test_2.py::test_render_with_body\nPASSED r2e_tests/test_2.py::test_multiline_reason\nPASSED r2e_tests/test_2.py::test_send_set_cookie_header\nPASSED r2e_tests/test_2.py::test_consecutive_write_eof\nPASSED r2e_tests/test_2.py::test_set_text_with_content_type\nPASSED r2e_tests/test_2.py::test_set_text_with_charset\nPASSED r2e_tests/test_2.py::test_default_content_type_in_stream_response\nPASSED r2e_tests/test_2.py::test_default_content_type_in_response\nPASSED r2e_tests/test_2.py::test_content_type_with_set_text\nPASSED r2e_tests/test_2.py::test_content_type_with_set_body\nPASSED r2e_tests/test_2.py::test_prepared_when_not_started\nPASSED r2e_tests/test_2.py::test_prepared_when_started\nPASSED r2e_tests/test_2.py::test_prepared_after_eof\nPASSED r2e_tests/test_2.py::test_drain_before_start\nPASSED r2e_tests/test_2.py::test_changing_status_after_prepare_raises\nPASSED r2e_tests/test_2.py::test_nonstr_text_in_ctor\nPASSED r2e_tests/test_2.py::test_text_in_ctor_with_content_type\nPASSED r2e_tests/test_2.py::test_text_in_ctor_with_content_type_header\nPASSED r2e_tests/test_2.py::test_text_in_ctor_with_content_type_header_multidict\nPASSED r2e_tests/test_2.py::test_body_in_ctor_with_content_type_header_multidict\nPASSED r2e_tests/test_2.py::test_text_with_empty_payload\nPASSED r2e_tests/test_2.py::test_response_with_content_length_header_without_body\nPASSED r2e_tests/test_2.py::test_response_with_immutable_headers\nPASSED r2e_tests/test_2.py::test_response_prepared_after_header_preparation\nPASSED r2e_tests/test_2.py::TestJSONResponse::test_content_type_is_application_json_by_default\nPASSED r2e_tests/test_2.py::TestJSONResponse::test_passing_text_only\nPASSED r2e_tests/test_2.py::TestJSONResponse::test_data_and_text_raises_value_error\nPASSED r2e_tests/test_2.py::TestJSONResponse::test_data_and_body_raises_value_error\nPASSED r2e_tests/test_2.py::TestJSONResponse::test_text_is_json_encoded\nPASSED r2e_tests/test_2.py::TestJSONResponse::test_content_type_is_overrideable\n============================= 178 passed in 7.03s ==============================\n",
    "new_commit_res_stderr": "/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/.venv/lib/python3.9/site-packages/pytest_asyncio/plugin.py:207: PytestDeprecationWarning: The configuration option \"asyncio_default_fixture_loop_scope\" is unset.\nThe event loop scope for asynchronous fixtures will default to the fixture caching scope. Future versions of pytest-asyncio will default the loop scope for asynchronous fixtures to function scope. Set the default fixture loop scope explicitly in order to avoid unexpected behavior in the future. Valid fixture loop scopes are: \"function\", \"class\", \"module\", \"package\", \"session\"\n\n  warnings.warn(PytestDeprecationWarning(_DEFAULT_FIXTURE_LOOP_SCOPE_UNSET))\n",
    "old_commit_res_code": 1,
    "old_commit_res_stdout": "============================= test session starts ==============================\nplatform linux -- Python 3.9.21, pytest-8.3.3, pluggy-1.5.0 -- /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/.venv/bin/python\ncachedir: .pytest_cache\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b\nconfigfile: setup.cfg\nplugins: cov-5.0.0, mock-3.14.0, asyncio-0.25.1\nasyncio: mode=strict, asyncio_default_fixture_loop_scope=None\ncollecting ... collected 178 items\n\nr2e_tests/test_1.py::test_all_http_exceptions_exported PASSED            [  0%]\nr2e_tests/test_1.py::test_HTTPOk PASSED                                  [  1%]\nr2e_tests/test_1.py::test_terminal_classes_has_status_code PASSED        [  1%]\nr2e_tests/test_1.py::test_HTTPFound PASSED                               [  2%]\nr2e_tests/test_1.py::test_HTTPFound_empty_location PASSED                [  2%]\nr2e_tests/test_1.py::test_HTTPFound_location_CRLF PASSED                 [  3%]\nr2e_tests/test_1.py::test_HTTPMethodNotAllowed PASSED                    [  3%]\nr2e_tests/test_1.py::test_override_body_with_text PASSED                 [  4%]\nr2e_tests/test_1.py::test_override_body_with_binary PASSED               [  5%]\nr2e_tests/test_1.py::test_default_body PASSED                            [  5%]\nr2e_tests/test_1.py::test_empty_body_204 PASSED                          [  6%]\nr2e_tests/test_1.py::test_empty_body_205 PASSED                          [  6%]\nr2e_tests/test_1.py::test_empty_body_304 PASSED                          [  7%]\nr2e_tests/test_1.py::test_no_link_451 PASSED                             [  7%]\nr2e_tests/test_1.py::test_link_none_451 PASSED                           [  8%]\nr2e_tests/test_1.py::test_link_empty_451 PASSED                          [  8%]\nr2e_tests/test_1.py::test_link_str_451 PASSED                            [  9%]\nr2e_tests/test_1.py::test_link_url_451 PASSED                            [ 10%]\nr2e_tests/test_1.py::test_link_CRLF_451 PASSED                           [ 10%]\nr2e_tests/test_1.py::test_HTTPException_retains_cause PASSED             [ 11%]\nr2e_tests/test_1.py::test_HTTPException_retains_cookie[pyloop] PASSED    [ 11%]\nr2e_tests/test_1.py::test_unicode_text_body_unauthorized PASSED          [ 12%]\nr2e_tests/test_1.py::test_multiline_reason FAILED                        [ 12%]\nr2e_tests/test_2.py::test_stream_response_ctor PASSED                    [ 13%]\nr2e_tests/test_2.py::test_stream_response_hashable PASSED                [ 14%]\nr2e_tests/test_2.py::test_stream_response_eq PASSED                      [ 14%]\nr2e_tests/test_2.py::test_stream_response_is_mutable_mapping PASSED      [ 15%]\nr2e_tests/test_2.py::test_stream_response_delitem PASSED                 [ 15%]\nr2e_tests/test_2.py::test_stream_response_len PASSED                     [ 16%]\nr2e_tests/test_2.py::test_request_iter PASSED                            [ 16%]\nr2e_tests/test_2.py::test_content_length PASSED                          [ 17%]\nr2e_tests/test_2.py::test_content_length_setter PASSED                   [ 17%]\nr2e_tests/test_2.py::test_content_length_setter_with_enable_chunked_encoding PASSED [ 18%]\nr2e_tests/test_2.py::test_drop_content_length_header_on_setting_len_to_None PASSED [ 19%]\nr2e_tests/test_2.py::test_set_content_length_to_None_on_non_set PASSED   [ 19%]\nr2e_tests/test_2.py::test_setting_content_type PASSED                    [ 20%]\nr2e_tests/test_2.py::test_setting_charset PASSED                         [ 20%]\nr2e_tests/test_2.py::test_default_charset PASSED                         [ 21%]\nr2e_tests/test_2.py::test_reset_charset PASSED                           [ 21%]\nr2e_tests/test_2.py::test_reset_charset_after_setting PASSED             [ 22%]\nr2e_tests/test_2.py::test_charset_without_content_type PASSED            [ 23%]\nr2e_tests/test_2.py::test_last_modified_initial PASSED                   [ 23%]\nr2e_tests/test_2.py::test_last_modified_string PASSED                    [ 24%]\nr2e_tests/test_2.py::test_last_modified_timestamp PASSED                 [ 24%]\nr2e_tests/test_2.py::test_last_modified_datetime PASSED                  [ 25%]\nr2e_tests/test_2.py::test_last_modified_reset PASSED                     [ 25%]\nr2e_tests/test_2.py::test_last_modified_string_invalid[xxyyzz-None] PASSED [ 26%]\nr2e_tests/test_2.py::test_last_modified_string_invalid[Tue, 08 Oct 4446413 00:56:40 GMT-None] PASSED [ 26%]\nr2e_tests/test_2.py::test_last_modified_string_invalid[Tue, 08 Oct 2000 00:56:80 GMT-None] PASSED [ 27%]\nr2e_tests/test_2.py::test_etag_initial PASSED                            [ 28%]\nr2e_tests/test_2.py::test_etag_string PASSED                             [ 28%]\nr2e_tests/test_2.py::test_etag_class[etag0-W/\"0123-weak-kotik\"] PASSED   [ 29%]\nr2e_tests/test_2.py::test_etag_class[etag1-\"0123-strong-kotik\"] PASSED   [ 29%]\nr2e_tests/test_2.py::test_etag_any PASSED                                [ 30%]\nr2e_tests/test_2.py::test_etag_invalid_value_set[\"invalid\"] PASSED       [ 30%]\nr2e_tests/test_2.py::test_etag_invalid_value_set[\\u043f\\u043e\\u0432\\u0438\\u043d\\u0435\\u043d \\u0431\\u0443\\u0442\\u0438 ascii] PASSED [ 31%]\nr2e_tests/test_2.py::test_etag_invalid_value_set[invalid_value2] PASSED  [ 32%]\nr2e_tests/test_2.py::test_etag_invalid_value_set[invalid_value3] PASSED  [ 32%]\nr2e_tests/test_2.py::test_etag_invalid_value_get[forgotten quotes] PASSED [ 33%]\nr2e_tests/test_2.py::test_etag_invalid_value_get[\"\\u2200 x \\u2209 ascii\"] PASSED [ 33%]\nr2e_tests/test_2.py::test_etag_invalid_value_class[123] PASSED           [ 34%]\nr2e_tests/test_2.py::test_etag_invalid_value_class[invalid1] PASSED      [ 34%]\nr2e_tests/test_2.py::test_etag_reset PASSED                              [ 35%]\nr2e_tests/test_2.py::test_start PASSED                                   [ 35%]\nr2e_tests/test_2.py::test_chunked_encoding PASSED                        [ 36%]\nr2e_tests/test_2.py::test_enable_chunked_encoding_with_content_length PASSED [ 37%]\nr2e_tests/test_2.py::test_chunk_size PASSED                              [ 37%]\nr2e_tests/test_2.py::test_chunked_encoding_forbidden_for_http_10 PASSED  [ 38%]\nr2e_tests/test_2.py::test_compression_no_accept PASSED                   [ 38%]\nr2e_tests/test_2.py::test_force_compression_no_accept_backwards_compat PASSED [ 39%]\nr2e_tests/test_2.py::test_force_compression_false_backwards_compat PASSED [ 39%]\nr2e_tests/test_2.py::test_compression_default_coding PASSED              [ 40%]\nr2e_tests/test_2.py::test_force_compression_deflate PASSED               [ 41%]\nr2e_tests/test_2.py::test_force_compression_no_accept_deflate PASSED     [ 41%]\nr2e_tests/test_2.py::test_force_compression_gzip PASSED                  [ 42%]\nr2e_tests/test_2.py::test_force_compression_no_accept_gzip PASSED        [ 42%]\nr2e_tests/test_2.py::test_change_content_threaded_compression_enabled PASSED [ 43%]\nr2e_tests/test_2.py::test_change_content_threaded_compression_enabled_explicit PASSED [ 43%]\nr2e_tests/test_2.py::test_change_content_length_if_compression_enabled PASSED [ 44%]\nr2e_tests/test_2.py::test_set_content_length_if_compression_enabled PASSED [ 44%]\nr2e_tests/test_2.py::test_remove_content_length_if_compression_enabled_http11 PASSED [ 45%]\nr2e_tests/test_2.py::test_remove_content_length_if_compression_enabled_http10 PASSED [ 46%]\nr2e_tests/test_2.py::test_force_compression_identity PASSED              [ 46%]\nr2e_tests/test_2.py::test_force_compression_identity_response PASSED     [ 47%]\nr2e_tests/test_2.py::test_rm_content_length_if_compression_http11 PASSED [ 47%]\nr2e_tests/test_2.py::test_rm_content_length_if_compression_http10 PASSED [ 48%]\nr2e_tests/test_2.py::test_rm_content_length_if_204 PASSED                [ 48%]\nr2e_tests/test_2.py::test_rm_transfer_encoding_rfc_9112_6_3_http_11[100] PASSED [ 49%]\nr2e_tests/test_2.py::test_rm_transfer_encoding_rfc_9112_6_3_http_11[101] PASSED [ 50%]\nr2e_tests/test_2.py::test_rm_transfer_encoding_rfc_9112_6_3_http_11[204] PASSED [ 50%]\nr2e_tests/test_2.py::test_rm_transfer_encoding_rfc_9112_6_3_http_11[304] PASSED [ 51%]\nr2e_tests/test_2.py::test_rm_content_length_1xx_204_304_responses[100] PASSED [ 51%]\nr2e_tests/test_2.py::test_rm_content_length_1xx_204_304_responses[101] PASSED [ 52%]\nr2e_tests/test_2.py::test_rm_content_length_1xx_204_304_responses[102] PASSED [ 52%]\nr2e_tests/test_2.py::test_rm_content_length_1xx_204_304_responses[204] PASSED [ 53%]\nr2e_tests/test_2.py::test_rm_content_length_1xx_204_304_responses[304] PASSED [ 53%]\nr2e_tests/test_2.py::test_head_response_keeps_content_length_of_original_body PASSED [ 54%]\nr2e_tests/test_2.py::test_head_response_omits_content_length_when_body_unset PASSED [ 55%]\nr2e_tests/test_2.py::test_304_response_omits_content_length_when_body_unset PASSED [ 55%]\nr2e_tests/test_2.py::test_content_length_on_chunked PASSED               [ 56%]\nr2e_tests/test_2.py::test_write_non_byteish PASSED                       [ 56%]\nr2e_tests/test_2.py::test_write_before_start PASSED                      [ 57%]\nr2e_tests/test_2.py::test_cannot_write_after_eof PASSED                  [ 57%]\nr2e_tests/test_2.py::test___repr___after_eof PASSED                      [ 58%]\nr2e_tests/test_2.py::test_cannot_write_eof_before_headers PASSED         [ 58%]\nr2e_tests/test_2.py::test_cannot_write_eof_twice PASSED                  [ 59%]\nr2e_tests/test_2.py::test_force_close PASSED                             [ 60%]\nr2e_tests/test_2.py::test_response_output_length PASSED                  [ 60%]\nr2e_tests/test_2.py::test_response_cookies PASSED                        [ 61%]\nr2e_tests/test_2.py::test_response_cookie_path PASSED                    [ 61%]\nr2e_tests/test_2.py::test_response_cookie__issue_del_cookie PASSED       [ 62%]\nr2e_tests/test_2.py::test_cookie_set_after_del PASSED                    [ 62%]\nr2e_tests/test_2.py::test_set_status_with_reason PASSED                  [ 63%]\nr2e_tests/test_2.py::test_start_force_close PASSED                       [ 64%]\nr2e_tests/test_2.py::test___repr__ PASSED                                [ 64%]\nr2e_tests/test_2.py::test___repr___not_prepared PASSED                   [ 65%]\nr2e_tests/test_2.py::test_keep_alive_http10_default PASSED               [ 65%]\nr2e_tests/test_2.py::test_keep_alive_http10_switched_on PASSED           [ 66%]\nr2e_tests/test_2.py::test_keep_alive_http09 PASSED                       [ 66%]\nr2e_tests/test_2.py::test_prepare_twice PASSED                           [ 67%]\nr2e_tests/test_2.py::test_prepare_calls_signal PASSED                    [ 67%]\nr2e_tests/test_2.py::test_response_ctor PASSED                           [ 68%]\nr2e_tests/test_2.py::test_ctor_with_headers_and_status PASSED            [ 69%]\nr2e_tests/test_2.py::test_ctor_content_type PASSED                       [ 69%]\nr2e_tests/test_2.py::test_ctor_text_body_combined PASSED                 [ 70%]\nr2e_tests/test_2.py::test_ctor_text PASSED                               [ 70%]\nr2e_tests/test_2.py::test_ctor_charset PASSED                            [ 71%]\nr2e_tests/test_2.py::test_ctor_charset_default_utf8 PASSED               [ 71%]\nr2e_tests/test_2.py::test_ctor_charset_in_content_type PASSED            [ 72%]\nr2e_tests/test_2.py::test_ctor_charset_without_text PASSED               [ 73%]\nr2e_tests/test_2.py::test_ctor_content_type_with_extra PASSED            [ 73%]\nr2e_tests/test_2.py::test_ctor_both_content_type_param_and_header_with_text PASSED [ 74%]\nr2e_tests/test_2.py::test_ctor_both_charset_param_and_header_with_text PASSED [ 74%]\nr2e_tests/test_2.py::test_ctor_both_content_type_param_and_header PASSED [ 75%]\nr2e_tests/test_2.py::test_ctor_both_charset_param_and_header PASSED      [ 75%]\nr2e_tests/test_2.py::test_assign_nonbyteish_body PASSED                  [ 76%]\nr2e_tests/test_2.py::test_assign_nonstr_text PASSED                      [ 76%]\nr2e_tests/test_2.py::test_payload_body_get_text[test-test] PASSED        [ 77%]\nr2e_tests/test_2.py::test_payload_body_get_text[payload1-test] PASSED    [ 78%]\nr2e_tests/test_2.py::test_payload_body_get_text[payload2-test] PASSED    [ 78%]\nr2e_tests/test_2.py::test_payload_body_get_text[payload3-test] PASSED    [ 79%]\nr2e_tests/test_2.py::test_payload_body_get_text[payload4-test] PASSED    [ 79%]\nr2e_tests/test_2.py::test_payload_body_get_text[payload5-test] PASSED    [ 80%]\nr2e_tests/test_2.py::test_payload_body_get_text[async_iter-None] PASSED  [ 80%]\nr2e_tests/test_2.py::test_payload_body_get_text[payload7-None] PASSED    [ 81%]\nr2e_tests/test_2.py::test_payload_body_get_text[payload8---x\\nContent-Type: text/plain; charset=utf-8\\r\\nContent-Length: 4\\r\\n\\r\\ntest] PASSED [ 82%]\nr2e_tests/test_2.py::test_response_set_content_length PASSED             [ 82%]\nr2e_tests/test_2.py::test_send_headers_for_empty_body PASSED             [ 83%]\nr2e_tests/test_2.py::test_render_with_body PASSED                        [ 83%]\nr2e_tests/test_2.py::test_multiline_reason FAILED                        [ 84%]\nr2e_tests/test_2.py::test_send_set_cookie_header FAILED                  [ 84%]\nr2e_tests/test_2.py::test_consecutive_write_eof PASSED                   [ 85%]\nr2e_tests/test_2.py::test_set_text_with_content_type PASSED              [ 85%]\nr2e_tests/test_2.py::test_set_text_with_charset PASSED                   [ 86%]\nr2e_tests/test_2.py::test_default_content_type_in_stream_response PASSED [ 87%]\nr2e_tests/test_2.py::test_default_content_type_in_response PASSED        [ 87%]\nr2e_tests/test_2.py::test_content_type_with_set_text PASSED              [ 88%]\nr2e_tests/test_2.py::test_content_type_with_set_body PASSED              [ 88%]\nr2e_tests/test_2.py::test_prepared_when_not_started PASSED               [ 89%]\nr2e_tests/test_2.py::test_prepared_when_started PASSED                   [ 89%]\nr2e_tests/test_2.py::test_prepared_after_eof PASSED                      [ 90%]\nr2e_tests/test_2.py::test_drain_before_start PASSED                      [ 91%]\nr2e_tests/test_2.py::test_changing_status_after_prepare_raises PASSED    [ 91%]\nr2e_tests/test_2.py::test_nonstr_text_in_ctor PASSED                     [ 92%]\nr2e_tests/test_2.py::test_text_in_ctor_with_content_type PASSED          [ 92%]\nr2e_tests/test_2.py::test_text_in_ctor_with_content_type_header PASSED   [ 93%]\nr2e_tests/test_2.py::test_text_in_ctor_with_content_type_header_multidict PASSED [ 93%]\nr2e_tests/test_2.py::test_body_in_ctor_with_content_type_header_multidict PASSED [ 94%]\nr2e_tests/test_2.py::test_text_with_empty_payload PASSED                 [ 94%]\nr2e_tests/test_2.py::test_response_with_content_length_header_without_body PASSED [ 95%]\nr2e_tests/test_2.py::test_response_with_immutable_headers PASSED         [ 96%]\nr2e_tests/test_2.py::test_response_prepared_after_header_preparation PASSED [ 96%]\nr2e_tests/test_2.py::TestJSONResponse::test_content_type_is_application_json_by_default PASSED [ 97%]\nr2e_tests/test_2.py::TestJSONResponse::test_passing_text_only PASSED     [ 97%]\nr2e_tests/test_2.py::TestJSONResponse::test_data_and_text_raises_value_error PASSED [ 98%]\nr2e_tests/test_2.py::TestJSONResponse::test_data_and_body_raises_value_error PASSED [ 98%]\nr2e_tests/test_2.py::TestJSONResponse::test_text_is_json_encoded PASSED  [ 99%]\nr2e_tests/test_2.py::TestJSONResponse::test_content_type_is_overrideable PASSED [100%]\n\n=================================== FAILURES ===================================\n____________________________ test_multiline_reason _____________________________\n\n    def test_multiline_reason() -> None:\n        with pytest.raises(ValueError, match=r\"Reason cannot contain \\\\n\"):\n>           web.HTTPOk(reason=\"Bad\\r\\nInjected-header: foo\")\nE           Failed: DID NOT RAISE <class 'ValueError'>\n\n\nr2e_tests/test_1.py:277: Failed\n____________________________ test_multiline_reason _____________________________\n\nbuf = bytearray(b''), writer = <Mock id='139650927597552'>\n\n    async def test_multiline_reason(buf, writer) -> None:\n        with pytest.raises(ValueError, match=r\"Reason cannot contain \\\\n\"):\n>           Response(reason=\"Bad\\r\\nInjected-header: foo\")\nE           Failed: DID NOT RAISE <class 'ValueError'>\n\nbuf        = bytearray(b'')\nwriter     = <Mock id='139650927597552'>\n\nr2e_tests/test_2.py:1231: Failed\n_________________________ test_send_set_cookie_header __________________________\n\ncls = <class '_pytest.runner.CallInfo'>\nfunc = <function call_and_report.<locals>.<lambda> at 0x7f03042e55e0>\nwhen = 'call'\nreraise = (<class '_pytest.outcomes.Exit'>, <class 'KeyboardInterrupt'>)\n\n    @classmethod\n    def from_call(\n        cls,\n        func: Callable[[], TResult],\n        when: Literal[\"collect\", \"setup\", \"call\", \"teardown\"],\n        reraise: type[BaseException] | tuple[type[BaseException], ...] | None = None,\n    ) -> CallInfo[TResult]:\n        \"\"\"Call func, wrapping the result in a CallInfo.\n    \n        :param func:\n            The function to call. Called without arguments.\n        :type func: Callable[[], _pytest.runner.TResult]\n        :param when:\n            The phase in which the function is called.\n        :param reraise:\n            Exception or exceptions that shall propagate if raised by the\n            function, instead of being wrapped in the CallInfo.\n        \"\"\"\n        excinfo = None\n        start = timing.time()\n        precise_start = timing.perf_counter()\n        try:\n>           result: TResult | None = func()\n\ncls        = <class '_pytest.runner.CallInfo'>\nduration   = 0.021480362003785558\nexcinfo    = <ExceptionInfo PytestUnraisableExceptionWarning('Exception ignored in: <socket.socket fd=-1, family=AddressFamily.AF_U...rning: unclosed <socket.socket fd=14, family=AddressFamily.AF_UNIX, type=SocketKind.SOCK_STREAM, proto=0>\\n') tblen=12>\nfunc       = <function call_and_report.<locals>.<lambda> at 0x7f03042e55e0>\nprecise_start = 94274.621653724\nprecise_stop = 94274.643134086\nreraise    = (<class '_pytest.outcomes.Exit'>, <class 'KeyboardInterrupt'>)\nresult     = None\nstart      = 1735795918.240466\nstop       = 1735795918.2619479\nwhen       = 'call'\n\n.venv/lib/python3.9/site-packages/_pytest/runner.py:341: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.venv/lib/python3.9/site-packages/_pytest/runner.py:242: in <lambda>\n    lambda: runtest_hook(item=item, **kwds), when=when, reraise=reraise\n        item       = <Function test_send_set_cookie_header>\n        kwds       = {}\n        runtest_hook = <HookCaller 'pytest_runtest_call'>\n.venv/lib/python3.9/site-packages/pluggy/_hooks.py:513: in __call__\n    return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult)\n        firstresult = False\n        kwargs     = {'item': <Function test_send_set_cookie_header>}\n        self       = <HookCaller 'pytest_runtest_call'>\n.venv/lib/python3.9/site-packages/pluggy/_manager.py:120: in _hookexec\n    return self._inner_hookexec(hook_name, methods, kwargs, firstresult)\n        firstresult = False\n        hook_name  = 'pytest_runtest_call'\n        kwargs     = {'item': <Function test_send_set_cookie_header>}\n        methods    = [<HookImpl plugin_name='runner', plugin=<module '_pytest.runner' from '/home/gcpuser/buckets/local_repoeval_bucket/rep...http_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/.venv/lib/python3.9/site-packages/_pytest/unraisableexception.py'>>, ...]\n        self       = <_pytest.config.PytestPluginManager object at 0x7f0306d23dc0>\n.venv/lib/python3.9/site-packages/_pytest/threadexception.py:92: in pytest_runtest_call\n    yield from thread_exception_runtest_hook()\n.venv/lib/python3.9/site-packages/_pytest/threadexception.py:68: in thread_exception_runtest_hook\n    yield\n        cm         = <_pytest.threadexception.catch_threading_exception object at 0x7f0303e1e910>\n.venv/lib/python3.9/site-packages/_pytest/unraisableexception.py:95: in pytest_runtest_call\n    yield from unraisable_exception_runtest_hook()\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\n    def unraisable_exception_runtest_hook() -> Generator[None]:\n        with catch_unraisable_exception() as cm:\n            try:\n                yield\n            finally:\n                if cm.unraisable:\n                    if cm.unraisable.err_msg is not None:\n                        err_msg = cm.unraisable.err_msg\n                    else:\n                        err_msg = \"Exception ignored in\"\n                    msg = f\"{err_msg}: {cm.unraisable.object!r}\\n\\n\"\n                    msg += \"\".join(\n                        traceback.format_exception(\n                            cm.unraisable.exc_type,\n                            cm.unraisable.exc_value,\n                            cm.unraisable.exc_traceback,\n                        )\n                    )\n>                   warnings.warn(pytest.PytestUnraisableExceptionWarning(msg))\nE                   pytest.PytestUnraisableExceptionWarning: Exception ignored in: <socket.socket fd=-1, family=AddressFamily.AF_UNIX, type=SocketKind.SOCK_STREAM, proto=0>\nE                   \nE                   Traceback (most recent call last):\nE                     File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/aiohttp/test_utils.py\", line 590, in teardown_test_loop\nE                       gc.collect()\nE                   ResourceWarning: unclosed <socket.socket fd=14, family=AddressFamily.AF_UNIX, type=SocketKind.SOCK_STREAM, proto=0>\n\ncm         = <_pytest.unraisableexception.catch_unraisable_exception object at 0x7f0303e1e9d0>\nerr_msg    = 'Exception ignored in'\nmsg        = 'Exception ignored in: <socket.socket fd=-1, family=AddressFamily.AF_UNIX, type=SocketKind.SOCK_STREAM, proto=0>\\n\\nTr...nResourceWarning: unclosed <socket.socket fd=14, family=AddressFamily.AF_UNIX, type=SocketKind.SOCK_STREAM, proto=0>\\n'\n\n.venv/lib/python3.9/site-packages/_pytest/unraisableexception.py:85: PytestUnraisableExceptionWarning\n==================================== PASSES ====================================\n\n---------- coverage: platform linux, python 3.9.21-final-0 -----------\nName                                     Stmts   Miss Branch BrPart  Cover\n--------------------------------------------------------------------------\naiohttp/__init__.py                         27     10      2      0    59%\naiohttp/abc.py                              98      2      0      0    98%\naiohttp/base_protocol.py                    68     36     22      3    39%\naiohttp/client.py                          554    252    202     57    48%\naiohttp/client_exceptions.py               154     65     20      1    52%\naiohttp/client_proto.py                    163     53     56     19    60%\naiohttp/client_reqrep.py                   693    270    300     78    52%\naiohttp/client_ws.py                       264    211     82      1    16%\naiohttp/compression_utils.py                70     21     14      2    63%\naiohttp/connector.py                       761    420    323     52    37%\naiohttp/cookiejar.py                       255    128    118     24    44%\naiohttp/formdata.py                         97     79     46      0    13%\naiohttp/hdrs.py                             90      0      0      0   100%\naiohttp/helpers.py                         502    213    178     27    51%\naiohttp/http.py                             11      0      2      0   100%\naiohttp/http_exceptions.py                  50     20      4      0    56%\naiohttp/http_parser.py                     504    404    208      1    14%\naiohttp/http_websocket.py                  394    287    152      0    20%\naiohttp/http_writer.py                     119     45     50     13    53%\naiohttp/locks.py                            24     16      4      0    29%\naiohttp/log.py                               7      0      0      0   100%\naiohttp/multipart.py                       623    447    266     13    22%\naiohttp/payload.py                         237     61     58     13    70%\naiohttp/payload_streamer.py                 31     11      4      0    69%\naiohttp/pytest_plugin.py                   162     60     42      6    61%\naiohttp/resolver.py                         79     55     26      2    25%\naiohttp/streams.py                         398    211    146     25    40%\naiohttp/tcp_helpers.py                      19      2      6      3    80%\naiohttp/test_utils.py                      318     62     52     18    78%\naiohttp/tracing.py                         191     69     32      0    69%\naiohttp/typedefs.py                         24      0      0      0   100%\naiohttp/web.py                             122     84     52      0    23%\naiohttp/web_app.py                         294     99     82     20    60%\naiohttp/web_exceptions.py                  157      2      8      0    99%\naiohttp/web_fileresponse.py                160    126     52      0    18%\naiohttp/web_log.py                         102     37     20      2    58%\naiohttp/web_middlewares.py                  55     35     20      0    27%\naiohttp/web_protocol.py                    354    129    155     49    54%\naiohttp/web_request.py                     446    245    140      8    37%\naiohttp/web_response.py                    482     12    220     16    96%\naiohttp/web_routedef.py                    100     44     10      0    55%\naiohttp/web_runner.py                      213     72     36     11    62%\naiohttp/web_server.py                       42      6     12      2    78%\naiohttp/web_urldispatcher.py               743    381    161     21    43%\naiohttp/web_ws.py                          382    310    132      1    15%\naiohttp/worker.py                          126    126     30      0     0%\ntests/conftest.py                          131    131     16      0     0%\ntests/test_base_protocol.py                198    198      2      0     0%\ntests/test_circular_imports.py              29     29     13      0     0%\ntests/test_classbasedview.py                39     39      0      0     0%\ntests/test_client_connection.py             94     94      2      0     0%\ntests/test_client_exceptions.py            199    199     14      0     0%\ntests/test_client_fingerprint.py            59     59      0      0     0%\ntests/test_client_functional.py           2553   2553     86      0     0%\ntests/test_client_proto.py                  99     99      0      0     0%\ntests/test_client_request.py               808    808     18      0     0%\ntests/test_client_response.py              480    480      6      0     0%\ntests/test_client_session.py               566    566     29      0     0%\ntests/test_client_ws.py                    487    487      2      0     0%\ntests/test_client_ws_functional.py         788    788     32      0     0%\ntests/test_connector.py                   1703   1703     88      0     0%\ntests/test_cookiejar.py                    350    350     24      0     0%\ntests/test_flowcontrol_streams.py          100    100      0      0     0%\ntests/test_formdata.py                      81     81      6      0     0%\ntests/test_helpers.py                      470    470     24      0     0%\ntests/test_http_exceptions.py              109    109     10      0     0%\ntests/test_http_parser.py                 1088   1088     66      0     0%\ntests/test_http_writer.py                  182    182     10      0     0%\ntests/test_imports.py                       34     34      6      0     0%\ntests/test_locks.py                         39     39      0      0     0%\ntests/test_loop.py                          36     36      0      0     0%\ntests/test_multipart.py                    826    826     32      0     0%\ntests/test_multipart_helpers.py            446    446      0      0     0%\ntests/test_payload.py                       95     95      0      0     0%\ntests/test_proxy.py                        302    302      0      0     0%\ntests/test_proxy_functional.py             459    459     18      0     0%\ntests/test_pytest_plugin.py                 27     27      0      0     0%\ntests/test_resolver.py                     197    197     20      0     0%\ntests/test_route_def.py                    210    210      0      0     0%\ntests/test_run_app.py                      563    563     30      0     0%\ntests/test_streams.py                     1077   1077     38      0     0%\ntests/test_tcp_helpers.py                   52     52      2      0     0%\ntests/test_test_utils.py                   251    251      6      0     0%\ntests/test_tracing.py                       48     48      0      0     0%\ntests/test_urldispatch.py                  851    851     24      0     0%\ntests/test_web_app.py                      454    454      6      0     0%\ntests/test_web_cli.py                       75     75      0      0     0%\ntests/test_web_exceptions.py               176    176     22      0     0%\ntests/test_web_functional.py              1580   1580     36      0     0%\ntests/test_web_log.py                      116    116      2      0     0%\ntests/test_web_middleware.py               268    268     16      0     0%\ntests/test_web_request.py                  507    507      8      0     0%\ntests/test_web_request_handler.py           42     42      0      0     0%\ntests/test_web_response.py                 897    897      6      0     0%\ntests/test_web_runner.py                   151    151      4      0     0%\ntests/test_web_sendfile.py                  84     84      0      0     0%\ntests/test_web_sendfile_functional.py      655    655     18      0     0%\ntests/test_web_server.py                   162    162      0      0     0%\ntests/test_web_urldispatcher.py            517    517     24      0     0%\ntests/test_web_websocket.py                401    401      8      0     0%\ntests/test_web_websocket_functional.py     799    799     28      0     0%\ntests/test_websocket_handshake.py          152    152     12      0     0%\ntests/test_websocket_parser.py             300    300     12      0     0%\ntests/test_websocket_writer.py              95     95      6      0     0%\ntests/test_worker.py                       191    191      2      0     0%\n--------------------------------------------------------------------------\nTOTAL                                    34513  28966   4379    488    17%\n\n============================= slowest 10 durations =============================\n0.06s call     r2e_tests/test_2.py::test_rm_content_length_1xx_204_304_responses[304]\n0.05s call     r2e_tests/test_2.py::test_rm_content_length_if_204\n0.04s call     r2e_tests/test_2.py::test_rm_transfer_encoding_rfc_9112_6_3_http_11[101]\n0.04s call     r2e_tests/test_2.py::test_rm_transfer_encoding_rfc_9112_6_3_http_11[304]\n0.04s call     r2e_tests/test_2.py::test_rm_transfer_encoding_rfc_9112_6_3_http_11[204]\n0.04s call     r2e_tests/test_2.py::test_rm_transfer_encoding_rfc_9112_6_3_http_11[100]\n0.03s call     r2e_tests/test_2.py::test_rm_content_length_1xx_204_304_responses[100]\n0.03s call     r2e_tests/test_2.py::test_head_response_keeps_content_length_of_original_body\n0.02s call     r2e_tests/test_2.py::test_head_response_omits_content_length_when_body_unset\n0.02s call     r2e_tests/test_2.py::test_rm_content_length_1xx_204_304_responses[204]\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::test_all_http_exceptions_exported\nPASSED r2e_tests/test_1.py::test_HTTPOk\nPASSED r2e_tests/test_1.py::test_terminal_classes_has_status_code\nPASSED r2e_tests/test_1.py::test_HTTPFound\nPASSED r2e_tests/test_1.py::test_HTTPFound_empty_location\nPASSED r2e_tests/test_1.py::test_HTTPFound_location_CRLF\nPASSED r2e_tests/test_1.py::test_HTTPMethodNotAllowed\nPASSED r2e_tests/test_1.py::test_override_body_with_text\nPASSED r2e_tests/test_1.py::test_override_body_with_binary\nPASSED r2e_tests/test_1.py::test_default_body\nPASSED r2e_tests/test_1.py::test_empty_body_204\nPASSED r2e_tests/test_1.py::test_empty_body_205\nPASSED r2e_tests/test_1.py::test_empty_body_304\nPASSED r2e_tests/test_1.py::test_no_link_451\nPASSED r2e_tests/test_1.py::test_link_none_451\nPASSED r2e_tests/test_1.py::test_link_empty_451\nPASSED r2e_tests/test_1.py::test_link_str_451\nPASSED r2e_tests/test_1.py::test_link_url_451\nPASSED r2e_tests/test_1.py::test_link_CRLF_451\nPASSED r2e_tests/test_1.py::test_HTTPException_retains_cause\nPASSED r2e_tests/test_1.py::test_HTTPException_retains_cookie[pyloop]\nPASSED r2e_tests/test_1.py::test_unicode_text_body_unauthorized\nPASSED r2e_tests/test_2.py::test_stream_response_ctor\nPASSED r2e_tests/test_2.py::test_stream_response_hashable\nPASSED r2e_tests/test_2.py::test_stream_response_eq\nPASSED r2e_tests/test_2.py::test_stream_response_is_mutable_mapping\nPASSED r2e_tests/test_2.py::test_stream_response_delitem\nPASSED r2e_tests/test_2.py::test_stream_response_len\nPASSED r2e_tests/test_2.py::test_request_iter\nPASSED r2e_tests/test_2.py::test_content_length\nPASSED r2e_tests/test_2.py::test_content_length_setter\nPASSED r2e_tests/test_2.py::test_content_length_setter_with_enable_chunked_encoding\nPASSED r2e_tests/test_2.py::test_drop_content_length_header_on_setting_len_to_None\nPASSED r2e_tests/test_2.py::test_set_content_length_to_None_on_non_set\nPASSED r2e_tests/test_2.py::test_setting_content_type\nPASSED r2e_tests/test_2.py::test_setting_charset\nPASSED r2e_tests/test_2.py::test_default_charset\nPASSED r2e_tests/test_2.py::test_reset_charset\nPASSED r2e_tests/test_2.py::test_reset_charset_after_setting\nPASSED r2e_tests/test_2.py::test_charset_without_content_type\nPASSED r2e_tests/test_2.py::test_last_modified_initial\nPASSED r2e_tests/test_2.py::test_last_modified_string\nPASSED r2e_tests/test_2.py::test_last_modified_timestamp\nPASSED r2e_tests/test_2.py::test_last_modified_datetime\nPASSED r2e_tests/test_2.py::test_last_modified_reset\nPASSED r2e_tests/test_2.py::test_last_modified_string_invalid[xxyyzz-None]\nPASSED r2e_tests/test_2.py::test_last_modified_string_invalid[Tue, 08 Oct 4446413 00:56:40 GMT-None]\nPASSED r2e_tests/test_2.py::test_last_modified_string_invalid[Tue, 08 Oct 2000 00:56:80 GMT-None]\nPASSED r2e_tests/test_2.py::test_etag_initial\nPASSED r2e_tests/test_2.py::test_etag_string\nPASSED r2e_tests/test_2.py::test_etag_class[etag0-W/\"0123-weak-kotik\"]\nPASSED r2e_tests/test_2.py::test_etag_class[etag1-\"0123-strong-kotik\"]\nPASSED r2e_tests/test_2.py::test_etag_any\nPASSED r2e_tests/test_2.py::test_etag_invalid_value_set[\"invalid\"]\nPASSED r2e_tests/test_2.py::test_etag_invalid_value_set[\\u043f\\u043e\\u0432\\u0438\\u043d\\u0435\\u043d \\u0431\\u0443\\u0442\\u0438 ascii]\nPASSED r2e_tests/test_2.py::test_etag_invalid_value_set[invalid_value2]\nPASSED r2e_tests/test_2.py::test_etag_invalid_value_set[invalid_value3]\nPASSED r2e_tests/test_2.py::test_etag_invalid_value_get[forgotten quotes]\nPASSED r2e_tests/test_2.py::test_etag_invalid_value_get[\"\\u2200 x \\u2209 ascii\"]\nPASSED r2e_tests/test_2.py::test_etag_invalid_value_class[123]\nPASSED r2e_tests/test_2.py::test_etag_invalid_value_class[invalid1]\nPASSED r2e_tests/test_2.py::test_etag_reset\nPASSED r2e_tests/test_2.py::test_start\nPASSED r2e_tests/test_2.py::test_chunked_encoding\nPASSED r2e_tests/test_2.py::test_enable_chunked_encoding_with_content_length\nPASSED r2e_tests/test_2.py::test_chunk_size\nPASSED r2e_tests/test_2.py::test_chunked_encoding_forbidden_for_http_10\nPASSED r2e_tests/test_2.py::test_compression_no_accept\nPASSED r2e_tests/test_2.py::test_force_compression_no_accept_backwards_compat\nPASSED r2e_tests/test_2.py::test_force_compression_false_backwards_compat\nPASSED r2e_tests/test_2.py::test_compression_default_coding\nPASSED r2e_tests/test_2.py::test_force_compression_deflate\nPASSED r2e_tests/test_2.py::test_force_compression_no_accept_deflate\nPASSED r2e_tests/test_2.py::test_force_compression_gzip\nPASSED r2e_tests/test_2.py::test_force_compression_no_accept_gzip\nPASSED r2e_tests/test_2.py::test_change_content_threaded_compression_enabled\nPASSED r2e_tests/test_2.py::test_change_content_threaded_compression_enabled_explicit\nPASSED r2e_tests/test_2.py::test_change_content_length_if_compression_enabled\nPASSED r2e_tests/test_2.py::test_set_content_length_if_compression_enabled\nPASSED r2e_tests/test_2.py::test_remove_content_length_if_compression_enabled_http11\nPASSED r2e_tests/test_2.py::test_remove_content_length_if_compression_enabled_http10\nPASSED r2e_tests/test_2.py::test_force_compression_identity\nPASSED r2e_tests/test_2.py::test_force_compression_identity_response\nPASSED r2e_tests/test_2.py::test_rm_content_length_if_compression_http11\nPASSED r2e_tests/test_2.py::test_rm_content_length_if_compression_http10\nPASSED r2e_tests/test_2.py::test_rm_content_length_if_204\nPASSED r2e_tests/test_2.py::test_rm_transfer_encoding_rfc_9112_6_3_http_11[100]\nPASSED r2e_tests/test_2.py::test_rm_transfer_encoding_rfc_9112_6_3_http_11[101]\nPASSED r2e_tests/test_2.py::test_rm_transfer_encoding_rfc_9112_6_3_http_11[204]\nPASSED r2e_tests/test_2.py::test_rm_transfer_encoding_rfc_9112_6_3_http_11[304]\nPASSED r2e_tests/test_2.py::test_rm_content_length_1xx_204_304_responses[100]\nPASSED r2e_tests/test_2.py::test_rm_content_length_1xx_204_304_responses[101]\nPASSED r2e_tests/test_2.py::test_rm_content_length_1xx_204_304_responses[102]\nPASSED r2e_tests/test_2.py::test_rm_content_length_1xx_204_304_responses[204]\nPASSED r2e_tests/test_2.py::test_rm_content_length_1xx_204_304_responses[304]\nPASSED r2e_tests/test_2.py::test_head_response_keeps_content_length_of_original_body\nPASSED r2e_tests/test_2.py::test_head_response_omits_content_length_when_body_unset\nPASSED r2e_tests/test_2.py::test_304_response_omits_content_length_when_body_unset\nPASSED r2e_tests/test_2.py::test_content_length_on_chunked\nPASSED r2e_tests/test_2.py::test_write_non_byteish\nPASSED r2e_tests/test_2.py::test_write_before_start\nPASSED r2e_tests/test_2.py::test_cannot_write_after_eof\nPASSED r2e_tests/test_2.py::test___repr___after_eof\nPASSED r2e_tests/test_2.py::test_cannot_write_eof_before_headers\nPASSED r2e_tests/test_2.py::test_cannot_write_eof_twice\nPASSED r2e_tests/test_2.py::test_force_close\nPASSED r2e_tests/test_2.py::test_response_output_length\nPASSED r2e_tests/test_2.py::test_response_cookies\nPASSED r2e_tests/test_2.py::test_response_cookie_path\nPASSED r2e_tests/test_2.py::test_response_cookie__issue_del_cookie\nPASSED r2e_tests/test_2.py::test_cookie_set_after_del\nPASSED r2e_tests/test_2.py::test_set_status_with_reason\nPASSED r2e_tests/test_2.py::test_start_force_close\nPASSED r2e_tests/test_2.py::test___repr__\nPASSED r2e_tests/test_2.py::test___repr___not_prepared\nPASSED r2e_tests/test_2.py::test_keep_alive_http10_default\nPASSED r2e_tests/test_2.py::test_keep_alive_http10_switched_on\nPASSED r2e_tests/test_2.py::test_keep_alive_http09\nPASSED r2e_tests/test_2.py::test_prepare_twice\nPASSED r2e_tests/test_2.py::test_prepare_calls_signal\nPASSED r2e_tests/test_2.py::test_response_ctor\nPASSED r2e_tests/test_2.py::test_ctor_with_headers_and_status\nPASSED r2e_tests/test_2.py::test_ctor_content_type\nPASSED r2e_tests/test_2.py::test_ctor_text_body_combined\nPASSED r2e_tests/test_2.py::test_ctor_text\nPASSED r2e_tests/test_2.py::test_ctor_charset\nPASSED r2e_tests/test_2.py::test_ctor_charset_default_utf8\nPASSED r2e_tests/test_2.py::test_ctor_charset_in_content_type\nPASSED r2e_tests/test_2.py::test_ctor_charset_without_text\nPASSED r2e_tests/test_2.py::test_ctor_content_type_with_extra\nPASSED r2e_tests/test_2.py::test_ctor_both_content_type_param_and_header_with_text\nPASSED r2e_tests/test_2.py::test_ctor_both_charset_param_and_header_with_text\nPASSED r2e_tests/test_2.py::test_ctor_both_content_type_param_and_header\nPASSED r2e_tests/test_2.py::test_ctor_both_charset_param_and_header\nPASSED r2e_tests/test_2.py::test_assign_nonbyteish_body\nPASSED r2e_tests/test_2.py::test_assign_nonstr_text\nPASSED r2e_tests/test_2.py::test_payload_body_get_text[test-test]\nPASSED r2e_tests/test_2.py::test_payload_body_get_text[payload1-test]\nPASSED r2e_tests/test_2.py::test_payload_body_get_text[payload2-test]\nPASSED r2e_tests/test_2.py::test_payload_body_get_text[payload3-test]\nPASSED r2e_tests/test_2.py::test_payload_body_get_text[payload4-test]\nPASSED r2e_tests/test_2.py::test_payload_body_get_text[payload5-test]\nPASSED r2e_tests/test_2.py::test_payload_body_get_text[async_iter-None]\nPASSED r2e_tests/test_2.py::test_payload_body_get_text[payload7-None]\nPASSED r2e_tests/test_2.py::test_payload_body_get_text[payload8---x\\nContent-Type: text/plain; charset=utf-8\\r\\nContent-Length: 4\\r\\n\\r\\ntest]\nPASSED r2e_tests/test_2.py::test_response_set_content_length\nPASSED r2e_tests/test_2.py::test_send_headers_for_empty_body\nPASSED r2e_tests/test_2.py::test_render_with_body\nPASSED r2e_tests/test_2.py::test_consecutive_write_eof\nPASSED r2e_tests/test_2.py::test_set_text_with_content_type\nPASSED r2e_tests/test_2.py::test_set_text_with_charset\nPASSED r2e_tests/test_2.py::test_default_content_type_in_stream_response\nPASSED r2e_tests/test_2.py::test_default_content_type_in_response\nPASSED r2e_tests/test_2.py::test_content_type_with_set_text\nPASSED r2e_tests/test_2.py::test_content_type_with_set_body\nPASSED r2e_tests/test_2.py::test_prepared_when_not_started\nPASSED r2e_tests/test_2.py::test_prepared_when_started\nPASSED r2e_tests/test_2.py::test_prepared_after_eof\nPASSED r2e_tests/test_2.py::test_drain_before_start\nPASSED r2e_tests/test_2.py::test_changing_status_after_prepare_raises\nPASSED r2e_tests/test_2.py::test_nonstr_text_in_ctor\nPASSED r2e_tests/test_2.py::test_text_in_ctor_with_content_type\nPASSED r2e_tests/test_2.py::test_text_in_ctor_with_content_type_header\nPASSED r2e_tests/test_2.py::test_text_in_ctor_with_content_type_header_multidict\nPASSED r2e_tests/test_2.py::test_body_in_ctor_with_content_type_header_multidict\nPASSED r2e_tests/test_2.py::test_text_with_empty_payload\nPASSED r2e_tests/test_2.py::test_response_with_content_length_header_without_body\nPASSED r2e_tests/test_2.py::test_response_with_immutable_headers\nPASSED r2e_tests/test_2.py::test_response_prepared_after_header_preparation\nPASSED r2e_tests/test_2.py::TestJSONResponse::test_content_type_is_application_json_by_default\nPASSED r2e_tests/test_2.py::TestJSONResponse::test_passing_text_only\nPASSED r2e_tests/test_2.py::TestJSONResponse::test_data_and_text_raises_value_error\nPASSED r2e_tests/test_2.py::TestJSONResponse::test_data_and_body_raises_value_error\nPASSED r2e_tests/test_2.py::TestJSONResponse::test_text_is_json_encoded\nPASSED r2e_tests/test_2.py::TestJSONResponse::test_content_type_is_overrideable\nFAILED r2e_tests/test_1.py::test_multiline_reason - Failed: DID NOT RAISE <cl...\nFAILED r2e_tests/test_2.py::test_multiline_reason - Failed: DID NOT RAISE <cl...\nFAILED r2e_tests/test_2.py::test_send_set_cookie_header - pytest.PytestUnrais...\n======================== 3 failed, 175 passed in 6.43s =========================\n",
    "old_commit_res_stderr": "/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e9609ad14aef19dfd62e29f99c01a25294ff8d6b/.venv/lib/python3.9/site-packages/pytest_asyncio/plugin.py:207: PytestDeprecationWarning: The configuration option \"asyncio_default_fixture_loop_scope\" is unset.\nThe event loop scope for asynchronous fixtures will default to the fixture caching scope. Future versions of pytest-asyncio will default the loop scope for asynchronous fixtures to function scope. Set the default fixture loop scope explicitly in order to avoid unexpected behavior in the future. Valid fixture loop scopes are: \"function\", \"class\", \"module\", \"package\", \"session\"\n\n  warnings.warn(PytestDeprecationWarning(_DEFAULT_FIXTURE_LOOP_SCOPE_UNSET))\n"
}
CHANGES/9167.bugfix.rst aiohttp/web_response.py tests/test_web_exceptions.py tests/test_web_response.py
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]
**Title:** HTTP Response Allows Newlines in Reason, Leading to Potential Header Injection

**Description:**
Including newline characters in the `reason` parameter of an HTTP response can lead to unintended header injection, causing malformed responses or security vulnerabilities.

**Example Buggy Code:**
```python
from aiohttp import web

async def handler(request):
    return web.HTTPOk(reason="OK\r\nInjected-Header: value")
```
In this example, the `reason` contains a newline character followed by an additional header. This allows the injection of the `Injected-Header` into the HTTP response.

**Expected Behavior:**
The server should reject any HTTP response `reason` that includes newline characters by raising a `ValueError`. This prevents the injection of unintended headers and ensures the integrity of the HTTP response.

**Actual Behavior:**
The server accepts the `reason` with newline characters without raising an error, allowing additional headers to be injected into the response.

[/ISSUE]
--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.

--- BEGIN FILE ---
```
### aiohttp/web_response.py
import asyncio
import collections.abc
import datetime
import enum
import json
import math
import time
import warnings
import zlib
from concurrent.futures import Executor
from http import HTTPStatus
from http.cookies import SimpleCookie
from typing import (
    TYPE_CHECKING,
    Any,
    Dict,
    Iterator,
    MutableMapping,
    Optional,
    Union,
    cast,
)

from multidict import CIMultiDict, istr

from . import hdrs, payload
from .abc import AbstractStreamWriter
from .compression_utils import ZLibCompressor
from .helpers import (
    ETAG_ANY,
    QUOTED_ETAG_RE,
    ETag,
    HeadersMixin,
    must_be_empty_body,
    parse_http_date,
    rfc822_formatted_time,
    sentinel,
    should_remove_content_length,
    validate_etag_value,
)
from .http import SERVER_SOFTWARE, HttpVersion10, HttpVersion11
from .payload import Payload
from .typedefs import JSONEncoder, LooseHeaders

__all__ = ("ContentCoding", "StreamResponse", "Response", "json_response")


if TYPE_CHECKING:
    from .web_request import BaseRequest

    BaseClass = MutableMapping[str, Any]
else:
    BaseClass = collections.abc.MutableMapping


# TODO(py311): Convert to StrEnum for wider use
class ContentCoding(enum.Enum):
    # The content codings that we have support for.
    #
    # Additional registered codings are listed at:
    # https://www.iana.org/assignments/http-parameters/http-parameters.xhtml#content-coding
    deflate = "deflate"
    gzip = "gzip"
    identity = "identity"


############################################################
# HTTP Response classes
############################################################


class StreamResponse(BaseClass, HeadersMixin):

    _length_check = True

    _body: Union[None, bytes, bytearray, Payload]

    def __init__(
        self,
        *,
        status: int = 200,
        reason: Optional[str] = None,
        headers: Optional[LooseHeaders] = None,
    ) -> None:
        self._body = None
        self._keep_alive: Optional[bool] = None
        self._chunked = False
        self._compression = False
        self._compression_strategy: int = zlib.Z_DEFAULT_STRATEGY
        self._compression_force: Optional[ContentCoding] = None
        self._cookies = SimpleCookie()

        self._req: Optional[BaseRequest] = None
        self._payload_writer: Optional[AbstractStreamWriter] = None
        self._eof_sent = False
        self._must_be_empty_body: Optional[bool] = None
        self._body_length = 0
        self._state: Dict[str, Any] = {}

        if headers is not None:
            self._headers: CIMultiDict[str] = CIMultiDict(headers)
        else:
            self._headers = CIMultiDict()

        self.set_status(status, reason)

    @property
    def prepared(self) -> bool:
        return self._eof_sent or self._payload_writer is not None

    @property
    def task(self) -> "Optional[asyncio.Task[None]]":
        if self._req:
            return self._req.task
        else:
            return None

    @property
    def status(self) -> int:
        return self._status

    @property
    def chunked(self) -> bool:
        return self._chunked

    @property
    def compression(self) -> bool:
        return self._compression

    @property
    def reason(self) -> str:
        return self._reason

    def set_status(
        self,
        status: int,
        reason: Optional[str] = None,
    ) -> None:
        assert (
            not self.prepared
        ), "Cannot change the response status code after the headers have been sent"
        self._status = int(status)
        if reason is None:
            try:
                reason = HTTPStatus(self._status).phrase
            except ValueError:
                reason = ""
        self._reason = reason

    @property
    def keep_alive(self) -> Optional[bool]:
        return self._keep_alive

    def force_close(self) -> None:
        self._keep_alive = False

    @property
    def body_length(self) -> int:
        return self._body_length

    @property
    def output_length(self) -> int:
        warnings.warn("output_length is deprecated", DeprecationWarning)
        assert self._payload_writer
        return self._payload_writer.buffer_size

    def enable_chunked_encoding(self, chunk_size: Optional[int] = None) -> None:
        """Enables automatic chunked transfer encoding."""
        self._chunked = True

        if hdrs.CONTENT_LENGTH in self._headers:
            raise RuntimeError(
                "You can't enable chunked encoding when a content length is set"
            )
        if chunk_size is not None:
            warnings.warn("Chunk size is deprecated #1615", DeprecationWarning)

    def enable_compression(
        self,
        force: Optional[Union[bool, ContentCoding]] = None,
        strategy: int = zlib.Z_DEFAULT_STRATEGY,
    ) -> None:
        """Enables response compression encoding."""
        # Backwards compatibility for when force was a bool <0.17.
        if isinstance(force, bool):
            force = ContentCoding.deflate if force else ContentCoding.identity
            warnings.warn(
                "Using boolean for force is deprecated #3318", DeprecationWarning
            )
        elif force is not None:
            assert isinstance(
                force, ContentCoding
            ), "force should one of None, bool or ContentEncoding"

        self._compression = True
        self._compression_force = force
        self._compression_strategy = strategy

    @property
    def headers(self) -> "CIMultiDict[str]":
        return self._headers

    @property
    def cookies(self) -> SimpleCookie:
        return self._cookies

    def set_cookie(
        self,
        name: str,
        value: str,
        *,
        expires: Optional[str] = None,
        domain: Optional[str] = None,
        max_age: Optional[Union[int, str]] = None,
        path: str = "/",
        secure: Optional[bool] = None,
        httponly: Optional[bool] = None,
        version: Optional[str] = None,
        samesite: Optional[str] = None,
    ) -> None:
        """Set or update response cookie.

        Sets new cookie or updates existent with new value.
        Also updates only those params which are not None.
        """
        old = self._cookies.get(name)
        if old is not None and old.coded_value == "":
            # deleted cookie
            self._cookies.pop(name, None)

        self._cookies[name] = value
        c = self._cookies[name]

        if expires is not None:
            c["expires"] = expires
        elif c.get("expires") == "Thu, 01 Jan 1970 00:00:00 GMT":
            del c["expires"]

        if domain is not None:
            c["domain"] = domain

        if max_age is not None:
            c["max-age"] = str(max_age)
        elif "max-age" in c:
            del c["max-age"]

        c["path"] = path

        if secure is not None:
            c["secure"] = secure
        if httponly is not None:
            c["httponly"] = httponly
        if version is not None:
            c["version"] = version
        if samesite is not None:
            c["samesite"] = samesite

    def del_cookie(
        self,
        name: str,
        *,
        domain: Optional[str] = None,
        path: str = "/",
        secure: Optional[bool] = None,
        httponly: Optional[bool] = None,
        samesite: Optional[str] = None,
    ) -> None:
        """Delete cookie.

        Creates new empty expired cookie.
        """
        # TODO: do we need domain/path here?
        self._cookies.pop(name, None)
        self.set_cookie(
            name,
            "",
            max_age=0,
            expires="Thu, 01 Jan 1970 00:00:00 GMT",
            domain=domain,
            path=path,
            secure=secure,
            httponly=httponly,
            samesite=samesite,
        )

    @property
    def content_length(self) -> Optional[int]:
        # Just a placeholder for adding setter
        return super().content_length

    @content_length.setter
    def content_length(self, value: Optional[int]) -> None:
        if value is not None:
            value = int(value)
            if self._chunked:
                raise RuntimeError(
                    "You can't set content length when chunked encoding is enable"
                )
            self._headers[hdrs.CONTENT_LENGTH] = str(value)
        else:
            self._headers.pop(hdrs.CONTENT_LENGTH, None)

    @property
    def content_type(self) -> str:
        # Just a placeholder for adding setter
        return super().content_type

    @content_type.setter
    def content_type(self, value: str) -> None:
        self.content_type  # read header values if needed
        self._content_type = str(value)
        self._generate_content_type_header()

    @property
    def charset(self) -> Optional[str]:
        # Just a placeholder for adding setter
        return super().charset

    @charset.setter
    def charset(self, value: Optional[str]) -> None:
        ctype = self.content_type  # read header values if needed
        if ctype == "application/octet-stream":
            raise RuntimeError(
                "Setting charset for application/octet-stream "
                "doesn't make sense, setup content_type first"
            )
        assert self._content_dict is not None
        if value is None:
            self._content_dict.pop("charset", None)
        else:
            self._content_dict["charset"] = str(value).lower()
        self._generate_content_type_header()

    @property
    def last_modified(self) -> Optional[datetime.datetime]:
        """The value of Last-Modified HTTP header, or None.

        This header is represented as a `datetime` object.
        """
        return parse_http_date(self._headers.get(hdrs.LAST_MODIFIED))

    @last_modified.setter
    def last_modified(
        self, value: Optional[Union[int, float, datetime.datetime, str]]
    ) -> None:
        if value is None:
            self._headers.pop(hdrs.LAST_MODIFIED, None)
        elif isinstance(value, (int, float)):
            self._headers[hdrs.LAST_MODIFIED] = time.strftime(
                "%a, %d %b %Y %H:%M:%S GMT", time.gmtime(math.ceil(value))
            )
        elif isinstance(value, datetime.datetime):
            self._headers[hdrs.LAST_MODIFIED] = time.strftime(
                "%a, %d %b %Y %H:%M:%S GMT", value.utctimetuple()
            )
        elif isinstance(value, str):
            self._headers[hdrs.LAST_MODIFIED] = value

    @property
    def etag(self) -> Optional[ETag]:
        quoted_value = self._headers.get(hdrs.ETAG)
        if not quoted_value:
            return None
        elif quoted_value == ETAG_ANY:
            return ETag(value=ETAG_ANY)
        match = QUOTED_ETAG_RE.fullmatch(quoted_value)
        if not match:
            return None
        is_weak, value = match.group(1, 2)
        return ETag(
            is_weak=bool(is_weak),
            value=value,
        )

    @etag.setter
    def etag(self, value: Optional[Union[ETag, str]]) -> None:
        if value is None:
            self._headers.pop(hdrs.ETAG, None)
        elif (isinstance(value, str) and value == ETAG_ANY) or (
            isinstance(value, ETag) and value.value == ETAG_ANY
        ):
            self._headers[hdrs.ETAG] = ETAG_ANY
        elif isinstance(value, str):
            validate_etag_value(value)
            self._headers[hdrs.ETAG] = f'"{value}"'
        elif isinstance(value, ETag) and isinstance(value.value, str):
            validate_etag_value(value.value)
            hdr_value = f'W/"{value.value}"' if value.is_weak else f'"{value.value}"'
            self._headers[hdrs.ETAG] = hdr_value
        else:
            raise ValueError(
                f"Unsupported etag type: {type(value)}. "
                f"etag must be str, ETag or None"
            )

    def _generate_content_type_header(
        self, CONTENT_TYPE: istr = hdrs.CONTENT_TYPE
    ) -> None:
        assert self._content_dict is not None
        assert self._content_type is not None
        params = "; ".join(f"{k}={v}" for k, v in self._content_dict.items())
        if params:
            ctype = self._content_type + "; " + params
        else:
            ctype = self._content_type
        self._headers[CONTENT_TYPE] = ctype

    async def _do_start_compression(self, coding: ContentCoding) -> None:
        if coding != ContentCoding.identity:
            assert self._payload_writer is not None
            self._headers[hdrs.CONTENT_ENCODING] = coding.value
            self._payload_writer.enable_compression(
                coding.value, self._compression_strategy
            )
            # Compressed payload may have different content length,
            # remove the header
            self._headers.popall(hdrs.CONTENT_LENGTH, None)

    async def _start_compression(self, request: "BaseRequest") -> None:
        if self._compression_force:
            await self._do_start_compression(self._compression_force)
        else:
            # Encoding comparisons should be case-insensitive
            # https://www.rfc-editor.org/rfc/rfc9110#section-8.4.1
            accept_encoding = request.headers.get(hdrs.ACCEPT_ENCODING, "").lower()
            for coding in ContentCoding:
                if coding.value in accept_encoding:
                    await self._do_start_compression(coding)
                    return

    async def prepare(self, request: "BaseRequest") -> Optional[AbstractStreamWriter]:
        if self._eof_sent:
            return None
        if self._payload_writer is not None:
            return self._payload_writer
        self._must_be_empty_body = must_be_empty_body(request.method, self.status)
        return await self._start(request)

    async def _start(self, request: "BaseRequest") -> AbstractStreamWriter:
        self._req = request
        writer = self._payload_writer = request._payload_writer

        await self._prepare_headers()
        await request._prepare_hook(self)
        await self._write_headers()

        return writer

    async def _prepare_headers(self) -> None:
        request = self._req
        assert request is not None
        writer = self._payload_writer
        assert writer is not None
        keep_alive = self._keep_alive
        if keep_alive is None:
            keep_alive = request.keep_alive
        self._keep_alive = keep_alive

        version = request.version

        headers = self._headers
        for cookie in self._cookies.values():
            value = cookie.output(header="")[1:]
            headers.add(hdrs.SET_COOKIE, value)

        if self._compression:
            await self._start_compression(request)

        if self._chunked:
            if version != HttpVersion11:
                raise RuntimeError(
                    "Using chunked encoding is forbidden "
                    "for HTTP/{0.major}.{0.minor}".format(request.version)
                )
            if not self._must_be_empty_body:
                writer.enable_chunking()
                headers[hdrs.TRANSFER_ENCODING] = "chunked"
            if hdrs.CONTENT_LENGTH in headers:
                del headers[hdrs.CONTENT_LENGTH]
        elif self._length_check:
            writer.length = self.content_length
            if writer.length is None:
                if version >= HttpVersion11:
                    if not self._must_be_empty_body:
                        writer.enable_chunking()
                        headers[hdrs.TRANSFER_ENCODING] = "chunked"
                elif not self._must_be_empty_body:
                    keep_alive = False

        # HTTP 1.1: https://tools.ietf.org/html/rfc7230#section-3.3.2
        # HTTP 1.0: https://tools.ietf.org/html/rfc1945#section-10.4
        if self._must_be_empty_body:
            if hdrs.CONTENT_LENGTH in headers and should_remove_content_length(
                request.method, self.status
            ):
                del headers[hdrs.CONTENT_LENGTH]
            # https://datatracker.ietf.org/doc/html/rfc9112#section-6.1-10
            # https://datatracker.ietf.org/doc/html/rfc9112#section-6.1-13
            if hdrs.TRANSFER_ENCODING in headers:
                del headers[hdrs.TRANSFER_ENCODING]
        elif self.content_length != 0:
            # https://www.rfc-editor.org/rfc/rfc9110#section-8.3-5
            headers.setdefault(hdrs.CONTENT_TYPE, "application/octet-stream")
        headers.setdefault(hdrs.DATE, rfc822_formatted_time())
        headers.setdefault(hdrs.SERVER, SERVER_SOFTWARE)

        # connection header
        if hdrs.CONNECTION not in headers:
            if keep_alive:
                if version == HttpVersion10:
                    headers[hdrs.CONNECTION] = "keep-alive"
            else:
                if version == HttpVersion11:
                    headers[hdrs.CONNECTION] = "close"

    async def _write_headers(self) -> None:
        request = self._req
        assert request is not None
        writer = self._payload_writer
        assert writer is not None
        # status line
        version = request.version
        status_line = f"HTTP/{version[0]}.{version[1]} {self._status} {self._reason}"
        await writer.write_headers(status_line, self._headers)

    async def write(self, data: bytes) -> None:
        assert isinstance(
            data, (bytes, bytearray, memoryview)
        ), "data argument must be byte-ish (%r)" % type(data)

        if self._eof_sent:
            raise RuntimeError("Cannot call write() after write_eof()")
        if self._payload_writer is None:
            raise RuntimeError("Cannot call write() before prepare()")

        await self._payload_writer.write(data)

    async def drain(self) -> None:
        assert not self._eof_sent, "EOF has already been sent"
        assert self._payload_writer is not None, "Response has not been started"
        warnings.warn(
            "drain method is deprecated, use await resp.write()",
            DeprecationWarning,
            stacklevel=2,
        )
        await self._payload_writer.drain()

    async def write_eof(self, data: bytes = b"") -> None:
        assert isinstance(
            data, (bytes, bytearray, memoryview)
        ), "data argument must be byte-ish (%r)" % type(data)

        if self._eof_sent:
            return

        assert self._payload_writer is not None, "Response has not been started"

        await self._payload_writer.write_eof(data)
        self._eof_sent = True
        self._req = None
        self._body_length = self._payload_writer.output_size
        self._payload_writer = None

    def __repr__(self) -> str:
        if self._eof_sent:
            info = "eof"
        elif self.prepared:
            assert self._req is not None
            info = f"{self._req.method} {self._req.path} "
        else:
            info = "not prepared"
        return f"<{self.__class__.__name__} {self.reason} {info}>"

    def __getitem__(self, key: str) -> Any:
        return self._state[key]

    def __setitem__(self, key: str, value: Any) -> None:
        self._state[key] = value

    def __delitem__(self, key: str) -> None:
        del self._state[key]

    def __len__(self) -> int:
        return len(self._state)

    def __iter__(self) -> Iterator[str]:
        return iter(self._state)

    def __hash__(self) -> int:
        return hash(id(self))

    def __eq__(self, other: object) -> bool:
        return self is other


class Response(StreamResponse):
    def __init__(
        self,
        *,
        body: Any = None,
        status: int = 200,
        reason: Optional[str] = None,
        text: Optional[str] = None,
        headers: Optional[LooseHeaders] = None,
        content_type: Optional[str] = None,
        charset: Optional[str] = None,
        zlib_executor_size: Optional[int] = None,
        zlib_executor: Optional[Executor] = None,
    ) -> None:
        if body is not None and text is not None:
            raise ValueError("body and text are not allowed together")

        if headers is None:
            real_headers: CIMultiDict[str] = CIMultiDict()
        elif not isinstance(headers, CIMultiDict):
            real_headers = CIMultiDict(headers)
        else:
            real_headers = headers  # = cast('CIMultiDict[str]', headers)

        if content_type is not None and "charset" in content_type:
            raise ValueError("charset must not be in content_type argument")

        if text is not None:
            if hdrs.CONTENT_TYPE in real_headers:
                if content_type or charset:
                    raise ValueError(
                        "passing both Content-Type header and "
                        "content_type or charset params "
                        "is forbidden"
                    )
            else:
                # fast path for filling headers
                if not isinstance(text, str):
                    raise TypeError("text argument must be str (%r)" % type(text))
                if content_type is None:
                    content_type = "text/plain"
                if charset is None:
                    charset = "utf-8"
                real_headers[hdrs.CONTENT_TYPE] = content_type + "; charset=" + charset
                body = text.encode(charset)
                text = None
        else:
            if hdrs.CONTENT_TYPE in real_headers:
                if content_type is not None or charset is not None:
                    raise ValueError(
                        "passing both Content-Type header and "
                        "content_type or charset params "
                        "is forbidden"
                    )
            else:
                if content_type is not None:
                    if charset is not None:
                        content_type += "; charset=" + charset
                    real_headers[hdrs.CONTENT_TYPE] = content_type

        super().__init__(status=status, reason=reason, headers=real_headers)

        if text is not None:
            self.text = text
        else:
            self.body = body

        self._compressed_body: Optional[bytes] = None
        self._zlib_executor_size = zlib_executor_size
        self._zlib_executor = zlib_executor

    @property
    def body(self) -> Optional[Union[bytes, Payload]]:
        return self._body

    @body.setter
    def body(self, body: Any) -> None:
        if body is None:
            self._body = None
        elif isinstance(body, (bytes, bytearray)):
            self._body = body
        else:
            try:
                self._body = body = payload.PAYLOAD_REGISTRY.get(body)
            except payload.LookupError:
                raise ValueError("Unsupported body type %r" % type(body))

            headers = self._headers

            # set content-type
            if hdrs.CONTENT_TYPE not in headers:
                headers[hdrs.CONTENT_TYPE] = body.content_type

            # copy payload headers
            if body.headers:
                for key, value in body.headers.items():
                    if key not in headers:
                        headers[key] = value

        self._compressed_body = None

    @property
    def text(self) -> Optional[str]:
        if self._body is None:
            return None
        return self._body.decode(self.charset or "utf-8")

    @text.setter
    def text(self, text: str) -> None:
        assert text is None or isinstance(
            text, str
        ), "text argument must be str (%r)" % type(text)

        if self.content_type == "application/octet-stream":
            self.content_type = "text/plain"
        if self.charset is None:
            self.charset = "utf-8"

        self._body = text.encode(self.charset)
        self._compressed_body = None

    @property
    def content_length(self) -> Optional[int]:
        if self._chunked:
            return None

        if hdrs.CONTENT_LENGTH in self._headers:
            return super().content_length

        if self._compressed_body is not None:
            # Return length of the compressed body
            return len(self._compressed_body)
        elif isinstance(self._body, Payload):
            # A payload without content length, or a compressed payload
            return None
        elif self._body is not None:
            return len(self._body)
        else:
            return 0

    @content_length.setter
    def content_length(self, value: Optional[int]) -> None:
        raise RuntimeError("Content length is set automatically")

    async def write_eof(self, data: bytes = b"") -> None:
        if self._eof_sent:
            return
        if self._compressed_body is None:
            body: Optional[Union[bytes, Payload]] = self._body
        else:
            body = self._compressed_body
        assert not data, f"data arg is not supported, got {data!r}"
        assert self._req is not None
        assert self._payload_writer is not None
        if body is not None:
            if self._must_be_empty_body:
                await super().write_eof()
            elif isinstance(self._body, Payload):
                await self._body.write(self._payload_writer)
                await super().write_eof()
            else:
                await super().write_eof(cast(bytes, body))
        else:
            await super().write_eof()

    async def _start(self, request: "BaseRequest") -> AbstractStreamWriter:
        if hdrs.CONTENT_LENGTH in self._headers:
            if should_remove_content_length(request.method, self.status):
                del self._headers[hdrs.CONTENT_LENGTH]
        elif not self._chunked:
            if isinstance(self._body, Payload):
                if self._body.size is not None:
                    self._headers[hdrs.CONTENT_LENGTH] = str(self._body.size)
            else:
                body_len = len(self._body) if self._body else "0"
                # https://www.rfc-editor.org/rfc/rfc9110.html#section-8.6-7
                if body_len != "0" or (
                    self.status != 304 and request.method.upper() != hdrs.METH_HEAD
                ):
                    self._headers[hdrs.CONTENT_LENGTH] = str(body_len)

        return await super()._start(request)

    async def _do_start_compression(self, coding: ContentCoding) -> None:
        if self._chunked or isinstance(self._body, Payload):
            return await super()._do_start_compression(coding)

        if coding != ContentCoding.identity:
            # Instead of using _payload_writer.enable_compression,
            # compress the whole body
            compressor = ZLibCompressor(
                encoding=str(coding.value),
                max_sync_chunk_size=self._zlib_executor_size,
                executor=self._zlib_executor,
            )
            assert self._body is not None
            if self._zlib_executor_size is None and len(self._body) > 1024 * 1024:
                warnings.warn(
                    "Synchronous compression of large response bodies "
                    f"({len(self._body)} bytes) might block the async event loop. "
                    "Consider providing a custom value to zlib_executor_size/"
                    "zlib_executor response properties or disabling compression on it."
                )
            self._compressed_body = (
                await compressor.compress(self._body) + compressor.flush()
            )
            assert self._compressed_body is not None

            self._headers[hdrs.CONTENT_ENCODING] = coding.value
            self._headers[hdrs.CONTENT_LENGTH] = str(len(self._compressed_body))


def json_response(
    data: Any = sentinel,
    *,
    text: Optional[str] = None,
    body: Optional[bytes] = None,
    status: int = 200,
    reason: Optional[str] = None,
    headers: Optional[LooseHeaders] = None,
    content_type: str = "application/json",
    dumps: JSONEncoder = json.dumps,
) -> Response:
    if data is not sentinel:
        if text or body:
            raise ValueError("only one of data, text, or body should be specified")
        else:
            text = dumps(data)
    return Response(
        text=text,
        body=body,
        status=status,
        reason=reason,
        headers=headers,
        content_type=content_type,
    )

```
--- END FILE ---

Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.

Every *SEARCH/REPLACE* edit must use this format:
1. The file path
2. The start of search block: <<<<<<< SEARCH
3. A contiguous chunk of lines to search for in the existing source code
4. The dividing line: =======
5. The lines to replace into the source code
6. The end of the replace block: >>>>>>> REPLACE

Here is an example:

```python
### mathweb/flask/app.py
<<<<<<< SEARCH
from flask import Flask
=======
import math
from flask import Flask
>>>>>>> REPLACE
```
</solution>

Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
Wrap each *SEARCH/REPLACE* edit in a code block as shown in the example above. If you have multiple *SEARCH/REPLACE* edits, use a separate code block for each one.
[ISSUE]
**Title:** HTTP Response Allows Newlines in Reason, Leading to Potential Header Injection

**Description:**
Including newline characters in the `reason` parameter of an HTTP response can lead to unintended header injection, causing malformed responses or security vulnerabilities.

**Example Buggy Code:**
```python
from aiohttp import web

async def handler(request):
    return web.HTTPOk(reason="OK\r\nInjected-Header: value")
```
In this example, the `reason` contains a newline character followed by an additional header. This allows the injection of the `Injected-Header` into the HTTP response.

**Expected Behavior:**
The server should reject any HTTP response `reason` that includes newline characters by raising a `ValueError`. This prevents the injection of unintended headers and ensures the integrity of the HTTP response.

**Actual Behavior:**
The server accepts the `reason` with newline characters without raising an error, allowing additional headers to be injected into the response.

[/ISSUE]
{
    "test_all_http_exceptions_exported": "PASSED",
    "test_HTTPOk": "PASSED",
    "test_terminal_classes_has_status_code": "PASSED",
    "test_HTTPFound": "PASSED",
    "test_HTTPFound_empty_location": "PASSED",
    "test_HTTPFound_location_CRLF": "PASSED",
    "test_HTTPMethodNotAllowed": "PASSED",
    "test_override_body_with_text": "PASSED",
    "test_override_body_with_binary": "PASSED",
    "test_default_body": "PASSED",
    "test_empty_body_204": "PASSED",
    "test_empty_body_205": "PASSED",
    "test_empty_body_304": "PASSED",
    "test_no_link_451": "PASSED",
    "test_link_none_451": "PASSED",
    "test_link_empty_451": "PASSED",
    "test_link_str_451": "PASSED",
    "test_link_url_451": "PASSED",
    "test_link_CRLF_451": "PASSED",
    "test_HTTPException_retains_cause": "PASSED",
    "test_HTTPException_retains_cookie[pyloop]": "PASSED",
    "test_unicode_text_body_unauthorized": "PASSED",
    "test_multiline_reason": "PASSED",
    "test_stream_response_ctor": "PASSED",
    "test_stream_response_hashable": "PASSED",
    "test_stream_response_eq": "PASSED",
    "test_stream_response_is_mutable_mapping": "PASSED",
    "test_stream_response_delitem": "PASSED",
    "test_stream_response_len": "PASSED",
    "test_request_iter": "PASSED",
    "test_content_length": "PASSED",
    "test_content_length_setter": "PASSED",
    "test_content_length_setter_with_enable_chunked_encoding": "PASSED",
    "test_drop_content_length_header_on_setting_len_to_None": "PASSED",
    "test_set_content_length_to_None_on_non_set": "PASSED",
    "test_setting_content_type": "PASSED",
    "test_setting_charset": "PASSED",
    "test_default_charset": "PASSED",
    "test_reset_charset": "PASSED",
    "test_reset_charset_after_setting": "PASSED",
    "test_charset_without_content_type": "PASSED",
    "test_last_modified_initial": "PASSED",
    "test_last_modified_string": "PASSED",
    "test_last_modified_timestamp": "PASSED",
    "test_last_modified_datetime": "PASSED",
    "test_last_modified_reset": "PASSED",
    "test_last_modified_string_invalid[xxyyzz-None]": "PASSED",
    "test_last_modified_string_invalid[Tue, 08 Oct 4446413 00:56:40 GMT-None]": "PASSED",
    "test_last_modified_string_invalid[Tue, 08 Oct 2000 00:56:80 GMT-None]": "PASSED",
    "test_etag_initial": "PASSED",
    "test_etag_string": "PASSED",
    "test_etag_class[etag0-W/\"0123-weak-kotik\"]": "PASSED",
    "test_etag_class[etag1-\"0123-strong-kotik\"]": "PASSED",
    "test_etag_any": "PASSED",
    "test_etag_invalid_value_set[\"invalid\"]": "PASSED",
    "test_etag_invalid_value_set[\\u043f\\u043e\\u0432\\u0438\\u043d\\u0435\\u043d \\u0431\\u0443\\u0442\\u0438 ascii]": "PASSED",
    "test_etag_invalid_value_set[invalid_value2]": "PASSED",
    "test_etag_invalid_value_set[invalid_value3]": "PASSED",
    "test_etag_invalid_value_get[forgotten quotes]": "PASSED",
    "test_etag_invalid_value_get[\"\\u2200 x \\u2209 ascii\"]": "PASSED",
    "test_etag_invalid_value_class[123]": "PASSED",
    "test_etag_invalid_value_class[invalid1]": "PASSED",
    "test_etag_reset": "PASSED",
    "test_start": "PASSED",
    "test_chunked_encoding": "PASSED",
    "test_enable_chunked_encoding_with_content_length": "PASSED",
    "test_chunk_size": "PASSED",
    "test_chunked_encoding_forbidden_for_http_10": "PASSED",
    "test_compression_no_accept": "PASSED",
    "test_force_compression_no_accept_backwards_compat": "PASSED",
    "test_force_compression_false_backwards_compat": "PASSED",
    "test_compression_default_coding": "PASSED",
    "test_force_compression_deflate": "PASSED",
    "test_force_compression_no_accept_deflate": "PASSED",
    "test_force_compression_gzip": "PASSED",
    "test_force_compression_no_accept_gzip": "PASSED",
    "test_change_content_threaded_compression_enabled": "PASSED",
    "test_change_content_threaded_compression_enabled_explicit": "PASSED",
    "test_change_content_length_if_compression_enabled": "PASSED",
    "test_set_content_length_if_compression_enabled": "PASSED",
    "test_remove_content_length_if_compression_enabled_http11": "PASSED",
    "test_remove_content_length_if_compression_enabled_http10": "PASSED",
    "test_force_compression_identity": "PASSED",
    "test_force_compression_identity_response": "PASSED",
    "test_rm_content_length_if_compression_http11": "PASSED",
    "test_rm_content_length_if_compression_http10": "PASSED",
    "test_rm_content_length_if_204": "PASSED",
    "test_rm_transfer_encoding_rfc_9112_6_3_http_11[100]": "PASSED",
    "test_rm_transfer_encoding_rfc_9112_6_3_http_11[101]": "PASSED",
    "test_rm_transfer_encoding_rfc_9112_6_3_http_11[204]": "PASSED",
    "test_rm_transfer_encoding_rfc_9112_6_3_http_11[304]": "PASSED",
    "test_rm_content_length_1xx_204_304_responses[100]": "PASSED",
    "test_rm_content_length_1xx_204_304_responses[101]": "PASSED",
    "test_rm_content_length_1xx_204_304_responses[102]": "PASSED",
    "test_rm_content_length_1xx_204_304_responses[204]": "PASSED",
    "test_rm_content_length_1xx_204_304_responses[304]": "PASSED",
    "test_head_response_keeps_content_length_of_original_body": "PASSED",
    "test_head_response_omits_content_length_when_body_unset": "PASSED",
    "test_304_response_omits_content_length_when_body_unset": "PASSED",
    "test_content_length_on_chunked": "PASSED",
    "test_write_non_byteish": "PASSED",
    "test_write_before_start": "PASSED",
    "test_cannot_write_after_eof": "PASSED",
    "test___repr___after_eof": "PASSED",
    "test_cannot_write_eof_before_headers": "PASSED",
    "test_cannot_write_eof_twice": "PASSED",
    "test_force_close": "PASSED",
    "test_response_output_length": "PASSED",
    "test_response_cookies": "PASSED",
    "test_response_cookie_path": "PASSED",
    "test_response_cookie__issue_del_cookie": "PASSED",
    "test_cookie_set_after_del": "PASSED",
    "test_set_status_with_reason": "PASSED",
    "test_start_force_close": "PASSED",
    "test___repr__": "PASSED",
    "test___repr___not_prepared": "PASSED",
    "test_keep_alive_http10_default": "PASSED",
    "test_keep_alive_http10_switched_on": "PASSED",
    "test_keep_alive_http09": "PASSED",
    "test_prepare_twice": "PASSED",
    "test_prepare_calls_signal": "PASSED",
    "test_response_ctor": "PASSED",
    "test_ctor_with_headers_and_status": "PASSED",
    "test_ctor_content_type": "PASSED",
    "test_ctor_text_body_combined": "PASSED",
    "test_ctor_text": "PASSED",
    "test_ctor_charset": "PASSED",
    "test_ctor_charset_default_utf8": "PASSED",
    "test_ctor_charset_in_content_type": "PASSED",
    "test_ctor_charset_without_text": "PASSED",
    "test_ctor_content_type_with_extra": "PASSED",
    "test_ctor_both_content_type_param_and_header_with_text": "PASSED",
    "test_ctor_both_charset_param_and_header_with_text": "PASSED",
    "test_ctor_both_content_type_param_and_header": "PASSED",
    "test_ctor_both_charset_param_and_header": "PASSED",
    "test_assign_nonbyteish_body": "PASSED",
    "test_assign_nonstr_text": "PASSED",
    "test_payload_body_get_text[test-test]": "PASSED",
    "test_payload_body_get_text[payload1-test]": "PASSED",
    "test_payload_body_get_text[payload2-test]": "PASSED",
    "test_payload_body_get_text[payload3-test]": "PASSED",
    "test_payload_body_get_text[payload4-test]": "PASSED",
    "test_payload_body_get_text[payload5-test]": "PASSED",
    "test_payload_body_get_text[async_iter-None]": "PASSED",
    "test_payload_body_get_text[payload7-None]": "PASSED",
    "test_payload_body_get_text[payload8---x\\nContent-Type: text/plain; charset=utf-8\\r\\nContent-Length: 4\\r\\n\\r\\ntest]": "PASSED",
    "test_response_set_content_length": "PASSED",
    "test_send_headers_for_empty_body": "PASSED",
    "test_render_with_body": "PASSED",
    "test_send_set_cookie_header": "PASSED",
    "test_consecutive_write_eof": "PASSED",
    "test_set_text_with_content_type": "PASSED",
    "test_set_text_with_charset": "PASSED",
    "test_default_content_type_in_stream_response": "PASSED",
    "test_default_content_type_in_response": "PASSED",
    "test_content_type_with_set_text": "PASSED",
    "test_content_type_with_set_body": "PASSED",
    "test_prepared_when_not_started": "PASSED",
    "test_prepared_when_started": "PASSED",
    "test_prepared_after_eof": "PASSED",
    "test_drain_before_start": "PASSED",
    "test_changing_status_after_prepare_raises": "PASSED",
    "test_nonstr_text_in_ctor": "PASSED",
    "test_text_in_ctor_with_content_type": "PASSED",
    "test_text_in_ctor_with_content_type_header": "PASSED",
    "test_text_in_ctor_with_content_type_header_multidict": "PASSED",
    "test_body_in_ctor_with_content_type_header_multidict": "PASSED",
    "test_text_with_empty_payload": "PASSED",
    "test_response_with_content_length_header_without_body": "PASSED",
    "test_response_with_immutable_headers": "PASSED",
    "test_response_prepared_after_header_preparation": "PASSED",
    "TestJSONResponse.test_content_type_is_application_json_by_default": "PASSED",
    "TestJSONResponse.test_passing_text_only": "PASSED",
    "TestJSONResponse.test_data_and_text_raises_value_error": "PASSED",
    "TestJSONResponse.test_data_and_body_raises_value_error": "PASSED",
    "TestJSONResponse.test_text_is_json_encoded": "PASSED",
    "TestJSONResponse.test_content_type_is_overrideable": "PASSED"
}
diff --git a/aiohttp/web_response.py b/aiohttp/web_response.py
index 2ba135f5..bf184980 100644
--- a/aiohttp/web_response.py
+++ b/aiohttp/web_response.py
@@ -145,6 +145,8 @@ class StreamResponse(BaseClass, HeadersMixin):
                 reason = HTTPStatus(self._status).phrase
             except ValueError:
                 reason = ""
+        if "\n" in reason:
+            raise ValueError("Reason cannot contain \\n")
         self._reason = reason
 
     @property

{"aiohttp/web_response.py": "import asyncio\nimport collections.abc\nimport datetime\nimport enum\nimport json\nimport math\nimport time\nimport warnings\nimport zlib\nfrom concurrent.futures import Executor\nfrom http import HTTPStatus\nfrom http.cookies import SimpleCookie\nfrom typing import (\n    TYPE_CHECKING,\n    Any,\n    Dict,\n    Iterator,\n    MutableMapping,\n    Optional,\n    Union,\n    cast,\n)\n\nfrom multidict import CIMultiDict, istr\n\nfrom . import hdrs, payload\nfrom .abc import AbstractStreamWriter\nfrom .compression_utils import ZLibCompressor\nfrom .helpers import (\n    ETAG_ANY,\n    QUOTED_ETAG_RE,\n    ETag,\n    HeadersMixin,\n    must_be_empty_body,\n    parse_http_date,\n    rfc822_formatted_time,\n    sentinel,\n    should_remove_content_length,\n    validate_etag_value,\n)\nfrom .http import SERVER_SOFTWARE, HttpVersion10, HttpVersion11\nfrom .payload import Payload\nfrom .typedefs import JSONEncoder, LooseHeaders\n\n__all__ = (\"ContentCoding\", \"StreamResponse\", \"Response\", \"json_response\")\n\n\nif TYPE_CHECKING:\n    from .web_request import BaseRequest\n\n    BaseClass = MutableMapping[str, Any]\nelse:\n    BaseClass = collections.abc.MutableMapping\n\n\n# TODO(py311): Convert to StrEnum for wider use\nclass ContentCoding(enum.Enum):\n    # The content codings that we have support for.\n    #\n    # Additional registered codings are listed at:\n    # https://www.iana.org/assignments/http-parameters/http-parameters.xhtml#content-coding\n    deflate = \"deflate\"\n    gzip = \"gzip\"\n    identity = \"identity\"\n\n\n############################################################\n# HTTP Response classes\n############################################################\n\n\nclass StreamResponse(BaseClass, HeadersMixin):\n\n    _length_check = True\n\n    _body: Union[None, bytes, bytearray, Payload]\n\n    def __init__(\n        self,\n        *,\n        status: int = 200,\n        reason: Optional[str] = None,\n        headers: Optional[LooseHeaders] = None,\n    ) -> None:\n        self._body = None\n        self._keep_alive: Optional[bool] = None\n        self._chunked = False\n        self._compression = False\n        self._compression_strategy: int = zlib.Z_DEFAULT_STRATEGY\n        self._compression_force: Optional[ContentCoding] = None\n        self._cookies = SimpleCookie()\n\n        self._req: Optional[BaseRequest] = None\n        self._payload_writer: Optional[AbstractStreamWriter] = None\n        self._eof_sent = False\n        self._must_be_empty_body: Optional[bool] = None\n        self._body_length = 0\n        self._state: Dict[str, Any] = {}\n\n        if headers is not None:\n            self._headers: CIMultiDict[str] = CIMultiDict(headers)\n        else:\n            self._headers = CIMultiDict()\n\n        self.set_status(status, reason)\n\n    @property\n    def prepared(self) -> bool:\n        return self._eof_sent or self._payload_writer is not None\n\n    @property\n    def task(self) -> \"Optional[asyncio.Task[None]]\":\n        if self._req:\n            return self._req.task\n        else:\n            return None\n\n    @property\n    def status(self) -> int:\n        return self._status\n\n    @property\n    def chunked(self) -> bool:\n        return self._chunked\n\n    @property\n    def compression(self) -> bool:\n        return self._compression\n\n    @property\n    def reason(self) -> str:\n        return self._reason\n\n    def set_status(\n        self,\n        status: int,\n        reason: Optional[str] = None,\n    ) -> None:\n        assert (\n            not self.prepared\n        ), \"Cannot change the response status code after the headers have been sent\"\n        self._status = int(status)\n        if reason is None:\n            try:\n                reason = HTTPStatus(self._status).phrase\n            except ValueError:\n                reason = \"\"\n        self._reason = reason\n\n    @property\n    def keep_alive(self) -> Optional[bool]:\n        return self._keep_alive\n\n    def force_close(self) -> None:\n        self._keep_alive = False\n\n    @property\n    def body_length(self) -> int:\n        return self._body_length\n\n    @property\n    def output_length(self) -> int:\n        warnings.warn(\"output_length is deprecated\", DeprecationWarning)\n        assert self._payload_writer\n        return self._payload_writer.buffer_size\n\n    def enable_chunked_encoding(self, chunk_size: Optional[int] = None) -> None:\n        \"\"\"Enables automatic chunked transfer encoding.\"\"\"\n        self._chunked = True\n\n        if hdrs.CONTENT_LENGTH in self._headers:\n            raise RuntimeError(\n                \"You can't enable chunked encoding when a content length is set\"\n            )\n        if chunk_size is not None:\n            warnings.warn(\"Chunk size is deprecated #1615\", DeprecationWarning)\n\n    def enable_compression(\n        self,\n        force: Optional[Union[bool, ContentCoding]] = None,\n        strategy: int = zlib.Z_DEFAULT_STRATEGY,\n    ) -> None:\n        \"\"\"Enables response compression encoding.\"\"\"\n        # Backwards compatibility for when force was a bool <0.17.\n        if isinstance(force, bool):\n            force = ContentCoding.deflate if force else ContentCoding.identity\n            warnings.warn(\n                \"Using boolean for force is deprecated #3318\", DeprecationWarning\n            )\n        elif force is not None:\n            assert isinstance(\n                force, ContentCoding\n            ), \"force should one of None, bool or ContentEncoding\"\n\n        self._compression = True\n        self._compression_force = force\n        self._compression_strategy = strategy\n\n    @property\n    def headers(self) -> \"CIMultiDict[str]\":\n        return self._headers\n\n    @property\n    def cookies(self) -> SimpleCookie:\n        return self._cookies\n\n    def set_cookie(\n        self,\n        name: str,\n        value: str,\n        *,\n        expires: Optional[str] = None,\n        domain: Optional[str] = None,\n        max_age: Optional[Union[int, str]] = None,\n        path: str = \"/\",\n        secure: Optional[bool] = None,\n        httponly: Optional[bool] = None,\n        version: Optional[str] = None,\n        samesite: Optional[str] = None,\n    ) -> None:\n        \"\"\"Set or update response cookie.\n\n        Sets new cookie or updates existent with new value.\n        Also updates only those params which are not None.\n        \"\"\"\n        old = self._cookies.get(name)\n        if old is not None and old.coded_value == \"\":\n            # deleted cookie\n            self._cookies.pop(name, None)\n\n        self._cookies[name] = value\n        c = self._cookies[name]\n\n        if expires is not None:\n            c[\"expires\"] = expires\n        elif c.get(\"expires\") == \"Thu, 01 Jan 1970 00:00:00 GMT\":\n            del c[\"expires\"]\n\n        if domain is not None:\n            c[\"domain\"] = domain\n\n        if max_age is not None:\n            c[\"max-age\"] = str(max_age)\n        elif \"max-age\" in c:\n            del c[\"max-age\"]\n\n        c[\"path\"] = path\n\n        if secure is not None:\n            c[\"secure\"] = secure\n        if httponly is not None:\n            c[\"httponly\"] = httponly\n        if version is not None:\n            c[\"version\"] = version\n        if samesite is not None:\n            c[\"samesite\"] = samesite\n\n    def del_cookie(\n        self,\n        name: str,\n        *,\n        domain: Optional[str] = None,\n        path: str = \"/\",\n        secure: Optional[bool] = None,\n        httponly: Optional[bool] = None,\n        samesite: Optional[str] = None,\n    ) -> None:\n        \"\"\"Delete cookie.\n\n        Creates new empty expired cookie.\n        \"\"\"\n        # TODO: do we need domain/path here?\n        self._cookies.pop(name, None)\n        self.set_cookie(\n            name,\n            \"\",\n            max_age=0,\n            expires=\"Thu, 01 Jan 1970 00:00:00 GMT\",\n            domain=domain,\n            path=path,\n            secure=secure,\n            httponly=httponly,\n            samesite=samesite,\n        )\n\n    @property\n    def content_length(self) -> Optional[int]:\n        # Just a placeholder for adding setter\n        return super().content_length\n\n    @content_length.setter\n    def content_length(self, value: Optional[int]) -> None:\n        if value is not None:\n            value = int(value)\n            if self._chunked:\n                raise RuntimeError(\n                    \"You can't set content length when chunked encoding is enable\"\n                )\n            self._headers[hdrs.CONTENT_LENGTH] = str(value)\n        else:\n            self._headers.pop(hdrs.CONTENT_LENGTH, None)\n\n    @property\n    def content_type(self) -> str:\n        # Just a placeholder for adding setter\n        return super().content_type\n\n    @content_type.setter\n    def content_type(self, value: str) -> None:\n        self.content_type  # read header values if needed\n        self._content_type = str(value)\n        self._generate_content_type_header()\n\n    @property\n    def charset(self) -> Optional[str]:\n        # Just a placeholder for adding setter\n        return super().charset\n\n    @charset.setter\n    def charset(self, value: Optional[str]) -> None:\n        ctype = self.content_type  # read header values if needed\n        if ctype == \"application/octet-stream\":\n            raise RuntimeError(\n                \"Setting charset for application/octet-stream \"\n                \"doesn't make sense, setup content_type first\"\n            )\n        assert self._content_dict is not None\n        if value is None:\n            self._content_dict.pop(\"charset\", None)\n        else:\n            self._content_dict[\"charset\"] = str(value).lower()\n        self._generate_content_type_header()\n\n    @property\n    def last_modified(self) -> Optional[datetime.datetime]:\n        \"\"\"The value of Last-Modified HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self._headers.get(hdrs.LAST_MODIFIED))\n\n    @last_modified.setter\n    def last_modified(\n        self, value: Optional[Union[int, float, datetime.datetime, str]]\n    ) -> None:\n        if value is None:\n            self._headers.pop(hdrs.LAST_MODIFIED, None)\n        elif isinstance(value, (int, float)):\n            self._headers[hdrs.LAST_MODIFIED] = time.strftime(\n                \"%a, %d %b %Y %H:%M:%S GMT\", time.gmtime(math.ceil(value))\n            )\n        elif isinstance(value, datetime.datetime):\n            self._headers[hdrs.LAST_MODIFIED] = time.strftime(\n                \"%a, %d %b %Y %H:%M:%S GMT\", value.utctimetuple()\n            )\n        elif isinstance(value, str):\n            self._headers[hdrs.LAST_MODIFIED] = value\n\n    @property\n    def etag(self) -> Optional[ETag]:\n        quoted_value = self._headers.get(hdrs.ETAG)\n        if not quoted_value:\n            return None\n        elif quoted_value == ETAG_ANY:\n            return ETag(value=ETAG_ANY)\n        match = QUOTED_ETAG_RE.fullmatch(quoted_value)\n        if not match:\n            return None\n        is_weak, value = match.group(1, 2)\n        return ETag(\n            is_weak=bool(is_weak),\n            value=value,\n        )\n\n    @etag.setter\n    def etag(self, value: Optional[Union[ETag, str]]) -> None:\n        if value is None:\n            self._headers.pop(hdrs.ETAG, None)\n        elif (isinstance(value, str) and value == ETAG_ANY) or (\n            isinstance(value, ETag) and value.value == ETAG_ANY\n        ):\n            self._headers[hdrs.ETAG] = ETAG_ANY\n        elif isinstance(value, str):\n            validate_etag_value(value)\n            self._headers[hdrs.ETAG] = f'\"{value}\"'\n        elif isinstance(value, ETag) and isinstance(value.value, str):\n            validate_etag_value(value.value)\n            hdr_value = f'W/\"{value.value}\"' if value.is_weak else f'\"{value.value}\"'\n            self._headers[hdrs.ETAG] = hdr_value\n        else:\n            raise ValueError(\n                f\"Unsupported etag type: {type(value)}. \"\n                f\"etag must be str, ETag or None\"\n            )\n\n    def _generate_content_type_header(\n        self, CONTENT_TYPE: istr = hdrs.CONTENT_TYPE\n    ) -> None:\n        assert self._content_dict is not None\n        assert self._content_type is not None\n        params = \"; \".join(f\"{k}={v}\" for k, v in self._content_dict.items())\n        if params:\n            ctype = self._content_type + \"; \" + params\n        else:\n            ctype = self._content_type\n        self._headers[CONTENT_TYPE] = ctype\n\n    async def _do_start_compression(self, coding: ContentCoding) -> None:\n        if coding != ContentCoding.identity:\n            assert self._payload_writer is not None\n            self._headers[hdrs.CONTENT_ENCODING] = coding.value\n            self._payload_writer.enable_compression(\n                coding.value, self._compression_strategy\n            )\n            # Compressed payload may have different content length,\n            # remove the header\n            self._headers.popall(hdrs.CONTENT_LENGTH, None)\n\n    async def _start_compression(self, request: \"BaseRequest\") -> None:\n        if self._compression_force:\n            await self._do_start_compression(self._compression_force)\n        else:\n            # Encoding comparisons should be case-insensitive\n            # https://www.rfc-editor.org/rfc/rfc9110#section-8.4.1\n            accept_encoding = request.headers.get(hdrs.ACCEPT_ENCODING, \"\").lower()\n            for coding in ContentCoding:\n                if coding.value in accept_encoding:\n                    await self._do_start_compression(coding)\n                    return\n\n    async def prepare(self, request: \"BaseRequest\") -> Optional[AbstractStreamWriter]:\n        if self._eof_sent:\n            return None\n        if self._payload_writer is not None:\n            return self._payload_writer\n        self._must_be_empty_body = must_be_empty_body(request.method, self.status)\n        return await self._start(request)\n\n    async def _start(self, request: \"BaseRequest\") -> AbstractStreamWriter:\n        self._req = request\n        writer = self._payload_writer = request._payload_writer\n\n        await self._prepare_headers()\n        await request._prepare_hook(self)\n        await self._write_headers()\n\n        return writer\n\n    async def _prepare_headers(self) -> None:\n        request = self._req\n        assert request is not None\n        writer = self._payload_writer\n        assert writer is not None\n        keep_alive = self._keep_alive\n        if keep_alive is None:\n            keep_alive = request.keep_alive\n        self._keep_alive = keep_alive\n\n        version = request.version\n\n        headers = self._headers\n        for cookie in self._cookies.values():\n            value = cookie.output(header=\"\")[1:]\n            headers.add(hdrs.SET_COOKIE, value)\n\n        if self._compression:\n            await self._start_compression(request)\n\n        if self._chunked:\n            if version != HttpVersion11:\n                raise RuntimeError(\n                    \"Using chunked encoding is forbidden \"\n                    \"for HTTP/{0.major}.{0.minor}\".format(request.version)\n                )\n            if not self._must_be_empty_body:\n                writer.enable_chunking()\n                headers[hdrs.TRANSFER_ENCODING] = \"chunked\"\n            if hdrs.CONTENT_LENGTH in headers:\n                del headers[hdrs.CONTENT_LENGTH]\n        elif self._length_check:\n            writer.length = self.content_length\n            if writer.length is None:\n                if version >= HttpVersion11:\n                    if not self._must_be_empty_body:\n                        writer.enable_chunking()\n                        headers[hdrs.TRANSFER_ENCODING] = \"chunked\"\n                elif not self._must_be_empty_body:\n                    keep_alive = False\n\n        # HTTP 1.1: https://tools.ietf.org/html/rfc7230#section-3.3.2\n        # HTTP 1.0: https://tools.ietf.org/html/rfc1945#section-10.4\n        if self._must_be_empty_body:\n            if hdrs.CONTENT_LENGTH in headers and should_remove_content_length(\n                request.method, self.status\n            ):\n                del headers[hdrs.CONTENT_LENGTH]\n            # https://datatracker.ietf.org/doc/html/rfc9112#section-6.1-10\n            # https://datatracker.ietf.org/doc/html/rfc9112#section-6.1-13\n            if hdrs.TRANSFER_ENCODING in headers:\n                del headers[hdrs.TRANSFER_ENCODING]\n        elif self.content_length != 0:\n            # https://www.rfc-editor.org/rfc/rfc9110#section-8.3-5\n            headers.setdefault(hdrs.CONTENT_TYPE, \"application/octet-stream\")\n        headers.setdefault(hdrs.DATE, rfc822_formatted_time())\n        headers.setdefault(hdrs.SERVER, SERVER_SOFTWARE)\n\n        # connection header\n        if hdrs.CONNECTION not in headers:\n            if keep_alive:\n                if version == HttpVersion10:\n                    headers[hdrs.CONNECTION] = \"keep-alive\"\n            else:\n                if version == HttpVersion11:\n                    headers[hdrs.CONNECTION] = \"close\"\n\n    async def _write_headers(self) -> None:\n        request = self._req\n        assert request is not None\n        writer = self._payload_writer\n        assert writer is not None\n        # status line\n        version = request.version\n        status_line = f\"HTTP/{version[0]}.{version[1]} {self._status} {self._reason}\"\n        await writer.write_headers(status_line, self._headers)\n\n    async def write(self, data: bytes) -> None:\n        assert isinstance(\n            data, (bytes, bytearray, memoryview)\n        ), \"data argument must be byte-ish (%r)\" % type(data)\n\n        if self._eof_sent:\n            raise RuntimeError(\"Cannot call write() after write_eof()\")\n        if self._payload_writer is None:\n            raise RuntimeError(\"Cannot call write() before prepare()\")\n\n        await self._payload_writer.write(data)\n\n    async def drain(self) -> None:\n        assert not self._eof_sent, \"EOF has already been sent\"\n        assert self._payload_writer is not None, \"Response has not been started\"\n        warnings.warn(\n            \"drain method is deprecated, use await resp.write()\",\n            DeprecationWarning,\n            stacklevel=2,\n        )\n        await self._payload_writer.drain()\n\n    async def write_eof(self, data: bytes = b\"\") -> None:\n        assert isinstance(\n            data, (bytes, bytearray, memoryview)\n        ), \"data argument must be byte-ish (%r)\" % type(data)\n\n        if self._eof_sent:\n            return\n\n        assert self._payload_writer is not None, \"Response has not been started\"\n\n        await self._payload_writer.write_eof(data)\n        self._eof_sent = True\n        self._req = None\n        self._body_length = self._payload_writer.output_size\n        self._payload_writer = None\n\n    def __repr__(self) -> str:\n        if self._eof_sent:\n            info = \"eof\"\n        elif self.prepared:\n            assert self._req is not None\n            info = f\"{self._req.method} {self._req.path} \"\n        else:\n            info = \"not prepared\"\n        return f\"<{self.__class__.__name__} {self.reason} {info}>\"\n\n    def __getitem__(self, key: str) -> Any:\n        return self._state[key]\n\n    def __setitem__(self, key: str, value: Any) -> None:\n        self._state[key] = value\n\n    def __delitem__(self, key: str) -> None:\n        del self._state[key]\n\n    def __len__(self) -> int:\n        return len(self._state)\n\n    def __iter__(self) -> Iterator[str]:\n        return iter(self._state)\n\n    def __hash__(self) -> int:\n        return hash(id(self))\n\n    def __eq__(self, other: object) -> bool:\n        return self is other\n\n\nclass Response(StreamResponse):\n    def __init__(\n        self,\n        *,\n        body: Any = None,\n        status: int = 200,\n        reason: Optional[str] = None,\n        text: Optional[str] = None,\n        headers: Optional[LooseHeaders] = None,\n        content_type: Optional[str] = None,\n        charset: Optional[str] = None,\n        zlib_executor_size: Optional[int] = None,\n        zlib_executor: Optional[Executor] = None,\n    ) -> None:\n        if body is not None and text is not None:\n            raise ValueError(\"body and text are not allowed together\")\n\n        if headers is None:\n            real_headers: CIMultiDict[str] = CIMultiDict()\n        elif not isinstance(headers, CIMultiDict):\n            real_headers = CIMultiDict(headers)\n        else:\n            real_headers = headers  # = cast('CIMultiDict[str]', headers)\n\n        if content_type is not None and \"charset\" in content_type:\n            raise ValueError(\"charset must not be in content_type argument\")\n\n        if text is not None:\n            if hdrs.CONTENT_TYPE in real_headers:\n                if content_type or charset:\n                    raise ValueError(\n                        \"passing both Content-Type header and \"\n                        \"content_type or charset params \"\n                        \"is forbidden\"\n                    )\n            else:\n                # fast path for filling headers\n                if not isinstance(text, str):\n                    raise TypeError(\"text argument must be str (%r)\" % type(text))\n                if content_type is None:\n                    content_type = \"text/plain\"\n                if charset is None:\n                    charset = \"utf-8\"\n                real_headers[hdrs.CONTENT_TYPE] = content_type + \"; charset=\" + charset\n                body = text.encode(charset)\n                text = None\n        else:\n            if hdrs.CONTENT_TYPE in real_headers:\n                if content_type is not None or charset is not None:\n                    raise ValueError(\n                        \"passing both Content-Type header and \"\n                        \"content_type or charset params \"\n                        \"is forbidden\"\n                    )\n            else:\n                if content_type is not None:\n                    if charset is not None:\n                        content_type += \"; charset=\" + charset\n                    real_headers[hdrs.CONTENT_TYPE] = content_type\n\n        super().__init__(status=status, reason=reason, headers=real_headers)\n\n        if text is not None:\n            self.text = text\n        else:\n            self.body = body\n\n        self._compressed_body: Optional[bytes] = None\n        self._zlib_executor_size = zlib_executor_size\n        self._zlib_executor = zlib_executor\n\n    @property\n    def body(self) -> Optional[Union[bytes, Payload]]:\n        return self._body\n\n    @body.setter\n    def body(self, body: Any) -> None:\n        if body is None:\n            self._body = None\n        elif isinstance(body, (bytes, bytearray)):\n            self._body = body\n        else:\n            try:\n                self._body = body = payload.PAYLOAD_REGISTRY.get(body)\n            except payload.LookupError:\n                raise ValueError(\"Unsupported body type %r\" % type(body))\n\n            headers = self._headers\n\n            # set content-type\n            if hdrs.CONTENT_TYPE not in headers:\n                headers[hdrs.CONTENT_TYPE] = body.content_type\n\n            # copy payload headers\n            if body.headers:\n                for key, value in body.headers.items():\n                    if key not in headers:\n                        headers[key] = value\n\n        self._compressed_body = None\n\n    @property\n    def text(self) -> Optional[str]:\n        if self._body is None:\n            return None\n        return self._body.decode(self.charset or \"utf-8\")\n\n    @text.setter\n    def text(self, text: str) -> None:\n        assert text is None or isinstance(\n            text, str\n        ), \"text argument must be str (%r)\" % type(text)\n\n        if self.content_type == \"application/octet-stream\":\n            self.content_type = \"text/plain\"\n        if self.charset is None:\n            self.charset = \"utf-8\"\n\n        self._body = text.encode(self.charset)\n        self._compressed_body = None\n\n    @property\n    def content_length(self) -> Optional[int]:\n        if self._chunked:\n            return None\n\n        if hdrs.CONTENT_LENGTH in self._headers:\n            return super().content_length\n\n        if self._compressed_body is not None:\n            # Return length of the compressed body\n            return len(self._compressed_body)\n        elif isinstance(self._body, Payload):\n            # A payload without content length, or a compressed payload\n            return None\n        elif self._body is not None:\n            return len(self._body)\n        else:\n            return 0\n\n    @content_length.setter\n    def content_length(self, value: Optional[int]) -> None:\n        raise RuntimeError(\"Content length is set automatically\")\n\n    async def write_eof(self, data: bytes = b\"\") -> None:\n        if self._eof_sent:\n            return\n        if self._compressed_body is None:\n            body: Optional[Union[bytes, Payload]] = self._body\n        else:\n            body = self._compressed_body\n        assert not data, f\"data arg is not supported, got {data!r}\"\n        assert self._req is not None\n        assert self._payload_writer is not None\n        if body is not None:\n            if self._must_be_empty_body:\n                await super().write_eof()\n            elif isinstance(self._body, Payload):\n                await self._body.write(self._payload_writer)\n                await super().write_eof()\n            else:\n                await super().write_eof(cast(bytes, body))\n        else:\n            await super().write_eof()\n\n    async def _start(self, request: \"BaseRequest\") -> AbstractStreamWriter:\n        if hdrs.CONTENT_LENGTH in self._headers:\n            if should_remove_content_length(request.method, self.status):\n                del self._headers[hdrs.CONTENT_LENGTH]\n        elif not self._chunked:\n            if isinstance(self._body, Payload):\n                if self._body.size is not None:\n                    self._headers[hdrs.CONTENT_LENGTH] = str(self._body.size)\n            else:\n                body_len = len(self._body) if self._body else \"0\"\n                # https://www.rfc-editor.org/rfc/rfc9110.html#section-8.6-7\n                if body_len != \"0\" or (\n                    self.status != 304 and request.method.upper() != hdrs.METH_HEAD\n                ):\n                    self._headers[hdrs.CONTENT_LENGTH] = str(body_len)\n\n        return await super()._start(request)\n\n    async def _do_start_compression(self, coding: ContentCoding) -> None:\n        if self._chunked or isinstance(self._body, Payload):\n            return await super()._do_start_compression(coding)\n\n        if coding != ContentCoding.identity:\n            # Instead of using _payload_writer.enable_compression,\n            # compress the whole body\n            compressor = ZLibCompressor(\n                encoding=str(coding.value),\n                max_sync_chunk_size=self._zlib_executor_size,\n                executor=self._zlib_executor,\n            )\n            assert self._body is not None\n            if self._zlib_executor_size is None and len(self._body) > 1024 * 1024:\n                warnings.warn(\n                    \"Synchronous compression of large response bodies \"\n                    f\"({len(self._body)} bytes) might block the async event loop. \"\n                    \"Consider providing a custom value to zlib_executor_size/\"\n                    \"zlib_executor response properties or disabling compression on it.\"\n                )\n            self._compressed_body = (\n                await compressor.compress(self._body) + compressor.flush()\n            )\n            assert self._compressed_body is not None\n\n            self._headers[hdrs.CONTENT_ENCODING] = coding.value\n            self._headers[hdrs.CONTENT_LENGTH] = str(len(self._compressed_body))\n\n\ndef json_response(\n    data: Any = sentinel,\n    *,\n    text: Optional[str] = None,\n    body: Optional[bytes] = None,\n    status: int = 200,\n    reason: Optional[str] = None,\n    headers: Optional[LooseHeaders] = None,\n    content_type: str = \"application/json\",\n    dumps: JSONEncoder = json.dumps,\n) -> Response:\n    if data is not sentinel:\n        if text or body:\n            raise ValueError(\"only one of data, text, or body should be specified\")\n        else:\n            text = dumps(data)\n    return Response(\n        text=text,\n        body=body,\n        status=status,\n        reason=reason,\n        headers=headers,\n        content_type=content_type,\n    )\n"}
A user will ask you to solve a task. You should first draft your thinking process (inner monologue). Then, generate the solution.

Your response format must follow the template below:
<think>
Your thoughts or/and draft, like working through an exercise on scratch paper. Be as casual and as long as you want until you are confident to generate a correct solution.
</think>
<solution>
Final solution presented to the user.
</solution>
system
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]
**Title:** HTTP Response Allows Newlines in Reason, Leading to Potential Header Injection

**Description:**
Including newline characters in the `reason` parameter of an HTTP response can lead to unintended header injection, causing malformed responses or security vulnerabilities.

**Example Buggy Code:**
```python
from aiohttp import web

async def handler(request):
    return web.HTTPOk(reason="OK\r\nInjected-Header: value")
```
In this example, the `reason` contains a newline character followed by an additional header. This allows the injection of the `Injected-Header` into the HTTP response.

**Expected Behavior:**
The server should reject any HTTP response `reason` that includes newline characters by raising a `ValueError`. This prevents the injection of unintended headers and ensures the integrity of the HTTP response.

**Actual Behavior:**
The server accepts the `reason` with newline characters without raising an error, allowing additional headers to be injected into the response.

[/ISSUE]
--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.

--- BEGIN FILE ---
```
### aiohttp/web_response.py
import asyncio
import collections.abc
import datetime
import enum
import json
import math
import time
import warnings
import zlib
from concurrent.futures import Executor
from http import HTTPStatus
from http.cookies import SimpleCookie
from typing import (
    TYPE_CHECKING,
    Any,
    Dict,
    Iterator,
    MutableMapping,
    Optional,
    Union,
    cast,
)

from multidict import CIMultiDict, istr

from . import hdrs, payload
from .abc import AbstractStreamWriter
from .compression_utils import ZLibCompressor
from .helpers import (
    ETAG_ANY,
    QUOTED_ETAG_RE,
    ETag,
    HeadersMixin,
    must_be_empty_body,
    parse_http_date,
    rfc822_formatted_time,
    sentinel,
    should_remove_content_length,
    validate_etag_value,
)
from .http import SERVER_SOFTWARE, HttpVersion10, HttpVersion11
from .payload import Payload
from .typedefs import JSONEncoder, LooseHeaders

__all__ = ("ContentCoding", "StreamResponse", "Response", "json_response")


if TYPE_CHECKING:
    from .web_request import BaseRequest

    BaseClass = MutableMapping[str, Any]
else:
    BaseClass = collections.abc.MutableMapping


# TODO(py311): Convert to StrEnum for wider use
class ContentCoding(enum.Enum):
    # The content codings that we have support for.
    #
    # Additional registered codings are listed at:
    # https://www.iana.org/assignments/http-parameters/http-parameters.xhtml#content-coding
    deflate = "deflate"
    gzip = "gzip"
    identity = "identity"


############################################################
# HTTP Response classes
############################################################


class StreamResponse(BaseClass, HeadersMixin):

    _length_check = True

    _body: Union[None, bytes, bytearray, Payload]

    def __init__(
        self,
        *,
        status: int = 200,
        reason: Optional[str] = None,
        headers: Optional[LooseHeaders] = None,
    ) -> None:
        self._body = None
        self._keep_alive: Optional[bool] = None
        self._chunked = False
        self._compression = False
        self._compression_strategy: int = zlib.Z_DEFAULT_STRATEGY
        self._compression_force: Optional[ContentCoding] = None
        self._cookies = SimpleCookie()

        self._req: Optional[BaseRequest] = None
        self._payload_writer: Optional[AbstractStreamWriter] = None
        self._eof_sent = False
        self._must_be_empty_body: Optional[bool] = None
        self._body_length = 0
        self._state: Dict[str, Any] = {}

        if headers is not None:
            self._headers: CIMultiDict[str] = CIMultiDict(headers)
        else:
            self._headers = CIMultiDict()

        self.set_status(status, reason)

    @property
    def prepared(self) -> bool:
        return self._eof_sent or self._payload_writer is not None

    @property
    def task(self) -> "Optional[asyncio.Task[None]]":
        if self._req:
            return self._req.task
        else:
            return None

    @property
    def status(self) -> int:
        return self._status

    @property
    def chunked(self) -> bool:
        return self._chunked

    @property
    def compression(self) -> bool:
        return self._compression

    @property
    def reason(self) -> str:
        return self._reason

    def set_status(
        self,
        status: int,
        reason: Optional[str] = None,
    ) -> None:
        assert (
            not self.prepared
        ), "Cannot change the response status code after the headers have been sent"
        self._status = int(status)
        if reason is None:
            try:
                reason = HTTPStatus(self._status).phrase
            except ValueError:
                reason = ""
        self._reason = reason

    @property
    def keep_alive(self) -> Optional[bool]:
        return self._keep_alive

    def force_close(self) -> None:
        self._keep_alive = False

    @property
    def body_length(self) -> int:
        return self._body_length

    @property
    def output_length(self) -> int:
        warnings.warn("output_length is deprecated", DeprecationWarning)
        assert self._payload_writer
        return self._payload_writer.buffer_size

    def enable_chunked_encoding(self, chunk_size: Optional[int] = None) -> None:
        """Enables automatic chunked transfer encoding."""
        self._chunked = True

        if hdrs.CONTENT_LENGTH in self._headers:
            raise RuntimeError(
                "You can't enable chunked encoding when a content length is set"
            )
        if chunk_size is not None:
            warnings.warn("Chunk size is deprecated #1615", DeprecationWarning)

    def enable_compression(
        self,
        force: Optional[Union[bool, ContentCoding]] = None,
        strategy: int = zlib.Z_DEFAULT_STRATEGY,
    ) -> None:
        """Enables response compression encoding."""
        # Backwards compatibility for when force was a bool <0.17.
        if isinstance(force, bool):
            force = ContentCoding.deflate if force else ContentCoding.identity
            warnings.warn(
                "Using boolean for force is deprecated #3318", DeprecationWarning
            )
        elif force is not None:
            assert isinstance(
                force, ContentCoding
            ), "force should one of None, bool or ContentEncoding"

        self._compression = True
        self._compression_force = force
        self._compression_strategy = strategy

    @property
    def headers(self) -> "CIMultiDict[str]":
        return self._headers

    @property
    def cookies(self) -> SimpleCookie:
        return self._cookies

    def set_cookie(
        self,
        name: str,
        value: str,
        *,
        expires: Optional[str] = None,
        domain: Optional[str] = None,
        max_age: Optional[Union[int, str]] = None,
        path: str = "/",
        secure: Optional[bool] = None,
        httponly: Optional[bool] = None,
        version: Optional[str] = None,
        samesite: Optional[str] = None,
    ) -> None:
        """Set or update response cookie.

        Sets new cookie or updates existent with new value.
        Also updates only those params which are not None.
        """
        old = self._cookies.get(name)
        if old is not None and old.coded_value == "":
            # deleted cookie
            self._cookies.pop(name, None)

        self._cookies[name] = value
        c = self._cookies[name]

        if expires is not None:
            c["expires"] = expires
        elif c.get("expires") == "Thu, 01 Jan 1970 00:00:00 GMT":
            del c["expires"]

        if domain is not None:
            c["domain"] = domain

        if max_age is not None:
            c["max-age"] = str(max_age)
        elif "max-age" in c:
            del c["max-age"]

        c["path"] = path

        if secure is not None:
            c["secure"] = secure
        if httponly is not None:
            c["httponly"] = httponly
        if version is not None:
            c["version"] = version
        if samesite is not None:
            c["samesite"] = samesite

    def del_cookie(
        self,
        name: str,
        *,
        domain: Optional[str] = None,
        path: str = "/",
        secure: Optional[bool] = None,
        httponly: Optional[bool] = None,
        samesite: Optional[str] = None,
    ) -> None:
        """Delete cookie.

        Creates new empty expired cookie.
        """
        # TODO: do we need domain/path here?
        self._cookies.pop(name, None)
        self.set_cookie(
            name,
            "",
            max_age=0,
            expires="Thu, 01 Jan 1970 00:00:00 GMT",
            domain=domain,
            path=path,
            secure=secure,
            httponly=httponly,
            samesite=samesite,
        )

    @property
    def content_length(self) -> Optional[int]:
        # Just a placeholder for adding setter
        return super().content_length

    @content_length.setter
    def content_length(self, value: Optional[int]) -> None:
        if value is not None:
            value = int(value)
            if self._chunked:
                raise RuntimeError(
                    "You can't set content length when chunked encoding is enable"
                )
            self._headers[hdrs.CONTENT_LENGTH] = str(value)
        else:
            self._headers.pop(hdrs.CONTENT_LENGTH, None)

    @property
    def content_type(self) -> str:
        # Just a placeholder for adding setter
        return super().content_type

    @content_type.setter
    def content_type(self, value: str) -> None:
        self.content_type  # read header values if needed
        self._content_type = str(value)
        self._generate_content_type_header()

    @property
    def charset(self) -> Optional[str]:
        # Just a placeholder for adding setter
        return super().charset

    @charset.setter
    def charset(self, value: Optional[str]) -> None:
        ctype = self.content_type  # read header values if needed
        if ctype == "application/octet-stream":
            raise RuntimeError(
                "Setting charset for application/octet-stream "
                "doesn't make sense, setup content_type first"
            )
        assert self._content_dict is not None
        if value is None:
            self._content_dict.pop("charset", None)
        else:
            self._content_dict["charset"] = str(value).lower()
        self._generate_content_type_header()

    @property
    def last_modified(self) -> Optional[datetime.datetime]:
        """The value of Last-Modified HTTP header, or None.

        This header is represented as a `datetime` object.
        """
        return parse_http_date(self._headers.get(hdrs.LAST_MODIFIED))

    @last_modified.setter
    def last_modified(
        self, value: Optional[Union[int, float, datetime.datetime, str]]
    ) -> None:
        if value is None:
            self._headers.pop(hdrs.LAST_MODIFIED, None)
        elif isinstance(value, (int, float)):
            self._headers[hdrs.LAST_MODIFIED] = time.strftime(
                "%a, %d %b %Y %H:%M:%S GMT", time.gmtime(math.ceil(value))
            )
        elif isinstance(value, datetime.datetime):
            self._headers[hdrs.LAST_MODIFIED] = time.strftime(
                "%a, %d %b %Y %H:%M:%S GMT", value.utctimetuple()
            )
        elif isinstance(value, str):
            self._headers[hdrs.LAST_MODIFIED] = value

    @property
    def etag(self) -> Optional[ETag]:
        quoted_value = self._headers.get(hdrs.ETAG)
        if not quoted_value:
            return None
        elif quoted_value == ETAG_ANY:
            return ETag(value=ETAG_ANY)
        match = QUOTED_ETAG_RE.fullmatch(quoted_value)
        if not match:
            return None
        is_weak, value = match.group(1, 2)
        return ETag(
            is_weak=bool(is_weak),
            value=value,
        )

    @etag.setter
    def etag(self, value: Optional[Union[ETag, str]]) -> None:
        if value is None:
            self._headers.pop(hdrs.ETAG, None)
        elif (isinstance(value, str) and value == ETAG_ANY) or (
            isinstance(value, ETag) and value.value == ETAG_ANY
        ):
            self._headers[hdrs.ETAG] = ETAG_ANY
        elif isinstance(value, str):
            validate_etag_value(value)
            self._headers[hdrs.ETAG] = f'"{value}"'
        elif isinstance(value, ETag) and isinstance(value.value, str):
            validate_etag_value(value.value)
            hdr_value = f'W/"{value.value}"' if value.is_weak else f'"{value.value}"'
            self._headers[hdrs.ETAG] = hdr_value
        else:
            raise ValueError(
                f"Unsupported etag type: {type(value)}. "
                f"etag must be str, ETag or None"
            )

    def _generate_content_type_header(
        self, CONTENT_TYPE: istr = hdrs.CONTENT_TYPE
    ) -> None:
        assert self._content_dict is not None
        assert self._content_type is not None
        params = "; ".join(f"{k}={v}" for k, v in self._content_dict.items())
        if params:
            ctype = self._content_type + "; " + params
        else:
            ctype = self._content_type
        self._headers[CONTENT_TYPE] = ctype

    async def _do_start_compression(self, coding: ContentCoding) -> None:
        if coding != ContentCoding.identity:
            assert self._payload_writer is not None
            self._headers[hdrs.CONTENT_ENCODING] = coding.value
            self._payload_writer.enable_compression(
                coding.value, self._compression_strategy
            )
            # Compressed payload may have different content length,
            # remove the header
            self._headers.popall(hdrs.CONTENT_LENGTH, None)

    async def _start_compression(self, request: "BaseRequest") -> None:
        if self._compression_force:
            await self._do_start_compression(self._compression_force)
        else:
            # Encoding comparisons should be case-insensitive
            # https://www.rfc-editor.org/rfc/rfc9110#section-8.4.1
            accept_encoding = request.headers.get(hdrs.ACCEPT_ENCODING, "").lower()
            for coding in ContentCoding:
                if coding.value in accept_encoding:
                    await self._do_start_compression(coding)
                    return

    async def prepare(self, request: "BaseRequest") -> Optional[AbstractStreamWriter]:
        if self._eof_sent:
            return None
        if self._payload_writer is not None:
            return self._payload_writer
        self._must_be_empty_body = must_be_empty_body(request.method, self.status)
        return await self._start(request)

    async def _start(self, request: "BaseRequest") -> AbstractStreamWriter:
        self._req = request
        writer = self._payload_writer = request._payload_writer

        await self._prepare_headers()
        await request._prepare_hook(self)
        await self._write_headers()

        return writer

    async def _prepare_headers(self) -> None:
        request = self._req
        assert request is not None
        writer = self._payload_writer
        assert writer is not None
        keep_alive = self._keep_alive
        if keep_alive is None:
            keep_alive = request.keep_alive
        self._keep_alive = keep_alive

        version = request.version

        headers = self._headers
        for cookie in self._cookies.values():
            value = cookie.output(header="")[1:]
            headers.add(hdrs.SET_COOKIE, value)

        if self._compression:
            await self._start_compression(request)

        if self._chunked:
            if version != HttpVersion11:
                raise RuntimeError(
                    "Using chunked encoding is forbidden "
                    "for HTTP/{0.major}.{0.minor}".format(request.version)
                )
            if not self._must_be_empty_body:
                writer.enable_chunking()
                headers[hdrs.TRANSFER_ENCODING] = "chunked"
            if hdrs.CONTENT_LENGTH in headers:
                del headers[hdrs.CONTENT_LENGTH]
        elif self._length_check:
            writer.length = self.content_length
            if writer.length is None:
                if version >= HttpVersion11:
                    if not self._must_be_empty_body:
                        writer.enable_chunking()
                        headers[hdrs.TRANSFER_ENCODING] = "chunked"
                elif not self._must_be_empty_body:
                    keep_alive = False

        # HTTP 1.1: https://tools.ietf.org/html/rfc7230#section-3.3.2
        # HTTP 1.0: https://tools.ietf.org/html/rfc1945#section-10.4
        if self._must_be_empty_body:
            if hdrs.CONTENT_LENGTH in headers and should_remove_content_length(
                request.method, self.status
            ):
                del headers[hdrs.CONTENT_LENGTH]
            # https://datatracker.ietf.org/doc/html/rfc9112#section-6.1-10
            # https://datatracker.ietf.org/doc/html/rfc9112#section-6.1-13
            if hdrs.TRANSFER_ENCODING in headers:
                del headers[hdrs.TRANSFER_ENCODING]
        elif self.content_length != 0:
            # https://www.rfc-editor.org/rfc/rfc9110#section-8.3-5
            headers.setdefault(hdrs.CONTENT_TYPE, "application/octet-stream")
        headers.setdefault(hdrs.DATE, rfc822_formatted_time())
        headers.setdefault(hdrs.SERVER, SERVER_SOFTWARE)

        # connection header
        if hdrs.CONNECTION not in headers:
            if keep_alive:
                if version == HttpVersion10:
                    headers[hdrs.CONNECTION] = "keep-alive"
            else:
                if version == HttpVersion11:
                    headers[hdrs.CONNECTION] = "close"

    async def _write_headers(self) -> None:
        request = self._req
        assert request is not None
        writer = self._payload_writer
        assert writer is not None
        # status line
        version = request.version
        status_line = f"HTTP/{version[0]}.{version[1]} {self._status} {self._reason}"
        await writer.write_headers(status_line, self._headers)

    async def write(self, data: bytes) -> None:
        assert isinstance(
            data, (bytes, bytearray, memoryview)
        ), "data argument must be byte-ish (%r)" % type(data)

        if self._eof_sent:
            raise RuntimeError("Cannot call write() after write_eof()")
        if self._payload_writer is None:
            raise RuntimeError("Cannot call write() before prepare()")

        await self._payload_writer.write(data)

    async def drain(self) -> None:
        assert not self._eof_sent, "EOF has already been sent"
        assert self._payload_writer is not None, "Response has not been started"
        warnings.warn(
            "drain method is deprecated, use await resp.write()",
            DeprecationWarning,
            stacklevel=2,
        )
        await self._payload_writer.drain()

    async def write_eof(self, data: bytes = b"") -> None:
        assert isinstance(
            data, (bytes, bytearray, memoryview)
        ), "data argument must be byte-ish (%r)" % type(data)

        if self._eof_sent:
            return

        assert self._payload_writer is not None, "Response has not been started"

        await self._payload_writer.write_eof(data)
        self._eof_sent = True
        self._req = None
        self._body_length = self._payload_writer.output_size
        self._payload_writer = None

    def __repr__(self) -> str:
        if self._eof_sent:
            info = "eof"
        elif self.prepared:
            assert self._req is not None
            info = f"{self._req.method} {self._req.path} "
        else:
            info = "not prepared"
        return f"<{self.__class__.__name__} {self.reason} {info}>"

    def __getitem__(self, key: str) -> Any:
        return self._state[key]

    def __setitem__(self, key: str, value: Any) -> None:
        self._state[key] = value

    def __delitem__(self, key: str) -> None:
        del self._state[key]

    def __len__(self) -> int:
        return len(self._state)

    def __iter__(self) -> Iterator[str]:
        return iter(self._state)

    def __hash__(self) -> int:
        return hash(id(self))

    def __eq__(self, other: object) -> bool:
        return self is other


class Response(StreamResponse):
    def __init__(
        self,
        *,
        body: Any = None,
        status: int = 200,
        reason: Optional[str] = None,
        text: Optional[str] = None,
        headers: Optional[LooseHeaders] = None,
        content_type: Optional[str] = None,
        charset: Optional[str] = None,
        zlib_executor_size: Optional[int] = None,
        zlib_executor: Optional[Executor] = None,
    ) -> None:
        if body is not None and text is not None:
            raise ValueError("body and text are not allowed together")

        if headers is None:
            real_headers: CIMultiDict[str] = CIMultiDict()
        elif not isinstance(headers, CIMultiDict):
            real_headers = CIMultiDict(headers)
        else:
            real_headers = headers  # = cast('CIMultiDict[str]', headers)

        if content_type is not None and "charset" in content_type:
            raise ValueError("charset must not be in content_type argument")

        if text is not None:
            if hdrs.CONTENT_TYPE in real_headers:
                if content_type or charset:
                    raise ValueError(
                        "passing both Content-Type header and "
                        "content_type or charset params "
                        "is forbidden"
                    )
            else:
                # fast path for filling headers
                if not isinstance(text, str):
                    raise TypeError("text argument must be str (%r)" % type(text))
                if content_type is None:
                    content_type = "text/plain"
                if charset is None:
                    charset = "utf-8"
                real_headers[hdrs.CONTENT_TYPE] = content_type + "; charset=" + charset
                body = text.encode(charset)
                text = None
        else:
            if hdrs.CONTENT_TYPE in real_headers:
                if content_type is not None or charset is not None:
                    raise ValueError(
                        "passing both Content-Type header and "
                        "content_type or charset params "
                        "is forbidden"
                    )
            else:
                if content_type is not None:
                    if charset is not None:
                        content_type += "; charset=" + charset
                    real_headers[hdrs.CONTENT_TYPE] = content_type

        super().__init__(status=status, reason=reason, headers=real_headers)

        if text is not None:
            self.text = text
        else:
            self.body = body

        self._compressed_body: Optional[bytes] = None
        self._zlib_executor_size = zlib_executor_size
        self._zlib_executor = zlib_executor

    @property
    def body(self) -> Optional[Union[bytes, Payload]]:
        return self._body

    @body.setter
    def body(self, body: Any) -> None:
        if body is None:
            self._body = None
        elif isinstance(body, (bytes, bytearray)):
            self._body = body
        else:
            try:
                self._body = body = payload.PAYLOAD_REGISTRY.get(body)
            except payload.LookupError:
                raise ValueError("Unsupported body type %r" % type(body))

            headers = self._headers

            # set content-type
            if hdrs.CONTENT_TYPE not in headers:
                headers[hdrs.CONTENT_TYPE] = body.content_type

            # copy payload headers
            if body.headers:
                for key, value in body.headers.items():
                    if key not in headers:
                        headers[key] = value

        self._compressed_body = None

    @property
    def text(self) -> Optional[str]:
        if self._body is None:
            return None
        return self._body.decode(self.charset or "utf-8")

    @text.setter
    def text(self, text: str) -> None:
        assert text is None or isinstance(
            text, str
        ), "text argument must be str (%r)" % type(text)

        if self.content_type == "application/octet-stream":
            self.content_type = "text/plain"
        if self.charset is None:
            self.charset = "utf-8"

        self._body = text.encode(self.charset)
        self._compressed_body = None

    @property
    def content_length(self) -> Optional[int]:
        if self._chunked:
            return None

        if hdrs.CONTENT_LENGTH in self._headers:
            return super().content_length

        if self._compressed_body is not None:
            # Return length of the compressed body
            return len(self._compressed_body)
        elif isinstance(self._body, Payload):
            # A payload without content length, or a compressed payload
            return None
        elif self._body is not None:
            return len(self._body)
        else:
            return 0

    @content_length.setter
    def content_length(self, value: Optional[int]) -> None:
        raise RuntimeError("Content length is set automatically")

    async def write_eof(self, data: bytes = b"") -> None:
        if self._eof_sent:
            return
        if self._compressed_body is None:
            body: Optional[Union[bytes, Payload]] = self._body
        else:
            body = self._compressed_body
        assert not data, f"data arg is not supported, got {data!r}"
        assert self._req is not None
        assert self._payload_writer is not None
        if body is not None:
            if self._must_be_empty_body:
                await super().write_eof()
            elif isinstance(self._body, Payload):
                await self._body.write(self._payload_writer)
                await super().write_eof()
            else:
                await super().write_eof(cast(bytes, body))
        else:
            await super().write_eof()

    async def _start(self, request: "BaseRequest") -> AbstractStreamWriter:
        if hdrs.CONTENT_LENGTH in self._headers:
            if should_remove_content_length(request.method, self.status):
                del self._headers[hdrs.CONTENT_LENGTH]
        elif not self._chunked:
            if isinstance(self._body, Payload):
                if self._body.size is not None:
                    self._headers[hdrs.CONTENT_LENGTH] = str(self._body.size)
            else:
                body_len = len(self._body) if self._body else "0"
                # https://www.rfc-editor.org/rfc/rfc9110.html#section-8.6-7
                if body_len != "0" or (
                    self.status != 304 and request.method.upper() != hdrs.METH_HEAD
                ):
                    self._headers[hdrs.CONTENT_LENGTH] = str(body_len)

        return await super()._start(request)

    async def _do_start_compression(self, coding: ContentCoding) -> None:
        if self._chunked or isinstance(self._body, Payload):
            return await super()._do_start_compression(coding)

        if coding != ContentCoding.identity:
            # Instead of using _payload_writer.enable_compression,
            # compress the whole body
            compressor = ZLibCompressor(
                encoding=str(coding.value),
                max_sync_chunk_size=self._zlib_executor_size,
                executor=self._zlib_executor,
            )
            assert self._body is not None
            if self._zlib_executor_size is None and len(self._body) > 1024 * 1024:
                warnings.warn(
                    "Synchronous compression of large response bodies "
                    f"({len(self._body)} bytes) might block the async event loop. "
                    "Consider providing a custom value to zlib_executor_size/"
                    "zlib_executor response properties or disabling compression on it."
                )
            self._compressed_body = (
                await compressor.compress(self._body) + compressor.flush()
            )
            assert self._compressed_body is not None

            self._headers[hdrs.CONTENT_ENCODING] = coding.value
            self._headers[hdrs.CONTENT_LENGTH] = str(len(self._compressed_body))


def json_response(
    data: Any = sentinel,
    *,
    text: Optional[str] = None,
    body: Optional[bytes] = None,
    status: int = 200,
    reason: Optional[str] = None,
    headers: Optional[LooseHeaders] = None,
    content_type: str = "application/json",
    dumps: JSONEncoder = json.dumps,
) -> Response:
    if data is not sentinel:
        if text or body:
            raise ValueError("only one of data, text, or body should be specified")
        else:
            text = dumps(data)
    return Response(
        text=text,
        body=body,
        status=status,
        reason=reason,
        headers=headers,
        content_type=content_type,
    )

```
--- END FILE ---

Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.

Every *SEARCH/REPLACE* edit must use this format:
1. The file path
2. The start of search block: <<<<<<< SEARCH
3. A contiguous chunk of lines to search for in the existing source code
4. The dividing line: =======
5. The lines to replace into the source code
6. The end of the replace block: >>>>>>> REPLACE

Here is an example:

```python
### mathweb/flask/app.py
<<<<<<< SEARCH
from flask import Flask
=======
import math
from flask import Flask
>>>>>>> REPLACE
```
</solution>

Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
Wrap each *SEARCH/REPLACE* edit in a code block as shown in the example above. If you have multiple *SEARCH/REPLACE* edits, use a separate code block for each one.
user