{
    "file_diffs": [
        {
            "old_file_content": "",
            "new_file_content": "Fixed ``ClientWebSocketResponse.close_code`` being erroneously set to ``None`` when there are concurrent async tasks receiving data and closing the connection.\n",
            "header": {
                "file": {
                    "path": "CHANGES/7306.bugfix"
                },
                "misc_line": "new file mode 100644"
            },
            "index_line": {
                "old_commit_hash": "00000000",
                "new_commit_hash": "173236d2",
                "mode": ""
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "/dev/null"
            },
            "plus_file": {
                "path": "b/CHANGES/7306.bugfix"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 0,
                            "length": 0
                        },
                        "new_range": {
                            "start": 1,
                            "length": null
                        },
                        "section": ""
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "Fixed ``ClientWebSocketResponse.close_code`` being erroneously set to ``None`` when there are concurrent async tasks receiving data and closing the connection.",
                                "type": "added"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "\"\"\"WebSocket client for asyncio.\"\"\"\n\nimport asyncio\nimport sys\nfrom typing import Any, Optional, cast\n\nfrom .client_exceptions import ClientError\nfrom .client_reqrep import ClientResponse\nfrom .helpers import call_later, set_result\nfrom .http import (\n    WS_CLOSED_MESSAGE,\n    WS_CLOSING_MESSAGE,\n    WebSocketError,\n    WSCloseCode,\n    WSMessage,\n    WSMsgType,\n)\nfrom .http_websocket import WebSocketWriter  # WSMessage\nfrom .streams import EofStream, FlowControlDataQueue\nfrom .typedefs import (\n    DEFAULT_JSON_DECODER,\n    DEFAULT_JSON_ENCODER,\n    JSONDecoder,\n    JSONEncoder,\n)\n\nif sys.version_info >= (3, 11):\n    import asyncio as async_timeout\nelse:\n    import async_timeout\n\n\nclass ClientWebSocketResponse:\n    def __init__(\n        self,\n        reader: \"FlowControlDataQueue[WSMessage]\",\n        writer: WebSocketWriter,\n        protocol: Optional[str],\n        response: ClientResponse,\n        timeout: float,\n        autoclose: bool,\n        autoping: bool,\n        loop: asyncio.AbstractEventLoop,\n        *,\n        receive_timeout: Optional[float] = None,\n        heartbeat: Optional[float] = None,\n        compress: int = 0,\n        client_notakeover: bool = False,\n    ) -> None:\n        self._response = response\n        self._conn = response.connection\n\n        self._writer = writer\n        self._reader = reader\n        self._protocol = protocol\n        self._closed = False\n        self._closing = False\n        self._close_code: Optional[int] = None\n        self._timeout = timeout\n        self._receive_timeout = receive_timeout\n        self._autoclose = autoclose\n        self._autoping = autoping\n        self._heartbeat = heartbeat\n        self._heartbeat_cb: Optional[asyncio.TimerHandle] = None\n        if heartbeat is not None:\n            self._pong_heartbeat = heartbeat / 2.0\n        self._pong_response_cb: Optional[asyncio.TimerHandle] = None\n        self._loop = loop\n        self._waiting: Optional[asyncio.Future[bool]] = None\n        self._exception: Optional[BaseException] = None\n        self._compress = compress\n        self._client_notakeover = client_notakeover\n\n        self._reset_heartbeat()\n\n    def _cancel_heartbeat(self) -> None:\n        if self._pong_response_cb is not None:\n            self._pong_response_cb.cancel()\n            self._pong_response_cb = None\n\n        if self._heartbeat_cb is not None:\n            self._heartbeat_cb.cancel()\n            self._heartbeat_cb = None\n\n    def _reset_heartbeat(self) -> None:\n        self._cancel_heartbeat()\n\n        if self._heartbeat is not None:\n            self._heartbeat_cb = call_later(\n                self._send_heartbeat,\n                self._heartbeat,\n                self._loop,\n                timeout_ceil_threshold=self._conn._connector._timeout_ceil_threshold\n                if self._conn is not None\n                else 5,\n            )\n\n    def _send_heartbeat(self) -> None:\n        if self._heartbeat is not None and not self._closed:\n            # fire-and-forget a task is not perfect but maybe ok for\n            # sending ping. Otherwise we need a long-living heartbeat\n            # task in the class.\n            self._loop.create_task(self._writer.ping())\n\n            if self._pong_response_cb is not None:\n                self._pong_response_cb.cancel()\n            self._pong_response_cb = call_later(\n                self._pong_not_received,\n                self._pong_heartbeat,\n                self._loop,\n                timeout_ceil_threshold=self._conn._connector._timeout_ceil_threshold\n                if self._conn is not None\n                else 5,\n            )\n\n    def _pong_not_received(self) -> None:\n        if not self._closed:\n            self._closed = True\n            self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n            self._exception = asyncio.TimeoutError()\n            self._response.close()\n\n    @property\n    def closed(self) -> bool:\n        return self._closed\n\n    @property\n    def close_code(self) -> Optional[int]:\n        return self._close_code\n\n    @property\n    def protocol(self) -> Optional[str]:\n        return self._protocol\n\n    @property\n    def compress(self) -> int:\n        return self._compress\n\n    @property\n    def client_notakeover(self) -> bool:\n        return self._client_notakeover\n\n    def get_extra_info(self, name: str, default: Any = None) -> Any:\n        \"\"\"extra info from connection transport\"\"\"\n        conn = self._response.connection\n        if conn is None:\n            return default\n        transport = conn.transport\n        if transport is None:\n            return default\n        return transport.get_extra_info(name, default)\n\n    def exception(self) -> Optional[BaseException]:\n        return self._exception\n\n    async def ping(self, message: bytes = b\"\") -> None:\n        await self._writer.ping(message)\n\n    async def pong(self, message: bytes = b\"\") -> None:\n        await self._writer.pong(message)\n\n    async def send_str(self, data: str, compress: Optional[int] = None) -> None:\n        if not isinstance(data, str):\n            raise TypeError(\"data argument must be str (%r)\" % type(data))\n        await self._writer.send(data, binary=False, compress=compress)\n\n    async def send_bytes(self, data: bytes, compress: Optional[int] = None) -> None:\n        if not isinstance(data, (bytes, bytearray, memoryview)):\n            raise TypeError(\"data argument must be byte-ish (%r)\" % type(data))\n        await self._writer.send(data, binary=True, compress=compress)\n\n    async def send_json(\n        self,\n        data: Any,\n        compress: Optional[int] = None,\n        *,\n        dumps: JSONEncoder = DEFAULT_JSON_ENCODER,\n    ) -> None:\n        await self.send_str(dumps(data), compress=compress)\n\n    async def close(self, *, code: int = WSCloseCode.OK, message: bytes = b\"\") -> bool:\n        # we need to break `receive()` cycle first,\n        # `close()` may be called from different task\n        if self._waiting is not None and not self._closed:\n            self._reader.feed_data(WS_CLOSING_MESSAGE, 0)\n            await self._waiting\n\n        if not self._closed:\n            self._cancel_heartbeat()\n            self._closed = True\n            try:\n                await self._writer.close(code, message)\n            except asyncio.CancelledError:\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                self._response.close()\n                raise\n            except Exception as exc:\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                self._exception = exc\n                self._response.close()\n                return True\n\n            if self._closing:\n                self._response.close()\n                return True\n\n            while True:\n                try:\n                    async with async_timeout.timeout(self._timeout):\n                        msg = await self._reader.read()\n                except asyncio.CancelledError:\n                    self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                    self._response.close()\n                    raise\n                except Exception as exc:\n                    self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                    self._exception = exc\n                    self._response.close()\n                    return True\n\n                if msg.type == WSMsgType.CLOSE:\n                    self._close_code = msg.data\n                    self._response.close()\n                    return True\n        else:\n            return False\n\n    async def receive(self, timeout: Optional[float] = None) -> WSMessage:\n        while True:\n            if self._waiting is not None:\n                raise RuntimeError(\"Concurrent call to receive() is not allowed\")\n\n            if self._closed:\n                return WS_CLOSED_MESSAGE\n            elif self._closing:\n                await self.close()\n                return WS_CLOSED_MESSAGE\n\n            try:\n                self._waiting = self._loop.create_future()\n                try:\n                    async with async_timeout.timeout(timeout or self._receive_timeout):\n                        msg = await self._reader.read()\n                    self._reset_heartbeat()\n                finally:\n                    waiter = self._waiting\n                    self._waiting = None\n                    set_result(waiter, True)\n            except (asyncio.CancelledError, asyncio.TimeoutError):\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                raise\n            except EofStream:\n                self._close_code = WSCloseCode.OK\n                await self.close()\n                return WSMessage(WSMsgType.CLOSED, None, None)\n            except ClientError:\n                self._closed = True\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                return WS_CLOSED_MESSAGE\n            except WebSocketError as exc:\n                self._close_code = exc.code\n                await self.close(code=exc.code)\n                return WSMessage(WSMsgType.ERROR, exc, None)\n            except Exception as exc:\n                self._exception = exc\n                self._closing = True\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                await self.close()\n                return WSMessage(WSMsgType.ERROR, exc, None)\n\n            if msg.type == WSMsgType.CLOSE:\n                self._closing = True\n                self._close_code = msg.data\n                if not self._closed and self._autoclose:\n                    await self.close()\n            elif msg.type == WSMsgType.CLOSING:\n                self._closing = True\n            elif msg.type == WSMsgType.PING and self._autoping:\n                await self.pong(msg.data)\n                continue\n            elif msg.type == WSMsgType.PONG and self._autoping:\n                continue\n\n            return msg\n\n    async def receive_str(self, *, timeout: Optional[float] = None) -> str:\n        msg = await self.receive(timeout)\n        if msg.type != WSMsgType.TEXT:\n            raise TypeError(f\"Received message {msg.type}:{msg.data!r} is not str\")\n        return cast(str, msg.data)\n\n    async def receive_bytes(self, *, timeout: Optional[float] = None) -> bytes:\n        msg = await self.receive(timeout)\n        if msg.type != WSMsgType.BINARY:\n            raise TypeError(f\"Received message {msg.type}:{msg.data!r} is not bytes\")\n        return cast(bytes, msg.data)\n\n    async def receive_json(\n        self,\n        *,\n        loads: JSONDecoder = DEFAULT_JSON_DECODER,\n        timeout: Optional[float] = None,\n    ) -> Any:\n        data = await self.receive_str(timeout=timeout)\n        return loads(data)\n\n    def __aiter__(self) -> \"ClientWebSocketResponse\":\n        return self\n\n    async def __anext__(self) -> WSMessage:\n        msg = await self.receive()\n        if msg.type in (WSMsgType.CLOSE, WSMsgType.CLOSING, WSMsgType.CLOSED):\n            raise StopAsyncIteration\n        return msg\n",
            "new_file_content": "\"\"\"WebSocket client for asyncio.\"\"\"\n\nimport asyncio\nimport sys\nfrom typing import Any, Optional, cast\n\nfrom .client_exceptions import ClientError\nfrom .client_reqrep import ClientResponse\nfrom .helpers import call_later, set_result\nfrom .http import (\n    WS_CLOSED_MESSAGE,\n    WS_CLOSING_MESSAGE,\n    WebSocketError,\n    WSCloseCode,\n    WSMessage,\n    WSMsgType,\n)\nfrom .http_websocket import WebSocketWriter  # WSMessage\nfrom .streams import EofStream, FlowControlDataQueue\nfrom .typedefs import (\n    DEFAULT_JSON_DECODER,\n    DEFAULT_JSON_ENCODER,\n    JSONDecoder,\n    JSONEncoder,\n)\n\nif sys.version_info >= (3, 11):\n    import asyncio as async_timeout\nelse:\n    import async_timeout\n\n\nclass ClientWebSocketResponse:\n    def __init__(\n        self,\n        reader: \"FlowControlDataQueue[WSMessage]\",\n        writer: WebSocketWriter,\n        protocol: Optional[str],\n        response: ClientResponse,\n        timeout: float,\n        autoclose: bool,\n        autoping: bool,\n        loop: asyncio.AbstractEventLoop,\n        *,\n        receive_timeout: Optional[float] = None,\n        heartbeat: Optional[float] = None,\n        compress: int = 0,\n        client_notakeover: bool = False,\n    ) -> None:\n        self._response = response\n        self._conn = response.connection\n\n        self._writer = writer\n        self._reader = reader\n        self._protocol = protocol\n        self._closed = False\n        self._closing = False\n        self._close_code: Optional[int] = None\n        self._timeout = timeout\n        self._receive_timeout = receive_timeout\n        self._autoclose = autoclose\n        self._autoping = autoping\n        self._heartbeat = heartbeat\n        self._heartbeat_cb: Optional[asyncio.TimerHandle] = None\n        if heartbeat is not None:\n            self._pong_heartbeat = heartbeat / 2.0\n        self._pong_response_cb: Optional[asyncio.TimerHandle] = None\n        self._loop = loop\n        self._waiting: Optional[asyncio.Future[bool]] = None\n        self._exception: Optional[BaseException] = None\n        self._compress = compress\n        self._client_notakeover = client_notakeover\n\n        self._reset_heartbeat()\n\n    def _cancel_heartbeat(self) -> None:\n        if self._pong_response_cb is not None:\n            self._pong_response_cb.cancel()\n            self._pong_response_cb = None\n\n        if self._heartbeat_cb is not None:\n            self._heartbeat_cb.cancel()\n            self._heartbeat_cb = None\n\n    def _reset_heartbeat(self) -> None:\n        self._cancel_heartbeat()\n\n        if self._heartbeat is not None:\n            self._heartbeat_cb = call_later(\n                self._send_heartbeat,\n                self._heartbeat,\n                self._loop,\n                timeout_ceil_threshold=self._conn._connector._timeout_ceil_threshold\n                if self._conn is not None\n                else 5,\n            )\n\n    def _send_heartbeat(self) -> None:\n        if self._heartbeat is not None and not self._closed:\n            # fire-and-forget a task is not perfect but maybe ok for\n            # sending ping. Otherwise we need a long-living heartbeat\n            # task in the class.\n            self._loop.create_task(self._writer.ping())\n\n            if self._pong_response_cb is not None:\n                self._pong_response_cb.cancel()\n            self._pong_response_cb = call_later(\n                self._pong_not_received,\n                self._pong_heartbeat,\n                self._loop,\n                timeout_ceil_threshold=self._conn._connector._timeout_ceil_threshold\n                if self._conn is not None\n                else 5,\n            )\n\n    def _pong_not_received(self) -> None:\n        if not self._closed:\n            self._closed = True\n            self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n            self._exception = asyncio.TimeoutError()\n            self._response.close()\n\n    @property\n    def closed(self) -> bool:\n        return self._closed\n\n    @property\n    def close_code(self) -> Optional[int]:\n        return self._close_code\n\n    @property\n    def protocol(self) -> Optional[str]:\n        return self._protocol\n\n    @property\n    def compress(self) -> int:\n        return self._compress\n\n    @property\n    def client_notakeover(self) -> bool:\n        return self._client_notakeover\n\n    def get_extra_info(self, name: str, default: Any = None) -> Any:\n        \"\"\"extra info from connection transport\"\"\"\n        conn = self._response.connection\n        if conn is None:\n            return default\n        transport = conn.transport\n        if transport is None:\n            return default\n        return transport.get_extra_info(name, default)\n\n    def exception(self) -> Optional[BaseException]:\n        return self._exception\n\n    async def ping(self, message: bytes = b\"\") -> None:\n        await self._writer.ping(message)\n\n    async def pong(self, message: bytes = b\"\") -> None:\n        await self._writer.pong(message)\n\n    async def send_str(self, data: str, compress: Optional[int] = None) -> None:\n        if not isinstance(data, str):\n            raise TypeError(\"data argument must be str (%r)\" % type(data))\n        await self._writer.send(data, binary=False, compress=compress)\n\n    async def send_bytes(self, data: bytes, compress: Optional[int] = None) -> None:\n        if not isinstance(data, (bytes, bytearray, memoryview)):\n            raise TypeError(\"data argument must be byte-ish (%r)\" % type(data))\n        await self._writer.send(data, binary=True, compress=compress)\n\n    async def send_json(\n        self,\n        data: Any,\n        compress: Optional[int] = None,\n        *,\n        dumps: JSONEncoder = DEFAULT_JSON_ENCODER,\n    ) -> None:\n        await self.send_str(dumps(data), compress=compress)\n\n    async def close(self, *, code: int = WSCloseCode.OK, message: bytes = b\"\") -> bool:\n        # we need to break `receive()` cycle first,\n        # `close()` may be called from different task\n        if self._waiting is not None and not self._closing:\n            self._closing = True\n            self._reader.feed_data(WS_CLOSING_MESSAGE, 0)\n            await self._waiting\n\n        if not self._closed:\n            self._cancel_heartbeat()\n            self._closed = True\n            try:\n                await self._writer.close(code, message)\n            except asyncio.CancelledError:\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                self._response.close()\n                raise\n            except Exception as exc:\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                self._exception = exc\n                self._response.close()\n                return True\n\n            if self._close_code:\n                self._response.close()\n                return True\n\n            while True:\n                try:\n                    async with async_timeout.timeout(self._timeout):\n                        msg = await self._reader.read()\n                except asyncio.CancelledError:\n                    self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                    self._response.close()\n                    raise\n                except Exception as exc:\n                    self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                    self._exception = exc\n                    self._response.close()\n                    return True\n\n                if msg.type == WSMsgType.CLOSE:\n                    self._close_code = msg.data\n                    self._response.close()\n                    return True\n        else:\n            return False\n\n    async def receive(self, timeout: Optional[float] = None) -> WSMessage:\n        while True:\n            if self._waiting is not None:\n                raise RuntimeError(\"Concurrent call to receive() is not allowed\")\n\n            if self._closed:\n                return WS_CLOSED_MESSAGE\n            elif self._closing:\n                await self.close()\n                return WS_CLOSED_MESSAGE\n\n            try:\n                self._waiting = self._loop.create_future()\n                try:\n                    async with async_timeout.timeout(timeout or self._receive_timeout):\n                        msg = await self._reader.read()\n                    self._reset_heartbeat()\n                finally:\n                    waiter = self._waiting\n                    self._waiting = None\n                    set_result(waiter, True)\n            except (asyncio.CancelledError, asyncio.TimeoutError):\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                raise\n            except EofStream:\n                self._close_code = WSCloseCode.OK\n                await self.close()\n                return WSMessage(WSMsgType.CLOSED, None, None)\n            except ClientError:\n                self._closed = True\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                return WS_CLOSED_MESSAGE\n            except WebSocketError as exc:\n                self._close_code = exc.code\n                await self.close(code=exc.code)\n                return WSMessage(WSMsgType.ERROR, exc, None)\n            except Exception as exc:\n                self._exception = exc\n                self._closing = True\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                await self.close()\n                return WSMessage(WSMsgType.ERROR, exc, None)\n\n            if msg.type == WSMsgType.CLOSE:\n                self._closing = True\n                self._close_code = msg.data\n                if not self._closed and self._autoclose:\n                    await self.close()\n            elif msg.type == WSMsgType.CLOSING:\n                self._closing = True\n            elif msg.type == WSMsgType.PING and self._autoping:\n                await self.pong(msg.data)\n                continue\n            elif msg.type == WSMsgType.PONG and self._autoping:\n                continue\n\n            return msg\n\n    async def receive_str(self, *, timeout: Optional[float] = None) -> str:\n        msg = await self.receive(timeout)\n        if msg.type != WSMsgType.TEXT:\n            raise TypeError(f\"Received message {msg.type}:{msg.data!r} is not str\")\n        return cast(str, msg.data)\n\n    async def receive_bytes(self, *, timeout: Optional[float] = None) -> bytes:\n        msg = await self.receive(timeout)\n        if msg.type != WSMsgType.BINARY:\n            raise TypeError(f\"Received message {msg.type}:{msg.data!r} is not bytes\")\n        return cast(bytes, msg.data)\n\n    async def receive_json(\n        self,\n        *,\n        loads: JSONDecoder = DEFAULT_JSON_DECODER,\n        timeout: Optional[float] = None,\n    ) -> Any:\n        data = await self.receive_str(timeout=timeout)\n        return loads(data)\n\n    def __aiter__(self) -> \"ClientWebSocketResponse\":\n        return self\n\n    async def __anext__(self) -> WSMessage:\n        msg = await self.receive()\n        if msg.type in (WSMsgType.CLOSE, WSMsgType.CLOSING, WSMsgType.CLOSED):\n            raise StopAsyncIteration\n        return msg\n",
            "header": {
                "file": {
                    "path": "aiohttp/client_ws.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "b6dbcca7",
                "new_commit_hash": "d9c74a30",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/aiohttp/client_ws.py"
            },
            "plus_file": {
                "path": "b/aiohttp/client_ws.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 181,
                            "length": 7
                        },
                        "new_range": {
                            "start": 181,
                            "length": 8
                        },
                        "section": "class ClientWebSocketResponse:"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "    async def close(self, *, code: int = WSCloseCode.OK, message: bytes = b\"\") -> bool:",
                                "type": "context"
                            },
                            {
                                "content": "        # we need to break `receive()` cycle first,",
                                "type": "context"
                            },
                            {
                                "content": "        # `close()` may be called from different task",
                                "type": "context"
                            },
                            {
                                "content": "        if self._waiting is not None and not self._closed:",
                                "type": "deleted"
                            },
                            {
                                "content": "        if self._waiting is not None and not self._closing:",
                                "type": "added"
                            },
                            {
                                "content": "            self._closing = True",
                                "type": "added"
                            },
                            {
                                "content": "            self._reader.feed_data(WS_CLOSING_MESSAGE, 0)",
                                "type": "context"
                            },
                            {
                                "content": "            await self._waiting",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "aiohttp/client_ws.py",
                            "type": "class",
                            "name": "ClientWebSocketResponse",
                            "content": "class ClientWebSocketResponse:\n    def __init__(\n        self,\n        reader: \"FlowControlDataQueue[WSMessage]\",\n        writer: WebSocketWriter,\n        protocol: Optional[str],\n        response: ClientResponse,\n        timeout: float,\n        autoclose: bool,\n        autoping: bool,\n        loop: asyncio.AbstractEventLoop,\n        *,\n        receive_timeout: Optional[float] = None,\n        heartbeat: Optional[float] = None,\n        compress: int = 0,\n        client_notakeover: bool = False,\n    ) -> None:\n        self._response = response\n        self._conn = response.connection\n\n        self._writer = writer\n        self._reader = reader\n        self._protocol = protocol\n        self._closed = False\n        self._closing = False\n        self._close_code: Optional[int] = None\n        self._timeout = timeout\n        self._receive_timeout = receive_timeout\n        self._autoclose = autoclose\n        self._autoping = autoping\n        self._heartbeat = heartbeat\n        self._heartbeat_cb: Optional[asyncio.TimerHandle] = None\n        if heartbeat is not None:\n            self._pong_heartbeat = heartbeat / 2.0\n        self._pong_response_cb: Optional[asyncio.TimerHandle] = None\n        self._loop = loop\n        self._waiting: Optional[asyncio.Future[bool]] = None\n        self._exception: Optional[BaseException] = None\n        self._compress = compress\n        self._client_notakeover = client_notakeover\n\n        self._reset_heartbeat()\n\n    def _cancel_heartbeat(self) -> None:\n        if self._pong_response_cb is not None:\n            self._pong_response_cb.cancel()\n            self._pong_response_cb = None\n\n        if self._heartbeat_cb is not None:\n            self._heartbeat_cb.cancel()\n            self._heartbeat_cb = None\n\n    def _reset_heartbeat(self) -> None:\n        self._cancel_heartbeat()\n\n        if self._heartbeat is not None:\n            self._heartbeat_cb = call_later(\n                self._send_heartbeat,\n                self._heartbeat,\n                self._loop,\n                timeout_ceil_threshold=self._conn._connector._timeout_ceil_threshold\n                if self._conn is not None\n                else 5,\n            )\n\n    def _send_heartbeat(self) -> None:\n        if self._heartbeat is not None and not self._closed:\n            # fire-and-forget a task is not perfect but maybe ok for\n            # sending ping. Otherwise we need a long-living heartbeat\n            # task in the class.\n            self._loop.create_task(self._writer.ping())\n\n            if self._pong_response_cb is not None:\n                self._pong_response_cb.cancel()\n            self._pong_response_cb = call_later(\n                self._pong_not_received,\n                self._pong_heartbeat,\n                self._loop,\n                timeout_ceil_threshold=self._conn._connector._timeout_ceil_threshold\n                if self._conn is not None\n                else 5,\n            )\n\n    def _pong_not_received(self) -> None:\n        if not self._closed:\n            self._closed = True\n            self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n            self._exception = asyncio.TimeoutError()\n            self._response.close()\n\n    @property\n    def closed(self) -> bool:\n        return self._closed\n\n    @property\n    def close_code(self) -> Optional[int]:\n        return self._close_code\n\n    @property\n    def protocol(self) -> Optional[str]:\n        return self._protocol\n\n    @property\n    def compress(self) -> int:\n        return self._compress\n\n    @property\n    def client_notakeover(self) -> bool:\n        return self._client_notakeover\n\n    def get_extra_info(self, name: str, default: Any = None) -> Any:\n        \"\"\"extra info from connection transport\"\"\"\n        conn = self._response.connection\n        if conn is None:\n            return default\n        transport = conn.transport\n        if transport is None:\n            return default\n        return transport.get_extra_info(name, default)\n\n    def exception(self) -> Optional[BaseException]:\n        return self._exception\n\n    async def ping(self, message: bytes = b\"\") -> None:\n        await self._writer.ping(message)\n\n    async def pong(self, message: bytes = b\"\") -> None:\n        await self._writer.pong(message)\n\n    async def send_str(self, data: str, compress: Optional[int] = None) -> None:\n        if not isinstance(data, str):\n            raise TypeError(\"data argument must be str (%r)\" % type(data))\n        await self._writer.send(data, binary=False, compress=compress)\n\n    async def send_bytes(self, data: bytes, compress: Optional[int] = None) -> None:\n        if not isinstance(data, (bytes, bytearray, memoryview)):\n            raise TypeError(\"data argument must be byte-ish (%r)\" % type(data))\n        await self._writer.send(data, binary=True, compress=compress)\n\n    async def send_json(\n        self,\n        data: Any,\n        compress: Optional[int] = None,\n        *,\n        dumps: JSONEncoder = DEFAULT_JSON_ENCODER,\n    ) -> None:\n        await self.send_str(dumps(data), compress=compress)\n\n    async def close(self, *, code: int = WSCloseCode.OK, message: bytes = b\"\") -> bool:\n        # we need to break `receive()` cycle first,\n        # `close()` may be called from different task\n        if self._waiting is not None and not self._closed:\n            self._reader.feed_data(WS_CLOSING_MESSAGE, 0)\n            await self._waiting\n\n        if not self._closed:\n            self._cancel_heartbeat()\n            self._closed = True\n            try:\n                await self._writer.close(code, message)\n            except asyncio.CancelledError:\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                self._response.close()\n                raise\n            except Exception as exc:\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                self._exception = exc\n                self._response.close()\n                return True\n\n            if self._closing:\n                self._response.close()\n                return True\n\n            while True:\n                try:\n                    async with async_timeout.timeout(self._timeout):\n                        msg = await self._reader.read()\n                except asyncio.CancelledError:\n                    self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                    self._response.close()\n                    raise\n                except Exception as exc:\n                    self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                    self._exception = exc\n                    self._response.close()\n                    return True\n\n                if msg.type == WSMsgType.CLOSE:\n                    self._close_code = msg.data\n                    self._response.close()\n                    return True\n        else:\n            return False\n\n    async def receive(self, timeout: Optional[float] = None) -> WSMessage:\n        while True:\n            if self._waiting is not None:\n                raise RuntimeError(\"Concurrent call to receive() is not allowed\")\n\n            if self._closed:\n                return WS_CLOSED_MESSAGE\n            elif self._closing:\n                await self.close()\n                return WS_CLOSED_MESSAGE\n\n            try:\n                self._waiting = self._loop.create_future()\n                try:\n                    async with async_timeout.timeout(timeout or self._receive_timeout):\n                        msg = await self._reader.read()\n                    self._reset_heartbeat()\n                finally:\n                    waiter = self._waiting\n                    self._waiting = None\n                    set_result(waiter, True)\n            except (asyncio.CancelledError, asyncio.TimeoutError):\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                raise\n            except EofStream:\n                self._close_code = WSCloseCode.OK\n                await self.close()\n                return WSMessage(WSMsgType.CLOSED, None, None)\n            except ClientError:\n                self._closed = True\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                return WS_CLOSED_MESSAGE\n            except WebSocketError as exc:\n                self._close_code = exc.code\n                await self.close(code=exc.code)\n                return WSMessage(WSMsgType.ERROR, exc, None)\n            except Exception as exc:\n                self._exception = exc\n                self._closing = True\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                await self.close()\n                return WSMessage(WSMsgType.ERROR, exc, None)\n\n            if msg.type == WSMsgType.CLOSE:\n                self._closing = True\n                self._close_code = msg.data\n                if not self._closed and self._autoclose:\n                    await self.close()\n            elif msg.type == WSMsgType.CLOSING:\n                self._closing = True\n            elif msg.type == WSMsgType.PING and self._autoping:\n                await self.pong(msg.data)\n                continue\n            elif msg.type == WSMsgType.PONG and self._autoping:\n                continue\n\n            return msg\n\n    async def receive_str(self, *, timeout: Optional[float] = None) -> str:\n        msg = await self.receive(timeout)\n        if msg.type != WSMsgType.TEXT:\n            raise TypeError(f\"Received message {msg.type}:{msg.data!r} is not str\")\n        return cast(str, msg.data)\n\n    async def receive_bytes(self, *, timeout: Optional[float] = None) -> bytes:\n        msg = await self.receive(timeout)\n        if msg.type != WSMsgType.BINARY:\n            raise TypeError(f\"Received message {msg.type}:{msg.data!r} is not bytes\")\n        return cast(bytes, msg.data)\n\n    async def receive_json(\n        self,\n        *,\n        loads: JSONDecoder = DEFAULT_JSON_DECODER,\n        timeout: Optional[float] = None,\n    ) -> Any:\n        data = await self.receive_str(timeout=timeout)\n        return loads(data)\n\n    def __aiter__(self) -> \"ClientWebSocketResponse\":\n        return self\n\n    async def __anext__(self) -> WSMessage:\n        msg = await self.receive()\n        if msg.type in (WSMsgType.CLOSE, WSMsgType.CLOSING, WSMsgType.CLOSED):\n            raise StopAsyncIteration\n        return msg",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 33,
                            "end_lineno": 314,
                            "parent": null
                        },
                        {
                            "file_name": "aiohttp/client_ws.py",
                            "type": "method",
                            "name": "ClientWebSocketResponse.close",
                            "content": "class ClientWebSocketResponse:\n    def __init__(\n        self,\n        reader: \"FlowControlDataQueue[WSMessage]\",\n        writer: WebSocketWriter,\n        protocol: Optional[str],\n        response: ClientResponse,\n        timeout: float,\n        autoclose: bool,\n        autoping: bool,\n        loop: asyncio.AbstractEventLoop,\n        *,\n        receive_timeout: Optional[float] = None,\n        heartbeat: Optional[float] = None,\n        compress: int = 0,\n        client_notakeover: bool = False,\n    ) -> None:\n        self._response = response\n        self._conn = response.connection\n\n        self._writer = writer\n        self._reader = reader\n        self._protocol = protocol\n        self._closed = False\n        self._closing = False\n        self._close_code: Optional[int] = None\n        self._timeout = timeout\n        self._receive_timeout = receive_timeout\n        self._autoclose = autoclose\n        self._autoping = autoping\n        self._heartbeat = heartbeat\n        self._heartbeat_cb: Optional[asyncio.TimerHandle] = None\n        if heartbeat is not None:\n            self._pong_heartbeat = heartbeat / 2.0\n        self._pong_response_cb: Optional[asyncio.TimerHandle] = None\n        self._loop = loop\n        self._waiting: Optional[asyncio.Future[bool]] = None\n        self._exception: Optional[BaseException] = None\n        self._compress = compress\n        self._client_notakeover = client_notakeover\n\n        self._reset_heartbeat()\n\n    def _cancel_heartbeat(self) -> None:\n        if self._pong_response_cb is not None:\n            self._pong_response_cb.cancel()\n            self._pong_response_cb = None\n\n        if self._heartbeat_cb is not None:\n            self._heartbeat_cb.cancel()\n            self._heartbeat_cb = None\n\n    def _reset_heartbeat(self) -> None:\n        self._cancel_heartbeat()\n\n        if self._heartbeat is not None:\n            self._heartbeat_cb = call_later(\n                self._send_heartbeat,\n                self._heartbeat,\n                self._loop,\n                timeout_ceil_threshold=self._conn._connector._timeout_ceil_threshold\n                if self._conn is not None\n                else 5,\n            )\n\n    def _send_heartbeat(self) -> None:\n        if self._heartbeat is not None and not self._closed:\n            # fire-and-forget a task is not perfect but maybe ok for\n            # sending ping. Otherwise we need a long-living heartbeat\n            # task in the class.\n            self._loop.create_task(self._writer.ping())\n\n            if self._pong_response_cb is not None:\n                self._pong_response_cb.cancel()\n            self._pong_response_cb = call_later(\n                self._pong_not_received,\n                self._pong_heartbeat,\n                self._loop,\n                timeout_ceil_threshold=self._conn._connector._timeout_ceil_threshold\n                if self._conn is not None\n                else 5,\n            )\n\n    def _pong_not_received(self) -> None:\n        if not self._closed:\n            self._closed = True\n            self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n            self._exception = asyncio.TimeoutError()\n            self._response.close()\n\n    @property\n    def closed(self) -> bool:\n        return self._closed\n\n    @property\n    def close_code(self) -> Optional[int]:\n        return self._close_code\n\n    @property\n    def protocol(self) -> Optional[str]:\n        return self._protocol\n\n    @property\n    def compress(self) -> int:\n        return self._compress\n\n    @property\n    def client_notakeover(self) -> bool:\n        return self._client_notakeover\n\n    def get_extra_info(self, name: str, default: Any = None) -> Any:\n        \"\"\"extra info from connection transport\"\"\"\n        conn = self._response.connection\n        if conn is None:\n            return default\n        transport = conn.transport\n        if transport is None:\n            return default\n        return transport.get_extra_info(name, default)\n\n    def exception(self) -> Optional[BaseException]:\n        return self._exception\n\n    async def ping(self, message: bytes = b\"\") -> None:\n        await self._writer.ping(message)\n\n    async def pong(self, message: bytes = b\"\") -> None:\n        await self._writer.pong(message)\n\n    async def send_str(self, data: str, compress: Optional[int] = None) -> None:\n        if not isinstance(data, str):\n            raise TypeError(\"data argument must be str (%r)\" % type(data))\n        await self._writer.send(data, binary=False, compress=compress)\n\n    async def send_bytes(self, data: bytes, compress: Optional[int] = None) -> None:\n        if not isinstance(data, (bytes, bytearray, memoryview)):\n            raise TypeError(\"data argument must be byte-ish (%r)\" % type(data))\n        await self._writer.send(data, binary=True, compress=compress)\n\n    async def send_json(\n        self,\n        data: Any,\n        compress: Optional[int] = None,\n        *,\n        dumps: JSONEncoder = DEFAULT_JSON_ENCODER,\n    ) -> None:\n        await self.send_str(dumps(data), compress=compress)\n\n    async def close(self, *, code: int = WSCloseCode.OK, message: bytes = b\"\") -> bool:\n        # we need to break `receive()` cycle first,\n        # `close()` may be called from different task\n        if self._waiting is not None and not self._closed:\n            self._reader.feed_data(WS_CLOSING_MESSAGE, 0)\n            await self._waiting\n\n        if not self._closed:\n            self._cancel_heartbeat()\n            self._closed = True\n            try:\n                await self._writer.close(code, message)\n            except asyncio.CancelledError:\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                self._response.close()\n                raise\n            except Exception as exc:\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                self._exception = exc\n                self._response.close()\n                return True\n\n            if self._closing:\n                self._response.close()\n                return True\n\n            while True:\n                try:\n                    async with async_timeout.timeout(self._timeout):\n                        msg = await self._reader.read()\n                except asyncio.CancelledError:\n                    self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                    self._response.close()\n                    raise\n                except Exception as exc:\n                    self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                    self._exception = exc\n                    self._response.close()\n                    return True\n\n                if msg.type == WSMsgType.CLOSE:\n                    self._close_code = msg.data\n                    self._response.close()\n                    return True\n        else:\n            return False\n\n    async def receive(self, timeout: Optional[float] = None) -> WSMessage:\n        while True:\n            if self._waiting is not None:\n                raise RuntimeError(\"Concurrent call to receive() is not allowed\")\n\n            if self._closed:\n                return WS_CLOSED_MESSAGE\n            elif self._closing:\n                await self.close()\n                return WS_CLOSED_MESSAGE\n\n            try:\n                self._waiting = self._loop.create_future()\n                try:\n                    async with async_timeout.timeout(timeout or self._receive_timeout):\n                        msg = await self._reader.read()\n                    self._reset_heartbeat()\n                finally:\n                    waiter = self._waiting\n                    self._waiting = None\n                    set_result(waiter, True)\n            except (asyncio.CancelledError, asyncio.TimeoutError):\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                raise\n            except EofStream:\n                self._close_code = WSCloseCode.OK\n                await self.close()\n                return WSMessage(WSMsgType.CLOSED, None, None)\n            except ClientError:\n                self._closed = True\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                return WS_CLOSED_MESSAGE\n            except WebSocketError as exc:\n                self._close_code = exc.code\n                await self.close(code=exc.code)\n                return WSMessage(WSMsgType.ERROR, exc, None)\n            except Exception as exc:\n                self._exception = exc\n                self._closing = True\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                await self.close()\n                return WSMessage(WSMsgType.ERROR, exc, None)\n\n            if msg.type == WSMsgType.CLOSE:\n                self._closing = True\n                self._close_code = msg.data\n                if not self._closed and self._autoclose:\n                    await self.close()\n            elif msg.type == WSMsgType.CLOSING:\n                self._closing = True\n            elif msg.type == WSMsgType.PING and self._autoping:\n                await self.pong(msg.data)\n                continue\n            elif msg.type == WSMsgType.PONG and self._autoping:\n                continue\n\n            return msg\n\n    async def receive_str(self, *, timeout: Optional[float] = None) -> str:\n        msg = await self.receive(timeout)\n        if msg.type != WSMsgType.TEXT:\n            raise TypeError(f\"Received message {msg.type}:{msg.data!r} is not str\")\n        return cast(str, msg.data)\n\n    async def receive_bytes(self, *, timeout: Optional[float] = None) -> bytes:\n        msg = await self.receive(timeout)\n        if msg.type != WSMsgType.BINARY:\n            raise TypeError(f\"Received message {msg.type}:{msg.data!r} is not bytes\")\n        return cast(bytes, msg.data)\n\n    async def receive_json(\n        self,\n        *,\n        loads: JSONDecoder = DEFAULT_JSON_DECODER,\n        timeout: Optional[float] = None,\n    ) -> Any:\n        data = await self.receive_str(timeout=timeout)\n        return loads(data)\n\n    def __aiter__(self) -> \"ClientWebSocketResponse\":\n        return self\n\n    async def __anext__(self) -> WSMessage:\n        msg = await self.receive()\n        if msg.type in (WSMsgType.CLOSE, WSMsgType.CLOSING, WSMsgType.CLOSED):\n            raise StopAsyncIteration\n        return msg",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 181,
                            "end_lineno": 226,
                            "parent": {
                                "file_name": "aiohttp/client_ws.py",
                                "type": "class",
                                "name": "ClientWebSocketResponse",
                                "content": "class ClientWebSocketResponse:\n    def __init__(\n        self,\n        reader: \"FlowControlDataQueue[WSMessage]\",\n        writer: WebSocketWriter,\n        protocol: Optional[str],\n        response: ClientResponse,\n        timeout: float,\n        autoclose: bool,\n        autoping: bool,\n        loop: asyncio.AbstractEventLoop,\n        *,\n        receive_timeout: Optional[float] = None,\n        heartbeat: Optional[float] = None,\n        compress: int = 0,\n        client_notakeover: bool = False,\n    ) -> None:\n        self._response = response\n        self._conn = response.connection\n\n        self._writer = writer\n        self._reader = reader\n        self._protocol = protocol\n        self._closed = False\n        self._closing = False\n        self._close_code: Optional[int] = None\n        self._timeout = timeout\n        self._receive_timeout = receive_timeout\n        self._autoclose = autoclose\n        self._autoping = autoping\n        self._heartbeat = heartbeat\n        self._heartbeat_cb: Optional[asyncio.TimerHandle] = None\n        if heartbeat is not None:\n            self._pong_heartbeat = heartbeat / 2.0\n        self._pong_response_cb: Optional[asyncio.TimerHandle] = None\n        self._loop = loop\n        self._waiting: Optional[asyncio.Future[bool]] = None\n        self._exception: Optional[BaseException] = None\n        self._compress = compress\n        self._client_notakeover = client_notakeover\n\n        self._reset_heartbeat()\n\n    def _cancel_heartbeat(self) -> None:\n        if self._pong_response_cb is not None:\n            self._pong_response_cb.cancel()\n            self._pong_response_cb = None\n\n        if self._heartbeat_cb is not None:\n            self._heartbeat_cb.cancel()\n            self._heartbeat_cb = None\n\n    def _reset_heartbeat(self) -> None:\n        self._cancel_heartbeat()\n\n        if self._heartbeat is not None:\n            self._heartbeat_cb = call_later(\n                self._send_heartbeat,\n                self._heartbeat,\n                self._loop,\n                timeout_ceil_threshold=self._conn._connector._timeout_ceil_threshold\n                if self._conn is not None\n                else 5,\n            )\n\n    def _send_heartbeat(self) -> None:\n        if self._heartbeat is not None and not self._closed:\n            # fire-and-forget a task is not perfect but maybe ok for\n            # sending ping. Otherwise we need a long-living heartbeat\n            # task in the class.\n            self._loop.create_task(self._writer.ping())\n\n            if self._pong_response_cb is not None:\n                self._pong_response_cb.cancel()\n            self._pong_response_cb = call_later(\n                self._pong_not_received,\n                self._pong_heartbeat,\n                self._loop,\n                timeout_ceil_threshold=self._conn._connector._timeout_ceil_threshold\n                if self._conn is not None\n                else 5,\n            )\n\n    def _pong_not_received(self) -> None:\n        if not self._closed:\n            self._closed = True\n            self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n            self._exception = asyncio.TimeoutError()\n            self._response.close()\n\n    @property\n    def closed(self) -> bool:\n        return self._closed\n\n    @property\n    def close_code(self) -> Optional[int]:\n        return self._close_code\n\n    @property\n    def protocol(self) -> Optional[str]:\n        return self._protocol\n\n    @property\n    def compress(self) -> int:\n        return self._compress\n\n    @property\n    def client_notakeover(self) -> bool:\n        return self._client_notakeover\n\n    def get_extra_info(self, name: str, default: Any = None) -> Any:\n        \"\"\"extra info from connection transport\"\"\"\n        conn = self._response.connection\n        if conn is None:\n            return default\n        transport = conn.transport\n        if transport is None:\n            return default\n        return transport.get_extra_info(name, default)\n\n    def exception(self) -> Optional[BaseException]:\n        return self._exception\n\n    async def ping(self, message: bytes = b\"\") -> None:\n        await self._writer.ping(message)\n\n    async def pong(self, message: bytes = b\"\") -> None:\n        await self._writer.pong(message)\n\n    async def send_str(self, data: str, compress: Optional[int] = None) -> None:\n        if not isinstance(data, str):\n            raise TypeError(\"data argument must be str (%r)\" % type(data))\n        await self._writer.send(data, binary=False, compress=compress)\n\n    async def send_bytes(self, data: bytes, compress: Optional[int] = None) -> None:\n        if not isinstance(data, (bytes, bytearray, memoryview)):\n            raise TypeError(\"data argument must be byte-ish (%r)\" % type(data))\n        await self._writer.send(data, binary=True, compress=compress)\n\n    async def send_json(\n        self,\n        data: Any,\n        compress: Optional[int] = None,\n        *,\n        dumps: JSONEncoder = DEFAULT_JSON_ENCODER,\n    ) -> None:\n        await self.send_str(dumps(data), compress=compress)\n\n    async def close(self, *, code: int = WSCloseCode.OK, message: bytes = b\"\") -> bool:\n        # we need to break `receive()` cycle first,\n        # `close()` may be called from different task\n        if self._waiting is not None and not self._closed:\n            self._reader.feed_data(WS_CLOSING_MESSAGE, 0)\n            await self._waiting\n\n        if not self._closed:\n            self._cancel_heartbeat()\n            self._closed = True\n            try:\n                await self._writer.close(code, message)\n            except asyncio.CancelledError:\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                self._response.close()\n                raise\n            except Exception as exc:\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                self._exception = exc\n                self._response.close()\n                return True\n\n            if self._closing:\n                self._response.close()\n                return True\n\n            while True:\n                try:\n                    async with async_timeout.timeout(self._timeout):\n                        msg = await self._reader.read()\n                except asyncio.CancelledError:\n                    self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                    self._response.close()\n                    raise\n                except Exception as exc:\n                    self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                    self._exception = exc\n                    self._response.close()\n                    return True\n\n                if msg.type == WSMsgType.CLOSE:\n                    self._close_code = msg.data\n                    self._response.close()\n                    return True\n        else:\n            return False\n\n    async def receive(self, timeout: Optional[float] = None) -> WSMessage:\n        while True:\n            if self._waiting is not None:\n                raise RuntimeError(\"Concurrent call to receive() is not allowed\")\n\n            if self._closed:\n                return WS_CLOSED_MESSAGE\n            elif self._closing:\n                await self.close()\n                return WS_CLOSED_MESSAGE\n\n            try:\n                self._waiting = self._loop.create_future()\n                try:\n                    async with async_timeout.timeout(timeout or self._receive_timeout):\n                        msg = await self._reader.read()\n                    self._reset_heartbeat()\n                finally:\n                    waiter = self._waiting\n                    self._waiting = None\n                    set_result(waiter, True)\n            except (asyncio.CancelledError, asyncio.TimeoutError):\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                raise\n            except EofStream:\n                self._close_code = WSCloseCode.OK\n                await self.close()\n                return WSMessage(WSMsgType.CLOSED, None, None)\n            except ClientError:\n                self._closed = True\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                return WS_CLOSED_MESSAGE\n            except WebSocketError as exc:\n                self._close_code = exc.code\n                await self.close(code=exc.code)\n                return WSMessage(WSMsgType.ERROR, exc, None)\n            except Exception as exc:\n                self._exception = exc\n                self._closing = True\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                await self.close()\n                return WSMessage(WSMsgType.ERROR, exc, None)\n\n            if msg.type == WSMsgType.CLOSE:\n                self._closing = True\n                self._close_code = msg.data\n                if not self._closed and self._autoclose:\n                    await self.close()\n            elif msg.type == WSMsgType.CLOSING:\n                self._closing = True\n            elif msg.type == WSMsgType.PING and self._autoping:\n                await self.pong(msg.data)\n                continue\n            elif msg.type == WSMsgType.PONG and self._autoping:\n                continue\n\n            return msg\n\n    async def receive_str(self, *, timeout: Optional[float] = None) -> str:\n        msg = await self.receive(timeout)\n        if msg.type != WSMsgType.TEXT:\n            raise TypeError(f\"Received message {msg.type}:{msg.data!r} is not str\")\n        return cast(str, msg.data)\n\n    async def receive_bytes(self, *, timeout: Optional[float] = None) -> bytes:\n        msg = await self.receive(timeout)\n        if msg.type != WSMsgType.BINARY:\n            raise TypeError(f\"Received message {msg.type}:{msg.data!r} is not bytes\")\n        return cast(bytes, msg.data)\n\n    async def receive_json(\n        self,\n        *,\n        loads: JSONDecoder = DEFAULT_JSON_DECODER,\n        timeout: Optional[float] = None,\n    ) -> Any:\n        data = await self.receive_str(timeout=timeout)\n        return loads(data)\n\n    def __aiter__(self) -> \"ClientWebSocketResponse\":\n        return self\n\n    async def __anext__(self) -> WSMessage:\n        msg = await self.receive()\n        if msg.type in (WSMsgType.CLOSE, WSMsgType.CLOSING, WSMsgType.CLOSED):\n            raise StopAsyncIteration\n        return msg",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 33,
                                "end_lineno": 314,
                                "parent": null
                            }
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 200,
                            "length": 7
                        },
                        "new_range": {
                            "start": 201,
                            "length": 7
                        },
                        "section": "class ClientWebSocketResponse:"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "                self._response.close()",
                                "type": "context"
                            },
                            {
                                "content": "                return True",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "            if self._closing:",
                                "type": "deleted"
                            },
                            {
                                "content": "            if self._close_code:",
                                "type": "added"
                            },
                            {
                                "content": "                self._response.close()",
                                "type": "context"
                            },
                            {
                                "content": "                return True",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "aiohttp/client_ws.py",
                            "type": "class",
                            "name": "ClientWebSocketResponse",
                            "content": "class ClientWebSocketResponse:\n    def __init__(\n        self,\n        reader: \"FlowControlDataQueue[WSMessage]\",\n        writer: WebSocketWriter,\n        protocol: Optional[str],\n        response: ClientResponse,\n        timeout: float,\n        autoclose: bool,\n        autoping: bool,\n        loop: asyncio.AbstractEventLoop,\n        *,\n        receive_timeout: Optional[float] = None,\n        heartbeat: Optional[float] = None,\n        compress: int = 0,\n        client_notakeover: bool = False,\n    ) -> None:\n        self._response = response\n        self._conn = response.connection\n\n        self._writer = writer\n        self._reader = reader\n        self._protocol = protocol\n        self._closed = False\n        self._closing = False\n        self._close_code: Optional[int] = None\n        self._timeout = timeout\n        self._receive_timeout = receive_timeout\n        self._autoclose = autoclose\n        self._autoping = autoping\n        self._heartbeat = heartbeat\n        self._heartbeat_cb: Optional[asyncio.TimerHandle] = None\n        if heartbeat is not None:\n            self._pong_heartbeat = heartbeat / 2.0\n        self._pong_response_cb: Optional[asyncio.TimerHandle] = None\n        self._loop = loop\n        self._waiting: Optional[asyncio.Future[bool]] = None\n        self._exception: Optional[BaseException] = None\n        self._compress = compress\n        self._client_notakeover = client_notakeover\n\n        self._reset_heartbeat()\n\n    def _cancel_heartbeat(self) -> None:\n        if self._pong_response_cb is not None:\n            self._pong_response_cb.cancel()\n            self._pong_response_cb = None\n\n        if self._heartbeat_cb is not None:\n            self._heartbeat_cb.cancel()\n            self._heartbeat_cb = None\n\n    def _reset_heartbeat(self) -> None:\n        self._cancel_heartbeat()\n\n        if self._heartbeat is not None:\n            self._heartbeat_cb = call_later(\n                self._send_heartbeat,\n                self._heartbeat,\n                self._loop,\n                timeout_ceil_threshold=self._conn._connector._timeout_ceil_threshold\n                if self._conn is not None\n                else 5,\n            )\n\n    def _send_heartbeat(self) -> None:\n        if self._heartbeat is not None and not self._closed:\n            # fire-and-forget a task is not perfect but maybe ok for\n            # sending ping. Otherwise we need a long-living heartbeat\n            # task in the class.\n            self._loop.create_task(self._writer.ping())\n\n            if self._pong_response_cb is not None:\n                self._pong_response_cb.cancel()\n            self._pong_response_cb = call_later(\n                self._pong_not_received,\n                self._pong_heartbeat,\n                self._loop,\n                timeout_ceil_threshold=self._conn._connector._timeout_ceil_threshold\n                if self._conn is not None\n                else 5,\n            )\n\n    def _pong_not_received(self) -> None:\n        if not self._closed:\n            self._closed = True\n            self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n            self._exception = asyncio.TimeoutError()\n            self._response.close()\n\n    @property\n    def closed(self) -> bool:\n        return self._closed\n\n    @property\n    def close_code(self) -> Optional[int]:\n        return self._close_code\n\n    @property\n    def protocol(self) -> Optional[str]:\n        return self._protocol\n\n    @property\n    def compress(self) -> int:\n        return self._compress\n\n    @property\n    def client_notakeover(self) -> bool:\n        return self._client_notakeover\n\n    def get_extra_info(self, name: str, default: Any = None) -> Any:\n        \"\"\"extra info from connection transport\"\"\"\n        conn = self._response.connection\n        if conn is None:\n            return default\n        transport = conn.transport\n        if transport is None:\n            return default\n        return transport.get_extra_info(name, default)\n\n    def exception(self) -> Optional[BaseException]:\n        return self._exception\n\n    async def ping(self, message: bytes = b\"\") -> None:\n        await self._writer.ping(message)\n\n    async def pong(self, message: bytes = b\"\") -> None:\n        await self._writer.pong(message)\n\n    async def send_str(self, data: str, compress: Optional[int] = None) -> None:\n        if not isinstance(data, str):\n            raise TypeError(\"data argument must be str (%r)\" % type(data))\n        await self._writer.send(data, binary=False, compress=compress)\n\n    async def send_bytes(self, data: bytes, compress: Optional[int] = None) -> None:\n        if not isinstance(data, (bytes, bytearray, memoryview)):\n            raise TypeError(\"data argument must be byte-ish (%r)\" % type(data))\n        await self._writer.send(data, binary=True, compress=compress)\n\n    async def send_json(\n        self,\n        data: Any,\n        compress: Optional[int] = None,\n        *,\n        dumps: JSONEncoder = DEFAULT_JSON_ENCODER,\n    ) -> None:\n        await self.send_str(dumps(data), compress=compress)\n\n    async def close(self, *, code: int = WSCloseCode.OK, message: bytes = b\"\") -> bool:\n        # we need to break `receive()` cycle first,\n        # `close()` may be called from different task\n        if self._waiting is not None and not self._closed:\n            self._reader.feed_data(WS_CLOSING_MESSAGE, 0)\n            await self._waiting\n\n        if not self._closed:\n            self._cancel_heartbeat()\n            self._closed = True\n            try:\n                await self._writer.close(code, message)\n            except asyncio.CancelledError:\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                self._response.close()\n                raise\n            except Exception as exc:\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                self._exception = exc\n                self._response.close()\n                return True\n\n            if self._closing:\n                self._response.close()\n                return True\n\n            while True:\n                try:\n                    async with async_timeout.timeout(self._timeout):\n                        msg = await self._reader.read()\n                except asyncio.CancelledError:\n                    self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                    self._response.close()\n                    raise\n                except Exception as exc:\n                    self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                    self._exception = exc\n                    self._response.close()\n                    return True\n\n                if msg.type == WSMsgType.CLOSE:\n                    self._close_code = msg.data\n                    self._response.close()\n                    return True\n        else:\n            return False\n\n    async def receive(self, timeout: Optional[float] = None) -> WSMessage:\n        while True:\n            if self._waiting is not None:\n                raise RuntimeError(\"Concurrent call to receive() is not allowed\")\n\n            if self._closed:\n                return WS_CLOSED_MESSAGE\n            elif self._closing:\n                await self.close()\n                return WS_CLOSED_MESSAGE\n\n            try:\n                self._waiting = self._loop.create_future()\n                try:\n                    async with async_timeout.timeout(timeout or self._receive_timeout):\n                        msg = await self._reader.read()\n                    self._reset_heartbeat()\n                finally:\n                    waiter = self._waiting\n                    self._waiting = None\n                    set_result(waiter, True)\n            except (asyncio.CancelledError, asyncio.TimeoutError):\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                raise\n            except EofStream:\n                self._close_code = WSCloseCode.OK\n                await self.close()\n                return WSMessage(WSMsgType.CLOSED, None, None)\n            except ClientError:\n                self._closed = True\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                return WS_CLOSED_MESSAGE\n            except WebSocketError as exc:\n                self._close_code = exc.code\n                await self.close(code=exc.code)\n                return WSMessage(WSMsgType.ERROR, exc, None)\n            except Exception as exc:\n                self._exception = exc\n                self._closing = True\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                await self.close()\n                return WSMessage(WSMsgType.ERROR, exc, None)\n\n            if msg.type == WSMsgType.CLOSE:\n                self._closing = True\n                self._close_code = msg.data\n                if not self._closed and self._autoclose:\n                    await self.close()\n            elif msg.type == WSMsgType.CLOSING:\n                self._closing = True\n            elif msg.type == WSMsgType.PING and self._autoping:\n                await self.pong(msg.data)\n                continue\n            elif msg.type == WSMsgType.PONG and self._autoping:\n                continue\n\n            return msg\n\n    async def receive_str(self, *, timeout: Optional[float] = None) -> str:\n        msg = await self.receive(timeout)\n        if msg.type != WSMsgType.TEXT:\n            raise TypeError(f\"Received message {msg.type}:{msg.data!r} is not str\")\n        return cast(str, msg.data)\n\n    async def receive_bytes(self, *, timeout: Optional[float] = None) -> bytes:\n        msg = await self.receive(timeout)\n        if msg.type != WSMsgType.BINARY:\n            raise TypeError(f\"Received message {msg.type}:{msg.data!r} is not bytes\")\n        return cast(bytes, msg.data)\n\n    async def receive_json(\n        self,\n        *,\n        loads: JSONDecoder = DEFAULT_JSON_DECODER,\n        timeout: Optional[float] = None,\n    ) -> Any:\n        data = await self.receive_str(timeout=timeout)\n        return loads(data)\n\n    def __aiter__(self) -> \"ClientWebSocketResponse\":\n        return self\n\n    async def __anext__(self) -> WSMessage:\n        msg = await self.receive()\n        if msg.type in (WSMsgType.CLOSE, WSMsgType.CLOSING, WSMsgType.CLOSED):\n            raise StopAsyncIteration\n        return msg",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 33,
                            "end_lineno": 314,
                            "parent": null
                        },
                        {
                            "file_name": "aiohttp/client_ws.py",
                            "type": "method",
                            "name": "ClientWebSocketResponse.close",
                            "content": "class ClientWebSocketResponse:\n    def __init__(\n        self,\n        reader: \"FlowControlDataQueue[WSMessage]\",\n        writer: WebSocketWriter,\n        protocol: Optional[str],\n        response: ClientResponse,\n        timeout: float,\n        autoclose: bool,\n        autoping: bool,\n        loop: asyncio.AbstractEventLoop,\n        *,\n        receive_timeout: Optional[float] = None,\n        heartbeat: Optional[float] = None,\n        compress: int = 0,\n        client_notakeover: bool = False,\n    ) -> None:\n        self._response = response\n        self._conn = response.connection\n\n        self._writer = writer\n        self._reader = reader\n        self._protocol = protocol\n        self._closed = False\n        self._closing = False\n        self._close_code: Optional[int] = None\n        self._timeout = timeout\n        self._receive_timeout = receive_timeout\n        self._autoclose = autoclose\n        self._autoping = autoping\n        self._heartbeat = heartbeat\n        self._heartbeat_cb: Optional[asyncio.TimerHandle] = None\n        if heartbeat is not None:\n            self._pong_heartbeat = heartbeat / 2.0\n        self._pong_response_cb: Optional[asyncio.TimerHandle] = None\n        self._loop = loop\n        self._waiting: Optional[asyncio.Future[bool]] = None\n        self._exception: Optional[BaseException] = None\n        self._compress = compress\n        self._client_notakeover = client_notakeover\n\n        self._reset_heartbeat()\n\n    def _cancel_heartbeat(self) -> None:\n        if self._pong_response_cb is not None:\n            self._pong_response_cb.cancel()\n            self._pong_response_cb = None\n\n        if self._heartbeat_cb is not None:\n            self._heartbeat_cb.cancel()\n            self._heartbeat_cb = None\n\n    def _reset_heartbeat(self) -> None:\n        self._cancel_heartbeat()\n\n        if self._heartbeat is not None:\n            self._heartbeat_cb = call_later(\n                self._send_heartbeat,\n                self._heartbeat,\n                self._loop,\n                timeout_ceil_threshold=self._conn._connector._timeout_ceil_threshold\n                if self._conn is not None\n                else 5,\n            )\n\n    def _send_heartbeat(self) -> None:\n        if self._heartbeat is not None and not self._closed:\n            # fire-and-forget a task is not perfect but maybe ok for\n            # sending ping. Otherwise we need a long-living heartbeat\n            # task in the class.\n            self._loop.create_task(self._writer.ping())\n\n            if self._pong_response_cb is not None:\n                self._pong_response_cb.cancel()\n            self._pong_response_cb = call_later(\n                self._pong_not_received,\n                self._pong_heartbeat,\n                self._loop,\n                timeout_ceil_threshold=self._conn._connector._timeout_ceil_threshold\n                if self._conn is not None\n                else 5,\n            )\n\n    def _pong_not_received(self) -> None:\n        if not self._closed:\n            self._closed = True\n            self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n            self._exception = asyncio.TimeoutError()\n            self._response.close()\n\n    @property\n    def closed(self) -> bool:\n        return self._closed\n\n    @property\n    def close_code(self) -> Optional[int]:\n        return self._close_code\n\n    @property\n    def protocol(self) -> Optional[str]:\n        return self._protocol\n\n    @property\n    def compress(self) -> int:\n        return self._compress\n\n    @property\n    def client_notakeover(self) -> bool:\n        return self._client_notakeover\n\n    def get_extra_info(self, name: str, default: Any = None) -> Any:\n        \"\"\"extra info from connection transport\"\"\"\n        conn = self._response.connection\n        if conn is None:\n            return default\n        transport = conn.transport\n        if transport is None:\n            return default\n        return transport.get_extra_info(name, default)\n\n    def exception(self) -> Optional[BaseException]:\n        return self._exception\n\n    async def ping(self, message: bytes = b\"\") -> None:\n        await self._writer.ping(message)\n\n    async def pong(self, message: bytes = b\"\") -> None:\n        await self._writer.pong(message)\n\n    async def send_str(self, data: str, compress: Optional[int] = None) -> None:\n        if not isinstance(data, str):\n            raise TypeError(\"data argument must be str (%r)\" % type(data))\n        await self._writer.send(data, binary=False, compress=compress)\n\n    async def send_bytes(self, data: bytes, compress: Optional[int] = None) -> None:\n        if not isinstance(data, (bytes, bytearray, memoryview)):\n            raise TypeError(\"data argument must be byte-ish (%r)\" % type(data))\n        await self._writer.send(data, binary=True, compress=compress)\n\n    async def send_json(\n        self,\n        data: Any,\n        compress: Optional[int] = None,\n        *,\n        dumps: JSONEncoder = DEFAULT_JSON_ENCODER,\n    ) -> None:\n        await self.send_str(dumps(data), compress=compress)\n\n    async def close(self, *, code: int = WSCloseCode.OK, message: bytes = b\"\") -> bool:\n        # we need to break `receive()` cycle first,\n        # `close()` may be called from different task\n        if self._waiting is not None and not self._closed:\n            self._reader.feed_data(WS_CLOSING_MESSAGE, 0)\n            await self._waiting\n\n        if not self._closed:\n            self._cancel_heartbeat()\n            self._closed = True\n            try:\n                await self._writer.close(code, message)\n            except asyncio.CancelledError:\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                self._response.close()\n                raise\n            except Exception as exc:\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                self._exception = exc\n                self._response.close()\n                return True\n\n            if self._closing:\n                self._response.close()\n                return True\n\n            while True:\n                try:\n                    async with async_timeout.timeout(self._timeout):\n                        msg = await self._reader.read()\n                except asyncio.CancelledError:\n                    self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                    self._response.close()\n                    raise\n                except Exception as exc:\n                    self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                    self._exception = exc\n                    self._response.close()\n                    return True\n\n                if msg.type == WSMsgType.CLOSE:\n                    self._close_code = msg.data\n                    self._response.close()\n                    return True\n        else:\n            return False\n\n    async def receive(self, timeout: Optional[float] = None) -> WSMessage:\n        while True:\n            if self._waiting is not None:\n                raise RuntimeError(\"Concurrent call to receive() is not allowed\")\n\n            if self._closed:\n                return WS_CLOSED_MESSAGE\n            elif self._closing:\n                await self.close()\n                return WS_CLOSED_MESSAGE\n\n            try:\n                self._waiting = self._loop.create_future()\n                try:\n                    async with async_timeout.timeout(timeout or self._receive_timeout):\n                        msg = await self._reader.read()\n                    self._reset_heartbeat()\n                finally:\n                    waiter = self._waiting\n                    self._waiting = None\n                    set_result(waiter, True)\n            except (asyncio.CancelledError, asyncio.TimeoutError):\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                raise\n            except EofStream:\n                self._close_code = WSCloseCode.OK\n                await self.close()\n                return WSMessage(WSMsgType.CLOSED, None, None)\n            except ClientError:\n                self._closed = True\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                return WS_CLOSED_MESSAGE\n            except WebSocketError as exc:\n                self._close_code = exc.code\n                await self.close(code=exc.code)\n                return WSMessage(WSMsgType.ERROR, exc, None)\n            except Exception as exc:\n                self._exception = exc\n                self._closing = True\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                await self.close()\n                return WSMessage(WSMsgType.ERROR, exc, None)\n\n            if msg.type == WSMsgType.CLOSE:\n                self._closing = True\n                self._close_code = msg.data\n                if not self._closed and self._autoclose:\n                    await self.close()\n            elif msg.type == WSMsgType.CLOSING:\n                self._closing = True\n            elif msg.type == WSMsgType.PING and self._autoping:\n                await self.pong(msg.data)\n                continue\n            elif msg.type == WSMsgType.PONG and self._autoping:\n                continue\n\n            return msg\n\n    async def receive_str(self, *, timeout: Optional[float] = None) -> str:\n        msg = await self.receive(timeout)\n        if msg.type != WSMsgType.TEXT:\n            raise TypeError(f\"Received message {msg.type}:{msg.data!r} is not str\")\n        return cast(str, msg.data)\n\n    async def receive_bytes(self, *, timeout: Optional[float] = None) -> bytes:\n        msg = await self.receive(timeout)\n        if msg.type != WSMsgType.BINARY:\n            raise TypeError(f\"Received message {msg.type}:{msg.data!r} is not bytes\")\n        return cast(bytes, msg.data)\n\n    async def receive_json(\n        self,\n        *,\n        loads: JSONDecoder = DEFAULT_JSON_DECODER,\n        timeout: Optional[float] = None,\n    ) -> Any:\n        data = await self.receive_str(timeout=timeout)\n        return loads(data)\n\n    def __aiter__(self) -> \"ClientWebSocketResponse\":\n        return self\n\n    async def __anext__(self) -> WSMessage:\n        msg = await self.receive()\n        if msg.type in (WSMsgType.CLOSE, WSMsgType.CLOSING, WSMsgType.CLOSED):\n            raise StopAsyncIteration\n        return msg",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 181,
                            "end_lineno": 226,
                            "parent": {
                                "file_name": "aiohttp/client_ws.py",
                                "type": "class",
                                "name": "ClientWebSocketResponse",
                                "content": "class ClientWebSocketResponse:\n    def __init__(\n        self,\n        reader: \"FlowControlDataQueue[WSMessage]\",\n        writer: WebSocketWriter,\n        protocol: Optional[str],\n        response: ClientResponse,\n        timeout: float,\n        autoclose: bool,\n        autoping: bool,\n        loop: asyncio.AbstractEventLoop,\n        *,\n        receive_timeout: Optional[float] = None,\n        heartbeat: Optional[float] = None,\n        compress: int = 0,\n        client_notakeover: bool = False,\n    ) -> None:\n        self._response = response\n        self._conn = response.connection\n\n        self._writer = writer\n        self._reader = reader\n        self._protocol = protocol\n        self._closed = False\n        self._closing = False\n        self._close_code: Optional[int] = None\n        self._timeout = timeout\n        self._receive_timeout = receive_timeout\n        self._autoclose = autoclose\n        self._autoping = autoping\n        self._heartbeat = heartbeat\n        self._heartbeat_cb: Optional[asyncio.TimerHandle] = None\n        if heartbeat is not None:\n            self._pong_heartbeat = heartbeat / 2.0\n        self._pong_response_cb: Optional[asyncio.TimerHandle] = None\n        self._loop = loop\n        self._waiting: Optional[asyncio.Future[bool]] = None\n        self._exception: Optional[BaseException] = None\n        self._compress = compress\n        self._client_notakeover = client_notakeover\n\n        self._reset_heartbeat()\n\n    def _cancel_heartbeat(self) -> None:\n        if self._pong_response_cb is not None:\n            self._pong_response_cb.cancel()\n            self._pong_response_cb = None\n\n        if self._heartbeat_cb is not None:\n            self._heartbeat_cb.cancel()\n            self._heartbeat_cb = None\n\n    def _reset_heartbeat(self) -> None:\n        self._cancel_heartbeat()\n\n        if self._heartbeat is not None:\n            self._heartbeat_cb = call_later(\n                self._send_heartbeat,\n                self._heartbeat,\n                self._loop,\n                timeout_ceil_threshold=self._conn._connector._timeout_ceil_threshold\n                if self._conn is not None\n                else 5,\n            )\n\n    def _send_heartbeat(self) -> None:\n        if self._heartbeat is not None and not self._closed:\n            # fire-and-forget a task is not perfect but maybe ok for\n            # sending ping. Otherwise we need a long-living heartbeat\n            # task in the class.\n            self._loop.create_task(self._writer.ping())\n\n            if self._pong_response_cb is not None:\n                self._pong_response_cb.cancel()\n            self._pong_response_cb = call_later(\n                self._pong_not_received,\n                self._pong_heartbeat,\n                self._loop,\n                timeout_ceil_threshold=self._conn._connector._timeout_ceil_threshold\n                if self._conn is not None\n                else 5,\n            )\n\n    def _pong_not_received(self) -> None:\n        if not self._closed:\n            self._closed = True\n            self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n            self._exception = asyncio.TimeoutError()\n            self._response.close()\n\n    @property\n    def closed(self) -> bool:\n        return self._closed\n\n    @property\n    def close_code(self) -> Optional[int]:\n        return self._close_code\n\n    @property\n    def protocol(self) -> Optional[str]:\n        return self._protocol\n\n    @property\n    def compress(self) -> int:\n        return self._compress\n\n    @property\n    def client_notakeover(self) -> bool:\n        return self._client_notakeover\n\n    def get_extra_info(self, name: str, default: Any = None) -> Any:\n        \"\"\"extra info from connection transport\"\"\"\n        conn = self._response.connection\n        if conn is None:\n            return default\n        transport = conn.transport\n        if transport is None:\n            return default\n        return transport.get_extra_info(name, default)\n\n    def exception(self) -> Optional[BaseException]:\n        return self._exception\n\n    async def ping(self, message: bytes = b\"\") -> None:\n        await self._writer.ping(message)\n\n    async def pong(self, message: bytes = b\"\") -> None:\n        await self._writer.pong(message)\n\n    async def send_str(self, data: str, compress: Optional[int] = None) -> None:\n        if not isinstance(data, str):\n            raise TypeError(\"data argument must be str (%r)\" % type(data))\n        await self._writer.send(data, binary=False, compress=compress)\n\n    async def send_bytes(self, data: bytes, compress: Optional[int] = None) -> None:\n        if not isinstance(data, (bytes, bytearray, memoryview)):\n            raise TypeError(\"data argument must be byte-ish (%r)\" % type(data))\n        await self._writer.send(data, binary=True, compress=compress)\n\n    async def send_json(\n        self,\n        data: Any,\n        compress: Optional[int] = None,\n        *,\n        dumps: JSONEncoder = DEFAULT_JSON_ENCODER,\n    ) -> None:\n        await self.send_str(dumps(data), compress=compress)\n\n    async def close(self, *, code: int = WSCloseCode.OK, message: bytes = b\"\") -> bool:\n        # we need to break `receive()` cycle first,\n        # `close()` may be called from different task\n        if self._waiting is not None and not self._closed:\n            self._reader.feed_data(WS_CLOSING_MESSAGE, 0)\n            await self._waiting\n\n        if not self._closed:\n            self._cancel_heartbeat()\n            self._closed = True\n            try:\n                await self._writer.close(code, message)\n            except asyncio.CancelledError:\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                self._response.close()\n                raise\n            except Exception as exc:\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                self._exception = exc\n                self._response.close()\n                return True\n\n            if self._closing:\n                self._response.close()\n                return True\n\n            while True:\n                try:\n                    async with async_timeout.timeout(self._timeout):\n                        msg = await self._reader.read()\n                except asyncio.CancelledError:\n                    self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                    self._response.close()\n                    raise\n                except Exception as exc:\n                    self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                    self._exception = exc\n                    self._response.close()\n                    return True\n\n                if msg.type == WSMsgType.CLOSE:\n                    self._close_code = msg.data\n                    self._response.close()\n                    return True\n        else:\n            return False\n\n    async def receive(self, timeout: Optional[float] = None) -> WSMessage:\n        while True:\n            if self._waiting is not None:\n                raise RuntimeError(\"Concurrent call to receive() is not allowed\")\n\n            if self._closed:\n                return WS_CLOSED_MESSAGE\n            elif self._closing:\n                await self.close()\n                return WS_CLOSED_MESSAGE\n\n            try:\n                self._waiting = self._loop.create_future()\n                try:\n                    async with async_timeout.timeout(timeout or self._receive_timeout):\n                        msg = await self._reader.read()\n                    self._reset_heartbeat()\n                finally:\n                    waiter = self._waiting\n                    self._waiting = None\n                    set_result(waiter, True)\n            except (asyncio.CancelledError, asyncio.TimeoutError):\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                raise\n            except EofStream:\n                self._close_code = WSCloseCode.OK\n                await self.close()\n                return WSMessage(WSMsgType.CLOSED, None, None)\n            except ClientError:\n                self._closed = True\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                return WS_CLOSED_MESSAGE\n            except WebSocketError as exc:\n                self._close_code = exc.code\n                await self.close(code=exc.code)\n                return WSMessage(WSMsgType.ERROR, exc, None)\n            except Exception as exc:\n                self._exception = exc\n                self._closing = True\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                await self.close()\n                return WSMessage(WSMsgType.ERROR, exc, None)\n\n            if msg.type == WSMsgType.CLOSE:\n                self._closing = True\n                self._close_code = msg.data\n                if not self._closed and self._autoclose:\n                    await self.close()\n            elif msg.type == WSMsgType.CLOSING:\n                self._closing = True\n            elif msg.type == WSMsgType.PING and self._autoping:\n                await self.pong(msg.data)\n                continue\n            elif msg.type == WSMsgType.PONG and self._autoping:\n                continue\n\n            return msg\n\n    async def receive_str(self, *, timeout: Optional[float] = None) -> str:\n        msg = await self.receive(timeout)\n        if msg.type != WSMsgType.TEXT:\n            raise TypeError(f\"Received message {msg.type}:{msg.data!r} is not str\")\n        return cast(str, msg.data)\n\n    async def receive_bytes(self, *, timeout: Optional[float] = None) -> bytes:\n        msg = await self.receive(timeout)\n        if msg.type != WSMsgType.BINARY:\n            raise TypeError(f\"Received message {msg.type}:{msg.data!r} is not bytes\")\n        return cast(bytes, msg.data)\n\n    async def receive_json(\n        self,\n        *,\n        loads: JSONDecoder = DEFAULT_JSON_DECODER,\n        timeout: Optional[float] = None,\n    ) -> Any:\n        data = await self.receive_str(timeout=timeout)\n        return loads(data)\n\n    def __aiter__(self) -> \"ClientWebSocketResponse\":\n        return self\n\n    async def __anext__(self) -> WSMessage:\n        msg = await self.receive()\n        if msg.type in (WSMsgType.CLOSE, WSMsgType.CLOSING, WSMsgType.CLOSED):\n            raise StopAsyncIteration\n        return msg",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 33,
                                "end_lineno": 314,
                                "parent": null
                            }
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "import asyncio\nimport sys\n\nimport pytest\n\nimport aiohttp\nfrom aiohttp import hdrs, web\n\nif sys.version_info >= (3, 11):\n    import asyncio as async_timeout\nelse:\n    import async_timeout\n\n\nasync def test_send_recv_text(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        msg = await ws.receive_str()\n        await ws.send_str(msg + \"/answer\")\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n    await resp.send_str(\"ask\")\n\n    assert resp.get_extra_info(\"socket\") is not None\n\n    data = await resp.receive_str()\n    assert data == \"ask/answer\"\n    await resp.close()\n\n    assert resp.get_extra_info(\"socket\") is None\n\n\nasync def test_send_recv_bytes_bad_type(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        msg = await ws.receive_str()\n        await ws.send_str(msg + \"/answer\")\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n    await resp.send_str(\"ask\")\n\n    with pytest.raises(TypeError):\n        await resp.receive_bytes()\n        await resp.close()\n\n\nasync def test_send_recv_bytes(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        msg = await ws.receive_bytes()\n        await ws.send_bytes(msg + b\"/answer\")\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n\n    await resp.send_bytes(b\"ask\")\n\n    data = await resp.receive_bytes()\n    assert data == b\"ask/answer\"\n\n    await resp.close()\n\n\nasync def test_send_recv_text_bad_type(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        msg = await ws.receive_bytes()\n        await ws.send_bytes(msg + b\"/answer\")\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n\n    await resp.send_bytes(b\"ask\")\n\n    with pytest.raises(TypeError):\n        await resp.receive_str()\n\n        await resp.close()\n\n\nasync def test_send_recv_json(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        data = await ws.receive_json()\n        await ws.send_json({\"response\": data[\"request\"]})\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n    payload = {\"request\": \"test\"}\n    await resp.send_json(payload)\n\n    data = await resp.receive_json()\n    assert data[\"response\"] == payload[\"request\"]\n    await resp.close()\n\n\nasync def test_ping_pong(aiohttp_client) -> None:\n    loop = asyncio.get_event_loop()\n    closed = loop.create_future()\n\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        msg = await ws.receive_bytes()\n        await ws.ping()\n        await ws.send_bytes(msg + b\"/answer\")\n        try:\n            await ws.close()\n        finally:\n            closed.set_result(1)\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n\n    await resp.ping()\n    await resp.send_bytes(b\"ask\")\n\n    msg = await resp.receive()\n    assert msg.type == aiohttp.WSMsgType.BINARY\n    assert msg.data == b\"ask/answer\"\n\n    msg = await resp.receive()\n    assert msg.type == aiohttp.WSMsgType.CLOSE\n\n    await resp.close()\n    await closed\n\n\nasync def test_ping_pong_manual(aiohttp_client) -> None:\n    loop = asyncio.get_event_loop()\n    closed = loop.create_future()\n\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        msg = await ws.receive_bytes()\n        await ws.ping()\n        await ws.send_bytes(msg + b\"/answer\")\n        try:\n            await ws.close()\n        finally:\n            closed.set_result(1)\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\", autoping=False)\n\n    await resp.ping()\n    await resp.send_bytes(b\"ask\")\n\n    msg = await resp.receive()\n    assert msg.type == aiohttp.WSMsgType.PONG\n\n    msg = await resp.receive()\n    assert msg.type == aiohttp.WSMsgType.PING\n    await resp.pong()\n\n    msg = await resp.receive()\n    assert msg.data == b\"ask/answer\"\n\n    msg = await resp.receive()\n    assert msg.type == aiohttp.WSMsgType.CLOSE\n\n    await closed\n\n\nasync def test_close(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        await ws.receive_bytes()\n        await ws.send_str(\"test\")\n\n        await ws.receive()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n\n    await resp.send_bytes(b\"ask\")\n\n    closed = await resp.close()\n    assert closed\n    assert resp.closed\n    assert resp.close_code == 1000\n\n    msg = await resp.receive()\n    assert msg.type == aiohttp.WSMsgType.CLOSED\n\n\nasync def test_concurrent_close(aiohttp_client) -> None:\n    client_ws = None\n\n    async def handler(request):\n        nonlocal client_ws\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        await ws.receive_bytes()\n        await ws.send_str(\"test\")\n\n        await client_ws.close()\n\n        msg = await ws.receive()\n        assert msg.type == aiohttp.WSMsgType.CLOSE\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    ws = client_ws = await client.ws_connect(\"/\")\n\n    await ws.send_bytes(b\"ask\")\n\n    msg = await ws.receive()\n    assert msg.type == aiohttp.WSMsgType.CLOSING\n\n    await asyncio.sleep(0.01)\n    msg = await ws.receive()\n    assert msg.type == aiohttp.WSMsgType.CLOSED\n\n\nasync def test_close_from_server(aiohttp_client) -> None:\n    loop = asyncio.get_event_loop()\n    closed = loop.create_future()\n\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        try:\n            await ws.receive_bytes()\n            await ws.close()\n        finally:\n            closed.set_result(1)\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n\n    await resp.send_bytes(b\"ask\")\n\n    msg = await resp.receive()\n    assert msg.type == aiohttp.WSMsgType.CLOSE\n    assert resp.closed\n\n    msg = await resp.receive()\n    assert msg.type == aiohttp.WSMsgType.CLOSED\n\n    await closed\n\n\nasync def test_close_manual(aiohttp_client) -> None:\n    loop = asyncio.get_event_loop()\n    closed = loop.create_future()\n\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        await ws.receive_bytes()\n        await ws.send_str(\"test\")\n\n        try:\n            await ws.close()\n        finally:\n            closed.set_result(1)\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\", autoclose=False)\n    await resp.send_bytes(b\"ask\")\n\n    msg = await resp.receive()\n    assert msg.data == \"test\"\n\n    msg = await resp.receive()\n    assert msg.type == aiohttp.WSMsgType.CLOSE\n    assert msg.data == 1000\n    assert msg.extra == \"\"\n    assert not resp.closed\n\n    await resp.close()\n    await closed\n    assert resp.closed\n\n\nasync def test_close_timeout(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n        await ws.receive_bytes()\n        await ws.send_str(\"test\")\n        await asyncio.sleep(1)\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\", timeout=0.2, autoclose=False)\n\n    await resp.send_bytes(b\"ask\")\n\n    msg = await resp.receive()\n    assert msg.data == \"test\"\n    assert msg.type == aiohttp.WSMsgType.TEXT\n\n    msg = await resp.close()\n    assert resp.closed\n    assert isinstance(resp.exception(), asyncio.TimeoutError)\n\n\nasync def test_close_cancel(aiohttp_client) -> None:\n    loop = asyncio.get_event_loop()\n\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n        await ws.receive_bytes()\n        await ws.send_str(\"test\")\n        await asyncio.sleep(10)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\", autoclose=False)\n\n    await resp.send_bytes(b\"ask\")\n\n    text = await resp.receive()\n    assert text.data == \"test\"\n\n    t = loop.create_task(resp.close())\n    await asyncio.sleep(0.1)\n    t.cancel()\n    await asyncio.sleep(0.1)\n    assert resp.closed\n    assert resp.exception() is None\n\n\nasync def test_override_default_headers(aiohttp_client) -> None:\n    async def handler(request):\n        assert request.headers[hdrs.SEC_WEBSOCKET_VERSION] == \"8\"\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n        await ws.send_str(\"answer\")\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    headers = {hdrs.SEC_WEBSOCKET_VERSION: \"8\"}\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\", headers=headers)\n    msg = await resp.receive()\n    assert msg.data == \"answer\"\n    await resp.close()\n\n\nasync def test_additional_headers(aiohttp_client) -> None:\n    async def handler(request):\n        assert request.headers[\"x-hdr\"] == \"xtra\"\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        await ws.send_str(\"answer\")\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\", headers={\"x-hdr\": \"xtra\"})\n    msg = await resp.receive()\n    assert msg.data == \"answer\"\n    await resp.close()\n\n\nasync def test_recv_protocol_error(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        await ws.receive_str()\n        ws._writer.transport.write(b\"01234\" * 100)\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n    await resp.send_str(\"ask\")\n\n    msg = await resp.receive()\n    assert msg.type == aiohttp.WSMsgType.ERROR\n    assert type(msg.data) is aiohttp.WebSocketError\n    assert msg.data.code == aiohttp.WSCloseCode.PROTOCOL_ERROR\n    assert str(msg.data) == \"Received frame with non-zero reserved bits\"\n    assert msg.extra is None\n    await resp.close()\n\n\nasync def test_recv_timeout(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        await ws.receive_str()\n\n        await asyncio.sleep(0.1)\n\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n    await resp.send_str(\"ask\")\n\n    with pytest.raises(asyncio.TimeoutError):\n        async with async_timeout.timeout(0.01):\n            await resp.receive()\n\n    await resp.close()\n\n\nasync def test_receive_timeout(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n        await ws.receive()\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\", receive_timeout=0.1)\n\n    with pytest.raises(asyncio.TimeoutError):\n        await resp.receive(0.05)\n\n    await resp.close()\n\n\nasync def test_custom_receive_timeout(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n        await ws.receive()\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n\n    with pytest.raises(asyncio.TimeoutError):\n        await resp.receive(0.05)\n\n    await resp.close()\n\n\nasync def test_heartbeat(aiohttp_client) -> None:\n    ping_received = False\n\n    async def handler(request):\n        nonlocal ping_received\n        ws = web.WebSocketResponse(autoping=False)\n        await ws.prepare(request)\n        msg = await ws.receive()\n        if msg.type == aiohttp.WSMsgType.ping:\n            ping_received = True\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\", heartbeat=0.01)\n    await asyncio.sleep(0.1)\n    await resp.receive()\n    await resp.close()\n\n    assert ping_received\n\n\nasync def test_heartbeat_no_pong(aiohttp_client) -> None:\n    ping_received = False\n\n    async def handler(request):\n        nonlocal ping_received\n        ws = web.WebSocketResponse(autoping=False)\n        await ws.prepare(request)\n        msg = await ws.receive()\n        if msg.type == aiohttp.WSMsgType.ping:\n            ping_received = True\n        await ws.receive()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\", heartbeat=0.05)\n\n    await resp.receive()\n    await resp.receive()\n\n    assert ping_received\n\n\nasync def test_send_recv_compress(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        msg = await ws.receive_str()\n        await ws.send_str(msg + \"/answer\")\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\", compress=15)\n    await resp.send_str(\"ask\")\n\n    assert resp.compress == 15\n\n    data = await resp.receive_str()\n    assert data == \"ask/answer\"\n\n    await resp.close()\n    assert resp.get_extra_info(\"socket\") is None\n\n\nasync def test_send_recv_compress_wbits(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        msg = await ws.receive_str()\n        await ws.send_str(msg + \"/answer\")\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\", compress=9)\n    await resp.send_str(\"ask\")\n\n    # Client indicates supports wbits 15\n    # Server supports wbit 15 for decode\n    assert resp.compress == 15\n\n    data = await resp.receive_str()\n    assert data == \"ask/answer\"\n\n    await resp.close()\n    assert resp.get_extra_info(\"socket\") is None\n\n\nasync def test_send_recv_compress_wbit_error(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        msg = await ws.receive_bytes()\n        await ws.send_bytes(msg + b\"/answer\")\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    with pytest.raises(ValueError):\n        await client.ws_connect(\"/\", compress=1)\n\n\nasync def test_ws_client_async_for(aiohttp_client) -> None:\n    items = [\"q1\", \"q2\", \"q3\"]\n\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n        for i in items:\n            await ws.send_str(i)\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n    it = iter(items)\n    async for msg in resp:\n        assert msg.data == next(it)\n\n    with pytest.raises(StopIteration):\n        next(it)\n\n    assert resp.closed\n\n\nasync def test_ws_async_with(aiohttp_server) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n        msg = await ws.receive()\n        await ws.send_str(msg.data + \"/answer\")\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    server = await aiohttp_server(app)\n\n    async with aiohttp.ClientSession() as client:\n        async with client.ws_connect(server.make_url(\"/\")) as ws:\n            await ws.send_str(\"request\")\n            msg = await ws.receive()\n            assert msg.data == \"request/answer\"\n\n        assert ws.closed\n\n\nasync def test_ws_async_with_send(aiohttp_server) -> None:\n    # send_xxx methods have to return awaitable objects\n\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n        msg = await ws.receive()\n        await ws.send_str(msg.data + \"/answer\")\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    server = await aiohttp_server(app)\n\n    async with aiohttp.ClientSession() as client:\n        async with client.ws_connect(server.make_url(\"/\")) as ws:\n            await ws.send_str(\"request\")\n            msg = await ws.receive()\n            assert msg.data == \"request/answer\"\n\n        assert ws.closed\n\n\nasync def test_ws_async_with_shortcut(aiohttp_server) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n        msg = await ws.receive()\n        await ws.send_str(msg.data + \"/answer\")\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    server = await aiohttp_server(app)\n\n    async with aiohttp.ClientSession() as client:\n        async with client.ws_connect(server.make_url(\"/\")) as ws:\n            await ws.send_str(\"request\")\n            msg = await ws.receive()\n            assert msg.data == \"request/answer\"\n\n        assert ws.closed\n\n\nasync def test_closed_async_for(aiohttp_client) -> None:\n    loop = asyncio.get_event_loop()\n    closed = loop.create_future()\n\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        try:\n            await ws.send_bytes(b\"started\")\n            await ws.receive_bytes()\n        finally:\n            closed.set_result(1)\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n\n    messages = []\n    async for msg in resp:\n        messages.append(msg)\n        if b\"started\" == msg.data:\n            await resp.send_bytes(b\"ask\")\n            await resp.close()\n\n    assert 1 == len(messages)\n    assert messages[0].type == aiohttp.WSMsgType.BINARY\n    assert messages[0].data == b\"started\"\n    assert resp.closed\n\n    await closed\n\n\nasync def test_peer_connection_lost(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        msg = await ws.receive_str()\n        assert msg == \"ask\"\n        await ws.send_str(\"answer\")\n        request.transport.close()\n        await asyncio.sleep(10)\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n    await resp.send_str(\"ask\")\n    assert \"answer\" == await resp.receive_str()\n\n    msg = await resp.receive()\n    assert msg.type == aiohttp.WSMsgType.CLOSED\n    await resp.close()\n\n\nasync def test_peer_connection_lost_iter(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        msg = await ws.receive_str()\n        assert msg == \"ask\"\n        await ws.send_str(\"answer\")\n        request.transport.close()\n        await asyncio.sleep(100)\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n    await resp.send_str(\"ask\")\n    async for msg in resp:\n        assert \"answer\" == msg.data\n\n    await resp.close()\n",
            "new_file_content": "import asyncio\nimport sys\n\nimport pytest\n\nimport aiohttp\nfrom aiohttp import hdrs, web\n\nif sys.version_info >= (3, 11):\n    import asyncio as async_timeout\nelse:\n    import async_timeout\n\n\nasync def test_send_recv_text(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        msg = await ws.receive_str()\n        await ws.send_str(msg + \"/answer\")\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n    await resp.send_str(\"ask\")\n\n    assert resp.get_extra_info(\"socket\") is not None\n\n    data = await resp.receive_str()\n    assert data == \"ask/answer\"\n    await resp.close()\n\n    assert resp.get_extra_info(\"socket\") is None\n\n\nasync def test_send_recv_bytes_bad_type(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        msg = await ws.receive_str()\n        await ws.send_str(msg + \"/answer\")\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n    await resp.send_str(\"ask\")\n\n    with pytest.raises(TypeError):\n        await resp.receive_bytes()\n        await resp.close()\n\n\nasync def test_send_recv_bytes(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        msg = await ws.receive_bytes()\n        await ws.send_bytes(msg + b\"/answer\")\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n\n    await resp.send_bytes(b\"ask\")\n\n    data = await resp.receive_bytes()\n    assert data == b\"ask/answer\"\n\n    await resp.close()\n\n\nasync def test_send_recv_text_bad_type(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        msg = await ws.receive_bytes()\n        await ws.send_bytes(msg + b\"/answer\")\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n\n    await resp.send_bytes(b\"ask\")\n\n    with pytest.raises(TypeError):\n        await resp.receive_str()\n\n        await resp.close()\n\n\nasync def test_send_recv_json(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        data = await ws.receive_json()\n        await ws.send_json({\"response\": data[\"request\"]})\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n    payload = {\"request\": \"test\"}\n    await resp.send_json(payload)\n\n    data = await resp.receive_json()\n    assert data[\"response\"] == payload[\"request\"]\n    await resp.close()\n\n\nasync def test_ping_pong(aiohttp_client) -> None:\n    loop = asyncio.get_event_loop()\n    closed = loop.create_future()\n\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        msg = await ws.receive_bytes()\n        await ws.ping()\n        await ws.send_bytes(msg + b\"/answer\")\n        try:\n            await ws.close()\n        finally:\n            closed.set_result(1)\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n\n    await resp.ping()\n    await resp.send_bytes(b\"ask\")\n\n    msg = await resp.receive()\n    assert msg.type == aiohttp.WSMsgType.BINARY\n    assert msg.data == b\"ask/answer\"\n\n    msg = await resp.receive()\n    assert msg.type == aiohttp.WSMsgType.CLOSE\n\n    await resp.close()\n    await closed\n\n\nasync def test_ping_pong_manual(aiohttp_client) -> None:\n    loop = asyncio.get_event_loop()\n    closed = loop.create_future()\n\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        msg = await ws.receive_bytes()\n        await ws.ping()\n        await ws.send_bytes(msg + b\"/answer\")\n        try:\n            await ws.close()\n        finally:\n            closed.set_result(1)\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\", autoping=False)\n\n    await resp.ping()\n    await resp.send_bytes(b\"ask\")\n\n    msg = await resp.receive()\n    assert msg.type == aiohttp.WSMsgType.PONG\n\n    msg = await resp.receive()\n    assert msg.type == aiohttp.WSMsgType.PING\n    await resp.pong()\n\n    msg = await resp.receive()\n    assert msg.data == b\"ask/answer\"\n\n    msg = await resp.receive()\n    assert msg.type == aiohttp.WSMsgType.CLOSE\n\n    await closed\n\n\nasync def test_close(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        await ws.receive_bytes()\n        await ws.send_str(\"test\")\n\n        await ws.receive()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n\n    await resp.send_bytes(b\"ask\")\n\n    closed = await resp.close()\n    assert closed\n    assert resp.closed\n    assert resp.close_code == 1000\n\n    msg = await resp.receive()\n    assert msg.type == aiohttp.WSMsgType.CLOSED\n\n\nasync def test_concurrent_close(aiohttp_client) -> None:\n    client_ws = None\n\n    async def handler(request):\n        nonlocal client_ws\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        await ws.receive_bytes()\n        await ws.send_str(\"test\")\n\n        await client_ws.close()\n\n        msg = await ws.receive()\n        assert msg.type == aiohttp.WSMsgType.CLOSE\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    ws = client_ws = await client.ws_connect(\"/\")\n\n    await ws.send_bytes(b\"ask\")\n\n    msg = await ws.receive()\n    assert msg.type == aiohttp.WSMsgType.CLOSING\n\n    await asyncio.sleep(0.01)\n    msg = await ws.receive()\n    assert msg.type == aiohttp.WSMsgType.CLOSED\n\n\nasync def test_concurrent_task_close(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n        await ws.receive()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    client = await aiohttp_client(app)\n    async with client.ws_connect(\"/\") as resp:\n        # wait for the message in a separate task\n        task = asyncio.create_task(resp.receive())\n\n        # Make sure we start to wait on receiving message before closing the connection\n        await asyncio.sleep(0.1)\n\n        closed = await resp.close()\n\n        await task\n\n        assert closed\n        assert resp.closed\n        assert resp.close_code == 1000\n\n\nasync def test_close_from_server(aiohttp_client) -> None:\n    loop = asyncio.get_event_loop()\n    closed = loop.create_future()\n\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        try:\n            await ws.receive_bytes()\n            await ws.close()\n        finally:\n            closed.set_result(1)\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n\n    await resp.send_bytes(b\"ask\")\n\n    msg = await resp.receive()\n    assert msg.type == aiohttp.WSMsgType.CLOSE\n    assert resp.closed\n\n    msg = await resp.receive()\n    assert msg.type == aiohttp.WSMsgType.CLOSED\n\n    await closed\n\n\nasync def test_close_manual(aiohttp_client) -> None:\n    loop = asyncio.get_event_loop()\n    closed = loop.create_future()\n\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        await ws.receive_bytes()\n        await ws.send_str(\"test\")\n\n        try:\n            await ws.close()\n        finally:\n            closed.set_result(1)\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\", autoclose=False)\n    await resp.send_bytes(b\"ask\")\n\n    msg = await resp.receive()\n    assert msg.data == \"test\"\n\n    msg = await resp.receive()\n    assert msg.type == aiohttp.WSMsgType.CLOSE\n    assert msg.data == 1000\n    assert msg.extra == \"\"\n    assert not resp.closed\n\n    await resp.close()\n    await closed\n    assert resp.closed\n\n\nasync def test_close_timeout(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n        await ws.receive_bytes()\n        await ws.send_str(\"test\")\n        await asyncio.sleep(1)\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\", timeout=0.2, autoclose=False)\n\n    await resp.send_bytes(b\"ask\")\n\n    msg = await resp.receive()\n    assert msg.data == \"test\"\n    assert msg.type == aiohttp.WSMsgType.TEXT\n\n    msg = await resp.close()\n    assert resp.closed\n    assert isinstance(resp.exception(), asyncio.TimeoutError)\n\n\nasync def test_close_cancel(aiohttp_client) -> None:\n    loop = asyncio.get_event_loop()\n\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n        await ws.receive_bytes()\n        await ws.send_str(\"test\")\n        await asyncio.sleep(10)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\", autoclose=False)\n\n    await resp.send_bytes(b\"ask\")\n\n    text = await resp.receive()\n    assert text.data == \"test\"\n\n    t = loop.create_task(resp.close())\n    await asyncio.sleep(0.1)\n    t.cancel()\n    await asyncio.sleep(0.1)\n    assert resp.closed\n    assert resp.exception() is None\n\n\nasync def test_override_default_headers(aiohttp_client) -> None:\n    async def handler(request):\n        assert request.headers[hdrs.SEC_WEBSOCKET_VERSION] == \"8\"\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n        await ws.send_str(\"answer\")\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    headers = {hdrs.SEC_WEBSOCKET_VERSION: \"8\"}\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\", headers=headers)\n    msg = await resp.receive()\n    assert msg.data == \"answer\"\n    await resp.close()\n\n\nasync def test_additional_headers(aiohttp_client) -> None:\n    async def handler(request):\n        assert request.headers[\"x-hdr\"] == \"xtra\"\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        await ws.send_str(\"answer\")\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\", headers={\"x-hdr\": \"xtra\"})\n    msg = await resp.receive()\n    assert msg.data == \"answer\"\n    await resp.close()\n\n\nasync def test_recv_protocol_error(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        await ws.receive_str()\n        ws._writer.transport.write(b\"01234\" * 100)\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n    await resp.send_str(\"ask\")\n\n    msg = await resp.receive()\n    assert msg.type == aiohttp.WSMsgType.ERROR\n    assert type(msg.data) is aiohttp.WebSocketError\n    assert msg.data.code == aiohttp.WSCloseCode.PROTOCOL_ERROR\n    assert str(msg.data) == \"Received frame with non-zero reserved bits\"\n    assert msg.extra is None\n    await resp.close()\n\n\nasync def test_recv_timeout(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        await ws.receive_str()\n\n        await asyncio.sleep(0.1)\n\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n    await resp.send_str(\"ask\")\n\n    with pytest.raises(asyncio.TimeoutError):\n        async with async_timeout.timeout(0.01):\n            await resp.receive()\n\n    await resp.close()\n\n\nasync def test_receive_timeout(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n        await ws.receive()\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\", receive_timeout=0.1)\n\n    with pytest.raises(asyncio.TimeoutError):\n        await resp.receive(0.05)\n\n    await resp.close()\n\n\nasync def test_custom_receive_timeout(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n        await ws.receive()\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n\n    with pytest.raises(asyncio.TimeoutError):\n        await resp.receive(0.05)\n\n    await resp.close()\n\n\nasync def test_heartbeat(aiohttp_client) -> None:\n    ping_received = False\n\n    async def handler(request):\n        nonlocal ping_received\n        ws = web.WebSocketResponse(autoping=False)\n        await ws.prepare(request)\n        msg = await ws.receive()\n        if msg.type == aiohttp.WSMsgType.ping:\n            ping_received = True\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\", heartbeat=0.01)\n    await asyncio.sleep(0.1)\n    await resp.receive()\n    await resp.close()\n\n    assert ping_received\n\n\nasync def test_heartbeat_no_pong(aiohttp_client) -> None:\n    ping_received = False\n\n    async def handler(request):\n        nonlocal ping_received\n        ws = web.WebSocketResponse(autoping=False)\n        await ws.prepare(request)\n        msg = await ws.receive()\n        if msg.type == aiohttp.WSMsgType.ping:\n            ping_received = True\n        await ws.receive()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\", heartbeat=0.05)\n\n    await resp.receive()\n    await resp.receive()\n\n    assert ping_received\n\n\nasync def test_send_recv_compress(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        msg = await ws.receive_str()\n        await ws.send_str(msg + \"/answer\")\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\", compress=15)\n    await resp.send_str(\"ask\")\n\n    assert resp.compress == 15\n\n    data = await resp.receive_str()\n    assert data == \"ask/answer\"\n\n    await resp.close()\n    assert resp.get_extra_info(\"socket\") is None\n\n\nasync def test_send_recv_compress_wbits(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        msg = await ws.receive_str()\n        await ws.send_str(msg + \"/answer\")\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\", compress=9)\n    await resp.send_str(\"ask\")\n\n    # Client indicates supports wbits 15\n    # Server supports wbit 15 for decode\n    assert resp.compress == 15\n\n    data = await resp.receive_str()\n    assert data == \"ask/answer\"\n\n    await resp.close()\n    assert resp.get_extra_info(\"socket\") is None\n\n\nasync def test_send_recv_compress_wbit_error(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        msg = await ws.receive_bytes()\n        await ws.send_bytes(msg + b\"/answer\")\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    with pytest.raises(ValueError):\n        await client.ws_connect(\"/\", compress=1)\n\n\nasync def test_ws_client_async_for(aiohttp_client) -> None:\n    items = [\"q1\", \"q2\", \"q3\"]\n\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n        for i in items:\n            await ws.send_str(i)\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n    it = iter(items)\n    async for msg in resp:\n        assert msg.data == next(it)\n\n    with pytest.raises(StopIteration):\n        next(it)\n\n    assert resp.closed\n\n\nasync def test_ws_async_with(aiohttp_server) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n        msg = await ws.receive()\n        await ws.send_str(msg.data + \"/answer\")\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    server = await aiohttp_server(app)\n\n    async with aiohttp.ClientSession() as client:\n        async with client.ws_connect(server.make_url(\"/\")) as ws:\n            await ws.send_str(\"request\")\n            msg = await ws.receive()\n            assert msg.data == \"request/answer\"\n\n        assert ws.closed\n\n\nasync def test_ws_async_with_send(aiohttp_server) -> None:\n    # send_xxx methods have to return awaitable objects\n\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n        msg = await ws.receive()\n        await ws.send_str(msg.data + \"/answer\")\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    server = await aiohttp_server(app)\n\n    async with aiohttp.ClientSession() as client:\n        async with client.ws_connect(server.make_url(\"/\")) as ws:\n            await ws.send_str(\"request\")\n            msg = await ws.receive()\n            assert msg.data == \"request/answer\"\n\n        assert ws.closed\n\n\nasync def test_ws_async_with_shortcut(aiohttp_server) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n        msg = await ws.receive()\n        await ws.send_str(msg.data + \"/answer\")\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    server = await aiohttp_server(app)\n\n    async with aiohttp.ClientSession() as client:\n        async with client.ws_connect(server.make_url(\"/\")) as ws:\n            await ws.send_str(\"request\")\n            msg = await ws.receive()\n            assert msg.data == \"request/answer\"\n\n        assert ws.closed\n\n\nasync def test_closed_async_for(aiohttp_client) -> None:\n    loop = asyncio.get_event_loop()\n    closed = loop.create_future()\n\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        try:\n            await ws.send_bytes(b\"started\")\n            await ws.receive_bytes()\n        finally:\n            closed.set_result(1)\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n\n    messages = []\n    async for msg in resp:\n        messages.append(msg)\n        if b\"started\" == msg.data:\n            await resp.send_bytes(b\"ask\")\n            await resp.close()\n\n    assert 1 == len(messages)\n    assert messages[0].type == aiohttp.WSMsgType.BINARY\n    assert messages[0].data == b\"started\"\n    assert resp.closed\n\n    await closed\n\n\nasync def test_peer_connection_lost(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        msg = await ws.receive_str()\n        assert msg == \"ask\"\n        await ws.send_str(\"answer\")\n        request.transport.close()\n        await asyncio.sleep(10)\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n    await resp.send_str(\"ask\")\n    assert \"answer\" == await resp.receive_str()\n\n    msg = await resp.receive()\n    assert msg.type == aiohttp.WSMsgType.CLOSED\n    await resp.close()\n\n\nasync def test_peer_connection_lost_iter(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        msg = await ws.receive_str()\n        assert msg == \"ask\"\n        await ws.send_str(\"answer\")\n        request.transport.close()\n        await asyncio.sleep(100)\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n    await resp.send_str(\"ask\")\n    async for msg in resp:\n        assert \"answer\" == msg.data\n\n    await resp.close()\n",
            "header": {
                "file": {
                    "path": "tests/test_client_ws_functional.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "62b59db0",
                "new_commit_hash": "87e4162c",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/tests/test_client_ws_functional.py"
            },
            "plus_file": {
                "path": "b/tests/test_client_ws_functional.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 262,
                            "length": 6
                        },
                        "new_range": {
                            "start": 262,
                            "length": 33
                        },
                        "section": "async def test_concurrent_close(aiohttp_client) -> None:"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "    assert msg.type == aiohttp.WSMsgType.CLOSED",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "async def test_concurrent_task_close(aiohttp_client) -> None:",
                                "type": "added"
                            },
                            {
                                "content": "    async def handler(request):",
                                "type": "added"
                            },
                            {
                                "content": "        ws = web.WebSocketResponse()",
                                "type": "added"
                            },
                            {
                                "content": "        await ws.prepare(request)",
                                "type": "added"
                            },
                            {
                                "content": "        await ws.receive()",
                                "type": "added"
                            },
                            {
                                "content": "        return ws",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "    app = web.Application()",
                                "type": "added"
                            },
                            {
                                "content": "    app.router.add_route(\"GET\", \"/\", handler)",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "    client = await aiohttp_client(app)",
                                "type": "added"
                            },
                            {
                                "content": "    async with client.ws_connect(\"/\") as resp:",
                                "type": "added"
                            },
                            {
                                "content": "        # wait for the message in a separate task",
                                "type": "added"
                            },
                            {
                                "content": "        task = asyncio.create_task(resp.receive())",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "        # Make sure we start to wait on receiving message before closing the connection",
                                "type": "added"
                            },
                            {
                                "content": "        await asyncio.sleep(0.1)",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "        closed = await resp.close()",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "        await task",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "        assert closed",
                                "type": "added"
                            },
                            {
                                "content": "        assert resp.closed",
                                "type": "added"
                            },
                            {
                                "content": "        assert resp.close_code == 1000",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "async def test_close_from_server(aiohttp_client) -> None:",
                                "type": "context"
                            },
                            {
                                "content": "    loop = asyncio.get_event_loop()",
                                "type": "context"
                            },
                            {
                                "content": "    closed = loop.create_future()",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [
                        {
                            "file_name": "tests/test_client_ws_functional.py",
                            "type": "function",
                            "name": "test_concurrent_task_close",
                            "content": "async def test_concurrent_task_close(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n        await ws.receive()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    client = await aiohttp_client(app)\n    async with client.ws_connect(\"/\") as resp:\n        # wait for the message in a separate task\n        task = asyncio.create_task(resp.receive())\n\n        # Make sure we start to wait on receiving message before closing the connection\n        await asyncio.sleep(0.1)\n\n        closed = await resp.close()\n\n        await task\n\n        assert closed\n        assert resp.closed\n        assert resp.close_code == 1000",
                            "ast_type_str": "AsyncFunctionDef",
                            "start_lineno": 265,
                            "end_lineno": 289,
                            "parent": null
                        }
                    ],
                    "deleted_entities": []
                }
            ]
        }
    ],
    "old_commit_hash": "dde1446cb9fb6835570795eebe58bf435a6a0006^",
    "new_commit_hash": "dde1446cb9fb6835570795eebe58bf435a6a0006",
    "commit_message": "[PR #7684/30850ba backport][3.9] Fix #7306 - Set ClientWebSocketResponse.close_code correctly in concu… (#7690)\n\nThis is a backport of PR https://github.com/aio-libs/aiohttp/pull/7680\r\nas merged into master\r\n(https://github.com/aio-libs/aiohttp/commit/30850babb43a8e28dd2df036776c62fd613d3d89).\r\n\r\nFixes the issue when If one asyncio task is waiting on receiving data\r\nand another asyncio task is closing the connection. The\r\nClientWebSocketResponse.close_code will be None after connection closed.",
    "commit_date": "2023-10-11T22:13:20+01:00",
    "metadata": {}
}
{
    "repo_name": "aiohttp",
    "new_commit_hash": "dde1446cb9fb6835570795eebe58bf435a6a0006",
    "test_file_codes": [
        "import asyncio\nimport sys\n\nimport pytest\n\nimport aiohttp\nfrom aiohttp import hdrs, web\n\nif sys.version_info >= (3, 11):\n    import asyncio as async_timeout\nelse:\n    import async_timeout\n\n\nasync def test_send_recv_text(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        msg = await ws.receive_str()\n        await ws.send_str(msg + \"/answer\")\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n    await resp.send_str(\"ask\")\n\n    assert resp.get_extra_info(\"socket\") is not None\n\n    data = await resp.receive_str()\n    assert data == \"ask/answer\"\n    await resp.close()\n\n    assert resp.get_extra_info(\"socket\") is None\n\n\nasync def test_send_recv_bytes_bad_type(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        msg = await ws.receive_str()\n        await ws.send_str(msg + \"/answer\")\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n    await resp.send_str(\"ask\")\n\n    with pytest.raises(TypeError):\n        await resp.receive_bytes()\n        await resp.close()\n\n\nasync def test_send_recv_bytes(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        msg = await ws.receive_bytes()\n        await ws.send_bytes(msg + b\"/answer\")\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n\n    await resp.send_bytes(b\"ask\")\n\n    data = await resp.receive_bytes()\n    assert data == b\"ask/answer\"\n\n    await resp.close()\n\n\nasync def test_send_recv_text_bad_type(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        msg = await ws.receive_bytes()\n        await ws.send_bytes(msg + b\"/answer\")\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n\n    await resp.send_bytes(b\"ask\")\n\n    with pytest.raises(TypeError):\n        await resp.receive_str()\n\n        await resp.close()\n\n\nasync def test_send_recv_json(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        data = await ws.receive_json()\n        await ws.send_json({\"response\": data[\"request\"]})\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n    payload = {\"request\": \"test\"}\n    await resp.send_json(payload)\n\n    data = await resp.receive_json()\n    assert data[\"response\"] == payload[\"request\"]\n    await resp.close()\n\n\nasync def test_ping_pong(aiohttp_client) -> None:\n    loop = asyncio.get_event_loop()\n    closed = loop.create_future()\n\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        msg = await ws.receive_bytes()\n        await ws.ping()\n        await ws.send_bytes(msg + b\"/answer\")\n        try:\n            await ws.close()\n        finally:\n            closed.set_result(1)\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n\n    await resp.ping()\n    await resp.send_bytes(b\"ask\")\n\n    msg = await resp.receive()\n    assert msg.type == aiohttp.WSMsgType.BINARY\n    assert msg.data == b\"ask/answer\"\n\n    msg = await resp.receive()\n    assert msg.type == aiohttp.WSMsgType.CLOSE\n\n    await resp.close()\n    await closed\n\n\nasync def test_ping_pong_manual(aiohttp_client) -> None:\n    loop = asyncio.get_event_loop()\n    closed = loop.create_future()\n\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        msg = await ws.receive_bytes()\n        await ws.ping()\n        await ws.send_bytes(msg + b\"/answer\")\n        try:\n            await ws.close()\n        finally:\n            closed.set_result(1)\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\", autoping=False)\n\n    await resp.ping()\n    await resp.send_bytes(b\"ask\")\n\n    msg = await resp.receive()\n    assert msg.type == aiohttp.WSMsgType.PONG\n\n    msg = await resp.receive()\n    assert msg.type == aiohttp.WSMsgType.PING\n    await resp.pong()\n\n    msg = await resp.receive()\n    assert msg.data == b\"ask/answer\"\n\n    msg = await resp.receive()\n    assert msg.type == aiohttp.WSMsgType.CLOSE\n\n    await closed\n\n\nasync def test_close(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        await ws.receive_bytes()\n        await ws.send_str(\"test\")\n\n        await ws.receive()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n\n    await resp.send_bytes(b\"ask\")\n\n    closed = await resp.close()\n    assert closed\n    assert resp.closed\n    assert resp.close_code == 1000\n\n    msg = await resp.receive()\n    assert msg.type == aiohttp.WSMsgType.CLOSED\n\n\nasync def test_concurrent_close(aiohttp_client) -> None:\n    client_ws = None\n\n    async def handler(request):\n        nonlocal client_ws\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        await ws.receive_bytes()\n        await ws.send_str(\"test\")\n\n        await client_ws.close()\n\n        msg = await ws.receive()\n        assert msg.type == aiohttp.WSMsgType.CLOSE\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    ws = client_ws = await client.ws_connect(\"/\")\n\n    await ws.send_bytes(b\"ask\")\n\n    msg = await ws.receive()\n    assert msg.type == aiohttp.WSMsgType.CLOSING\n\n    await asyncio.sleep(0.01)\n    msg = await ws.receive()\n    assert msg.type == aiohttp.WSMsgType.CLOSED\n\n\nasync def test_concurrent_task_close(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n        await ws.receive()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    client = await aiohttp_client(app)\n    async with client.ws_connect(\"/\") as resp:\n        # wait for the message in a separate task\n        task = asyncio.create_task(resp.receive())\n\n        # Make sure we start to wait on receiving message before closing the connection\n        await asyncio.sleep(0.1)\n\n        closed = await resp.close()\n\n        await task\n\n        assert closed\n        assert resp.closed\n        assert resp.close_code == 1000\n\n\nasync def test_close_from_server(aiohttp_client) -> None:\n    loop = asyncio.get_event_loop()\n    closed = loop.create_future()\n\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        try:\n            await ws.receive_bytes()\n            await ws.close()\n        finally:\n            closed.set_result(1)\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n\n    await resp.send_bytes(b\"ask\")\n\n    msg = await resp.receive()\n    assert msg.type == aiohttp.WSMsgType.CLOSE\n    assert resp.closed\n\n    msg = await resp.receive()\n    assert msg.type == aiohttp.WSMsgType.CLOSED\n\n    await closed\n\n\nasync def test_close_manual(aiohttp_client) -> None:\n    loop = asyncio.get_event_loop()\n    closed = loop.create_future()\n\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        await ws.receive_bytes()\n        await ws.send_str(\"test\")\n\n        try:\n            await ws.close()\n        finally:\n            closed.set_result(1)\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\", autoclose=False)\n    await resp.send_bytes(b\"ask\")\n\n    msg = await resp.receive()\n    assert msg.data == \"test\"\n\n    msg = await resp.receive()\n    assert msg.type == aiohttp.WSMsgType.CLOSE\n    assert msg.data == 1000\n    assert msg.extra == \"\"\n    assert not resp.closed\n\n    await resp.close()\n    await closed\n    assert resp.closed\n\n\nasync def test_close_timeout(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n        await ws.receive_bytes()\n        await ws.send_str(\"test\")\n        await asyncio.sleep(1)\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\", timeout=0.2, autoclose=False)\n\n    await resp.send_bytes(b\"ask\")\n\n    msg = await resp.receive()\n    assert msg.data == \"test\"\n    assert msg.type == aiohttp.WSMsgType.TEXT\n\n    msg = await resp.close()\n    assert resp.closed\n    assert isinstance(resp.exception(), asyncio.TimeoutError)\n\n\nasync def test_close_cancel(aiohttp_client) -> None:\n    loop = asyncio.get_event_loop()\n\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n        await ws.receive_bytes()\n        await ws.send_str(\"test\")\n        await asyncio.sleep(10)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\", autoclose=False)\n\n    await resp.send_bytes(b\"ask\")\n\n    text = await resp.receive()\n    assert text.data == \"test\"\n\n    t = loop.create_task(resp.close())\n    await asyncio.sleep(0.1)\n    t.cancel()\n    await asyncio.sleep(0.1)\n    assert resp.closed\n    assert resp.exception() is None\n\n\nasync def test_override_default_headers(aiohttp_client) -> None:\n    async def handler(request):\n        assert request.headers[hdrs.SEC_WEBSOCKET_VERSION] == \"8\"\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n        await ws.send_str(\"answer\")\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    headers = {hdrs.SEC_WEBSOCKET_VERSION: \"8\"}\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\", headers=headers)\n    msg = await resp.receive()\n    assert msg.data == \"answer\"\n    await resp.close()\n\n\nasync def test_additional_headers(aiohttp_client) -> None:\n    async def handler(request):\n        assert request.headers[\"x-hdr\"] == \"xtra\"\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        await ws.send_str(\"answer\")\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\", headers={\"x-hdr\": \"xtra\"})\n    msg = await resp.receive()\n    assert msg.data == \"answer\"\n    await resp.close()\n\n\nasync def test_recv_protocol_error(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        await ws.receive_str()\n        ws._writer.transport.write(b\"01234\" * 100)\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n    await resp.send_str(\"ask\")\n\n    msg = await resp.receive()\n    assert msg.type == aiohttp.WSMsgType.ERROR\n    assert type(msg.data) is aiohttp.WebSocketError\n    assert msg.data.code == aiohttp.WSCloseCode.PROTOCOL_ERROR\n    assert str(msg.data) == \"Received frame with non-zero reserved bits\"\n    assert msg.extra is None\n    await resp.close()\n\n\nasync def test_recv_timeout(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        await ws.receive_str()\n\n        await asyncio.sleep(0.1)\n\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n    await resp.send_str(\"ask\")\n\n    with pytest.raises(asyncio.TimeoutError):\n        async with async_timeout.timeout(0.01):\n            await resp.receive()\n\n    await resp.close()\n\n\nasync def test_receive_timeout(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n        await ws.receive()\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\", receive_timeout=0.1)\n\n    with pytest.raises(asyncio.TimeoutError):\n        await resp.receive(0.05)\n\n    await resp.close()\n\n\nasync def test_custom_receive_timeout(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n        await ws.receive()\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n\n    with pytest.raises(asyncio.TimeoutError):\n        await resp.receive(0.05)\n\n    await resp.close()\n\n\nasync def test_heartbeat(aiohttp_client) -> None:\n    ping_received = False\n\n    async def handler(request):\n        nonlocal ping_received\n        ws = web.WebSocketResponse(autoping=False)\n        await ws.prepare(request)\n        msg = await ws.receive()\n        if msg.type == aiohttp.WSMsgType.ping:\n            ping_received = True\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\", heartbeat=0.01)\n    await asyncio.sleep(0.1)\n    await resp.receive()\n    await resp.close()\n\n    assert ping_received\n\n\nasync def test_heartbeat_no_pong(aiohttp_client) -> None:\n    ping_received = False\n\n    async def handler(request):\n        nonlocal ping_received\n        ws = web.WebSocketResponse(autoping=False)\n        await ws.prepare(request)\n        msg = await ws.receive()\n        if msg.type == aiohttp.WSMsgType.ping:\n            ping_received = True\n        await ws.receive()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\", heartbeat=0.05)\n\n    await resp.receive()\n    await resp.receive()\n\n    assert ping_received\n\n\nasync def test_send_recv_compress(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        msg = await ws.receive_str()\n        await ws.send_str(msg + \"/answer\")\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\", compress=15)\n    await resp.send_str(\"ask\")\n\n    assert resp.compress == 15\n\n    data = await resp.receive_str()\n    assert data == \"ask/answer\"\n\n    await resp.close()\n    assert resp.get_extra_info(\"socket\") is None\n\n\nasync def test_send_recv_compress_wbits(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        msg = await ws.receive_str()\n        await ws.send_str(msg + \"/answer\")\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\", compress=9)\n    await resp.send_str(\"ask\")\n\n    # Client indicates supports wbits 15\n    # Server supports wbit 15 for decode\n    assert resp.compress == 15\n\n    data = await resp.receive_str()\n    assert data == \"ask/answer\"\n\n    await resp.close()\n    assert resp.get_extra_info(\"socket\") is None\n\n\nasync def test_send_recv_compress_wbit_error(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        msg = await ws.receive_bytes()\n        await ws.send_bytes(msg + b\"/answer\")\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    with pytest.raises(ValueError):\n        await client.ws_connect(\"/\", compress=1)\n\n\nasync def test_ws_client_async_for(aiohttp_client) -> None:\n    items = [\"q1\", \"q2\", \"q3\"]\n\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n        for i in items:\n            await ws.send_str(i)\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n    it = iter(items)\n    async for msg in resp:\n        assert msg.data == next(it)\n\n    with pytest.raises(StopIteration):\n        next(it)\n\n    assert resp.closed\n\n\nasync def test_ws_async_with(aiohttp_server) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n        msg = await ws.receive()\n        await ws.send_str(msg.data + \"/answer\")\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    server = await aiohttp_server(app)\n\n    async with aiohttp.ClientSession() as client:\n        async with client.ws_connect(server.make_url(\"/\")) as ws:\n            await ws.send_str(\"request\")\n            msg = await ws.receive()\n            assert msg.data == \"request/answer\"\n\n        assert ws.closed\n\n\nasync def test_ws_async_with_send(aiohttp_server) -> None:\n    # send_xxx methods have to return awaitable objects\n\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n        msg = await ws.receive()\n        await ws.send_str(msg.data + \"/answer\")\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    server = await aiohttp_server(app)\n\n    async with aiohttp.ClientSession() as client:\n        async with client.ws_connect(server.make_url(\"/\")) as ws:\n            await ws.send_str(\"request\")\n            msg = await ws.receive()\n            assert msg.data == \"request/answer\"\n\n        assert ws.closed\n\n\nasync def test_ws_async_with_shortcut(aiohttp_server) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n        msg = await ws.receive()\n        await ws.send_str(msg.data + \"/answer\")\n        await ws.close()\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    server = await aiohttp_server(app)\n\n    async with aiohttp.ClientSession() as client:\n        async with client.ws_connect(server.make_url(\"/\")) as ws:\n            await ws.send_str(\"request\")\n            msg = await ws.receive()\n            assert msg.data == \"request/answer\"\n\n        assert ws.closed\n\n\nasync def test_closed_async_for(aiohttp_client) -> None:\n    loop = asyncio.get_event_loop()\n    closed = loop.create_future()\n\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        try:\n            await ws.send_bytes(b\"started\")\n            await ws.receive_bytes()\n        finally:\n            closed.set_result(1)\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n\n    messages = []\n    async for msg in resp:\n        messages.append(msg)\n        if b\"started\" == msg.data:\n            await resp.send_bytes(b\"ask\")\n            await resp.close()\n\n    assert 1 == len(messages)\n    assert messages[0].type == aiohttp.WSMsgType.BINARY\n    assert messages[0].data == b\"started\"\n    assert resp.closed\n\n    await closed\n\n\nasync def test_peer_connection_lost(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        msg = await ws.receive_str()\n        assert msg == \"ask\"\n        await ws.send_str(\"answer\")\n        request.transport.close()\n        await asyncio.sleep(10)\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n    await resp.send_str(\"ask\")\n    assert \"answer\" == await resp.receive_str()\n\n    msg = await resp.receive()\n    assert msg.type == aiohttp.WSMsgType.CLOSED\n    await resp.close()\n\n\nasync def test_peer_connection_lost_iter(aiohttp_client) -> None:\n    async def handler(request):\n        ws = web.WebSocketResponse()\n        await ws.prepare(request)\n\n        msg = await ws.receive_str()\n        assert msg == \"ask\"\n        await ws.send_str(\"answer\")\n        request.transport.close()\n        await asyncio.sleep(100)\n        return ws\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    resp = await client.ws_connect(\"/\")\n    await resp.send_str(\"ask\")\n    async for msg in resp:\n        assert \"answer\" == msg.data\n\n    await resp.close()\n",
        "import asyncio\nimport os\nimport socket\nimport ssl\nimport sys\nfrom hashlib import md5, sha256\nfrom pathlib import Path\nfrom tempfile import TemporaryDirectory\nfrom uuid import uuid4\n\nimport pytest\n\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 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"
    ],
    "test_file_names": [
        "test_1.py",
        "conftest.py"
    ],
    "setup_res_code": 0,
    "setup_res_stdout": "re-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/requirements/cython.txt\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/tools/gen.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/hdrs.py\n./tools/gen.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/_helpers.pyx\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/_http_parser.pyx\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/_http_writer.pyx\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/_websocket.pyx\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/_helpers.pyi\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/_cparser.pxd\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/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 install\n\n> llhttp@9.1.3 prepare\n> npm run clean && npm run build-ts\n\n\n> llhttp@9.1.3 clean\n> rm -rf lib && rm -rf test/tmp\n\n\n> llhttp@9.1.3 build-ts\n> tsc\n\n\nadded 157 packages, and audited 158 packages in 4s\n\n23 packages are looking for funding\n  run `npm fund` for details\n\n5 vulnerabilities (4 moderate, 1 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_dde1446cb9fb6835570795eebe58bf435a6a0006/vendor/llhttp'\nnpx ts-node bin/generate.ts\nmake[1]: Leaving directory '/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/vendor/llhttp'\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/__init__.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/abc.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/base_protocol.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/client.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/client_exceptions.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/client_proto.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/client_reqrep.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/client_ws.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/compression_utils.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/connector.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/cookiejar.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/formdata.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/helpers.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/http.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/http_exceptions.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/http_parser.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/http_websocket.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/http_writer.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/locks.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/log.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/multipart.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/payload.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/payload_streamer.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/pytest_plugin.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/resolver.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/streams.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/tcp_helpers.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/test_utils.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/tracing.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/typedefs.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/web.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/web_app.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/web_exceptions.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/web_fileresponse.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/web_log.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/web_middlewares.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/web_protocol.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/web_request.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/web_response.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/web_routedef.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/web_runner.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/web_server.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/web_urldispatcher.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/web_ws.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/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 40ms\nPrepared 1 package in 0.51ms\nInstalled 1 package in 15ms\n + pip==24.3.1\nResolved 3 packages in 13ms\nInstalled 3 packages in 45ms\n + cython==3.0.3\n + multidict==6.0.4\n + typing-extensions==4.7.1\nResolved 97 packages in 203ms\nUninstalled 1 package in 8ms\nInstalled 95 packages in 84ms\n + aiodns==3.1.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.5.0\n + async-timeout==4.0.3\n + attrs==23.1.0\n + babel==2.12.1\n + blockdiag==3.0.0\n + brotli==1.1.0\n + build==0.10.0\n + certifi==2023.7.22\n + cffi==1.15.1\n + cfgv==3.3.1\n + charset-normalizer==3.2.0\n + cherry-picker==2.1.0\n + click==8.1.6\n + click-default-group==1.2.2\n + coverage==7.3.2\n + cryptography==41.0.3\n + distlib==0.3.7\n + docutils==0.20.1\n + exceptiongroup==1.1.2\n + filelock==3.12.2\n + freezegun==1.2.2\n + frozenlist==1.4.0\n + funcparserlib==1.0.1\n + gidgethub==5.3.0\n + gunicorn==21.2.0\n + identify==2.5.26\n + idna==3.4\n + imagesize==1.4.1\n + importlib-metadata==8.5.0\n + importlib-resources==6.4.5\n + incremental==22.10.0\n + iniconfig==2.0.0\n + jinja2==3.1.2\n + markupsafe==2.1.3\n + mypy==1.5.1\n + mypy-extensions==1.0.0\n + nodeenv==1.8.0\n + packaging==23.1\n + pillow==9.5.0\n - pip==24.3.1\n + pip==23.2.1\n + pip-tools==7.3.0\n + platformdirs==3.10.0\n + pluggy==1.2.0\n + pre-commit==3.4.0\n + proxy-py==2.4.3\n + pycares==4.3.0\n + pycparser==2.21\n + pydantic==2.2.0\n + pydantic-core==2.6.0\n + pygments==2.15.1\n + pyjwt==2.8.0\n + pyproject-hooks==1.0.0\n + pytest==7.4.2\n + pytest-cov==4.1.0\n + pytest-mock==3.11.1\n + python-dateutil==2.8.2\n + python-on-whales==0.65.0\n + pyyaml==6.0.1\n + re-assert==1.1.0\n + regex==2023.6.3\n + requests==2.31.0\n + setuptools==68.0.0\n + setuptools-git==1.2\n + six==1.16.0\n + slotscheck==0.17.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.3.2a0\n + toml==0.10.2\n + tomli==2.0.1\n + towncrier==23.6.0\n + tqdm==4.65.0\n + trustme==1.1.0\n + typer==0.9.0\n + uritemplate==4.1.1\n + urllib3==2.0.4\n + uvloop==0.17.0\n + virtualenv==20.24.2\n + wait-for-it==2.2.2\n + webcolors==1.13\n + wheel==0.41.0\n + yarl==1.9.2\n + zipp==3.21.0\nResolved 8 packages in 1.27s\nPrepared 1 package in 15.90s\nInstalled 1 package in 0.53ms\n + aiohttp==3.9.0b0 (from file:///home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006)\nResolved 24 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.23.8\n",
    "new_commit_res_code": 0,
    "new_commit_res_stdout": "============================= test session starts ==============================\nplatform linux -- Python 3.9.21, pytest-7.4.2, pluggy-1.2.0 -- /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/.venv/bin/python\ncachedir: .pytest_cache\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006\nconfigfile: setup.cfg\nplugins: mock-3.11.1, asyncio-0.23.8, cov-4.1.0\nasyncio: mode=strict\ncollecting ... collected 32 items\n\nr2e_tests/test_1.py::test_send_recv_text[pyloop] PASSED                  [  3%]\nr2e_tests/test_1.py::test_send_recv_bytes_bad_type[pyloop] PASSED        [  6%]\nr2e_tests/test_1.py::test_send_recv_bytes[pyloop] PASSED                 [  9%]\nr2e_tests/test_1.py::test_send_recv_text_bad_type[pyloop] PASSED         [ 12%]\nr2e_tests/test_1.py::test_send_recv_json[pyloop] PASSED                  [ 15%]\nr2e_tests/test_1.py::test_ping_pong[pyloop] PASSED                       [ 18%]\nr2e_tests/test_1.py::test_ping_pong_manual[pyloop] PASSED                [ 21%]\nr2e_tests/test_1.py::test_close[pyloop] PASSED                           [ 25%]\nr2e_tests/test_1.py::test_concurrent_close[pyloop] PASSED                [ 28%]\nr2e_tests/test_1.py::test_concurrent_task_close[pyloop] PASSED           [ 31%]\nr2e_tests/test_1.py::test_close_from_server[pyloop] PASSED               [ 34%]\nr2e_tests/test_1.py::test_close_manual[pyloop] PASSED                    [ 37%]\nr2e_tests/test_1.py::test_close_timeout[pyloop] PASSED                   [ 40%]\nr2e_tests/test_1.py::test_close_cancel[pyloop] PASSED                    [ 43%]\nr2e_tests/test_1.py::test_override_default_headers[pyloop] PASSED        [ 46%]\nr2e_tests/test_1.py::test_additional_headers[pyloop] PASSED              [ 50%]\nr2e_tests/test_1.py::test_recv_protocol_error[pyloop] PASSED             [ 53%]\nr2e_tests/test_1.py::test_recv_timeout[pyloop] PASSED                    [ 56%]\nr2e_tests/test_1.py::test_receive_timeout[pyloop] PASSED                 [ 59%]\nr2e_tests/test_1.py::test_custom_receive_timeout[pyloop] PASSED          [ 62%]\nr2e_tests/test_1.py::test_heartbeat[pyloop] PASSED                       [ 65%]\nr2e_tests/test_1.py::test_heartbeat_no_pong[pyloop] PASSED               [ 68%]\nr2e_tests/test_1.py::test_send_recv_compress[pyloop] PASSED              [ 71%]\nr2e_tests/test_1.py::test_send_recv_compress_wbits[pyloop] PASSED        [ 75%]\nr2e_tests/test_1.py::test_send_recv_compress_wbit_error[pyloop] PASSED   [ 78%]\nr2e_tests/test_1.py::test_ws_client_async_for[pyloop] PASSED             [ 81%]\nr2e_tests/test_1.py::test_ws_async_with[pyloop] PASSED                   [ 84%]\nr2e_tests/test_1.py::test_ws_async_with_send[pyloop] PASSED              [ 87%]\nr2e_tests/test_1.py::test_ws_async_with_shortcut[pyloop] PASSED          [ 90%]\nr2e_tests/test_1.py::test_closed_async_for[pyloop] PASSED                [ 93%]\nr2e_tests/test_1.py::test_peer_connection_lost[pyloop] PASSED            [ 96%]\nr2e_tests/test_1.py::test_peer_connection_lost_iter[pyloop] 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      8      2      1    69%\naiohttp/abc.py                              90      2      0      0    98%\naiohttp/base_protocol.py                    66     36     22      3    38%\naiohttp/client.py                          490    188    180     57    56%\naiohttp/client_exceptions.py               135     57     16      1    52%\naiohttp/client_proto.py                    149     34     54     15    72%\naiohttp/client_reqrep.py                   646    296    280     58    46%\naiohttp/client_ws.py                       210     26     66     14    86%\naiohttp/compression_utils.py                68     18     14      3    65%\naiohttp/connector.py                       713    420    311     44    33%\naiohttp/cookiejar.py                       256    163    117     10    28%\naiohttp/formdata.py                         93     76     46      0    12%\naiohttp/hdrs.py                             90      0      0      0   100%\naiohttp/helpers.py                         513    264    178     20    42%\naiohttp/http.py                             11      0      2      0   100%\naiohttp/http_exceptions.py                  51     21      6      0    53%\naiohttp/http_parser.py                     490    391    196      1    15%\naiohttp/http_websocket.py                  385     78    152     38    74%\naiohttp/http_writer.py                     118     44     50     13    53%\naiohttp/locks.py                            24     16      4      0    29%\naiohttp/log.py                               7      0      0      0   100%\naiohttp/multipart.py                       562    455    232      0    14%\naiohttp/payload.py                         219    107     56      1    43%\naiohttp/payload_streamer.py                 29     10      4      0    70%\naiohttp/pytest_plugin.py                   167     56     42      9    63%\naiohttp/resolver.py                         68     47     22      0    23%\naiohttp/streams.py                         396    261    144      3    28%\naiohttp/tcp_helpers.py                      19      2      6      3    80%\naiohttp/test_utils.py                      313    119     52     13    57%\naiohttp/tracing.py                         191     69     32      0    69%\naiohttp/typedefs.py                         23      0      0      0   100%\naiohttp/web.py                             116     81     52      0    22%\naiohttp/web_app.py                         301    108     74     19    58%\naiohttp/web_exceptions.py                  151     22      6      0    82%\naiohttp/web_fileresponse.py                141    118     50      0    12%\naiohttp/web_log.py                         102     37     20      1    59%\naiohttp/web_middlewares.py                  55     37     20      0    24%\naiohttp/web_protocol.py                    343    136    157     37    50%\naiohttp/web_request.py                     435    245    128      8    36%\naiohttp/web_response.py                    474    302    206     11    27%\naiohttp/web_routedef.py                    106     46     10      0    55%\naiohttp/web_runner.py                      218     70     36     10    64%\naiohttp/web_server.py                       38      5      6      1    82%\naiohttp/web_urldispatcher.py               708    371    161     20    41%\naiohttp/web_ws.py                          319    100    108     33    63%\naiohttp/worker.py                          126    126     30      0     0%\ntests/__init__.py                            0      0      0      0   100%\ntests/conftest.py                          105    105     16      0     0%\ntests/test_base_protocol.py                198    198      2      0     0%\ntests/test_circular_imports.py              31     31     15      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            183    183     14      0     0%\ntests/test_client_fingerprint.py            59     59      0      0     0%\ntests/test_client_functional.py           2207   2207     70      0     0%\ntests/test_client_proto.py                  99     99      0      0     0%\ntests/test_client_request.py               773    773     18      0     0%\ntests/test_client_response.py              456    456      4      0     0%\ntests/test_client_session.py               482    482     23      0     0%\ntests/test_client_ws.py                    415    415      2      0     0%\ntests/test_client_ws_functional.py         605    605     16      0     0%\ntests/test_connector.py                   1520   1520     76      0     0%\ntests/test_cookiejar.py                    349    349     22      0     0%\ntests/test_flowcontrol_streams.py          100    100      0      0     0%\ntests/test_formdata.py                      72     72      6      0     0%\ntests/test_helpers.py                      442    442     24      0     0%\ntests/test_http_exceptions.py              109    109     10      0     0%\ntests/test_http_parser.py                  844    844     40      0     0%\ntests/test_http_writer.py                  182    182     10      0     0%\ntests/test_imports.py                       31     31      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                    747    747     22      0     0%\ntests/test_multipart_helpers.py            446    446      0      0     0%\ntests/test_payload.py                       94     94      0      0     0%\ntests/test_proxy.py                        285    285      0      0     0%\ntests/test_proxy_functional.py             472    472     22      0     0%\ntests/test_pytest_plugin.py                 27     27      0      0     0%\ntests/test_resolver.py                     176    176     12      0     0%\ntests/test_route_def.py                    210    210      0      0     0%\ntests/test_run_app.py                      460    460     24      0     0%\ntests/test_streams.py                     1077   1077     40      0     0%\ntests/test_tcp_helpers.py                   52     52      2      0     0%\ntests/test_test_utils.py                   242    242      6      0     0%\ntests/test_tracing.py                       48     48      0      0     0%\ntests/test_urldispatch.py                  844    844     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               157    157     22      0     0%\ntests/test_web_functional.py              1523   1523     36      0     0%\ntests/test_web_log.py                      116    116      2      0     0%\ntests/test_web_middleware.py               266    266     12      0     0%\ntests/test_web_request.py                  490    490      8      0     0%\ntests/test_web_request_handler.py           40     40      0      0     0%\ntests/test_web_response.py                 817    817      4      0     0%\ntests/test_web_runner.py                   146    146      4      0     0%\ntests/test_web_sendfile.py                  76     76      0      0     0%\ntests/test_web_sendfile_functional.py      634    634     18      0     0%\ntests/test_web_server.py                   160    160      0      0     0%\ntests/test_web_urldispatcher.py            306    306     14      0     0%\ntests/test_web_websocket.py                304    304      4      0     0%\ntests/test_web_websocket_functional.py     542    542     16      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              68     68      0      0     0%\ntests/test_worker.py                       191    191      4      0     0%\n--------------------------------------------------------------------------\nTOTAL                                    31719  26535   4052    447    17%\n\n============================= slowest 10 durations =============================\n0.20s call     r2e_tests/test_1.py::test_close_cancel[pyloop]\n0.20s call     r2e_tests/test_1.py::test_close_timeout[pyloop]\n0.11s call     r2e_tests/test_1.py::test_concurrent_task_close[pyloop]\n0.10s call     r2e_tests/test_1.py::test_heartbeat[pyloop]\n0.08s call     r2e_tests/test_1.py::test_heartbeat_no_pong[pyloop]\n0.06s teardown r2e_tests/test_1.py::test_concurrent_task_close[pyloop]\n0.05s call     r2e_tests/test_1.py::test_custom_receive_timeout[pyloop]\n0.05s call     r2e_tests/test_1.py::test_receive_timeout[pyloop]\n0.02s teardown r2e_tests/test_1.py::test_custom_receive_timeout[pyloop]\n0.02s teardown r2e_tests/test_1.py::test_heartbeat_no_pong[pyloop]\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::test_send_recv_text[pyloop]\nPASSED r2e_tests/test_1.py::test_send_recv_bytes_bad_type[pyloop]\nPASSED r2e_tests/test_1.py::test_send_recv_bytes[pyloop]\nPASSED r2e_tests/test_1.py::test_send_recv_text_bad_type[pyloop]\nPASSED r2e_tests/test_1.py::test_send_recv_json[pyloop]\nPASSED r2e_tests/test_1.py::test_ping_pong[pyloop]\nPASSED r2e_tests/test_1.py::test_ping_pong_manual[pyloop]\nPASSED r2e_tests/test_1.py::test_close[pyloop]\nPASSED r2e_tests/test_1.py::test_concurrent_close[pyloop]\nPASSED r2e_tests/test_1.py::test_concurrent_task_close[pyloop]\nPASSED r2e_tests/test_1.py::test_close_from_server[pyloop]\nPASSED r2e_tests/test_1.py::test_close_manual[pyloop]\nPASSED r2e_tests/test_1.py::test_close_timeout[pyloop]\nPASSED r2e_tests/test_1.py::test_close_cancel[pyloop]\nPASSED r2e_tests/test_1.py::test_override_default_headers[pyloop]\nPASSED r2e_tests/test_1.py::test_additional_headers[pyloop]\nPASSED r2e_tests/test_1.py::test_recv_protocol_error[pyloop]\nPASSED r2e_tests/test_1.py::test_recv_timeout[pyloop]\nPASSED r2e_tests/test_1.py::test_receive_timeout[pyloop]\nPASSED r2e_tests/test_1.py::test_custom_receive_timeout[pyloop]\nPASSED r2e_tests/test_1.py::test_heartbeat[pyloop]\nPASSED r2e_tests/test_1.py::test_heartbeat_no_pong[pyloop]\nPASSED r2e_tests/test_1.py::test_send_recv_compress[pyloop]\nPASSED r2e_tests/test_1.py::test_send_recv_compress_wbits[pyloop]\nPASSED r2e_tests/test_1.py::test_send_recv_compress_wbit_error[pyloop]\nPASSED r2e_tests/test_1.py::test_ws_client_async_for[pyloop]\nPASSED r2e_tests/test_1.py::test_ws_async_with[pyloop]\nPASSED r2e_tests/test_1.py::test_ws_async_with_send[pyloop]\nPASSED r2e_tests/test_1.py::test_ws_async_with_shortcut[pyloop]\nPASSED r2e_tests/test_1.py::test_closed_async_for[pyloop]\nPASSED r2e_tests/test_1.py::test_peer_connection_lost[pyloop]\nPASSED r2e_tests/test_1.py::test_peer_connection_lost_iter[pyloop]\n============================== 32 passed in 4.86s ==============================\n",
    "new_commit_res_stderr": "",
    "old_commit_res_code": 1,
    "old_commit_res_stdout": "============================= test session starts ==============================\nplatform linux -- Python 3.9.21, pytest-7.4.2, pluggy-1.2.0 -- /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/.venv/bin/python\ncachedir: .pytest_cache\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006\nconfigfile: setup.cfg\nplugins: mock-3.11.1, asyncio-0.23.8, cov-4.1.0\nasyncio: mode=strict\ncollecting ... collected 32 items\n\nr2e_tests/test_1.py::test_send_recv_text[pyloop] PASSED                  [  3%]\nr2e_tests/test_1.py::test_send_recv_bytes_bad_type[pyloop] PASSED        [  6%]\nr2e_tests/test_1.py::test_send_recv_bytes[pyloop] PASSED                 [  9%]\nr2e_tests/test_1.py::test_send_recv_text_bad_type[pyloop] PASSED         [ 12%]\nr2e_tests/test_1.py::test_send_recv_json[pyloop] PASSED                  [ 15%]\nr2e_tests/test_1.py::test_ping_pong[pyloop] PASSED                       [ 18%]\nr2e_tests/test_1.py::test_ping_pong_manual[pyloop] PASSED                [ 21%]\nr2e_tests/test_1.py::test_close[pyloop] PASSED                           [ 25%]\nr2e_tests/test_1.py::test_concurrent_close[pyloop] PASSED                [ 28%]\nr2e_tests/test_1.py::test_concurrent_task_close[pyloop] FAILED           [ 31%]\nr2e_tests/test_1.py::test_close_from_server[pyloop] PASSED               [ 34%]\nr2e_tests/test_1.py::test_close_manual[pyloop] PASSED                    [ 37%]\nr2e_tests/test_1.py::test_close_timeout[pyloop] PASSED                   [ 40%]\nr2e_tests/test_1.py::test_close_cancel[pyloop] PASSED                    [ 43%]\nr2e_tests/test_1.py::test_override_default_headers[pyloop] PASSED        [ 46%]\nr2e_tests/test_1.py::test_additional_headers[pyloop] PASSED              [ 50%]\nr2e_tests/test_1.py::test_recv_protocol_error[pyloop] PASSED             [ 53%]\nr2e_tests/test_1.py::test_recv_timeout[pyloop] PASSED                    [ 56%]\nr2e_tests/test_1.py::test_receive_timeout[pyloop] PASSED                 [ 59%]\nr2e_tests/test_1.py::test_custom_receive_timeout[pyloop] PASSED          [ 62%]\nr2e_tests/test_1.py::test_heartbeat[pyloop] PASSED                       [ 65%]\nr2e_tests/test_1.py::test_heartbeat_no_pong[pyloop] PASSED               [ 68%]\nr2e_tests/test_1.py::test_send_recv_compress[pyloop] PASSED              [ 71%]\nr2e_tests/test_1.py::test_send_recv_compress_wbits[pyloop] PASSED        [ 75%]\nr2e_tests/test_1.py::test_send_recv_compress_wbit_error[pyloop] PASSED   [ 78%]\nr2e_tests/test_1.py::test_ws_client_async_for[pyloop] PASSED             [ 81%]\nr2e_tests/test_1.py::test_ws_async_with[pyloop] PASSED                   [ 84%]\nr2e_tests/test_1.py::test_ws_async_with_send[pyloop] PASSED              [ 87%]\nr2e_tests/test_1.py::test_ws_async_with_shortcut[pyloop] PASSED          [ 90%]\nr2e_tests/test_1.py::test_closed_async_for[pyloop] PASSED                [ 93%]\nr2e_tests/test_1.py::test_peer_connection_lost[pyloop] PASSED            [ 96%]\nr2e_tests/test_1.py::test_peer_connection_lost_iter[pyloop] PASSED       [100%]\n\n=================================== FAILURES ===================================\n______________________ test_concurrent_task_close[pyloop] ______________________\n\naiohttp_client = <function aiohttp_client.<locals>.go at 0x76164fcddf70>\n\n    async def test_concurrent_task_close(aiohttp_client) -> None:\n        async def handler(request):\n            ws = web.WebSocketResponse()\n            await ws.prepare(request)\n            await ws.receive()\n            return ws\n    \n        app = web.Application()\n        app.router.add_route(\"GET\", \"/\", handler)\n    \n        client = await aiohttp_client(app)\n        async with client.ws_connect(\"/\") as resp:\n            # wait for the message in a separate task\n            task = asyncio.create_task(resp.receive())\n    \n            # Make sure we start to wait on receiving message before closing the connection\n            await asyncio.sleep(0.1)\n    \n            closed = await resp.close()\n    \n            await task\n    \n            assert closed\n            assert resp.closed\n>           assert resp.close_code == 1000\nE           assert None == 1000\nE            +  where None = <aiohttp.client_ws.ClientWebSocketResponse object at 0x76164fbfaa30>.close_code\n\naiohttp_client = <function aiohttp_client.<locals>.go at 0x76164fcddf70>\napp        = <Application 0x76164fca48b0>\nclient     = <aiohttp.test_utils.TestClient object at 0x76164fca4ca0>\nclosed     = True\nhandler    = <function test_concurrent_task_close.<locals>.handler at 0x76164fcdda60>\nresp       = <aiohttp.client_ws.ClientWebSocketResponse object at 0x76164fbfaa30>\ntask       = <Task finished name='Task-79' coro=<ClientWebSocketResponse.receive() done, defined at /home/gcpuser/buckets/local_rep...repos/aiohttp_dde1446cb9fb6835570795eebe58bf435a6a0006/aiohttp/client_ws.py:228> result=WSMessage(typ...e, extra=None)>\n\nr2e_tests/test_1.py:289: AssertionError\n==================================== PASSES ====================================\n\n---------- coverage: platform linux, python 3.9.21-final-0 -----------\nName                                     Stmts   Miss Branch BrPart  Cover\n--------------------------------------------------------------------------\naiohttp/__init__.py                         27      8      2      1    69%\naiohttp/abc.py                              90      2      0      0    98%\naiohttp/base_protocol.py                    66     36     22      3    38%\naiohttp/client.py                          490    188    180     57    56%\naiohttp/client_exceptions.py               135     57     16      1    52%\naiohttp/client_proto.py                    149     34     54     15    72%\naiohttp/client_reqrep.py                   646    296    280     58    46%\naiohttp/client_ws.py                       209     26     66     14    85%\naiohttp/compression_utils.py                68     18     14      3    65%\naiohttp/connector.py                       713    422    311     46    33%\naiohttp/cookiejar.py                       256    163    117     10    28%\naiohttp/formdata.py                         93     76     46      0    12%\naiohttp/hdrs.py                             90      0      0      0   100%\naiohttp/helpers.py                         513    264    178     20    42%\naiohttp/http.py                             11      0      2      0   100%\naiohttp/http_exceptions.py                  51     21      6      0    53%\naiohttp/http_parser.py                     490    391    196      1    15%\naiohttp/http_websocket.py                  385     78    152     38    74%\naiohttp/http_writer.py                     118     44     50     13    53%\naiohttp/locks.py                            24     16      4      0    29%\naiohttp/log.py                               7      0      0      0   100%\naiohttp/multipart.py                       562    455    232      0    14%\naiohttp/payload.py                         219    107     56      1    43%\naiohttp/payload_streamer.py                 29     10      4      0    70%\naiohttp/pytest_plugin.py                   167     55     42      9    64%\naiohttp/resolver.py                         68     47     22      0    23%\naiohttp/streams.py                         396    260    144      2    28%\naiohttp/tcp_helpers.py                      19      2      6      3    80%\naiohttp/test_utils.py                      313    119     52     13    57%\naiohttp/tracing.py                         191     69     32      0    69%\naiohttp/typedefs.py                         23      0      0      0   100%\naiohttp/web.py                             116     81     52      0    22%\naiohttp/web_app.py                         301    107     74     19    58%\naiohttp/web_exceptions.py                  151     22      6      0    82%\naiohttp/web_fileresponse.py                141    118     50      0    12%\naiohttp/web_log.py                         102     37     20      1    59%\naiohttp/web_middlewares.py                  55     37     20      0    24%\naiohttp/web_protocol.py                    343    136    157     37    50%\naiohttp/web_request.py                     435    245    128      8    36%\naiohttp/web_response.py                    474    302    206     11    27%\naiohttp/web_routedef.py                    106     46     10      0    55%\naiohttp/web_runner.py                      218     70     36     10    64%\naiohttp/web_server.py                       38      5      6      1    82%\naiohttp/web_urldispatcher.py               708    371    161     20    41%\naiohttp/web_ws.py                          319    100    108     33    63%\naiohttp/worker.py                          126    126     30      0     0%\ntests/__init__.py                            0      0      0      0   100%\ntests/conftest.py                          105    105     16      0     0%\ntests/test_base_protocol.py                198    198      2      0     0%\ntests/test_circular_imports.py              31     31     15      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            183    183     14      0     0%\ntests/test_client_fingerprint.py            59     59      0      0     0%\ntests/test_client_functional.py           2207   2207     70      0     0%\ntests/test_client_proto.py                  99     99      0      0     0%\ntests/test_client_request.py               773    773     18      0     0%\ntests/test_client_response.py              456    456      4      0     0%\ntests/test_client_session.py               482    482     23      0     0%\ntests/test_client_ws.py                    415    415      2      0     0%\ntests/test_client_ws_functional.py         588    588     16      0     0%\ntests/test_connector.py                   1520   1520     76      0     0%\ntests/test_cookiejar.py                    349    349     22      0     0%\ntests/test_flowcontrol_streams.py          100    100      0      0     0%\ntests/test_formdata.py                      72     72      6      0     0%\ntests/test_helpers.py                      442    442     24      0     0%\ntests/test_http_exceptions.py              109    109     10      0     0%\ntests/test_http_parser.py                  844    844     40      0     0%\ntests/test_http_writer.py                  182    182     10      0     0%\ntests/test_imports.py                       31     31      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                    747    747     22      0     0%\ntests/test_multipart_helpers.py            446    446      0      0     0%\ntests/test_payload.py                       94     94      0      0     0%\ntests/test_proxy.py                        285    285      0      0     0%\ntests/test_proxy_functional.py             472    472     22      0     0%\ntests/test_pytest_plugin.py                 27     27      0      0     0%\ntests/test_resolver.py                     176    176     12      0     0%\ntests/test_route_def.py                    210    210      0      0     0%\ntests/test_run_app.py                      460    460     24      0     0%\ntests/test_streams.py                     1077   1077     40      0     0%\ntests/test_tcp_helpers.py                   52     52      2      0     0%\ntests/test_test_utils.py                   242    242      6      0     0%\ntests/test_tracing.py                       48     48      0      0     0%\ntests/test_urldispatch.py                  844    844     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               157    157     22      0     0%\ntests/test_web_functional.py              1523   1523     36      0     0%\ntests/test_web_log.py                      116    116      2      0     0%\ntests/test_web_middleware.py               266    266     12      0     0%\ntests/test_web_request.py                  490    490      8      0     0%\ntests/test_web_request_handler.py           40     40      0      0     0%\ntests/test_web_response.py                 817    817      4      0     0%\ntests/test_web_runner.py                   146    146      4      0     0%\ntests/test_web_sendfile.py                  76     76      0      0     0%\ntests/test_web_sendfile_functional.py      634    634     18      0     0%\ntests/test_web_server.py                   160    160      0      0     0%\ntests/test_web_urldispatcher.py            306    306     14      0     0%\ntests/test_web_websocket.py                304    304      4      0     0%\ntests/test_web_websocket_functional.py     542    542     16      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              68     68      0      0     0%\ntests/test_worker.py                       191    191      4      0     0%\n--------------------------------------------------------------------------\nTOTAL                                    31701  26517   4052    448    17%\n\n============================= slowest 10 durations =============================\n0.20s call     r2e_tests/test_1.py::test_close_cancel[pyloop]\n0.20s call     r2e_tests/test_1.py::test_close_timeout[pyloop]\n0.10s call     r2e_tests/test_1.py::test_recv_timeout[pyloop]\n0.10s call     r2e_tests/test_1.py::test_concurrent_task_close[pyloop]\n0.10s call     r2e_tests/test_1.py::test_heartbeat[pyloop]\n0.08s call     r2e_tests/test_1.py::test_heartbeat_no_pong[pyloop]\n0.05s call     r2e_tests/test_1.py::test_custom_receive_timeout[pyloop]\n0.05s call     r2e_tests/test_1.py::test_receive_timeout[pyloop]\n0.02s teardown r2e_tests/test_1.py::test_heartbeat[pyloop]\n0.02s teardown r2e_tests/test_1.py::test_custom_receive_timeout[pyloop]\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::test_send_recv_text[pyloop]\nPASSED r2e_tests/test_1.py::test_send_recv_bytes_bad_type[pyloop]\nPASSED r2e_tests/test_1.py::test_send_recv_bytes[pyloop]\nPASSED r2e_tests/test_1.py::test_send_recv_text_bad_type[pyloop]\nPASSED r2e_tests/test_1.py::test_send_recv_json[pyloop]\nPASSED r2e_tests/test_1.py::test_ping_pong[pyloop]\nPASSED r2e_tests/test_1.py::test_ping_pong_manual[pyloop]\nPASSED r2e_tests/test_1.py::test_close[pyloop]\nPASSED r2e_tests/test_1.py::test_concurrent_close[pyloop]\nPASSED r2e_tests/test_1.py::test_close_from_server[pyloop]\nPASSED r2e_tests/test_1.py::test_close_manual[pyloop]\nPASSED r2e_tests/test_1.py::test_close_timeout[pyloop]\nPASSED r2e_tests/test_1.py::test_close_cancel[pyloop]\nPASSED r2e_tests/test_1.py::test_override_default_headers[pyloop]\nPASSED r2e_tests/test_1.py::test_additional_headers[pyloop]\nPASSED r2e_tests/test_1.py::test_recv_protocol_error[pyloop]\nPASSED r2e_tests/test_1.py::test_recv_timeout[pyloop]\nPASSED r2e_tests/test_1.py::test_receive_timeout[pyloop]\nPASSED r2e_tests/test_1.py::test_custom_receive_timeout[pyloop]\nPASSED r2e_tests/test_1.py::test_heartbeat[pyloop]\nPASSED r2e_tests/test_1.py::test_heartbeat_no_pong[pyloop]\nPASSED r2e_tests/test_1.py::test_send_recv_compress[pyloop]\nPASSED r2e_tests/test_1.py::test_send_recv_compress_wbits[pyloop]\nPASSED r2e_tests/test_1.py::test_send_recv_compress_wbit_error[pyloop]\nPASSED r2e_tests/test_1.py::test_ws_client_async_for[pyloop]\nPASSED r2e_tests/test_1.py::test_ws_async_with[pyloop]\nPASSED r2e_tests/test_1.py::test_ws_async_with_send[pyloop]\nPASSED r2e_tests/test_1.py::test_ws_async_with_shortcut[pyloop]\nPASSED r2e_tests/test_1.py::test_closed_async_for[pyloop]\nPASSED r2e_tests/test_1.py::test_peer_connection_lost[pyloop]\nPASSED r2e_tests/test_1.py::test_peer_connection_lost_iter[pyloop]\nFAILED r2e_tests/test_1.py::test_concurrent_task_close[pyloop] - assert None ...\n========================= 1 failed, 31 passed in 4.60s =========================\n",
    "old_commit_res_stderr": ""
}
CHANGES/7306.bugfix aiohttp/client_ws.py tests/test_client_ws_functional.py
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]

**Title:** WebSocket `close_code` Remains `None` During Concurrent Connection Closure

**Description**
When attempting to close a WebSocket connection from one asyncio task while another task is waiting to receive data, the `close_code` is not correctly set and remains `None` after the connection is closed. This behavior prevents clients from accurately determining the reason for the connection closure.

**Example Code**
```python
async def test_concurrent_task_close(aiohttp_client) -> None:
    async def handler(request):
        ws = web.WebSocketResponse()
        await ws.prepare(request)
        await ws.receive()
        return ws

    app = web.Application()
    app.router.add_route("GET", "/", handler)

    client = await aiohttp_client(app)
    async with client.ws_connect("/") as resp:
        # Start a task that waits to receive a message
        task = asyncio.create_task(resp.receive())

        # Ensure the receive task is waiting
        await asyncio.sleep(0.1)

        # Close the WebSocket connection
        closed = await resp.close()

        await task

        print(resp.close_code)  # Expected: 1000, Actual: None
```

**Expected Behavior**
After closing the WebSocket connection, `resp.close_code` should be set to `1000`, indicating a normal closure of the connection.

**Actual Behavior**
The `resp.close_code` remains `None` after the connection is closed, making it unclear whether the closure was intentional or due to an error.

[/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/client_ws.py
"""WebSocket client for asyncio."""

import asyncio
import sys
from typing import Any, Optional, cast

from .client_exceptions import ClientError
from .client_reqrep import ClientResponse
from .helpers import call_later, set_result
from .http import (
    WS_CLOSED_MESSAGE,
    WS_CLOSING_MESSAGE,
    WebSocketError,
    WSCloseCode,
    WSMessage,
    WSMsgType,
)
from .http_websocket import WebSocketWriter  # WSMessage
from .streams import EofStream, FlowControlDataQueue
from .typedefs import (
    DEFAULT_JSON_DECODER,
    DEFAULT_JSON_ENCODER,
    JSONDecoder,
    JSONEncoder,
)

if sys.version_info >= (3, 11):
    import asyncio as async_timeout
else:
    import async_timeout


class ClientWebSocketResponse:
    def __init__(
        self,
        reader: "FlowControlDataQueue[WSMessage]",
        writer: WebSocketWriter,
        protocol: Optional[str],
        response: ClientResponse,
        timeout: float,
        autoclose: bool,
        autoping: bool,
        loop: asyncio.AbstractEventLoop,
        *,
        receive_timeout: Optional[float] = None,
        heartbeat: Optional[float] = None,
        compress: int = 0,
        client_notakeover: bool = False,
    ) -> None:
        self._response = response
        self._conn = response.connection

        self._writer = writer
        self._reader = reader
        self._protocol = protocol
        self._closed = False
        self._closing = False
        self._close_code: Optional[int] = None
        self._timeout = timeout
        self._receive_timeout = receive_timeout
        self._autoclose = autoclose
        self._autoping = autoping
        self._heartbeat = heartbeat
        self._heartbeat_cb: Optional[asyncio.TimerHandle] = None
        if heartbeat is not None:
            self._pong_heartbeat = heartbeat / 2.0
        self._pong_response_cb: Optional[asyncio.TimerHandle] = None
        self._loop = loop
        self._waiting: Optional[asyncio.Future[bool]] = None
        self._exception: Optional[BaseException] = None
        self._compress = compress
        self._client_notakeover = client_notakeover

        self._reset_heartbeat()

    def _cancel_heartbeat(self) -> None:
        if self._pong_response_cb is not None:
            self._pong_response_cb.cancel()
            self._pong_response_cb = None

        if self._heartbeat_cb is not None:
            self._heartbeat_cb.cancel()
            self._heartbeat_cb = None

    def _reset_heartbeat(self) -> None:
        self._cancel_heartbeat()

        if self._heartbeat is not None:
            self._heartbeat_cb = call_later(
                self._send_heartbeat,
                self._heartbeat,
                self._loop,
                timeout_ceil_threshold=self._conn._connector._timeout_ceil_threshold
                if self._conn is not None
                else 5,
            )

    def _send_heartbeat(self) -> None:
        if self._heartbeat is not None and not self._closed:
            # fire-and-forget a task is not perfect but maybe ok for
            # sending ping. Otherwise we need a long-living heartbeat
            # task in the class.
            self._loop.create_task(self._writer.ping())

            if self._pong_response_cb is not None:
                self._pong_response_cb.cancel()
            self._pong_response_cb = call_later(
                self._pong_not_received,
                self._pong_heartbeat,
                self._loop,
                timeout_ceil_threshold=self._conn._connector._timeout_ceil_threshold
                if self._conn is not None
                else 5,
            )

    def _pong_not_received(self) -> None:
        if not self._closed:
            self._closed = True
            self._close_code = WSCloseCode.ABNORMAL_CLOSURE
            self._exception = asyncio.TimeoutError()
            self._response.close()

    @property
    def closed(self) -> bool:
        return self._closed

    @property
    def close_code(self) -> Optional[int]:
        return self._close_code

    @property
    def protocol(self) -> Optional[str]:
        return self._protocol

    @property
    def compress(self) -> int:
        return self._compress

    @property
    def client_notakeover(self) -> bool:
        return self._client_notakeover

    def get_extra_info(self, name: str, default: Any = None) -> Any:
        """extra info from connection transport"""
        conn = self._response.connection
        if conn is None:
            return default
        transport = conn.transport
        if transport is None:
            return default
        return transport.get_extra_info(name, default)

    def exception(self) -> Optional[BaseException]:
        return self._exception

    async def ping(self, message: bytes = b"") -> None:
        await self._writer.ping(message)

    async def pong(self, message: bytes = b"") -> None:
        await self._writer.pong(message)

    async def send_str(self, data: str, compress: Optional[int] = None) -> None:
        if not isinstance(data, str):
            raise TypeError("data argument must be str (%r)" % type(data))
        await self._writer.send(data, binary=False, compress=compress)

    async def send_bytes(self, data: bytes, compress: Optional[int] = None) -> None:
        if not isinstance(data, (bytes, bytearray, memoryview)):
            raise TypeError("data argument must be byte-ish (%r)" % type(data))
        await self._writer.send(data, binary=True, compress=compress)

    async def send_json(
        self,
        data: Any,
        compress: Optional[int] = None,
        *,
        dumps: JSONEncoder = DEFAULT_JSON_ENCODER,
    ) -> None:
        await self.send_str(dumps(data), compress=compress)

    async def close(self, *, code: int = WSCloseCode.OK, message: bytes = b"") -> bool:
        # we need to break `receive()` cycle first,
        # `close()` may be called from different task
        if self._waiting is not None and not self._closed:
            self._reader.feed_data(WS_CLOSING_MESSAGE, 0)
            await self._waiting

        if not self._closed:
            self._cancel_heartbeat()
            self._closed = True
            try:
                await self._writer.close(code, message)
            except asyncio.CancelledError:
                self._close_code = WSCloseCode.ABNORMAL_CLOSURE
                self._response.close()
                raise
            except Exception as exc:
                self._close_code = WSCloseCode.ABNORMAL_CLOSURE
                self._exception = exc
                self._response.close()
                return True

            if self._closing:
                self._response.close()
                return True

            while True:
                try:
                    async with async_timeout.timeout(self._timeout):
                        msg = await self._reader.read()
                except asyncio.CancelledError:
                    self._close_code = WSCloseCode.ABNORMAL_CLOSURE
                    self._response.close()
                    raise
                except Exception as exc:
                    self._close_code = WSCloseCode.ABNORMAL_CLOSURE
                    self._exception = exc
                    self._response.close()
                    return True

                if msg.type == WSMsgType.CLOSE:
                    self._close_code = msg.data
                    self._response.close()
                    return True
        else:
            return False

    async def receive(self, timeout: Optional[float] = None) -> WSMessage:
        while True:
            if self._waiting is not None:
                raise RuntimeError("Concurrent call to receive() is not allowed")

            if self._closed:
                return WS_CLOSED_MESSAGE
            elif self._closing:
                await self.close()
                return WS_CLOSED_MESSAGE

            try:
                self._waiting = self._loop.create_future()
                try:
                    async with async_timeout.timeout(timeout or self._receive_timeout):
                        msg = await self._reader.read()
                    self._reset_heartbeat()
                finally:
                    waiter = self._waiting
                    self._waiting = None
                    set_result(waiter, True)
            except (asyncio.CancelledError, asyncio.TimeoutError):
                self._close_code = WSCloseCode.ABNORMAL_CLOSURE
                raise
            except EofStream:
                self._close_code = WSCloseCode.OK
                await self.close()
                return WSMessage(WSMsgType.CLOSED, None, None)
            except ClientError:
                self._closed = True
                self._close_code = WSCloseCode.ABNORMAL_CLOSURE
                return WS_CLOSED_MESSAGE
            except WebSocketError as exc:
                self._close_code = exc.code
                await self.close(code=exc.code)
                return WSMessage(WSMsgType.ERROR, exc, None)
            except Exception as exc:
                self._exception = exc
                self._closing = True
                self._close_code = WSCloseCode.ABNORMAL_CLOSURE
                await self.close()
                return WSMessage(WSMsgType.ERROR, exc, None)

            if msg.type == WSMsgType.CLOSE:
                self._closing = True
                self._close_code = msg.data
                if not self._closed and self._autoclose:
                    await self.close()
            elif msg.type == WSMsgType.CLOSING:
                self._closing = True
            elif msg.type == WSMsgType.PING and self._autoping:
                await self.pong(msg.data)
                continue
            elif msg.type == WSMsgType.PONG and self._autoping:
                continue

            return msg

    async def receive_str(self, *, timeout: Optional[float] = None) -> str:
        msg = await self.receive(timeout)
        if msg.type != WSMsgType.TEXT:
            raise TypeError(f"Received message {msg.type}:{msg.data!r} is not str")
        return cast(str, msg.data)

    async def receive_bytes(self, *, timeout: Optional[float] = None) -> bytes:
        msg = await self.receive(timeout)
        if msg.type != WSMsgType.BINARY:
            raise TypeError(f"Received message {msg.type}:{msg.data!r} is not bytes")
        return cast(bytes, msg.data)

    async def receive_json(
        self,
        *,
        loads: JSONDecoder = DEFAULT_JSON_DECODER,
        timeout: Optional[float] = None,
    ) -> Any:
        data = await self.receive_str(timeout=timeout)
        return loads(data)

    def __aiter__(self) -> "ClientWebSocketResponse":
        return self

    async def __anext__(self) -> WSMessage:
        msg = await self.receive()
        if msg.type in (WSMsgType.CLOSE, WSMsgType.CLOSING, WSMsgType.CLOSED):
            raise StopAsyncIteration
        return msg

```
--- 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:** WebSocket `close_code` Remains `None` During Concurrent Connection Closure

**Description**
When attempting to close a WebSocket connection from one asyncio task while another task is waiting to receive data, the `close_code` is not correctly set and remains `None` after the connection is closed. This behavior prevents clients from accurately determining the reason for the connection closure.

**Example Code**
```python
async def test_concurrent_task_close(aiohttp_client) -> None:
    async def handler(request):
        ws = web.WebSocketResponse()
        await ws.prepare(request)
        await ws.receive()
        return ws

    app = web.Application()
    app.router.add_route("GET", "/", handler)

    client = await aiohttp_client(app)
    async with client.ws_connect("/") as resp:
        # Start a task that waits to receive a message
        task = asyncio.create_task(resp.receive())

        # Ensure the receive task is waiting
        await asyncio.sleep(0.1)

        # Close the WebSocket connection
        closed = await resp.close()

        await task

        print(resp.close_code)  # Expected: 1000, Actual: None
```

**Expected Behavior**
After closing the WebSocket connection, `resp.close_code` should be set to `1000`, indicating a normal closure of the connection.

**Actual Behavior**
The `resp.close_code` remains `None` after the connection is closed, making it unclear whether the closure was intentional or due to an error.

[/ISSUE]
{
    "test_send_recv_text[pyloop]": "PASSED",
    "test_send_recv_bytes_bad_type[pyloop]": "PASSED",
    "test_send_recv_bytes[pyloop]": "PASSED",
    "test_send_recv_text_bad_type[pyloop]": "PASSED",
    "test_send_recv_json[pyloop]": "PASSED",
    "test_ping_pong[pyloop]": "PASSED",
    "test_ping_pong_manual[pyloop]": "PASSED",
    "test_close[pyloop]": "PASSED",
    "test_concurrent_close[pyloop]": "PASSED",
    "test_concurrent_task_close[pyloop]": "PASSED",
    "test_close_from_server[pyloop]": "PASSED",
    "test_close_manual[pyloop]": "PASSED",
    "test_close_timeout[pyloop]": "PASSED",
    "test_close_cancel[pyloop]": "PASSED",
    "test_override_default_headers[pyloop]": "PASSED",
    "test_additional_headers[pyloop]": "PASSED",
    "test_recv_protocol_error[pyloop]": "PASSED",
    "test_recv_timeout[pyloop]": "PASSED",
    "test_receive_timeout[pyloop]": "PASSED",
    "test_custom_receive_timeout[pyloop]": "PASSED",
    "test_heartbeat[pyloop]": "PASSED",
    "test_heartbeat_no_pong[pyloop]": "PASSED",
    "test_send_recv_compress[pyloop]": "PASSED",
    "test_send_recv_compress_wbits[pyloop]": "PASSED",
    "test_send_recv_compress_wbit_error[pyloop]": "PASSED",
    "test_ws_client_async_for[pyloop]": "PASSED",
    "test_ws_async_with[pyloop]": "PASSED",
    "test_ws_async_with_send[pyloop]": "PASSED",
    "test_ws_async_with_shortcut[pyloop]": "PASSED",
    "test_closed_async_for[pyloop]": "PASSED",
    "test_peer_connection_lost[pyloop]": "PASSED",
    "test_peer_connection_lost_iter[pyloop]": "PASSED"
}
diff --git a/aiohttp/client_ws.py b/aiohttp/client_ws.py
index b6dbcca7..d9c74a30 100644
--- a/aiohttp/client_ws.py
+++ b/aiohttp/client_ws.py
@@ -181,7 +181,8 @@ class ClientWebSocketResponse:
     async def close(self, *, code: int = WSCloseCode.OK, message: bytes = b"") -> bool:
         # we need to break `receive()` cycle first,
         # `close()` may be called from different task
-        if self._waiting is not None and not self._closed:
+        if self._waiting is not None and not self._closing:
+            self._closing = True
             self._reader.feed_data(WS_CLOSING_MESSAGE, 0)
             await self._waiting
 
@@ -200,7 +201,7 @@ class ClientWebSocketResponse:
                 self._response.close()
                 return True
 
-            if self._closing:
+            if self._close_code:
                 self._response.close()
                 return True
 

{"aiohttp/client_ws.py": "\"\"\"WebSocket client for asyncio.\"\"\"\n\nimport asyncio\nimport sys\nfrom typing import Any, Optional, cast\n\nfrom .client_exceptions import ClientError\nfrom .client_reqrep import ClientResponse\nfrom .helpers import call_later, set_result\nfrom .http import (\n    WS_CLOSED_MESSAGE,\n    WS_CLOSING_MESSAGE,\n    WebSocketError,\n    WSCloseCode,\n    WSMessage,\n    WSMsgType,\n)\nfrom .http_websocket import WebSocketWriter  # WSMessage\nfrom .streams import EofStream, FlowControlDataQueue\nfrom .typedefs import (\n    DEFAULT_JSON_DECODER,\n    DEFAULT_JSON_ENCODER,\n    JSONDecoder,\n    JSONEncoder,\n)\n\nif sys.version_info >= (3, 11):\n    import asyncio as async_timeout\nelse:\n    import async_timeout\n\n\nclass ClientWebSocketResponse:\n    def __init__(\n        self,\n        reader: \"FlowControlDataQueue[WSMessage]\",\n        writer: WebSocketWriter,\n        protocol: Optional[str],\n        response: ClientResponse,\n        timeout: float,\n        autoclose: bool,\n        autoping: bool,\n        loop: asyncio.AbstractEventLoop,\n        *,\n        receive_timeout: Optional[float] = None,\n        heartbeat: Optional[float] = None,\n        compress: int = 0,\n        client_notakeover: bool = False,\n    ) -> None:\n        self._response = response\n        self._conn = response.connection\n\n        self._writer = writer\n        self._reader = reader\n        self._protocol = protocol\n        self._closed = False\n        self._closing = False\n        self._close_code: Optional[int] = None\n        self._timeout = timeout\n        self._receive_timeout = receive_timeout\n        self._autoclose = autoclose\n        self._autoping = autoping\n        self._heartbeat = heartbeat\n        self._heartbeat_cb: Optional[asyncio.TimerHandle] = None\n        if heartbeat is not None:\n            self._pong_heartbeat = heartbeat / 2.0\n        self._pong_response_cb: Optional[asyncio.TimerHandle] = None\n        self._loop = loop\n        self._waiting: Optional[asyncio.Future[bool]] = None\n        self._exception: Optional[BaseException] = None\n        self._compress = compress\n        self._client_notakeover = client_notakeover\n\n        self._reset_heartbeat()\n\n    def _cancel_heartbeat(self) -> None:\n        if self._pong_response_cb is not None:\n            self._pong_response_cb.cancel()\n            self._pong_response_cb = None\n\n        if self._heartbeat_cb is not None:\n            self._heartbeat_cb.cancel()\n            self._heartbeat_cb = None\n\n    def _reset_heartbeat(self) -> None:\n        self._cancel_heartbeat()\n\n        if self._heartbeat is not None:\n            self._heartbeat_cb = call_later(\n                self._send_heartbeat,\n                self._heartbeat,\n                self._loop,\n                timeout_ceil_threshold=self._conn._connector._timeout_ceil_threshold\n                if self._conn is not None\n                else 5,\n            )\n\n    def _send_heartbeat(self) -> None:\n        if self._heartbeat is not None and not self._closed:\n            # fire-and-forget a task is not perfect but maybe ok for\n            # sending ping. Otherwise we need a long-living heartbeat\n            # task in the class.\n            self._loop.create_task(self._writer.ping())\n\n            if self._pong_response_cb is not None:\n                self._pong_response_cb.cancel()\n            self._pong_response_cb = call_later(\n                self._pong_not_received,\n                self._pong_heartbeat,\n                self._loop,\n                timeout_ceil_threshold=self._conn._connector._timeout_ceil_threshold\n                if self._conn is not None\n                else 5,\n            )\n\n    def _pong_not_received(self) -> None:\n        if not self._closed:\n            self._closed = True\n            self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n            self._exception = asyncio.TimeoutError()\n            self._response.close()\n\n    @property\n    def closed(self) -> bool:\n        return self._closed\n\n    @property\n    def close_code(self) -> Optional[int]:\n        return self._close_code\n\n    @property\n    def protocol(self) -> Optional[str]:\n        return self._protocol\n\n    @property\n    def compress(self) -> int:\n        return self._compress\n\n    @property\n    def client_notakeover(self) -> bool:\n        return self._client_notakeover\n\n    def get_extra_info(self, name: str, default: Any = None) -> Any:\n        \"\"\"extra info from connection transport\"\"\"\n        conn = self._response.connection\n        if conn is None:\n            return default\n        transport = conn.transport\n        if transport is None:\n            return default\n        return transport.get_extra_info(name, default)\n\n    def exception(self) -> Optional[BaseException]:\n        return self._exception\n\n    async def ping(self, message: bytes = b\"\") -> None:\n        await self._writer.ping(message)\n\n    async def pong(self, message: bytes = b\"\") -> None:\n        await self._writer.pong(message)\n\n    async def send_str(self, data: str, compress: Optional[int] = None) -> None:\n        if not isinstance(data, str):\n            raise TypeError(\"data argument must be str (%r)\" % type(data))\n        await self._writer.send(data, binary=False, compress=compress)\n\n    async def send_bytes(self, data: bytes, compress: Optional[int] = None) -> None:\n        if not isinstance(data, (bytes, bytearray, memoryview)):\n            raise TypeError(\"data argument must be byte-ish (%r)\" % type(data))\n        await self._writer.send(data, binary=True, compress=compress)\n\n    async def send_json(\n        self,\n        data: Any,\n        compress: Optional[int] = None,\n        *,\n        dumps: JSONEncoder = DEFAULT_JSON_ENCODER,\n    ) -> None:\n        await self.send_str(dumps(data), compress=compress)\n\n    async def close(self, *, code: int = WSCloseCode.OK, message: bytes = b\"\") -> bool:\n        # we need to break `receive()` cycle first,\n        # `close()` may be called from different task\n        if self._waiting is not None and not self._closed:\n            self._reader.feed_data(WS_CLOSING_MESSAGE, 0)\n            await self._waiting\n\n        if not self._closed:\n            self._cancel_heartbeat()\n            self._closed = True\n            try:\n                await self._writer.close(code, message)\n            except asyncio.CancelledError:\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                self._response.close()\n                raise\n            except Exception as exc:\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                self._exception = exc\n                self._response.close()\n                return True\n\n            if self._closing:\n                self._response.close()\n                return True\n\n            while True:\n                try:\n                    async with async_timeout.timeout(self._timeout):\n                        msg = await self._reader.read()\n                except asyncio.CancelledError:\n                    self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                    self._response.close()\n                    raise\n                except Exception as exc:\n                    self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                    self._exception = exc\n                    self._response.close()\n                    return True\n\n                if msg.type == WSMsgType.CLOSE:\n                    self._close_code = msg.data\n                    self._response.close()\n                    return True\n        else:\n            return False\n\n    async def receive(self, timeout: Optional[float] = None) -> WSMessage:\n        while True:\n            if self._waiting is not None:\n                raise RuntimeError(\"Concurrent call to receive() is not allowed\")\n\n            if self._closed:\n                return WS_CLOSED_MESSAGE\n            elif self._closing:\n                await self.close()\n                return WS_CLOSED_MESSAGE\n\n            try:\n                self._waiting = self._loop.create_future()\n                try:\n                    async with async_timeout.timeout(timeout or self._receive_timeout):\n                        msg = await self._reader.read()\n                    self._reset_heartbeat()\n                finally:\n                    waiter = self._waiting\n                    self._waiting = None\n                    set_result(waiter, True)\n            except (asyncio.CancelledError, asyncio.TimeoutError):\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                raise\n            except EofStream:\n                self._close_code = WSCloseCode.OK\n                await self.close()\n                return WSMessage(WSMsgType.CLOSED, None, None)\n            except ClientError:\n                self._closed = True\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                return WS_CLOSED_MESSAGE\n            except WebSocketError as exc:\n                self._close_code = exc.code\n                await self.close(code=exc.code)\n                return WSMessage(WSMsgType.ERROR, exc, None)\n            except Exception as exc:\n                self._exception = exc\n                self._closing = True\n                self._close_code = WSCloseCode.ABNORMAL_CLOSURE\n                await self.close()\n                return WSMessage(WSMsgType.ERROR, exc, None)\n\n            if msg.type == WSMsgType.CLOSE:\n                self._closing = True\n                self._close_code = msg.data\n                if not self._closed and self._autoclose:\n                    await self.close()\n            elif msg.type == WSMsgType.CLOSING:\n                self._closing = True\n            elif msg.type == WSMsgType.PING and self._autoping:\n                await self.pong(msg.data)\n                continue\n            elif msg.type == WSMsgType.PONG and self._autoping:\n                continue\n\n            return msg\n\n    async def receive_str(self, *, timeout: Optional[float] = None) -> str:\n        msg = await self.receive(timeout)\n        if msg.type != WSMsgType.TEXT:\n            raise TypeError(f\"Received message {msg.type}:{msg.data!r} is not str\")\n        return cast(str, msg.data)\n\n    async def receive_bytes(self, *, timeout: Optional[float] = None) -> bytes:\n        msg = await self.receive(timeout)\n        if msg.type != WSMsgType.BINARY:\n            raise TypeError(f\"Received message {msg.type}:{msg.data!r} is not bytes\")\n        return cast(bytes, msg.data)\n\n    async def receive_json(\n        self,\n        *,\n        loads: JSONDecoder = DEFAULT_JSON_DECODER,\n        timeout: Optional[float] = None,\n    ) -> Any:\n        data = await self.receive_str(timeout=timeout)\n        return loads(data)\n\n    def __aiter__(self) -> \"ClientWebSocketResponse\":\n        return self\n\n    async def __anext__(self) -> WSMessage:\n        msg = await self.receive()\n        if msg.type in (WSMsgType.CLOSE, WSMsgType.CLOSING, WSMsgType.CLOSED):\n            raise StopAsyncIteration\n        return msg\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:** WebSocket `close_code` Remains `None` During Concurrent Connection Closure

**Description**
When attempting to close a WebSocket connection from one asyncio task while another task is waiting to receive data, the `close_code` is not correctly set and remains `None` after the connection is closed. This behavior prevents clients from accurately determining the reason for the connection closure.

**Example Code**
```python
async def test_concurrent_task_close(aiohttp_client) -> None:
    async def handler(request):
        ws = web.WebSocketResponse()
        await ws.prepare(request)
        await ws.receive()
        return ws

    app = web.Application()
    app.router.add_route("GET", "/", handler)

    client = await aiohttp_client(app)
    async with client.ws_connect("/") as resp:
        # Start a task that waits to receive a message
        task = asyncio.create_task(resp.receive())

        # Ensure the receive task is waiting
        await asyncio.sleep(0.1)

        # Close the WebSocket connection
        closed = await resp.close()

        await task

        print(resp.close_code)  # Expected: 1000, Actual: None
```

**Expected Behavior**
After closing the WebSocket connection, `resp.close_code` should be set to `1000`, indicating a normal closure of the connection.

**Actual Behavior**
The `resp.close_code` remains `None` after the connection is closed, making it unclear whether the closure was intentional or due to an error.

[/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/client_ws.py
"""WebSocket client for asyncio."""

import asyncio
import sys
from typing import Any, Optional, cast

from .client_exceptions import ClientError
from .client_reqrep import ClientResponse
from .helpers import call_later, set_result
from .http import (
    WS_CLOSED_MESSAGE,
    WS_CLOSING_MESSAGE,
    WebSocketError,
    WSCloseCode,
    WSMessage,
    WSMsgType,
)
from .http_websocket import WebSocketWriter  # WSMessage
from .streams import EofStream, FlowControlDataQueue
from .typedefs import (
    DEFAULT_JSON_DECODER,
    DEFAULT_JSON_ENCODER,
    JSONDecoder,
    JSONEncoder,
)

if sys.version_info >= (3, 11):
    import asyncio as async_timeout
else:
    import async_timeout


class ClientWebSocketResponse:
    def __init__(
        self,
        reader: "FlowControlDataQueue[WSMessage]",
        writer: WebSocketWriter,
        protocol: Optional[str],
        response: ClientResponse,
        timeout: float,
        autoclose: bool,
        autoping: bool,
        loop: asyncio.AbstractEventLoop,
        *,
        receive_timeout: Optional[float] = None,
        heartbeat: Optional[float] = None,
        compress: int = 0,
        client_notakeover: bool = False,
    ) -> None:
        self._response = response
        self._conn = response.connection

        self._writer = writer
        self._reader = reader
        self._protocol = protocol
        self._closed = False
        self._closing = False
        self._close_code: Optional[int] = None
        self._timeout = timeout
        self._receive_timeout = receive_timeout
        self._autoclose = autoclose
        self._autoping = autoping
        self._heartbeat = heartbeat
        self._heartbeat_cb: Optional[asyncio.TimerHandle] = None
        if heartbeat is not None:
            self._pong_heartbeat = heartbeat / 2.0
        self._pong_response_cb: Optional[asyncio.TimerHandle] = None
        self._loop = loop
        self._waiting: Optional[asyncio.Future[bool]] = None
        self._exception: Optional[BaseException] = None
        self._compress = compress
        self._client_notakeover = client_notakeover

        self._reset_heartbeat()

    def _cancel_heartbeat(self) -> None:
        if self._pong_response_cb is not None:
            self._pong_response_cb.cancel()
            self._pong_response_cb = None

        if self._heartbeat_cb is not None:
            self._heartbeat_cb.cancel()
            self._heartbeat_cb = None

    def _reset_heartbeat(self) -> None:
        self._cancel_heartbeat()

        if self._heartbeat is not None:
            self._heartbeat_cb = call_later(
                self._send_heartbeat,
                self._heartbeat,
                self._loop,
                timeout_ceil_threshold=self._conn._connector._timeout_ceil_threshold
                if self._conn is not None
                else 5,
            )

    def _send_heartbeat(self) -> None:
        if self._heartbeat is not None and not self._closed:
            # fire-and-forget a task is not perfect but maybe ok for
            # sending ping. Otherwise we need a long-living heartbeat
            # task in the class.
            self._loop.create_task(self._writer.ping())

            if self._pong_response_cb is not None:
                self._pong_response_cb.cancel()
            self._pong_response_cb = call_later(
                self._pong_not_received,
                self._pong_heartbeat,
                self._loop,
                timeout_ceil_threshold=self._conn._connector._timeout_ceil_threshold
                if self._conn is not None
                else 5,
            )

    def _pong_not_received(self) -> None:
        if not self._closed:
            self._closed = True
            self._close_code = WSCloseCode.ABNORMAL_CLOSURE
            self._exception = asyncio.TimeoutError()
            self._response.close()

    @property
    def closed(self) -> bool:
        return self._closed

    @property
    def close_code(self) -> Optional[int]:
        return self._close_code

    @property
    def protocol(self) -> Optional[str]:
        return self._protocol

    @property
    def compress(self) -> int:
        return self._compress

    @property
    def client_notakeover(self) -> bool:
        return self._client_notakeover

    def get_extra_info(self, name: str, default: Any = None) -> Any:
        """extra info from connection transport"""
        conn = self._response.connection
        if conn is None:
            return default
        transport = conn.transport
        if transport is None:
            return default
        return transport.get_extra_info(name, default)

    def exception(self) -> Optional[BaseException]:
        return self._exception

    async def ping(self, message: bytes = b"") -> None:
        await self._writer.ping(message)

    async def pong(self, message: bytes = b"") -> None:
        await self._writer.pong(message)

    async def send_str(self, data: str, compress: Optional[int] = None) -> None:
        if not isinstance(data, str):
            raise TypeError("data argument must be str (%r)" % type(data))
        await self._writer.send(data, binary=False, compress=compress)

    async def send_bytes(self, data: bytes, compress: Optional[int] = None) -> None:
        if not isinstance(data, (bytes, bytearray, memoryview)):
            raise TypeError("data argument must be byte-ish (%r)" % type(data))
        await self._writer.send(data, binary=True, compress=compress)

    async def send_json(
        self,
        data: Any,
        compress: Optional[int] = None,
        *,
        dumps: JSONEncoder = DEFAULT_JSON_ENCODER,
    ) -> None:
        await self.send_str(dumps(data), compress=compress)

    async def close(self, *, code: int = WSCloseCode.OK, message: bytes = b"") -> bool:
        # we need to break `receive()` cycle first,
        # `close()` may be called from different task
        if self._waiting is not None and not self._closed:
            self._reader.feed_data(WS_CLOSING_MESSAGE, 0)
            await self._waiting

        if not self._closed:
            self._cancel_heartbeat()
            self._closed = True
            try:
                await self._writer.close(code, message)
            except asyncio.CancelledError:
                self._close_code = WSCloseCode.ABNORMAL_CLOSURE
                self._response.close()
                raise
            except Exception as exc:
                self._close_code = WSCloseCode.ABNORMAL_CLOSURE
                self._exception = exc
                self._response.close()
                return True

            if self._closing:
                self._response.close()
                return True

            while True:
                try:
                    async with async_timeout.timeout(self._timeout):
                        msg = await self._reader.read()
                except asyncio.CancelledError:
                    self._close_code = WSCloseCode.ABNORMAL_CLOSURE
                    self._response.close()
                    raise
                except Exception as exc:
                    self._close_code = WSCloseCode.ABNORMAL_CLOSURE
                    self._exception = exc
                    self._response.close()
                    return True

                if msg.type == WSMsgType.CLOSE:
                    self._close_code = msg.data
                    self._response.close()
                    return True
        else:
            return False

    async def receive(self, timeout: Optional[float] = None) -> WSMessage:
        while True:
            if self._waiting is not None:
                raise RuntimeError("Concurrent call to receive() is not allowed")

            if self._closed:
                return WS_CLOSED_MESSAGE
            elif self._closing:
                await self.close()
                return WS_CLOSED_MESSAGE

            try:
                self._waiting = self._loop.create_future()
                try:
                    async with async_timeout.timeout(timeout or self._receive_timeout):
                        msg = await self._reader.read()
                    self._reset_heartbeat()
                finally:
                    waiter = self._waiting
                    self._waiting = None
                    set_result(waiter, True)
            except (asyncio.CancelledError, asyncio.TimeoutError):
                self._close_code = WSCloseCode.ABNORMAL_CLOSURE
                raise
            except EofStream:
                self._close_code = WSCloseCode.OK
                await self.close()
                return WSMessage(WSMsgType.CLOSED, None, None)
            except ClientError:
                self._closed = True
                self._close_code = WSCloseCode.ABNORMAL_CLOSURE
                return WS_CLOSED_MESSAGE
            except WebSocketError as exc:
                self._close_code = exc.code
                await self.close(code=exc.code)
                return WSMessage(WSMsgType.ERROR, exc, None)
            except Exception as exc:
                self._exception = exc
                self._closing = True
                self._close_code = WSCloseCode.ABNORMAL_CLOSURE
                await self.close()
                return WSMessage(WSMsgType.ERROR, exc, None)

            if msg.type == WSMsgType.CLOSE:
                self._closing = True
                self._close_code = msg.data
                if not self._closed and self._autoclose:
                    await self.close()
            elif msg.type == WSMsgType.CLOSING:
                self._closing = True
            elif msg.type == WSMsgType.PING and self._autoping:
                await self.pong(msg.data)
                continue
            elif msg.type == WSMsgType.PONG and self._autoping:
                continue

            return msg

    async def receive_str(self, *, timeout: Optional[float] = None) -> str:
        msg = await self.receive(timeout)
        if msg.type != WSMsgType.TEXT:
            raise TypeError(f"Received message {msg.type}:{msg.data!r} is not str")
        return cast(str, msg.data)

    async def receive_bytes(self, *, timeout: Optional[float] = None) -> bytes:
        msg = await self.receive(timeout)
        if msg.type != WSMsgType.BINARY:
            raise TypeError(f"Received message {msg.type}:{msg.data!r} is not bytes")
        return cast(bytes, msg.data)

    async def receive_json(
        self,
        *,
        loads: JSONDecoder = DEFAULT_JSON_DECODER,
        timeout: Optional[float] = None,
    ) -> Any:
        data = await self.receive_str(timeout=timeout)
        return loads(data)

    def __aiter__(self) -> "ClientWebSocketResponse":
        return self

    async def __anext__(self) -> WSMessage:
        msg = await self.receive()
        if msg.type in (WSMsgType.CLOSE, WSMsgType.CLOSING, WSMsgType.CLOSED):
            raise StopAsyncIteration
        return msg

```
--- 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