{
    "file_diffs": [
        {
            "old_file_content": "",
            "new_file_content": "Fixed client incorrectly reusing a connection when the previous message had not been fully sent -- by :user:`Dreamsorcerer`.\n",
            "header": {
                "file": {
                    "path": "CHANGES/8992.bugfix.rst"
                },
                "misc_line": "new file mode 100644"
            },
            "index_line": {
                "old_commit_hash": "00000000",
                "new_commit_hash": "bc41d5fe",
                "mode": ""
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "/dev/null"
            },
            "plus_file": {
                "path": "b/CHANGES/8992.bugfix.rst"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 0,
                            "length": 0
                        },
                        "new_range": {
                            "start": 1,
                            "length": null
                        },
                        "section": ""
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "Fixed client incorrectly reusing a connection when the previous message had not been fully sent -- by :user:`Dreamsorcerer`.",
                                "type": "added"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "import asyncio\nimport codecs\nimport contextlib\nimport functools\nimport io\nimport re\nimport sys\nimport traceback\nimport warnings\nfrom hashlib import md5, sha1, sha256\nfrom http.cookies import CookieError, Morsel, SimpleCookie\nfrom types import MappingProxyType, TracebackType\nfrom typing import (\n    TYPE_CHECKING,\n    Any,\n    Callable,\n    Dict,\n    Iterable,\n    List,\n    Mapping,\n    Optional,\n    Tuple,\n    Type,\n    Union,\n    cast,\n)\n\nimport attr\nfrom multidict import CIMultiDict, CIMultiDictProxy, MultiDict, MultiDictProxy\nfrom yarl import URL\n\nfrom . import hdrs, helpers, http, multipart, payload\nfrom .abc import AbstractStreamWriter\nfrom .client_exceptions import (\n    ClientConnectionError,\n    ClientOSError,\n    ClientResponseError,\n    ContentTypeError,\n    InvalidURL,\n    ServerFingerprintMismatch,\n)\nfrom .compression_utils import HAS_BROTLI\nfrom .formdata import FormData\nfrom .helpers import (\n    BaseTimerContext,\n    BasicAuth,\n    HeadersMixin,\n    TimerNoop,\n    basicauth_from_netrc,\n    netrc_from_env,\n    noop,\n    reify,\n    set_exception,\n    set_result,\n)\nfrom .http import (\n    SERVER_SOFTWARE,\n    HttpVersion,\n    HttpVersion10,\n    HttpVersion11,\n    StreamWriter,\n)\nfrom .log import client_logger\nfrom .streams import StreamReader\nfrom .typedefs import (\n    DEFAULT_JSON_DECODER,\n    JSONDecoder,\n    LooseCookies,\n    LooseHeaders,\n    RawHeaders,\n)\n\ntry:\n    import ssl\n    from ssl import SSLContext\nexcept ImportError:  # pragma: no cover\n    ssl = None  # type: ignore[assignment]\n    SSLContext = object  # type: ignore[misc,assignment]\n\n\n__all__ = (\"ClientRequest\", \"ClientResponse\", \"RequestInfo\", \"Fingerprint\")\n\n\nif TYPE_CHECKING:\n    from .client import ClientSession\n    from .connector import Connection\n    from .tracing import Trace\n\n\n_CONTAINS_CONTROL_CHAR_RE = re.compile(r\"[^-!#$%&'*+.^_`|~0-9a-zA-Z]\")\njson_re = re.compile(r\"^application/(?:[\\w.+-]+?\\+)?json\")\n\n\ndef _gen_default_accept_encoding() -> str:\n    return \"gzip, deflate, br\" if HAS_BROTLI else \"gzip, deflate\"\n\n\n@attr.s(auto_attribs=True, frozen=True, slots=True)\nclass ContentDisposition:\n    type: Optional[str]\n    parameters: \"MappingProxyType[str, str]\"\n    filename: Optional[str]\n\n\n@attr.s(auto_attribs=True, frozen=True, slots=True)\nclass RequestInfo:\n    url: URL\n    method: str\n    headers: \"CIMultiDictProxy[str]\"\n    real_url: URL = attr.ib()\n\n    @real_url.default\n    def real_url_default(self) -> URL:\n        return self.url\n\n\nclass Fingerprint:\n    HASHFUNC_BY_DIGESTLEN = {\n        16: md5,\n        20: sha1,\n        32: sha256,\n    }\n\n    def __init__(self, fingerprint: bytes) -> None:\n        digestlen = len(fingerprint)\n        hashfunc = self.HASHFUNC_BY_DIGESTLEN.get(digestlen)\n        if not hashfunc:\n            raise ValueError(\"fingerprint has invalid length\")\n        elif hashfunc is md5 or hashfunc is sha1:\n            raise ValueError(\n                \"md5 and sha1 are insecure and \" \"not supported. Use sha256.\"\n            )\n        self._hashfunc = hashfunc\n        self._fingerprint = fingerprint\n\n    @property\n    def fingerprint(self) -> bytes:\n        return self._fingerprint\n\n    def check(self, transport: asyncio.Transport) -> None:\n        if not transport.get_extra_info(\"sslcontext\"):\n            return\n        sslobj = transport.get_extra_info(\"ssl_object\")\n        cert = sslobj.getpeercert(binary_form=True)\n        got = self._hashfunc(cert).digest()\n        if got != self._fingerprint:\n            host, port, *_ = transport.get_extra_info(\"peername\")\n            raise ServerFingerprintMismatch(self._fingerprint, got, host, port)\n\n\nif ssl is not None:\n    SSL_ALLOWED_TYPES = (ssl.SSLContext, bool, Fingerprint, type(None))\nelse:  # pragma: no cover\n    SSL_ALLOWED_TYPES = (bool, type(None))\n\n\ndef _merge_ssl_params(\n    ssl: Union[\"SSLContext\", bool, Fingerprint],\n    verify_ssl: Optional[bool],\n    ssl_context: Optional[\"SSLContext\"],\n    fingerprint: Optional[bytes],\n) -> Union[\"SSLContext\", bool, Fingerprint]:\n    if ssl is None:\n        ssl = True  # Double check for backwards compatibility\n    if verify_ssl is not None and not verify_ssl:\n        warnings.warn(\n            \"verify_ssl is deprecated, use ssl=False instead\",\n            DeprecationWarning,\n            stacklevel=3,\n        )\n        if ssl is not True:\n            raise ValueError(\n                \"verify_ssl, ssl_context, fingerprint and ssl \"\n                \"parameters are mutually exclusive\"\n            )\n        else:\n            ssl = False\n    if ssl_context is not None:\n        warnings.warn(\n            \"ssl_context is deprecated, use ssl=context instead\",\n            DeprecationWarning,\n            stacklevel=3,\n        )\n        if ssl is not True:\n            raise ValueError(\n                \"verify_ssl, ssl_context, fingerprint and ssl \"\n                \"parameters are mutually exclusive\"\n            )\n        else:\n            ssl = ssl_context\n    if fingerprint is not None:\n        warnings.warn(\n            \"fingerprint is deprecated, \" \"use ssl=Fingerprint(fingerprint) instead\",\n            DeprecationWarning,\n            stacklevel=3,\n        )\n        if ssl is not True:\n            raise ValueError(\n                \"verify_ssl, ssl_context, fingerprint and ssl \"\n                \"parameters are mutually exclusive\"\n            )\n        else:\n            ssl = Fingerprint(fingerprint)\n    if not isinstance(ssl, SSL_ALLOWED_TYPES):\n        raise TypeError(\n            \"ssl should be SSLContext, bool, Fingerprint or None, \"\n            \"got {!r} instead.\".format(ssl)\n        )\n    return ssl\n\n\n@attr.s(auto_attribs=True, slots=True, frozen=True, cache_hash=True)\nclass ConnectionKey:\n    # the key should contain an information about used proxy / TLS\n    # to prevent reusing wrong connections from a pool\n    host: str\n    port: Optional[int]\n    is_ssl: bool\n    ssl: Union[SSLContext, bool, Fingerprint]\n    proxy: Optional[URL]\n    proxy_auth: Optional[BasicAuth]\n    proxy_headers_hash: Optional[int]  # hash(CIMultiDict)\n\n\ndef _is_expected_content_type(\n    response_content_type: str, expected_content_type: str\n) -> bool:\n    if expected_content_type == \"application/json\":\n        return json_re.match(response_content_type) is not None\n    return expected_content_type in response_content_type\n\n\nclass ClientRequest:\n    GET_METHODS = {\n        hdrs.METH_GET,\n        hdrs.METH_HEAD,\n        hdrs.METH_OPTIONS,\n        hdrs.METH_TRACE,\n    }\n    POST_METHODS = {hdrs.METH_PATCH, hdrs.METH_POST, hdrs.METH_PUT}\n    ALL_METHODS = GET_METHODS.union(POST_METHODS).union({hdrs.METH_DELETE})\n\n    DEFAULT_HEADERS = {\n        hdrs.ACCEPT: \"*/*\",\n        hdrs.ACCEPT_ENCODING: _gen_default_accept_encoding(),\n    }\n\n    # Type of body depends on PAYLOAD_REGISTRY, which is dynamic.\n    body: Any = b\"\"\n    auth = None\n    response = None\n\n    __writer = None  # async task for streaming data\n    _continue = None  # waiter future for '100 Continue' response\n\n    # N.B.\n    # Adding __del__ method with self._writer closing doesn't make sense\n    # because _writer is instance method, thus it keeps a reference to self.\n    # Until writer has finished finalizer will not be called.\n\n    def __init__(\n        self,\n        method: str,\n        url: URL,\n        *,\n        params: Optional[Mapping[str, str]] = None,\n        headers: Optional[LooseHeaders] = None,\n        skip_auto_headers: Optional[Iterable[str]] = None,\n        data: Any = None,\n        cookies: Optional[LooseCookies] = None,\n        auth: Optional[BasicAuth] = None,\n        version: http.HttpVersion = http.HttpVersion11,\n        compress: Optional[str] = None,\n        chunked: Optional[bool] = None,\n        expect100: bool = False,\n        loop: Optional[asyncio.AbstractEventLoop] = None,\n        response_class: Optional[Type[\"ClientResponse\"]] = None,\n        proxy: Optional[URL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        timer: Optional[BaseTimerContext] = None,\n        session: Optional[\"ClientSession\"] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        proxy_headers: Optional[LooseHeaders] = None,\n        traces: Optional[List[\"Trace\"]] = None,\n        trust_env: bool = False,\n        server_hostname: Optional[str] = None,\n    ):\n        if loop is None:\n            loop = asyncio.get_event_loop()\n\n        match = _CONTAINS_CONTROL_CHAR_RE.search(method)\n        if match:\n            raise ValueError(\n                f\"Method cannot contain non-token characters {method!r} \"\n                \"(found at least {match.group()!r})\"\n            )\n\n        assert isinstance(url, URL), url\n        assert isinstance(proxy, (URL, type(None))), proxy\n        # FIXME: session is None in tests only, need to fix tests\n        # assert session is not None\n        self._session = cast(\"ClientSession\", session)\n        if params:\n            q = MultiDict(url.query)\n            url2 = url.with_query(params)\n            q.extend(url2.query)\n            url = url.with_query(q)\n        self.original_url = url\n        self.url = url.with_fragment(None)\n        self.method = method.upper()\n        self.chunked = chunked\n        self.compress = compress\n        self.loop = loop\n        self.length = None\n        if response_class is None:\n            real_response_class = ClientResponse\n        else:\n            real_response_class = response_class\n        self.response_class: Type[ClientResponse] = real_response_class\n        self._timer = timer if timer is not None else TimerNoop()\n        self._ssl = ssl if ssl is not None else True\n        self.server_hostname = server_hostname\n\n        if loop.get_debug():\n            self._source_traceback = traceback.extract_stack(sys._getframe(1))\n\n        self.update_version(version)\n        self.update_host(url)\n        self.update_headers(headers)\n        self.update_auto_headers(skip_auto_headers)\n        self.update_cookies(cookies)\n        self.update_content_encoding(data)\n        self.update_auth(auth, trust_env)\n        self.update_proxy(proxy, proxy_auth, proxy_headers)\n\n        self.update_body_from_data(data)\n        if data is not None or self.method not in self.GET_METHODS:\n            self.update_transfer_encoding()\n        self.update_expect_continue(expect100)\n        if traces is None:\n            traces = []\n        self._traces = traces\n\n    def __reset_writer(self, _: object = None) -> None:\n        self.__writer = None\n\n    @property\n    def _writer(self) -> Optional[\"asyncio.Task[None]\"]:\n        return self.__writer\n\n    @_writer.setter\n    def _writer(self, writer: Optional[\"asyncio.Task[None]\"]) -> None:\n        if self.__writer is not None:\n            self.__writer.remove_done_callback(self.__reset_writer)\n        self.__writer = writer\n        if writer is None:\n            return\n        if writer.done():\n            # The writer is already done, so we can reset it immediately.\n            self.__reset_writer()\n        else:\n            writer.add_done_callback(self.__reset_writer)\n\n    def is_ssl(self) -> bool:\n        return self.url.scheme in (\"https\", \"wss\")\n\n    @property\n    def ssl(self) -> Union[\"SSLContext\", bool, Fingerprint]:\n        return self._ssl\n\n    @property\n    def connection_key(self) -> ConnectionKey:\n        proxy_headers = self.proxy_headers\n        if proxy_headers:\n            h: Optional[int] = hash(tuple((k, v) for k, v in proxy_headers.items()))\n        else:\n            h = None\n        return ConnectionKey(\n            self.host,\n            self.port,\n            self.is_ssl(),\n            self.ssl,\n            self.proxy,\n            self.proxy_auth,\n            h,\n        )\n\n    @property\n    def host(self) -> str:\n        ret = self.url.raw_host\n        assert ret is not None\n        return ret\n\n    @property\n    def port(self) -> Optional[int]:\n        return self.url.port\n\n    @property\n    def request_info(self) -> RequestInfo:\n        headers: CIMultiDictProxy[str] = CIMultiDictProxy(self.headers)\n        return RequestInfo(self.url, self.method, headers, self.original_url)\n\n    def update_host(self, url: URL) -> None:\n        \"\"\"Update destination host, port and connection type (ssl).\"\"\"\n        # get host/port\n        if not url.raw_host:\n            raise InvalidURL(url)\n\n        # basic auth info\n        username, password = url.user, url.password\n        if username or password:\n            self.auth = helpers.BasicAuth(username or \"\", password or \"\")\n\n    def update_version(self, version: Union[http.HttpVersion, str]) -> None:\n        \"\"\"Convert request version to two elements tuple.\n\n        parser HTTP version '1.1' => (1, 1)\n        \"\"\"\n        if isinstance(version, str):\n            v = [part.strip() for part in version.split(\".\", 1)]\n            try:\n                version = http.HttpVersion(int(v[0]), int(v[1]))\n            except ValueError:\n                raise ValueError(\n                    f\"Can not parse http version number: {version}\"\n                ) from None\n        self.version = version\n\n    def update_headers(self, headers: Optional[LooseHeaders]) -> None:\n        \"\"\"Update request headers.\"\"\"\n        self.headers: CIMultiDict[str] = CIMultiDict()\n\n        # add host\n        netloc = cast(str, self.url.raw_host)\n        if helpers.is_ipv6_address(netloc):\n            netloc = f\"[{netloc}]\"\n        # See https://github.com/aio-libs/aiohttp/issues/3636.\n        netloc = netloc.rstrip(\".\")\n        if self.url.port is not None and not self.url.is_default_port():\n            netloc += \":\" + str(self.url.port)\n        self.headers[hdrs.HOST] = netloc\n\n        if headers:\n            if isinstance(headers, (dict, MultiDictProxy, MultiDict)):\n                headers = headers.items()\n\n            for key, value in headers:  # type: ignore[misc]\n                # A special case for Host header\n                if key.lower() == \"host\":\n                    self.headers[key] = value\n                else:\n                    self.headers.add(key, value)\n\n    def update_auto_headers(self, skip_auto_headers: Optional[Iterable[str]]) -> None:\n        if skip_auto_headers is not None:\n            self.skip_auto_headers = CIMultiDict(\n                (hdr, None) for hdr in sorted(skip_auto_headers)\n            )\n            used_headers = self.headers.copy()\n            used_headers.extend(self.skip_auto_headers)  # type: ignore[arg-type]\n        else:\n            # Fast path when there are no headers to skip\n            # which is the most common case.\n            self.skip_auto_headers = CIMultiDict()\n            used_headers = self.headers\n\n        for hdr, val in self.DEFAULT_HEADERS.items():\n            if hdr not in used_headers:\n                self.headers.add(hdr, val)\n\n        if hdrs.USER_AGENT not in used_headers:\n            self.headers[hdrs.USER_AGENT] = SERVER_SOFTWARE\n\n    def update_cookies(self, cookies: Optional[LooseCookies]) -> None:\n        \"\"\"Update request cookies header.\"\"\"\n        if not cookies:\n            return\n\n        c = SimpleCookie()\n        if hdrs.COOKIE in self.headers:\n            c.load(self.headers.get(hdrs.COOKIE, \"\"))\n            del self.headers[hdrs.COOKIE]\n\n        if isinstance(cookies, Mapping):\n            iter_cookies = cookies.items()\n        else:\n            iter_cookies = cookies  # type: ignore[assignment]\n        for name, value in iter_cookies:\n            if isinstance(value, Morsel):\n                # Preserve coded_value\n                mrsl_val = value.get(value.key, Morsel())\n                mrsl_val.set(value.key, value.value, value.coded_value)\n                c[name] = mrsl_val\n            else:\n                c[name] = value  # type: ignore[assignment]\n\n        self.headers[hdrs.COOKIE] = c.output(header=\"\", sep=\";\").strip()\n\n    def update_content_encoding(self, data: Any) -> None:\n        \"\"\"Set request content encoding.\"\"\"\n        if data is None:\n            return\n\n        enc = self.headers.get(hdrs.CONTENT_ENCODING, \"\").lower()\n        if enc:\n            if self.compress:\n                raise ValueError(\n                    \"compress can not be set \" \"if Content-Encoding header is set\"\n                )\n        elif self.compress:\n            if not isinstance(self.compress, str):\n                self.compress = \"deflate\"\n            self.headers[hdrs.CONTENT_ENCODING] = self.compress\n            self.chunked = True  # enable chunked, no need to deal with length\n\n    def update_transfer_encoding(self) -> None:\n        \"\"\"Analyze transfer-encoding header.\"\"\"\n        te = self.headers.get(hdrs.TRANSFER_ENCODING, \"\").lower()\n\n        if \"chunked\" in te:\n            if self.chunked:\n                raise ValueError(\n                    \"chunked can not be set \"\n                    'if \"Transfer-Encoding: chunked\" header is set'\n                )\n\n        elif self.chunked:\n            if hdrs.CONTENT_LENGTH in self.headers:\n                raise ValueError(\n                    \"chunked can not be set \" \"if Content-Length header is set\"\n                )\n\n            self.headers[hdrs.TRANSFER_ENCODING] = \"chunked\"\n        else:\n            if hdrs.CONTENT_LENGTH not in self.headers:\n                self.headers[hdrs.CONTENT_LENGTH] = str(len(self.body))\n\n    def update_auth(self, auth: Optional[BasicAuth], trust_env: bool = False) -> None:\n        \"\"\"Set basic auth.\"\"\"\n        if auth is None:\n            auth = self.auth\n        if auth is None and trust_env and self.url.host is not None:\n            netrc_obj = netrc_from_env()\n            with contextlib.suppress(LookupError):\n                auth = basicauth_from_netrc(netrc_obj, self.url.host)\n        if auth is None:\n            return\n\n        if not isinstance(auth, helpers.BasicAuth):\n            raise TypeError(\"BasicAuth() tuple is required instead\")\n\n        self.headers[hdrs.AUTHORIZATION] = auth.encode()\n\n    def update_body_from_data(self, body: Any) -> None:\n        if body is None:\n            return\n\n        # FormData\n        if isinstance(body, FormData):\n            body = body()\n\n        try:\n            body = payload.PAYLOAD_REGISTRY.get(body, disposition=None)\n        except payload.LookupError:\n            body = FormData(body)()\n\n        self.body = body\n\n        # enable chunked encoding if needed\n        if not self.chunked:\n            if hdrs.CONTENT_LENGTH not in self.headers:\n                size = body.size\n                if size is None:\n                    self.chunked = True\n                else:\n                    if hdrs.CONTENT_LENGTH not in self.headers:\n                        self.headers[hdrs.CONTENT_LENGTH] = str(size)\n\n        # copy payload headers\n        assert body.headers\n        for key, value in body.headers.items():\n            if key in self.headers or key in self.skip_auto_headers:\n                continue\n            self.headers[key] = value\n\n    def update_expect_continue(self, expect: bool = False) -> None:\n        if expect:\n            self.headers[hdrs.EXPECT] = \"100-continue\"\n        elif self.headers.get(hdrs.EXPECT, \"\").lower() == \"100-continue\":\n            expect = True\n\n        if expect:\n            self._continue = self.loop.create_future()\n\n    def update_proxy(\n        self,\n        proxy: Optional[URL],\n        proxy_auth: Optional[BasicAuth],\n        proxy_headers: Optional[LooseHeaders],\n    ) -> None:\n        if proxy_auth and not isinstance(proxy_auth, helpers.BasicAuth):\n            raise ValueError(\"proxy_auth must be None or BasicAuth() tuple\")\n        self.proxy = proxy\n        self.proxy_auth = proxy_auth\n        if proxy_headers is not None and not isinstance(\n            proxy_headers, (MultiDict, MultiDictProxy)\n        ):\n            proxy_headers = CIMultiDict(proxy_headers)\n        self.proxy_headers = proxy_headers\n\n    def keep_alive(self) -> bool:\n        if self.version < HttpVersion10:\n            # keep alive not supported at all\n            return False\n        if self.version == HttpVersion10:\n            if self.headers.get(hdrs.CONNECTION) == \"keep-alive\":\n                return True\n            else:  # no headers means we close for Http 1.0\n                return False\n        elif self.headers.get(hdrs.CONNECTION) == \"close\":\n            return False\n\n        return True\n\n    async def write_bytes(\n        self, writer: AbstractStreamWriter, conn: \"Connection\"\n    ) -> None:\n        \"\"\"Support coroutines that yields bytes objects.\"\"\"\n        # 100 response\n        if self._continue is not None:\n            try:\n                await writer.drain()\n                await self._continue\n            except asyncio.CancelledError:\n                return\n\n        protocol = conn.protocol\n        assert protocol is not None\n        try:\n            if isinstance(self.body, payload.Payload):\n                await self.body.write(writer)\n            else:\n                if isinstance(self.body, (bytes, bytearray)):\n                    self.body = (self.body,)\n\n                for chunk in self.body:\n                    await writer.write(chunk)\n        except OSError as underlying_exc:\n            reraised_exc = underlying_exc\n\n            exc_is_not_timeout = underlying_exc.errno is not None or not isinstance(\n                underlying_exc, asyncio.TimeoutError\n            )\n            if exc_is_not_timeout:\n                reraised_exc = ClientOSError(\n                    underlying_exc.errno,\n                    f\"Can not write request body for {self.url !s}\",\n                )\n\n            set_exception(protocol, reraised_exc, underlying_exc)\n        except asyncio.CancelledError:\n            await writer.write_eof()\n        except Exception as underlying_exc:\n            set_exception(\n                protocol,\n                ClientConnectionError(\n                    f\"Failed to send bytes into the underlying connection {conn !s}\",\n                ),\n                underlying_exc,\n            )\n        else:\n            await writer.write_eof()\n            protocol.start_timeout()\n\n    async def send(self, conn: \"Connection\") -> \"ClientResponse\":\n        # Specify request target:\n        # - CONNECT request must send authority form URI\n        # - not CONNECT proxy must send absolute form URI\n        # - most common is origin form URI\n        if self.method == hdrs.METH_CONNECT:\n            connect_host = self.url.raw_host\n            assert connect_host is not None\n            if helpers.is_ipv6_address(connect_host):\n                connect_host = f\"[{connect_host}]\"\n            path = f\"{connect_host}:{self.url.port}\"\n        elif self.proxy and not self.is_ssl():\n            path = str(self.url)\n        else:\n            path = self.url.raw_path\n            if self.url.raw_query_string:\n                path += \"?\" + self.url.raw_query_string\n\n        protocol = conn.protocol\n        assert protocol is not None\n        writer = StreamWriter(\n            protocol,\n            self.loop,\n            on_chunk_sent=functools.partial(\n                self._on_chunk_request_sent, self.method, self.url\n            ),\n            on_headers_sent=functools.partial(\n                self._on_headers_request_sent, self.method, self.url\n            ),\n        )\n\n        if self.compress:\n            writer.enable_compression(self.compress)\n\n        if self.chunked is not None:\n            writer.enable_chunking()\n\n        # set default content-type\n        if (\n            self.method in self.POST_METHODS\n            and hdrs.CONTENT_TYPE not in self.skip_auto_headers\n            and hdrs.CONTENT_TYPE not in self.headers\n        ):\n            self.headers[hdrs.CONTENT_TYPE] = \"application/octet-stream\"\n\n        # set the connection header\n        connection = self.headers.get(hdrs.CONNECTION)\n        if not connection:\n            if self.keep_alive():\n                if self.version == HttpVersion10:\n                    connection = \"keep-alive\"\n            else:\n                if self.version == HttpVersion11:\n                    connection = \"close\"\n\n        if connection is not None:\n            self.headers[hdrs.CONNECTION] = connection\n\n        # status + headers\n        v = self.version\n        status_line = f\"{self.method} {path} HTTP/{v.major}.{v.minor}\"\n        await writer.write_headers(status_line, self.headers)\n        coro = self.write_bytes(writer, conn)\n\n        if sys.version_info >= (3, 12):\n            # Optimization for Python 3.12, try to write\n            # bytes immediately to avoid having to schedule\n            # the task on the event loop.\n            task = asyncio.Task(coro, loop=self.loop, eager_start=True)\n        else:\n            task = self.loop.create_task(coro)\n\n        self._writer = task\n        response_class = self.response_class\n        assert response_class is not None\n        self.response = response_class(\n            self.method,\n            self.original_url,\n            writer=self._writer,\n            continue100=self._continue,\n            timer=self._timer,\n            request_info=self.request_info,\n            traces=self._traces,\n            loop=self.loop,\n            session=self._session,\n        )\n        return self.response\n\n    async def close(self) -> None:\n        if self._writer is not None:\n            with contextlib.suppress(asyncio.CancelledError):\n                await self._writer\n\n    def terminate(self) -> None:\n        if self._writer is not None:\n            if not self.loop.is_closed():\n                self._writer.cancel()\n            self._writer.remove_done_callback(self.__reset_writer)\n            self._writer = None\n\n    async def _on_chunk_request_sent(self, method: str, url: URL, chunk: bytes) -> None:\n        for trace in self._traces:\n            await trace.send_request_chunk_sent(method, url, chunk)\n\n    async def _on_headers_request_sent(\n        self, method: str, url: URL, headers: \"CIMultiDict[str]\"\n    ) -> None:\n        for trace in self._traces:\n            await trace.send_request_headers(method, url, headers)\n\n\nclass ClientResponse(HeadersMixin):\n\n    # Some of these attributes are None when created,\n    # but will be set by the start() method.\n    # As the end user will likely never see the None values, we cheat the types below.\n    # from the Status-Line of the response\n    version: Optional[HttpVersion] = None  # HTTP-Version\n    status: int = None  # type: ignore[assignment] # Status-Code\n    reason: Optional[str] = None  # Reason-Phrase\n\n    content: StreamReader = None  # type: ignore[assignment]  # Payload stream\n    _headers: CIMultiDictProxy[str] = None  # type: ignore[assignment]\n    _raw_headers: RawHeaders = None  # type: ignore[assignment]\n\n    _connection = None  # current connection\n    _source_traceback: Optional[traceback.StackSummary] = None\n    # set up by ClientRequest after ClientResponse object creation\n    # post-init stage allows to not change ctor signature\n    _closed = True  # to allow __del__ for non-initialized properly response\n    _released = False\n    __writer = None\n\n    def __init__(\n        self,\n        method: str,\n        url: URL,\n        *,\n        writer: \"asyncio.Task[None]\",\n        continue100: Optional[\"asyncio.Future[bool]\"],\n        timer: BaseTimerContext,\n        request_info: RequestInfo,\n        traces: List[\"Trace\"],\n        loop: asyncio.AbstractEventLoop,\n        session: \"ClientSession\",\n    ) -> None:\n        assert isinstance(url, URL)\n\n        self.method = method\n        self.cookies = SimpleCookie()\n\n        self._real_url = url\n        self._url = url.with_fragment(None)\n        self._body: Any = None\n        self._writer: Optional[asyncio.Task[None]] = writer\n        self._continue = continue100  # None by default\n        self._closed = True\n        self._history: Tuple[ClientResponse, ...] = ()\n        self._request_info = request_info\n        self._timer = timer if timer is not None else TimerNoop()\n        self._cache: Dict[str, Any] = {}\n        self._traces = traces\n        self._loop = loop\n        # store a reference to session #1985\n        self._session: Optional[ClientSession] = session\n        # Save reference to _resolve_charset, so that get_encoding() will still\n        # work after the response has finished reading the body.\n        if session is None:\n            # TODO: Fix session=None in tests (see ClientRequest.__init__).\n            self._resolve_charset: Callable[[\"ClientResponse\", bytes], str] = (\n                lambda *_: \"utf-8\"\n            )\n        else:\n            self._resolve_charset = session._resolve_charset\n        if loop.get_debug():\n            self._source_traceback = traceback.extract_stack(sys._getframe(1))\n\n    def __reset_writer(self, _: object = None) -> None:\n        self.__writer = None\n\n    @property\n    def _writer(self) -> Optional[\"asyncio.Task[None]\"]:\n        return self.__writer\n\n    @_writer.setter\n    def _writer(self, writer: Optional[\"asyncio.Task[None]\"]) -> None:\n        if self.__writer is not None:\n            self.__writer.remove_done_callback(self.__reset_writer)\n        self.__writer = writer\n        if writer is None:\n            return\n        if writer.done():\n            # The writer is already done, so we can reset it immediately.\n            self.__reset_writer()\n        else:\n            writer.add_done_callback(self.__reset_writer)\n\n    @reify\n    def url(self) -> URL:\n        return self._url\n\n    @reify\n    def url_obj(self) -> URL:\n        warnings.warn(\"Deprecated, use .url #1654\", DeprecationWarning, stacklevel=2)\n        return self._url\n\n    @reify\n    def real_url(self) -> URL:\n        return self._real_url\n\n    @reify\n    def host(self) -> str:\n        assert self._url.host is not None\n        return self._url.host\n\n    @reify\n    def headers(self) -> \"CIMultiDictProxy[str]\":\n        return self._headers\n\n    @reify\n    def raw_headers(self) -> RawHeaders:\n        return self._raw_headers\n\n    @reify\n    def request_info(self) -> RequestInfo:\n        return self._request_info\n\n    @reify\n    def content_disposition(self) -> Optional[ContentDisposition]:\n        raw = self._headers.get(hdrs.CONTENT_DISPOSITION)\n        if raw is None:\n            return None\n        disposition_type, params_dct = multipart.parse_content_disposition(raw)\n        params = MappingProxyType(params_dct)\n        filename = multipart.content_disposition_filename(params)\n        return ContentDisposition(disposition_type, params, filename)\n\n    def __del__(self, _warnings: Any = warnings) -> None:\n        if self._closed:\n            return\n\n        if self._connection is not None:\n            self._connection.release()\n            self._cleanup_writer()\n\n            if self._loop.get_debug():\n                kwargs = {\"source\": self}\n                _warnings.warn(f\"Unclosed response {self!r}\", ResourceWarning, **kwargs)\n                context = {\"client_response\": self, \"message\": \"Unclosed response\"}\n                if self._source_traceback:\n                    context[\"source_traceback\"] = self._source_traceback\n                self._loop.call_exception_handler(context)\n\n    def __repr__(self) -> str:\n        out = io.StringIO()\n        ascii_encodable_url = str(self.url)\n        if self.reason:\n            ascii_encodable_reason = self.reason.encode(\n                \"ascii\", \"backslashreplace\"\n            ).decode(\"ascii\")\n        else:\n            ascii_encodable_reason = \"None\"\n        print(\n            \"<ClientResponse({}) [{} {}]>\".format(\n                ascii_encodable_url, self.status, ascii_encodable_reason\n            ),\n            file=out,\n        )\n        print(self.headers, file=out)\n        return out.getvalue()\n\n    @property\n    def connection(self) -> Optional[\"Connection\"]:\n        return self._connection\n\n    @reify\n    def history(self) -> Tuple[\"ClientResponse\", ...]:\n        \"\"\"A sequence of of responses, if redirects occurred.\"\"\"\n        return self._history\n\n    @reify\n    def links(self) -> \"MultiDictProxy[MultiDictProxy[Union[str, URL]]]\":\n        links_str = \", \".join(self.headers.getall(\"link\", []))\n\n        if not links_str:\n            return MultiDictProxy(MultiDict())\n\n        links: MultiDict[MultiDictProxy[Union[str, URL]]] = MultiDict()\n\n        for val in re.split(r\",(?=\\s*<)\", links_str):\n            match = re.match(r\"\\s*<(.*)>(.*)\", val)\n            if match is None:  # pragma: no cover\n                # the check exists to suppress mypy error\n                continue\n            url, params_str = match.groups()\n            params = params_str.split(\";\")[1:]\n\n            link: MultiDict[Union[str, URL]] = MultiDict()\n\n            for param in params:\n                match = re.match(r\"^\\s*(\\S*)\\s*=\\s*(['\\\"]?)(.*?)(\\2)\\s*$\", param, re.M)\n                if match is None:  # pragma: no cover\n                    # the check exists to suppress mypy error\n                    continue\n                key, _, value, _ = match.groups()\n\n                link.add(key, value)\n\n            key = link.get(\"rel\", url)\n\n            link.add(\"url\", self.url.join(URL(url)))\n\n            links.add(str(key), MultiDictProxy(link))\n\n        return MultiDictProxy(links)\n\n    async def start(self, connection: \"Connection\") -> \"ClientResponse\":\n        \"\"\"Start response processing.\"\"\"\n        self._closed = False\n        self._protocol = connection.protocol\n        self._connection = connection\n\n        with self._timer:\n            while True:\n                # read response\n                try:\n                    protocol = self._protocol\n                    message, payload = await protocol.read()  # type: ignore[union-attr]\n                except http.HttpProcessingError as exc:\n                    raise ClientResponseError(\n                        self.request_info,\n                        self.history,\n                        status=exc.code,\n                        message=exc.message,\n                        headers=exc.headers,\n                    ) from exc\n\n                if message.code < 100 or message.code > 199 or message.code == 101:\n                    break\n\n                if self._continue is not None:\n                    set_result(self._continue, True)\n                    self._continue = None\n\n        # payload eof handler\n        payload.on_eof(self._response_eof)\n\n        # response status\n        self.version = message.version\n        self.status = message.code\n        self.reason = message.reason\n\n        # headers\n        self._headers = message.headers  # type is CIMultiDictProxy\n        self._raw_headers = message.raw_headers  # type is Tuple[bytes, bytes]\n\n        # payload\n        self.content = payload\n\n        # cookies\n        for hdr in self.headers.getall(hdrs.SET_COOKIE, ()):\n            try:\n                self.cookies.load(hdr)\n            except CookieError as exc:\n                client_logger.warning(\"Can not load response cookies: %s\", exc)\n        return self\n\n    def _response_eof(self) -> None:\n        if self._closed:\n            return\n\n        # protocol could be None because connection could be detached\n        protocol = self._connection and self._connection.protocol\n        if protocol is not None and protocol.upgraded:\n            return\n\n        self._closed = True\n        self._cleanup_writer()\n        self._release_connection()\n\n    @property\n    def closed(self) -> bool:\n        return self._closed\n\n    def close(self) -> None:\n        if not self._released:\n            self._notify_content()\n\n        self._closed = True\n        if self._loop is None or self._loop.is_closed():\n            return\n\n        self._cleanup_writer()\n        if self._connection is not None:\n            self._connection.close()\n            self._connection = None\n\n    def release(self) -> Any:\n        if not self._released:\n            self._notify_content()\n\n        self._closed = True\n\n        self._cleanup_writer()\n        self._release_connection()\n        return noop()\n\n    @property\n    def ok(self) -> bool:\n        \"\"\"Returns ``True`` if ``status`` is less than ``400``, ``False`` if not.\n\n        This is **not** a check for ``200 OK`` but a check that the response\n        status is under 400.\n        \"\"\"\n        return 400 > self.status\n\n    def raise_for_status(self) -> None:\n        if not self.ok:\n            # reason should always be not None for a started response\n            assert self.reason is not None\n            self.release()\n            raise ClientResponseError(\n                self.request_info,\n                self.history,\n                status=self.status,\n                message=self.reason,\n                headers=self.headers,\n            )\n\n    def _release_connection(self) -> None:\n        if self._connection is not None:\n            if self._writer is None:\n                self._connection.release()\n                self._connection = None\n            else:\n                self._writer.add_done_callback(lambda f: self._release_connection())\n\n    async def _wait_released(self) -> None:\n        if self._writer is not None:\n            await self._writer\n        self._release_connection()\n\n    def _cleanup_writer(self) -> None:\n        if self._writer is not None:\n            self._writer.cancel()\n        self._session = None\n\n    def _notify_content(self) -> None:\n        content = self.content\n        if content and content.exception() is None:\n            set_exception(content, ClientConnectionError(\"Connection closed\"))\n        self._released = True\n\n    async def wait_for_close(self) -> None:\n        if self._writer is not None:\n            await self._writer\n        self.release()\n\n    async def read(self) -> bytes:\n        \"\"\"Read response payload.\"\"\"\n        if self._body is None:\n            try:\n                self._body = await self.content.read()\n                for trace in self._traces:\n                    await trace.send_response_chunk_received(\n                        self.method, self.url, self._body\n                    )\n            except BaseException:\n                self.close()\n                raise\n        elif self._released:  # Response explicitly released\n            raise ClientConnectionError(\"Connection closed\")\n\n        protocol = self._connection and self._connection.protocol\n        if protocol is None or not protocol.upgraded:\n            await self._wait_released()  # Underlying connection released\n        return self._body  # type: ignore[no-any-return]\n\n    def get_encoding(self) -> str:\n        ctype = self.headers.get(hdrs.CONTENT_TYPE, \"\").lower()\n        mimetype = helpers.parse_mimetype(ctype)\n\n        encoding = mimetype.parameters.get(\"charset\")\n        if encoding:\n            with contextlib.suppress(LookupError):\n                return codecs.lookup(encoding).name\n\n        if mimetype.type == \"application\" and (\n            mimetype.subtype == \"json\" or mimetype.subtype == \"rdap\"\n        ):\n            # RFC 7159 states that the default encoding is UTF-8.\n            # RFC 7483 defines application/rdap+json\n            return \"utf-8\"\n\n        if self._body is None:\n            raise RuntimeError(\n                \"Cannot compute fallback encoding of a not yet read body\"\n            )\n\n        return self._resolve_charset(self, self._body)\n\n    async def text(self, encoding: Optional[str] = None, errors: str = \"strict\") -> str:\n        \"\"\"Read response payload and decode.\"\"\"\n        if self._body is None:\n            await self.read()\n\n        if encoding is None:\n            encoding = self.get_encoding()\n\n        return self._body.decode(  # type: ignore[no-any-return,union-attr]\n            encoding, errors=errors\n        )\n\n    async def json(\n        self,\n        *,\n        encoding: Optional[str] = None,\n        loads: JSONDecoder = DEFAULT_JSON_DECODER,\n        content_type: Optional[str] = \"application/json\",\n    ) -> Any:\n        \"\"\"Read and decodes JSON response.\"\"\"\n        if self._body is None:\n            await self.read()\n\n        if content_type:\n            ctype = self.headers.get(hdrs.CONTENT_TYPE, \"\").lower()\n            if not _is_expected_content_type(ctype, content_type):\n                raise ContentTypeError(\n                    self.request_info,\n                    self.history,\n                    status=self.status,\n                    message=(\n                        \"Attempt to decode JSON with \" \"unexpected mimetype: %s\" % ctype\n                    ),\n                    headers=self.headers,\n                )\n\n        stripped = self._body.strip()  # type: ignore[union-attr]\n        if not stripped:\n            return None\n\n        if encoding is None:\n            encoding = self.get_encoding()\n\n        return loads(stripped.decode(encoding))\n\n    async def __aenter__(self) -> \"ClientResponse\":\n        return self\n\n    async def __aexit__(\n        self,\n        exc_type: Optional[Type[BaseException]],\n        exc_val: Optional[BaseException],\n        exc_tb: Optional[TracebackType],\n    ) -> None:\n        # similar to _RequestContextManager, we do not need to check\n        # for exceptions, response object can close connection\n        # if state is broken\n        self.release()\n        await self.wait_for_close()\n",
            "new_file_content": "import asyncio\nimport codecs\nimport contextlib\nimport functools\nimport io\nimport re\nimport sys\nimport traceback\nimport warnings\nfrom hashlib import md5, sha1, sha256\nfrom http.cookies import CookieError, Morsel, SimpleCookie\nfrom types import MappingProxyType, TracebackType\nfrom typing import (\n    TYPE_CHECKING,\n    Any,\n    Callable,\n    Dict,\n    Iterable,\n    List,\n    Mapping,\n    Optional,\n    Tuple,\n    Type,\n    Union,\n    cast,\n)\n\nimport attr\nfrom multidict import CIMultiDict, CIMultiDictProxy, MultiDict, MultiDictProxy\nfrom yarl import URL\n\nfrom . import hdrs, helpers, http, multipart, payload\nfrom .abc import AbstractStreamWriter\nfrom .client_exceptions import (\n    ClientConnectionError,\n    ClientOSError,\n    ClientResponseError,\n    ContentTypeError,\n    InvalidURL,\n    ServerFingerprintMismatch,\n)\nfrom .compression_utils import HAS_BROTLI\nfrom .formdata import FormData\nfrom .helpers import (\n    BaseTimerContext,\n    BasicAuth,\n    HeadersMixin,\n    TimerNoop,\n    basicauth_from_netrc,\n    netrc_from_env,\n    noop,\n    reify,\n    set_exception,\n    set_result,\n)\nfrom .http import (\n    SERVER_SOFTWARE,\n    HttpVersion,\n    HttpVersion10,\n    HttpVersion11,\n    StreamWriter,\n)\nfrom .log import client_logger\nfrom .streams import StreamReader\nfrom .typedefs import (\n    DEFAULT_JSON_DECODER,\n    JSONDecoder,\n    LooseCookies,\n    LooseHeaders,\n    RawHeaders,\n)\n\ntry:\n    import ssl\n    from ssl import SSLContext\nexcept ImportError:  # pragma: no cover\n    ssl = None  # type: ignore[assignment]\n    SSLContext = object  # type: ignore[misc,assignment]\n\n\n__all__ = (\"ClientRequest\", \"ClientResponse\", \"RequestInfo\", \"Fingerprint\")\n\n\nif TYPE_CHECKING:\n    from .client import ClientSession\n    from .connector import Connection\n    from .tracing import Trace\n\n\n_CONTAINS_CONTROL_CHAR_RE = re.compile(r\"[^-!#$%&'*+.^_`|~0-9a-zA-Z]\")\njson_re = re.compile(r\"^application/(?:[\\w.+-]+?\\+)?json\")\n\n\ndef _gen_default_accept_encoding() -> str:\n    return \"gzip, deflate, br\" if HAS_BROTLI else \"gzip, deflate\"\n\n\n@attr.s(auto_attribs=True, frozen=True, slots=True)\nclass ContentDisposition:\n    type: Optional[str]\n    parameters: \"MappingProxyType[str, str]\"\n    filename: Optional[str]\n\n\n@attr.s(auto_attribs=True, frozen=True, slots=True)\nclass RequestInfo:\n    url: URL\n    method: str\n    headers: \"CIMultiDictProxy[str]\"\n    real_url: URL = attr.ib()\n\n    @real_url.default\n    def real_url_default(self) -> URL:\n        return self.url\n\n\nclass Fingerprint:\n    HASHFUNC_BY_DIGESTLEN = {\n        16: md5,\n        20: sha1,\n        32: sha256,\n    }\n\n    def __init__(self, fingerprint: bytes) -> None:\n        digestlen = len(fingerprint)\n        hashfunc = self.HASHFUNC_BY_DIGESTLEN.get(digestlen)\n        if not hashfunc:\n            raise ValueError(\"fingerprint has invalid length\")\n        elif hashfunc is md5 or hashfunc is sha1:\n            raise ValueError(\n                \"md5 and sha1 are insecure and \" \"not supported. Use sha256.\"\n            )\n        self._hashfunc = hashfunc\n        self._fingerprint = fingerprint\n\n    @property\n    def fingerprint(self) -> bytes:\n        return self._fingerprint\n\n    def check(self, transport: asyncio.Transport) -> None:\n        if not transport.get_extra_info(\"sslcontext\"):\n            return\n        sslobj = transport.get_extra_info(\"ssl_object\")\n        cert = sslobj.getpeercert(binary_form=True)\n        got = self._hashfunc(cert).digest()\n        if got != self._fingerprint:\n            host, port, *_ = transport.get_extra_info(\"peername\")\n            raise ServerFingerprintMismatch(self._fingerprint, got, host, port)\n\n\nif ssl is not None:\n    SSL_ALLOWED_TYPES = (ssl.SSLContext, bool, Fingerprint, type(None))\nelse:  # pragma: no cover\n    SSL_ALLOWED_TYPES = (bool, type(None))\n\n\ndef _merge_ssl_params(\n    ssl: Union[\"SSLContext\", bool, Fingerprint],\n    verify_ssl: Optional[bool],\n    ssl_context: Optional[\"SSLContext\"],\n    fingerprint: Optional[bytes],\n) -> Union[\"SSLContext\", bool, Fingerprint]:\n    if ssl is None:\n        ssl = True  # Double check for backwards compatibility\n    if verify_ssl is not None and not verify_ssl:\n        warnings.warn(\n            \"verify_ssl is deprecated, use ssl=False instead\",\n            DeprecationWarning,\n            stacklevel=3,\n        )\n        if ssl is not True:\n            raise ValueError(\n                \"verify_ssl, ssl_context, fingerprint and ssl \"\n                \"parameters are mutually exclusive\"\n            )\n        else:\n            ssl = False\n    if ssl_context is not None:\n        warnings.warn(\n            \"ssl_context is deprecated, use ssl=context instead\",\n            DeprecationWarning,\n            stacklevel=3,\n        )\n        if ssl is not True:\n            raise ValueError(\n                \"verify_ssl, ssl_context, fingerprint and ssl \"\n                \"parameters are mutually exclusive\"\n            )\n        else:\n            ssl = ssl_context\n    if fingerprint is not None:\n        warnings.warn(\n            \"fingerprint is deprecated, \" \"use ssl=Fingerprint(fingerprint) instead\",\n            DeprecationWarning,\n            stacklevel=3,\n        )\n        if ssl is not True:\n            raise ValueError(\n                \"verify_ssl, ssl_context, fingerprint and ssl \"\n                \"parameters are mutually exclusive\"\n            )\n        else:\n            ssl = Fingerprint(fingerprint)\n    if not isinstance(ssl, SSL_ALLOWED_TYPES):\n        raise TypeError(\n            \"ssl should be SSLContext, bool, Fingerprint or None, \"\n            \"got {!r} instead.\".format(ssl)\n        )\n    return ssl\n\n\n@attr.s(auto_attribs=True, slots=True, frozen=True, cache_hash=True)\nclass ConnectionKey:\n    # the key should contain an information about used proxy / TLS\n    # to prevent reusing wrong connections from a pool\n    host: str\n    port: Optional[int]\n    is_ssl: bool\n    ssl: Union[SSLContext, bool, Fingerprint]\n    proxy: Optional[URL]\n    proxy_auth: Optional[BasicAuth]\n    proxy_headers_hash: Optional[int]  # hash(CIMultiDict)\n\n\ndef _is_expected_content_type(\n    response_content_type: str, expected_content_type: str\n) -> bool:\n    if expected_content_type == \"application/json\":\n        return json_re.match(response_content_type) is not None\n    return expected_content_type in response_content_type\n\n\nclass ClientRequest:\n    GET_METHODS = {\n        hdrs.METH_GET,\n        hdrs.METH_HEAD,\n        hdrs.METH_OPTIONS,\n        hdrs.METH_TRACE,\n    }\n    POST_METHODS = {hdrs.METH_PATCH, hdrs.METH_POST, hdrs.METH_PUT}\n    ALL_METHODS = GET_METHODS.union(POST_METHODS).union({hdrs.METH_DELETE})\n\n    DEFAULT_HEADERS = {\n        hdrs.ACCEPT: \"*/*\",\n        hdrs.ACCEPT_ENCODING: _gen_default_accept_encoding(),\n    }\n\n    # Type of body depends on PAYLOAD_REGISTRY, which is dynamic.\n    body: Any = b\"\"\n    auth = None\n    response = None\n\n    __writer = None  # async task for streaming data\n    _continue = None  # waiter future for '100 Continue' response\n\n    # N.B.\n    # Adding __del__ method with self._writer closing doesn't make sense\n    # because _writer is instance method, thus it keeps a reference to self.\n    # Until writer has finished finalizer will not be called.\n\n    def __init__(\n        self,\n        method: str,\n        url: URL,\n        *,\n        params: Optional[Mapping[str, str]] = None,\n        headers: Optional[LooseHeaders] = None,\n        skip_auto_headers: Optional[Iterable[str]] = None,\n        data: Any = None,\n        cookies: Optional[LooseCookies] = None,\n        auth: Optional[BasicAuth] = None,\n        version: http.HttpVersion = http.HttpVersion11,\n        compress: Optional[str] = None,\n        chunked: Optional[bool] = None,\n        expect100: bool = False,\n        loop: Optional[asyncio.AbstractEventLoop] = None,\n        response_class: Optional[Type[\"ClientResponse\"]] = None,\n        proxy: Optional[URL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        timer: Optional[BaseTimerContext] = None,\n        session: Optional[\"ClientSession\"] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        proxy_headers: Optional[LooseHeaders] = None,\n        traces: Optional[List[\"Trace\"]] = None,\n        trust_env: bool = False,\n        server_hostname: Optional[str] = None,\n    ):\n        if loop is None:\n            loop = asyncio.get_event_loop()\n\n        match = _CONTAINS_CONTROL_CHAR_RE.search(method)\n        if match:\n            raise ValueError(\n                f\"Method cannot contain non-token characters {method!r} \"\n                \"(found at least {match.group()!r})\"\n            )\n\n        assert isinstance(url, URL), url\n        assert isinstance(proxy, (URL, type(None))), proxy\n        # FIXME: session is None in tests only, need to fix tests\n        # assert session is not None\n        self._session = cast(\"ClientSession\", session)\n        if params:\n            q = MultiDict(url.query)\n            url2 = url.with_query(params)\n            q.extend(url2.query)\n            url = url.with_query(q)\n        self.original_url = url\n        self.url = url.with_fragment(None)\n        self.method = method.upper()\n        self.chunked = chunked\n        self.compress = compress\n        self.loop = loop\n        self.length = None\n        if response_class is None:\n            real_response_class = ClientResponse\n        else:\n            real_response_class = response_class\n        self.response_class: Type[ClientResponse] = real_response_class\n        self._timer = timer if timer is not None else TimerNoop()\n        self._ssl = ssl if ssl is not None else True\n        self.server_hostname = server_hostname\n\n        if loop.get_debug():\n            self._source_traceback = traceback.extract_stack(sys._getframe(1))\n\n        self.update_version(version)\n        self.update_host(url)\n        self.update_headers(headers)\n        self.update_auto_headers(skip_auto_headers)\n        self.update_cookies(cookies)\n        self.update_content_encoding(data)\n        self.update_auth(auth, trust_env)\n        self.update_proxy(proxy, proxy_auth, proxy_headers)\n\n        self.update_body_from_data(data)\n        if data is not None or self.method not in self.GET_METHODS:\n            self.update_transfer_encoding()\n        self.update_expect_continue(expect100)\n        if traces is None:\n            traces = []\n        self._traces = traces\n\n    def __reset_writer(self, _: object = None) -> None:\n        self.__writer = None\n\n    @property\n    def _writer(self) -> Optional[\"asyncio.Task[None]\"]:\n        return self.__writer\n\n    @_writer.setter\n    def _writer(self, writer: Optional[\"asyncio.Task[None]\"]) -> None:\n        if self.__writer is not None:\n            self.__writer.remove_done_callback(self.__reset_writer)\n        self.__writer = writer\n        if writer is None:\n            return\n        if writer.done():\n            # The writer is already done, so we can reset it immediately.\n            self.__reset_writer()\n        else:\n            writer.add_done_callback(self.__reset_writer)\n\n    def is_ssl(self) -> bool:\n        return self.url.scheme in (\"https\", \"wss\")\n\n    @property\n    def ssl(self) -> Union[\"SSLContext\", bool, Fingerprint]:\n        return self._ssl\n\n    @property\n    def connection_key(self) -> ConnectionKey:\n        proxy_headers = self.proxy_headers\n        if proxy_headers:\n            h: Optional[int] = hash(tuple((k, v) for k, v in proxy_headers.items()))\n        else:\n            h = None\n        return ConnectionKey(\n            self.host,\n            self.port,\n            self.is_ssl(),\n            self.ssl,\n            self.proxy,\n            self.proxy_auth,\n            h,\n        )\n\n    @property\n    def host(self) -> str:\n        ret = self.url.raw_host\n        assert ret is not None\n        return ret\n\n    @property\n    def port(self) -> Optional[int]:\n        return self.url.port\n\n    @property\n    def request_info(self) -> RequestInfo:\n        headers: CIMultiDictProxy[str] = CIMultiDictProxy(self.headers)\n        return RequestInfo(self.url, self.method, headers, self.original_url)\n\n    def update_host(self, url: URL) -> None:\n        \"\"\"Update destination host, port and connection type (ssl).\"\"\"\n        # get host/port\n        if not url.raw_host:\n            raise InvalidURL(url)\n\n        # basic auth info\n        username, password = url.user, url.password\n        if username or password:\n            self.auth = helpers.BasicAuth(username or \"\", password or \"\")\n\n    def update_version(self, version: Union[http.HttpVersion, str]) -> None:\n        \"\"\"Convert request version to two elements tuple.\n\n        parser HTTP version '1.1' => (1, 1)\n        \"\"\"\n        if isinstance(version, str):\n            v = [part.strip() for part in version.split(\".\", 1)]\n            try:\n                version = http.HttpVersion(int(v[0]), int(v[1]))\n            except ValueError:\n                raise ValueError(\n                    f\"Can not parse http version number: {version}\"\n                ) from None\n        self.version = version\n\n    def update_headers(self, headers: Optional[LooseHeaders]) -> None:\n        \"\"\"Update request headers.\"\"\"\n        self.headers: CIMultiDict[str] = CIMultiDict()\n\n        # add host\n        netloc = cast(str, self.url.raw_host)\n        if helpers.is_ipv6_address(netloc):\n            netloc = f\"[{netloc}]\"\n        # See https://github.com/aio-libs/aiohttp/issues/3636.\n        netloc = netloc.rstrip(\".\")\n        if self.url.port is not None and not self.url.is_default_port():\n            netloc += \":\" + str(self.url.port)\n        self.headers[hdrs.HOST] = netloc\n\n        if headers:\n            if isinstance(headers, (dict, MultiDictProxy, MultiDict)):\n                headers = headers.items()\n\n            for key, value in headers:  # type: ignore[misc]\n                # A special case for Host header\n                if key.lower() == \"host\":\n                    self.headers[key] = value\n                else:\n                    self.headers.add(key, value)\n\n    def update_auto_headers(self, skip_auto_headers: Optional[Iterable[str]]) -> None:\n        if skip_auto_headers is not None:\n            self.skip_auto_headers = CIMultiDict(\n                (hdr, None) for hdr in sorted(skip_auto_headers)\n            )\n            used_headers = self.headers.copy()\n            used_headers.extend(self.skip_auto_headers)  # type: ignore[arg-type]\n        else:\n            # Fast path when there are no headers to skip\n            # which is the most common case.\n            self.skip_auto_headers = CIMultiDict()\n            used_headers = self.headers\n\n        for hdr, val in self.DEFAULT_HEADERS.items():\n            if hdr not in used_headers:\n                self.headers.add(hdr, val)\n\n        if hdrs.USER_AGENT not in used_headers:\n            self.headers[hdrs.USER_AGENT] = SERVER_SOFTWARE\n\n    def update_cookies(self, cookies: Optional[LooseCookies]) -> None:\n        \"\"\"Update request cookies header.\"\"\"\n        if not cookies:\n            return\n\n        c = SimpleCookie()\n        if hdrs.COOKIE in self.headers:\n            c.load(self.headers.get(hdrs.COOKIE, \"\"))\n            del self.headers[hdrs.COOKIE]\n\n        if isinstance(cookies, Mapping):\n            iter_cookies = cookies.items()\n        else:\n            iter_cookies = cookies  # type: ignore[assignment]\n        for name, value in iter_cookies:\n            if isinstance(value, Morsel):\n                # Preserve coded_value\n                mrsl_val = value.get(value.key, Morsel())\n                mrsl_val.set(value.key, value.value, value.coded_value)\n                c[name] = mrsl_val\n            else:\n                c[name] = value  # type: ignore[assignment]\n\n        self.headers[hdrs.COOKIE] = c.output(header=\"\", sep=\";\").strip()\n\n    def update_content_encoding(self, data: Any) -> None:\n        \"\"\"Set request content encoding.\"\"\"\n        if data is None:\n            return\n\n        enc = self.headers.get(hdrs.CONTENT_ENCODING, \"\").lower()\n        if enc:\n            if self.compress:\n                raise ValueError(\n                    \"compress can not be set \" \"if Content-Encoding header is set\"\n                )\n        elif self.compress:\n            if not isinstance(self.compress, str):\n                self.compress = \"deflate\"\n            self.headers[hdrs.CONTENT_ENCODING] = self.compress\n            self.chunked = True  # enable chunked, no need to deal with length\n\n    def update_transfer_encoding(self) -> None:\n        \"\"\"Analyze transfer-encoding header.\"\"\"\n        te = self.headers.get(hdrs.TRANSFER_ENCODING, \"\").lower()\n\n        if \"chunked\" in te:\n            if self.chunked:\n                raise ValueError(\n                    \"chunked can not be set \"\n                    'if \"Transfer-Encoding: chunked\" header is set'\n                )\n\n        elif self.chunked:\n            if hdrs.CONTENT_LENGTH in self.headers:\n                raise ValueError(\n                    \"chunked can not be set \" \"if Content-Length header is set\"\n                )\n\n            self.headers[hdrs.TRANSFER_ENCODING] = \"chunked\"\n        else:\n            if hdrs.CONTENT_LENGTH not in self.headers:\n                self.headers[hdrs.CONTENT_LENGTH] = str(len(self.body))\n\n    def update_auth(self, auth: Optional[BasicAuth], trust_env: bool = False) -> None:\n        \"\"\"Set basic auth.\"\"\"\n        if auth is None:\n            auth = self.auth\n        if auth is None and trust_env and self.url.host is not None:\n            netrc_obj = netrc_from_env()\n            with contextlib.suppress(LookupError):\n                auth = basicauth_from_netrc(netrc_obj, self.url.host)\n        if auth is None:\n            return\n\n        if not isinstance(auth, helpers.BasicAuth):\n            raise TypeError(\"BasicAuth() tuple is required instead\")\n\n        self.headers[hdrs.AUTHORIZATION] = auth.encode()\n\n    def update_body_from_data(self, body: Any) -> None:\n        if body is None:\n            return\n\n        # FormData\n        if isinstance(body, FormData):\n            body = body()\n\n        try:\n            body = payload.PAYLOAD_REGISTRY.get(body, disposition=None)\n        except payload.LookupError:\n            body = FormData(body)()\n\n        self.body = body\n\n        # enable chunked encoding if needed\n        if not self.chunked:\n            if hdrs.CONTENT_LENGTH not in self.headers:\n                size = body.size\n                if size is None:\n                    self.chunked = True\n                else:\n                    if hdrs.CONTENT_LENGTH not in self.headers:\n                        self.headers[hdrs.CONTENT_LENGTH] = str(size)\n\n        # copy payload headers\n        assert body.headers\n        for key, value in body.headers.items():\n            if key in self.headers or key in self.skip_auto_headers:\n                continue\n            self.headers[key] = value\n\n    def update_expect_continue(self, expect: bool = False) -> None:\n        if expect:\n            self.headers[hdrs.EXPECT] = \"100-continue\"\n        elif self.headers.get(hdrs.EXPECT, \"\").lower() == \"100-continue\":\n            expect = True\n\n        if expect:\n            self._continue = self.loop.create_future()\n\n    def update_proxy(\n        self,\n        proxy: Optional[URL],\n        proxy_auth: Optional[BasicAuth],\n        proxy_headers: Optional[LooseHeaders],\n    ) -> None:\n        if proxy_auth and not isinstance(proxy_auth, helpers.BasicAuth):\n            raise ValueError(\"proxy_auth must be None or BasicAuth() tuple\")\n        self.proxy = proxy\n        self.proxy_auth = proxy_auth\n        if proxy_headers is not None and not isinstance(\n            proxy_headers, (MultiDict, MultiDictProxy)\n        ):\n            proxy_headers = CIMultiDict(proxy_headers)\n        self.proxy_headers = proxy_headers\n\n    def keep_alive(self) -> bool:\n        if self.version < HttpVersion10:\n            # keep alive not supported at all\n            return False\n        if self.version == HttpVersion10:\n            if self.headers.get(hdrs.CONNECTION) == \"keep-alive\":\n                return True\n            else:  # no headers means we close for Http 1.0\n                return False\n        elif self.headers.get(hdrs.CONNECTION) == \"close\":\n            return False\n\n        return True\n\n    async def write_bytes(\n        self, writer: AbstractStreamWriter, conn: \"Connection\"\n    ) -> None:\n        \"\"\"Support coroutines that yields bytes objects.\"\"\"\n        # 100 response\n        if self._continue is not None:\n            try:\n                await writer.drain()\n                await self._continue\n            except asyncio.CancelledError:\n                return\n\n        protocol = conn.protocol\n        assert protocol is not None\n        try:\n            if isinstance(self.body, payload.Payload):\n                await self.body.write(writer)\n            else:\n                if isinstance(self.body, (bytes, bytearray)):\n                    self.body = (self.body,)\n\n                for chunk in self.body:\n                    await writer.write(chunk)\n        except OSError as underlying_exc:\n            reraised_exc = underlying_exc\n\n            exc_is_not_timeout = underlying_exc.errno is not None or not isinstance(\n                underlying_exc, asyncio.TimeoutError\n            )\n            if exc_is_not_timeout:\n                reraised_exc = ClientOSError(\n                    underlying_exc.errno,\n                    f\"Can not write request body for {self.url !s}\",\n                )\n\n            set_exception(protocol, reraised_exc, underlying_exc)\n        except asyncio.CancelledError:\n            # Body hasn't been fully sent, so connection can't be reused.\n            conn.close()\n        except Exception as underlying_exc:\n            set_exception(\n                protocol,\n                ClientConnectionError(\n                    f\"Failed to send bytes into the underlying connection {conn !s}\",\n                ),\n                underlying_exc,\n            )\n        else:\n            await writer.write_eof()\n            protocol.start_timeout()\n\n    async def send(self, conn: \"Connection\") -> \"ClientResponse\":\n        # Specify request target:\n        # - CONNECT request must send authority form URI\n        # - not CONNECT proxy must send absolute form URI\n        # - most common is origin form URI\n        if self.method == hdrs.METH_CONNECT:\n            connect_host = self.url.raw_host\n            assert connect_host is not None\n            if helpers.is_ipv6_address(connect_host):\n                connect_host = f\"[{connect_host}]\"\n            path = f\"{connect_host}:{self.url.port}\"\n        elif self.proxy and not self.is_ssl():\n            path = str(self.url)\n        else:\n            path = self.url.raw_path\n            if self.url.raw_query_string:\n                path += \"?\" + self.url.raw_query_string\n\n        protocol = conn.protocol\n        assert protocol is not None\n        writer = StreamWriter(\n            protocol,\n            self.loop,\n            on_chunk_sent=functools.partial(\n                self._on_chunk_request_sent, self.method, self.url\n            ),\n            on_headers_sent=functools.partial(\n                self._on_headers_request_sent, self.method, self.url\n            ),\n        )\n\n        if self.compress:\n            writer.enable_compression(self.compress)\n\n        if self.chunked is not None:\n            writer.enable_chunking()\n\n        # set default content-type\n        if (\n            self.method in self.POST_METHODS\n            and hdrs.CONTENT_TYPE not in self.skip_auto_headers\n            and hdrs.CONTENT_TYPE not in self.headers\n        ):\n            self.headers[hdrs.CONTENT_TYPE] = \"application/octet-stream\"\n\n        # set the connection header\n        connection = self.headers.get(hdrs.CONNECTION)\n        if not connection:\n            if self.keep_alive():\n                if self.version == HttpVersion10:\n                    connection = \"keep-alive\"\n            else:\n                if self.version == HttpVersion11:\n                    connection = \"close\"\n\n        if connection is not None:\n            self.headers[hdrs.CONNECTION] = connection\n\n        # status + headers\n        v = self.version\n        status_line = f\"{self.method} {path} HTTP/{v.major}.{v.minor}\"\n        await writer.write_headers(status_line, self.headers)\n        coro = self.write_bytes(writer, conn)\n\n        if sys.version_info >= (3, 12):\n            # Optimization for Python 3.12, try to write\n            # bytes immediately to avoid having to schedule\n            # the task on the event loop.\n            task = asyncio.Task(coro, loop=self.loop, eager_start=True)\n        else:\n            task = self.loop.create_task(coro)\n\n        self._writer = task\n        response_class = self.response_class\n        assert response_class is not None\n        self.response = response_class(\n            self.method,\n            self.original_url,\n            writer=self._writer,\n            continue100=self._continue,\n            timer=self._timer,\n            request_info=self.request_info,\n            traces=self._traces,\n            loop=self.loop,\n            session=self._session,\n        )\n        return self.response\n\n    async def close(self) -> None:\n        if self._writer is not None:\n            with contextlib.suppress(asyncio.CancelledError):\n                await self._writer\n\n    def terminate(self) -> None:\n        if self._writer is not None:\n            if not self.loop.is_closed():\n                self._writer.cancel()\n            self._writer.remove_done_callback(self.__reset_writer)\n            self._writer = None\n\n    async def _on_chunk_request_sent(self, method: str, url: URL, chunk: bytes) -> None:\n        for trace in self._traces:\n            await trace.send_request_chunk_sent(method, url, chunk)\n\n    async def _on_headers_request_sent(\n        self, method: str, url: URL, headers: \"CIMultiDict[str]\"\n    ) -> None:\n        for trace in self._traces:\n            await trace.send_request_headers(method, url, headers)\n\n\nclass ClientResponse(HeadersMixin):\n\n    # Some of these attributes are None when created,\n    # but will be set by the start() method.\n    # As the end user will likely never see the None values, we cheat the types below.\n    # from the Status-Line of the response\n    version: Optional[HttpVersion] = None  # HTTP-Version\n    status: int = None  # type: ignore[assignment] # Status-Code\n    reason: Optional[str] = None  # Reason-Phrase\n\n    content: StreamReader = None  # type: ignore[assignment]  # Payload stream\n    _headers: CIMultiDictProxy[str] = None  # type: ignore[assignment]\n    _raw_headers: RawHeaders = None  # type: ignore[assignment]\n\n    _connection = None  # current connection\n    _source_traceback: Optional[traceback.StackSummary] = None\n    # set up by ClientRequest after ClientResponse object creation\n    # post-init stage allows to not change ctor signature\n    _closed = True  # to allow __del__ for non-initialized properly response\n    _released = False\n    __writer = None\n\n    def __init__(\n        self,\n        method: str,\n        url: URL,\n        *,\n        writer: \"asyncio.Task[None]\",\n        continue100: Optional[\"asyncio.Future[bool]\"],\n        timer: BaseTimerContext,\n        request_info: RequestInfo,\n        traces: List[\"Trace\"],\n        loop: asyncio.AbstractEventLoop,\n        session: \"ClientSession\",\n    ) -> None:\n        assert isinstance(url, URL)\n\n        self.method = method\n        self.cookies = SimpleCookie()\n\n        self._real_url = url\n        self._url = url.with_fragment(None)\n        self._body: Any = None\n        self._writer: Optional[asyncio.Task[None]] = writer\n        self._continue = continue100  # None by default\n        self._closed = True\n        self._history: Tuple[ClientResponse, ...] = ()\n        self._request_info = request_info\n        self._timer = timer if timer is not None else TimerNoop()\n        self._cache: Dict[str, Any] = {}\n        self._traces = traces\n        self._loop = loop\n        # store a reference to session #1985\n        self._session: Optional[ClientSession] = session\n        # Save reference to _resolve_charset, so that get_encoding() will still\n        # work after the response has finished reading the body.\n        if session is None:\n            # TODO: Fix session=None in tests (see ClientRequest.__init__).\n            self._resolve_charset: Callable[[\"ClientResponse\", bytes], str] = (\n                lambda *_: \"utf-8\"\n            )\n        else:\n            self._resolve_charset = session._resolve_charset\n        if loop.get_debug():\n            self._source_traceback = traceback.extract_stack(sys._getframe(1))\n\n    def __reset_writer(self, _: object = None) -> None:\n        self.__writer = None\n\n    @property\n    def _writer(self) -> Optional[\"asyncio.Task[None]\"]:\n        return self.__writer\n\n    @_writer.setter\n    def _writer(self, writer: Optional[\"asyncio.Task[None]\"]) -> None:\n        if self.__writer is not None:\n            self.__writer.remove_done_callback(self.__reset_writer)\n        self.__writer = writer\n        if writer is None:\n            return\n        if writer.done():\n            # The writer is already done, so we can reset it immediately.\n            self.__reset_writer()\n        else:\n            writer.add_done_callback(self.__reset_writer)\n\n    @reify\n    def url(self) -> URL:\n        return self._url\n\n    @reify\n    def url_obj(self) -> URL:\n        warnings.warn(\"Deprecated, use .url #1654\", DeprecationWarning, stacklevel=2)\n        return self._url\n\n    @reify\n    def real_url(self) -> URL:\n        return self._real_url\n\n    @reify\n    def host(self) -> str:\n        assert self._url.host is not None\n        return self._url.host\n\n    @reify\n    def headers(self) -> \"CIMultiDictProxy[str]\":\n        return self._headers\n\n    @reify\n    def raw_headers(self) -> RawHeaders:\n        return self._raw_headers\n\n    @reify\n    def request_info(self) -> RequestInfo:\n        return self._request_info\n\n    @reify\n    def content_disposition(self) -> Optional[ContentDisposition]:\n        raw = self._headers.get(hdrs.CONTENT_DISPOSITION)\n        if raw is None:\n            return None\n        disposition_type, params_dct = multipart.parse_content_disposition(raw)\n        params = MappingProxyType(params_dct)\n        filename = multipart.content_disposition_filename(params)\n        return ContentDisposition(disposition_type, params, filename)\n\n    def __del__(self, _warnings: Any = warnings) -> None:\n        if self._closed:\n            return\n\n        if self._connection is not None:\n            self._connection.release()\n            self._cleanup_writer()\n\n            if self._loop.get_debug():\n                kwargs = {\"source\": self}\n                _warnings.warn(f\"Unclosed response {self!r}\", ResourceWarning, **kwargs)\n                context = {\"client_response\": self, \"message\": \"Unclosed response\"}\n                if self._source_traceback:\n                    context[\"source_traceback\"] = self._source_traceback\n                self._loop.call_exception_handler(context)\n\n    def __repr__(self) -> str:\n        out = io.StringIO()\n        ascii_encodable_url = str(self.url)\n        if self.reason:\n            ascii_encodable_reason = self.reason.encode(\n                \"ascii\", \"backslashreplace\"\n            ).decode(\"ascii\")\n        else:\n            ascii_encodable_reason = \"None\"\n        print(\n            \"<ClientResponse({}) [{} {}]>\".format(\n                ascii_encodable_url, self.status, ascii_encodable_reason\n            ),\n            file=out,\n        )\n        print(self.headers, file=out)\n        return out.getvalue()\n\n    @property\n    def connection(self) -> Optional[\"Connection\"]:\n        return self._connection\n\n    @reify\n    def history(self) -> Tuple[\"ClientResponse\", ...]:\n        \"\"\"A sequence of of responses, if redirects occurred.\"\"\"\n        return self._history\n\n    @reify\n    def links(self) -> \"MultiDictProxy[MultiDictProxy[Union[str, URL]]]\":\n        links_str = \", \".join(self.headers.getall(\"link\", []))\n\n        if not links_str:\n            return MultiDictProxy(MultiDict())\n\n        links: MultiDict[MultiDictProxy[Union[str, URL]]] = MultiDict()\n\n        for val in re.split(r\",(?=\\s*<)\", links_str):\n            match = re.match(r\"\\s*<(.*)>(.*)\", val)\n            if match is None:  # pragma: no cover\n                # the check exists to suppress mypy error\n                continue\n            url, params_str = match.groups()\n            params = params_str.split(\";\")[1:]\n\n            link: MultiDict[Union[str, URL]] = MultiDict()\n\n            for param in params:\n                match = re.match(r\"^\\s*(\\S*)\\s*=\\s*(['\\\"]?)(.*?)(\\2)\\s*$\", param, re.M)\n                if match is None:  # pragma: no cover\n                    # the check exists to suppress mypy error\n                    continue\n                key, _, value, _ = match.groups()\n\n                link.add(key, value)\n\n            key = link.get(\"rel\", url)\n\n            link.add(\"url\", self.url.join(URL(url)))\n\n            links.add(str(key), MultiDictProxy(link))\n\n        return MultiDictProxy(links)\n\n    async def start(self, connection: \"Connection\") -> \"ClientResponse\":\n        \"\"\"Start response processing.\"\"\"\n        self._closed = False\n        self._protocol = connection.protocol\n        self._connection = connection\n\n        with self._timer:\n            while True:\n                # read response\n                try:\n                    protocol = self._protocol\n                    message, payload = await protocol.read()  # type: ignore[union-attr]\n                except http.HttpProcessingError as exc:\n                    raise ClientResponseError(\n                        self.request_info,\n                        self.history,\n                        status=exc.code,\n                        message=exc.message,\n                        headers=exc.headers,\n                    ) from exc\n\n                if message.code < 100 or message.code > 199 or message.code == 101:\n                    break\n\n                if self._continue is not None:\n                    set_result(self._continue, True)\n                    self._continue = None\n\n        # payload eof handler\n        payload.on_eof(self._response_eof)\n\n        # response status\n        self.version = message.version\n        self.status = message.code\n        self.reason = message.reason\n\n        # headers\n        self._headers = message.headers  # type is CIMultiDictProxy\n        self._raw_headers = message.raw_headers  # type is Tuple[bytes, bytes]\n\n        # payload\n        self.content = payload\n\n        # cookies\n        for hdr in self.headers.getall(hdrs.SET_COOKIE, ()):\n            try:\n                self.cookies.load(hdr)\n            except CookieError as exc:\n                client_logger.warning(\"Can not load response cookies: %s\", exc)\n        return self\n\n    def _response_eof(self) -> None:\n        if self._closed:\n            return\n\n        # protocol could be None because connection could be detached\n        protocol = self._connection and self._connection.protocol\n        if protocol is not None and protocol.upgraded:\n            return\n\n        self._closed = True\n        self._cleanup_writer()\n        self._release_connection()\n\n    @property\n    def closed(self) -> bool:\n        return self._closed\n\n    def close(self) -> None:\n        if not self._released:\n            self._notify_content()\n\n        self._closed = True\n        if self._loop is None or self._loop.is_closed():\n            return\n\n        self._cleanup_writer()\n        if self._connection is not None:\n            self._connection.close()\n            self._connection = None\n\n    def release(self) -> Any:\n        if not self._released:\n            self._notify_content()\n\n        self._closed = True\n\n        self._cleanup_writer()\n        self._release_connection()\n        return noop()\n\n    @property\n    def ok(self) -> bool:\n        \"\"\"Returns ``True`` if ``status`` is less than ``400``, ``False`` if not.\n\n        This is **not** a check for ``200 OK`` but a check that the response\n        status is under 400.\n        \"\"\"\n        return 400 > self.status\n\n    def raise_for_status(self) -> None:\n        if not self.ok:\n            # reason should always be not None for a started response\n            assert self.reason is not None\n            self.release()\n            raise ClientResponseError(\n                self.request_info,\n                self.history,\n                status=self.status,\n                message=self.reason,\n                headers=self.headers,\n            )\n\n    def _release_connection(self) -> None:\n        if self._connection is not None:\n            if self._writer is None:\n                self._connection.release()\n                self._connection = None\n            else:\n                self._writer.add_done_callback(lambda f: self._release_connection())\n\n    async def _wait_released(self) -> None:\n        if self._writer is not None:\n            await self._writer\n        self._release_connection()\n\n    def _cleanup_writer(self) -> None:\n        if self._writer is not None:\n            self._writer.cancel()\n        self._session = None\n\n    def _notify_content(self) -> None:\n        content = self.content\n        if content and content.exception() is None:\n            set_exception(content, ClientConnectionError(\"Connection closed\"))\n        self._released = True\n\n    async def wait_for_close(self) -> None:\n        if self._writer is not None:\n            await self._writer\n        self.release()\n\n    async def read(self) -> bytes:\n        \"\"\"Read response payload.\"\"\"\n        if self._body is None:\n            try:\n                self._body = await self.content.read()\n                for trace in self._traces:\n                    await trace.send_response_chunk_received(\n                        self.method, self.url, self._body\n                    )\n            except BaseException:\n                self.close()\n                raise\n        elif self._released:  # Response explicitly released\n            raise ClientConnectionError(\"Connection closed\")\n\n        protocol = self._connection and self._connection.protocol\n        if protocol is None or not protocol.upgraded:\n            await self._wait_released()  # Underlying connection released\n        return self._body  # type: ignore[no-any-return]\n\n    def get_encoding(self) -> str:\n        ctype = self.headers.get(hdrs.CONTENT_TYPE, \"\").lower()\n        mimetype = helpers.parse_mimetype(ctype)\n\n        encoding = mimetype.parameters.get(\"charset\")\n        if encoding:\n            with contextlib.suppress(LookupError):\n                return codecs.lookup(encoding).name\n\n        if mimetype.type == \"application\" and (\n            mimetype.subtype == \"json\" or mimetype.subtype == \"rdap\"\n        ):\n            # RFC 7159 states that the default encoding is UTF-8.\n            # RFC 7483 defines application/rdap+json\n            return \"utf-8\"\n\n        if self._body is None:\n            raise RuntimeError(\n                \"Cannot compute fallback encoding of a not yet read body\"\n            )\n\n        return self._resolve_charset(self, self._body)\n\n    async def text(self, encoding: Optional[str] = None, errors: str = \"strict\") -> str:\n        \"\"\"Read response payload and decode.\"\"\"\n        if self._body is None:\n            await self.read()\n\n        if encoding is None:\n            encoding = self.get_encoding()\n\n        return self._body.decode(  # type: ignore[no-any-return,union-attr]\n            encoding, errors=errors\n        )\n\n    async def json(\n        self,\n        *,\n        encoding: Optional[str] = None,\n        loads: JSONDecoder = DEFAULT_JSON_DECODER,\n        content_type: Optional[str] = \"application/json\",\n    ) -> Any:\n        \"\"\"Read and decodes JSON response.\"\"\"\n        if self._body is None:\n            await self.read()\n\n        if content_type:\n            ctype = self.headers.get(hdrs.CONTENT_TYPE, \"\").lower()\n            if not _is_expected_content_type(ctype, content_type):\n                raise ContentTypeError(\n                    self.request_info,\n                    self.history,\n                    status=self.status,\n                    message=(\n                        \"Attempt to decode JSON with \" \"unexpected mimetype: %s\" % ctype\n                    ),\n                    headers=self.headers,\n                )\n\n        stripped = self._body.strip()  # type: ignore[union-attr]\n        if not stripped:\n            return None\n\n        if encoding is None:\n            encoding = self.get_encoding()\n\n        return loads(stripped.decode(encoding))\n\n    async def __aenter__(self) -> \"ClientResponse\":\n        return self\n\n    async def __aexit__(\n        self,\n        exc_type: Optional[Type[BaseException]],\n        exc_val: Optional[BaseException],\n        exc_tb: Optional[TracebackType],\n    ) -> None:\n        # similar to _RequestContextManager, we do not need to check\n        # for exceptions, response object can close connection\n        # if state is broken\n        self.release()\n        await self.wait_for_close()\n",
            "header": {
                "file": {
                    "path": "aiohttp/client_reqrep.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "933f3275",
                "new_commit_hash": "d2c5f16d",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/aiohttp/client_reqrep.py"
            },
            "plus_file": {
                "path": "b/aiohttp/client_reqrep.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 659,
                            "length": 7
                        },
                        "new_range": {
                            "start": 659,
                            "length": 8
                        },
                        "section": "class ClientRequest:"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "            set_exception(protocol, reraised_exc, underlying_exc)",
                                "type": "context"
                            },
                            {
                                "content": "        except asyncio.CancelledError:",
                                "type": "context"
                            },
                            {
                                "content": "            await writer.write_eof()",
                                "type": "deleted"
                            },
                            {
                                "content": "            # Body hasn't been fully sent, so connection can't be reused.",
                                "type": "added"
                            },
                            {
                                "content": "            conn.close()",
                                "type": "added"
                            },
                            {
                                "content": "        except Exception as underlying_exc:",
                                "type": "context"
                            },
                            {
                                "content": "            set_exception(",
                                "type": "context"
                            },
                            {
                                "content": "                protocol,",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "aiohttp/client_reqrep.py",
                            "type": "method",
                            "name": "ClientRequest.write_bytes",
                            "content": "class ClientRequest:\n    GET_METHODS = {\n        hdrs.METH_GET,\n        hdrs.METH_HEAD,\n        hdrs.METH_OPTIONS,\n        hdrs.METH_TRACE,\n    }\n    POST_METHODS = {hdrs.METH_PATCH, hdrs.METH_POST, hdrs.METH_PUT}\n    ALL_METHODS = GET_METHODS.union(POST_METHODS).union({hdrs.METH_DELETE})\n\n    DEFAULT_HEADERS = {\n        hdrs.ACCEPT: \"*/*\",\n        hdrs.ACCEPT_ENCODING: _gen_default_accept_encoding(),\n    }\n\n    # Type of body depends on PAYLOAD_REGISTRY, which is dynamic.\n    body: Any = b\"\"\n    auth = None\n    response = None\n\n    __writer = None  # async task for streaming data\n    _continue = None  # waiter future for '100 Continue' response\n\n    # N.B.\n    # Adding __del__ method with self._writer closing doesn't make sense\n    # because _writer is instance method, thus it keeps a reference to self.\n    # Until writer has finished finalizer will not be called.\n\n    def __init__(\n        self,\n        method: str,\n        url: URL,\n        *,\n        params: Optional[Mapping[str, str]] = None,\n        headers: Optional[LooseHeaders] = None,\n        skip_auto_headers: Optional[Iterable[str]] = None,\n        data: Any = None,\n        cookies: Optional[LooseCookies] = None,\n        auth: Optional[BasicAuth] = None,\n        version: http.HttpVersion = http.HttpVersion11,\n        compress: Optional[str] = None,\n        chunked: Optional[bool] = None,\n        expect100: bool = False,\n        loop: Optional[asyncio.AbstractEventLoop] = None,\n        response_class: Optional[Type[\"ClientResponse\"]] = None,\n        proxy: Optional[URL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        timer: Optional[BaseTimerContext] = None,\n        session: Optional[\"ClientSession\"] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        proxy_headers: Optional[LooseHeaders] = None,\n        traces: Optional[List[\"Trace\"]] = None,\n        trust_env: bool = False,\n        server_hostname: Optional[str] = None,\n    ):\n        if loop is None:\n            loop = asyncio.get_event_loop()\n\n        match = _CONTAINS_CONTROL_CHAR_RE.search(method)\n        if match:\n            raise ValueError(\n                f\"Method cannot contain non-token characters {method!r} \"\n                \"(found at least {match.group()!r})\"\n            )\n\n        assert isinstance(url, URL), url\n        assert isinstance(proxy, (URL, type(None))), proxy\n        # FIXME: session is None in tests only, need to fix tests\n        # assert session is not None\n        self._session = cast(\"ClientSession\", session)\n        if params:\n            q = MultiDict(url.query)\n            url2 = url.with_query(params)\n            q.extend(url2.query)\n            url = url.with_query(q)\n        self.original_url = url\n        self.url = url.with_fragment(None)\n        self.method = method.upper()\n        self.chunked = chunked\n        self.compress = compress\n        self.loop = loop\n        self.length = None\n        if response_class is None:\n            real_response_class = ClientResponse\n        else:\n            real_response_class = response_class\n        self.response_class: Type[ClientResponse] = real_response_class\n        self._timer = timer if timer is not None else TimerNoop()\n        self._ssl = ssl if ssl is not None else True\n        self.server_hostname = server_hostname\n\n        if loop.get_debug():\n            self._source_traceback = traceback.extract_stack(sys._getframe(1))\n\n        self.update_version(version)\n        self.update_host(url)\n        self.update_headers(headers)\n        self.update_auto_headers(skip_auto_headers)\n        self.update_cookies(cookies)\n        self.update_content_encoding(data)\n        self.update_auth(auth, trust_env)\n        self.update_proxy(proxy, proxy_auth, proxy_headers)\n\n        self.update_body_from_data(data)\n        if data is not None or self.method not in self.GET_METHODS:\n            self.update_transfer_encoding()\n        self.update_expect_continue(expect100)\n        if traces is None:\n            traces = []\n        self._traces = traces\n\n    def __reset_writer(self, _: object = None) -> None:\n        self.__writer = None\n\n    @property\n    def _writer(self) -> Optional[\"asyncio.Task[None]\"]:\n        return self.__writer\n\n    @_writer.setter\n    def _writer(self, writer: Optional[\"asyncio.Task[None]\"]) -> None:\n        if self.__writer is not None:\n            self.__writer.remove_done_callback(self.__reset_writer)\n        self.__writer = writer\n        if writer is None:\n            return\n        if writer.done():\n            # The writer is already done, so we can reset it immediately.\n            self.__reset_writer()\n        else:\n            writer.add_done_callback(self.__reset_writer)\n\n    def is_ssl(self) -> bool:\n        return self.url.scheme in (\"https\", \"wss\")\n\n    @property\n    def ssl(self) -> Union[\"SSLContext\", bool, Fingerprint]:\n        return self._ssl\n\n    @property\n    def connection_key(self) -> ConnectionKey:\n        proxy_headers = self.proxy_headers\n        if proxy_headers:\n            h: Optional[int] = hash(tuple((k, v) for k, v in proxy_headers.items()))\n        else:\n            h = None\n        return ConnectionKey(\n            self.host,\n            self.port,\n            self.is_ssl(),\n            self.ssl,\n            self.proxy,\n            self.proxy_auth,\n            h,\n        )\n\n    @property\n    def host(self) -> str:\n        ret = self.url.raw_host\n        assert ret is not None\n        return ret\n\n    @property\n    def port(self) -> Optional[int]:\n        return self.url.port\n\n    @property\n    def request_info(self) -> RequestInfo:\n        headers: CIMultiDictProxy[str] = CIMultiDictProxy(self.headers)\n        return RequestInfo(self.url, self.method, headers, self.original_url)\n\n    def update_host(self, url: URL) -> None:\n        \"\"\"Update destination host, port and connection type (ssl).\"\"\"\n        # get host/port\n        if not url.raw_host:\n            raise InvalidURL(url)\n\n        # basic auth info\n        username, password = url.user, url.password\n        if username or password:\n            self.auth = helpers.BasicAuth(username or \"\", password or \"\")\n\n    def update_version(self, version: Union[http.HttpVersion, str]) -> None:\n        \"\"\"Convert request version to two elements tuple.\n\n        parser HTTP version '1.1' => (1, 1)\n        \"\"\"\n        if isinstance(version, str):\n            v = [part.strip() for part in version.split(\".\", 1)]\n            try:\n                version = http.HttpVersion(int(v[0]), int(v[1]))\n            except ValueError:\n                raise ValueError(\n                    f\"Can not parse http version number: {version}\"\n                ) from None\n        self.version = version\n\n    def update_headers(self, headers: Optional[LooseHeaders]) -> None:\n        \"\"\"Update request headers.\"\"\"\n        self.headers: CIMultiDict[str] = CIMultiDict()\n\n        # add host\n        netloc = cast(str, self.url.raw_host)\n        if helpers.is_ipv6_address(netloc):\n            netloc = f\"[{netloc}]\"\n        # See https://github.com/aio-libs/aiohttp/issues/3636.\n        netloc = netloc.rstrip(\".\")\n        if self.url.port is not None and not self.url.is_default_port():\n            netloc += \":\" + str(self.url.port)\n        self.headers[hdrs.HOST] = netloc\n\n        if headers:\n            if isinstance(headers, (dict, MultiDictProxy, MultiDict)):\n                headers = headers.items()\n\n            for key, value in headers:  # type: ignore[misc]\n                # A special case for Host header\n                if key.lower() == \"host\":\n                    self.headers[key] = value\n                else:\n                    self.headers.add(key, value)\n\n    def update_auto_headers(self, skip_auto_headers: Optional[Iterable[str]]) -> None:\n        if skip_auto_headers is not None:\n            self.skip_auto_headers = CIMultiDict(\n                (hdr, None) for hdr in sorted(skip_auto_headers)\n            )\n            used_headers = self.headers.copy()\n            used_headers.extend(self.skip_auto_headers)  # type: ignore[arg-type]\n        else:\n            # Fast path when there are no headers to skip\n            # which is the most common case.\n            self.skip_auto_headers = CIMultiDict()\n            used_headers = self.headers\n\n        for hdr, val in self.DEFAULT_HEADERS.items():\n            if hdr not in used_headers:\n                self.headers.add(hdr, val)\n\n        if hdrs.USER_AGENT not in used_headers:\n            self.headers[hdrs.USER_AGENT] = SERVER_SOFTWARE\n\n    def update_cookies(self, cookies: Optional[LooseCookies]) -> None:\n        \"\"\"Update request cookies header.\"\"\"\n        if not cookies:\n            return\n\n        c = SimpleCookie()\n        if hdrs.COOKIE in self.headers:\n            c.load(self.headers.get(hdrs.COOKIE, \"\"))\n            del self.headers[hdrs.COOKIE]\n\n        if isinstance(cookies, Mapping):\n            iter_cookies = cookies.items()\n        else:\n            iter_cookies = cookies  # type: ignore[assignment]\n        for name, value in iter_cookies:\n            if isinstance(value, Morsel):\n                # Preserve coded_value\n                mrsl_val = value.get(value.key, Morsel())\n                mrsl_val.set(value.key, value.value, value.coded_value)\n                c[name] = mrsl_val\n            else:\n                c[name] = value  # type: ignore[assignment]\n\n        self.headers[hdrs.COOKIE] = c.output(header=\"\", sep=\";\").strip()\n\n    def update_content_encoding(self, data: Any) -> None:\n        \"\"\"Set request content encoding.\"\"\"\n        if data is None:\n            return\n\n        enc = self.headers.get(hdrs.CONTENT_ENCODING, \"\").lower()\n        if enc:\n            if self.compress:\n                raise ValueError(\n                    \"compress can not be set \" \"if Content-Encoding header is set\"\n                )\n        elif self.compress:\n            if not isinstance(self.compress, str):\n                self.compress = \"deflate\"\n            self.headers[hdrs.CONTENT_ENCODING] = self.compress\n            self.chunked = True  # enable chunked, no need to deal with length\n\n    def update_transfer_encoding(self) -> None:\n        \"\"\"Analyze transfer-encoding header.\"\"\"\n        te = self.headers.get(hdrs.TRANSFER_ENCODING, \"\").lower()\n\n        if \"chunked\" in te:\n            if self.chunked:\n                raise ValueError(\n                    \"chunked can not be set \"\n                    'if \"Transfer-Encoding: chunked\" header is set'\n                )\n\n        elif self.chunked:\n            if hdrs.CONTENT_LENGTH in self.headers:\n                raise ValueError(\n                    \"chunked can not be set \" \"if Content-Length header is set\"\n                )\n\n            self.headers[hdrs.TRANSFER_ENCODING] = \"chunked\"\n        else:\n            if hdrs.CONTENT_LENGTH not in self.headers:\n                self.headers[hdrs.CONTENT_LENGTH] = str(len(self.body))\n\n    def update_auth(self, auth: Optional[BasicAuth], trust_env: bool = False) -> None:\n        \"\"\"Set basic auth.\"\"\"\n        if auth is None:\n            auth = self.auth\n        if auth is None and trust_env and self.url.host is not None:\n            netrc_obj = netrc_from_env()\n            with contextlib.suppress(LookupError):\n                auth = basicauth_from_netrc(netrc_obj, self.url.host)\n        if auth is None:\n            return\n\n        if not isinstance(auth, helpers.BasicAuth):\n            raise TypeError(\"BasicAuth() tuple is required instead\")\n\n        self.headers[hdrs.AUTHORIZATION] = auth.encode()\n\n    def update_body_from_data(self, body: Any) -> None:\n        if body is None:\n            return\n\n        # FormData\n        if isinstance(body, FormData):\n            body = body()\n\n        try:\n            body = payload.PAYLOAD_REGISTRY.get(body, disposition=None)\n        except payload.LookupError:\n            body = FormData(body)()\n\n        self.body = body\n\n        # enable chunked encoding if needed\n        if not self.chunked:\n            if hdrs.CONTENT_LENGTH not in self.headers:\n                size = body.size\n                if size is None:\n                    self.chunked = True\n                else:\n                    if hdrs.CONTENT_LENGTH not in self.headers:\n                        self.headers[hdrs.CONTENT_LENGTH] = str(size)\n\n        # copy payload headers\n        assert body.headers\n        for key, value in body.headers.items():\n            if key in self.headers or key in self.skip_auto_headers:\n                continue\n            self.headers[key] = value\n\n    def update_expect_continue(self, expect: bool = False) -> None:\n        if expect:\n            self.headers[hdrs.EXPECT] = \"100-continue\"\n        elif self.headers.get(hdrs.EXPECT, \"\").lower() == \"100-continue\":\n            expect = True\n\n        if expect:\n            self._continue = self.loop.create_future()\n\n    def update_proxy(\n        self,\n        proxy: Optional[URL],\n        proxy_auth: Optional[BasicAuth],\n        proxy_headers: Optional[LooseHeaders],\n    ) -> None:\n        if proxy_auth and not isinstance(proxy_auth, helpers.BasicAuth):\n            raise ValueError(\"proxy_auth must be None or BasicAuth() tuple\")\n        self.proxy = proxy\n        self.proxy_auth = proxy_auth\n        if proxy_headers is not None and not isinstance(\n            proxy_headers, (MultiDict, MultiDictProxy)\n        ):\n            proxy_headers = CIMultiDict(proxy_headers)\n        self.proxy_headers = proxy_headers\n\n    def keep_alive(self) -> bool:\n        if self.version < HttpVersion10:\n            # keep alive not supported at all\n            return False\n        if self.version == HttpVersion10:\n            if self.headers.get(hdrs.CONNECTION) == \"keep-alive\":\n                return True\n            else:  # no headers means we close for Http 1.0\n                return False\n        elif self.headers.get(hdrs.CONNECTION) == \"close\":\n            return False\n\n        return True\n\n    async def write_bytes(\n        self, writer: AbstractStreamWriter, conn: \"Connection\"\n    ) -> None:\n        \"\"\"Support coroutines that yields bytes objects.\"\"\"\n        # 100 response\n        if self._continue is not None:\n            try:\n                await writer.drain()\n                await self._continue\n            except asyncio.CancelledError:\n                return\n\n        protocol = conn.protocol\n        assert protocol is not None\n        try:\n            if isinstance(self.body, payload.Payload):\n                await self.body.write(writer)\n            else:\n                if isinstance(self.body, (bytes, bytearray)):\n                    self.body = (self.body,)\n\n                for chunk in self.body:\n                    await writer.write(chunk)\n        except OSError as underlying_exc:\n            reraised_exc = underlying_exc\n\n            exc_is_not_timeout = underlying_exc.errno is not None or not isinstance(\n                underlying_exc, asyncio.TimeoutError\n            )\n            if exc_is_not_timeout:\n                reraised_exc = ClientOSError(\n                    underlying_exc.errno,\n                    f\"Can not write request body for {self.url !s}\",\n                )\n\n            set_exception(protocol, reraised_exc, underlying_exc)\n        except asyncio.CancelledError:\n            await writer.write_eof()\n        except Exception as underlying_exc:\n            set_exception(\n                protocol,\n                ClientConnectionError(\n                    f\"Failed to send bytes into the underlying connection {conn !s}\",\n                ),\n                underlying_exc,\n            )\n        else:\n            await writer.write_eof()\n            protocol.start_timeout()\n\n    async def send(self, conn: \"Connection\") -> \"ClientResponse\":\n        # Specify request target:\n        # - CONNECT request must send authority form URI\n        # - not CONNECT proxy must send absolute form URI\n        # - most common is origin form URI\n        if self.method == hdrs.METH_CONNECT:\n            connect_host = self.url.raw_host\n            assert connect_host is not None\n            if helpers.is_ipv6_address(connect_host):\n                connect_host = f\"[{connect_host}]\"\n            path = f\"{connect_host}:{self.url.port}\"\n        elif self.proxy and not self.is_ssl():\n            path = str(self.url)\n        else:\n            path = self.url.raw_path\n            if self.url.raw_query_string:\n                path += \"?\" + self.url.raw_query_string\n\n        protocol = conn.protocol\n        assert protocol is not None\n        writer = StreamWriter(\n            protocol,\n            self.loop,\n            on_chunk_sent=functools.partial(\n                self._on_chunk_request_sent, self.method, self.url\n            ),\n            on_headers_sent=functools.partial(\n                self._on_headers_request_sent, self.method, self.url\n            ),\n        )\n\n        if self.compress:\n            writer.enable_compression(self.compress)\n\n        if self.chunked is not None:\n            writer.enable_chunking()\n\n        # set default content-type\n        if (\n            self.method in self.POST_METHODS\n            and hdrs.CONTENT_TYPE not in self.skip_auto_headers\n            and hdrs.CONTENT_TYPE not in self.headers\n        ):\n            self.headers[hdrs.CONTENT_TYPE] = \"application/octet-stream\"\n\n        # set the connection header\n        connection = self.headers.get(hdrs.CONNECTION)\n        if not connection:\n            if self.keep_alive():\n                if self.version == HttpVersion10:\n                    connection = \"keep-alive\"\n            else:\n                if self.version == HttpVersion11:\n                    connection = \"close\"\n\n        if connection is not None:\n            self.headers[hdrs.CONNECTION] = connection\n\n        # status + headers\n        v = self.version\n        status_line = f\"{self.method} {path} HTTP/{v.major}.{v.minor}\"\n        await writer.write_headers(status_line, self.headers)\n        coro = self.write_bytes(writer, conn)\n\n        if sys.version_info >= (3, 12):\n            # Optimization for Python 3.12, try to write\n            # bytes immediately to avoid having to schedule\n            # the task on the event loop.\n            task = asyncio.Task(coro, loop=self.loop, eager_start=True)\n        else:\n            task = self.loop.create_task(coro)\n\n        self._writer = task\n        response_class = self.response_class\n        assert response_class is not None\n        self.response = response_class(\n            self.method,\n            self.original_url,\n            writer=self._writer,\n            continue100=self._continue,\n            timer=self._timer,\n            request_info=self.request_info,\n            traces=self._traces,\n            loop=self.loop,\n            session=self._session,\n        )\n        return self.response\n\n    async def close(self) -> None:\n        if self._writer is not None:\n            with contextlib.suppress(asyncio.CancelledError):\n                await self._writer\n\n    def terminate(self) -> None:\n        if self._writer is not None:\n            if not self.loop.is_closed():\n                self._writer.cancel()\n            self._writer.remove_done_callback(self.__reset_writer)\n            self._writer = None\n\n    async def _on_chunk_request_sent(self, method: str, url: URL, chunk: bytes) -> None:\n        for trace in self._traces:\n            await trace.send_request_chunk_sent(method, url, chunk)\n\n    async def _on_headers_request_sent(\n        self, method: str, url: URL, headers: \"CIMultiDict[str]\"\n    ) -> None:\n        for trace in self._traces:\n            await trace.send_request_headers(method, url, headers)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 625,
                            "end_lineno": 673,
                            "parent": {
                                "file_name": "aiohttp/client_reqrep.py",
                                "type": "class",
                                "name": "ClientRequest",
                                "content": "class ClientRequest:\n    GET_METHODS = {\n        hdrs.METH_GET,\n        hdrs.METH_HEAD,\n        hdrs.METH_OPTIONS,\n        hdrs.METH_TRACE,\n    }\n    POST_METHODS = {hdrs.METH_PATCH, hdrs.METH_POST, hdrs.METH_PUT}\n    ALL_METHODS = GET_METHODS.union(POST_METHODS).union({hdrs.METH_DELETE})\n\n    DEFAULT_HEADERS = {\n        hdrs.ACCEPT: \"*/*\",\n        hdrs.ACCEPT_ENCODING: _gen_default_accept_encoding(),\n    }\n\n    # Type of body depends on PAYLOAD_REGISTRY, which is dynamic.\n    body: Any = b\"\"\n    auth = None\n    response = None\n\n    __writer = None  # async task for streaming data\n    _continue = None  # waiter future for '100 Continue' response\n\n    # N.B.\n    # Adding __del__ method with self._writer closing doesn't make sense\n    # because _writer is instance method, thus it keeps a reference to self.\n    # Until writer has finished finalizer will not be called.\n\n    def __init__(\n        self,\n        method: str,\n        url: URL,\n        *,\n        params: Optional[Mapping[str, str]] = None,\n        headers: Optional[LooseHeaders] = None,\n        skip_auto_headers: Optional[Iterable[str]] = None,\n        data: Any = None,\n        cookies: Optional[LooseCookies] = None,\n        auth: Optional[BasicAuth] = None,\n        version: http.HttpVersion = http.HttpVersion11,\n        compress: Optional[str] = None,\n        chunked: Optional[bool] = None,\n        expect100: bool = False,\n        loop: Optional[asyncio.AbstractEventLoop] = None,\n        response_class: Optional[Type[\"ClientResponse\"]] = None,\n        proxy: Optional[URL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        timer: Optional[BaseTimerContext] = None,\n        session: Optional[\"ClientSession\"] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        proxy_headers: Optional[LooseHeaders] = None,\n        traces: Optional[List[\"Trace\"]] = None,\n        trust_env: bool = False,\n        server_hostname: Optional[str] = None,\n    ):\n        if loop is None:\n            loop = asyncio.get_event_loop()\n\n        match = _CONTAINS_CONTROL_CHAR_RE.search(method)\n        if match:\n            raise ValueError(\n                f\"Method cannot contain non-token characters {method!r} \"\n                \"(found at least {match.group()!r})\"\n            )\n\n        assert isinstance(url, URL), url\n        assert isinstance(proxy, (URL, type(None))), proxy\n        # FIXME: session is None in tests only, need to fix tests\n        # assert session is not None\n        self._session = cast(\"ClientSession\", session)\n        if params:\n            q = MultiDict(url.query)\n            url2 = url.with_query(params)\n            q.extend(url2.query)\n            url = url.with_query(q)\n        self.original_url = url\n        self.url = url.with_fragment(None)\n        self.method = method.upper()\n        self.chunked = chunked\n        self.compress = compress\n        self.loop = loop\n        self.length = None\n        if response_class is None:\n            real_response_class = ClientResponse\n        else:\n            real_response_class = response_class\n        self.response_class: Type[ClientResponse] = real_response_class\n        self._timer = timer if timer is not None else TimerNoop()\n        self._ssl = ssl if ssl is not None else True\n        self.server_hostname = server_hostname\n\n        if loop.get_debug():\n            self._source_traceback = traceback.extract_stack(sys._getframe(1))\n\n        self.update_version(version)\n        self.update_host(url)\n        self.update_headers(headers)\n        self.update_auto_headers(skip_auto_headers)\n        self.update_cookies(cookies)\n        self.update_content_encoding(data)\n        self.update_auth(auth, trust_env)\n        self.update_proxy(proxy, proxy_auth, proxy_headers)\n\n        self.update_body_from_data(data)\n        if data is not None or self.method not in self.GET_METHODS:\n            self.update_transfer_encoding()\n        self.update_expect_continue(expect100)\n        if traces is None:\n            traces = []\n        self._traces = traces\n\n    def __reset_writer(self, _: object = None) -> None:\n        self.__writer = None\n\n    @property\n    def _writer(self) -> Optional[\"asyncio.Task[None]\"]:\n        return self.__writer\n\n    @_writer.setter\n    def _writer(self, writer: Optional[\"asyncio.Task[None]\"]) -> None:\n        if self.__writer is not None:\n            self.__writer.remove_done_callback(self.__reset_writer)\n        self.__writer = writer\n        if writer is None:\n            return\n        if writer.done():\n            # The writer is already done, so we can reset it immediately.\n            self.__reset_writer()\n        else:\n            writer.add_done_callback(self.__reset_writer)\n\n    def is_ssl(self) -> bool:\n        return self.url.scheme in (\"https\", \"wss\")\n\n    @property\n    def ssl(self) -> Union[\"SSLContext\", bool, Fingerprint]:\n        return self._ssl\n\n    @property\n    def connection_key(self) -> ConnectionKey:\n        proxy_headers = self.proxy_headers\n        if proxy_headers:\n            h: Optional[int] = hash(tuple((k, v) for k, v in proxy_headers.items()))\n        else:\n            h = None\n        return ConnectionKey(\n            self.host,\n            self.port,\n            self.is_ssl(),\n            self.ssl,\n            self.proxy,\n            self.proxy_auth,\n            h,\n        )\n\n    @property\n    def host(self) -> str:\n        ret = self.url.raw_host\n        assert ret is not None\n        return ret\n\n    @property\n    def port(self) -> Optional[int]:\n        return self.url.port\n\n    @property\n    def request_info(self) -> RequestInfo:\n        headers: CIMultiDictProxy[str] = CIMultiDictProxy(self.headers)\n        return RequestInfo(self.url, self.method, headers, self.original_url)\n\n    def update_host(self, url: URL) -> None:\n        \"\"\"Update destination host, port and connection type (ssl).\"\"\"\n        # get host/port\n        if not url.raw_host:\n            raise InvalidURL(url)\n\n        # basic auth info\n        username, password = url.user, url.password\n        if username or password:\n            self.auth = helpers.BasicAuth(username or \"\", password or \"\")\n\n    def update_version(self, version: Union[http.HttpVersion, str]) -> None:\n        \"\"\"Convert request version to two elements tuple.\n\n        parser HTTP version '1.1' => (1, 1)\n        \"\"\"\n        if isinstance(version, str):\n            v = [part.strip() for part in version.split(\".\", 1)]\n            try:\n                version = http.HttpVersion(int(v[0]), int(v[1]))\n            except ValueError:\n                raise ValueError(\n                    f\"Can not parse http version number: {version}\"\n                ) from None\n        self.version = version\n\n    def update_headers(self, headers: Optional[LooseHeaders]) -> None:\n        \"\"\"Update request headers.\"\"\"\n        self.headers: CIMultiDict[str] = CIMultiDict()\n\n        # add host\n        netloc = cast(str, self.url.raw_host)\n        if helpers.is_ipv6_address(netloc):\n            netloc = f\"[{netloc}]\"\n        # See https://github.com/aio-libs/aiohttp/issues/3636.\n        netloc = netloc.rstrip(\".\")\n        if self.url.port is not None and not self.url.is_default_port():\n            netloc += \":\" + str(self.url.port)\n        self.headers[hdrs.HOST] = netloc\n\n        if headers:\n            if isinstance(headers, (dict, MultiDictProxy, MultiDict)):\n                headers = headers.items()\n\n            for key, value in headers:  # type: ignore[misc]\n                # A special case for Host header\n                if key.lower() == \"host\":\n                    self.headers[key] = value\n                else:\n                    self.headers.add(key, value)\n\n    def update_auto_headers(self, skip_auto_headers: Optional[Iterable[str]]) -> None:\n        if skip_auto_headers is not None:\n            self.skip_auto_headers = CIMultiDict(\n                (hdr, None) for hdr in sorted(skip_auto_headers)\n            )\n            used_headers = self.headers.copy()\n            used_headers.extend(self.skip_auto_headers)  # type: ignore[arg-type]\n        else:\n            # Fast path when there are no headers to skip\n            # which is the most common case.\n            self.skip_auto_headers = CIMultiDict()\n            used_headers = self.headers\n\n        for hdr, val in self.DEFAULT_HEADERS.items():\n            if hdr not in used_headers:\n                self.headers.add(hdr, val)\n\n        if hdrs.USER_AGENT not in used_headers:\n            self.headers[hdrs.USER_AGENT] = SERVER_SOFTWARE\n\n    def update_cookies(self, cookies: Optional[LooseCookies]) -> None:\n        \"\"\"Update request cookies header.\"\"\"\n        if not cookies:\n            return\n\n        c = SimpleCookie()\n        if hdrs.COOKIE in self.headers:\n            c.load(self.headers.get(hdrs.COOKIE, \"\"))\n            del self.headers[hdrs.COOKIE]\n\n        if isinstance(cookies, Mapping):\n            iter_cookies = cookies.items()\n        else:\n            iter_cookies = cookies  # type: ignore[assignment]\n        for name, value in iter_cookies:\n            if isinstance(value, Morsel):\n                # Preserve coded_value\n                mrsl_val = value.get(value.key, Morsel())\n                mrsl_val.set(value.key, value.value, value.coded_value)\n                c[name] = mrsl_val\n            else:\n                c[name] = value  # type: ignore[assignment]\n\n        self.headers[hdrs.COOKIE] = c.output(header=\"\", sep=\";\").strip()\n\n    def update_content_encoding(self, data: Any) -> None:\n        \"\"\"Set request content encoding.\"\"\"\n        if data is None:\n            return\n\n        enc = self.headers.get(hdrs.CONTENT_ENCODING, \"\").lower()\n        if enc:\n            if self.compress:\n                raise ValueError(\n                    \"compress can not be set \" \"if Content-Encoding header is set\"\n                )\n        elif self.compress:\n            if not isinstance(self.compress, str):\n                self.compress = \"deflate\"\n            self.headers[hdrs.CONTENT_ENCODING] = self.compress\n            self.chunked = True  # enable chunked, no need to deal with length\n\n    def update_transfer_encoding(self) -> None:\n        \"\"\"Analyze transfer-encoding header.\"\"\"\n        te = self.headers.get(hdrs.TRANSFER_ENCODING, \"\").lower()\n\n        if \"chunked\" in te:\n            if self.chunked:\n                raise ValueError(\n                    \"chunked can not be set \"\n                    'if \"Transfer-Encoding: chunked\" header is set'\n                )\n\n        elif self.chunked:\n            if hdrs.CONTENT_LENGTH in self.headers:\n                raise ValueError(\n                    \"chunked can not be set \" \"if Content-Length header is set\"\n                )\n\n            self.headers[hdrs.TRANSFER_ENCODING] = \"chunked\"\n        else:\n            if hdrs.CONTENT_LENGTH not in self.headers:\n                self.headers[hdrs.CONTENT_LENGTH] = str(len(self.body))\n\n    def update_auth(self, auth: Optional[BasicAuth], trust_env: bool = False) -> None:\n        \"\"\"Set basic auth.\"\"\"\n        if auth is None:\n            auth = self.auth\n        if auth is None and trust_env and self.url.host is not None:\n            netrc_obj = netrc_from_env()\n            with contextlib.suppress(LookupError):\n                auth = basicauth_from_netrc(netrc_obj, self.url.host)\n        if auth is None:\n            return\n\n        if not isinstance(auth, helpers.BasicAuth):\n            raise TypeError(\"BasicAuth() tuple is required instead\")\n\n        self.headers[hdrs.AUTHORIZATION] = auth.encode()\n\n    def update_body_from_data(self, body: Any) -> None:\n        if body is None:\n            return\n\n        # FormData\n        if isinstance(body, FormData):\n            body = body()\n\n        try:\n            body = payload.PAYLOAD_REGISTRY.get(body, disposition=None)\n        except payload.LookupError:\n            body = FormData(body)()\n\n        self.body = body\n\n        # enable chunked encoding if needed\n        if not self.chunked:\n            if hdrs.CONTENT_LENGTH not in self.headers:\n                size = body.size\n                if size is None:\n                    self.chunked = True\n                else:\n                    if hdrs.CONTENT_LENGTH not in self.headers:\n                        self.headers[hdrs.CONTENT_LENGTH] = str(size)\n\n        # copy payload headers\n        assert body.headers\n        for key, value in body.headers.items():\n            if key in self.headers or key in self.skip_auto_headers:\n                continue\n            self.headers[key] = value\n\n    def update_expect_continue(self, expect: bool = False) -> None:\n        if expect:\n            self.headers[hdrs.EXPECT] = \"100-continue\"\n        elif self.headers.get(hdrs.EXPECT, \"\").lower() == \"100-continue\":\n            expect = True\n\n        if expect:\n            self._continue = self.loop.create_future()\n\n    def update_proxy(\n        self,\n        proxy: Optional[URL],\n        proxy_auth: Optional[BasicAuth],\n        proxy_headers: Optional[LooseHeaders],\n    ) -> None:\n        if proxy_auth and not isinstance(proxy_auth, helpers.BasicAuth):\n            raise ValueError(\"proxy_auth must be None or BasicAuth() tuple\")\n        self.proxy = proxy\n        self.proxy_auth = proxy_auth\n        if proxy_headers is not None and not isinstance(\n            proxy_headers, (MultiDict, MultiDictProxy)\n        ):\n            proxy_headers = CIMultiDict(proxy_headers)\n        self.proxy_headers = proxy_headers\n\n    def keep_alive(self) -> bool:\n        if self.version < HttpVersion10:\n            # keep alive not supported at all\n            return False\n        if self.version == HttpVersion10:\n            if self.headers.get(hdrs.CONNECTION) == \"keep-alive\":\n                return True\n            else:  # no headers means we close for Http 1.0\n                return False\n        elif self.headers.get(hdrs.CONNECTION) == \"close\":\n            return False\n\n        return True\n\n    async def write_bytes(\n        self, writer: AbstractStreamWriter, conn: \"Connection\"\n    ) -> None:\n        \"\"\"Support coroutines that yields bytes objects.\"\"\"\n        # 100 response\n        if self._continue is not None:\n            try:\n                await writer.drain()\n                await self._continue\n            except asyncio.CancelledError:\n                return\n\n        protocol = conn.protocol\n        assert protocol is not None\n        try:\n            if isinstance(self.body, payload.Payload):\n                await self.body.write(writer)\n            else:\n                if isinstance(self.body, (bytes, bytearray)):\n                    self.body = (self.body,)\n\n                for chunk in self.body:\n                    await writer.write(chunk)\n        except OSError as underlying_exc:\n            reraised_exc = underlying_exc\n\n            exc_is_not_timeout = underlying_exc.errno is not None or not isinstance(\n                underlying_exc, asyncio.TimeoutError\n            )\n            if exc_is_not_timeout:\n                reraised_exc = ClientOSError(\n                    underlying_exc.errno,\n                    f\"Can not write request body for {self.url !s}\",\n                )\n\n            set_exception(protocol, reraised_exc, underlying_exc)\n        except asyncio.CancelledError:\n            await writer.write_eof()\n        except Exception as underlying_exc:\n            set_exception(\n                protocol,\n                ClientConnectionError(\n                    f\"Failed to send bytes into the underlying connection {conn !s}\",\n                ),\n                underlying_exc,\n            )\n        else:\n            await writer.write_eof()\n            protocol.start_timeout()\n\n    async def send(self, conn: \"Connection\") -> \"ClientResponse\":\n        # Specify request target:\n        # - CONNECT request must send authority form URI\n        # - not CONNECT proxy must send absolute form URI\n        # - most common is origin form URI\n        if self.method == hdrs.METH_CONNECT:\n            connect_host = self.url.raw_host\n            assert connect_host is not None\n            if helpers.is_ipv6_address(connect_host):\n                connect_host = f\"[{connect_host}]\"\n            path = f\"{connect_host}:{self.url.port}\"\n        elif self.proxy and not self.is_ssl():\n            path = str(self.url)\n        else:\n            path = self.url.raw_path\n            if self.url.raw_query_string:\n                path += \"?\" + self.url.raw_query_string\n\n        protocol = conn.protocol\n        assert protocol is not None\n        writer = StreamWriter(\n            protocol,\n            self.loop,\n            on_chunk_sent=functools.partial(\n                self._on_chunk_request_sent, self.method, self.url\n            ),\n            on_headers_sent=functools.partial(\n                self._on_headers_request_sent, self.method, self.url\n            ),\n        )\n\n        if self.compress:\n            writer.enable_compression(self.compress)\n\n        if self.chunked is not None:\n            writer.enable_chunking()\n\n        # set default content-type\n        if (\n            self.method in self.POST_METHODS\n            and hdrs.CONTENT_TYPE not in self.skip_auto_headers\n            and hdrs.CONTENT_TYPE not in self.headers\n        ):\n            self.headers[hdrs.CONTENT_TYPE] = \"application/octet-stream\"\n\n        # set the connection header\n        connection = self.headers.get(hdrs.CONNECTION)\n        if not connection:\n            if self.keep_alive():\n                if self.version == HttpVersion10:\n                    connection = \"keep-alive\"\n            else:\n                if self.version == HttpVersion11:\n                    connection = \"close\"\n\n        if connection is not None:\n            self.headers[hdrs.CONNECTION] = connection\n\n        # status + headers\n        v = self.version\n        status_line = f\"{self.method} {path} HTTP/{v.major}.{v.minor}\"\n        await writer.write_headers(status_line, self.headers)\n        coro = self.write_bytes(writer, conn)\n\n        if sys.version_info >= (3, 12):\n            # Optimization for Python 3.12, try to write\n            # bytes immediately to avoid having to schedule\n            # the task on the event loop.\n            task = asyncio.Task(coro, loop=self.loop, eager_start=True)\n        else:\n            task = self.loop.create_task(coro)\n\n        self._writer = task\n        response_class = self.response_class\n        assert response_class is not None\n        self.response = response_class(\n            self.method,\n            self.original_url,\n            writer=self._writer,\n            continue100=self._continue,\n            timer=self._timer,\n            request_info=self.request_info,\n            traces=self._traces,\n            loop=self.loop,\n            session=self._session,\n        )\n        return self.response\n\n    async def close(self) -> None:\n        if self._writer is not None:\n            with contextlib.suppress(asyncio.CancelledError):\n                await self._writer\n\n    def terminate(self) -> None:\n        if self._writer is not None:\n            if not self.loop.is_closed():\n                self._writer.cancel()\n            self._writer.remove_done_callback(self.__reset_writer)\n            self._writer = None\n\n    async def _on_chunk_request_sent(self, method: str, url: URL, chunk: bytes) -> None:\n        for trace in self._traces:\n            await trace.send_request_chunk_sent(method, url, chunk)\n\n    async def _on_headers_request_sent(\n        self, method: str, url: URL, headers: \"CIMultiDict[str]\"\n    ) -> None:\n        for trace in self._traces:\n            await trace.send_request_headers(method, url, headers)",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 233,
                                "end_lineno": 783,
                                "parent": null
                            }
                        },
                        {
                            "file_name": "aiohttp/client_reqrep.py",
                            "type": "class",
                            "name": "ClientRequest",
                            "content": "class ClientRequest:\n    GET_METHODS = {\n        hdrs.METH_GET,\n        hdrs.METH_HEAD,\n        hdrs.METH_OPTIONS,\n        hdrs.METH_TRACE,\n    }\n    POST_METHODS = {hdrs.METH_PATCH, hdrs.METH_POST, hdrs.METH_PUT}\n    ALL_METHODS = GET_METHODS.union(POST_METHODS).union({hdrs.METH_DELETE})\n\n    DEFAULT_HEADERS = {\n        hdrs.ACCEPT: \"*/*\",\n        hdrs.ACCEPT_ENCODING: _gen_default_accept_encoding(),\n    }\n\n    # Type of body depends on PAYLOAD_REGISTRY, which is dynamic.\n    body: Any = b\"\"\n    auth = None\n    response = None\n\n    __writer = None  # async task for streaming data\n    _continue = None  # waiter future for '100 Continue' response\n\n    # N.B.\n    # Adding __del__ method with self._writer closing doesn't make sense\n    # because _writer is instance method, thus it keeps a reference to self.\n    # Until writer has finished finalizer will not be called.\n\n    def __init__(\n        self,\n        method: str,\n        url: URL,\n        *,\n        params: Optional[Mapping[str, str]] = None,\n        headers: Optional[LooseHeaders] = None,\n        skip_auto_headers: Optional[Iterable[str]] = None,\n        data: Any = None,\n        cookies: Optional[LooseCookies] = None,\n        auth: Optional[BasicAuth] = None,\n        version: http.HttpVersion = http.HttpVersion11,\n        compress: Optional[str] = None,\n        chunked: Optional[bool] = None,\n        expect100: bool = False,\n        loop: Optional[asyncio.AbstractEventLoop] = None,\n        response_class: Optional[Type[\"ClientResponse\"]] = None,\n        proxy: Optional[URL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        timer: Optional[BaseTimerContext] = None,\n        session: Optional[\"ClientSession\"] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        proxy_headers: Optional[LooseHeaders] = None,\n        traces: Optional[List[\"Trace\"]] = None,\n        trust_env: bool = False,\n        server_hostname: Optional[str] = None,\n    ):\n        if loop is None:\n            loop = asyncio.get_event_loop()\n\n        match = _CONTAINS_CONTROL_CHAR_RE.search(method)\n        if match:\n            raise ValueError(\n                f\"Method cannot contain non-token characters {method!r} \"\n                \"(found at least {match.group()!r})\"\n            )\n\n        assert isinstance(url, URL), url\n        assert isinstance(proxy, (URL, type(None))), proxy\n        # FIXME: session is None in tests only, need to fix tests\n        # assert session is not None\n        self._session = cast(\"ClientSession\", session)\n        if params:\n            q = MultiDict(url.query)\n            url2 = url.with_query(params)\n            q.extend(url2.query)\n            url = url.with_query(q)\n        self.original_url = url\n        self.url = url.with_fragment(None)\n        self.method = method.upper()\n        self.chunked = chunked\n        self.compress = compress\n        self.loop = loop\n        self.length = None\n        if response_class is None:\n            real_response_class = ClientResponse\n        else:\n            real_response_class = response_class\n        self.response_class: Type[ClientResponse] = real_response_class\n        self._timer = timer if timer is not None else TimerNoop()\n        self._ssl = ssl if ssl is not None else True\n        self.server_hostname = server_hostname\n\n        if loop.get_debug():\n            self._source_traceback = traceback.extract_stack(sys._getframe(1))\n\n        self.update_version(version)\n        self.update_host(url)\n        self.update_headers(headers)\n        self.update_auto_headers(skip_auto_headers)\n        self.update_cookies(cookies)\n        self.update_content_encoding(data)\n        self.update_auth(auth, trust_env)\n        self.update_proxy(proxy, proxy_auth, proxy_headers)\n\n        self.update_body_from_data(data)\n        if data is not None or self.method not in self.GET_METHODS:\n            self.update_transfer_encoding()\n        self.update_expect_continue(expect100)\n        if traces is None:\n            traces = []\n        self._traces = traces\n\n    def __reset_writer(self, _: object = None) -> None:\n        self.__writer = None\n\n    @property\n    def _writer(self) -> Optional[\"asyncio.Task[None]\"]:\n        return self.__writer\n\n    @_writer.setter\n    def _writer(self, writer: Optional[\"asyncio.Task[None]\"]) -> None:\n        if self.__writer is not None:\n            self.__writer.remove_done_callback(self.__reset_writer)\n        self.__writer = writer\n        if writer is None:\n            return\n        if writer.done():\n            # The writer is already done, so we can reset it immediately.\n            self.__reset_writer()\n        else:\n            writer.add_done_callback(self.__reset_writer)\n\n    def is_ssl(self) -> bool:\n        return self.url.scheme in (\"https\", \"wss\")\n\n    @property\n    def ssl(self) -> Union[\"SSLContext\", bool, Fingerprint]:\n        return self._ssl\n\n    @property\n    def connection_key(self) -> ConnectionKey:\n        proxy_headers = self.proxy_headers\n        if proxy_headers:\n            h: Optional[int] = hash(tuple((k, v) for k, v in proxy_headers.items()))\n        else:\n            h = None\n        return ConnectionKey(\n            self.host,\n            self.port,\n            self.is_ssl(),\n            self.ssl,\n            self.proxy,\n            self.proxy_auth,\n            h,\n        )\n\n    @property\n    def host(self) -> str:\n        ret = self.url.raw_host\n        assert ret is not None\n        return ret\n\n    @property\n    def port(self) -> Optional[int]:\n        return self.url.port\n\n    @property\n    def request_info(self) -> RequestInfo:\n        headers: CIMultiDictProxy[str] = CIMultiDictProxy(self.headers)\n        return RequestInfo(self.url, self.method, headers, self.original_url)\n\n    def update_host(self, url: URL) -> None:\n        \"\"\"Update destination host, port and connection type (ssl).\"\"\"\n        # get host/port\n        if not url.raw_host:\n            raise InvalidURL(url)\n\n        # basic auth info\n        username, password = url.user, url.password\n        if username or password:\n            self.auth = helpers.BasicAuth(username or \"\", password or \"\")\n\n    def update_version(self, version: Union[http.HttpVersion, str]) -> None:\n        \"\"\"Convert request version to two elements tuple.\n\n        parser HTTP version '1.1' => (1, 1)\n        \"\"\"\n        if isinstance(version, str):\n            v = [part.strip() for part in version.split(\".\", 1)]\n            try:\n                version = http.HttpVersion(int(v[0]), int(v[1]))\n            except ValueError:\n                raise ValueError(\n                    f\"Can not parse http version number: {version}\"\n                ) from None\n        self.version = version\n\n    def update_headers(self, headers: Optional[LooseHeaders]) -> None:\n        \"\"\"Update request headers.\"\"\"\n        self.headers: CIMultiDict[str] = CIMultiDict()\n\n        # add host\n        netloc = cast(str, self.url.raw_host)\n        if helpers.is_ipv6_address(netloc):\n            netloc = f\"[{netloc}]\"\n        # See https://github.com/aio-libs/aiohttp/issues/3636.\n        netloc = netloc.rstrip(\".\")\n        if self.url.port is not None and not self.url.is_default_port():\n            netloc += \":\" + str(self.url.port)\n        self.headers[hdrs.HOST] = netloc\n\n        if headers:\n            if isinstance(headers, (dict, MultiDictProxy, MultiDict)):\n                headers = headers.items()\n\n            for key, value in headers:  # type: ignore[misc]\n                # A special case for Host header\n                if key.lower() == \"host\":\n                    self.headers[key] = value\n                else:\n                    self.headers.add(key, value)\n\n    def update_auto_headers(self, skip_auto_headers: Optional[Iterable[str]]) -> None:\n        if skip_auto_headers is not None:\n            self.skip_auto_headers = CIMultiDict(\n                (hdr, None) for hdr in sorted(skip_auto_headers)\n            )\n            used_headers = self.headers.copy()\n            used_headers.extend(self.skip_auto_headers)  # type: ignore[arg-type]\n        else:\n            # Fast path when there are no headers to skip\n            # which is the most common case.\n            self.skip_auto_headers = CIMultiDict()\n            used_headers = self.headers\n\n        for hdr, val in self.DEFAULT_HEADERS.items():\n            if hdr not in used_headers:\n                self.headers.add(hdr, val)\n\n        if hdrs.USER_AGENT not in used_headers:\n            self.headers[hdrs.USER_AGENT] = SERVER_SOFTWARE\n\n    def update_cookies(self, cookies: Optional[LooseCookies]) -> None:\n        \"\"\"Update request cookies header.\"\"\"\n        if not cookies:\n            return\n\n        c = SimpleCookie()\n        if hdrs.COOKIE in self.headers:\n            c.load(self.headers.get(hdrs.COOKIE, \"\"))\n            del self.headers[hdrs.COOKIE]\n\n        if isinstance(cookies, Mapping):\n            iter_cookies = cookies.items()\n        else:\n            iter_cookies = cookies  # type: ignore[assignment]\n        for name, value in iter_cookies:\n            if isinstance(value, Morsel):\n                # Preserve coded_value\n                mrsl_val = value.get(value.key, Morsel())\n                mrsl_val.set(value.key, value.value, value.coded_value)\n                c[name] = mrsl_val\n            else:\n                c[name] = value  # type: ignore[assignment]\n\n        self.headers[hdrs.COOKIE] = c.output(header=\"\", sep=\";\").strip()\n\n    def update_content_encoding(self, data: Any) -> None:\n        \"\"\"Set request content encoding.\"\"\"\n        if data is None:\n            return\n\n        enc = self.headers.get(hdrs.CONTENT_ENCODING, \"\").lower()\n        if enc:\n            if self.compress:\n                raise ValueError(\n                    \"compress can not be set \" \"if Content-Encoding header is set\"\n                )\n        elif self.compress:\n            if not isinstance(self.compress, str):\n                self.compress = \"deflate\"\n            self.headers[hdrs.CONTENT_ENCODING] = self.compress\n            self.chunked = True  # enable chunked, no need to deal with length\n\n    def update_transfer_encoding(self) -> None:\n        \"\"\"Analyze transfer-encoding header.\"\"\"\n        te = self.headers.get(hdrs.TRANSFER_ENCODING, \"\").lower()\n\n        if \"chunked\" in te:\n            if self.chunked:\n                raise ValueError(\n                    \"chunked can not be set \"\n                    'if \"Transfer-Encoding: chunked\" header is set'\n                )\n\n        elif self.chunked:\n            if hdrs.CONTENT_LENGTH in self.headers:\n                raise ValueError(\n                    \"chunked can not be set \" \"if Content-Length header is set\"\n                )\n\n            self.headers[hdrs.TRANSFER_ENCODING] = \"chunked\"\n        else:\n            if hdrs.CONTENT_LENGTH not in self.headers:\n                self.headers[hdrs.CONTENT_LENGTH] = str(len(self.body))\n\n    def update_auth(self, auth: Optional[BasicAuth], trust_env: bool = False) -> None:\n        \"\"\"Set basic auth.\"\"\"\n        if auth is None:\n            auth = self.auth\n        if auth is None and trust_env and self.url.host is not None:\n            netrc_obj = netrc_from_env()\n            with contextlib.suppress(LookupError):\n                auth = basicauth_from_netrc(netrc_obj, self.url.host)\n        if auth is None:\n            return\n\n        if not isinstance(auth, helpers.BasicAuth):\n            raise TypeError(\"BasicAuth() tuple is required instead\")\n\n        self.headers[hdrs.AUTHORIZATION] = auth.encode()\n\n    def update_body_from_data(self, body: Any) -> None:\n        if body is None:\n            return\n\n        # FormData\n        if isinstance(body, FormData):\n            body = body()\n\n        try:\n            body = payload.PAYLOAD_REGISTRY.get(body, disposition=None)\n        except payload.LookupError:\n            body = FormData(body)()\n\n        self.body = body\n\n        # enable chunked encoding if needed\n        if not self.chunked:\n            if hdrs.CONTENT_LENGTH not in self.headers:\n                size = body.size\n                if size is None:\n                    self.chunked = True\n                else:\n                    if hdrs.CONTENT_LENGTH not in self.headers:\n                        self.headers[hdrs.CONTENT_LENGTH] = str(size)\n\n        # copy payload headers\n        assert body.headers\n        for key, value in body.headers.items():\n            if key in self.headers or key in self.skip_auto_headers:\n                continue\n            self.headers[key] = value\n\n    def update_expect_continue(self, expect: bool = False) -> None:\n        if expect:\n            self.headers[hdrs.EXPECT] = \"100-continue\"\n        elif self.headers.get(hdrs.EXPECT, \"\").lower() == \"100-continue\":\n            expect = True\n\n        if expect:\n            self._continue = self.loop.create_future()\n\n    def update_proxy(\n        self,\n        proxy: Optional[URL],\n        proxy_auth: Optional[BasicAuth],\n        proxy_headers: Optional[LooseHeaders],\n    ) -> None:\n        if proxy_auth and not isinstance(proxy_auth, helpers.BasicAuth):\n            raise ValueError(\"proxy_auth must be None or BasicAuth() tuple\")\n        self.proxy = proxy\n        self.proxy_auth = proxy_auth\n        if proxy_headers is not None and not isinstance(\n            proxy_headers, (MultiDict, MultiDictProxy)\n        ):\n            proxy_headers = CIMultiDict(proxy_headers)\n        self.proxy_headers = proxy_headers\n\n    def keep_alive(self) -> bool:\n        if self.version < HttpVersion10:\n            # keep alive not supported at all\n            return False\n        if self.version == HttpVersion10:\n            if self.headers.get(hdrs.CONNECTION) == \"keep-alive\":\n                return True\n            else:  # no headers means we close for Http 1.0\n                return False\n        elif self.headers.get(hdrs.CONNECTION) == \"close\":\n            return False\n\n        return True\n\n    async def write_bytes(\n        self, writer: AbstractStreamWriter, conn: \"Connection\"\n    ) -> None:\n        \"\"\"Support coroutines that yields bytes objects.\"\"\"\n        # 100 response\n        if self._continue is not None:\n            try:\n                await writer.drain()\n                await self._continue\n            except asyncio.CancelledError:\n                return\n\n        protocol = conn.protocol\n        assert protocol is not None\n        try:\n            if isinstance(self.body, payload.Payload):\n                await self.body.write(writer)\n            else:\n                if isinstance(self.body, (bytes, bytearray)):\n                    self.body = (self.body,)\n\n                for chunk in self.body:\n                    await writer.write(chunk)\n        except OSError as underlying_exc:\n            reraised_exc = underlying_exc\n\n            exc_is_not_timeout = underlying_exc.errno is not None or not isinstance(\n                underlying_exc, asyncio.TimeoutError\n            )\n            if exc_is_not_timeout:\n                reraised_exc = ClientOSError(\n                    underlying_exc.errno,\n                    f\"Can not write request body for {self.url !s}\",\n                )\n\n            set_exception(protocol, reraised_exc, underlying_exc)\n        except asyncio.CancelledError:\n            await writer.write_eof()\n        except Exception as underlying_exc:\n            set_exception(\n                protocol,\n                ClientConnectionError(\n                    f\"Failed to send bytes into the underlying connection {conn !s}\",\n                ),\n                underlying_exc,\n            )\n        else:\n            await writer.write_eof()\n            protocol.start_timeout()\n\n    async def send(self, conn: \"Connection\") -> \"ClientResponse\":\n        # Specify request target:\n        # - CONNECT request must send authority form URI\n        # - not CONNECT proxy must send absolute form URI\n        # - most common is origin form URI\n        if self.method == hdrs.METH_CONNECT:\n            connect_host = self.url.raw_host\n            assert connect_host is not None\n            if helpers.is_ipv6_address(connect_host):\n                connect_host = f\"[{connect_host}]\"\n            path = f\"{connect_host}:{self.url.port}\"\n        elif self.proxy and not self.is_ssl():\n            path = str(self.url)\n        else:\n            path = self.url.raw_path\n            if self.url.raw_query_string:\n                path += \"?\" + self.url.raw_query_string\n\n        protocol = conn.protocol\n        assert protocol is not None\n        writer = StreamWriter(\n            protocol,\n            self.loop,\n            on_chunk_sent=functools.partial(\n                self._on_chunk_request_sent, self.method, self.url\n            ),\n            on_headers_sent=functools.partial(\n                self._on_headers_request_sent, self.method, self.url\n            ),\n        )\n\n        if self.compress:\n            writer.enable_compression(self.compress)\n\n        if self.chunked is not None:\n            writer.enable_chunking()\n\n        # set default content-type\n        if (\n            self.method in self.POST_METHODS\n            and hdrs.CONTENT_TYPE not in self.skip_auto_headers\n            and hdrs.CONTENT_TYPE not in self.headers\n        ):\n            self.headers[hdrs.CONTENT_TYPE] = \"application/octet-stream\"\n\n        # set the connection header\n        connection = self.headers.get(hdrs.CONNECTION)\n        if not connection:\n            if self.keep_alive():\n                if self.version == HttpVersion10:\n                    connection = \"keep-alive\"\n            else:\n                if self.version == HttpVersion11:\n                    connection = \"close\"\n\n        if connection is not None:\n            self.headers[hdrs.CONNECTION] = connection\n\n        # status + headers\n        v = self.version\n        status_line = f\"{self.method} {path} HTTP/{v.major}.{v.minor}\"\n        await writer.write_headers(status_line, self.headers)\n        coro = self.write_bytes(writer, conn)\n\n        if sys.version_info >= (3, 12):\n            # Optimization for Python 3.12, try to write\n            # bytes immediately to avoid having to schedule\n            # the task on the event loop.\n            task = asyncio.Task(coro, loop=self.loop, eager_start=True)\n        else:\n            task = self.loop.create_task(coro)\n\n        self._writer = task\n        response_class = self.response_class\n        assert response_class is not None\n        self.response = response_class(\n            self.method,\n            self.original_url,\n            writer=self._writer,\n            continue100=self._continue,\n            timer=self._timer,\n            request_info=self.request_info,\n            traces=self._traces,\n            loop=self.loop,\n            session=self._session,\n        )\n        return self.response\n\n    async def close(self) -> None:\n        if self._writer is not None:\n            with contextlib.suppress(asyncio.CancelledError):\n                await self._writer\n\n    def terminate(self) -> None:\n        if self._writer is not None:\n            if not self.loop.is_closed():\n                self._writer.cancel()\n            self._writer.remove_done_callback(self.__reset_writer)\n            self._writer = None\n\n    async def _on_chunk_request_sent(self, method: str, url: URL, chunk: bytes) -> None:\n        for trace in self._traces:\n            await trace.send_request_chunk_sent(method, url, chunk)\n\n    async def _on_headers_request_sent(\n        self, method: str, url: URL, headers: \"CIMultiDict[str]\"\n    ) -> None:\n        for trace in self._traces:\n            await trace.send_request_headers(method, url, headers)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 233,
                            "end_lineno": 783,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "# HTTP client functional tests against aiohttp.web server\n\nimport asyncio\nimport datetime\nimport http.cookies\nimport io\nimport json\nimport pathlib\nimport socket\nimport ssl\nimport sys\nimport tarfile\nimport time\nimport zipfile\nfrom typing import Any, AsyncIterator, Type\nfrom unittest import mock\n\nimport pytest\nfrom multidict import MultiDict\nfrom yarl import URL\n\nimport aiohttp\nfrom aiohttp import Fingerprint, ServerFingerprintMismatch, hdrs, web\nfrom aiohttp.abc import AbstractResolver\nfrom aiohttp.client_exceptions import (\n    InvalidURL,\n    InvalidUrlClientError,\n    InvalidUrlRedirectClientError,\n    NonHttpUrlClientError,\n    NonHttpUrlRedirectClientError,\n    SocketTimeoutError,\n    TooManyRedirects,\n)\nfrom aiohttp.pytest_plugin import AiohttpClient, AiohttpServer, TestClient\nfrom aiohttp.test_utils import unused_port\n\n\n@pytest.fixture\ndef here():\n    return pathlib.Path(__file__).parent\n\n\n@pytest.fixture\ndef fname(here):\n    return here / \"conftest.py\"\n\n\nasync def test_keepalive_two_requests_success(aiohttp_client) -> None:\n    async def handler(request):\n        body = await request.read()\n        assert b\"\" == body\n        return web.Response(body=b\"OK\")\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    connector = aiohttp.TCPConnector(limit=1)\n    client = await aiohttp_client(app, connector=connector)\n\n    resp1 = await client.get(\"/\")\n    await resp1.read()\n    resp2 = await client.get(\"/\")\n    await resp2.read()\n\n    assert 1 == len(client._session.connector._conns)\n\n\nasync def test_keepalive_after_head_requests_success(aiohttp_client) -> None:\n    async def handler(request):\n        body = await request.read()\n        assert b\"\" == body\n        return web.Response(body=b\"OK\")\n\n    cnt_conn_reuse = 0\n\n    async def on_reuseconn(session, ctx, params):\n        nonlocal cnt_conn_reuse\n        cnt_conn_reuse += 1\n\n    trace_config = aiohttp.TraceConfig()\n    trace_config._on_connection_reuseconn.append(on_reuseconn)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    app.router.add_route(\"HEAD\", \"/\", handler)\n\n    connector = aiohttp.TCPConnector(limit=1)\n    client = await aiohttp_client(\n        app, connector=connector, trace_configs=[trace_config]\n    )\n\n    resp1 = await client.head(\"/\")\n    await resp1.read()\n    resp2 = await client.get(\"/\")\n    await resp2.read()\n\n    assert 1 == cnt_conn_reuse\n\n\n@pytest.mark.parametrize(\"status\", (101, 204, 304))\nasync def test_keepalive_after_empty_body_status(\n    aiohttp_client: Any, status: int\n) -> None:\n    async def handler(request):\n        body = await request.read()\n        assert b\"\" == body\n        return web.Response(status=status)\n\n    cnt_conn_reuse = 0\n\n    async def on_reuseconn(session, ctx, params):\n        nonlocal cnt_conn_reuse\n        cnt_conn_reuse += 1\n\n    trace_config = aiohttp.TraceConfig()\n    trace_config._on_connection_reuseconn.append(on_reuseconn)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    connector = aiohttp.TCPConnector(limit=1)\n    client = await aiohttp_client(\n        app, connector=connector, trace_configs=[trace_config]\n    )\n\n    resp1 = await client.get(\"/\")\n    await resp1.read()\n    resp2 = await client.get(\"/\")\n    await resp2.read()\n\n    assert cnt_conn_reuse == 1\n\n\n@pytest.mark.parametrize(\"status\", (101, 204, 304))\nasync def test_keepalive_after_empty_body_status_stream_response(\n    aiohttp_client: Any, status: int\n) -> None:\n    async def handler(request):\n        stream_response = web.StreamResponse(status=status)\n        await stream_response.prepare(request)\n        return stream_response\n\n    cnt_conn_reuse = 0\n\n    async def on_reuseconn(session, ctx, params):\n        nonlocal cnt_conn_reuse\n        cnt_conn_reuse += 1\n\n    trace_config = aiohttp.TraceConfig()\n    trace_config._on_connection_reuseconn.append(on_reuseconn)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    connector = aiohttp.TCPConnector(limit=1)\n    client = await aiohttp_client(\n        app, connector=connector, trace_configs=[trace_config]\n    )\n\n    resp1 = await client.get(\"/\")\n    await resp1.read()\n    resp2 = await client.get(\"/\")\n    await resp2.read()\n\n    assert cnt_conn_reuse == 1\n\n\nasync def test_keepalive_response_released(aiohttp_client: Any) -> None:\n    async def handler(request):\n        body = await request.read()\n        assert b\"\" == body\n        return web.Response(body=b\"OK\")\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    connector = aiohttp.TCPConnector(limit=1)\n    client = await aiohttp_client(app, connector=connector)\n\n    resp1 = await client.get(\"/\")\n    resp1.release()\n    resp2 = await client.get(\"/\")\n    resp2.release()\n\n    assert 1 == len(client._session.connector._conns)\n\n\nasync def test_upgrade_connection_not_released_after_read(aiohttp_client) -> None:\n    async def handler(request: web.Request) -> web.Response:\n        body = await request.read()\n        assert b\"\" == body\n        return web.Response(\n            status=101, headers={\"Connection\": \"Upgrade\", \"Upgrade\": \"tcp\"}\n        )\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    await resp.read()\n    assert resp.connection is not None\n    assert not resp.closed\n\n\nasync def test_keepalive_server_force_close_connection(aiohttp_client) -> None:\n    async def handler(request):\n        body = await request.read()\n        assert b\"\" == body\n        response = web.Response(body=b\"OK\")\n        response.force_close()\n        return response\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    connector = aiohttp.TCPConnector(limit=1)\n    client = await aiohttp_client(app, connector=connector)\n\n    resp1 = await client.get(\"/\")\n    resp1.close()\n    resp2 = await client.get(\"/\")\n    resp2.close()\n\n    assert 0 == len(client._session.connector._conns)\n\n\nasync def test_keepalive_timeout_async_sleep() -> None:\n    async def handler(request):\n        body = await request.read()\n        assert b\"\" == body\n        return web.Response(body=b\"OK\")\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    runner = web.AppRunner(app, tcp_keepalive=True, keepalive_timeout=0.001)\n    await runner.setup()\n\n    port = unused_port()\n    site = web.TCPSite(runner, host=\"localhost\", port=port)\n    await site.start()\n\n    try:\n        async with aiohttp.client.ClientSession() as sess:\n            resp1 = await sess.get(f\"http://localhost:{port}/\")\n            await resp1.read()\n            # wait for server keepalive_timeout\n            await asyncio.sleep(0.01)\n            resp2 = await sess.get(f\"http://localhost:{port}/\")\n            await resp2.read()\n    finally:\n        await asyncio.gather(runner.shutdown(), site.stop())\n\n\n@pytest.mark.skipif(\n    sys.version_info[:2] == (3, 11),\n    reason=\"https://github.com/pytest-dev/pytest/issues/10763\",\n)\nasync def test_keepalive_timeout_sync_sleep() -> None:\n    async def handler(request):\n        body = await request.read()\n        assert b\"\" == body\n        return web.Response(body=b\"OK\")\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    runner = web.AppRunner(app, tcp_keepalive=True, keepalive_timeout=0.001)\n    await runner.setup()\n\n    port = unused_port()\n    site = web.TCPSite(runner, host=\"localhost\", port=port)\n    await site.start()\n\n    try:\n        async with aiohttp.client.ClientSession() as sess:\n            resp1 = await sess.get(f\"http://localhost:{port}/\")\n            await resp1.read()\n            # wait for server keepalive_timeout\n            # time.sleep is a more challenging scenario than asyncio.sleep\n            time.sleep(0.01)\n            resp2 = await sess.get(f\"http://localhost:{port}/\")\n            await resp2.read()\n    finally:\n        await asyncio.gather(runner.shutdown(), site.stop())\n\n\nasync def test_release_early(aiohttp_client) -> None:\n    async def handler(request):\n        await request.read()\n        return web.Response(body=b\"OK\")\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    client = await aiohttp_client(app)\n    resp = await client.get(\"/\")\n    assert resp.closed\n    await resp.wait_for_close()\n    assert 1 == len(client._session.connector._conns)\n\n\nasync def test_HTTP_304(aiohttp_client) -> None:\n    async def handler(request):\n        body = await request.read()\n        assert b\"\" == body\n        return web.Response(status=304)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert resp.status == 304\n    content = await resp.read()\n    assert content == b\"\"\n\n\nasync def test_stream_request_on_server_eof(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=\"OK\", status=200)\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n    app.add_routes([web.put(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n\n    async def data_gen():\n        for _ in range(2):\n            yield b\"just data\"\n            await asyncio.sleep(0.1)\n\n    async with client.put(\"/\", data=data_gen()) as resp:\n        assert 200 == resp.status\n        assert len(client.session.connector._acquired) == 1\n        conn = next(iter(client.session.connector._acquired))\n\n    async with client.get(\"/\") as resp:\n        assert 200 == resp.status\n\n    # Connection should have been reused\n    conns = next(iter(client.session.connector._conns.values()))\n    assert len(conns) == 1\n    assert conns[0][0] is conn\n\n\nasync def test_stream_request_on_server_eof_nested(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=\"OK\", status=200)\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n    app.add_routes([web.put(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n\n    async def data_gen():\n        for _ in range(2):\n            yield b\"just data\"\n            await asyncio.sleep(0.1)\n\n    async with client.put(\"/\", data=data_gen()) as resp:\n        assert 200 == resp.status\n        async with client.get(\"/\") as resp:\n            assert 200 == resp.status\n\n    # Should be 2 separate connections\n    conns = next(iter(client.session.connector._conns.values()))\n    assert len(conns) == 2\n\n\nasync def test_HTTP_304_WITH_BODY(aiohttp_client) -> None:\n    async def handler(request):\n        body = await request.read()\n        assert b\"\" == body\n        return web.Response(body=b\"test\", status=304)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert resp.status == 304\n    content = await resp.read()\n    assert content == b\"\"\n\n\nasync def test_auto_header_user_agent(aiohttp_client) -> None:\n    async def handler(request):\n        assert \"aiohttp\" in request.headers[\"user-agent\"]\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/\") as resp:\n        assert 200 == resp.status\n\n\nasync def test_skip_auto_headers_user_agent(aiohttp_client) -> None:\n    async def handler(request):\n        assert hdrs.USER_AGENT not in request.headers\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/\", skip_auto_headers=[\"user-agent\"]) as resp:\n        assert 200 == resp.status\n\n\nasync def test_skip_default_auto_headers_user_agent(aiohttp_client) -> None:\n    async def handler(request):\n        assert hdrs.USER_AGENT not in request.headers\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app, skip_auto_headers=[\"user-agent\"])\n\n    async with client.get(\"/\") as resp:\n        assert 200 == resp.status\n\n\nasync def test_skip_auto_headers_content_type(aiohttp_client) -> None:\n    async def handler(request):\n        assert hdrs.CONTENT_TYPE not in request.headers\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/\", skip_auto_headers=[\"content-type\"]) as resp:\n        assert 200 == resp.status\n\n\nasync def test_post_data_bytesio(aiohttp_client) -> None:\n    data = b\"some buffer\"\n\n    async def handler(request):\n        assert len(data) == request.content_length\n        val = await request.read()\n        assert data == val\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"POST\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    with io.BytesIO(data) as file_handle:\n        async with client.post(\"/\", data=file_handle) as resp:\n            assert 200 == resp.status\n\n\nasync def test_post_data_with_bytesio_file(aiohttp_client) -> None:\n    data = b\"some buffer\"\n\n    async def handler(request):\n        post_data = await request.post()\n        assert [\"file\"] == list(post_data.keys())\n        assert data == post_data[\"file\"].file.read()\n        post_data[\"file\"].file.close()  # aiohttp < 4 doesn't autoclose files\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"POST\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    with io.BytesIO(data) as file_handle:\n        async with client.post(\"/\", data={\"file\": file_handle}) as resp:\n            assert 200 == resp.status\n\n\nasync def test_post_data_stringio(aiohttp_client) -> None:\n    data = \"some buffer\"\n\n    async def handler(request):\n        assert len(data) == request.content_length\n        assert request.headers[\"CONTENT-TYPE\"] == \"text/plain; charset=utf-8\"\n        val = await request.text()\n        assert data == val\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"POST\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.post(\"/\", data=io.StringIO(data)) as resp:\n        assert 200 == resp.status\n\n\nasync def test_post_data_textio_encoding(aiohttp_client) -> None:\n    data = \"текст\"\n\n    async def handler(request):\n        assert request.headers[\"CONTENT-TYPE\"] == \"text/plain; charset=koi8-r\"\n        val = await request.text()\n        assert data == val\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"POST\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    pl = aiohttp.TextIOPayload(io.StringIO(data), encoding=\"koi8-r\")\n    async with client.post(\"/\", data=pl) as resp:\n        assert 200 == resp.status\n\n\nasync def test_post_data_zipfile_filelike(aiohttp_client: AiohttpClient) -> None:\n    data = b\"This is a zip file payload text file.\"\n\n    async def handler(request: web.Request) -> web.Response:\n        val = await request.read()\n        assert data == val, \"Transmitted zipfile member failed to match original data.\"\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"POST\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    buf = io.BytesIO()\n    with zipfile.ZipFile(file=buf, mode=\"w\") as zf:\n        with zf.open(\"payload1.txt\", mode=\"w\") as zip_filelike_writing:\n            zip_filelike_writing.write(data)\n\n    buf.seek(0)\n    zf = zipfile.ZipFile(file=buf, mode=\"r\")\n    resp = await client.post(\"/\", data=zf.open(\"payload1.txt\"))\n    assert 200 == resp.status\n\n\nasync def test_post_data_tarfile_filelike(aiohttp_client: AiohttpClient) -> None:\n    data = b\"This is a tar file payload text file.\"\n\n    async def handler(request: web.Request) -> web.Response:\n        val = await request.read()\n        assert data == val, \"Transmitted tarfile member failed to match original data.\"\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"POST\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    buf = io.BytesIO()\n    with tarfile.open(fileobj=buf, mode=\"w\") as tf:\n        ti = tarfile.TarInfo(name=\"payload1.txt\")\n        ti.size = len(data)\n        tf.addfile(tarinfo=ti, fileobj=io.BytesIO(data))\n\n    # Random-access tarfile.\n    buf.seek(0)\n    tf = tarfile.open(fileobj=buf, mode=\"r:\")\n    resp = await client.post(\"/\", data=tf.extractfile(\"payload1.txt\"))\n    assert 200 == resp.status\n\n    # Streaming tarfile.\n    buf.seek(0)\n    tf = tarfile.open(fileobj=buf, mode=\"r|\")\n    for entry in tf:\n        resp = await client.post(\"/\", data=tf.extractfile(entry))\n        assert 200 == resp.status\n\n\nasync def test_ssl_client(\n    aiohttp_server,\n    ssl_ctx,\n    aiohttp_client,\n    client_ssl_ctx,\n) -> None:\n    connector = aiohttp.TCPConnector(ssl=client_ssl_ctx)\n\n    async def handler(request):\n        return web.Response(text=\"Test message\")\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    server = await aiohttp_server(app, ssl=ssl_ctx)\n    client = await aiohttp_client(server, connector=connector)\n\n    resp = await client.get(\"/\")\n    assert 200 == resp.status\n    txt = await resp.text()\n    assert txt == \"Test message\"\n\n\nasync def test_tcp_connector_fingerprint_ok(\n    aiohttp_server,\n    aiohttp_client,\n    ssl_ctx,\n    tls_certificate_fingerprint_sha256,\n):\n    tls_fingerprint = Fingerprint(tls_certificate_fingerprint_sha256)\n\n    async def handler(request):\n        return web.Response(text=\"Test message\")\n\n    connector = aiohttp.TCPConnector(ssl=tls_fingerprint)\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    server = await aiohttp_server(app, ssl=ssl_ctx)\n    client = await aiohttp_client(server, connector=connector)\n\n    async with client.get(\"/\") as resp:\n        assert resp.status == 200\n\n\nasync def test_tcp_connector_fingerprint_fail(\n    aiohttp_server,\n    aiohttp_client,\n    ssl_ctx,\n    tls_certificate_fingerprint_sha256,\n):\n    async def handler(request):\n        return web.Response(text=\"Test message\")\n\n    bad_fingerprint = b\"\\x00\" * len(tls_certificate_fingerprint_sha256)\n\n    connector = aiohttp.TCPConnector(ssl=Fingerprint(bad_fingerprint))\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    server = await aiohttp_server(app, ssl=ssl_ctx)\n    client = await aiohttp_client(server, connector=connector)\n\n    with pytest.raises(ServerFingerprintMismatch) as cm:\n        await client.get(\"/\")\n    exc = cm.value\n    assert exc.expected == bad_fingerprint\n    assert exc.got == tls_certificate_fingerprint_sha256\n\n\nasync def test_format_task_get(aiohttp_server) -> None:\n    async def handler(request):\n        return web.Response(body=b\"OK\")\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    server = await aiohttp_server(app)\n    client = aiohttp.ClientSession()\n    task = asyncio.create_task(client.get(server.make_url(\"/\")))\n    assert f\"{task}\".startswith(\"<Task pending\")\n    resp = await task\n    resp.close()\n    await client.close()\n\n\nasync def test_str_params(aiohttp_client) -> None:\n    async def handler(request):\n        assert \"q=t est\" in request.rel_url.query_string\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/\", params=\"q=t+est\") as resp:\n        assert 200 == resp.status\n\n\nasync def test_drop_params_on_redirect(aiohttp_client) -> None:\n    async def handler_redirect(request):\n        return web.Response(status=301, headers={\"Location\": \"/ok?a=redirect\"})\n\n    async def handler_ok(request):\n        assert request.rel_url.query_string == \"a=redirect\"\n        return web.Response(status=200)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/ok\", handler_ok)\n    app.router.add_route(\"GET\", \"/redirect\", handler_redirect)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/redirect\", params={\"a\": \"initial\"}) as resp:\n        assert resp.status == 200\n\n\nasync def test_drop_fragment_on_redirect(aiohttp_client) -> None:\n    async def handler_redirect(request):\n        return web.Response(status=301, headers={\"Location\": \"/ok#fragment\"})\n\n    async def handler_ok(request):\n        return web.Response(status=200)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/ok\", handler_ok)\n    app.router.add_route(\"GET\", \"/redirect\", handler_redirect)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/redirect\") as resp:\n        assert resp.status == 200\n        assert resp.url.path == \"/ok\"\n\n\nasync def test_drop_fragment(aiohttp_client) -> None:\n    async def handler_ok(request):\n        return web.Response(status=200)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/ok\", handler_ok)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/ok#fragment\") as resp:\n        assert resp.status == 200\n        assert resp.url.path == \"/ok\"\n\n\nasync def test_history(aiohttp_client) -> None:\n    async def handler_redirect(request):\n        return web.Response(status=301, headers={\"Location\": \"/ok\"})\n\n    async def handler_ok(request):\n        return web.Response(status=200)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/ok\", handler_ok)\n    app.router.add_route(\"GET\", \"/redirect\", handler_redirect)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/ok\") as resp:\n        assert len(resp.history) == 0\n        assert resp.status == 200\n\n    async with client.get(\"/redirect\") as resp_redirect:\n        assert len(resp_redirect.history) == 1\n        assert resp_redirect.history[0].status == 301\n        assert resp_redirect.status == 200\n\n\nasync def test_keepalive_closed_by_server(aiohttp_client) -> None:\n    async def handler(request):\n        body = await request.read()\n        assert b\"\" == body\n        resp = web.Response(body=b\"OK\")\n        resp.force_close()\n        return resp\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    connector = aiohttp.TCPConnector(limit=1)\n    client = await aiohttp_client(app, connector=connector)\n\n    resp1 = await client.get(\"/\")\n    val1 = await resp1.read()\n    assert val1 == b\"OK\"\n    resp2 = await client.get(\"/\")\n    val2 = await resp2.read()\n    assert val2 == b\"OK\"\n\n    assert 0 == len(client._session.connector._conns)\n\n\nasync def test_wait_for(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(body=b\"OK\")\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await asyncio.wait_for(client.get(\"/\"), 10)\n    assert resp.status == 200\n    txt = await resp.text()\n    assert txt == \"OK\"\n\n\nasync def test_raw_headers(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    async with client.get(\"/\") as resp:\n        assert resp.status == 200\n\n        raw_headers = tuple((bytes(h), bytes(v)) for h, v in resp.raw_headers)\n        assert raw_headers == (\n            (b\"Content-Length\", b\"0\"),\n            (b\"Date\", mock.ANY),\n            (b\"Server\", mock.ANY),\n        )\n\n\nasync def test_host_header_first(aiohttp_client) -> None:\n    async def handler(request):\n        assert list(request.headers)[0] == hdrs.HOST\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    async with client.get(\"/\") as resp:\n        assert resp.status == 200\n\n\nasync def test_empty_header_values(aiohttp_client) -> None:\n    async def handler(request):\n        resp = web.Response()\n        resp.headers[\"X-Empty\"] = \"\"\n        return resp\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    async with client.get(\"/\") as resp:\n        assert resp.status == 200\n        raw_headers = tuple((bytes(h), bytes(v)) for h, v in resp.raw_headers)\n        assert raw_headers == (\n            (b\"X-Empty\", b\"\"),\n            (b\"Content-Length\", b\"0\"),\n            (b\"Date\", mock.ANY),\n            (b\"Server\", mock.ANY),\n        )\n\n\nasync def test_204_with_gzipped_content_encoding(aiohttp_client) -> None:\n    async def handler(request):\n        resp = web.StreamResponse(status=204)\n        resp.content_length = 0\n        resp.content_type = \"application/json\"\n        # resp.enable_compression(web.ContentCoding.gzip)\n        resp.headers[\"Content-Encoding\"] = \"gzip\"\n        await resp.prepare(request)\n        return resp\n\n    app = web.Application()\n    app.router.add_route(\"DELETE\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.delete(\"/\") as resp:\n        assert resp.status == 204\n        assert resp.closed\n\n\nasync def test_timeout_on_reading_headers(aiohttp_client, mocker) -> None:\n    async def handler(request):\n        resp = web.StreamResponse()\n        await asyncio.sleep(0.1)\n        await resp.prepare(request)\n        return resp\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    with pytest.raises(asyncio.TimeoutError):\n        await client.get(\"/\", timeout=0.01)\n\n\nasync def test_timeout_on_conn_reading_headers(aiohttp_client, mocker) -> None:\n    # tests case where user did not set a connection timeout\n\n    async def handler(request):\n        resp = web.StreamResponse()\n        await asyncio.sleep(0.1)\n        await resp.prepare(request)\n        return resp\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    conn = aiohttp.TCPConnector()\n    client = await aiohttp_client(app, connector=conn)\n\n    with pytest.raises(asyncio.TimeoutError):\n        await client.get(\"/\", timeout=0.01)\n\n\nasync def test_timeout_on_session_read_timeout(aiohttp_client, mocker) -> None:\n    async def handler(request):\n        resp = web.StreamResponse()\n        await asyncio.sleep(0.1)\n        await resp.prepare(request)\n        return resp\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    conn = aiohttp.TCPConnector()\n    client = await aiohttp_client(\n        app, connector=conn, timeout=aiohttp.ClientTimeout(sock_read=0.01)\n    )\n\n    with pytest.raises(asyncio.TimeoutError):\n        await client.get(\"/\")\n\n\nasync def test_read_timeout_between_chunks(aiohttp_client, mocker) -> None:\n    async def handler(request):\n        resp = aiohttp.web.StreamResponse()\n        await resp.prepare(request)\n        # write data 4 times, with pauses. Total time 2 seconds.\n        for _ in range(4):\n            await asyncio.sleep(0.5)\n            await resp.write(b\"data\\n\")\n        return resp\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    # A timeout of 0.2 seconds should apply per read.\n    timeout = aiohttp.ClientTimeout(sock_read=1)\n    client = await aiohttp_client(app, timeout=timeout)\n\n    res = b\"\"\n    async with await client.get(\"/\") as resp:\n        res += await resp.read()\n\n    assert res == b\"data\\n\" * 4\n\n\nasync def test_read_timeout_on_reading_chunks(aiohttp_client, mocker) -> None:\n    async def handler(request):\n        resp = aiohttp.web.StreamResponse()\n        await resp.prepare(request)\n        await resp.write(b\"data\\n\")\n        await asyncio.sleep(1)\n        await resp.write(b\"data\\n\")\n        return resp\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    # A timeout of 0.2 seconds should apply per read.\n    timeout = aiohttp.ClientTimeout(sock_read=0.2)\n    client = await aiohttp_client(app, timeout=timeout)\n\n    async with await client.get(\"/\") as resp:\n        assert (await resp.content.read(5)) == b\"data\\n\"\n        with pytest.raises(asyncio.TimeoutError):\n            await resp.content.read()\n\n\nasync def test_read_timeout_on_write(aiohttp_client) -> None:\n    async def gen_payload() -> AsyncIterator[str]:\n        # Delay writing to ensure read timeout isn't triggered before writing completes.\n        await asyncio.sleep(0.5)\n        yield b\"foo\"\n\n    async def handler(request: web.Request) -> web.Response:\n        return web.Response(body=await request.read())\n\n    app = web.Application()\n    app.router.add_put(\"/\", handler)\n\n    timeout = aiohttp.ClientTimeout(total=None, sock_read=0.1)\n    client = await aiohttp_client(app)\n    async with client.put(\"/\", data=gen_payload(), timeout=timeout) as resp:\n        result = await resp.read()  # Should not trigger a read timeout.\n    assert result == b\"foo\"\n\n\nasync def test_timeout_on_reading_data(aiohttp_client, mocker) -> None:\n    loop = asyncio.get_event_loop()\n\n    fut = loop.create_future()\n\n    async def handler(request):\n        resp = web.StreamResponse(headers={\"content-length\": \"100\"})\n        await resp.prepare(request)\n        fut.set_result(None)\n        await asyncio.sleep(0.2)\n        return resp\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\", timeout=1)\n    await fut\n\n    with pytest.raises(asyncio.TimeoutError):\n        await resp.read()\n\n\nasync def test_timeout_none(aiohttp_client, mocker) -> None:\n    async def handler(request):\n        resp = web.StreamResponse()\n        await resp.prepare(request)\n        return resp\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/\", timeout=None) as resp:\n        assert resp.status == 200\n\n\nasync def test_readline_error_on_conn_close(aiohttp_client) -> None:\n    loop = asyncio.get_event_loop()\n\n    async def handler(request):\n        resp_ = web.StreamResponse()\n        await resp_.prepare(request)\n\n        # make sure connection is closed by client.\n        with pytest.raises(aiohttp.ServerDisconnectedError):\n            for _ in range(10):\n                await resp_.write(b\"data\\n\")\n                await asyncio.sleep(0.5)\n            return resp_\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    server = await aiohttp_client(app)\n\n    session = aiohttp.ClientSession()\n    try:\n        timer_started = False\n        url, headers = server.make_url(\"/\"), {\"Connection\": \"Keep-alive\"}\n        resp = await session.get(url, headers=headers)\n        with pytest.raises(aiohttp.ClientConnectionError):\n            while True:\n                data = await resp.content.readline()\n                data = data.strip()\n                if not data:\n                    break\n                assert data == b\"data\"\n                if not timer_started:\n\n                    def do_release():\n                        loop.create_task(resp.release())\n\n                    loop.call_later(1.0, do_release)\n                    timer_started = True\n    finally:\n        await session.close()\n\n\nasync def test_no_error_on_conn_close_if_eof(aiohttp_client) -> None:\n    async def handler(request):\n        resp_ = web.StreamResponse()\n        await resp_.prepare(request)\n        await resp_.write(b\"data\\n\")\n        await asyncio.sleep(0.5)\n        return resp_\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    server = await aiohttp_client(app)\n\n    session = aiohttp.ClientSession()\n    try:\n        url, headers = server.make_url(\"/\"), {\"Connection\": \"Keep-alive\"}\n        resp = await session.get(url, headers=headers)\n        while True:\n            data = await resp.content.readline()\n            data = data.strip()\n            if not data:\n                break\n            assert data == b\"data\"\n\n        assert resp.content.exception() is None\n    finally:\n        await session.close()\n\n\nasync def test_error_not_overwrote_on_conn_close(aiohttp_client) -> None:\n    async def handler(request):\n        resp_ = web.StreamResponse()\n        await resp_.prepare(request)\n        return resp_\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    server = await aiohttp_client(app)\n\n    session = aiohttp.ClientSession()\n    try:\n        url, headers = server.make_url(\"/\"), {\"Connection\": \"Keep-alive\"}\n        resp = await session.get(url, headers=headers)\n        resp.content.set_exception(ValueError())\n    finally:\n        await session.close()\n\n    assert isinstance(resp.content.exception(), ValueError)\n\n\nasync def test_HTTP_200_OK_METHOD(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=request.method)\n\n    app = web.Application()\n    for meth in (\"get\", \"post\", \"put\", \"delete\", \"head\", \"patch\", \"options\"):\n        app.router.add_route(meth.upper(), \"/\", handler)\n\n    client = await aiohttp_client(app)\n    for meth in (\"get\", \"post\", \"put\", \"delete\", \"head\", \"patch\", \"options\"):\n        resp = await client.request(meth, \"/\")\n        assert resp.status == 200\n        assert len(resp.history) == 0\n\n        content1 = await resp.read()\n        content2 = await resp.read()\n        assert content1 == content2\n        content = await resp.text()\n\n        if meth == \"head\":\n            assert b\"\" == content1\n        else:\n            assert meth.upper() == content\n\n\nasync def test_HTTP_200_OK_METHOD_connector(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=request.method)\n\n    conn = aiohttp.TCPConnector()\n    conn.clear_dns_cache()\n\n    app = web.Application()\n    for meth in (\"get\", \"post\", \"put\", \"delete\", \"head\"):\n        app.router.add_route(meth.upper(), \"/\", handler)\n    client = await aiohttp_client(app, connector=conn)\n\n    for meth in (\"get\", \"post\", \"put\", \"delete\", \"head\"):\n        resp = await client.request(meth, \"/\")\n\n        content1 = await resp.read()\n        content2 = await resp.read()\n        assert content1 == content2\n        content = await resp.text()\n\n        assert resp.status == 200\n        if meth == \"head\":\n            assert b\"\" == content1\n        else:\n            assert meth.upper() == content\n\n\nasync def test_HTTP_302_REDIRECT_GET(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=request.method)\n\n    async def redirect(request):\n        raise web.HTTPFound(location=\"/\")\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    app.router.add_get(\"/redirect\", redirect)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/redirect\") as resp:\n        assert 200 == resp.status\n        assert 1 == len(resp.history)\n\n\nasync def test_HTTP_302_REDIRECT_HEAD(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=request.method)\n\n    async def redirect(request):\n        raise web.HTTPFound(location=\"/\")\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    app.router.add_get(\"/redirect\", redirect)\n    app.router.add_head(\"/\", handler)\n    app.router.add_head(\"/redirect\", redirect)\n    client = await aiohttp_client(app)\n\n    async with client.request(\"head\", \"/redirect\") as resp:\n        assert 200 == resp.status\n        assert 1 == len(resp.history)\n        assert resp.method == \"HEAD\"\n\n\nasync def test_HTTP_302_REDIRECT_NON_HTTP(aiohttp_client) -> None:\n    async def redirect(request):\n        raise web.HTTPFound(location=\"ftp://127.0.0.1/test/\")\n\n    app = web.Application()\n    app.router.add_get(\"/redirect\", redirect)\n    client = await aiohttp_client(app)\n\n    with pytest.raises(NonHttpUrlRedirectClientError):\n        await client.get(\"/redirect\")\n\n\nasync def test_HTTP_302_REDIRECT_POST(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=request.method)\n\n    async def redirect(request):\n        raise web.HTTPFound(location=\"/\")\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    app.router.add_post(\"/redirect\", redirect)\n    client = await aiohttp_client(app)\n\n    resp = await client.post(\"/redirect\")\n    assert 200 == resp.status\n    assert 1 == len(resp.history)\n    txt = await resp.text()\n    assert txt == \"GET\"\n    resp.close()\n\n\nasync def test_HTTP_302_REDIRECT_POST_with_content_length_hdr(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=request.method)\n\n    async def redirect(request):\n        await request.read()\n        raise web.HTTPFound(location=\"/\")\n\n    data = json.dumps({\"some\": \"data\"})\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    app.router.add_post(\"/redirect\", redirect)\n    client = await aiohttp_client(app)\n\n    resp = await client.post(\n        \"/redirect\", data=data, headers={\"Content-Length\": str(len(data))}\n    )\n    assert 200 == resp.status\n    assert 1 == len(resp.history)\n    txt = await resp.text()\n    assert txt == \"GET\"\n    resp.close()\n\n\nasync def test_HTTP_307_REDIRECT_POST(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=request.method)\n\n    async def redirect(request):\n        await request.read()\n        raise web.HTTPTemporaryRedirect(location=\"/\")\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    app.router.add_post(\"/redirect\", redirect)\n    client = await aiohttp_client(app)\n\n    resp = await client.post(\"/redirect\", data={\"some\": \"data\"})\n    assert 200 == resp.status\n    assert 1 == len(resp.history)\n    txt = await resp.text()\n    assert txt == \"POST\"\n    resp.close()\n\n\nasync def test_HTTP_308_PERMANENT_REDIRECT_POST(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=request.method)\n\n    async def redirect(request):\n        await request.read()\n        raise web.HTTPPermanentRedirect(location=\"/\")\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    app.router.add_post(\"/redirect\", redirect)\n    client = await aiohttp_client(app)\n\n    resp = await client.post(\"/redirect\", data={\"some\": \"data\"})\n    assert 200 == resp.status\n    assert 1 == len(resp.history)\n    txt = await resp.text()\n    assert txt == \"POST\"\n    resp.close()\n\n\nasync def test_HTTP_302_max_redirects(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=request.method)\n\n    async def redirect(request):\n        count = int(request.match_info[\"count\"])\n        if count:\n            raise web.HTTPFound(location=f\"/redirect/{count - 1}\")\n        else:\n            raise web.HTTPFound(location=\"/\")\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    app.router.add_get(r\"/redirect/{count:\\d+}\", redirect)\n    client = await aiohttp_client(app)\n\n    with pytest.raises(TooManyRedirects) as ctx:\n        await client.get(\"/redirect/5\", max_redirects=2)\n    assert 2 == len(ctx.value.history)\n    assert ctx.value.request_info.url.path == \"/redirect/5\"\n    assert ctx.value.request_info.method == \"GET\"\n\n\nasync def test_HTTP_200_GET_WITH_PARAMS(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(\n            text=\"&\".join(k + \"=\" + v for k, v in request.query.items())\n        )\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\", params={\"q\": \"test\"})\n    assert 200 == resp.status\n    txt = await resp.text()\n    assert txt == \"q=test\"\n    resp.close()\n\n\nasync def test_HTTP_200_GET_WITH_MultiDict_PARAMS(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(\n            text=\"&\".join(k + \"=\" + v for k, v in request.query.items())\n        )\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\", params=MultiDict([(\"q\", \"test\"), (\"q\", \"test2\")]))\n    assert 200 == resp.status\n    txt = await resp.text()\n    assert txt == \"q=test&q=test2\"\n    resp.close()\n\n\nasync def test_HTTP_200_GET_WITH_MIXED_PARAMS(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(\n            text=\"&\".join(k + \"=\" + v for k, v in request.query.items())\n        )\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/?test=true\", params={\"q\": \"test\"})\n    assert 200 == resp.status\n    txt = await resp.text()\n    assert txt == \"test=true&q=test\"\n    resp.close()\n\n\nasync def test_POST_DATA(aiohttp_client) -> None:\n    async def handler(request):\n        data = await request.post()\n        return web.json_response(dict(data))\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.post(\"/\", data={\"some\": \"data\"})\n    assert 200 == resp.status\n    content = await resp.json()\n    assert content == {\"some\": \"data\"}\n    resp.close()\n\n\nasync def test_POST_DATA_with_explicit_formdata(aiohttp_client) -> None:\n    async def handler(request):\n        data = await request.post()\n        return web.json_response(dict(data))\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    form = aiohttp.FormData()\n    form.add_field(\"name\", \"text\")\n\n    resp = await client.post(\"/\", data=form)\n    assert 200 == resp.status\n    content = await resp.json()\n    assert content == {\"name\": \"text\"}\n    resp.close()\n\n\nasync def test_POST_DATA_with_charset(aiohttp_client) -> None:\n    async def handler(request):\n        mp = await request.multipart()\n        part = await mp.next()\n        text = await part.text()\n        return web.Response(text=text)\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    form = aiohttp.FormData()\n    form.add_field(\"name\", \"текст\", content_type=\"text/plain; charset=koi8-r\")\n\n    resp = await client.post(\"/\", data=form)\n    assert 200 == resp.status\n    content = await resp.text()\n    assert content == \"текст\"\n    resp.close()\n\n\nasync def test_POST_DATA_formdats_with_charset(aiohttp_client) -> None:\n    async def handler(request):\n        mp = await request.post()\n        assert \"name\" in mp\n        return web.Response(text=mp[\"name\"])\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    form = aiohttp.FormData(charset=\"koi8-r\")\n    form.add_field(\"name\", \"текст\")\n\n    resp = await client.post(\"/\", data=form)\n    assert 200 == resp.status\n    content = await resp.text()\n    assert content == \"текст\"\n    resp.close()\n\n\nasync def test_POST_DATA_with_charset_post(aiohttp_client) -> None:\n    async def handler(request):\n        data = await request.post()\n        return web.Response(text=data[\"name\"])\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    form = aiohttp.FormData()\n    form.add_field(\"name\", \"текст\", content_type=\"text/plain; charset=koi8-r\")\n\n    resp = await client.post(\"/\", data=form)\n    assert 200 == resp.status\n    content = await resp.text()\n    assert content == \"текст\"\n    resp.close()\n\n\nasync def test_POST_MultiDict(aiohttp_client) -> None:\n    async def handler(request):\n        data = await request.post()\n        assert data == MultiDict([(\"q\", \"test1\"), (\"q\", \"test2\")])\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.post(\n        \"/\", data=MultiDict([(\"q\", \"test1\"), (\"q\", \"test2\")])\n    ) as resp:\n        assert 200 == resp.status\n\n\nasync def test_POST_DATA_DEFLATE(aiohttp_client) -> None:\n    async def handler(request):\n        data = await request.post()\n        return web.json_response(dict(data))\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.post(\"/\", data={\"some\": \"data\"}, compress=True)\n    assert 200 == resp.status\n    content = await resp.json()\n    assert content == {\"some\": \"data\"}\n    resp.close()\n\n\nasync def test_POST_FILES(aiohttp_client, fname) -> None:\n    async def handler(request):\n        data = await request.post()\n        assert data[\"some\"].filename == fname.name\n        with fname.open(\"rb\") as f:\n            content1 = f.read()\n        content2 = data[\"some\"].file.read()\n        assert content1 == content2\n        assert data[\"test\"].file.read() == b\"data\"\n        data[\"some\"].file.close()\n        data[\"test\"].file.close()\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with fname.open(\"rb\") as f:\n        async with client.post(\n            \"/\", data={\"some\": f, \"test\": io.BytesIO(b\"data\")}, chunked=True\n        ) as resp:\n            assert 200 == resp.status\n\n\nasync def test_POST_FILES_DEFLATE(aiohttp_client, fname) -> None:\n    async def handler(request):\n        data = await request.post()\n        assert data[\"some\"].filename == fname.name\n        with fname.open(\"rb\") as f:\n            content1 = f.read()\n        content2 = data[\"some\"].file.read()\n        data[\"some\"].file.close()\n        assert content1 == content2\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with fname.open(\"rb\") as f:\n        async with client.post(\n            \"/\", data={\"some\": f}, chunked=True, compress=\"deflate\"\n        ) as resp:\n            assert 200 == resp.status\n\n\nasync def test_POST_bytes(aiohttp_client) -> None:\n    body = b\"0\" * 12345\n\n    async def handler(request):\n        data = await request.read()\n        assert body == data\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.post(\"/\", data=body) as resp:\n        assert 200 == resp.status\n\n\nasync def test_POST_bytes_too_large(aiohttp_client) -> None:\n    body = b\"0\" * (2**20 + 1)\n\n    async def handler(request):\n        data = await request.content.read()\n        assert body == data\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with pytest.warns(ResourceWarning):\n        resp = await client.post(\"/\", data=body)\n\n    assert 200 == resp.status\n    resp.close()\n\n\nasync def test_POST_FILES_STR(aiohttp_client, fname) -> None:\n    async def handler(request):\n        data = await request.post()\n        with fname.open(\"rb\") as f:\n            content1 = f.read().decode()\n        content2 = data[\"some\"]\n        assert content1 == content2\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with fname.open(\"rb\") as f:\n        async with client.post(\"/\", data={\"some\": f.read().decode()}) as resp:\n            assert 200 == resp.status\n\n\nasync def test_POST_FILES_STR_SIMPLE(aiohttp_client, fname) -> None:\n    async def handler(request):\n        data = await request.read()\n        with fname.open(\"rb\") as f:\n            content = f.read()\n        assert content == data\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with fname.open(\"rb\") as f:\n        async with client.post(\"/\", data=f.read()) as resp:\n            assert 200 == resp.status\n\n\nasync def test_POST_FILES_LIST(aiohttp_client, fname) -> None:\n    async def handler(request):\n        data = await request.post()\n        assert fname.name == data[\"some\"].filename\n        with fname.open(\"rb\") as f:\n            content = f.read()\n        assert content == data[\"some\"].file.read()\n        data[\"some\"].file.close()\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with fname.open(\"rb\") as f:\n        async with client.post(\"/\", data=[(\"some\", f)]) as resp:\n            assert 200 == resp.status\n\n\nasync def test_POST_FILES_CT(aiohttp_client, fname) -> None:\n    async def handler(request):\n        data = await request.post()\n        assert fname.name == data[\"some\"].filename\n        assert \"text/plain\" == data[\"some\"].content_type\n        with fname.open(\"rb\") as f:\n            content = f.read()\n        assert content == data[\"some\"].file.read()\n        data[\"some\"].file.close()\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with fname.open(\"rb\") as f:\n        form = aiohttp.FormData()\n        form.add_field(\"some\", f, content_type=\"text/plain\")\n        async with client.post(\"/\", data=form) as resp:\n            assert 200 == resp.status\n\n\nasync def test_POST_FILES_SINGLE(aiohttp_client, fname) -> None:\n    async def handler(request):\n        data = await request.text()\n        with fname.open(\"rb\") as f:\n            content = f.read().decode()\n            assert content == data\n        # if system cannot determine 'text/x-python' MIME type\n        # then use 'application/octet-stream' default\n        assert request.content_type in [\n            \"text/plain\",\n            \"application/octet-stream\",\n            \"text/x-python\",\n        ]\n        assert \"content-disposition\" not in request.headers\n\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with fname.open(\"rb\") as f:\n        async with client.post(\"/\", data=f) as resp:\n            assert 200 == resp.status\n\n\nasync def test_POST_FILES_SINGLE_content_disposition(aiohttp_client, fname) -> None:\n    async def handler(request):\n        data = await request.text()\n        with fname.open(\"rb\") as f:\n            content = f.read().decode()\n            assert content == data\n        # if system cannot determine 'application/pgp-keys' MIME type\n        # then use 'application/octet-stream' default\n        assert request.content_type in [\n            \"text/plain\",\n            \"application/octet-stream\",\n            \"text/x-python\",\n        ]\n        assert request.headers[\"content-disposition\"] == (\n            'inline; filename=\"conftest.py\"'\n        )\n\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with fname.open(\"rb\") as f:\n        async with client.post(\n            \"/\", data=aiohttp.get_payload(f, disposition=\"inline\")\n        ) as resp:\n            assert 200 == resp.status\n\n\nasync def test_POST_FILES_SINGLE_BINARY(aiohttp_client, fname) -> None:\n    async def handler(request):\n        data = await request.read()\n        with fname.open(\"rb\") as f:\n            content = f.read()\n        assert content == data\n        # if system cannot determine 'application/pgp-keys' MIME type\n        # then use 'application/octet-stream' default\n        assert request.content_type in [\n            \"application/pgp-keys\",\n            \"text/plain\",\n            \"text/x-python\",\n            \"application/octet-stream\",\n        ]\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with fname.open(\"rb\") as f:\n        async with client.post(\"/\", data=f) as resp:\n            assert 200 == resp.status\n\n\nasync def test_POST_FILES_IO(aiohttp_client) -> None:\n    async def handler(request):\n        data = await request.post()\n        assert b\"data\" == data[\"unknown\"].file.read()\n        assert data[\"unknown\"].content_type == \"application/octet-stream\"\n        assert data[\"unknown\"].filename == \"unknown\"\n        data[\"unknown\"].file.close()\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with io.BytesIO(b\"data\") as file_handle:\n        async with client.post(\"/\", data=[file_handle]) as resp:\n            assert 200 == resp.status\n\n\nasync def test_POST_FILES_IO_WITH_PARAMS(aiohttp_client) -> None:\n    async def handler(request):\n        data = await request.post()\n        assert data[\"test\"] == \"true\"\n        assert data[\"unknown\"].content_type == \"application/octet-stream\"\n        assert data[\"unknown\"].filename == \"unknown\"\n        assert data[\"unknown\"].file.read() == b\"data\"\n        data[\"unknown\"].file.close()\n        assert data.getall(\"q\") == [\"t1\", \"t2\"]\n\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with io.BytesIO(b\"data\") as file_handle:\n        async with client.post(\n            \"/\",\n            data=((\"test\", \"true\"), MultiDict([(\"q\", \"t1\"), (\"q\", \"t2\")]), file_handle),\n        ) as resp:\n            assert 200 == resp.status\n\n\nasync def test_POST_FILES_WITH_DATA(aiohttp_client, fname) -> None:\n    async def handler(request):\n        data = await request.post()\n        assert data[\"test\"] == \"true\"\n        assert data[\"some\"].content_type in [\n            \"text/x-python\",\n            \"text/plain\",\n            \"application/octet-stream\",\n        ]\n        assert data[\"some\"].filename == fname.name\n        with fname.open(\"rb\") as f:\n            assert data[\"some\"].file.read() == f.read()\n            data[\"some\"].file.close()\n\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with fname.open(\"rb\") as f:\n        async with client.post(\"/\", data={\"test\": \"true\", \"some\": f}) as resp:\n            assert 200 == resp.status\n\n\nasync def test_POST_STREAM_DATA(aiohttp_client, fname) -> None:\n    async def handler(request):\n        assert request.content_type == \"application/octet-stream\"\n        content = await request.read()\n        with fname.open(\"rb\") as f:\n            expected = f.read()\n            assert request.content_length == len(expected)\n            assert content == expected\n\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with fname.open(\"rb\") as f:\n        data_size = len(f.read())\n\n    with pytest.warns(DeprecationWarning):\n\n        @aiohttp.streamer\n        async def stream(writer, fname):\n            with fname.open(\"rb\") as f:\n                data = f.read(100)\n                while data:\n                    await writer.write(data)\n                    data = f.read(100)\n\n    async with client.post(\n        \"/\", data=stream(fname), headers={\"Content-Length\": str(data_size)}\n    ) as resp:\n        assert 200 == resp.status\n\n\nasync def test_POST_STREAM_DATA_no_params(aiohttp_client, fname) -> None:\n    async def handler(request):\n        assert request.content_type == \"application/octet-stream\"\n        content = await request.read()\n        with fname.open(\"rb\") as f:\n            expected = f.read()\n            assert request.content_length == len(expected)\n            assert content == expected\n\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with fname.open(\"rb\") as f:\n        data_size = len(f.read())\n\n    with pytest.warns(DeprecationWarning):\n\n        @aiohttp.streamer\n        async def stream(writer):\n            with fname.open(\"rb\") as f:\n                data = f.read(100)\n                while data:\n                    await writer.write(data)\n                    data = f.read(100)\n\n    async with client.post(\n        \"/\", data=stream, headers={\"Content-Length\": str(data_size)}\n    ) as resp:\n        assert 200 == resp.status\n\n\nasync def test_json(aiohttp_client) -> None:\n    async def handler(request):\n        assert request.content_type == \"application/json\"\n        data = await request.json()\n        return web.Response(body=aiohttp.JsonPayload(data))\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.post(\"/\", json={\"some\": \"data\"})\n    assert 200 == resp.status\n    content = await resp.json()\n    assert content == {\"some\": \"data\"}\n    resp.close()\n\n    with pytest.raises(ValueError):\n        await client.post(\"/\", data=\"some data\", json={\"some\": \"data\"})\n\n\nasync def test_json_custom(aiohttp_client) -> None:\n    async def handler(request):\n        assert request.content_type == \"application/json\"\n        data = await request.json()\n        return web.Response(body=aiohttp.JsonPayload(data))\n\n    used = False\n\n    def dumps(obj):\n        nonlocal used\n        used = True\n        return json.dumps(obj)\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app, json_serialize=dumps)\n\n    resp = await client.post(\"/\", json={\"some\": \"data\"})\n    assert 200 == resp.status\n    assert used\n    content = await resp.json()\n    assert content == {\"some\": \"data\"}\n    resp.close()\n\n    with pytest.raises(ValueError):\n        await client.post(\"/\", data=\"some data\", json={\"some\": \"data\"})\n\n\nasync def test_expect_continue(aiohttp_client) -> None:\n    expect_called = False\n\n    async def handler(request):\n        data = await request.post()\n        assert data == {\"some\": \"data\"}\n        return web.Response()\n\n    async def expect_handler(request):\n        nonlocal expect_called\n        expect = request.headers.get(hdrs.EXPECT)\n        if expect.lower() == \"100-continue\":\n            request.transport.write(b\"HTTP/1.1 100 Continue\\r\\n\\r\\n\")\n            expect_called = True\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler, expect_handler=expect_handler)\n    client = await aiohttp_client(app)\n\n    async with client.post(\"/\", data={\"some\": \"data\"}, expect100=True) as resp:\n        assert 200 == resp.status\n    assert expect_called\n\n\nasync def test_encoding_deflate(aiohttp_client) -> None:\n    async def handler(request):\n        resp = web.Response(text=\"text\")\n        resp.enable_chunked_encoding()\n        resp.enable_compression(web.ContentCoding.deflate)\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert 200 == resp.status\n    txt = await resp.text()\n    assert txt == \"text\"\n    resp.close()\n\n\nasync def test_encoding_deflate_nochunk(aiohttp_client) -> None:\n    async def handler(request):\n        resp = web.Response(text=\"text\")\n        resp.enable_compression(web.ContentCoding.deflate)\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert 200 == resp.status\n    txt = await resp.text()\n    assert txt == \"text\"\n    resp.close()\n\n\nasync def test_encoding_gzip(aiohttp_client) -> None:\n    async def handler(request):\n        resp = web.Response(text=\"text\")\n        resp.enable_chunked_encoding()\n        resp.enable_compression(web.ContentCoding.gzip)\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert 200 == resp.status\n    txt = await resp.text()\n    assert txt == \"text\"\n    resp.close()\n\n\nasync def test_encoding_gzip_write_by_chunks(aiohttp_client) -> None:\n    async def handler(request):\n        resp = web.StreamResponse()\n        resp.enable_compression(web.ContentCoding.gzip)\n        await resp.prepare(request)\n        await resp.write(b\"0\")\n        await resp.write(b\"0\")\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert 200 == resp.status\n    txt = await resp.text()\n    assert txt == \"00\"\n    resp.close()\n\n\nasync def test_encoding_gzip_nochunk(aiohttp_client) -> None:\n    async def handler(request):\n        resp = web.Response(text=\"text\")\n        resp.enable_compression(web.ContentCoding.gzip)\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert 200 == resp.status\n    txt = await resp.text()\n    assert txt == \"text\"\n    resp.close()\n\n\nasync def test_bad_payload_compression(aiohttp_client) -> None:\n    async def handler(request):\n        resp = web.Response(text=\"text\")\n        resp.headers[\"Content-Encoding\"] = \"gzip\"\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert 200 == resp.status\n\n    with pytest.raises(aiohttp.ClientPayloadError):\n        await resp.read()\n\n    resp.close()\n\n\nasync def test_bad_payload_chunked_encoding(aiohttp_client) -> None:\n    async def handler(request):\n        resp = web.StreamResponse()\n        resp.force_close()\n        resp._length_check = False\n        resp.headers[\"Transfer-Encoding\"] = \"chunked\"\n        writer = await resp.prepare(request)\n        await writer.write(b\"9\\r\\n\\r\\n\")\n        await writer.write_eof()\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert 200 == resp.status\n\n    with pytest.raises(aiohttp.ClientPayloadError):\n        await resp.read()\n\n    resp.close()\n\n\nasync def test_no_payload_304_with_chunked_encoding(aiohttp_client: Any) -> None:\n    \"\"\"Test a 304 response with no payload with chunked set should have it removed.\"\"\"\n\n    async def handler(request):\n        resp = web.StreamResponse(status=304)\n        resp.enable_chunked_encoding()\n        resp._length_check = False\n        resp.headers[\"Transfer-Encoding\"] = \"chunked\"\n        writer = await resp.prepare(request)\n        await writer.write_eof()\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert resp.status == 304\n    assert hdrs.CONTENT_LENGTH not in resp.headers\n    assert hdrs.TRANSFER_ENCODING not in resp.headers\n    await resp.read()\n\n    resp.close()\n\n\nasync def test_head_request_with_chunked_encoding(aiohttp_client: Any) -> None:\n    \"\"\"Test a head response with chunked set should have it removed.\"\"\"\n\n    async def handler(request):\n        resp = web.StreamResponse(status=200)\n        resp.enable_chunked_encoding()\n        resp._length_check = False\n        resp.headers[\"Transfer-Encoding\"] = \"chunked\"\n        writer = await resp.prepare(request)\n        await writer.write_eof()\n        return resp\n\n    app = web.Application()\n    app.router.add_head(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.head(\"/\")\n    assert resp.status == 200\n    assert hdrs.CONTENT_LENGTH not in resp.headers\n    assert hdrs.TRANSFER_ENCODING not in resp.headers\n    await resp.read()\n\n    resp.close()\n\n\nasync def test_no_payload_200_with_chunked_encoding(aiohttp_client: Any) -> None:\n    \"\"\"Test chunked is preserved on a 200 response with no payload.\"\"\"\n\n    async def handler(request):\n        resp = web.StreamResponse(status=200)\n        resp.enable_chunked_encoding()\n        resp._length_check = False\n        resp.headers[\"Transfer-Encoding\"] = \"chunked\"\n        writer = await resp.prepare(request)\n        await writer.write_eof()\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert resp.status == 200\n    assert hdrs.CONTENT_LENGTH not in resp.headers\n    assert hdrs.TRANSFER_ENCODING in resp.headers\n    await resp.read()\n\n    resp.close()\n\n\nasync def test_bad_payload_content_length(aiohttp_client: Any) -> None:\n    async def handler(request):\n        resp = web.Response(text=\"text\")\n        resp.headers[\"Content-Length\"] = \"10000\"\n        resp.force_close()\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert 200 == resp.status\n\n    with pytest.raises(aiohttp.ClientPayloadError):\n        await resp.read()\n\n    resp.close()\n\n\nasync def test_payload_content_length_by_chunks(aiohttp_client) -> None:\n    async def handler(request):\n        resp = web.StreamResponse(headers={\"content-length\": \"2\"})\n        await resp.prepare(request)\n        await resp.write(b\"answer\")\n        await resp.write(b\"two\")\n        request.transport.close()\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    data = await resp.read()\n    assert data == b\"an\"\n    resp.close()\n\n\nasync def test_chunked(aiohttp_client) -> None:\n    async def handler(request):\n        resp = web.Response(text=\"text\")\n        resp.enable_chunked_encoding()\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert 200 == resp.status\n    assert resp.headers[\"Transfer-Encoding\"] == \"chunked\"\n    txt = await resp.text()\n    assert txt == \"text\"\n    resp.close()\n\n\nasync def test_shortcuts(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=request.method)\n\n    app = web.Application()\n    for meth in (\"get\", \"post\", \"put\", \"delete\", \"head\", \"patch\", \"options\"):\n        app.router.add_route(meth.upper(), \"/\", handler)\n    client = await aiohttp_client(app)\n\n    for meth in (\"get\", \"post\", \"put\", \"delete\", \"head\", \"patch\", \"options\"):\n        coro = getattr(client.session, meth)\n        resp = await coro(client.make_url(\"/\"))\n\n        assert resp.status == 200\n        assert len(resp.history) == 0\n\n        content1 = await resp.read()\n        content2 = await resp.read()\n        assert content1 == content2\n        content = await resp.text()\n\n        if meth == \"head\":\n            assert b\"\" == content1\n        else:\n            assert meth.upper() == content\n\n\nasync def test_cookies(aiohttp_client) -> None:\n    async def handler(request):\n        assert request.cookies.keys() == {\"test1\", \"test3\"}\n        assert request.cookies[\"test1\"] == \"123\"\n        assert request.cookies[\"test3\"] == \"456\"\n        return web.Response()\n\n    c = http.cookies.Morsel()\n    c.set(\"test3\", \"456\", \"456\")\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app, cookies={\"test1\": \"123\", \"test2\": c})\n\n    async with client.get(\"/\") as resp:\n        assert 200 == resp.status\n\n\nasync def test_cookies_per_request(aiohttp_client) -> None:\n    async def handler(request):\n        assert request.cookies.keys() == {\"test1\", \"test3\", \"test4\", \"test6\"}\n        assert request.cookies[\"test1\"] == \"123\"\n        assert request.cookies[\"test3\"] == \"456\"\n        assert request.cookies[\"test4\"] == \"789\"\n        assert request.cookies[\"test6\"] == \"abc\"\n        return web.Response()\n\n    c = http.cookies.Morsel()\n    c.set(\"test3\", \"456\", \"456\")\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app, cookies={\"test1\": \"123\", \"test2\": c})\n\n    rc = http.cookies.Morsel()\n    rc.set(\"test6\", \"abc\", \"abc\")\n\n    async with client.get(\"/\", cookies={\"test4\": \"789\", \"test5\": rc}) as resp:\n        assert 200 == resp.status\n\n\nasync def test_cookies_redirect(aiohttp_client) -> None:\n    async def redirect1(request):\n        ret = web.Response(status=301, headers={\"Location\": \"/redirect2\"})\n        ret.set_cookie(\"c\", \"1\")\n        return ret\n\n    async def redirect2(request):\n        ret = web.Response(status=301, headers={\"Location\": \"/\"})\n        ret.set_cookie(\"c\", \"2\")\n        return ret\n\n    async def handler(request):\n        assert request.cookies.keys() == {\"c\"}\n        assert request.cookies[\"c\"] == \"2\"\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_get(\"/redirect1\", redirect1)\n    app.router.add_get(\"/redirect2\", redirect2)\n    app.router.add_get(\"/\", handler)\n\n    client = await aiohttp_client(app)\n    async with client.get(\"/redirect1\") as resp:\n        assert 200 == resp.status\n\n\nasync def test_cookies_on_empty_session_jar(aiohttp_client) -> None:\n    async def handler(request):\n        assert \"custom-cookie\" in request.cookies\n        assert request.cookies[\"custom-cookie\"] == \"abc\"\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app, cookies=None)\n\n    async with client.get(\"/\", cookies={\"custom-cookie\": \"abc\"}) as resp:\n        assert 200 == resp.status\n\n\nasync def test_morsel_with_attributes(aiohttp_client) -> None:\n    # A comment from original test:\n    #\n    # No cookie attribute should pass here\n    # they are only used as filters\n    # whether to send particular cookie or not.\n    # E.g. if cookie expires it just becomes thrown away.\n    # Server who sent the cookie with some attributes\n    # already knows them, no need to send this back again and again\n\n    async def handler(request):\n        assert request.cookies.keys() == {\"test3\"}\n        assert request.cookies[\"test3\"] == \"456\"\n        return web.Response()\n\n    c = http.cookies.Morsel()\n    c.set(\"test3\", \"456\", \"456\")\n    c[\"httponly\"] = True\n    c[\"secure\"] = True\n    c[\"max-age\"] = 1000\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app, cookies={\"test2\": c})\n\n    async with client.get(\"/\") as resp:\n        assert 200 == resp.status\n\n\nasync def test_set_cookies(aiohttp_client) -> None:\n    async def handler(request):\n        ret = web.Response()\n        ret.set_cookie(\"c1\", \"cookie1\")\n        ret.set_cookie(\"c2\", \"cookie2\")\n        ret.headers.add(\n            \"Set-Cookie\",\n            \"ISAWPLB{A7F52349-3531-4DA9-8776-F74BC6F4F1BB}=\"\n            \"{925EC0B8-CB17-4BEB-8A35-1033813B0523}; \"\n            \"HttpOnly; Path=/\",\n        )\n        return ret\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with mock.patch(\"aiohttp.client_reqrep.client_logger\") as m_log:\n        async with client.get(\"/\") as resp:\n            assert 200 == resp.status\n            cookie_names = {c.key for c in client.session.cookie_jar}\n        assert cookie_names == {\"c1\", \"c2\"}\n\n        m_log.warning.assert_called_with(\"Can not load response cookies: %s\", mock.ANY)\n\n\nasync def test_set_cookies_expired(aiohttp_client) -> None:\n    async def handler(request):\n        ret = web.Response()\n        ret.set_cookie(\"c1\", \"cookie1\")\n        ret.set_cookie(\"c2\", \"cookie2\")\n        ret.headers.add(\n            \"Set-Cookie\",\n            \"c3=cookie3; \" \"HttpOnly; Path=/\" \" Expires=Tue, 1 Jan 1980 12:00:00 GMT; \",\n        )\n        return ret\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/\") as resp:\n        assert 200 == resp.status\n        cookie_names = {c.key for c in client.session.cookie_jar}\n    assert cookie_names == {\"c1\", \"c2\"}\n\n\nasync def test_set_cookies_max_age(aiohttp_client) -> None:\n    async def handler(request):\n        ret = web.Response()\n        ret.set_cookie(\"c1\", \"cookie1\")\n        ret.set_cookie(\"c2\", \"cookie2\")\n        ret.headers.add(\"Set-Cookie\", \"c3=cookie3; \" \"HttpOnly; Path=/\" \" Max-Age=1; \")\n        return ret\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/\") as resp:\n        assert 200 == resp.status\n        cookie_names = {c.key for c in client.session.cookie_jar}\n        assert cookie_names == {\"c1\", \"c2\", \"c3\"}\n        await asyncio.sleep(2)\n        cookie_names = {c.key for c in client.session.cookie_jar}\n        assert cookie_names == {\"c1\", \"c2\"}\n\n\nasync def test_set_cookies_max_age_overflow(aiohttp_client) -> None:\n    async def handler(request):\n        ret = web.Response()\n        ret.headers.add(\n            \"Set-Cookie\",\n            \"overflow=overflow; \" \"HttpOnly; Path=/\" \" Max-Age=\" + str(overflow) + \"; \",\n        )\n        return ret\n\n    overflow = int(\n        datetime.datetime.max.replace(tzinfo=datetime.timezone.utc).timestamp()\n    )\n    empty = None\n    try:\n        empty = datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(\n            seconds=overflow\n        )\n    except OverflowError as ex:\n        assert isinstance(ex, OverflowError)\n    assert not isinstance(empty, datetime.datetime)\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/\") as resp:\n        assert 200 == resp.status\n        for cookie in client.session.cookie_jar:\n            if cookie.key == \"overflow\":\n                assert int(cookie[\"max-age\"]) == int(overflow)\n\n\nasync def test_request_conn_error() -> None:\n    client = aiohttp.ClientSession()\n    with pytest.raises(aiohttp.ClientConnectionError):\n        await client.get(\"http://0.0.0.0:1\")\n    await client.close()\n\n\n@pytest.mark.xfail\nasync def test_broken_connection(aiohttp_client) -> None:\n    async def handler(request):\n        request.transport.close()\n        return web.Response(text=\"answer\" * 1000)\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with pytest.raises(aiohttp.ClientResponseError):\n        await client.get(\"/\")\n\n\nasync def test_broken_connection_2(aiohttp_client) -> None:\n    async def handler(request):\n        resp = web.StreamResponse(headers={\"content-length\": \"1000\"})\n        await resp.prepare(request)\n        await resp.write(b\"answer\")\n        request.transport.close()\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    with pytest.raises(aiohttp.ClientPayloadError):\n        await resp.read()\n    resp.close()\n\n\nasync def test_custom_headers(aiohttp_client) -> None:\n    async def handler(request):\n        assert request.headers[\"x-api-key\"] == \"foo\"\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.post(\n        \"/\", headers={\"Content-Type\": \"application/json\", \"x-api-key\": \"foo\"}\n    ) as resp:\n        assert resp.status == 200\n\n\nasync def test_redirect_to_absolute_url(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=request.method)\n\n    async def redirect(request):\n        raise web.HTTPFound(location=client.make_url(\"/\"))\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    app.router.add_get(\"/redirect\", redirect)\n\n    client = await aiohttp_client(app)\n    async with client.get(\"/redirect\") as resp:\n        assert 200 == resp.status\n\n\nasync def test_redirect_without_location_header(aiohttp_client) -> None:\n    body = b\"redirect\"\n\n    async def handler_redirect(request):\n        return web.Response(status=301, body=body)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/redirect\", handler_redirect)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/redirect\")\n    data = await resp.read()\n    assert data == body\n\n\nasync def test_chunked_deprecated(aiohttp_client) -> None:\n    async def handler_redirect(request):\n        return web.Response(status=301)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/redirect\", handler_redirect)\n    client = await aiohttp_client(app)\n\n    with pytest.warns(DeprecationWarning):\n        await client.post(\"/\", chunked=1024)\n\n\nINVALID_URL_WITH_ERROR_MESSAGE_YARL_NEW = (\n    # yarl.URL.__new__ raises ValueError\n    (\"http://:/\", \"http://:/\"),\n    (\"http://example.org:non_int_port/\", \"http://example.org:non_int_port/\"),\n)\n\nINVALID_URL_WITH_ERROR_MESSAGE_YARL_ORIGIN = (\n    # # yarl.URL.origin raises ValueError\n    (\"http:/\", \"http:///\"),\n    (\"http:/example.com\", \"http:///example.com\"),\n    (\"http:///example.com\", \"http:///example.com\"),\n)\n\nNON_HTTP_URL_WITH_ERROR_MESSAGE = (\n    (\"call:+380123456789\", r\"call:\\+380123456789\"),\n    (\"skype:handle\", \"skype:handle\"),\n    (\"slack://instance/room\", \"slack://instance/room\"),\n    (\"steam:code\", \"steam:code\"),\n    (\"twitter://handle\", \"twitter://handle\"),\n    (\"bluesky://profile/d:i:d\", \"bluesky://profile/d:i:d\"),\n)\n\n\n@pytest.mark.parametrize(\n    (\"url\", \"error_message_url\", \"expected_exception_class\"),\n    (\n        *(\n            (url, message, InvalidUrlClientError)\n            for (url, message) in INVALID_URL_WITH_ERROR_MESSAGE_YARL_NEW\n        ),\n        *(\n            (url, message, InvalidUrlClientError)\n            for (url, message) in INVALID_URL_WITH_ERROR_MESSAGE_YARL_ORIGIN\n        ),\n        *(\n            (url, message, NonHttpUrlClientError)\n            for (url, message) in NON_HTTP_URL_WITH_ERROR_MESSAGE\n        ),\n    ),\n)\nasync def test_invalid_and_non_http_url(\n    url: Any, error_message_url: Any, expected_exception_class: Any\n) -> None:\n    async with aiohttp.ClientSession() as http_session:\n        with pytest.raises(\n            expected_exception_class, match=rf\"^{error_message_url}( - [A-Za-z ]+)?\"\n        ):\n            await http_session.get(url)\n\n\n@pytest.mark.parametrize(\n    (\"invalid_redirect_url\", \"error_message_url\", \"expected_exception_class\"),\n    (\n        *(\n            (url, message, InvalidUrlRedirectClientError)\n            for (url, message) in INVALID_URL_WITH_ERROR_MESSAGE_YARL_ORIGIN\n            + INVALID_URL_WITH_ERROR_MESSAGE_YARL_NEW\n        ),\n        *(\n            (url, message, NonHttpUrlRedirectClientError)\n            for (url, message) in NON_HTTP_URL_WITH_ERROR_MESSAGE\n        ),\n    ),\n)\nasync def test_invalid_redirect_url(\n    aiohttp_client: Any,\n    invalid_redirect_url: Any,\n    error_message_url: str,\n    expected_exception_class: Any,\n) -> None:\n    headers = {hdrs.LOCATION: invalid_redirect_url}\n\n    async def generate_redirecting_response(request):\n        return web.Response(status=301, headers=headers)\n\n    app = web.Application()\n    app.router.add_get(\"/redirect\", generate_redirecting_response)\n    client = await aiohttp_client(app)\n\n    with pytest.raises(\n        expected_exception_class, match=rf\"^{error_message_url}( - [A-Za-z ]+)?\"\n    ):\n        await client.get(\"/redirect\")\n\n\n@pytest.mark.parametrize(\n    (\"invalid_redirect_url\", \"error_message_url\", \"expected_exception_class\"),\n    (\n        *(\n            (url, message, InvalidUrlRedirectClientError)\n            for (url, message) in INVALID_URL_WITH_ERROR_MESSAGE_YARL_ORIGIN\n            + INVALID_URL_WITH_ERROR_MESSAGE_YARL_NEW\n        ),\n        *(\n            (url, message, NonHttpUrlRedirectClientError)\n            for (url, message) in NON_HTTP_URL_WITH_ERROR_MESSAGE\n        ),\n    ),\n)\nasync def test_invalid_redirect_url_multiple_redirects(\n    aiohttp_client: Any,\n    invalid_redirect_url: Any,\n    error_message_url: str,\n    expected_exception_class: Any,\n) -> None:\n    app = web.Application()\n\n    for path, location in [\n        (\"/redirect\", \"/redirect1\"),\n        (\"/redirect1\", \"/redirect2\"),\n        (\"/redirect2\", invalid_redirect_url),\n    ]:\n\n        async def generate_redirecting_response(request):\n            return web.Response(status=301, headers={hdrs.LOCATION: location})\n\n        app.router.add_get(path, generate_redirecting_response)\n\n    client = await aiohttp_client(app)\n\n    with pytest.raises(\n        expected_exception_class, match=rf\"^{error_message_url}( - [A-Za-z ]+)?\"\n    ):\n        await client.get(\"/redirect\")\n\n\n@pytest.mark.parametrize(\n    (\"status\", \"expected_ok\"),\n    (\n        (200, True),\n        (201, True),\n        (301, True),\n        (400, False),\n        (403, False),\n        (500, False),\n    ),\n)\nasync def test_ok_from_status(aiohttp_client, status, expected_ok) -> None:\n    async def handler(request):\n        return web.Response(status=status, body=b\"\")\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/endpoint\", handler)\n    client = await aiohttp_client(app, raise_for_status=False)\n    async with client.get(\"/endpoint\") as resp:\n        assert resp.ok is expected_ok\n\n\nasync def test_raise_for_status(aiohttp_client) -> None:\n    async def handler_redirect(request):\n        raise web.HTTPBadRequest()\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler_redirect)\n    client = await aiohttp_client(app, raise_for_status=True)\n\n    with pytest.raises(aiohttp.ClientResponseError):\n        await client.get(\"/\")\n\n\nasync def test_raise_for_status_per_request(aiohttp_client) -> None:\n    async def handler_redirect(request):\n        raise web.HTTPBadRequest()\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler_redirect)\n    client = await aiohttp_client(app)\n\n    with pytest.raises(aiohttp.ClientResponseError):\n        await client.get(\"/\", raise_for_status=True)\n\n\nasync def test_raise_for_status_disable_per_request(aiohttp_client) -> None:\n    async def handler_redirect(request):\n        raise web.HTTPBadRequest()\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler_redirect)\n    client = await aiohttp_client(app, raise_for_status=True)\n\n    async with client.get(\"/\", raise_for_status=False) as resp:\n        assert 400 == resp.status\n\n\nasync def test_request_raise_for_status_default(aiohttp_server) -> None:\n    async def handler(request):\n        raise web.HTTPBadRequest()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    server = await aiohttp_server(app)\n\n    async with aiohttp.request(\"GET\", server.make_url(\"/\")) as resp:\n        assert resp.status == 400\n\n\nasync def test_request_raise_for_status_disabled(aiohttp_server) -> None:\n    async def handler(request):\n        raise web.HTTPBadRequest()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    server = await aiohttp_server(app)\n    url = server.make_url(\"/\")\n\n    async with aiohttp.request(\"GET\", url, raise_for_status=False) as resp:\n        assert resp.status == 400\n\n\nasync def test_request_raise_for_status_enabled(aiohttp_server) -> None:\n    async def handler(request):\n        raise web.HTTPBadRequest()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    server = await aiohttp_server(app)\n    url = server.make_url(\"/\")\n\n    with pytest.raises(aiohttp.ClientResponseError):\n        async with aiohttp.request(\"GET\", url, raise_for_status=True):\n            assert False, \"never executed\"  # pragma: no cover\n\n\nasync def test_session_raise_for_status_coro(aiohttp_client) -> None:\n    async def handle(request):\n        return web.Response(text=\"ok\")\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handle)\n\n    raise_for_status_called = 0\n\n    async def custom_r4s(response):\n        nonlocal raise_for_status_called\n        raise_for_status_called += 1\n        assert response.status == 200\n        assert response.request_info.method == \"GET\"\n\n    client = await aiohttp_client(app, raise_for_status=custom_r4s)\n    await client.get(\"/\")\n    assert raise_for_status_called == 1\n    await client.get(\"/\", raise_for_status=True)\n    assert raise_for_status_called == 1  # custom_r4s not called again\n    await client.get(\"/\", raise_for_status=False)\n    assert raise_for_status_called == 1  # custom_r4s not called again\n\n\nasync def test_request_raise_for_status_coro(aiohttp_client) -> None:\n    async def handle(request):\n        return web.Response(text=\"ok\")\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handle)\n\n    raise_for_status_called = 0\n\n    async def custom_r4s(response):\n        nonlocal raise_for_status_called\n        raise_for_status_called += 1\n        assert response.status == 200\n        assert response.request_info.method == \"GET\"\n\n    client = await aiohttp_client(app)\n    await client.get(\"/\", raise_for_status=custom_r4s)\n    assert raise_for_status_called == 1\n    await client.get(\"/\", raise_for_status=True)\n    assert raise_for_status_called == 1  # custom_r4s not called again\n    await client.get(\"/\", raise_for_status=False)\n    assert raise_for_status_called == 1  # custom_r4s not called again\n\n\nasync def test_invalid_idna() -> None:\n    session = aiohttp.ClientSession()\n    try:\n        with pytest.raises(aiohttp.InvalidURL):\n            await session.get(\"http://\\u2061owhefopw.com\")\n    finally:\n        await session.close()\n\n\nasync def test_creds_in_auth_and_url() -> None:\n    session = aiohttp.ClientSession()\n    try:\n        with pytest.raises(ValueError):\n            await session.get(\n                \"http://user:pass@example.com\", auth=aiohttp.BasicAuth(\"user2\", \"pass2\")\n            )\n    finally:\n        await session.close()\n\n\n@pytest.fixture\ndef create_server_for_url_and_handler(aiohttp_server, tls_certificate_authority):\n    def create(url, srv):\n        app = web.Application()\n        app.router.add_route(\"GET\", url.path, srv)\n\n        kwargs = {}\n        if url.scheme == \"https\":\n            cert = tls_certificate_authority.issue_cert(\n                url.host, \"localhost\", \"127.0.0.1\"\n            )\n            ssl_ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)\n            cert.configure_cert(ssl_ctx)\n            kwargs[\"ssl\"] = ssl_ctx\n        return aiohttp_server(app, **kwargs)\n\n    return create\n\n\n@pytest.mark.parametrize(\n    [\"url_from\", \"url_to\"],\n    [\n        [\"http://host1.com/path1\", \"http://host2.com/path2\"],\n        [\"http://host1.com/path1\", \"https://host1.com/path1\"],\n        [\"https://host1.com/path1\", \"http://host1.com/path2\"],\n    ],\n    ids=(\n        \"entirely different hosts\",\n        \"http -> https\",\n        \"https -> http\",\n    ),\n)\nasync def test_drop_auth_on_redirect_to_other_host(\n    create_server_for_url_and_handler,\n    url_from,\n    url_to,\n) -> None:\n    url_from, url_to = URL(url_from), URL(url_to)\n\n    async def srv_from(request):\n        assert request.host == url_from.host\n        assert request.headers[\"Authorization\"] == \"Basic dXNlcjpwYXNz\"\n        raise web.HTTPFound(url_to)\n\n    async def srv_to(request):\n        assert request.host == url_to.host\n        assert \"Authorization\" not in request.headers, \"Header wasn't dropped\"\n        return web.Response()\n\n    server_from = await create_server_for_url_and_handler(url_from, srv_from)\n    server_to = await create_server_for_url_and_handler(url_to, srv_to)\n\n    assert (\n        url_from.host != url_to.host or server_from.scheme != server_to.scheme\n    ), \"Invalid test case, host or scheme must differ\"\n\n    protocol_port_map = {\n        \"http\": 80,\n        \"https\": 443,\n    }\n    etc_hosts = {\n        (url_from.host, protocol_port_map[server_from.scheme]): server_from,\n        (url_to.host, protocol_port_map[server_to.scheme]): server_to,\n    }\n\n    class FakeResolver(AbstractResolver):\n        async def resolve(self, host, port=0, family=socket.AF_INET):\n            server = etc_hosts[(host, port)]\n\n            return [\n                {\n                    \"hostname\": host,\n                    \"host\": server.host,\n                    \"port\": server.port,\n                    \"family\": socket.AF_INET,\n                    \"proto\": 0,\n                    \"flags\": socket.AI_NUMERICHOST,\n                }\n            ]\n\n        async def close(self):\n            pass\n\n    connector = aiohttp.TCPConnector(resolver=FakeResolver(), ssl=False)\n\n    async with aiohttp.ClientSession(connector=connector) as client:\n        resp = await client.get(\n            url_from,\n            auth=aiohttp.BasicAuth(\"user\", \"pass\"),\n        )\n        assert resp.status == 200\n        resp = await client.get(\n            url_from,\n            headers={\"Authorization\": \"Basic dXNlcjpwYXNz\"},\n        )\n        assert resp.status == 200\n\n\nasync def test_async_with_session() -> None:\n    async with aiohttp.ClientSession() as session:\n        pass\n\n    assert session.closed\n\n\nasync def test_session_close_awaitable() -> None:\n    session = aiohttp.ClientSession()\n    await session.close()\n\n    assert session.closed\n\n\nasync def test_close_resp_on_error_async_with_session(aiohttp_server) -> None:\n    async def handler(request):\n        resp = web.StreamResponse(headers={\"content-length\": \"100\"})\n        await resp.prepare(request)\n        await asyncio.sleep(0.1)\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    server = await aiohttp_server(app)\n\n    async with aiohttp.ClientSession() as session:\n        with pytest.raises(RuntimeError):\n            async with session.get(server.make_url(\"/\")) as resp:\n                resp.content.set_exception(RuntimeError())\n                await resp.read()\n\n        assert len(session._connector._conns) == 0\n\n\nasync def test_release_resp_on_normal_exit_from_cm(aiohttp_server) -> None:\n    async def handler(request):\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    server = await aiohttp_server(app)\n\n    async with aiohttp.ClientSession() as session:\n        async with session.get(server.make_url(\"/\")) as resp:\n            await resp.read()\n\n        assert len(session._connector._conns) == 1\n\n\nasync def test_non_close_detached_session_on_error_cm(aiohttp_server) -> None:\n    async def handler(request):\n        resp = web.StreamResponse(headers={\"content-length\": \"100\"})\n        await resp.prepare(request)\n        await asyncio.sleep(0.1)\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    server = await aiohttp_server(app)\n\n    session = aiohttp.ClientSession()\n    cm = session.get(server.make_url(\"/\"))\n    assert not session.closed\n    with pytest.raises(RuntimeError):\n        async with cm as resp:\n            resp.content.set_exception(RuntimeError())\n            await resp.read()\n    assert not session.closed\n\n\nasync def test_close_detached_session_on_non_existing_addr() -> None:\n    class FakeResolver(AbstractResolver):\n        async def resolve(host, port=0, family=socket.AF_INET):\n            return {}\n\n        async def close(self):\n            pass\n\n    connector = aiohttp.TCPConnector(resolver=FakeResolver())\n\n    session = aiohttp.ClientSession(connector=connector)\n\n    async with session:\n        cm = session.get(\"http://non-existing.example.com\")\n        assert not session.closed\n        with pytest.raises(Exception):\n            await cm\n\n    assert session.closed\n\n\nasync def test_aiohttp_request_context_manager(aiohttp_server) -> None:\n    async def handler(request):\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    server = await aiohttp_server(app)\n\n    async with aiohttp.request(\"GET\", server.make_url(\"/\")) as resp:\n        await resp.read()\n        assert resp.status == 200\n\n\nasync def test_aiohttp_request_ctx_manager_close_sess_on_error(\n    ssl_ctx, aiohttp_server\n) -> None:\n    async def handler(request):\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    server = await aiohttp_server(app, ssl=ssl_ctx)\n\n    cm = aiohttp.request(\"GET\", server.make_url(\"/\"))\n\n    with pytest.raises(aiohttp.ClientConnectionError):\n        async with cm:\n            pass\n\n    assert cm._session.closed\n\n\nasync def test_aiohttp_request_ctx_manager_not_found() -> None:\n\n    with pytest.raises(aiohttp.ClientConnectionError):\n        async with aiohttp.request(\"GET\", \"http://wrong-dns-name.com\"):\n            assert False, \"never executed\"  # pragma: no cover\n\n\nasync def test_yield_from_in_session_request(aiohttp_client) -> None:\n    # a test for backward compatibility with yield from syntax\n    async def handler(request):\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n\n    client = await aiohttp_client(app)\n    async with client.get(\"/\") as resp:\n        assert resp.status == 200\n\n\nasync def test_close_context_manager(aiohttp_client) -> None:\n    # a test for backward compatibility with yield from syntax\n    async def handler(request):\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n\n    client = await aiohttp_client(app)\n    ctx = client.get(\"/\")\n    ctx.close()\n    assert not ctx._coro.cr_running\n\n\nasync def test_session_auth(aiohttp_client) -> None:\n    async def handler(request):\n        return web.json_response({\"headers\": dict(request.headers)})\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n\n    client = await aiohttp_client(app, auth=aiohttp.BasicAuth(\"login\", \"pass\"))\n\n    r = await client.get(\"/\")\n    assert r.status == 200\n    content = await r.json()\n    assert content[\"headers\"][\"Authorization\"] == \"Basic bG9naW46cGFzcw==\"\n\n\nasync def test_session_auth_override(aiohttp_client) -> None:\n    async def handler(request):\n        return web.json_response({\"headers\": dict(request.headers)})\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n\n    client = await aiohttp_client(app, auth=aiohttp.BasicAuth(\"login\", \"pass\"))\n\n    r = await client.get(\"/\", auth=aiohttp.BasicAuth(\"other_login\", \"pass\"))\n    assert r.status == 200\n    content = await r.json()\n    val = content[\"headers\"][\"Authorization\"]\n    assert val == \"Basic b3RoZXJfbG9naW46cGFzcw==\"\n\n\nasync def test_session_auth_header_conflict(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n\n    client = await aiohttp_client(app, auth=aiohttp.BasicAuth(\"login\", \"pass\"))\n    headers = {\"Authorization\": \"Basic b3RoZXJfbG9naW46cGFzcw==\"}\n    with pytest.raises(ValueError):\n        await client.get(\"/\", headers=headers)\n\n\nasync def test_session_headers(aiohttp_client) -> None:\n    async def handler(request):\n        return web.json_response({\"headers\": dict(request.headers)})\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n\n    client = await aiohttp_client(app, headers={\"X-Real-IP\": \"192.168.0.1\"})\n\n    r = await client.get(\"/\")\n    assert r.status == 200\n    content = await r.json()\n    assert content[\"headers\"][\"X-Real-IP\"] == \"192.168.0.1\"\n\n\nasync def test_session_headers_merge(aiohttp_client) -> None:\n    async def handler(request):\n        return web.json_response({\"headers\": dict(request.headers)})\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n\n    client = await aiohttp_client(\n        app, headers=[(\"X-Real-IP\", \"192.168.0.1\"), (\"X-Sent-By\", \"requests\")]\n    )\n\n    r = await client.get(\"/\", headers={\"X-Sent-By\": \"aiohttp\"})\n    assert r.status == 200\n    content = await r.json()\n    assert content[\"headers\"][\"X-Real-IP\"] == \"192.168.0.1\"\n    assert content[\"headers\"][\"X-Sent-By\"] == \"aiohttp\"\n\n\nasync def test_multidict_headers(aiohttp_client) -> None:\n    async def handler(request):\n        assert await request.read() == data\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n\n    client = await aiohttp_client(app)\n\n    data = b\"sample data\"\n\n    async with client.post(\n        \"/\", data=data, headers=MultiDict({\"Content-Length\": str(len(data))})\n    ) as r:\n        assert r.status == 200\n\n\nasync def test_request_conn_closed(aiohttp_client) -> None:\n    async def handler(request):\n        request.transport.close()\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n\n    client = await aiohttp_client(app)\n    with pytest.raises(aiohttp.ServerDisconnectedError) as excinfo:\n        resp = await client.get(\"/\")\n        await resp.read()\n\n    assert str(excinfo.value) != \"\"\n\n\nasync def test_dont_close_explicit_connector(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n\n    client = await aiohttp_client(app)\n    r = await client.get(\"/\")\n    await r.read()\n\n    assert 1 == len(client.session.connector._conns)\n\n\nasync def test_server_close_keepalive_connection() -> None:\n    loop = asyncio.get_event_loop()\n\n    class Proto(asyncio.Protocol):\n        def connection_made(self, transport):\n            self.transp = transport\n            self.data = b\"\"\n\n        def data_received(self, data):\n            self.data += data\n            if data.endswith(b\"\\r\\n\\r\\n\"):\n                self.transp.write(\n                    b\"HTTP/1.1 200 OK\\r\\n\"\n                    b\"CONTENT-LENGTH: 2\\r\\n\"\n                    b\"CONNECTION: close\\r\\n\"\n                    b\"\\r\\n\"\n                    b\"ok\"\n                )\n                self.transp.close()\n\n        def connection_lost(self, exc):\n            self.transp = None\n\n    server = await loop.create_server(Proto, \"127.0.0.1\", unused_port())\n\n    addr = server.sockets[0].getsockname()\n\n    connector = aiohttp.TCPConnector(limit=1)\n    session = aiohttp.ClientSession(connector=connector)\n\n    url = \"http://{}:{}/\".format(*addr)\n    for i in range(2):\n        r = await session.request(\"GET\", url)\n        await r.read()\n        assert 0 == len(connector._conns)\n    await session.close()\n    await connector.close()\n    server.close()\n    await server.wait_closed()\n\n\nasync def test_handle_keepalive_on_closed_connection() -> None:\n    loop = asyncio.get_event_loop()\n\n    class Proto(asyncio.Protocol):\n        def connection_made(self, transport):\n            self.transp = transport\n            self.data = b\"\"\n\n        def data_received(self, data):\n            self.data += data\n            if data.endswith(b\"\\r\\n\\r\\n\"):\n                self.transp.write(\n                    b\"HTTP/1.1 200 OK\\r\\n\" b\"CONTENT-LENGTH: 2\\r\\n\" b\"\\r\\n\" b\"ok\"\n                )\n                self.transp.close()\n\n        def connection_lost(self, exc):\n            self.transp = None\n\n    server = await loop.create_server(Proto, \"127.0.0.1\", unused_port())\n\n    addr = server.sockets[0].getsockname()\n\n    async with aiohttp.TCPConnector(limit=1) as connector:\n        async with aiohttp.ClientSession(connector=connector) as session:\n            url = \"http://{}:{}/\".format(*addr)\n\n            r = await session.request(\"GET\", url)\n            await r.read()\n            assert 1 == len(connector._conns)\n            closed_conn = next(iter(connector._conns.values()))\n\n            await session.request(\"GET\", url)\n            assert 1 == len(connector._conns)\n            new_conn = next(iter(connector._conns.values()))\n            assert closed_conn is not new_conn\n\n    server.close()\n    await server.wait_closed()\n\n\nasync def test_error_in_performing_request(ssl_ctx, aiohttp_client, aiohttp_server):\n    async def handler(request):\n        return web.Response()\n\n    def exception_handler(loop, context):\n        # skip log messages about destroyed but pending tasks\n        pass\n\n    loop = asyncio.get_event_loop()\n    loop.set_exception_handler(exception_handler)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    server = await aiohttp_server(app, ssl=ssl_ctx)\n\n    conn = aiohttp.TCPConnector(limit=1)\n    client = await aiohttp_client(server, connector=conn)\n\n    with pytest.raises(aiohttp.ClientConnectionError):\n        await client.get(\"/\")\n\n    # second try should not hang\n    with pytest.raises(aiohttp.ClientConnectionError):\n        await client.get(\"/\")\n\n\nasync def test_await_after_cancelling(aiohttp_client) -> None:\n    loop = asyncio.get_event_loop()\n\n    async def handler(request):\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    client = await aiohttp_client(app)\n\n    fut1 = loop.create_future()\n    fut2 = loop.create_future()\n\n    async def fetch1():\n        resp = await client.get(\"/\")\n        assert resp.status == 200\n        fut1.set_result(None)\n        with pytest.raises(asyncio.CancelledError):\n            await fut2\n        resp.release()\n\n    async def fetch2():\n        await fut1\n        resp = await client.get(\"/\")\n        assert resp.status == 200\n\n    async def canceller():\n        await fut1\n        fut2.cancel()\n\n    await asyncio.gather(fetch1(), fetch2(), canceller())\n\n\nasync def test_async_payload_generator(aiohttp_client) -> None:\n    async def handler(request):\n        data = await request.read()\n        assert data == b\"1234567890\" * 100\n        return web.Response()\n\n    app = web.Application()\n    app.add_routes([web.post(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n\n    async def gen():\n        for i in range(100):\n            yield b\"1234567890\"\n\n    async with client.post(\"/\", data=gen()) as resp:\n        assert resp.status == 200\n\n\nasync def test_read_from_closed_response(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(body=b\"data\")\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/\") as resp:\n        assert resp.status == 200\n\n    with pytest.raises(aiohttp.ClientConnectionError):\n        await resp.read()\n\n\nasync def test_read_from_closed_response2(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(body=b\"data\")\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/\") as resp:\n        assert resp.status == 200\n        await resp.read()\n\n    with pytest.raises(aiohttp.ClientConnectionError):\n        await resp.read()\n\n\nasync def test_read_from_closed_content(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(body=b\"data\")\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/\") as resp:\n        assert resp.status == 200\n\n    with pytest.raises(aiohttp.ClientConnectionError):\n        await resp.content.readline()\n\n\nasync def test_read_timeout(aiohttp_client) -> None:\n    async def handler(request):\n        await asyncio.sleep(5)\n        return web.Response()\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    timeout = aiohttp.ClientTimeout(sock_read=0.1)\n    client = await aiohttp_client(app, timeout=timeout)\n\n    with pytest.raises(aiohttp.ServerTimeoutError):\n        await client.get(\"/\")\n\n\nasync def test_socket_timeout(aiohttp_client: Any) -> None:\n    async def handler(request):\n        await asyncio.sleep(5)\n        return web.Response()\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    timeout = aiohttp.ClientTimeout(sock_read=0.1)\n    client = await aiohttp_client(app, timeout=timeout)\n\n    with pytest.raises(SocketTimeoutError):\n        await client.get(\"/\")\n\n\nasync def test_read_timeout_closes_connection(aiohttp_client: AiohttpClient) -> None:\n    request_count = 0\n\n    async def handler(request):\n        nonlocal request_count\n        request_count += 1\n        if request_count < 3:\n            await asyncio.sleep(0.5)\n        return web.Response(body=f\"request:{request_count}\")\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    timeout = aiohttp.ClientTimeout(total=0.1)\n    client: TestClient = await aiohttp_client(app, timeout=timeout)\n    with pytest.raises(asyncio.TimeoutError):\n        await client.get(\"/\")\n\n    # Make sure its really closed\n    assert not client.session.connector._conns\n\n    with pytest.raises(asyncio.TimeoutError):\n        await client.get(\"/\")\n\n    # Make sure its really closed\n    assert not client.session.connector._conns\n    result = await client.get(\"/\")\n    assert await result.read() == b\"request:3\"\n\n    # Make sure its not closed\n    assert client.session.connector._conns\n\n\nasync def test_read_timeout_on_prepared_response(aiohttp_client: Any) -> None:\n    async def handler(request):\n        resp = aiohttp.web.StreamResponse()\n        await resp.prepare(request)\n        await asyncio.sleep(5)\n        await resp.drain()\n        return resp\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    timeout = aiohttp.ClientTimeout(sock_read=0.1)\n    client = await aiohttp_client(app, timeout=timeout)\n\n    with pytest.raises(aiohttp.ServerTimeoutError):\n        async with await client.get(\"/\") as resp:\n            await resp.read()\n\n\nasync def test_timeout_with_full_buffer(aiohttp_client) -> None:\n    async def handler(request):\n        \"\"\"Server response that never ends and always has more data available.\"\"\"\n        resp = web.StreamResponse()\n        await resp.prepare(request)\n        while True:\n            await resp.write(b\"1\" * 1000)\n            await asyncio.sleep(0.01)\n\n    async def request(client):\n        timeout = aiohttp.ClientTimeout(total=0.5)\n        async with await client.get(\"/\", timeout=timeout) as resp:\n            with pytest.raises(asyncio.TimeoutError):\n                async for data in resp.content.iter_chunked(1):\n                    await asyncio.sleep(0.01)\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n    # wait_for() used just to ensure that a failing test doesn't hang.\n    await asyncio.wait_for(request(client), 1)\n\n\nasync def test_read_bufsize_session_default(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(body=b\"1234567\")\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app, read_bufsize=2)\n\n    async with await client.get(\"/\") as resp:\n        assert resp.content.get_read_buffer_limits() == (2, 4)\n\n\nasync def test_read_bufsize_explicit(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(body=b\"1234567\")\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n\n    async with await client.get(\"/\", read_bufsize=4) as resp:\n        assert resp.content.get_read_buffer_limits() == (4, 8)\n\n\nasync def test_http_empty_data_text(aiohttp_client) -> None:\n    async def handler(request):\n        data = await request.read()\n        ret = \"ok\" if data == b\"\" else \"fail\"\n        resp = web.Response(text=ret)\n        resp.headers[\"Content-Type\"] = request.headers[\"Content-Type\"]\n        return resp\n\n    app = web.Application()\n    app.add_routes([web.post(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n\n    async with await client.post(\"/\", data=\"\") as resp:\n        assert resp.status == 200\n        assert await resp.text() == \"ok\"\n        assert resp.headers[\"Content-Type\"] == \"text/plain; charset=utf-8\"\n\n\nasync def test_max_field_size_session_default(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(headers={\"Custom\": \"x\" * 8190})\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n\n    async with await client.get(\"/\") as resp:\n        assert resp.headers[\"Custom\"] == \"x\" * 8190\n\n\nasync def test_max_field_size_session_default_fail(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(headers={\"Custom\": \"x\" * 8191})\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n    with pytest.raises(aiohttp.ClientResponseError):\n        await client.get(\"/\")\n\n\nasync def test_max_field_size_session_explicit(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(headers={\"Custom\": \"x\" * 8191})\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app, max_field_size=8191)\n\n    async with await client.get(\"/\") as resp:\n        assert resp.headers[\"Custom\"] == \"x\" * 8191\n\n\nasync def test_max_field_size_request_explicit(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(headers={\"Custom\": \"x\" * 8191})\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n\n    async with await client.get(\"/\", max_field_size=8191) as resp:\n        assert resp.headers[\"Custom\"] == \"x\" * 8191\n\n\nasync def test_max_line_size_session_default(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(status=200, reason=\"x\" * 8190)\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n\n    async with await client.get(\"/\") as resp:\n        assert resp.reason == \"x\" * 8190\n\n\nasync def test_max_line_size_session_default_fail(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(status=200, reason=\"x\" * 8192)\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n    with pytest.raises(aiohttp.ClientResponseError):\n        await client.get(\"/\")\n\n\nasync def test_max_line_size_session_explicit(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(status=200, reason=\"x\" * 8191)\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app, max_line_size=8191)\n\n    async with await client.get(\"/\") as resp:\n        assert resp.reason == \"x\" * 8191\n\n\nasync def test_max_line_size_request_explicit(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(status=200, reason=\"x\" * 8191)\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n\n    async with await client.get(\"/\", max_line_size=8191) as resp:\n        assert resp.reason == \"x\" * 8191\n\n\n@pytest.mark.xfail(raises=asyncio.TimeoutError, reason=\"#7599\")\nasync def test_rejected_upload(aiohttp_client, tmp_path) -> None:\n    async def ok_handler(request):\n        return web.Response()\n\n    async def not_ok_handler(request):\n        raise web.HTTPBadRequest()\n\n    app = web.Application()\n    app.router.add_get(\"/ok\", ok_handler)\n    app.router.add_post(\"/not_ok\", not_ok_handler)\n    client = await aiohttp_client(app)\n\n    file_size_bytes = 1024 * 1024\n    file_path = tmp_path / \"uploaded.txt\"\n    file_path.write_text(\"0\" * file_size_bytes, encoding=\"utf8\")\n\n    with open(file_path, \"rb\") as file:\n        data = {\"file\": file}\n        async with await client.post(\"/not_ok\", data=data) as resp_not_ok:\n            assert 400 == resp_not_ok.status\n\n    async with await client.get(\n        \"/ok\", timeout=aiohttp.ClientTimeout(total=0.01)\n    ) as resp_ok:\n        assert 200 == resp_ok.status\n\n\n@pytest.mark.parametrize(\n    (\"value\", \"exc_type\"),\n    [(42, TypeError), (\"InvalidUrl\", InvalidURL)],\n)\nasync def test_request_with_wrong_proxy(\n    aiohttp_client: AiohttpClient, value: Any, exc_type: Type[Exception]\n) -> None:\n    app = web.Application()\n    session = await aiohttp_client(app)\n\n    with pytest.raises(exc_type):\n        await session.get(\"/\", proxy=value)  # type: ignore[arg-type]\n\n\nasync def test_raise_for_status_is_none(aiohttp_client: AiohttpClient) -> None:\n    async def handler(_: web.Request) -> web.Response:\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    session = await aiohttp_client(app, raise_for_status=None)  # type: ignore[arg-type]\n\n    await session.get(\"/\")\n\n\nasync def test_exception_when_read_outside_of_session(\n    aiohttp_server: AiohttpServer,\n) -> None:\n    async def handler(request: web.Request) -> web.Response:\n        return web.Response(body=b\"1\" * 1000000)\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n\n    server = await aiohttp_server(app)\n    async with aiohttp.ClientSession() as sess:\n        resp = await sess.get(server.make_url(\"/\"))\n\n    with pytest.raises(RuntimeError, match=\"Connection closed\"):\n        await resp.read()\n",
            "new_file_content": "# HTTP client functional tests against aiohttp.web server\n\nimport asyncio\nimport datetime\nimport http.cookies\nimport io\nimport json\nimport pathlib\nimport socket\nimport ssl\nimport sys\nimport tarfile\nimport time\nimport zipfile\nfrom typing import Any, AsyncIterator, Type\nfrom unittest import mock\n\nimport pytest\nfrom multidict import MultiDict\nfrom yarl import URL\n\nimport aiohttp\nfrom aiohttp import Fingerprint, ServerFingerprintMismatch, hdrs, web\nfrom aiohttp.abc import AbstractResolver\nfrom aiohttp.client_exceptions import (\n    InvalidURL,\n    InvalidUrlClientError,\n    InvalidUrlRedirectClientError,\n    NonHttpUrlClientError,\n    NonHttpUrlRedirectClientError,\n    SocketTimeoutError,\n    TooManyRedirects,\n)\nfrom aiohttp.pytest_plugin import AiohttpClient, AiohttpServer, TestClient\nfrom aiohttp.test_utils import unused_port\n\n\n@pytest.fixture\ndef here():\n    return pathlib.Path(__file__).parent\n\n\n@pytest.fixture\ndef fname(here):\n    return here / \"conftest.py\"\n\n\nasync def test_keepalive_two_requests_success(aiohttp_client) -> None:\n    async def handler(request):\n        body = await request.read()\n        assert b\"\" == body\n        return web.Response(body=b\"OK\")\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    connector = aiohttp.TCPConnector(limit=1)\n    client = await aiohttp_client(app, connector=connector)\n\n    resp1 = await client.get(\"/\")\n    await resp1.read()\n    resp2 = await client.get(\"/\")\n    await resp2.read()\n\n    assert 1 == len(client._session.connector._conns)\n\n\nasync def test_keepalive_after_head_requests_success(aiohttp_client) -> None:\n    async def handler(request):\n        body = await request.read()\n        assert b\"\" == body\n        return web.Response(body=b\"OK\")\n\n    cnt_conn_reuse = 0\n\n    async def on_reuseconn(session, ctx, params):\n        nonlocal cnt_conn_reuse\n        cnt_conn_reuse += 1\n\n    trace_config = aiohttp.TraceConfig()\n    trace_config._on_connection_reuseconn.append(on_reuseconn)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    app.router.add_route(\"HEAD\", \"/\", handler)\n\n    connector = aiohttp.TCPConnector(limit=1)\n    client = await aiohttp_client(\n        app, connector=connector, trace_configs=[trace_config]\n    )\n\n    resp1 = await client.head(\"/\")\n    await resp1.read()\n    resp2 = await client.get(\"/\")\n    await resp2.read()\n\n    assert 1 == cnt_conn_reuse\n\n\n@pytest.mark.parametrize(\"status\", (101, 204, 304))\nasync def test_keepalive_after_empty_body_status(\n    aiohttp_client: Any, status: int\n) -> None:\n    async def handler(request):\n        body = await request.read()\n        assert b\"\" == body\n        return web.Response(status=status)\n\n    cnt_conn_reuse = 0\n\n    async def on_reuseconn(session, ctx, params):\n        nonlocal cnt_conn_reuse\n        cnt_conn_reuse += 1\n\n    trace_config = aiohttp.TraceConfig()\n    trace_config._on_connection_reuseconn.append(on_reuseconn)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    connector = aiohttp.TCPConnector(limit=1)\n    client = await aiohttp_client(\n        app, connector=connector, trace_configs=[trace_config]\n    )\n\n    resp1 = await client.get(\"/\")\n    await resp1.read()\n    resp2 = await client.get(\"/\")\n    await resp2.read()\n\n    assert cnt_conn_reuse == 1\n\n\n@pytest.mark.parametrize(\"status\", (101, 204, 304))\nasync def test_keepalive_after_empty_body_status_stream_response(\n    aiohttp_client: Any, status: int\n) -> None:\n    async def handler(request):\n        stream_response = web.StreamResponse(status=status)\n        await stream_response.prepare(request)\n        return stream_response\n\n    cnt_conn_reuse = 0\n\n    async def on_reuseconn(session, ctx, params):\n        nonlocal cnt_conn_reuse\n        cnt_conn_reuse += 1\n\n    trace_config = aiohttp.TraceConfig()\n    trace_config._on_connection_reuseconn.append(on_reuseconn)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    connector = aiohttp.TCPConnector(limit=1)\n    client = await aiohttp_client(\n        app, connector=connector, trace_configs=[trace_config]\n    )\n\n    resp1 = await client.get(\"/\")\n    await resp1.read()\n    resp2 = await client.get(\"/\")\n    await resp2.read()\n\n    assert cnt_conn_reuse == 1\n\n\nasync def test_keepalive_response_released(aiohttp_client: Any) -> None:\n    async def handler(request):\n        body = await request.read()\n        assert b\"\" == body\n        return web.Response(body=b\"OK\")\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    connector = aiohttp.TCPConnector(limit=1)\n    client = await aiohttp_client(app, connector=connector)\n\n    resp1 = await client.get(\"/\")\n    resp1.release()\n    resp2 = await client.get(\"/\")\n    resp2.release()\n\n    assert 1 == len(client._session.connector._conns)\n\n\nasync def test_upgrade_connection_not_released_after_read(aiohttp_client) -> None:\n    async def handler(request: web.Request) -> web.Response:\n        body = await request.read()\n        assert b\"\" == body\n        return web.Response(\n            status=101, headers={\"Connection\": \"Upgrade\", \"Upgrade\": \"tcp\"}\n        )\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    await resp.read()\n    assert resp.connection is not None\n    assert not resp.closed\n\n\nasync def test_keepalive_server_force_close_connection(aiohttp_client) -> None:\n    async def handler(request):\n        body = await request.read()\n        assert b\"\" == body\n        response = web.Response(body=b\"OK\")\n        response.force_close()\n        return response\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    connector = aiohttp.TCPConnector(limit=1)\n    client = await aiohttp_client(app, connector=connector)\n\n    resp1 = await client.get(\"/\")\n    resp1.close()\n    resp2 = await client.get(\"/\")\n    resp2.close()\n\n    assert 0 == len(client._session.connector._conns)\n\n\nasync def test_keepalive_timeout_async_sleep() -> None:\n    async def handler(request):\n        body = await request.read()\n        assert b\"\" == body\n        return web.Response(body=b\"OK\")\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    runner = web.AppRunner(app, tcp_keepalive=True, keepalive_timeout=0.001)\n    await runner.setup()\n\n    port = unused_port()\n    site = web.TCPSite(runner, host=\"localhost\", port=port)\n    await site.start()\n\n    try:\n        async with aiohttp.client.ClientSession() as sess:\n            resp1 = await sess.get(f\"http://localhost:{port}/\")\n            await resp1.read()\n            # wait for server keepalive_timeout\n            await asyncio.sleep(0.01)\n            resp2 = await sess.get(f\"http://localhost:{port}/\")\n            await resp2.read()\n    finally:\n        await asyncio.gather(runner.shutdown(), site.stop())\n\n\n@pytest.mark.skipif(\n    sys.version_info[:2] == (3, 11),\n    reason=\"https://github.com/pytest-dev/pytest/issues/10763\",\n)\nasync def test_keepalive_timeout_sync_sleep() -> None:\n    async def handler(request):\n        body = await request.read()\n        assert b\"\" == body\n        return web.Response(body=b\"OK\")\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    runner = web.AppRunner(app, tcp_keepalive=True, keepalive_timeout=0.001)\n    await runner.setup()\n\n    port = unused_port()\n    site = web.TCPSite(runner, host=\"localhost\", port=port)\n    await site.start()\n\n    try:\n        async with aiohttp.client.ClientSession() as sess:\n            resp1 = await sess.get(f\"http://localhost:{port}/\")\n            await resp1.read()\n            # wait for server keepalive_timeout\n            # time.sleep is a more challenging scenario than asyncio.sleep\n            time.sleep(0.01)\n            resp2 = await sess.get(f\"http://localhost:{port}/\")\n            await resp2.read()\n    finally:\n        await asyncio.gather(runner.shutdown(), site.stop())\n\n\nasync def test_release_early(aiohttp_client) -> None:\n    async def handler(request):\n        await request.read()\n        return web.Response(body=b\"OK\")\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    client = await aiohttp_client(app)\n    resp = await client.get(\"/\")\n    assert resp.closed\n    await resp.wait_for_close()\n    assert 1 == len(client._session.connector._conns)\n\n\nasync def test_HTTP_304(aiohttp_client) -> None:\n    async def handler(request):\n        body = await request.read()\n        assert b\"\" == body\n        return web.Response(status=304)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert resp.status == 304\n    content = await resp.read()\n    assert content == b\"\"\n\n\nasync def test_stream_request_on_server_eof(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=\"OK\", status=200)\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n    app.add_routes([web.put(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n\n    async def data_gen():\n        for _ in range(2):\n            yield b\"just data\"\n            await asyncio.sleep(0.1)\n\n    async with client.put(\"/\", data=data_gen()) as resp:\n        assert 200 == resp.status\n        assert len(client.session.connector._acquired) == 1\n        conn = next(iter(client.session.connector._acquired))\n\n    async with client.get(\"/\") as resp:\n        assert 200 == resp.status\n\n    # First connection should have been closed, otherwise server won't know if it\n    # received the full message.\n    conns = next(iter(client.session.connector._conns.values()))\n    assert len(conns) == 1\n    assert conns[0][0] is not conn\n\n\nasync def test_stream_request_on_server_eof_nested(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=\"OK\", status=200)\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n    app.add_routes([web.put(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n\n    async def data_gen():\n        for _ in range(2):\n            yield b\"just data\"\n            await asyncio.sleep(0.1)\n\n    assert client.session.connector is not None\n    async with client.put(\"/\", data=data_gen()) as resp:\n        first_conn = next(iter(client.session.connector._acquired))\n        assert 200 == resp.status\n\n        async with client.get(\"/\") as resp2:\n            assert 200 == resp2.status\n\n    # Should be 2 separate connections\n    conns = next(iter(client.session.connector._conns.values()))\n    assert len(conns) == 1\n\n    assert first_conn is not None\n    assert not first_conn.is_connected()\n    assert first_conn is not conns[0][0]\n\n\nasync def test_HTTP_304_WITH_BODY(aiohttp_client) -> None:\n    async def handler(request):\n        body = await request.read()\n        assert b\"\" == body\n        return web.Response(body=b\"test\", status=304)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert resp.status == 304\n    content = await resp.read()\n    assert content == b\"\"\n\n\nasync def test_auto_header_user_agent(aiohttp_client) -> None:\n    async def handler(request):\n        assert \"aiohttp\" in request.headers[\"user-agent\"]\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/\") as resp:\n        assert 200 == resp.status\n\n\nasync def test_skip_auto_headers_user_agent(aiohttp_client) -> None:\n    async def handler(request):\n        assert hdrs.USER_AGENT not in request.headers\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/\", skip_auto_headers=[\"user-agent\"]) as resp:\n        assert 200 == resp.status\n\n\nasync def test_skip_default_auto_headers_user_agent(aiohttp_client) -> None:\n    async def handler(request):\n        assert hdrs.USER_AGENT not in request.headers\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app, skip_auto_headers=[\"user-agent\"])\n\n    async with client.get(\"/\") as resp:\n        assert 200 == resp.status\n\n\nasync def test_skip_auto_headers_content_type(aiohttp_client) -> None:\n    async def handler(request):\n        assert hdrs.CONTENT_TYPE not in request.headers\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/\", skip_auto_headers=[\"content-type\"]) as resp:\n        assert 200 == resp.status\n\n\nasync def test_post_data_bytesio(aiohttp_client) -> None:\n    data = b\"some buffer\"\n\n    async def handler(request):\n        assert len(data) == request.content_length\n        val = await request.read()\n        assert data == val\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"POST\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    with io.BytesIO(data) as file_handle:\n        async with client.post(\"/\", data=file_handle) as resp:\n            assert 200 == resp.status\n\n\nasync def test_post_data_with_bytesio_file(aiohttp_client) -> None:\n    data = b\"some buffer\"\n\n    async def handler(request):\n        post_data = await request.post()\n        assert [\"file\"] == list(post_data.keys())\n        assert data == post_data[\"file\"].file.read()\n        post_data[\"file\"].file.close()  # aiohttp < 4 doesn't autoclose files\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"POST\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    with io.BytesIO(data) as file_handle:\n        async with client.post(\"/\", data={\"file\": file_handle}) as resp:\n            assert 200 == resp.status\n\n\nasync def test_post_data_stringio(aiohttp_client) -> None:\n    data = \"some buffer\"\n\n    async def handler(request):\n        assert len(data) == request.content_length\n        assert request.headers[\"CONTENT-TYPE\"] == \"text/plain; charset=utf-8\"\n        val = await request.text()\n        assert data == val\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"POST\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.post(\"/\", data=io.StringIO(data)) as resp:\n        assert 200 == resp.status\n\n\nasync def test_post_data_textio_encoding(aiohttp_client) -> None:\n    data = \"текст\"\n\n    async def handler(request):\n        assert request.headers[\"CONTENT-TYPE\"] == \"text/plain; charset=koi8-r\"\n        val = await request.text()\n        assert data == val\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"POST\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    pl = aiohttp.TextIOPayload(io.StringIO(data), encoding=\"koi8-r\")\n    async with client.post(\"/\", data=pl) as resp:\n        assert 200 == resp.status\n\n\nasync def test_post_data_zipfile_filelike(aiohttp_client: AiohttpClient) -> None:\n    data = b\"This is a zip file payload text file.\"\n\n    async def handler(request: web.Request) -> web.Response:\n        val = await request.read()\n        assert data == val, \"Transmitted zipfile member failed to match original data.\"\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"POST\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    buf = io.BytesIO()\n    with zipfile.ZipFile(file=buf, mode=\"w\") as zf:\n        with zf.open(\"payload1.txt\", mode=\"w\") as zip_filelike_writing:\n            zip_filelike_writing.write(data)\n\n    buf.seek(0)\n    zf = zipfile.ZipFile(file=buf, mode=\"r\")\n    resp = await client.post(\"/\", data=zf.open(\"payload1.txt\"))\n    assert 200 == resp.status\n\n\nasync def test_post_data_tarfile_filelike(aiohttp_client: AiohttpClient) -> None:\n    data = b\"This is a tar file payload text file.\"\n\n    async def handler(request: web.Request) -> web.Response:\n        val = await request.read()\n        assert data == val, \"Transmitted tarfile member failed to match original data.\"\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"POST\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    buf = io.BytesIO()\n    with tarfile.open(fileobj=buf, mode=\"w\") as tf:\n        ti = tarfile.TarInfo(name=\"payload1.txt\")\n        ti.size = len(data)\n        tf.addfile(tarinfo=ti, fileobj=io.BytesIO(data))\n\n    # Random-access tarfile.\n    buf.seek(0)\n    tf = tarfile.open(fileobj=buf, mode=\"r:\")\n    resp = await client.post(\"/\", data=tf.extractfile(\"payload1.txt\"))\n    assert 200 == resp.status\n\n    # Streaming tarfile.\n    buf.seek(0)\n    tf = tarfile.open(fileobj=buf, mode=\"r|\")\n    for entry in tf:\n        resp = await client.post(\"/\", data=tf.extractfile(entry))\n        assert 200 == resp.status\n\n\nasync def test_ssl_client(\n    aiohttp_server,\n    ssl_ctx,\n    aiohttp_client,\n    client_ssl_ctx,\n) -> None:\n    connector = aiohttp.TCPConnector(ssl=client_ssl_ctx)\n\n    async def handler(request):\n        return web.Response(text=\"Test message\")\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    server = await aiohttp_server(app, ssl=ssl_ctx)\n    client = await aiohttp_client(server, connector=connector)\n\n    resp = await client.get(\"/\")\n    assert 200 == resp.status\n    txt = await resp.text()\n    assert txt == \"Test message\"\n\n\nasync def test_tcp_connector_fingerprint_ok(\n    aiohttp_server,\n    aiohttp_client,\n    ssl_ctx,\n    tls_certificate_fingerprint_sha256,\n):\n    tls_fingerprint = Fingerprint(tls_certificate_fingerprint_sha256)\n\n    async def handler(request):\n        return web.Response(text=\"Test message\")\n\n    connector = aiohttp.TCPConnector(ssl=tls_fingerprint)\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    server = await aiohttp_server(app, ssl=ssl_ctx)\n    client = await aiohttp_client(server, connector=connector)\n\n    async with client.get(\"/\") as resp:\n        assert resp.status == 200\n\n\nasync def test_tcp_connector_fingerprint_fail(\n    aiohttp_server,\n    aiohttp_client,\n    ssl_ctx,\n    tls_certificate_fingerprint_sha256,\n):\n    async def handler(request):\n        return web.Response(text=\"Test message\")\n\n    bad_fingerprint = b\"\\x00\" * len(tls_certificate_fingerprint_sha256)\n\n    connector = aiohttp.TCPConnector(ssl=Fingerprint(bad_fingerprint))\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    server = await aiohttp_server(app, ssl=ssl_ctx)\n    client = await aiohttp_client(server, connector=connector)\n\n    with pytest.raises(ServerFingerprintMismatch) as cm:\n        await client.get(\"/\")\n    exc = cm.value\n    assert exc.expected == bad_fingerprint\n    assert exc.got == tls_certificate_fingerprint_sha256\n\n\nasync def test_format_task_get(aiohttp_server) -> None:\n    async def handler(request):\n        return web.Response(body=b\"OK\")\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    server = await aiohttp_server(app)\n    client = aiohttp.ClientSession()\n    task = asyncio.create_task(client.get(server.make_url(\"/\")))\n    assert f\"{task}\".startswith(\"<Task pending\")\n    resp = await task\n    resp.close()\n    await client.close()\n\n\nasync def test_str_params(aiohttp_client) -> None:\n    async def handler(request):\n        assert \"q=t est\" in request.rel_url.query_string\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/\", params=\"q=t+est\") as resp:\n        assert 200 == resp.status\n\n\nasync def test_drop_params_on_redirect(aiohttp_client) -> None:\n    async def handler_redirect(request):\n        return web.Response(status=301, headers={\"Location\": \"/ok?a=redirect\"})\n\n    async def handler_ok(request):\n        assert request.rel_url.query_string == \"a=redirect\"\n        return web.Response(status=200)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/ok\", handler_ok)\n    app.router.add_route(\"GET\", \"/redirect\", handler_redirect)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/redirect\", params={\"a\": \"initial\"}) as resp:\n        assert resp.status == 200\n\n\nasync def test_drop_fragment_on_redirect(aiohttp_client) -> None:\n    async def handler_redirect(request):\n        return web.Response(status=301, headers={\"Location\": \"/ok#fragment\"})\n\n    async def handler_ok(request):\n        return web.Response(status=200)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/ok\", handler_ok)\n    app.router.add_route(\"GET\", \"/redirect\", handler_redirect)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/redirect\") as resp:\n        assert resp.status == 200\n        assert resp.url.path == \"/ok\"\n\n\nasync def test_drop_fragment(aiohttp_client) -> None:\n    async def handler_ok(request):\n        return web.Response(status=200)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/ok\", handler_ok)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/ok#fragment\") as resp:\n        assert resp.status == 200\n        assert resp.url.path == \"/ok\"\n\n\nasync def test_history(aiohttp_client) -> None:\n    async def handler_redirect(request):\n        return web.Response(status=301, headers={\"Location\": \"/ok\"})\n\n    async def handler_ok(request):\n        return web.Response(status=200)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/ok\", handler_ok)\n    app.router.add_route(\"GET\", \"/redirect\", handler_redirect)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/ok\") as resp:\n        assert len(resp.history) == 0\n        assert resp.status == 200\n\n    async with client.get(\"/redirect\") as resp_redirect:\n        assert len(resp_redirect.history) == 1\n        assert resp_redirect.history[0].status == 301\n        assert resp_redirect.status == 200\n\n\nasync def test_keepalive_closed_by_server(aiohttp_client) -> None:\n    async def handler(request):\n        body = await request.read()\n        assert b\"\" == body\n        resp = web.Response(body=b\"OK\")\n        resp.force_close()\n        return resp\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    connector = aiohttp.TCPConnector(limit=1)\n    client = await aiohttp_client(app, connector=connector)\n\n    resp1 = await client.get(\"/\")\n    val1 = await resp1.read()\n    assert val1 == b\"OK\"\n    resp2 = await client.get(\"/\")\n    val2 = await resp2.read()\n    assert val2 == b\"OK\"\n\n    assert 0 == len(client._session.connector._conns)\n\n\nasync def test_wait_for(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(body=b\"OK\")\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await asyncio.wait_for(client.get(\"/\"), 10)\n    assert resp.status == 200\n    txt = await resp.text()\n    assert txt == \"OK\"\n\n\nasync def test_raw_headers(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    async with client.get(\"/\") as resp:\n        assert resp.status == 200\n\n        raw_headers = tuple((bytes(h), bytes(v)) for h, v in resp.raw_headers)\n        assert raw_headers == (\n            (b\"Content-Length\", b\"0\"),\n            (b\"Date\", mock.ANY),\n            (b\"Server\", mock.ANY),\n        )\n\n\nasync def test_host_header_first(aiohttp_client) -> None:\n    async def handler(request):\n        assert list(request.headers)[0] == hdrs.HOST\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    async with client.get(\"/\") as resp:\n        assert resp.status == 200\n\n\nasync def test_empty_header_values(aiohttp_client) -> None:\n    async def handler(request):\n        resp = web.Response()\n        resp.headers[\"X-Empty\"] = \"\"\n        return resp\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    async with client.get(\"/\") as resp:\n        assert resp.status == 200\n        raw_headers = tuple((bytes(h), bytes(v)) for h, v in resp.raw_headers)\n        assert raw_headers == (\n            (b\"X-Empty\", b\"\"),\n            (b\"Content-Length\", b\"0\"),\n            (b\"Date\", mock.ANY),\n            (b\"Server\", mock.ANY),\n        )\n\n\nasync def test_204_with_gzipped_content_encoding(aiohttp_client) -> None:\n    async def handler(request):\n        resp = web.StreamResponse(status=204)\n        resp.content_length = 0\n        resp.content_type = \"application/json\"\n        # resp.enable_compression(web.ContentCoding.gzip)\n        resp.headers[\"Content-Encoding\"] = \"gzip\"\n        await resp.prepare(request)\n        return resp\n\n    app = web.Application()\n    app.router.add_route(\"DELETE\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.delete(\"/\") as resp:\n        assert resp.status == 204\n        assert resp.closed\n\n\nasync def test_timeout_on_reading_headers(aiohttp_client, mocker) -> None:\n    async def handler(request):\n        resp = web.StreamResponse()\n        await asyncio.sleep(0.1)\n        await resp.prepare(request)\n        return resp\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    with pytest.raises(asyncio.TimeoutError):\n        await client.get(\"/\", timeout=0.01)\n\n\nasync def test_timeout_on_conn_reading_headers(aiohttp_client, mocker) -> None:\n    # tests case where user did not set a connection timeout\n\n    async def handler(request):\n        resp = web.StreamResponse()\n        await asyncio.sleep(0.1)\n        await resp.prepare(request)\n        return resp\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    conn = aiohttp.TCPConnector()\n    client = await aiohttp_client(app, connector=conn)\n\n    with pytest.raises(asyncio.TimeoutError):\n        await client.get(\"/\", timeout=0.01)\n\n\nasync def test_timeout_on_session_read_timeout(aiohttp_client, mocker) -> None:\n    async def handler(request):\n        resp = web.StreamResponse()\n        await asyncio.sleep(0.1)\n        await resp.prepare(request)\n        return resp\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    conn = aiohttp.TCPConnector()\n    client = await aiohttp_client(\n        app, connector=conn, timeout=aiohttp.ClientTimeout(sock_read=0.01)\n    )\n\n    with pytest.raises(asyncio.TimeoutError):\n        await client.get(\"/\")\n\n\nasync def test_read_timeout_between_chunks(aiohttp_client, mocker) -> None:\n    async def handler(request):\n        resp = aiohttp.web.StreamResponse()\n        await resp.prepare(request)\n        # write data 4 times, with pauses. Total time 2 seconds.\n        for _ in range(4):\n            await asyncio.sleep(0.5)\n            await resp.write(b\"data\\n\")\n        return resp\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    # A timeout of 0.2 seconds should apply per read.\n    timeout = aiohttp.ClientTimeout(sock_read=1)\n    client = await aiohttp_client(app, timeout=timeout)\n\n    res = b\"\"\n    async with await client.get(\"/\") as resp:\n        res += await resp.read()\n\n    assert res == b\"data\\n\" * 4\n\n\nasync def test_read_timeout_on_reading_chunks(aiohttp_client, mocker) -> None:\n    async def handler(request):\n        resp = aiohttp.web.StreamResponse()\n        await resp.prepare(request)\n        await resp.write(b\"data\\n\")\n        await asyncio.sleep(1)\n        await resp.write(b\"data\\n\")\n        return resp\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    # A timeout of 0.2 seconds should apply per read.\n    timeout = aiohttp.ClientTimeout(sock_read=0.2)\n    client = await aiohttp_client(app, timeout=timeout)\n\n    async with await client.get(\"/\") as resp:\n        assert (await resp.content.read(5)) == b\"data\\n\"\n        with pytest.raises(asyncio.TimeoutError):\n            await resp.content.read()\n\n\nasync def test_read_timeout_on_write(aiohttp_client) -> None:\n    async def gen_payload() -> AsyncIterator[str]:\n        # Delay writing to ensure read timeout isn't triggered before writing completes.\n        await asyncio.sleep(0.5)\n        yield b\"foo\"\n\n    async def handler(request: web.Request) -> web.Response:\n        return web.Response(body=await request.read())\n\n    app = web.Application()\n    app.router.add_put(\"/\", handler)\n\n    timeout = aiohttp.ClientTimeout(total=None, sock_read=0.1)\n    client = await aiohttp_client(app)\n    async with client.put(\"/\", data=gen_payload(), timeout=timeout) as resp:\n        result = await resp.read()  # Should not trigger a read timeout.\n    assert result == b\"foo\"\n\n\nasync def test_timeout_on_reading_data(aiohttp_client, mocker) -> None:\n    loop = asyncio.get_event_loop()\n\n    fut = loop.create_future()\n\n    async def handler(request):\n        resp = web.StreamResponse(headers={\"content-length\": \"100\"})\n        await resp.prepare(request)\n        fut.set_result(None)\n        await asyncio.sleep(0.2)\n        return resp\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\", timeout=1)\n    await fut\n\n    with pytest.raises(asyncio.TimeoutError):\n        await resp.read()\n\n\nasync def test_timeout_none(aiohttp_client, mocker) -> None:\n    async def handler(request):\n        resp = web.StreamResponse()\n        await resp.prepare(request)\n        return resp\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/\", timeout=None) as resp:\n        assert resp.status == 200\n\n\nasync def test_readline_error_on_conn_close(aiohttp_client) -> None:\n    loop = asyncio.get_event_loop()\n\n    async def handler(request):\n        resp_ = web.StreamResponse()\n        await resp_.prepare(request)\n\n        # make sure connection is closed by client.\n        with pytest.raises(aiohttp.ServerDisconnectedError):\n            for _ in range(10):\n                await resp_.write(b\"data\\n\")\n                await asyncio.sleep(0.5)\n            return resp_\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    server = await aiohttp_client(app)\n\n    session = aiohttp.ClientSession()\n    try:\n        timer_started = False\n        url, headers = server.make_url(\"/\"), {\"Connection\": \"Keep-alive\"}\n        resp = await session.get(url, headers=headers)\n        with pytest.raises(aiohttp.ClientConnectionError):\n            while True:\n                data = await resp.content.readline()\n                data = data.strip()\n                if not data:\n                    break\n                assert data == b\"data\"\n                if not timer_started:\n\n                    def do_release():\n                        loop.create_task(resp.release())\n\n                    loop.call_later(1.0, do_release)\n                    timer_started = True\n    finally:\n        await session.close()\n\n\nasync def test_no_error_on_conn_close_if_eof(aiohttp_client) -> None:\n    async def handler(request):\n        resp_ = web.StreamResponse()\n        await resp_.prepare(request)\n        await resp_.write(b\"data\\n\")\n        await asyncio.sleep(0.5)\n        return resp_\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    server = await aiohttp_client(app)\n\n    session = aiohttp.ClientSession()\n    try:\n        url, headers = server.make_url(\"/\"), {\"Connection\": \"Keep-alive\"}\n        resp = await session.get(url, headers=headers)\n        while True:\n            data = await resp.content.readline()\n            data = data.strip()\n            if not data:\n                break\n            assert data == b\"data\"\n\n        assert resp.content.exception() is None\n    finally:\n        await session.close()\n\n\nasync def test_error_not_overwrote_on_conn_close(aiohttp_client) -> None:\n    async def handler(request):\n        resp_ = web.StreamResponse()\n        await resp_.prepare(request)\n        return resp_\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    server = await aiohttp_client(app)\n\n    session = aiohttp.ClientSession()\n    try:\n        url, headers = server.make_url(\"/\"), {\"Connection\": \"Keep-alive\"}\n        resp = await session.get(url, headers=headers)\n        resp.content.set_exception(ValueError())\n    finally:\n        await session.close()\n\n    assert isinstance(resp.content.exception(), ValueError)\n\n\nasync def test_HTTP_200_OK_METHOD(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=request.method)\n\n    app = web.Application()\n    for meth in (\"get\", \"post\", \"put\", \"delete\", \"head\", \"patch\", \"options\"):\n        app.router.add_route(meth.upper(), \"/\", handler)\n\n    client = await aiohttp_client(app)\n    for meth in (\"get\", \"post\", \"put\", \"delete\", \"head\", \"patch\", \"options\"):\n        resp = await client.request(meth, \"/\")\n        assert resp.status == 200\n        assert len(resp.history) == 0\n\n        content1 = await resp.read()\n        content2 = await resp.read()\n        assert content1 == content2\n        content = await resp.text()\n\n        if meth == \"head\":\n            assert b\"\" == content1\n        else:\n            assert meth.upper() == content\n\n\nasync def test_HTTP_200_OK_METHOD_connector(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=request.method)\n\n    conn = aiohttp.TCPConnector()\n    conn.clear_dns_cache()\n\n    app = web.Application()\n    for meth in (\"get\", \"post\", \"put\", \"delete\", \"head\"):\n        app.router.add_route(meth.upper(), \"/\", handler)\n    client = await aiohttp_client(app, connector=conn)\n\n    for meth in (\"get\", \"post\", \"put\", \"delete\", \"head\"):\n        resp = await client.request(meth, \"/\")\n\n        content1 = await resp.read()\n        content2 = await resp.read()\n        assert content1 == content2\n        content = await resp.text()\n\n        assert resp.status == 200\n        if meth == \"head\":\n            assert b\"\" == content1\n        else:\n            assert meth.upper() == content\n\n\nasync def test_HTTP_302_REDIRECT_GET(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=request.method)\n\n    async def redirect(request):\n        raise web.HTTPFound(location=\"/\")\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    app.router.add_get(\"/redirect\", redirect)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/redirect\") as resp:\n        assert 200 == resp.status\n        assert 1 == len(resp.history)\n\n\nasync def test_HTTP_302_REDIRECT_HEAD(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=request.method)\n\n    async def redirect(request):\n        raise web.HTTPFound(location=\"/\")\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    app.router.add_get(\"/redirect\", redirect)\n    app.router.add_head(\"/\", handler)\n    app.router.add_head(\"/redirect\", redirect)\n    client = await aiohttp_client(app)\n\n    async with client.request(\"head\", \"/redirect\") as resp:\n        assert 200 == resp.status\n        assert 1 == len(resp.history)\n        assert resp.method == \"HEAD\"\n\n\nasync def test_HTTP_302_REDIRECT_NON_HTTP(aiohttp_client) -> None:\n    async def redirect(request):\n        raise web.HTTPFound(location=\"ftp://127.0.0.1/test/\")\n\n    app = web.Application()\n    app.router.add_get(\"/redirect\", redirect)\n    client = await aiohttp_client(app)\n\n    with pytest.raises(NonHttpUrlRedirectClientError):\n        await client.get(\"/redirect\")\n\n\nasync def test_HTTP_302_REDIRECT_POST(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=request.method)\n\n    async def redirect(request):\n        raise web.HTTPFound(location=\"/\")\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    app.router.add_post(\"/redirect\", redirect)\n    client = await aiohttp_client(app)\n\n    resp = await client.post(\"/redirect\")\n    assert 200 == resp.status\n    assert 1 == len(resp.history)\n    txt = await resp.text()\n    assert txt == \"GET\"\n    resp.close()\n\n\nasync def test_HTTP_302_REDIRECT_POST_with_content_length_hdr(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=request.method)\n\n    async def redirect(request):\n        await request.read()\n        raise web.HTTPFound(location=\"/\")\n\n    data = json.dumps({\"some\": \"data\"})\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    app.router.add_post(\"/redirect\", redirect)\n    client = await aiohttp_client(app)\n\n    resp = await client.post(\n        \"/redirect\", data=data, headers={\"Content-Length\": str(len(data))}\n    )\n    assert 200 == resp.status\n    assert 1 == len(resp.history)\n    txt = await resp.text()\n    assert txt == \"GET\"\n    resp.close()\n\n\nasync def test_HTTP_307_REDIRECT_POST(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=request.method)\n\n    async def redirect(request):\n        await request.read()\n        raise web.HTTPTemporaryRedirect(location=\"/\")\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    app.router.add_post(\"/redirect\", redirect)\n    client = await aiohttp_client(app)\n\n    resp = await client.post(\"/redirect\", data={\"some\": \"data\"})\n    assert 200 == resp.status\n    assert 1 == len(resp.history)\n    txt = await resp.text()\n    assert txt == \"POST\"\n    resp.close()\n\n\nasync def test_HTTP_308_PERMANENT_REDIRECT_POST(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=request.method)\n\n    async def redirect(request):\n        await request.read()\n        raise web.HTTPPermanentRedirect(location=\"/\")\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    app.router.add_post(\"/redirect\", redirect)\n    client = await aiohttp_client(app)\n\n    resp = await client.post(\"/redirect\", data={\"some\": \"data\"})\n    assert 200 == resp.status\n    assert 1 == len(resp.history)\n    txt = await resp.text()\n    assert txt == \"POST\"\n    resp.close()\n\n\nasync def test_HTTP_302_max_redirects(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=request.method)\n\n    async def redirect(request):\n        count = int(request.match_info[\"count\"])\n        if count:\n            raise web.HTTPFound(location=f\"/redirect/{count - 1}\")\n        else:\n            raise web.HTTPFound(location=\"/\")\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    app.router.add_get(r\"/redirect/{count:\\d+}\", redirect)\n    client = await aiohttp_client(app)\n\n    with pytest.raises(TooManyRedirects) as ctx:\n        await client.get(\"/redirect/5\", max_redirects=2)\n    assert 2 == len(ctx.value.history)\n    assert ctx.value.request_info.url.path == \"/redirect/5\"\n    assert ctx.value.request_info.method == \"GET\"\n\n\nasync def test_HTTP_200_GET_WITH_PARAMS(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(\n            text=\"&\".join(k + \"=\" + v for k, v in request.query.items())\n        )\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\", params={\"q\": \"test\"})\n    assert 200 == resp.status\n    txt = await resp.text()\n    assert txt == \"q=test\"\n    resp.close()\n\n\nasync def test_HTTP_200_GET_WITH_MultiDict_PARAMS(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(\n            text=\"&\".join(k + \"=\" + v for k, v in request.query.items())\n        )\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\", params=MultiDict([(\"q\", \"test\"), (\"q\", \"test2\")]))\n    assert 200 == resp.status\n    txt = await resp.text()\n    assert txt == \"q=test&q=test2\"\n    resp.close()\n\n\nasync def test_HTTP_200_GET_WITH_MIXED_PARAMS(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(\n            text=\"&\".join(k + \"=\" + v for k, v in request.query.items())\n        )\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/?test=true\", params={\"q\": \"test\"})\n    assert 200 == resp.status\n    txt = await resp.text()\n    assert txt == \"test=true&q=test\"\n    resp.close()\n\n\nasync def test_POST_DATA(aiohttp_client) -> None:\n    async def handler(request):\n        data = await request.post()\n        return web.json_response(dict(data))\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.post(\"/\", data={\"some\": \"data\"})\n    assert 200 == resp.status\n    content = await resp.json()\n    assert content == {\"some\": \"data\"}\n    resp.close()\n\n\nasync def test_POST_DATA_with_explicit_formdata(aiohttp_client) -> None:\n    async def handler(request):\n        data = await request.post()\n        return web.json_response(dict(data))\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    form = aiohttp.FormData()\n    form.add_field(\"name\", \"text\")\n\n    resp = await client.post(\"/\", data=form)\n    assert 200 == resp.status\n    content = await resp.json()\n    assert content == {\"name\": \"text\"}\n    resp.close()\n\n\nasync def test_POST_DATA_with_charset(aiohttp_client) -> None:\n    async def handler(request):\n        mp = await request.multipart()\n        part = await mp.next()\n        text = await part.text()\n        return web.Response(text=text)\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    form = aiohttp.FormData()\n    form.add_field(\"name\", \"текст\", content_type=\"text/plain; charset=koi8-r\")\n\n    resp = await client.post(\"/\", data=form)\n    assert 200 == resp.status\n    content = await resp.text()\n    assert content == \"текст\"\n    resp.close()\n\n\nasync def test_POST_DATA_formdats_with_charset(aiohttp_client) -> None:\n    async def handler(request):\n        mp = await request.post()\n        assert \"name\" in mp\n        return web.Response(text=mp[\"name\"])\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    form = aiohttp.FormData(charset=\"koi8-r\")\n    form.add_field(\"name\", \"текст\")\n\n    resp = await client.post(\"/\", data=form)\n    assert 200 == resp.status\n    content = await resp.text()\n    assert content == \"текст\"\n    resp.close()\n\n\nasync def test_POST_DATA_with_charset_post(aiohttp_client) -> None:\n    async def handler(request):\n        data = await request.post()\n        return web.Response(text=data[\"name\"])\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    form = aiohttp.FormData()\n    form.add_field(\"name\", \"текст\", content_type=\"text/plain; charset=koi8-r\")\n\n    resp = await client.post(\"/\", data=form)\n    assert 200 == resp.status\n    content = await resp.text()\n    assert content == \"текст\"\n    resp.close()\n\n\nasync def test_POST_MultiDict(aiohttp_client) -> None:\n    async def handler(request):\n        data = await request.post()\n        assert data == MultiDict([(\"q\", \"test1\"), (\"q\", \"test2\")])\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.post(\n        \"/\", data=MultiDict([(\"q\", \"test1\"), (\"q\", \"test2\")])\n    ) as resp:\n        assert 200 == resp.status\n\n\nasync def test_POST_DATA_DEFLATE(aiohttp_client) -> None:\n    async def handler(request):\n        data = await request.post()\n        return web.json_response(dict(data))\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.post(\"/\", data={\"some\": \"data\"}, compress=True)\n    assert 200 == resp.status\n    content = await resp.json()\n    assert content == {\"some\": \"data\"}\n    resp.close()\n\n\nasync def test_POST_FILES(aiohttp_client, fname) -> None:\n    async def handler(request):\n        data = await request.post()\n        assert data[\"some\"].filename == fname.name\n        with fname.open(\"rb\") as f:\n            content1 = f.read()\n        content2 = data[\"some\"].file.read()\n        assert content1 == content2\n        assert data[\"test\"].file.read() == b\"data\"\n        data[\"some\"].file.close()\n        data[\"test\"].file.close()\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with fname.open(\"rb\") as f:\n        async with client.post(\n            \"/\", data={\"some\": f, \"test\": io.BytesIO(b\"data\")}, chunked=True\n        ) as resp:\n            assert 200 == resp.status\n\n\nasync def test_POST_FILES_DEFLATE(aiohttp_client, fname) -> None:\n    async def handler(request):\n        data = await request.post()\n        assert data[\"some\"].filename == fname.name\n        with fname.open(\"rb\") as f:\n            content1 = f.read()\n        content2 = data[\"some\"].file.read()\n        data[\"some\"].file.close()\n        assert content1 == content2\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with fname.open(\"rb\") as f:\n        async with client.post(\n            \"/\", data={\"some\": f}, chunked=True, compress=\"deflate\"\n        ) as resp:\n            assert 200 == resp.status\n\n\nasync def test_POST_bytes(aiohttp_client) -> None:\n    body = b\"0\" * 12345\n\n    async def handler(request):\n        data = await request.read()\n        assert body == data\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.post(\"/\", data=body) as resp:\n        assert 200 == resp.status\n\n\nasync def test_POST_bytes_too_large(aiohttp_client) -> None:\n    body = b\"0\" * (2**20 + 1)\n\n    async def handler(request):\n        data = await request.content.read()\n        assert body == data\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with pytest.warns(ResourceWarning):\n        resp = await client.post(\"/\", data=body)\n\n    assert 200 == resp.status\n    resp.close()\n\n\nasync def test_POST_FILES_STR(aiohttp_client, fname) -> None:\n    async def handler(request):\n        data = await request.post()\n        with fname.open(\"rb\") as f:\n            content1 = f.read().decode()\n        content2 = data[\"some\"]\n        assert content1 == content2\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with fname.open(\"rb\") as f:\n        async with client.post(\"/\", data={\"some\": f.read().decode()}) as resp:\n            assert 200 == resp.status\n\n\nasync def test_POST_FILES_STR_SIMPLE(aiohttp_client, fname) -> None:\n    async def handler(request):\n        data = await request.read()\n        with fname.open(\"rb\") as f:\n            content = f.read()\n        assert content == data\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with fname.open(\"rb\") as f:\n        async with client.post(\"/\", data=f.read()) as resp:\n            assert 200 == resp.status\n\n\nasync def test_POST_FILES_LIST(aiohttp_client, fname) -> None:\n    async def handler(request):\n        data = await request.post()\n        assert fname.name == data[\"some\"].filename\n        with fname.open(\"rb\") as f:\n            content = f.read()\n        assert content == data[\"some\"].file.read()\n        data[\"some\"].file.close()\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with fname.open(\"rb\") as f:\n        async with client.post(\"/\", data=[(\"some\", f)]) as resp:\n            assert 200 == resp.status\n\n\nasync def test_POST_FILES_CT(aiohttp_client, fname) -> None:\n    async def handler(request):\n        data = await request.post()\n        assert fname.name == data[\"some\"].filename\n        assert \"text/plain\" == data[\"some\"].content_type\n        with fname.open(\"rb\") as f:\n            content = f.read()\n        assert content == data[\"some\"].file.read()\n        data[\"some\"].file.close()\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with fname.open(\"rb\") as f:\n        form = aiohttp.FormData()\n        form.add_field(\"some\", f, content_type=\"text/plain\")\n        async with client.post(\"/\", data=form) as resp:\n            assert 200 == resp.status\n\n\nasync def test_POST_FILES_SINGLE(aiohttp_client, fname) -> None:\n    async def handler(request):\n        data = await request.text()\n        with fname.open(\"rb\") as f:\n            content = f.read().decode()\n            assert content == data\n        # if system cannot determine 'text/x-python' MIME type\n        # then use 'application/octet-stream' default\n        assert request.content_type in [\n            \"text/plain\",\n            \"application/octet-stream\",\n            \"text/x-python\",\n        ]\n        assert \"content-disposition\" not in request.headers\n\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with fname.open(\"rb\") as f:\n        async with client.post(\"/\", data=f) as resp:\n            assert 200 == resp.status\n\n\nasync def test_POST_FILES_SINGLE_content_disposition(aiohttp_client, fname) -> None:\n    async def handler(request):\n        data = await request.text()\n        with fname.open(\"rb\") as f:\n            content = f.read().decode()\n            assert content == data\n        # if system cannot determine 'application/pgp-keys' MIME type\n        # then use 'application/octet-stream' default\n        assert request.content_type in [\n            \"text/plain\",\n            \"application/octet-stream\",\n            \"text/x-python\",\n        ]\n        assert request.headers[\"content-disposition\"] == (\n            'inline; filename=\"conftest.py\"'\n        )\n\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with fname.open(\"rb\") as f:\n        async with client.post(\n            \"/\", data=aiohttp.get_payload(f, disposition=\"inline\")\n        ) as resp:\n            assert 200 == resp.status\n\n\nasync def test_POST_FILES_SINGLE_BINARY(aiohttp_client, fname) -> None:\n    async def handler(request):\n        data = await request.read()\n        with fname.open(\"rb\") as f:\n            content = f.read()\n        assert content == data\n        # if system cannot determine 'application/pgp-keys' MIME type\n        # then use 'application/octet-stream' default\n        assert request.content_type in [\n            \"application/pgp-keys\",\n            \"text/plain\",\n            \"text/x-python\",\n            \"application/octet-stream\",\n        ]\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with fname.open(\"rb\") as f:\n        async with client.post(\"/\", data=f) as resp:\n            assert 200 == resp.status\n\n\nasync def test_POST_FILES_IO(aiohttp_client) -> None:\n    async def handler(request):\n        data = await request.post()\n        assert b\"data\" == data[\"unknown\"].file.read()\n        assert data[\"unknown\"].content_type == \"application/octet-stream\"\n        assert data[\"unknown\"].filename == \"unknown\"\n        data[\"unknown\"].file.close()\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with io.BytesIO(b\"data\") as file_handle:\n        async with client.post(\"/\", data=[file_handle]) as resp:\n            assert 200 == resp.status\n\n\nasync def test_POST_FILES_IO_WITH_PARAMS(aiohttp_client) -> None:\n    async def handler(request):\n        data = await request.post()\n        assert data[\"test\"] == \"true\"\n        assert data[\"unknown\"].content_type == \"application/octet-stream\"\n        assert data[\"unknown\"].filename == \"unknown\"\n        assert data[\"unknown\"].file.read() == b\"data\"\n        data[\"unknown\"].file.close()\n        assert data.getall(\"q\") == [\"t1\", \"t2\"]\n\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with io.BytesIO(b\"data\") as file_handle:\n        async with client.post(\n            \"/\",\n            data=((\"test\", \"true\"), MultiDict([(\"q\", \"t1\"), (\"q\", \"t2\")]), file_handle),\n        ) as resp:\n            assert 200 == resp.status\n\n\nasync def test_POST_FILES_WITH_DATA(aiohttp_client, fname) -> None:\n    async def handler(request):\n        data = await request.post()\n        assert data[\"test\"] == \"true\"\n        assert data[\"some\"].content_type in [\n            \"text/x-python\",\n            \"text/plain\",\n            \"application/octet-stream\",\n        ]\n        assert data[\"some\"].filename == fname.name\n        with fname.open(\"rb\") as f:\n            assert data[\"some\"].file.read() == f.read()\n            data[\"some\"].file.close()\n\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with fname.open(\"rb\") as f:\n        async with client.post(\"/\", data={\"test\": \"true\", \"some\": f}) as resp:\n            assert 200 == resp.status\n\n\nasync def test_POST_STREAM_DATA(aiohttp_client, fname) -> None:\n    async def handler(request):\n        assert request.content_type == \"application/octet-stream\"\n        content = await request.read()\n        with fname.open(\"rb\") as f:\n            expected = f.read()\n            assert request.content_length == len(expected)\n            assert content == expected\n\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with fname.open(\"rb\") as f:\n        data_size = len(f.read())\n\n    with pytest.warns(DeprecationWarning):\n\n        @aiohttp.streamer\n        async def stream(writer, fname):\n            with fname.open(\"rb\") as f:\n                data = f.read(100)\n                while data:\n                    await writer.write(data)\n                    data = f.read(100)\n\n    async with client.post(\n        \"/\", data=stream(fname), headers={\"Content-Length\": str(data_size)}\n    ) as resp:\n        assert 200 == resp.status\n\n\nasync def test_POST_STREAM_DATA_no_params(aiohttp_client, fname) -> None:\n    async def handler(request):\n        assert request.content_type == \"application/octet-stream\"\n        content = await request.read()\n        with fname.open(\"rb\") as f:\n            expected = f.read()\n            assert request.content_length == len(expected)\n            assert content == expected\n\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with fname.open(\"rb\") as f:\n        data_size = len(f.read())\n\n    with pytest.warns(DeprecationWarning):\n\n        @aiohttp.streamer\n        async def stream(writer):\n            with fname.open(\"rb\") as f:\n                data = f.read(100)\n                while data:\n                    await writer.write(data)\n                    data = f.read(100)\n\n    async with client.post(\n        \"/\", data=stream, headers={\"Content-Length\": str(data_size)}\n    ) as resp:\n        assert 200 == resp.status\n\n\nasync def test_json(aiohttp_client) -> None:\n    async def handler(request):\n        assert request.content_type == \"application/json\"\n        data = await request.json()\n        return web.Response(body=aiohttp.JsonPayload(data))\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.post(\"/\", json={\"some\": \"data\"})\n    assert 200 == resp.status\n    content = await resp.json()\n    assert content == {\"some\": \"data\"}\n    resp.close()\n\n    with pytest.raises(ValueError):\n        await client.post(\"/\", data=\"some data\", json={\"some\": \"data\"})\n\n\nasync def test_json_custom(aiohttp_client) -> None:\n    async def handler(request):\n        assert request.content_type == \"application/json\"\n        data = await request.json()\n        return web.Response(body=aiohttp.JsonPayload(data))\n\n    used = False\n\n    def dumps(obj):\n        nonlocal used\n        used = True\n        return json.dumps(obj)\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app, json_serialize=dumps)\n\n    resp = await client.post(\"/\", json={\"some\": \"data\"})\n    assert 200 == resp.status\n    assert used\n    content = await resp.json()\n    assert content == {\"some\": \"data\"}\n    resp.close()\n\n    with pytest.raises(ValueError):\n        await client.post(\"/\", data=\"some data\", json={\"some\": \"data\"})\n\n\nasync def test_expect_continue(aiohttp_client) -> None:\n    expect_called = False\n\n    async def handler(request):\n        data = await request.post()\n        assert data == {\"some\": \"data\"}\n        return web.Response()\n\n    async def expect_handler(request):\n        nonlocal expect_called\n        expect = request.headers.get(hdrs.EXPECT)\n        if expect.lower() == \"100-continue\":\n            request.transport.write(b\"HTTP/1.1 100 Continue\\r\\n\\r\\n\")\n            expect_called = True\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler, expect_handler=expect_handler)\n    client = await aiohttp_client(app)\n\n    async with client.post(\"/\", data={\"some\": \"data\"}, expect100=True) as resp:\n        assert 200 == resp.status\n    assert expect_called\n\n\nasync def test_encoding_deflate(aiohttp_client) -> None:\n    async def handler(request):\n        resp = web.Response(text=\"text\")\n        resp.enable_chunked_encoding()\n        resp.enable_compression(web.ContentCoding.deflate)\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert 200 == resp.status\n    txt = await resp.text()\n    assert txt == \"text\"\n    resp.close()\n\n\nasync def test_encoding_deflate_nochunk(aiohttp_client) -> None:\n    async def handler(request):\n        resp = web.Response(text=\"text\")\n        resp.enable_compression(web.ContentCoding.deflate)\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert 200 == resp.status\n    txt = await resp.text()\n    assert txt == \"text\"\n    resp.close()\n\n\nasync def test_encoding_gzip(aiohttp_client) -> None:\n    async def handler(request):\n        resp = web.Response(text=\"text\")\n        resp.enable_chunked_encoding()\n        resp.enable_compression(web.ContentCoding.gzip)\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert 200 == resp.status\n    txt = await resp.text()\n    assert txt == \"text\"\n    resp.close()\n\n\nasync def test_encoding_gzip_write_by_chunks(aiohttp_client) -> None:\n    async def handler(request):\n        resp = web.StreamResponse()\n        resp.enable_compression(web.ContentCoding.gzip)\n        await resp.prepare(request)\n        await resp.write(b\"0\")\n        await resp.write(b\"0\")\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert 200 == resp.status\n    txt = await resp.text()\n    assert txt == \"00\"\n    resp.close()\n\n\nasync def test_encoding_gzip_nochunk(aiohttp_client) -> None:\n    async def handler(request):\n        resp = web.Response(text=\"text\")\n        resp.enable_compression(web.ContentCoding.gzip)\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert 200 == resp.status\n    txt = await resp.text()\n    assert txt == \"text\"\n    resp.close()\n\n\nasync def test_bad_payload_compression(aiohttp_client) -> None:\n    async def handler(request):\n        resp = web.Response(text=\"text\")\n        resp.headers[\"Content-Encoding\"] = \"gzip\"\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert 200 == resp.status\n\n    with pytest.raises(aiohttp.ClientPayloadError):\n        await resp.read()\n\n    resp.close()\n\n\nasync def test_bad_payload_chunked_encoding(aiohttp_client) -> None:\n    async def handler(request):\n        resp = web.StreamResponse()\n        resp.force_close()\n        resp._length_check = False\n        resp.headers[\"Transfer-Encoding\"] = \"chunked\"\n        writer = await resp.prepare(request)\n        await writer.write(b\"9\\r\\n\\r\\n\")\n        await writer.write_eof()\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert 200 == resp.status\n\n    with pytest.raises(aiohttp.ClientPayloadError):\n        await resp.read()\n\n    resp.close()\n\n\nasync def test_no_payload_304_with_chunked_encoding(aiohttp_client: Any) -> None:\n    \"\"\"Test a 304 response with no payload with chunked set should have it removed.\"\"\"\n\n    async def handler(request):\n        resp = web.StreamResponse(status=304)\n        resp.enable_chunked_encoding()\n        resp._length_check = False\n        resp.headers[\"Transfer-Encoding\"] = \"chunked\"\n        writer = await resp.prepare(request)\n        await writer.write_eof()\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert resp.status == 304\n    assert hdrs.CONTENT_LENGTH not in resp.headers\n    assert hdrs.TRANSFER_ENCODING not in resp.headers\n    await resp.read()\n\n    resp.close()\n\n\nasync def test_head_request_with_chunked_encoding(aiohttp_client: Any) -> None:\n    \"\"\"Test a head response with chunked set should have it removed.\"\"\"\n\n    async def handler(request):\n        resp = web.StreamResponse(status=200)\n        resp.enable_chunked_encoding()\n        resp._length_check = False\n        resp.headers[\"Transfer-Encoding\"] = \"chunked\"\n        writer = await resp.prepare(request)\n        await writer.write_eof()\n        return resp\n\n    app = web.Application()\n    app.router.add_head(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.head(\"/\")\n    assert resp.status == 200\n    assert hdrs.CONTENT_LENGTH not in resp.headers\n    assert hdrs.TRANSFER_ENCODING not in resp.headers\n    await resp.read()\n\n    resp.close()\n\n\nasync def test_no_payload_200_with_chunked_encoding(aiohttp_client: Any) -> None:\n    \"\"\"Test chunked is preserved on a 200 response with no payload.\"\"\"\n\n    async def handler(request):\n        resp = web.StreamResponse(status=200)\n        resp.enable_chunked_encoding()\n        resp._length_check = False\n        resp.headers[\"Transfer-Encoding\"] = \"chunked\"\n        writer = await resp.prepare(request)\n        await writer.write_eof()\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert resp.status == 200\n    assert hdrs.CONTENT_LENGTH not in resp.headers\n    assert hdrs.TRANSFER_ENCODING in resp.headers\n    await resp.read()\n\n    resp.close()\n\n\nasync def test_bad_payload_content_length(aiohttp_client: Any) -> None:\n    async def handler(request):\n        resp = web.Response(text=\"text\")\n        resp.headers[\"Content-Length\"] = \"10000\"\n        resp.force_close()\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert 200 == resp.status\n\n    with pytest.raises(aiohttp.ClientPayloadError):\n        await resp.read()\n\n    resp.close()\n\n\nasync def test_payload_content_length_by_chunks(aiohttp_client) -> None:\n    async def handler(request):\n        resp = web.StreamResponse(headers={\"content-length\": \"2\"})\n        await resp.prepare(request)\n        await resp.write(b\"answer\")\n        await resp.write(b\"two\")\n        request.transport.close()\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    data = await resp.read()\n    assert data == b\"an\"\n    resp.close()\n\n\nasync def test_chunked(aiohttp_client) -> None:\n    async def handler(request):\n        resp = web.Response(text=\"text\")\n        resp.enable_chunked_encoding()\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert 200 == resp.status\n    assert resp.headers[\"Transfer-Encoding\"] == \"chunked\"\n    txt = await resp.text()\n    assert txt == \"text\"\n    resp.close()\n\n\nasync def test_shortcuts(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=request.method)\n\n    app = web.Application()\n    for meth in (\"get\", \"post\", \"put\", \"delete\", \"head\", \"patch\", \"options\"):\n        app.router.add_route(meth.upper(), \"/\", handler)\n    client = await aiohttp_client(app)\n\n    for meth in (\"get\", \"post\", \"put\", \"delete\", \"head\", \"patch\", \"options\"):\n        coro = getattr(client.session, meth)\n        resp = await coro(client.make_url(\"/\"))\n\n        assert resp.status == 200\n        assert len(resp.history) == 0\n\n        content1 = await resp.read()\n        content2 = await resp.read()\n        assert content1 == content2\n        content = await resp.text()\n\n        if meth == \"head\":\n            assert b\"\" == content1\n        else:\n            assert meth.upper() == content\n\n\nasync def test_cookies(aiohttp_client) -> None:\n    async def handler(request):\n        assert request.cookies.keys() == {\"test1\", \"test3\"}\n        assert request.cookies[\"test1\"] == \"123\"\n        assert request.cookies[\"test3\"] == \"456\"\n        return web.Response()\n\n    c = http.cookies.Morsel()\n    c.set(\"test3\", \"456\", \"456\")\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app, cookies={\"test1\": \"123\", \"test2\": c})\n\n    async with client.get(\"/\") as resp:\n        assert 200 == resp.status\n\n\nasync def test_cookies_per_request(aiohttp_client) -> None:\n    async def handler(request):\n        assert request.cookies.keys() == {\"test1\", \"test3\", \"test4\", \"test6\"}\n        assert request.cookies[\"test1\"] == \"123\"\n        assert request.cookies[\"test3\"] == \"456\"\n        assert request.cookies[\"test4\"] == \"789\"\n        assert request.cookies[\"test6\"] == \"abc\"\n        return web.Response()\n\n    c = http.cookies.Morsel()\n    c.set(\"test3\", \"456\", \"456\")\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app, cookies={\"test1\": \"123\", \"test2\": c})\n\n    rc = http.cookies.Morsel()\n    rc.set(\"test6\", \"abc\", \"abc\")\n\n    async with client.get(\"/\", cookies={\"test4\": \"789\", \"test5\": rc}) as resp:\n        assert 200 == resp.status\n\n\nasync def test_cookies_redirect(aiohttp_client) -> None:\n    async def redirect1(request):\n        ret = web.Response(status=301, headers={\"Location\": \"/redirect2\"})\n        ret.set_cookie(\"c\", \"1\")\n        return ret\n\n    async def redirect2(request):\n        ret = web.Response(status=301, headers={\"Location\": \"/\"})\n        ret.set_cookie(\"c\", \"2\")\n        return ret\n\n    async def handler(request):\n        assert request.cookies.keys() == {\"c\"}\n        assert request.cookies[\"c\"] == \"2\"\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_get(\"/redirect1\", redirect1)\n    app.router.add_get(\"/redirect2\", redirect2)\n    app.router.add_get(\"/\", handler)\n\n    client = await aiohttp_client(app)\n    async with client.get(\"/redirect1\") as resp:\n        assert 200 == resp.status\n\n\nasync def test_cookies_on_empty_session_jar(aiohttp_client) -> None:\n    async def handler(request):\n        assert \"custom-cookie\" in request.cookies\n        assert request.cookies[\"custom-cookie\"] == \"abc\"\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app, cookies=None)\n\n    async with client.get(\"/\", cookies={\"custom-cookie\": \"abc\"}) as resp:\n        assert 200 == resp.status\n\n\nasync def test_morsel_with_attributes(aiohttp_client) -> None:\n    # A comment from original test:\n    #\n    # No cookie attribute should pass here\n    # they are only used as filters\n    # whether to send particular cookie or not.\n    # E.g. if cookie expires it just becomes thrown away.\n    # Server who sent the cookie with some attributes\n    # already knows them, no need to send this back again and again\n\n    async def handler(request):\n        assert request.cookies.keys() == {\"test3\"}\n        assert request.cookies[\"test3\"] == \"456\"\n        return web.Response()\n\n    c = http.cookies.Morsel()\n    c.set(\"test3\", \"456\", \"456\")\n    c[\"httponly\"] = True\n    c[\"secure\"] = True\n    c[\"max-age\"] = 1000\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app, cookies={\"test2\": c})\n\n    async with client.get(\"/\") as resp:\n        assert 200 == resp.status\n\n\nasync def test_set_cookies(aiohttp_client) -> None:\n    async def handler(request):\n        ret = web.Response()\n        ret.set_cookie(\"c1\", \"cookie1\")\n        ret.set_cookie(\"c2\", \"cookie2\")\n        ret.headers.add(\n            \"Set-Cookie\",\n            \"ISAWPLB{A7F52349-3531-4DA9-8776-F74BC6F4F1BB}=\"\n            \"{925EC0B8-CB17-4BEB-8A35-1033813B0523}; \"\n            \"HttpOnly; Path=/\",\n        )\n        return ret\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with mock.patch(\"aiohttp.client_reqrep.client_logger\") as m_log:\n        async with client.get(\"/\") as resp:\n            assert 200 == resp.status\n            cookie_names = {c.key for c in client.session.cookie_jar}\n        assert cookie_names == {\"c1\", \"c2\"}\n\n        m_log.warning.assert_called_with(\"Can not load response cookies: %s\", mock.ANY)\n\n\nasync def test_set_cookies_expired(aiohttp_client) -> None:\n    async def handler(request):\n        ret = web.Response()\n        ret.set_cookie(\"c1\", \"cookie1\")\n        ret.set_cookie(\"c2\", \"cookie2\")\n        ret.headers.add(\n            \"Set-Cookie\",\n            \"c3=cookie3; \" \"HttpOnly; Path=/\" \" Expires=Tue, 1 Jan 1980 12:00:00 GMT; \",\n        )\n        return ret\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/\") as resp:\n        assert 200 == resp.status\n        cookie_names = {c.key for c in client.session.cookie_jar}\n    assert cookie_names == {\"c1\", \"c2\"}\n\n\nasync def test_set_cookies_max_age(aiohttp_client) -> None:\n    async def handler(request):\n        ret = web.Response()\n        ret.set_cookie(\"c1\", \"cookie1\")\n        ret.set_cookie(\"c2\", \"cookie2\")\n        ret.headers.add(\"Set-Cookie\", \"c3=cookie3; \" \"HttpOnly; Path=/\" \" Max-Age=1; \")\n        return ret\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/\") as resp:\n        assert 200 == resp.status\n        cookie_names = {c.key for c in client.session.cookie_jar}\n        assert cookie_names == {\"c1\", \"c2\", \"c3\"}\n        await asyncio.sleep(2)\n        cookie_names = {c.key for c in client.session.cookie_jar}\n        assert cookie_names == {\"c1\", \"c2\"}\n\n\nasync def test_set_cookies_max_age_overflow(aiohttp_client) -> None:\n    async def handler(request):\n        ret = web.Response()\n        ret.headers.add(\n            \"Set-Cookie\",\n            \"overflow=overflow; \" \"HttpOnly; Path=/\" \" Max-Age=\" + str(overflow) + \"; \",\n        )\n        return ret\n\n    overflow = int(\n        datetime.datetime.max.replace(tzinfo=datetime.timezone.utc).timestamp()\n    )\n    empty = None\n    try:\n        empty = datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(\n            seconds=overflow\n        )\n    except OverflowError as ex:\n        assert isinstance(ex, OverflowError)\n    assert not isinstance(empty, datetime.datetime)\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/\") as resp:\n        assert 200 == resp.status\n        for cookie in client.session.cookie_jar:\n            if cookie.key == \"overflow\":\n                assert int(cookie[\"max-age\"]) == int(overflow)\n\n\nasync def test_request_conn_error() -> None:\n    client = aiohttp.ClientSession()\n    with pytest.raises(aiohttp.ClientConnectionError):\n        await client.get(\"http://0.0.0.0:1\")\n    await client.close()\n\n\n@pytest.mark.xfail\nasync def test_broken_connection(aiohttp_client) -> None:\n    async def handler(request):\n        request.transport.close()\n        return web.Response(text=\"answer\" * 1000)\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with pytest.raises(aiohttp.ClientResponseError):\n        await client.get(\"/\")\n\n\nasync def test_broken_connection_2(aiohttp_client) -> None:\n    async def handler(request):\n        resp = web.StreamResponse(headers={\"content-length\": \"1000\"})\n        await resp.prepare(request)\n        await resp.write(b\"answer\")\n        request.transport.close()\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    with pytest.raises(aiohttp.ClientPayloadError):\n        await resp.read()\n    resp.close()\n\n\nasync def test_custom_headers(aiohttp_client) -> None:\n    async def handler(request):\n        assert request.headers[\"x-api-key\"] == \"foo\"\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.post(\n        \"/\", headers={\"Content-Type\": \"application/json\", \"x-api-key\": \"foo\"}\n    ) as resp:\n        assert resp.status == 200\n\n\nasync def test_redirect_to_absolute_url(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=request.method)\n\n    async def redirect(request):\n        raise web.HTTPFound(location=client.make_url(\"/\"))\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    app.router.add_get(\"/redirect\", redirect)\n\n    client = await aiohttp_client(app)\n    async with client.get(\"/redirect\") as resp:\n        assert 200 == resp.status\n\n\nasync def test_redirect_without_location_header(aiohttp_client) -> None:\n    body = b\"redirect\"\n\n    async def handler_redirect(request):\n        return web.Response(status=301, body=body)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/redirect\", handler_redirect)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/redirect\")\n    data = await resp.read()\n    assert data == body\n\n\nasync def test_chunked_deprecated(aiohttp_client) -> None:\n    async def handler_redirect(request):\n        return web.Response(status=301)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/redirect\", handler_redirect)\n    client = await aiohttp_client(app)\n\n    with pytest.warns(DeprecationWarning):\n        await client.post(\"/\", chunked=1024)\n\n\nINVALID_URL_WITH_ERROR_MESSAGE_YARL_NEW = (\n    # yarl.URL.__new__ raises ValueError\n    (\"http://:/\", \"http://:/\"),\n    (\"http://example.org:non_int_port/\", \"http://example.org:non_int_port/\"),\n)\n\nINVALID_URL_WITH_ERROR_MESSAGE_YARL_ORIGIN = (\n    # # yarl.URL.origin raises ValueError\n    (\"http:/\", \"http:///\"),\n    (\"http:/example.com\", \"http:///example.com\"),\n    (\"http:///example.com\", \"http:///example.com\"),\n)\n\nNON_HTTP_URL_WITH_ERROR_MESSAGE = (\n    (\"call:+380123456789\", r\"call:\\+380123456789\"),\n    (\"skype:handle\", \"skype:handle\"),\n    (\"slack://instance/room\", \"slack://instance/room\"),\n    (\"steam:code\", \"steam:code\"),\n    (\"twitter://handle\", \"twitter://handle\"),\n    (\"bluesky://profile/d:i:d\", \"bluesky://profile/d:i:d\"),\n)\n\n\n@pytest.mark.parametrize(\n    (\"url\", \"error_message_url\", \"expected_exception_class\"),\n    (\n        *(\n            (url, message, InvalidUrlClientError)\n            for (url, message) in INVALID_URL_WITH_ERROR_MESSAGE_YARL_NEW\n        ),\n        *(\n            (url, message, InvalidUrlClientError)\n            for (url, message) in INVALID_URL_WITH_ERROR_MESSAGE_YARL_ORIGIN\n        ),\n        *(\n            (url, message, NonHttpUrlClientError)\n            for (url, message) in NON_HTTP_URL_WITH_ERROR_MESSAGE\n        ),\n    ),\n)\nasync def test_invalid_and_non_http_url(\n    url: Any, error_message_url: Any, expected_exception_class: Any\n) -> None:\n    async with aiohttp.ClientSession() as http_session:\n        with pytest.raises(\n            expected_exception_class, match=rf\"^{error_message_url}( - [A-Za-z ]+)?\"\n        ):\n            await http_session.get(url)\n\n\n@pytest.mark.parametrize(\n    (\"invalid_redirect_url\", \"error_message_url\", \"expected_exception_class\"),\n    (\n        *(\n            (url, message, InvalidUrlRedirectClientError)\n            for (url, message) in INVALID_URL_WITH_ERROR_MESSAGE_YARL_ORIGIN\n            + INVALID_URL_WITH_ERROR_MESSAGE_YARL_NEW\n        ),\n        *(\n            (url, message, NonHttpUrlRedirectClientError)\n            for (url, message) in NON_HTTP_URL_WITH_ERROR_MESSAGE\n        ),\n    ),\n)\nasync def test_invalid_redirect_url(\n    aiohttp_client: Any,\n    invalid_redirect_url: Any,\n    error_message_url: str,\n    expected_exception_class: Any,\n) -> None:\n    headers = {hdrs.LOCATION: invalid_redirect_url}\n\n    async def generate_redirecting_response(request):\n        return web.Response(status=301, headers=headers)\n\n    app = web.Application()\n    app.router.add_get(\"/redirect\", generate_redirecting_response)\n    client = await aiohttp_client(app)\n\n    with pytest.raises(\n        expected_exception_class, match=rf\"^{error_message_url}( - [A-Za-z ]+)?\"\n    ):\n        await client.get(\"/redirect\")\n\n\n@pytest.mark.parametrize(\n    (\"invalid_redirect_url\", \"error_message_url\", \"expected_exception_class\"),\n    (\n        *(\n            (url, message, InvalidUrlRedirectClientError)\n            for (url, message) in INVALID_URL_WITH_ERROR_MESSAGE_YARL_ORIGIN\n            + INVALID_URL_WITH_ERROR_MESSAGE_YARL_NEW\n        ),\n        *(\n            (url, message, NonHttpUrlRedirectClientError)\n            for (url, message) in NON_HTTP_URL_WITH_ERROR_MESSAGE\n        ),\n    ),\n)\nasync def test_invalid_redirect_url_multiple_redirects(\n    aiohttp_client: Any,\n    invalid_redirect_url: Any,\n    error_message_url: str,\n    expected_exception_class: Any,\n) -> None:\n    app = web.Application()\n\n    for path, location in [\n        (\"/redirect\", \"/redirect1\"),\n        (\"/redirect1\", \"/redirect2\"),\n        (\"/redirect2\", invalid_redirect_url),\n    ]:\n\n        async def generate_redirecting_response(request):\n            return web.Response(status=301, headers={hdrs.LOCATION: location})\n\n        app.router.add_get(path, generate_redirecting_response)\n\n    client = await aiohttp_client(app)\n\n    with pytest.raises(\n        expected_exception_class, match=rf\"^{error_message_url}( - [A-Za-z ]+)?\"\n    ):\n        await client.get(\"/redirect\")\n\n\n@pytest.mark.parametrize(\n    (\"status\", \"expected_ok\"),\n    (\n        (200, True),\n        (201, True),\n        (301, True),\n        (400, False),\n        (403, False),\n        (500, False),\n    ),\n)\nasync def test_ok_from_status(aiohttp_client, status, expected_ok) -> None:\n    async def handler(request):\n        return web.Response(status=status, body=b\"\")\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/endpoint\", handler)\n    client = await aiohttp_client(app, raise_for_status=False)\n    async with client.get(\"/endpoint\") as resp:\n        assert resp.ok is expected_ok\n\n\nasync def test_raise_for_status(aiohttp_client) -> None:\n    async def handler_redirect(request):\n        raise web.HTTPBadRequest()\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler_redirect)\n    client = await aiohttp_client(app, raise_for_status=True)\n\n    with pytest.raises(aiohttp.ClientResponseError):\n        await client.get(\"/\")\n\n\nasync def test_raise_for_status_per_request(aiohttp_client) -> None:\n    async def handler_redirect(request):\n        raise web.HTTPBadRequest()\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler_redirect)\n    client = await aiohttp_client(app)\n\n    with pytest.raises(aiohttp.ClientResponseError):\n        await client.get(\"/\", raise_for_status=True)\n\n\nasync def test_raise_for_status_disable_per_request(aiohttp_client) -> None:\n    async def handler_redirect(request):\n        raise web.HTTPBadRequest()\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler_redirect)\n    client = await aiohttp_client(app, raise_for_status=True)\n\n    async with client.get(\"/\", raise_for_status=False) as resp:\n        assert 400 == resp.status\n\n\nasync def test_request_raise_for_status_default(aiohttp_server) -> None:\n    async def handler(request):\n        raise web.HTTPBadRequest()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    server = await aiohttp_server(app)\n\n    async with aiohttp.request(\"GET\", server.make_url(\"/\")) as resp:\n        assert resp.status == 400\n\n\nasync def test_request_raise_for_status_disabled(aiohttp_server) -> None:\n    async def handler(request):\n        raise web.HTTPBadRequest()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    server = await aiohttp_server(app)\n    url = server.make_url(\"/\")\n\n    async with aiohttp.request(\"GET\", url, raise_for_status=False) as resp:\n        assert resp.status == 400\n\n\nasync def test_request_raise_for_status_enabled(aiohttp_server) -> None:\n    async def handler(request):\n        raise web.HTTPBadRequest()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    server = await aiohttp_server(app)\n    url = server.make_url(\"/\")\n\n    with pytest.raises(aiohttp.ClientResponseError):\n        async with aiohttp.request(\"GET\", url, raise_for_status=True):\n            assert False, \"never executed\"  # pragma: no cover\n\n\nasync def test_session_raise_for_status_coro(aiohttp_client) -> None:\n    async def handle(request):\n        return web.Response(text=\"ok\")\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handle)\n\n    raise_for_status_called = 0\n\n    async def custom_r4s(response):\n        nonlocal raise_for_status_called\n        raise_for_status_called += 1\n        assert response.status == 200\n        assert response.request_info.method == \"GET\"\n\n    client = await aiohttp_client(app, raise_for_status=custom_r4s)\n    await client.get(\"/\")\n    assert raise_for_status_called == 1\n    await client.get(\"/\", raise_for_status=True)\n    assert raise_for_status_called == 1  # custom_r4s not called again\n    await client.get(\"/\", raise_for_status=False)\n    assert raise_for_status_called == 1  # custom_r4s not called again\n\n\nasync def test_request_raise_for_status_coro(aiohttp_client) -> None:\n    async def handle(request):\n        return web.Response(text=\"ok\")\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handle)\n\n    raise_for_status_called = 0\n\n    async def custom_r4s(response):\n        nonlocal raise_for_status_called\n        raise_for_status_called += 1\n        assert response.status == 200\n        assert response.request_info.method == \"GET\"\n\n    client = await aiohttp_client(app)\n    await client.get(\"/\", raise_for_status=custom_r4s)\n    assert raise_for_status_called == 1\n    await client.get(\"/\", raise_for_status=True)\n    assert raise_for_status_called == 1  # custom_r4s not called again\n    await client.get(\"/\", raise_for_status=False)\n    assert raise_for_status_called == 1  # custom_r4s not called again\n\n\nasync def test_invalid_idna() -> None:\n    session = aiohttp.ClientSession()\n    try:\n        with pytest.raises(aiohttp.InvalidURL):\n            await session.get(\"http://\\u2061owhefopw.com\")\n    finally:\n        await session.close()\n\n\nasync def test_creds_in_auth_and_url() -> None:\n    session = aiohttp.ClientSession()\n    try:\n        with pytest.raises(ValueError):\n            await session.get(\n                \"http://user:pass@example.com\", auth=aiohttp.BasicAuth(\"user2\", \"pass2\")\n            )\n    finally:\n        await session.close()\n\n\n@pytest.fixture\ndef create_server_for_url_and_handler(aiohttp_server, tls_certificate_authority):\n    def create(url, srv):\n        app = web.Application()\n        app.router.add_route(\"GET\", url.path, srv)\n\n        kwargs = {}\n        if url.scheme == \"https\":\n            cert = tls_certificate_authority.issue_cert(\n                url.host, \"localhost\", \"127.0.0.1\"\n            )\n            ssl_ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)\n            cert.configure_cert(ssl_ctx)\n            kwargs[\"ssl\"] = ssl_ctx\n        return aiohttp_server(app, **kwargs)\n\n    return create\n\n\n@pytest.mark.parametrize(\n    [\"url_from\", \"url_to\"],\n    [\n        [\"http://host1.com/path1\", \"http://host2.com/path2\"],\n        [\"http://host1.com/path1\", \"https://host1.com/path1\"],\n        [\"https://host1.com/path1\", \"http://host1.com/path2\"],\n    ],\n    ids=(\n        \"entirely different hosts\",\n        \"http -> https\",\n        \"https -> http\",\n    ),\n)\nasync def test_drop_auth_on_redirect_to_other_host(\n    create_server_for_url_and_handler,\n    url_from,\n    url_to,\n) -> None:\n    url_from, url_to = URL(url_from), URL(url_to)\n\n    async def srv_from(request):\n        assert request.host == url_from.host\n        assert request.headers[\"Authorization\"] == \"Basic dXNlcjpwYXNz\"\n        raise web.HTTPFound(url_to)\n\n    async def srv_to(request):\n        assert request.host == url_to.host\n        assert \"Authorization\" not in request.headers, \"Header wasn't dropped\"\n        return web.Response()\n\n    server_from = await create_server_for_url_and_handler(url_from, srv_from)\n    server_to = await create_server_for_url_and_handler(url_to, srv_to)\n\n    assert (\n        url_from.host != url_to.host or server_from.scheme != server_to.scheme\n    ), \"Invalid test case, host or scheme must differ\"\n\n    protocol_port_map = {\n        \"http\": 80,\n        \"https\": 443,\n    }\n    etc_hosts = {\n        (url_from.host, protocol_port_map[server_from.scheme]): server_from,\n        (url_to.host, protocol_port_map[server_to.scheme]): server_to,\n    }\n\n    class FakeResolver(AbstractResolver):\n        async def resolve(self, host, port=0, family=socket.AF_INET):\n            server = etc_hosts[(host, port)]\n\n            return [\n                {\n                    \"hostname\": host,\n                    \"host\": server.host,\n                    \"port\": server.port,\n                    \"family\": socket.AF_INET,\n                    \"proto\": 0,\n                    \"flags\": socket.AI_NUMERICHOST,\n                }\n            ]\n\n        async def close(self):\n            pass\n\n    connector = aiohttp.TCPConnector(resolver=FakeResolver(), ssl=False)\n\n    async with aiohttp.ClientSession(connector=connector) as client:\n        resp = await client.get(\n            url_from,\n            auth=aiohttp.BasicAuth(\"user\", \"pass\"),\n        )\n        assert resp.status == 200\n        resp = await client.get(\n            url_from,\n            headers={\"Authorization\": \"Basic dXNlcjpwYXNz\"},\n        )\n        assert resp.status == 200\n\n\nasync def test_async_with_session() -> None:\n    async with aiohttp.ClientSession() as session:\n        pass\n\n    assert session.closed\n\n\nasync def test_session_close_awaitable() -> None:\n    session = aiohttp.ClientSession()\n    await session.close()\n\n    assert session.closed\n\n\nasync def test_close_resp_on_error_async_with_session(aiohttp_server) -> None:\n    async def handler(request):\n        resp = web.StreamResponse(headers={\"content-length\": \"100\"})\n        await resp.prepare(request)\n        await asyncio.sleep(0.1)\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    server = await aiohttp_server(app)\n\n    async with aiohttp.ClientSession() as session:\n        with pytest.raises(RuntimeError):\n            async with session.get(server.make_url(\"/\")) as resp:\n                resp.content.set_exception(RuntimeError())\n                await resp.read()\n\n        assert len(session._connector._conns) == 0\n\n\nasync def test_release_resp_on_normal_exit_from_cm(aiohttp_server) -> None:\n    async def handler(request):\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    server = await aiohttp_server(app)\n\n    async with aiohttp.ClientSession() as session:\n        async with session.get(server.make_url(\"/\")) as resp:\n            await resp.read()\n\n        assert len(session._connector._conns) == 1\n\n\nasync def test_non_close_detached_session_on_error_cm(aiohttp_server) -> None:\n    async def handler(request):\n        resp = web.StreamResponse(headers={\"content-length\": \"100\"})\n        await resp.prepare(request)\n        await asyncio.sleep(0.1)\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    server = await aiohttp_server(app)\n\n    session = aiohttp.ClientSession()\n    cm = session.get(server.make_url(\"/\"))\n    assert not session.closed\n    with pytest.raises(RuntimeError):\n        async with cm as resp:\n            resp.content.set_exception(RuntimeError())\n            await resp.read()\n    assert not session.closed\n\n\nasync def test_close_detached_session_on_non_existing_addr() -> None:\n    class FakeResolver(AbstractResolver):\n        async def resolve(host, port=0, family=socket.AF_INET):\n            return {}\n\n        async def close(self):\n            pass\n\n    connector = aiohttp.TCPConnector(resolver=FakeResolver())\n\n    session = aiohttp.ClientSession(connector=connector)\n\n    async with session:\n        cm = session.get(\"http://non-existing.example.com\")\n        assert not session.closed\n        with pytest.raises(Exception):\n            await cm\n\n    assert session.closed\n\n\nasync def test_aiohttp_request_context_manager(aiohttp_server) -> None:\n    async def handler(request):\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    server = await aiohttp_server(app)\n\n    async with aiohttp.request(\"GET\", server.make_url(\"/\")) as resp:\n        await resp.read()\n        assert resp.status == 200\n\n\nasync def test_aiohttp_request_ctx_manager_close_sess_on_error(\n    ssl_ctx, aiohttp_server\n) -> None:\n    async def handler(request):\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    server = await aiohttp_server(app, ssl=ssl_ctx)\n\n    cm = aiohttp.request(\"GET\", server.make_url(\"/\"))\n\n    with pytest.raises(aiohttp.ClientConnectionError):\n        async with cm:\n            pass\n\n    assert cm._session.closed\n\n\nasync def test_aiohttp_request_ctx_manager_not_found() -> None:\n\n    with pytest.raises(aiohttp.ClientConnectionError):\n        async with aiohttp.request(\"GET\", \"http://wrong-dns-name.com\"):\n            assert False, \"never executed\"  # pragma: no cover\n\n\nasync def test_yield_from_in_session_request(aiohttp_client) -> None:\n    # a test for backward compatibility with yield from syntax\n    async def handler(request):\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n\n    client = await aiohttp_client(app)\n    async with client.get(\"/\") as resp:\n        assert resp.status == 200\n\n\nasync def test_close_context_manager(aiohttp_client) -> None:\n    # a test for backward compatibility with yield from syntax\n    async def handler(request):\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n\n    client = await aiohttp_client(app)\n    ctx = client.get(\"/\")\n    ctx.close()\n    assert not ctx._coro.cr_running\n\n\nasync def test_session_auth(aiohttp_client) -> None:\n    async def handler(request):\n        return web.json_response({\"headers\": dict(request.headers)})\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n\n    client = await aiohttp_client(app, auth=aiohttp.BasicAuth(\"login\", \"pass\"))\n\n    r = await client.get(\"/\")\n    assert r.status == 200\n    content = await r.json()\n    assert content[\"headers\"][\"Authorization\"] == \"Basic bG9naW46cGFzcw==\"\n\n\nasync def test_session_auth_override(aiohttp_client) -> None:\n    async def handler(request):\n        return web.json_response({\"headers\": dict(request.headers)})\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n\n    client = await aiohttp_client(app, auth=aiohttp.BasicAuth(\"login\", \"pass\"))\n\n    r = await client.get(\"/\", auth=aiohttp.BasicAuth(\"other_login\", \"pass\"))\n    assert r.status == 200\n    content = await r.json()\n    val = content[\"headers\"][\"Authorization\"]\n    assert val == \"Basic b3RoZXJfbG9naW46cGFzcw==\"\n\n\nasync def test_session_auth_header_conflict(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n\n    client = await aiohttp_client(app, auth=aiohttp.BasicAuth(\"login\", \"pass\"))\n    headers = {\"Authorization\": \"Basic b3RoZXJfbG9naW46cGFzcw==\"}\n    with pytest.raises(ValueError):\n        await client.get(\"/\", headers=headers)\n\n\nasync def test_session_headers(aiohttp_client) -> None:\n    async def handler(request):\n        return web.json_response({\"headers\": dict(request.headers)})\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n\n    client = await aiohttp_client(app, headers={\"X-Real-IP\": \"192.168.0.1\"})\n\n    r = await client.get(\"/\")\n    assert r.status == 200\n    content = await r.json()\n    assert content[\"headers\"][\"X-Real-IP\"] == \"192.168.0.1\"\n\n\nasync def test_session_headers_merge(aiohttp_client) -> None:\n    async def handler(request):\n        return web.json_response({\"headers\": dict(request.headers)})\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n\n    client = await aiohttp_client(\n        app, headers=[(\"X-Real-IP\", \"192.168.0.1\"), (\"X-Sent-By\", \"requests\")]\n    )\n\n    r = await client.get(\"/\", headers={\"X-Sent-By\": \"aiohttp\"})\n    assert r.status == 200\n    content = await r.json()\n    assert content[\"headers\"][\"X-Real-IP\"] == \"192.168.0.1\"\n    assert content[\"headers\"][\"X-Sent-By\"] == \"aiohttp\"\n\n\nasync def test_multidict_headers(aiohttp_client) -> None:\n    async def handler(request):\n        assert await request.read() == data\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n\n    client = await aiohttp_client(app)\n\n    data = b\"sample data\"\n\n    async with client.post(\n        \"/\", data=data, headers=MultiDict({\"Content-Length\": str(len(data))})\n    ) as r:\n        assert r.status == 200\n\n\nasync def test_request_conn_closed(aiohttp_client) -> None:\n    async def handler(request):\n        request.transport.close()\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n\n    client = await aiohttp_client(app)\n    with pytest.raises(aiohttp.ServerDisconnectedError) as excinfo:\n        resp = await client.get(\"/\")\n        await resp.read()\n\n    assert str(excinfo.value) != \"\"\n\n\nasync def test_dont_close_explicit_connector(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n\n    client = await aiohttp_client(app)\n    r = await client.get(\"/\")\n    await r.read()\n\n    assert 1 == len(client.session.connector._conns)\n\n\nasync def test_server_close_keepalive_connection() -> None:\n    loop = asyncio.get_event_loop()\n\n    class Proto(asyncio.Protocol):\n        def connection_made(self, transport):\n            self.transp = transport\n            self.data = b\"\"\n\n        def data_received(self, data):\n            self.data += data\n            if data.endswith(b\"\\r\\n\\r\\n\"):\n                self.transp.write(\n                    b\"HTTP/1.1 200 OK\\r\\n\"\n                    b\"CONTENT-LENGTH: 2\\r\\n\"\n                    b\"CONNECTION: close\\r\\n\"\n                    b\"\\r\\n\"\n                    b\"ok\"\n                )\n                self.transp.close()\n\n        def connection_lost(self, exc):\n            self.transp = None\n\n    server = await loop.create_server(Proto, \"127.0.0.1\", unused_port())\n\n    addr = server.sockets[0].getsockname()\n\n    connector = aiohttp.TCPConnector(limit=1)\n    session = aiohttp.ClientSession(connector=connector)\n\n    url = \"http://{}:{}/\".format(*addr)\n    for i in range(2):\n        r = await session.request(\"GET\", url)\n        await r.read()\n        assert 0 == len(connector._conns)\n    await session.close()\n    await connector.close()\n    server.close()\n    await server.wait_closed()\n\n\nasync def test_handle_keepalive_on_closed_connection() -> None:\n    loop = asyncio.get_event_loop()\n\n    class Proto(asyncio.Protocol):\n        def connection_made(self, transport):\n            self.transp = transport\n            self.data = b\"\"\n\n        def data_received(self, data):\n            self.data += data\n            if data.endswith(b\"\\r\\n\\r\\n\"):\n                self.transp.write(\n                    b\"HTTP/1.1 200 OK\\r\\n\" b\"CONTENT-LENGTH: 2\\r\\n\" b\"\\r\\n\" b\"ok\"\n                )\n                self.transp.close()\n\n        def connection_lost(self, exc):\n            self.transp = None\n\n    server = await loop.create_server(Proto, \"127.0.0.1\", unused_port())\n\n    addr = server.sockets[0].getsockname()\n\n    async with aiohttp.TCPConnector(limit=1) as connector:\n        async with aiohttp.ClientSession(connector=connector) as session:\n            url = \"http://{}:{}/\".format(*addr)\n\n            r = await session.request(\"GET\", url)\n            await r.read()\n            assert 1 == len(connector._conns)\n            closed_conn = next(iter(connector._conns.values()))\n\n            await session.request(\"GET\", url)\n            assert 1 == len(connector._conns)\n            new_conn = next(iter(connector._conns.values()))\n            assert closed_conn is not new_conn\n\n    server.close()\n    await server.wait_closed()\n\n\nasync def test_error_in_performing_request(ssl_ctx, aiohttp_client, aiohttp_server):\n    async def handler(request):\n        return web.Response()\n\n    def exception_handler(loop, context):\n        # skip log messages about destroyed but pending tasks\n        pass\n\n    loop = asyncio.get_event_loop()\n    loop.set_exception_handler(exception_handler)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    server = await aiohttp_server(app, ssl=ssl_ctx)\n\n    conn = aiohttp.TCPConnector(limit=1)\n    client = await aiohttp_client(server, connector=conn)\n\n    with pytest.raises(aiohttp.ClientConnectionError):\n        await client.get(\"/\")\n\n    # second try should not hang\n    with pytest.raises(aiohttp.ClientConnectionError):\n        await client.get(\"/\")\n\n\nasync def test_await_after_cancelling(aiohttp_client) -> None:\n    loop = asyncio.get_event_loop()\n\n    async def handler(request):\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    client = await aiohttp_client(app)\n\n    fut1 = loop.create_future()\n    fut2 = loop.create_future()\n\n    async def fetch1():\n        resp = await client.get(\"/\")\n        assert resp.status == 200\n        fut1.set_result(None)\n        with pytest.raises(asyncio.CancelledError):\n            await fut2\n        resp.release()\n\n    async def fetch2():\n        await fut1\n        resp = await client.get(\"/\")\n        assert resp.status == 200\n\n    async def canceller():\n        await fut1\n        fut2.cancel()\n\n    await asyncio.gather(fetch1(), fetch2(), canceller())\n\n\nasync def test_async_payload_generator(aiohttp_client) -> None:\n    async def handler(request):\n        data = await request.read()\n        assert data == b\"1234567890\" * 100\n        return web.Response()\n\n    app = web.Application()\n    app.add_routes([web.post(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n\n    async def gen():\n        for i in range(100):\n            yield b\"1234567890\"\n\n    async with client.post(\"/\", data=gen()) as resp:\n        assert resp.status == 200\n\n\nasync def test_read_from_closed_response(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(body=b\"data\")\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/\") as resp:\n        assert resp.status == 200\n\n    with pytest.raises(aiohttp.ClientConnectionError):\n        await resp.read()\n\n\nasync def test_read_from_closed_response2(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(body=b\"data\")\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/\") as resp:\n        assert resp.status == 200\n        await resp.read()\n\n    with pytest.raises(aiohttp.ClientConnectionError):\n        await resp.read()\n\n\nasync def test_read_from_closed_content(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(body=b\"data\")\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/\") as resp:\n        assert resp.status == 200\n\n    with pytest.raises(aiohttp.ClientConnectionError):\n        await resp.content.readline()\n\n\nasync def test_read_timeout(aiohttp_client) -> None:\n    async def handler(request):\n        await asyncio.sleep(5)\n        return web.Response()\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    timeout = aiohttp.ClientTimeout(sock_read=0.1)\n    client = await aiohttp_client(app, timeout=timeout)\n\n    with pytest.raises(aiohttp.ServerTimeoutError):\n        await client.get(\"/\")\n\n\nasync def test_socket_timeout(aiohttp_client: Any) -> None:\n    async def handler(request):\n        await asyncio.sleep(5)\n        return web.Response()\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    timeout = aiohttp.ClientTimeout(sock_read=0.1)\n    client = await aiohttp_client(app, timeout=timeout)\n\n    with pytest.raises(SocketTimeoutError):\n        await client.get(\"/\")\n\n\nasync def test_read_timeout_closes_connection(aiohttp_client: AiohttpClient) -> None:\n    request_count = 0\n\n    async def handler(request):\n        nonlocal request_count\n        request_count += 1\n        if request_count < 3:\n            await asyncio.sleep(0.5)\n        return web.Response(body=f\"request:{request_count}\")\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    timeout = aiohttp.ClientTimeout(total=0.1)\n    client: TestClient = await aiohttp_client(app, timeout=timeout)\n    with pytest.raises(asyncio.TimeoutError):\n        await client.get(\"/\")\n\n    # Make sure its really closed\n    assert not client.session.connector._conns\n\n    with pytest.raises(asyncio.TimeoutError):\n        await client.get(\"/\")\n\n    # Make sure its really closed\n    assert not client.session.connector._conns\n    result = await client.get(\"/\")\n    assert await result.read() == b\"request:3\"\n\n    # Make sure its not closed\n    assert client.session.connector._conns\n\n\nasync def test_read_timeout_on_prepared_response(aiohttp_client: Any) -> None:\n    async def handler(request):\n        resp = aiohttp.web.StreamResponse()\n        await resp.prepare(request)\n        await asyncio.sleep(5)\n        await resp.drain()\n        return resp\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    timeout = aiohttp.ClientTimeout(sock_read=0.1)\n    client = await aiohttp_client(app, timeout=timeout)\n\n    with pytest.raises(aiohttp.ServerTimeoutError):\n        async with await client.get(\"/\") as resp:\n            await resp.read()\n\n\nasync def test_timeout_with_full_buffer(aiohttp_client) -> None:\n    async def handler(request):\n        \"\"\"Server response that never ends and always has more data available.\"\"\"\n        resp = web.StreamResponse()\n        await resp.prepare(request)\n        while True:\n            await resp.write(b\"1\" * 1000)\n            await asyncio.sleep(0.01)\n\n    async def request(client):\n        timeout = aiohttp.ClientTimeout(total=0.5)\n        async with await client.get(\"/\", timeout=timeout) as resp:\n            with pytest.raises(asyncio.TimeoutError):\n                async for data in resp.content.iter_chunked(1):\n                    await asyncio.sleep(0.01)\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n    # wait_for() used just to ensure that a failing test doesn't hang.\n    await asyncio.wait_for(request(client), 1)\n\n\nasync def test_read_bufsize_session_default(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(body=b\"1234567\")\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app, read_bufsize=2)\n\n    async with await client.get(\"/\") as resp:\n        assert resp.content.get_read_buffer_limits() == (2, 4)\n\n\nasync def test_read_bufsize_explicit(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(body=b\"1234567\")\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n\n    async with await client.get(\"/\", read_bufsize=4) as resp:\n        assert resp.content.get_read_buffer_limits() == (4, 8)\n\n\nasync def test_http_empty_data_text(aiohttp_client) -> None:\n    async def handler(request):\n        data = await request.read()\n        ret = \"ok\" if data == b\"\" else \"fail\"\n        resp = web.Response(text=ret)\n        resp.headers[\"Content-Type\"] = request.headers[\"Content-Type\"]\n        return resp\n\n    app = web.Application()\n    app.add_routes([web.post(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n\n    async with await client.post(\"/\", data=\"\") as resp:\n        assert resp.status == 200\n        assert await resp.text() == \"ok\"\n        assert resp.headers[\"Content-Type\"] == \"text/plain; charset=utf-8\"\n\n\nasync def test_max_field_size_session_default(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(headers={\"Custom\": \"x\" * 8190})\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n\n    async with await client.get(\"/\") as resp:\n        assert resp.headers[\"Custom\"] == \"x\" * 8190\n\n\nasync def test_max_field_size_session_default_fail(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(headers={\"Custom\": \"x\" * 8191})\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n    with pytest.raises(aiohttp.ClientResponseError):\n        await client.get(\"/\")\n\n\nasync def test_max_field_size_session_explicit(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(headers={\"Custom\": \"x\" * 8191})\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app, max_field_size=8191)\n\n    async with await client.get(\"/\") as resp:\n        assert resp.headers[\"Custom\"] == \"x\" * 8191\n\n\nasync def test_max_field_size_request_explicit(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(headers={\"Custom\": \"x\" * 8191})\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n\n    async with await client.get(\"/\", max_field_size=8191) as resp:\n        assert resp.headers[\"Custom\"] == \"x\" * 8191\n\n\nasync def test_max_line_size_session_default(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(status=200, reason=\"x\" * 8190)\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n\n    async with await client.get(\"/\") as resp:\n        assert resp.reason == \"x\" * 8190\n\n\nasync def test_max_line_size_session_default_fail(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(status=200, reason=\"x\" * 8192)\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n    with pytest.raises(aiohttp.ClientResponseError):\n        await client.get(\"/\")\n\n\nasync def test_max_line_size_session_explicit(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(status=200, reason=\"x\" * 8191)\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app, max_line_size=8191)\n\n    async with await client.get(\"/\") as resp:\n        assert resp.reason == \"x\" * 8191\n\n\nasync def test_max_line_size_request_explicit(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(status=200, reason=\"x\" * 8191)\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n\n    async with await client.get(\"/\", max_line_size=8191) as resp:\n        assert resp.reason == \"x\" * 8191\n\n\nasync def test_rejected_upload(\n    aiohttp_client: AiohttpClient, tmp_path: pathlib.Path\n) -> None:\n    async def ok_handler(request: web.Request) -> web.Response:\n        return web.Response()\n\n    async def not_ok_handler(request):\n        raise web.HTTPBadRequest()\n\n    app = web.Application()\n    app.router.add_get(\"/ok\", ok_handler)\n    app.router.add_post(\"/not_ok\", not_ok_handler)\n    client = await aiohttp_client(app)\n\n    file_size_bytes = 1024 * 1024\n    file_path = tmp_path / \"uploaded.txt\"\n    file_path.write_text(\"0\" * file_size_bytes, encoding=\"utf8\")\n\n    with open(file_path, \"rb\") as file:\n        data = {\"file\": file}\n        async with client.post(\"/not_ok\", data=data) as resp_not_ok:\n            assert resp_not_ok.status == 400\n\n    async with client.get(\"/ok\", timeout=aiohttp.ClientTimeout(total=1)) as resp_ok:\n        assert resp_ok.status == 200\n\n\n@pytest.mark.parametrize(\n    (\"value\", \"exc_type\"),\n    [(42, TypeError), (\"InvalidUrl\", InvalidURL)],\n)\nasync def test_request_with_wrong_proxy(\n    aiohttp_client: AiohttpClient, value: Any, exc_type: Type[Exception]\n) -> None:\n    app = web.Application()\n    session = await aiohttp_client(app)\n\n    with pytest.raises(exc_type):\n        await session.get(\"/\", proxy=value)  # type: ignore[arg-type]\n\n\nasync def test_raise_for_status_is_none(aiohttp_client: AiohttpClient) -> None:\n    async def handler(_: web.Request) -> web.Response:\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    session = await aiohttp_client(app, raise_for_status=None)  # type: ignore[arg-type]\n\n    await session.get(\"/\")\n\n\nasync def test_exception_when_read_outside_of_session(\n    aiohttp_server: AiohttpServer,\n) -> None:\n    async def handler(request: web.Request) -> web.Response:\n        return web.Response(body=b\"1\" * 1000000)\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n\n    server = await aiohttp_server(app)\n    async with aiohttp.ClientSession() as sess:\n        resp = await sess.get(server.make_url(\"/\"))\n\n    with pytest.raises(RuntimeError, match=\"Connection closed\"):\n        await resp.read()\n",
            "header": {
                "file": {
                    "path": "tests/test_client_functional.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "1f9173bd",
                "new_commit_hash": "7de19526",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/tests/test_client_functional.py"
            },
            "plus_file": {
                "path": "b/tests/test_client_functional.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 341,
                            "length": 10
                        },
                        "new_range": {
                            "start": 341,
                            "length": 11
                        },
                        "section": "async def test_stream_request_on_server_eof(aiohttp_client) -> None:"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "    async with client.get(\"/\") as resp:",
                                "type": "context"
                            },
                            {
                                "content": "        assert 200 == resp.status",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    # Connection should have been reused",
                                "type": "deleted"
                            },
                            {
                                "content": "    # First connection should have been closed, otherwise server won't know if it",
                                "type": "added"
                            },
                            {
                                "content": "    # received the full message.",
                                "type": "added"
                            },
                            {
                                "content": "    conns = next(iter(client.session.connector._conns.values()))",
                                "type": "context"
                            },
                            {
                                "content": "    assert len(conns) == 1",
                                "type": "context"
                            },
                            {
                                "content": "    assert conns[0][0] is conn",
                                "type": "deleted"
                            },
                            {
                                "content": "    assert conns[0][0] is not conn",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "async def test_stream_request_on_server_eof_nested(aiohttp_client) -> None:",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "tests/test_client_functional.py",
                            "type": "function",
                            "name": "test_stream_request_on_server_eof",
                            "content": "async def test_stream_request_on_server_eof(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=\"OK\", status=200)\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n    app.add_routes([web.put(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n\n    async def data_gen():\n        for _ in range(2):\n            yield b\"just data\"\n            await asyncio.sleep(0.1)\n\n    async with client.put(\"/\", data=data_gen()) as resp:\n        assert 200 == resp.status\n        assert len(client.session.connector._acquired) == 1\n        conn = next(iter(client.session.connector._acquired))\n\n    async with client.get(\"/\") as resp:\n        assert 200 == resp.status\n\n    # Connection should have been reused\n    conns = next(iter(client.session.connector._conns.values()))\n    assert len(conns) == 1\n    assert conns[0][0] is conn",
                            "ast_type_str": "AsyncFunctionDef",
                            "start_lineno": 321,
                            "end_lineno": 347,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 362,
                            "length": 14
                        },
                        "new_range": {
                            "start": 363,
                            "length": 21
                        },
                        "section": "async def test_stream_request_on_server_eof_nested(aiohttp_client) -> None:"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "            yield b\"just data\"",
                                "type": "context"
                            },
                            {
                                "content": "            await asyncio.sleep(0.1)",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    assert client.session.connector is not None",
                                "type": "added"
                            },
                            {
                                "content": "    async with client.put(\"/\", data=data_gen()) as resp:",
                                "type": "context"
                            },
                            {
                                "content": "        first_conn = next(iter(client.session.connector._acquired))",
                                "type": "added"
                            },
                            {
                                "content": "        assert 200 == resp.status",
                                "type": "context"
                            },
                            {
                                "content": "        async with client.get(\"/\") as resp:",
                                "type": "deleted"
                            },
                            {
                                "content": "            assert 200 == resp.status",
                                "type": "deleted"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "        async with client.get(\"/\") as resp2:",
                                "type": "added"
                            },
                            {
                                "content": "            assert 200 == resp2.status",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    # Should be 2 separate connections",
                                "type": "context"
                            },
                            {
                                "content": "    conns = next(iter(client.session.connector._conns.values()))",
                                "type": "context"
                            },
                            {
                                "content": "    assert len(conns) == 2",
                                "type": "deleted"
                            },
                            {
                                "content": "    assert len(conns) == 1",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "    assert first_conn is not None",
                                "type": "added"
                            },
                            {
                                "content": "    assert not first_conn.is_connected()",
                                "type": "added"
                            },
                            {
                                "content": "    assert first_conn is not conns[0][0]",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "async def test_HTTP_304_WITH_BODY(aiohttp_client) -> None:",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "tests/test_client_functional.py",
                            "type": "function",
                            "name": "test_stream_request_on_server_eof_nested",
                            "content": "async def test_stream_request_on_server_eof_nested(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=\"OK\", status=200)\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n    app.add_routes([web.put(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n\n    async def data_gen():\n        for _ in range(2):\n            yield b\"just data\"\n            await asyncio.sleep(0.1)\n\n    async with client.put(\"/\", data=data_gen()) as resp:\n        assert 200 == resp.status\n        async with client.get(\"/\") as resp:\n            assert 200 == resp.status\n\n    # Should be 2 separate connections\n    conns = next(iter(client.session.connector._conns.values()))\n    assert len(conns) == 2",
                            "ast_type_str": "AsyncFunctionDef",
                            "start_lineno": 350,
                            "end_lineno": 372,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 3651,
                            "length": 9
                        },
                        "new_range": {
                            "start": 3659,
                            "length": 10
                        },
                        "section": "async def test_max_line_size_request_explicit(aiohttp_client) -> None:"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        assert resp.reason == \"x\" * 8191",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "@pytest.mark.xfail(raises=asyncio.TimeoutError, reason=\"#7599\")",
                                "type": "deleted"
                            },
                            {
                                "content": "async def test_rejected_upload(aiohttp_client, tmp_path) -> None:",
                                "type": "deleted"
                            },
                            {
                                "content": "    async def ok_handler(request):",
                                "type": "deleted"
                            },
                            {
                                "content": "async def test_rejected_upload(",
                                "type": "added"
                            },
                            {
                                "content": "    aiohttp_client: AiohttpClient, tmp_path: pathlib.Path",
                                "type": "added"
                            },
                            {
                                "content": ") -> None:",
                                "type": "added"
                            },
                            {
                                "content": "    async def ok_handler(request: web.Request) -> web.Response:",
                                "type": "added"
                            },
                            {
                                "content": "        return web.Response()",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    async def not_ok_handler(request):",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "tests/test_client_functional.py",
                            "type": "function",
                            "name": "test_rejected_upload",
                            "content": "async def test_rejected_upload(aiohttp_client, tmp_path) -> None:\n    async def ok_handler(request):\n        return web.Response()\n\n    async def not_ok_handler(request):\n        raise web.HTTPBadRequest()\n\n    app = web.Application()\n    app.router.add_get(\"/ok\", ok_handler)\n    app.router.add_post(\"/not_ok\", not_ok_handler)\n    client = await aiohttp_client(app)\n\n    file_size_bytes = 1024 * 1024\n    file_path = tmp_path / \"uploaded.txt\"\n    file_path.write_text(\"0\" * file_size_bytes, encoding=\"utf8\")\n\n    with open(file_path, \"rb\") as file:\n        data = {\"file\": file}\n        async with await client.post(\"/not_ok\", data=data) as resp_not_ok:\n            assert 400 == resp_not_ok.status\n\n    async with await client.get(\n        \"/ok\", timeout=aiohttp.ClientTimeout(total=0.01)\n    ) as resp_ok:\n        assert 200 == resp_ok.status",
                            "ast_type_str": "AsyncFunctionDef",
                            "start_lineno": 3655,
                            "end_lineno": 3679,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 3670,
                            "length": 13
                        },
                        "new_range": {
                            "start": 3679,
                            "length": 11
                        },
                        "section": "async def test_rejected_upload(aiohttp_client, tmp_path) -> None:"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    with open(file_path, \"rb\") as file:",
                                "type": "context"
                            },
                            {
                                "content": "        data = {\"file\": file}",
                                "type": "context"
                            },
                            {
                                "content": "        async with await client.post(\"/not_ok\", data=data) as resp_not_ok:",
                                "type": "deleted"
                            },
                            {
                                "content": "            assert 400 == resp_not_ok.status",
                                "type": "deleted"
                            },
                            {
                                "content": "        async with client.post(\"/not_ok\", data=data) as resp_not_ok:",
                                "type": "added"
                            },
                            {
                                "content": "            assert resp_not_ok.status == 400",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    async with await client.get(",
                                "type": "deleted"
                            },
                            {
                                "content": "        \"/ok\", timeout=aiohttp.ClientTimeout(total=0.01)",
                                "type": "deleted"
                            },
                            {
                                "content": "    ) as resp_ok:",
                                "type": "deleted"
                            },
                            {
                                "content": "        assert 200 == resp_ok.status",
                                "type": "deleted"
                            },
                            {
                                "content": "    async with client.get(\"/ok\", timeout=aiohttp.ClientTimeout(total=1)) as resp_ok:",
                                "type": "added"
                            },
                            {
                                "content": "        assert resp_ok.status == 200",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "@pytest.mark.parametrize(",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "tests/test_client_functional.py",
                            "type": "function",
                            "name": "test_rejected_upload",
                            "content": "async def test_rejected_upload(aiohttp_client, tmp_path) -> None:\n    async def ok_handler(request):\n        return web.Response()\n\n    async def not_ok_handler(request):\n        raise web.HTTPBadRequest()\n\n    app = web.Application()\n    app.router.add_get(\"/ok\", ok_handler)\n    app.router.add_post(\"/not_ok\", not_ok_handler)\n    client = await aiohttp_client(app)\n\n    file_size_bytes = 1024 * 1024\n    file_path = tmp_path / \"uploaded.txt\"\n    file_path.write_text(\"0\" * file_size_bytes, encoding=\"utf8\")\n\n    with open(file_path, \"rb\") as file:\n        data = {\"file\": file}\n        async with await client.post(\"/not_ok\", data=data) as resp_not_ok:\n            assert 400 == resp_not_ok.status\n\n    async with await client.get(\n        \"/ok\", timeout=aiohttp.ClientTimeout(total=0.01)\n    ) as resp_ok:\n        assert 200 == resp_ok.status",
                            "ast_type_str": "AsyncFunctionDef",
                            "start_lineno": 3655,
                            "end_lineno": 3679,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        }
    ],
    "old_commit_hash": "fecb85a9291d4cae6c06999c388421cde02c9860^",
    "new_commit_hash": "fecb85a9291d4cae6c06999c388421cde02c9860",
    "commit_message": "Fix cancelled payload send leading to hung connection (#8992) (#9003)\n\n(cherry picked from commit 5c0b8e4a7897f48063f684ac16e7dd18f6218274)",
    "commit_date": "2024-09-03T14:06:55+01:00",
    "metadata": {}
}
{
    "repo_name": "aiohttp",
    "new_commit_hash": "fecb85a9291d4cae6c06999c388421cde02c9860",
    "test_file_codes": [
        "# HTTP client functional tests against aiohttp.web server\n\nimport asyncio\nimport datetime\nimport http.cookies\nimport io\nimport json\nimport pathlib\nimport socket\nimport ssl\nimport sys\nimport tarfile\nimport time\nimport zipfile\nfrom typing import Any, AsyncIterator, Type\nfrom unittest import mock\n\nimport pytest\nfrom multidict import MultiDict\nfrom yarl import URL\n\nimport aiohttp\nfrom aiohttp import Fingerprint, ServerFingerprintMismatch, hdrs, web\nfrom aiohttp.abc import AbstractResolver\nfrom aiohttp.client_exceptions import (\n    InvalidURL,\n    InvalidUrlClientError,\n    InvalidUrlRedirectClientError,\n    NonHttpUrlClientError,\n    NonHttpUrlRedirectClientError,\n    SocketTimeoutError,\n    TooManyRedirects,\n)\nfrom aiohttp.pytest_plugin import AiohttpClient, AiohttpServer, TestClient\nfrom aiohttp.test_utils import unused_port\n\n\n@pytest.fixture\ndef here():\n    return pathlib.Path(__file__).parent\n\n\n@pytest.fixture\ndef fname(here):\n    return here / \"conftest.py\"\n\n\nasync def test_keepalive_two_requests_success(aiohttp_client) -> None:\n    async def handler(request):\n        body = await request.read()\n        assert b\"\" == body\n        return web.Response(body=b\"OK\")\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    connector = aiohttp.TCPConnector(limit=1)\n    client = await aiohttp_client(app, connector=connector)\n\n    resp1 = await client.get(\"/\")\n    await resp1.read()\n    resp2 = await client.get(\"/\")\n    await resp2.read()\n\n    assert 1 == len(client._session.connector._conns)\n\n\nasync def test_keepalive_after_head_requests_success(aiohttp_client) -> None:\n    async def handler(request):\n        body = await request.read()\n        assert b\"\" == body\n        return web.Response(body=b\"OK\")\n\n    cnt_conn_reuse = 0\n\n    async def on_reuseconn(session, ctx, params):\n        nonlocal cnt_conn_reuse\n        cnt_conn_reuse += 1\n\n    trace_config = aiohttp.TraceConfig()\n    trace_config._on_connection_reuseconn.append(on_reuseconn)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    app.router.add_route(\"HEAD\", \"/\", handler)\n\n    connector = aiohttp.TCPConnector(limit=1)\n    client = await aiohttp_client(\n        app, connector=connector, trace_configs=[trace_config]\n    )\n\n    resp1 = await client.head(\"/\")\n    await resp1.read()\n    resp2 = await client.get(\"/\")\n    await resp2.read()\n\n    assert 1 == cnt_conn_reuse\n\n\n@pytest.mark.parametrize(\"status\", (101, 204, 304))\nasync def test_keepalive_after_empty_body_status(\n    aiohttp_client: Any, status: int\n) -> None:\n    async def handler(request):\n        body = await request.read()\n        assert b\"\" == body\n        return web.Response(status=status)\n\n    cnt_conn_reuse = 0\n\n    async def on_reuseconn(session, ctx, params):\n        nonlocal cnt_conn_reuse\n        cnt_conn_reuse += 1\n\n    trace_config = aiohttp.TraceConfig()\n    trace_config._on_connection_reuseconn.append(on_reuseconn)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    connector = aiohttp.TCPConnector(limit=1)\n    client = await aiohttp_client(\n        app, connector=connector, trace_configs=[trace_config]\n    )\n\n    resp1 = await client.get(\"/\")\n    await resp1.read()\n    resp2 = await client.get(\"/\")\n    await resp2.read()\n\n    assert cnt_conn_reuse == 1\n\n\n@pytest.mark.parametrize(\"status\", (101, 204, 304))\nasync def test_keepalive_after_empty_body_status_stream_response(\n    aiohttp_client: Any, status: int\n) -> None:\n    async def handler(request):\n        stream_response = web.StreamResponse(status=status)\n        await stream_response.prepare(request)\n        return stream_response\n\n    cnt_conn_reuse = 0\n\n    async def on_reuseconn(session, ctx, params):\n        nonlocal cnt_conn_reuse\n        cnt_conn_reuse += 1\n\n    trace_config = aiohttp.TraceConfig()\n    trace_config._on_connection_reuseconn.append(on_reuseconn)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    connector = aiohttp.TCPConnector(limit=1)\n    client = await aiohttp_client(\n        app, connector=connector, trace_configs=[trace_config]\n    )\n\n    resp1 = await client.get(\"/\")\n    await resp1.read()\n    resp2 = await client.get(\"/\")\n    await resp2.read()\n\n    assert cnt_conn_reuse == 1\n\n\nasync def test_keepalive_response_released(aiohttp_client: Any) -> None:\n    async def handler(request):\n        body = await request.read()\n        assert b\"\" == body\n        return web.Response(body=b\"OK\")\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    connector = aiohttp.TCPConnector(limit=1)\n    client = await aiohttp_client(app, connector=connector)\n\n    resp1 = await client.get(\"/\")\n    resp1.release()\n    resp2 = await client.get(\"/\")\n    resp2.release()\n\n    assert 1 == len(client._session.connector._conns)\n\n\nasync def test_upgrade_connection_not_released_after_read(aiohttp_client) -> None:\n    async def handler(request: web.Request) -> web.Response:\n        body = await request.read()\n        assert b\"\" == body\n        return web.Response(\n            status=101, headers={\"Connection\": \"Upgrade\", \"Upgrade\": \"tcp\"}\n        )\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    await resp.read()\n    assert resp.connection is not None\n    assert not resp.closed\n\n\nasync def test_keepalive_server_force_close_connection(aiohttp_client) -> None:\n    async def handler(request):\n        body = await request.read()\n        assert b\"\" == body\n        response = web.Response(body=b\"OK\")\n        response.force_close()\n        return response\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    connector = aiohttp.TCPConnector(limit=1)\n    client = await aiohttp_client(app, connector=connector)\n\n    resp1 = await client.get(\"/\")\n    resp1.close()\n    resp2 = await client.get(\"/\")\n    resp2.close()\n\n    assert 0 == len(client._session.connector._conns)\n\n\nasync def test_keepalive_timeout_async_sleep() -> None:\n    async def handler(request):\n        body = await request.read()\n        assert b\"\" == body\n        return web.Response(body=b\"OK\")\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    runner = web.AppRunner(app, tcp_keepalive=True, keepalive_timeout=0.001)\n    await runner.setup()\n\n    port = unused_port()\n    site = web.TCPSite(runner, host=\"localhost\", port=port)\n    await site.start()\n\n    try:\n        async with aiohttp.client.ClientSession() as sess:\n            resp1 = await sess.get(f\"http://localhost:{port}/\")\n            await resp1.read()\n            # wait for server keepalive_timeout\n            await asyncio.sleep(0.01)\n            resp2 = await sess.get(f\"http://localhost:{port}/\")\n            await resp2.read()\n    finally:\n        await asyncio.gather(runner.shutdown(), site.stop())\n\n\n@pytest.mark.skipif(\n    sys.version_info[:2] == (3, 11),\n    reason=\"https://github.com/pytest-dev/pytest/issues/10763\",\n)\nasync def test_keepalive_timeout_sync_sleep() -> None:\n    async def handler(request):\n        body = await request.read()\n        assert b\"\" == body\n        return web.Response(body=b\"OK\")\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    runner = web.AppRunner(app, tcp_keepalive=True, keepalive_timeout=0.001)\n    await runner.setup()\n\n    port = unused_port()\n    site = web.TCPSite(runner, host=\"localhost\", port=port)\n    await site.start()\n\n    try:\n        async with aiohttp.client.ClientSession() as sess:\n            resp1 = await sess.get(f\"http://localhost:{port}/\")\n            await resp1.read()\n            # wait for server keepalive_timeout\n            # time.sleep is a more challenging scenario than asyncio.sleep\n            time.sleep(0.01)\n            resp2 = await sess.get(f\"http://localhost:{port}/\")\n            await resp2.read()\n    finally:\n        await asyncio.gather(runner.shutdown(), site.stop())\n\n\nasync def test_release_early(aiohttp_client) -> None:\n    async def handler(request):\n        await request.read()\n        return web.Response(body=b\"OK\")\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    client = await aiohttp_client(app)\n    resp = await client.get(\"/\")\n    assert resp.closed\n    await resp.wait_for_close()\n    assert 1 == len(client._session.connector._conns)\n\n\nasync def test_HTTP_304(aiohttp_client) -> None:\n    async def handler(request):\n        body = await request.read()\n        assert b\"\" == body\n        return web.Response(status=304)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert resp.status == 304\n    content = await resp.read()\n    assert content == b\"\"\n\n\nasync def test_stream_request_on_server_eof(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=\"OK\", status=200)\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n    app.add_routes([web.put(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n\n    async def data_gen():\n        for _ in range(2):\n            yield b\"just data\"\n            await asyncio.sleep(0.1)\n\n    async with client.put(\"/\", data=data_gen()) as resp:\n        assert 200 == resp.status\n        assert len(client.session.connector._acquired) == 1\n        conn = next(iter(client.session.connector._acquired))\n\n    async with client.get(\"/\") as resp:\n        assert 200 == resp.status\n\n    # First connection should have been closed, otherwise server won't know if it\n    # received the full message.\n    conns = next(iter(client.session.connector._conns.values()))\n    assert len(conns) == 1\n    assert conns[0][0] is not conn\n\n\nasync def test_stream_request_on_server_eof_nested(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=\"OK\", status=200)\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n    app.add_routes([web.put(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n\n    async def data_gen():\n        for _ in range(2):\n            yield b\"just data\"\n            await asyncio.sleep(0.1)\n\n    assert client.session.connector is not None\n    async with client.put(\"/\", data=data_gen()) as resp:\n        first_conn = next(iter(client.session.connector._acquired))\n        assert 200 == resp.status\n\n        async with client.get(\"/\") as resp2:\n            assert 200 == resp2.status\n\n    # Should be 2 separate connections\n    conns = next(iter(client.session.connector._conns.values()))\n    assert len(conns) == 1\n\n    assert first_conn is not None\n    assert not first_conn.is_connected()\n    assert first_conn is not conns[0][0]\n\n\nasync def test_HTTP_304_WITH_BODY(aiohttp_client) -> None:\n    async def handler(request):\n        body = await request.read()\n        assert b\"\" == body\n        return web.Response(body=b\"test\", status=304)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert resp.status == 304\n    content = await resp.read()\n    assert content == b\"\"\n\n\nasync def test_auto_header_user_agent(aiohttp_client) -> None:\n    async def handler(request):\n        assert \"aiohttp\" in request.headers[\"user-agent\"]\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/\") as resp:\n        assert 200 == resp.status\n\n\nasync def test_skip_auto_headers_user_agent(aiohttp_client) -> None:\n    async def handler(request):\n        assert hdrs.USER_AGENT not in request.headers\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/\", skip_auto_headers=[\"user-agent\"]) as resp:\n        assert 200 == resp.status\n\n\nasync def test_skip_default_auto_headers_user_agent(aiohttp_client) -> None:\n    async def handler(request):\n        assert hdrs.USER_AGENT not in request.headers\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app, skip_auto_headers=[\"user-agent\"])\n\n    async with client.get(\"/\") as resp:\n        assert 200 == resp.status\n\n\nasync def test_skip_auto_headers_content_type(aiohttp_client) -> None:\n    async def handler(request):\n        assert hdrs.CONTENT_TYPE not in request.headers\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/\", skip_auto_headers=[\"content-type\"]) as resp:\n        assert 200 == resp.status\n\n\nasync def test_post_data_bytesio(aiohttp_client) -> None:\n    data = b\"some buffer\"\n\n    async def handler(request):\n        assert len(data) == request.content_length\n        val = await request.read()\n        assert data == val\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"POST\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    with io.BytesIO(data) as file_handle:\n        async with client.post(\"/\", data=file_handle) as resp:\n            assert 200 == resp.status\n\n\nasync def test_post_data_with_bytesio_file(aiohttp_client) -> None:\n    data = b\"some buffer\"\n\n    async def handler(request):\n        post_data = await request.post()\n        assert [\"file\"] == list(post_data.keys())\n        assert data == post_data[\"file\"].file.read()\n        post_data[\"file\"].file.close()  # aiohttp < 4 doesn't autoclose files\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"POST\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    with io.BytesIO(data) as file_handle:\n        async with client.post(\"/\", data={\"file\": file_handle}) as resp:\n            assert 200 == resp.status\n\n\nasync def test_post_data_stringio(aiohttp_client) -> None:\n    data = \"some buffer\"\n\n    async def handler(request):\n        assert len(data) == request.content_length\n        assert request.headers[\"CONTENT-TYPE\"] == \"text/plain; charset=utf-8\"\n        val = await request.text()\n        assert data == val\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"POST\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.post(\"/\", data=io.StringIO(data)) as resp:\n        assert 200 == resp.status\n\n\nasync def test_post_data_textio_encoding(aiohttp_client) -> None:\n    data = \"текст\"\n\n    async def handler(request):\n        assert request.headers[\"CONTENT-TYPE\"] == \"text/plain; charset=koi8-r\"\n        val = await request.text()\n        assert data == val\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"POST\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    pl = aiohttp.TextIOPayload(io.StringIO(data), encoding=\"koi8-r\")\n    async with client.post(\"/\", data=pl) as resp:\n        assert 200 == resp.status\n\n\nasync def test_post_data_zipfile_filelike(aiohttp_client: AiohttpClient) -> None:\n    data = b\"This is a zip file payload text file.\"\n\n    async def handler(request: web.Request) -> web.Response:\n        val = await request.read()\n        assert data == val, \"Transmitted zipfile member failed to match original data.\"\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"POST\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    buf = io.BytesIO()\n    with zipfile.ZipFile(file=buf, mode=\"w\") as zf:\n        with zf.open(\"payload1.txt\", mode=\"w\") as zip_filelike_writing:\n            zip_filelike_writing.write(data)\n\n    buf.seek(0)\n    zf = zipfile.ZipFile(file=buf, mode=\"r\")\n    resp = await client.post(\"/\", data=zf.open(\"payload1.txt\"))\n    assert 200 == resp.status\n\n\nasync def test_post_data_tarfile_filelike(aiohttp_client: AiohttpClient) -> None:\n    data = b\"This is a tar file payload text file.\"\n\n    async def handler(request: web.Request) -> web.Response:\n        val = await request.read()\n        assert data == val, \"Transmitted tarfile member failed to match original data.\"\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"POST\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    buf = io.BytesIO()\n    with tarfile.open(fileobj=buf, mode=\"w\") as tf:\n        ti = tarfile.TarInfo(name=\"payload1.txt\")\n        ti.size = len(data)\n        tf.addfile(tarinfo=ti, fileobj=io.BytesIO(data))\n\n    # Random-access tarfile.\n    buf.seek(0)\n    tf = tarfile.open(fileobj=buf, mode=\"r:\")\n    resp = await client.post(\"/\", data=tf.extractfile(\"payload1.txt\"))\n    assert 200 == resp.status\n\n    # Streaming tarfile.\n    buf.seek(0)\n    tf = tarfile.open(fileobj=buf, mode=\"r|\")\n    for entry in tf:\n        resp = await client.post(\"/\", data=tf.extractfile(entry))\n        assert 200 == resp.status\n\n\nasync def test_ssl_client(\n    aiohttp_server,\n    ssl_ctx,\n    aiohttp_client,\n    client_ssl_ctx,\n) -> None:\n    connector = aiohttp.TCPConnector(ssl=client_ssl_ctx)\n\n    async def handler(request):\n        return web.Response(text=\"Test message\")\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    server = await aiohttp_server(app, ssl=ssl_ctx)\n    client = await aiohttp_client(server, connector=connector)\n\n    resp = await client.get(\"/\")\n    assert 200 == resp.status\n    txt = await resp.text()\n    assert txt == \"Test message\"\n\n\nasync def test_tcp_connector_fingerprint_ok(\n    aiohttp_server,\n    aiohttp_client,\n    ssl_ctx,\n    tls_certificate_fingerprint_sha256,\n):\n    tls_fingerprint = Fingerprint(tls_certificate_fingerprint_sha256)\n\n    async def handler(request):\n        return web.Response(text=\"Test message\")\n\n    connector = aiohttp.TCPConnector(ssl=tls_fingerprint)\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    server = await aiohttp_server(app, ssl=ssl_ctx)\n    client = await aiohttp_client(server, connector=connector)\n\n    async with client.get(\"/\") as resp:\n        assert resp.status == 200\n\n\nasync def test_tcp_connector_fingerprint_fail(\n    aiohttp_server,\n    aiohttp_client,\n    ssl_ctx,\n    tls_certificate_fingerprint_sha256,\n):\n    async def handler(request):\n        return web.Response(text=\"Test message\")\n\n    bad_fingerprint = b\"\\x00\" * len(tls_certificate_fingerprint_sha256)\n\n    connector = aiohttp.TCPConnector(ssl=Fingerprint(bad_fingerprint))\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    server = await aiohttp_server(app, ssl=ssl_ctx)\n    client = await aiohttp_client(server, connector=connector)\n\n    with pytest.raises(ServerFingerprintMismatch) as cm:\n        await client.get(\"/\")\n    exc = cm.value\n    assert exc.expected == bad_fingerprint\n    assert exc.got == tls_certificate_fingerprint_sha256\n\n\nasync def test_format_task_get(aiohttp_server) -> None:\n    async def handler(request):\n        return web.Response(body=b\"OK\")\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    server = await aiohttp_server(app)\n    client = aiohttp.ClientSession()\n    task = asyncio.create_task(client.get(server.make_url(\"/\")))\n    assert f\"{task}\".startswith(\"<Task pending\")\n    resp = await task\n    resp.close()\n    await client.close()\n\n\nasync def test_str_params(aiohttp_client) -> None:\n    async def handler(request):\n        assert \"q=t est\" in request.rel_url.query_string\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/\", params=\"q=t+est\") as resp:\n        assert 200 == resp.status\n\n\nasync def test_drop_params_on_redirect(aiohttp_client) -> None:\n    async def handler_redirect(request):\n        return web.Response(status=301, headers={\"Location\": \"/ok?a=redirect\"})\n\n    async def handler_ok(request):\n        assert request.rel_url.query_string == \"a=redirect\"\n        return web.Response(status=200)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/ok\", handler_ok)\n    app.router.add_route(\"GET\", \"/redirect\", handler_redirect)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/redirect\", params={\"a\": \"initial\"}) as resp:\n        assert resp.status == 200\n\n\nasync def test_drop_fragment_on_redirect(aiohttp_client) -> None:\n    async def handler_redirect(request):\n        return web.Response(status=301, headers={\"Location\": \"/ok#fragment\"})\n\n    async def handler_ok(request):\n        return web.Response(status=200)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/ok\", handler_ok)\n    app.router.add_route(\"GET\", \"/redirect\", handler_redirect)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/redirect\") as resp:\n        assert resp.status == 200\n        assert resp.url.path == \"/ok\"\n\n\nasync def test_drop_fragment(aiohttp_client) -> None:\n    async def handler_ok(request):\n        return web.Response(status=200)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/ok\", handler_ok)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/ok#fragment\") as resp:\n        assert resp.status == 200\n        assert resp.url.path == \"/ok\"\n\n\nasync def test_history(aiohttp_client) -> None:\n    async def handler_redirect(request):\n        return web.Response(status=301, headers={\"Location\": \"/ok\"})\n\n    async def handler_ok(request):\n        return web.Response(status=200)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/ok\", handler_ok)\n    app.router.add_route(\"GET\", \"/redirect\", handler_redirect)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/ok\") as resp:\n        assert len(resp.history) == 0\n        assert resp.status == 200\n\n    async with client.get(\"/redirect\") as resp_redirect:\n        assert len(resp_redirect.history) == 1\n        assert resp_redirect.history[0].status == 301\n        assert resp_redirect.status == 200\n\n\nasync def test_keepalive_closed_by_server(aiohttp_client) -> None:\n    async def handler(request):\n        body = await request.read()\n        assert b\"\" == body\n        resp = web.Response(body=b\"OK\")\n        resp.force_close()\n        return resp\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    connector = aiohttp.TCPConnector(limit=1)\n    client = await aiohttp_client(app, connector=connector)\n\n    resp1 = await client.get(\"/\")\n    val1 = await resp1.read()\n    assert val1 == b\"OK\"\n    resp2 = await client.get(\"/\")\n    val2 = await resp2.read()\n    assert val2 == b\"OK\"\n\n    assert 0 == len(client._session.connector._conns)\n\n\nasync def test_wait_for(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(body=b\"OK\")\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await asyncio.wait_for(client.get(\"/\"), 10)\n    assert resp.status == 200\n    txt = await resp.text()\n    assert txt == \"OK\"\n\n\nasync def test_raw_headers(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    async with client.get(\"/\") as resp:\n        assert resp.status == 200\n\n        raw_headers = tuple((bytes(h), bytes(v)) for h, v in resp.raw_headers)\n        assert raw_headers == (\n            (b\"Content-Length\", b\"0\"),\n            (b\"Date\", mock.ANY),\n            (b\"Server\", mock.ANY),\n        )\n\n\nasync def test_host_header_first(aiohttp_client) -> None:\n    async def handler(request):\n        assert list(request.headers)[0] == hdrs.HOST\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    async with client.get(\"/\") as resp:\n        assert resp.status == 200\n\n\nasync def test_empty_header_values(aiohttp_client) -> None:\n    async def handler(request):\n        resp = web.Response()\n        resp.headers[\"X-Empty\"] = \"\"\n        return resp\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n    async with client.get(\"/\") as resp:\n        assert resp.status == 200\n        raw_headers = tuple((bytes(h), bytes(v)) for h, v in resp.raw_headers)\n        assert raw_headers == (\n            (b\"X-Empty\", b\"\"),\n            (b\"Content-Length\", b\"0\"),\n            (b\"Date\", mock.ANY),\n            (b\"Server\", mock.ANY),\n        )\n\n\nasync def test_204_with_gzipped_content_encoding(aiohttp_client) -> None:\n    async def handler(request):\n        resp = web.StreamResponse(status=204)\n        resp.content_length = 0\n        resp.content_type = \"application/json\"\n        # resp.enable_compression(web.ContentCoding.gzip)\n        resp.headers[\"Content-Encoding\"] = \"gzip\"\n        await resp.prepare(request)\n        return resp\n\n    app = web.Application()\n    app.router.add_route(\"DELETE\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.delete(\"/\") as resp:\n        assert resp.status == 204\n        assert resp.closed\n\n\nasync def test_timeout_on_reading_headers(aiohttp_client, mocker) -> None:\n    async def handler(request):\n        resp = web.StreamResponse()\n        await asyncio.sleep(0.1)\n        await resp.prepare(request)\n        return resp\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    with pytest.raises(asyncio.TimeoutError):\n        await client.get(\"/\", timeout=0.01)\n\n\nasync def test_timeout_on_conn_reading_headers(aiohttp_client, mocker) -> None:\n    # tests case where user did not set a connection timeout\n\n    async def handler(request):\n        resp = web.StreamResponse()\n        await asyncio.sleep(0.1)\n        await resp.prepare(request)\n        return resp\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    conn = aiohttp.TCPConnector()\n    client = await aiohttp_client(app, connector=conn)\n\n    with pytest.raises(asyncio.TimeoutError):\n        await client.get(\"/\", timeout=0.01)\n\n\nasync def test_timeout_on_session_read_timeout(aiohttp_client, mocker) -> None:\n    async def handler(request):\n        resp = web.StreamResponse()\n        await asyncio.sleep(0.1)\n        await resp.prepare(request)\n        return resp\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    conn = aiohttp.TCPConnector()\n    client = await aiohttp_client(\n        app, connector=conn, timeout=aiohttp.ClientTimeout(sock_read=0.01)\n    )\n\n    with pytest.raises(asyncio.TimeoutError):\n        await client.get(\"/\")\n\n\nasync def test_read_timeout_between_chunks(aiohttp_client, mocker) -> None:\n    async def handler(request):\n        resp = aiohttp.web.StreamResponse()\n        await resp.prepare(request)\n        # write data 4 times, with pauses. Total time 2 seconds.\n        for _ in range(4):\n            await asyncio.sleep(0.5)\n            await resp.write(b\"data\\n\")\n        return resp\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    # A timeout of 0.2 seconds should apply per read.\n    timeout = aiohttp.ClientTimeout(sock_read=1)\n    client = await aiohttp_client(app, timeout=timeout)\n\n    res = b\"\"\n    async with await client.get(\"/\") as resp:\n        res += await resp.read()\n\n    assert res == b\"data\\n\" * 4\n\n\nasync def test_read_timeout_on_reading_chunks(aiohttp_client, mocker) -> None:\n    async def handler(request):\n        resp = aiohttp.web.StreamResponse()\n        await resp.prepare(request)\n        await resp.write(b\"data\\n\")\n        await asyncio.sleep(1)\n        await resp.write(b\"data\\n\")\n        return resp\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    # A timeout of 0.2 seconds should apply per read.\n    timeout = aiohttp.ClientTimeout(sock_read=0.2)\n    client = await aiohttp_client(app, timeout=timeout)\n\n    async with await client.get(\"/\") as resp:\n        assert (await resp.content.read(5)) == b\"data\\n\"\n        with pytest.raises(asyncio.TimeoutError):\n            await resp.content.read()\n\n\nasync def test_read_timeout_on_write(aiohttp_client) -> None:\n    async def gen_payload() -> AsyncIterator[str]:\n        # Delay writing to ensure read timeout isn't triggered before writing completes.\n        await asyncio.sleep(0.5)\n        yield b\"foo\"\n\n    async def handler(request: web.Request) -> web.Response:\n        return web.Response(body=await request.read())\n\n    app = web.Application()\n    app.router.add_put(\"/\", handler)\n\n    timeout = aiohttp.ClientTimeout(total=None, sock_read=0.1)\n    client = await aiohttp_client(app)\n    async with client.put(\"/\", data=gen_payload(), timeout=timeout) as resp:\n        result = await resp.read()  # Should not trigger a read timeout.\n    assert result == b\"foo\"\n\n\nasync def test_timeout_on_reading_data(aiohttp_client, mocker) -> None:\n    loop = asyncio.get_event_loop()\n\n    fut = loop.create_future()\n\n    async def handler(request):\n        resp = web.StreamResponse(headers={\"content-length\": \"100\"})\n        await resp.prepare(request)\n        fut.set_result(None)\n        await asyncio.sleep(0.2)\n        return resp\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\", timeout=1)\n    await fut\n\n    with pytest.raises(asyncio.TimeoutError):\n        await resp.read()\n\n\nasync def test_timeout_none(aiohttp_client, mocker) -> None:\n    async def handler(request):\n        resp = web.StreamResponse()\n        await resp.prepare(request)\n        return resp\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/\", timeout=None) as resp:\n        assert resp.status == 200\n\n\nasync def test_readline_error_on_conn_close(aiohttp_client) -> None:\n    loop = asyncio.get_event_loop()\n\n    async def handler(request):\n        resp_ = web.StreamResponse()\n        await resp_.prepare(request)\n\n        # make sure connection is closed by client.\n        with pytest.raises(aiohttp.ServerDisconnectedError):\n            for _ in range(10):\n                await resp_.write(b\"data\\n\")\n                await asyncio.sleep(0.5)\n            return resp_\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    server = await aiohttp_client(app)\n\n    session = aiohttp.ClientSession()\n    try:\n        timer_started = False\n        url, headers = server.make_url(\"/\"), {\"Connection\": \"Keep-alive\"}\n        resp = await session.get(url, headers=headers)\n        with pytest.raises(aiohttp.ClientConnectionError):\n            while True:\n                data = await resp.content.readline()\n                data = data.strip()\n                if not data:\n                    break\n                assert data == b\"data\"\n                if not timer_started:\n\n                    def do_release():\n                        loop.create_task(resp.release())\n\n                    loop.call_later(1.0, do_release)\n                    timer_started = True\n    finally:\n        await session.close()\n\n\nasync def test_no_error_on_conn_close_if_eof(aiohttp_client) -> None:\n    async def handler(request):\n        resp_ = web.StreamResponse()\n        await resp_.prepare(request)\n        await resp_.write(b\"data\\n\")\n        await asyncio.sleep(0.5)\n        return resp_\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    server = await aiohttp_client(app)\n\n    session = aiohttp.ClientSession()\n    try:\n        url, headers = server.make_url(\"/\"), {\"Connection\": \"Keep-alive\"}\n        resp = await session.get(url, headers=headers)\n        while True:\n            data = await resp.content.readline()\n            data = data.strip()\n            if not data:\n                break\n            assert data == b\"data\"\n\n        assert resp.content.exception() is None\n    finally:\n        await session.close()\n\n\nasync def test_error_not_overwrote_on_conn_close(aiohttp_client) -> None:\n    async def handler(request):\n        resp_ = web.StreamResponse()\n        await resp_.prepare(request)\n        return resp_\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    server = await aiohttp_client(app)\n\n    session = aiohttp.ClientSession()\n    try:\n        url, headers = server.make_url(\"/\"), {\"Connection\": \"Keep-alive\"}\n        resp = await session.get(url, headers=headers)\n        resp.content.set_exception(ValueError())\n    finally:\n        await session.close()\n\n    assert isinstance(resp.content.exception(), ValueError)\n\n\nasync def test_HTTP_200_OK_METHOD(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=request.method)\n\n    app = web.Application()\n    for meth in (\"get\", \"post\", \"put\", \"delete\", \"head\", \"patch\", \"options\"):\n        app.router.add_route(meth.upper(), \"/\", handler)\n\n    client = await aiohttp_client(app)\n    for meth in (\"get\", \"post\", \"put\", \"delete\", \"head\", \"patch\", \"options\"):\n        resp = await client.request(meth, \"/\")\n        assert resp.status == 200\n        assert len(resp.history) == 0\n\n        content1 = await resp.read()\n        content2 = await resp.read()\n        assert content1 == content2\n        content = await resp.text()\n\n        if meth == \"head\":\n            assert b\"\" == content1\n        else:\n            assert meth.upper() == content\n\n\nasync def test_HTTP_200_OK_METHOD_connector(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=request.method)\n\n    conn = aiohttp.TCPConnector()\n    conn.clear_dns_cache()\n\n    app = web.Application()\n    for meth in (\"get\", \"post\", \"put\", \"delete\", \"head\"):\n        app.router.add_route(meth.upper(), \"/\", handler)\n    client = await aiohttp_client(app, connector=conn)\n\n    for meth in (\"get\", \"post\", \"put\", \"delete\", \"head\"):\n        resp = await client.request(meth, \"/\")\n\n        content1 = await resp.read()\n        content2 = await resp.read()\n        assert content1 == content2\n        content = await resp.text()\n\n        assert resp.status == 200\n        if meth == \"head\":\n            assert b\"\" == content1\n        else:\n            assert meth.upper() == content\n\n\nasync def test_HTTP_302_REDIRECT_GET(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=request.method)\n\n    async def redirect(request):\n        raise web.HTTPFound(location=\"/\")\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    app.router.add_get(\"/redirect\", redirect)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/redirect\") as resp:\n        assert 200 == resp.status\n        assert 1 == len(resp.history)\n\n\nasync def test_HTTP_302_REDIRECT_HEAD(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=request.method)\n\n    async def redirect(request):\n        raise web.HTTPFound(location=\"/\")\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    app.router.add_get(\"/redirect\", redirect)\n    app.router.add_head(\"/\", handler)\n    app.router.add_head(\"/redirect\", redirect)\n    client = await aiohttp_client(app)\n\n    async with client.request(\"head\", \"/redirect\") as resp:\n        assert 200 == resp.status\n        assert 1 == len(resp.history)\n        assert resp.method == \"HEAD\"\n\n\nasync def test_HTTP_302_REDIRECT_NON_HTTP(aiohttp_client) -> None:\n    async def redirect(request):\n        raise web.HTTPFound(location=\"ftp://127.0.0.1/test/\")\n\n    app = web.Application()\n    app.router.add_get(\"/redirect\", redirect)\n    client = await aiohttp_client(app)\n\n    with pytest.raises(NonHttpUrlRedirectClientError):\n        await client.get(\"/redirect\")\n\n\nasync def test_HTTP_302_REDIRECT_POST(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=request.method)\n\n    async def redirect(request):\n        raise web.HTTPFound(location=\"/\")\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    app.router.add_post(\"/redirect\", redirect)\n    client = await aiohttp_client(app)\n\n    resp = await client.post(\"/redirect\")\n    assert 200 == resp.status\n    assert 1 == len(resp.history)\n    txt = await resp.text()\n    assert txt == \"GET\"\n    resp.close()\n\n\nasync def test_HTTP_302_REDIRECT_POST_with_content_length_hdr(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=request.method)\n\n    async def redirect(request):\n        await request.read()\n        raise web.HTTPFound(location=\"/\")\n\n    data = json.dumps({\"some\": \"data\"})\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    app.router.add_post(\"/redirect\", redirect)\n    client = await aiohttp_client(app)\n\n    resp = await client.post(\n        \"/redirect\", data=data, headers={\"Content-Length\": str(len(data))}\n    )\n    assert 200 == resp.status\n    assert 1 == len(resp.history)\n    txt = await resp.text()\n    assert txt == \"GET\"\n    resp.close()\n\n\nasync def test_HTTP_307_REDIRECT_POST(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=request.method)\n\n    async def redirect(request):\n        await request.read()\n        raise web.HTTPTemporaryRedirect(location=\"/\")\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    app.router.add_post(\"/redirect\", redirect)\n    client = await aiohttp_client(app)\n\n    resp = await client.post(\"/redirect\", data={\"some\": \"data\"})\n    assert 200 == resp.status\n    assert 1 == len(resp.history)\n    txt = await resp.text()\n    assert txt == \"POST\"\n    resp.close()\n\n\nasync def test_HTTP_308_PERMANENT_REDIRECT_POST(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=request.method)\n\n    async def redirect(request):\n        await request.read()\n        raise web.HTTPPermanentRedirect(location=\"/\")\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    app.router.add_post(\"/redirect\", redirect)\n    client = await aiohttp_client(app)\n\n    resp = await client.post(\"/redirect\", data={\"some\": \"data\"})\n    assert 200 == resp.status\n    assert 1 == len(resp.history)\n    txt = await resp.text()\n    assert txt == \"POST\"\n    resp.close()\n\n\nasync def test_HTTP_302_max_redirects(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=request.method)\n\n    async def redirect(request):\n        count = int(request.match_info[\"count\"])\n        if count:\n            raise web.HTTPFound(location=f\"/redirect/{count - 1}\")\n        else:\n            raise web.HTTPFound(location=\"/\")\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    app.router.add_get(r\"/redirect/{count:\\d+}\", redirect)\n    client = await aiohttp_client(app)\n\n    with pytest.raises(TooManyRedirects) as ctx:\n        await client.get(\"/redirect/5\", max_redirects=2)\n    assert 2 == len(ctx.value.history)\n    assert ctx.value.request_info.url.path == \"/redirect/5\"\n    assert ctx.value.request_info.method == \"GET\"\n\n\nasync def test_HTTP_200_GET_WITH_PARAMS(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(\n            text=\"&\".join(k + \"=\" + v for k, v in request.query.items())\n        )\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\", params={\"q\": \"test\"})\n    assert 200 == resp.status\n    txt = await resp.text()\n    assert txt == \"q=test\"\n    resp.close()\n\n\nasync def test_HTTP_200_GET_WITH_MultiDict_PARAMS(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(\n            text=\"&\".join(k + \"=\" + v for k, v in request.query.items())\n        )\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\", params=MultiDict([(\"q\", \"test\"), (\"q\", \"test2\")]))\n    assert 200 == resp.status\n    txt = await resp.text()\n    assert txt == \"q=test&q=test2\"\n    resp.close()\n\n\nasync def test_HTTP_200_GET_WITH_MIXED_PARAMS(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(\n            text=\"&\".join(k + \"=\" + v for k, v in request.query.items())\n        )\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/?test=true\", params={\"q\": \"test\"})\n    assert 200 == resp.status\n    txt = await resp.text()\n    assert txt == \"test=true&q=test\"\n    resp.close()\n\n\nasync def test_POST_DATA(aiohttp_client) -> None:\n    async def handler(request):\n        data = await request.post()\n        return web.json_response(dict(data))\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.post(\"/\", data={\"some\": \"data\"})\n    assert 200 == resp.status\n    content = await resp.json()\n    assert content == {\"some\": \"data\"}\n    resp.close()\n\n\nasync def test_POST_DATA_with_explicit_formdata(aiohttp_client) -> None:\n    async def handler(request):\n        data = await request.post()\n        return web.json_response(dict(data))\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    form = aiohttp.FormData()\n    form.add_field(\"name\", \"text\")\n\n    resp = await client.post(\"/\", data=form)\n    assert 200 == resp.status\n    content = await resp.json()\n    assert content == {\"name\": \"text\"}\n    resp.close()\n\n\nasync def test_POST_DATA_with_charset(aiohttp_client) -> None:\n    async def handler(request):\n        mp = await request.multipart()\n        part = await mp.next()\n        text = await part.text()\n        return web.Response(text=text)\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    form = aiohttp.FormData()\n    form.add_field(\"name\", \"текст\", content_type=\"text/plain; charset=koi8-r\")\n\n    resp = await client.post(\"/\", data=form)\n    assert 200 == resp.status\n    content = await resp.text()\n    assert content == \"текст\"\n    resp.close()\n\n\nasync def test_POST_DATA_formdats_with_charset(aiohttp_client) -> None:\n    async def handler(request):\n        mp = await request.post()\n        assert \"name\" in mp\n        return web.Response(text=mp[\"name\"])\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    form = aiohttp.FormData(charset=\"koi8-r\")\n    form.add_field(\"name\", \"текст\")\n\n    resp = await client.post(\"/\", data=form)\n    assert 200 == resp.status\n    content = await resp.text()\n    assert content == \"текст\"\n    resp.close()\n\n\nasync def test_POST_DATA_with_charset_post(aiohttp_client) -> None:\n    async def handler(request):\n        data = await request.post()\n        return web.Response(text=data[\"name\"])\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    form = aiohttp.FormData()\n    form.add_field(\"name\", \"текст\", content_type=\"text/plain; charset=koi8-r\")\n\n    resp = await client.post(\"/\", data=form)\n    assert 200 == resp.status\n    content = await resp.text()\n    assert content == \"текст\"\n    resp.close()\n\n\nasync def test_POST_MultiDict(aiohttp_client) -> None:\n    async def handler(request):\n        data = await request.post()\n        assert data == MultiDict([(\"q\", \"test1\"), (\"q\", \"test2\")])\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.post(\n        \"/\", data=MultiDict([(\"q\", \"test1\"), (\"q\", \"test2\")])\n    ) as resp:\n        assert 200 == resp.status\n\n\nasync def test_POST_DATA_DEFLATE(aiohttp_client) -> None:\n    async def handler(request):\n        data = await request.post()\n        return web.json_response(dict(data))\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.post(\"/\", data={\"some\": \"data\"}, compress=True)\n    assert 200 == resp.status\n    content = await resp.json()\n    assert content == {\"some\": \"data\"}\n    resp.close()\n\n\nasync def test_POST_FILES(aiohttp_client, fname) -> None:\n    async def handler(request):\n        data = await request.post()\n        assert data[\"some\"].filename == fname.name\n        with fname.open(\"rb\") as f:\n            content1 = f.read()\n        content2 = data[\"some\"].file.read()\n        assert content1 == content2\n        assert data[\"test\"].file.read() == b\"data\"\n        data[\"some\"].file.close()\n        data[\"test\"].file.close()\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with fname.open(\"rb\") as f:\n        async with client.post(\n            \"/\", data={\"some\": f, \"test\": io.BytesIO(b\"data\")}, chunked=True\n        ) as resp:\n            assert 200 == resp.status\n\n\nasync def test_POST_FILES_DEFLATE(aiohttp_client, fname) -> None:\n    async def handler(request):\n        data = await request.post()\n        assert data[\"some\"].filename == fname.name\n        with fname.open(\"rb\") as f:\n            content1 = f.read()\n        content2 = data[\"some\"].file.read()\n        data[\"some\"].file.close()\n        assert content1 == content2\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with fname.open(\"rb\") as f:\n        async with client.post(\n            \"/\", data={\"some\": f}, chunked=True, compress=\"deflate\"\n        ) as resp:\n            assert 200 == resp.status\n\n\nasync def test_POST_bytes(aiohttp_client) -> None:\n    body = b\"0\" * 12345\n\n    async def handler(request):\n        data = await request.read()\n        assert body == data\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.post(\"/\", data=body) as resp:\n        assert 200 == resp.status\n\n\nasync def test_POST_bytes_too_large(aiohttp_client) -> None:\n    body = b\"0\" * (2**20 + 1)\n\n    async def handler(request):\n        data = await request.content.read()\n        assert body == data\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with pytest.warns(ResourceWarning):\n        resp = await client.post(\"/\", data=body)\n\n    assert 200 == resp.status\n    resp.close()\n\n\nasync def test_POST_FILES_STR(aiohttp_client, fname) -> None:\n    async def handler(request):\n        data = await request.post()\n        with fname.open(\"rb\") as f:\n            content1 = f.read().decode()\n        content2 = data[\"some\"]\n        assert content1 == content2\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with fname.open(\"rb\") as f:\n        async with client.post(\"/\", data={\"some\": f.read().decode()}) as resp:\n            assert 200 == resp.status\n\n\nasync def test_POST_FILES_STR_SIMPLE(aiohttp_client, fname) -> None:\n    async def handler(request):\n        data = await request.read()\n        with fname.open(\"rb\") as f:\n            content = f.read()\n        assert content == data\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with fname.open(\"rb\") as f:\n        async with client.post(\"/\", data=f.read()) as resp:\n            assert 200 == resp.status\n\n\nasync def test_POST_FILES_LIST(aiohttp_client, fname) -> None:\n    async def handler(request):\n        data = await request.post()\n        assert fname.name == data[\"some\"].filename\n        with fname.open(\"rb\") as f:\n            content = f.read()\n        assert content == data[\"some\"].file.read()\n        data[\"some\"].file.close()\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with fname.open(\"rb\") as f:\n        async with client.post(\"/\", data=[(\"some\", f)]) as resp:\n            assert 200 == resp.status\n\n\nasync def test_POST_FILES_CT(aiohttp_client, fname) -> None:\n    async def handler(request):\n        data = await request.post()\n        assert fname.name == data[\"some\"].filename\n        assert \"text/plain\" == data[\"some\"].content_type\n        with fname.open(\"rb\") as f:\n            content = f.read()\n        assert content == data[\"some\"].file.read()\n        data[\"some\"].file.close()\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with fname.open(\"rb\") as f:\n        form = aiohttp.FormData()\n        form.add_field(\"some\", f, content_type=\"text/plain\")\n        async with client.post(\"/\", data=form) as resp:\n            assert 200 == resp.status\n\n\nasync def test_POST_FILES_SINGLE(aiohttp_client, fname) -> None:\n    async def handler(request):\n        data = await request.text()\n        with fname.open(\"rb\") as f:\n            content = f.read().decode()\n            assert content == data\n        # if system cannot determine 'text/x-python' MIME type\n        # then use 'application/octet-stream' default\n        assert request.content_type in [\n            \"text/plain\",\n            \"application/octet-stream\",\n            \"text/x-python\",\n        ]\n        assert \"content-disposition\" not in request.headers\n\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with fname.open(\"rb\") as f:\n        async with client.post(\"/\", data=f) as resp:\n            assert 200 == resp.status\n\n\nasync def test_POST_FILES_SINGLE_content_disposition(aiohttp_client, fname) -> None:\n    async def handler(request):\n        data = await request.text()\n        with fname.open(\"rb\") as f:\n            content = f.read().decode()\n            assert content == data\n        # if system cannot determine 'application/pgp-keys' MIME type\n        # then use 'application/octet-stream' default\n        assert request.content_type in [\n            \"text/plain\",\n            \"application/octet-stream\",\n            \"text/x-python\",\n        ]\n        assert request.headers[\"content-disposition\"] == (\n            'inline; filename=\"conftest.py\"'\n        )\n\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with fname.open(\"rb\") as f:\n        async with client.post(\n            \"/\", data=aiohttp.get_payload(f, disposition=\"inline\")\n        ) as resp:\n            assert 200 == resp.status\n\n\nasync def test_POST_FILES_SINGLE_BINARY(aiohttp_client, fname) -> None:\n    async def handler(request):\n        data = await request.read()\n        with fname.open(\"rb\") as f:\n            content = f.read()\n        assert content == data\n        # if system cannot determine 'application/pgp-keys' MIME type\n        # then use 'application/octet-stream' default\n        assert request.content_type in [\n            \"application/pgp-keys\",\n            \"text/plain\",\n            \"text/x-python\",\n            \"application/octet-stream\",\n        ]\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with fname.open(\"rb\") as f:\n        async with client.post(\"/\", data=f) as resp:\n            assert 200 == resp.status\n\n\nasync def test_POST_FILES_IO(aiohttp_client) -> None:\n    async def handler(request):\n        data = await request.post()\n        assert b\"data\" == data[\"unknown\"].file.read()\n        assert data[\"unknown\"].content_type == \"application/octet-stream\"\n        assert data[\"unknown\"].filename == \"unknown\"\n        data[\"unknown\"].file.close()\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with io.BytesIO(b\"data\") as file_handle:\n        async with client.post(\"/\", data=[file_handle]) as resp:\n            assert 200 == resp.status\n\n\nasync def test_POST_FILES_IO_WITH_PARAMS(aiohttp_client) -> None:\n    async def handler(request):\n        data = await request.post()\n        assert data[\"test\"] == \"true\"\n        assert data[\"unknown\"].content_type == \"application/octet-stream\"\n        assert data[\"unknown\"].filename == \"unknown\"\n        assert data[\"unknown\"].file.read() == b\"data\"\n        data[\"unknown\"].file.close()\n        assert data.getall(\"q\") == [\"t1\", \"t2\"]\n\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with io.BytesIO(b\"data\") as file_handle:\n        async with client.post(\n            \"/\",\n            data=((\"test\", \"true\"), MultiDict([(\"q\", \"t1\"), (\"q\", \"t2\")]), file_handle),\n        ) as resp:\n            assert 200 == resp.status\n\n\nasync def test_POST_FILES_WITH_DATA(aiohttp_client, fname) -> None:\n    async def handler(request):\n        data = await request.post()\n        assert data[\"test\"] == \"true\"\n        assert data[\"some\"].content_type in [\n            \"text/x-python\",\n            \"text/plain\",\n            \"application/octet-stream\",\n        ]\n        assert data[\"some\"].filename == fname.name\n        with fname.open(\"rb\") as f:\n            assert data[\"some\"].file.read() == f.read()\n            data[\"some\"].file.close()\n\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with fname.open(\"rb\") as f:\n        async with client.post(\"/\", data={\"test\": \"true\", \"some\": f}) as resp:\n            assert 200 == resp.status\n\n\nasync def test_POST_STREAM_DATA(aiohttp_client, fname) -> None:\n    async def handler(request):\n        assert request.content_type == \"application/octet-stream\"\n        content = await request.read()\n        with fname.open(\"rb\") as f:\n            expected = f.read()\n            assert request.content_length == len(expected)\n            assert content == expected\n\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with fname.open(\"rb\") as f:\n        data_size = len(f.read())\n\n    with pytest.warns(DeprecationWarning):\n\n        @aiohttp.streamer\n        async def stream(writer, fname):\n            with fname.open(\"rb\") as f:\n                data = f.read(100)\n                while data:\n                    await writer.write(data)\n                    data = f.read(100)\n\n    async with client.post(\n        \"/\", data=stream(fname), headers={\"Content-Length\": str(data_size)}\n    ) as resp:\n        assert 200 == resp.status\n\n\nasync def test_POST_STREAM_DATA_no_params(aiohttp_client, fname) -> None:\n    async def handler(request):\n        assert request.content_type == \"application/octet-stream\"\n        content = await request.read()\n        with fname.open(\"rb\") as f:\n            expected = f.read()\n            assert request.content_length == len(expected)\n            assert content == expected\n\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with fname.open(\"rb\") as f:\n        data_size = len(f.read())\n\n    with pytest.warns(DeprecationWarning):\n\n        @aiohttp.streamer\n        async def stream(writer):\n            with fname.open(\"rb\") as f:\n                data = f.read(100)\n                while data:\n                    await writer.write(data)\n                    data = f.read(100)\n\n    async with client.post(\n        \"/\", data=stream, headers={\"Content-Length\": str(data_size)}\n    ) as resp:\n        assert 200 == resp.status\n\n\nasync def test_json(aiohttp_client) -> None:\n    async def handler(request):\n        assert request.content_type == \"application/json\"\n        data = await request.json()\n        return web.Response(body=aiohttp.JsonPayload(data))\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.post(\"/\", json={\"some\": \"data\"})\n    assert 200 == resp.status\n    content = await resp.json()\n    assert content == {\"some\": \"data\"}\n    resp.close()\n\n    with pytest.raises(ValueError):\n        await client.post(\"/\", data=\"some data\", json={\"some\": \"data\"})\n\n\nasync def test_json_custom(aiohttp_client) -> None:\n    async def handler(request):\n        assert request.content_type == \"application/json\"\n        data = await request.json()\n        return web.Response(body=aiohttp.JsonPayload(data))\n\n    used = False\n\n    def dumps(obj):\n        nonlocal used\n        used = True\n        return json.dumps(obj)\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app, json_serialize=dumps)\n\n    resp = await client.post(\"/\", json={\"some\": \"data\"})\n    assert 200 == resp.status\n    assert used\n    content = await resp.json()\n    assert content == {\"some\": \"data\"}\n    resp.close()\n\n    with pytest.raises(ValueError):\n        await client.post(\"/\", data=\"some data\", json={\"some\": \"data\"})\n\n\nasync def test_expect_continue(aiohttp_client) -> None:\n    expect_called = False\n\n    async def handler(request):\n        data = await request.post()\n        assert data == {\"some\": \"data\"}\n        return web.Response()\n\n    async def expect_handler(request):\n        nonlocal expect_called\n        expect = request.headers.get(hdrs.EXPECT)\n        if expect.lower() == \"100-continue\":\n            request.transport.write(b\"HTTP/1.1 100 Continue\\r\\n\\r\\n\")\n            expect_called = True\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler, expect_handler=expect_handler)\n    client = await aiohttp_client(app)\n\n    async with client.post(\"/\", data={\"some\": \"data\"}, expect100=True) as resp:\n        assert 200 == resp.status\n    assert expect_called\n\n\nasync def test_encoding_deflate(aiohttp_client) -> None:\n    async def handler(request):\n        resp = web.Response(text=\"text\")\n        resp.enable_chunked_encoding()\n        resp.enable_compression(web.ContentCoding.deflate)\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert 200 == resp.status\n    txt = await resp.text()\n    assert txt == \"text\"\n    resp.close()\n\n\nasync def test_encoding_deflate_nochunk(aiohttp_client) -> None:\n    async def handler(request):\n        resp = web.Response(text=\"text\")\n        resp.enable_compression(web.ContentCoding.deflate)\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert 200 == resp.status\n    txt = await resp.text()\n    assert txt == \"text\"\n    resp.close()\n\n\nasync def test_encoding_gzip(aiohttp_client) -> None:\n    async def handler(request):\n        resp = web.Response(text=\"text\")\n        resp.enable_chunked_encoding()\n        resp.enable_compression(web.ContentCoding.gzip)\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert 200 == resp.status\n    txt = await resp.text()\n    assert txt == \"text\"\n    resp.close()\n\n\nasync def test_encoding_gzip_write_by_chunks(aiohttp_client) -> None:\n    async def handler(request):\n        resp = web.StreamResponse()\n        resp.enable_compression(web.ContentCoding.gzip)\n        await resp.prepare(request)\n        await resp.write(b\"0\")\n        await resp.write(b\"0\")\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert 200 == resp.status\n    txt = await resp.text()\n    assert txt == \"00\"\n    resp.close()\n\n\nasync def test_encoding_gzip_nochunk(aiohttp_client) -> None:\n    async def handler(request):\n        resp = web.Response(text=\"text\")\n        resp.enable_compression(web.ContentCoding.gzip)\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert 200 == resp.status\n    txt = await resp.text()\n    assert txt == \"text\"\n    resp.close()\n\n\nasync def test_bad_payload_compression(aiohttp_client) -> None:\n    async def handler(request):\n        resp = web.Response(text=\"text\")\n        resp.headers[\"Content-Encoding\"] = \"gzip\"\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert 200 == resp.status\n\n    with pytest.raises(aiohttp.ClientPayloadError):\n        await resp.read()\n\n    resp.close()\n\n\nasync def test_bad_payload_chunked_encoding(aiohttp_client) -> None:\n    async def handler(request):\n        resp = web.StreamResponse()\n        resp.force_close()\n        resp._length_check = False\n        resp.headers[\"Transfer-Encoding\"] = \"chunked\"\n        writer = await resp.prepare(request)\n        await writer.write(b\"9\\r\\n\\r\\n\")\n        await writer.write_eof()\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert 200 == resp.status\n\n    with pytest.raises(aiohttp.ClientPayloadError):\n        await resp.read()\n\n    resp.close()\n\n\nasync def test_no_payload_304_with_chunked_encoding(aiohttp_client: Any) -> None:\n    \"\"\"Test a 304 response with no payload with chunked set should have it removed.\"\"\"\n\n    async def handler(request):\n        resp = web.StreamResponse(status=304)\n        resp.enable_chunked_encoding()\n        resp._length_check = False\n        resp.headers[\"Transfer-Encoding\"] = \"chunked\"\n        writer = await resp.prepare(request)\n        await writer.write_eof()\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert resp.status == 304\n    assert hdrs.CONTENT_LENGTH not in resp.headers\n    assert hdrs.TRANSFER_ENCODING not in resp.headers\n    await resp.read()\n\n    resp.close()\n\n\nasync def test_head_request_with_chunked_encoding(aiohttp_client: Any) -> None:\n    \"\"\"Test a head response with chunked set should have it removed.\"\"\"\n\n    async def handler(request):\n        resp = web.StreamResponse(status=200)\n        resp.enable_chunked_encoding()\n        resp._length_check = False\n        resp.headers[\"Transfer-Encoding\"] = \"chunked\"\n        writer = await resp.prepare(request)\n        await writer.write_eof()\n        return resp\n\n    app = web.Application()\n    app.router.add_head(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.head(\"/\")\n    assert resp.status == 200\n    assert hdrs.CONTENT_LENGTH not in resp.headers\n    assert hdrs.TRANSFER_ENCODING not in resp.headers\n    await resp.read()\n\n    resp.close()\n\n\nasync def test_no_payload_200_with_chunked_encoding(aiohttp_client: Any) -> None:\n    \"\"\"Test chunked is preserved on a 200 response with no payload.\"\"\"\n\n    async def handler(request):\n        resp = web.StreamResponse(status=200)\n        resp.enable_chunked_encoding()\n        resp._length_check = False\n        resp.headers[\"Transfer-Encoding\"] = \"chunked\"\n        writer = await resp.prepare(request)\n        await writer.write_eof()\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert resp.status == 200\n    assert hdrs.CONTENT_LENGTH not in resp.headers\n    assert hdrs.TRANSFER_ENCODING in resp.headers\n    await resp.read()\n\n    resp.close()\n\n\nasync def test_bad_payload_content_length(aiohttp_client: Any) -> None:\n    async def handler(request):\n        resp = web.Response(text=\"text\")\n        resp.headers[\"Content-Length\"] = \"10000\"\n        resp.force_close()\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert 200 == resp.status\n\n    with pytest.raises(aiohttp.ClientPayloadError):\n        await resp.read()\n\n    resp.close()\n\n\nasync def test_payload_content_length_by_chunks(aiohttp_client) -> None:\n    async def handler(request):\n        resp = web.StreamResponse(headers={\"content-length\": \"2\"})\n        await resp.prepare(request)\n        await resp.write(b\"answer\")\n        await resp.write(b\"two\")\n        request.transport.close()\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    data = await resp.read()\n    assert data == b\"an\"\n    resp.close()\n\n\nasync def test_chunked(aiohttp_client) -> None:\n    async def handler(request):\n        resp = web.Response(text=\"text\")\n        resp.enable_chunked_encoding()\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    assert 200 == resp.status\n    assert resp.headers[\"Transfer-Encoding\"] == \"chunked\"\n    txt = await resp.text()\n    assert txt == \"text\"\n    resp.close()\n\n\nasync def test_shortcuts(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=request.method)\n\n    app = web.Application()\n    for meth in (\"get\", \"post\", \"put\", \"delete\", \"head\", \"patch\", \"options\"):\n        app.router.add_route(meth.upper(), \"/\", handler)\n    client = await aiohttp_client(app)\n\n    for meth in (\"get\", \"post\", \"put\", \"delete\", \"head\", \"patch\", \"options\"):\n        coro = getattr(client.session, meth)\n        resp = await coro(client.make_url(\"/\"))\n\n        assert resp.status == 200\n        assert len(resp.history) == 0\n\n        content1 = await resp.read()\n        content2 = await resp.read()\n        assert content1 == content2\n        content = await resp.text()\n\n        if meth == \"head\":\n            assert b\"\" == content1\n        else:\n            assert meth.upper() == content\n\n\nasync def test_cookies(aiohttp_client) -> None:\n    async def handler(request):\n        assert request.cookies.keys() == {\"test1\", \"test3\"}\n        assert request.cookies[\"test1\"] == \"123\"\n        assert request.cookies[\"test3\"] == \"456\"\n        return web.Response()\n\n    c = http.cookies.Morsel()\n    c.set(\"test3\", \"456\", \"456\")\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app, cookies={\"test1\": \"123\", \"test2\": c})\n\n    async with client.get(\"/\") as resp:\n        assert 200 == resp.status\n\n\nasync def test_cookies_per_request(aiohttp_client) -> None:\n    async def handler(request):\n        assert request.cookies.keys() == {\"test1\", \"test3\", \"test4\", \"test6\"}\n        assert request.cookies[\"test1\"] == \"123\"\n        assert request.cookies[\"test3\"] == \"456\"\n        assert request.cookies[\"test4\"] == \"789\"\n        assert request.cookies[\"test6\"] == \"abc\"\n        return web.Response()\n\n    c = http.cookies.Morsel()\n    c.set(\"test3\", \"456\", \"456\")\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app, cookies={\"test1\": \"123\", \"test2\": c})\n\n    rc = http.cookies.Morsel()\n    rc.set(\"test6\", \"abc\", \"abc\")\n\n    async with client.get(\"/\", cookies={\"test4\": \"789\", \"test5\": rc}) as resp:\n        assert 200 == resp.status\n\n\nasync def test_cookies_redirect(aiohttp_client) -> None:\n    async def redirect1(request):\n        ret = web.Response(status=301, headers={\"Location\": \"/redirect2\"})\n        ret.set_cookie(\"c\", \"1\")\n        return ret\n\n    async def redirect2(request):\n        ret = web.Response(status=301, headers={\"Location\": \"/\"})\n        ret.set_cookie(\"c\", \"2\")\n        return ret\n\n    async def handler(request):\n        assert request.cookies.keys() == {\"c\"}\n        assert request.cookies[\"c\"] == \"2\"\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_get(\"/redirect1\", redirect1)\n    app.router.add_get(\"/redirect2\", redirect2)\n    app.router.add_get(\"/\", handler)\n\n    client = await aiohttp_client(app)\n    async with client.get(\"/redirect1\") as resp:\n        assert 200 == resp.status\n\n\nasync def test_cookies_on_empty_session_jar(aiohttp_client) -> None:\n    async def handler(request):\n        assert \"custom-cookie\" in request.cookies\n        assert request.cookies[\"custom-cookie\"] == \"abc\"\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app, cookies=None)\n\n    async with client.get(\"/\", cookies={\"custom-cookie\": \"abc\"}) as resp:\n        assert 200 == resp.status\n\n\nasync def test_morsel_with_attributes(aiohttp_client) -> None:\n    # A comment from original test:\n    #\n    # No cookie attribute should pass here\n    # they are only used as filters\n    # whether to send particular cookie or not.\n    # E.g. if cookie expires it just becomes thrown away.\n    # Server who sent the cookie with some attributes\n    # already knows them, no need to send this back again and again\n\n    async def handler(request):\n        assert request.cookies.keys() == {\"test3\"}\n        assert request.cookies[\"test3\"] == \"456\"\n        return web.Response()\n\n    c = http.cookies.Morsel()\n    c.set(\"test3\", \"456\", \"456\")\n    c[\"httponly\"] = True\n    c[\"secure\"] = True\n    c[\"max-age\"] = 1000\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app, cookies={\"test2\": c})\n\n    async with client.get(\"/\") as resp:\n        assert 200 == resp.status\n\n\nasync def test_set_cookies(aiohttp_client) -> None:\n    async def handler(request):\n        ret = web.Response()\n        ret.set_cookie(\"c1\", \"cookie1\")\n        ret.set_cookie(\"c2\", \"cookie2\")\n        ret.headers.add(\n            \"Set-Cookie\",\n            \"ISAWPLB{A7F52349-3531-4DA9-8776-F74BC6F4F1BB}=\"\n            \"{925EC0B8-CB17-4BEB-8A35-1033813B0523}; \"\n            \"HttpOnly; Path=/\",\n        )\n        return ret\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with mock.patch(\"aiohttp.client_reqrep.client_logger\") as m_log:\n        async with client.get(\"/\") as resp:\n            assert 200 == resp.status\n            cookie_names = {c.key for c in client.session.cookie_jar}\n        assert cookie_names == {\"c1\", \"c2\"}\n\n        m_log.warning.assert_called_with(\"Can not load response cookies: %s\", mock.ANY)\n\n\nasync def test_set_cookies_expired(aiohttp_client) -> None:\n    async def handler(request):\n        ret = web.Response()\n        ret.set_cookie(\"c1\", \"cookie1\")\n        ret.set_cookie(\"c2\", \"cookie2\")\n        ret.headers.add(\n            \"Set-Cookie\",\n            \"c3=cookie3; \" \"HttpOnly; Path=/\" \" Expires=Tue, 1 Jan 1980 12:00:00 GMT; \",\n        )\n        return ret\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/\") as resp:\n        assert 200 == resp.status\n        cookie_names = {c.key for c in client.session.cookie_jar}\n    assert cookie_names == {\"c1\", \"c2\"}\n\n\nasync def test_set_cookies_max_age(aiohttp_client) -> None:\n    async def handler(request):\n        ret = web.Response()\n        ret.set_cookie(\"c1\", \"cookie1\")\n        ret.set_cookie(\"c2\", \"cookie2\")\n        ret.headers.add(\"Set-Cookie\", \"c3=cookie3; \" \"HttpOnly; Path=/\" \" Max-Age=1; \")\n        return ret\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/\") as resp:\n        assert 200 == resp.status\n        cookie_names = {c.key for c in client.session.cookie_jar}\n        assert cookie_names == {\"c1\", \"c2\", \"c3\"}\n        await asyncio.sleep(2)\n        cookie_names = {c.key for c in client.session.cookie_jar}\n        assert cookie_names == {\"c1\", \"c2\"}\n\n\nasync def test_set_cookies_max_age_overflow(aiohttp_client) -> None:\n    async def handler(request):\n        ret = web.Response()\n        ret.headers.add(\n            \"Set-Cookie\",\n            \"overflow=overflow; \" \"HttpOnly; Path=/\" \" Max-Age=\" + str(overflow) + \"; \",\n        )\n        return ret\n\n    overflow = int(\n        datetime.datetime.max.replace(tzinfo=datetime.timezone.utc).timestamp()\n    )\n    empty = None\n    try:\n        empty = datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(\n            seconds=overflow\n        )\n    except OverflowError as ex:\n        assert isinstance(ex, OverflowError)\n    assert not isinstance(empty, datetime.datetime)\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/\") as resp:\n        assert 200 == resp.status\n        for cookie in client.session.cookie_jar:\n            if cookie.key == \"overflow\":\n                assert int(cookie[\"max-age\"]) == int(overflow)\n\n\nasync def test_request_conn_error() -> None:\n    client = aiohttp.ClientSession()\n    with pytest.raises(aiohttp.ClientConnectionError):\n        await client.get(\"http://0.0.0.0:1\")\n    await client.close()\n\n\n@pytest.mark.xfail\nasync def test_broken_connection(aiohttp_client) -> None:\n    async def handler(request):\n        request.transport.close()\n        return web.Response(text=\"answer\" * 1000)\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    with pytest.raises(aiohttp.ClientResponseError):\n        await client.get(\"/\")\n\n\nasync def test_broken_connection_2(aiohttp_client) -> None:\n    async def handler(request):\n        resp = web.StreamResponse(headers={\"content-length\": \"1000\"})\n        await resp.prepare(request)\n        await resp.write(b\"answer\")\n        request.transport.close()\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/\")\n    with pytest.raises(aiohttp.ClientPayloadError):\n        await resp.read()\n    resp.close()\n\n\nasync def test_custom_headers(aiohttp_client) -> None:\n    async def handler(request):\n        assert request.headers[\"x-api-key\"] == \"foo\"\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n    client = await aiohttp_client(app)\n\n    async with client.post(\n        \"/\", headers={\"Content-Type\": \"application/json\", \"x-api-key\": \"foo\"}\n    ) as resp:\n        assert resp.status == 200\n\n\nasync def test_redirect_to_absolute_url(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(text=request.method)\n\n    async def redirect(request):\n        raise web.HTTPFound(location=client.make_url(\"/\"))\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    app.router.add_get(\"/redirect\", redirect)\n\n    client = await aiohttp_client(app)\n    async with client.get(\"/redirect\") as resp:\n        assert 200 == resp.status\n\n\nasync def test_redirect_without_location_header(aiohttp_client) -> None:\n    body = b\"redirect\"\n\n    async def handler_redirect(request):\n        return web.Response(status=301, body=body)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/redirect\", handler_redirect)\n    client = await aiohttp_client(app)\n\n    resp = await client.get(\"/redirect\")\n    data = await resp.read()\n    assert data == body\n\n\nasync def test_chunked_deprecated(aiohttp_client) -> None:\n    async def handler_redirect(request):\n        return web.Response(status=301)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/redirect\", handler_redirect)\n    client = await aiohttp_client(app)\n\n    with pytest.warns(DeprecationWarning):\n        await client.post(\"/\", chunked=1024)\n\n\nINVALID_URL_WITH_ERROR_MESSAGE_YARL_NEW = (\n    # yarl.URL.__new__ raises ValueError\n    (\"http://:/\", \"http://:/\"),\n    (\"http://example.org:non_int_port/\", \"http://example.org:non_int_port/\"),\n)\n\nINVALID_URL_WITH_ERROR_MESSAGE_YARL_ORIGIN = (\n    # # yarl.URL.origin raises ValueError\n    (\"http:/\", \"http:///\"),\n    (\"http:/example.com\", \"http:///example.com\"),\n    (\"http:///example.com\", \"http:///example.com\"),\n)\n\nNON_HTTP_URL_WITH_ERROR_MESSAGE = (\n    (\"call:+380123456789\", r\"call:\\+380123456789\"),\n    (\"skype:handle\", \"skype:handle\"),\n    (\"slack://instance/room\", \"slack://instance/room\"),\n    (\"steam:code\", \"steam:code\"),\n    (\"twitter://handle\", \"twitter://handle\"),\n    (\"bluesky://profile/d:i:d\", \"bluesky://profile/d:i:d\"),\n)\n\n\n@pytest.mark.parametrize(\n    (\"url\", \"error_message_url\", \"expected_exception_class\"),\n    (\n        *(\n            (url, message, InvalidUrlClientError)\n            for (url, message) in INVALID_URL_WITH_ERROR_MESSAGE_YARL_NEW\n        ),\n        *(\n            (url, message, InvalidUrlClientError)\n            for (url, message) in INVALID_URL_WITH_ERROR_MESSAGE_YARL_ORIGIN\n        ),\n        *(\n            (url, message, NonHttpUrlClientError)\n            for (url, message) in NON_HTTP_URL_WITH_ERROR_MESSAGE\n        ),\n    ),\n)\nasync def test_invalid_and_non_http_url(\n    url: Any, error_message_url: Any, expected_exception_class: Any\n) -> None:\n    async with aiohttp.ClientSession() as http_session:\n        with pytest.raises(\n            expected_exception_class, match=rf\"^{error_message_url}( - [A-Za-z ]+)?\"\n        ):\n            await http_session.get(url)\n\n\n@pytest.mark.parametrize(\n    (\"invalid_redirect_url\", \"error_message_url\", \"expected_exception_class\"),\n    (\n        *(\n            (url, message, InvalidUrlRedirectClientError)\n            for (url, message) in INVALID_URL_WITH_ERROR_MESSAGE_YARL_ORIGIN\n            + INVALID_URL_WITH_ERROR_MESSAGE_YARL_NEW\n        ),\n        *(\n            (url, message, NonHttpUrlRedirectClientError)\n            for (url, message) in NON_HTTP_URL_WITH_ERROR_MESSAGE\n        ),\n    ),\n)\nasync def test_invalid_redirect_url(\n    aiohttp_client: Any,\n    invalid_redirect_url: Any,\n    error_message_url: str,\n    expected_exception_class: Any,\n) -> None:\n    headers = {hdrs.LOCATION: invalid_redirect_url}\n\n    async def generate_redirecting_response(request):\n        return web.Response(status=301, headers=headers)\n\n    app = web.Application()\n    app.router.add_get(\"/redirect\", generate_redirecting_response)\n    client = await aiohttp_client(app)\n\n    with pytest.raises(\n        expected_exception_class, match=rf\"^{error_message_url}( - [A-Za-z ]+)?\"\n    ):\n        await client.get(\"/redirect\")\n\n\n@pytest.mark.parametrize(\n    (\"invalid_redirect_url\", \"error_message_url\", \"expected_exception_class\"),\n    (\n        *(\n            (url, message, InvalidUrlRedirectClientError)\n            for (url, message) in INVALID_URL_WITH_ERROR_MESSAGE_YARL_ORIGIN\n            + INVALID_URL_WITH_ERROR_MESSAGE_YARL_NEW\n        ),\n        *(\n            (url, message, NonHttpUrlRedirectClientError)\n            for (url, message) in NON_HTTP_URL_WITH_ERROR_MESSAGE\n        ),\n    ),\n)\nasync def test_invalid_redirect_url_multiple_redirects(\n    aiohttp_client: Any,\n    invalid_redirect_url: Any,\n    error_message_url: str,\n    expected_exception_class: Any,\n) -> None:\n    app = web.Application()\n\n    for path, location in [\n        (\"/redirect\", \"/redirect1\"),\n        (\"/redirect1\", \"/redirect2\"),\n        (\"/redirect2\", invalid_redirect_url),\n    ]:\n\n        async def generate_redirecting_response(request):\n            return web.Response(status=301, headers={hdrs.LOCATION: location})\n\n        app.router.add_get(path, generate_redirecting_response)\n\n    client = await aiohttp_client(app)\n\n    with pytest.raises(\n        expected_exception_class, match=rf\"^{error_message_url}( - [A-Za-z ]+)?\"\n    ):\n        await client.get(\"/redirect\")\n\n\n@pytest.mark.parametrize(\n    (\"status\", \"expected_ok\"),\n    (\n        (200, True),\n        (201, True),\n        (301, True),\n        (400, False),\n        (403, False),\n        (500, False),\n    ),\n)\nasync def test_ok_from_status(aiohttp_client, status, expected_ok) -> None:\n    async def handler(request):\n        return web.Response(status=status, body=b\"\")\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/endpoint\", handler)\n    client = await aiohttp_client(app, raise_for_status=False)\n    async with client.get(\"/endpoint\") as resp:\n        assert resp.ok is expected_ok\n\n\nasync def test_raise_for_status(aiohttp_client) -> None:\n    async def handler_redirect(request):\n        raise web.HTTPBadRequest()\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler_redirect)\n    client = await aiohttp_client(app, raise_for_status=True)\n\n    with pytest.raises(aiohttp.ClientResponseError):\n        await client.get(\"/\")\n\n\nasync def test_raise_for_status_per_request(aiohttp_client) -> None:\n    async def handler_redirect(request):\n        raise web.HTTPBadRequest()\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler_redirect)\n    client = await aiohttp_client(app)\n\n    with pytest.raises(aiohttp.ClientResponseError):\n        await client.get(\"/\", raise_for_status=True)\n\n\nasync def test_raise_for_status_disable_per_request(aiohttp_client) -> None:\n    async def handler_redirect(request):\n        raise web.HTTPBadRequest()\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler_redirect)\n    client = await aiohttp_client(app, raise_for_status=True)\n\n    async with client.get(\"/\", raise_for_status=False) as resp:\n        assert 400 == resp.status\n\n\nasync def test_request_raise_for_status_default(aiohttp_server) -> None:\n    async def handler(request):\n        raise web.HTTPBadRequest()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    server = await aiohttp_server(app)\n\n    async with aiohttp.request(\"GET\", server.make_url(\"/\")) as resp:\n        assert resp.status == 400\n\n\nasync def test_request_raise_for_status_disabled(aiohttp_server) -> None:\n    async def handler(request):\n        raise web.HTTPBadRequest()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    server = await aiohttp_server(app)\n    url = server.make_url(\"/\")\n\n    async with aiohttp.request(\"GET\", url, raise_for_status=False) as resp:\n        assert resp.status == 400\n\n\nasync def test_request_raise_for_status_enabled(aiohttp_server) -> None:\n    async def handler(request):\n        raise web.HTTPBadRequest()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    server = await aiohttp_server(app)\n    url = server.make_url(\"/\")\n\n    with pytest.raises(aiohttp.ClientResponseError):\n        async with aiohttp.request(\"GET\", url, raise_for_status=True):\n            assert False, \"never executed\"  # pragma: no cover\n\n\nasync def test_session_raise_for_status_coro(aiohttp_client) -> None:\n    async def handle(request):\n        return web.Response(text=\"ok\")\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handle)\n\n    raise_for_status_called = 0\n\n    async def custom_r4s(response):\n        nonlocal raise_for_status_called\n        raise_for_status_called += 1\n        assert response.status == 200\n        assert response.request_info.method == \"GET\"\n\n    client = await aiohttp_client(app, raise_for_status=custom_r4s)\n    await client.get(\"/\")\n    assert raise_for_status_called == 1\n    await client.get(\"/\", raise_for_status=True)\n    assert raise_for_status_called == 1  # custom_r4s not called again\n    await client.get(\"/\", raise_for_status=False)\n    assert raise_for_status_called == 1  # custom_r4s not called again\n\n\nasync def test_request_raise_for_status_coro(aiohttp_client) -> None:\n    async def handle(request):\n        return web.Response(text=\"ok\")\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handle)\n\n    raise_for_status_called = 0\n\n    async def custom_r4s(response):\n        nonlocal raise_for_status_called\n        raise_for_status_called += 1\n        assert response.status == 200\n        assert response.request_info.method == \"GET\"\n\n    client = await aiohttp_client(app)\n    await client.get(\"/\", raise_for_status=custom_r4s)\n    assert raise_for_status_called == 1\n    await client.get(\"/\", raise_for_status=True)\n    assert raise_for_status_called == 1  # custom_r4s not called again\n    await client.get(\"/\", raise_for_status=False)\n    assert raise_for_status_called == 1  # custom_r4s not called again\n\n\nasync def test_invalid_idna() -> None:\n    session = aiohttp.ClientSession()\n    try:\n        with pytest.raises(aiohttp.InvalidURL):\n            await session.get(\"http://\\u2061owhefopw.com\")\n    finally:\n        await session.close()\n\n\nasync def test_creds_in_auth_and_url() -> None:\n    session = aiohttp.ClientSession()\n    try:\n        with pytest.raises(ValueError):\n            await session.get(\n                \"http://user:pass@example.com\", auth=aiohttp.BasicAuth(\"user2\", \"pass2\")\n            )\n    finally:\n        await session.close()\n\n\n@pytest.fixture\ndef create_server_for_url_and_handler(aiohttp_server, tls_certificate_authority):\n    def create(url, srv):\n        app = web.Application()\n        app.router.add_route(\"GET\", url.path, srv)\n\n        kwargs = {}\n        if url.scheme == \"https\":\n            cert = tls_certificate_authority.issue_cert(\n                url.host, \"localhost\", \"127.0.0.1\"\n            )\n            ssl_ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)\n            cert.configure_cert(ssl_ctx)\n            kwargs[\"ssl\"] = ssl_ctx\n        return aiohttp_server(app, **kwargs)\n\n    return create\n\n\n@pytest.mark.parametrize(\n    [\"url_from\", \"url_to\"],\n    [\n        [\"http://host1.com/path1\", \"http://host2.com/path2\"],\n        [\"http://host1.com/path1\", \"https://host1.com/path1\"],\n        [\"https://host1.com/path1\", \"http://host1.com/path2\"],\n    ],\n    ids=(\n        \"entirely different hosts\",\n        \"http -> https\",\n        \"https -> http\",\n    ),\n)\nasync def test_drop_auth_on_redirect_to_other_host(\n    create_server_for_url_and_handler,\n    url_from,\n    url_to,\n) -> None:\n    url_from, url_to = URL(url_from), URL(url_to)\n\n    async def srv_from(request):\n        assert request.host == url_from.host\n        assert request.headers[\"Authorization\"] == \"Basic dXNlcjpwYXNz\"\n        raise web.HTTPFound(url_to)\n\n    async def srv_to(request):\n        assert request.host == url_to.host\n        assert \"Authorization\" not in request.headers, \"Header wasn't dropped\"\n        return web.Response()\n\n    server_from = await create_server_for_url_and_handler(url_from, srv_from)\n    server_to = await create_server_for_url_and_handler(url_to, srv_to)\n\n    assert (\n        url_from.host != url_to.host or server_from.scheme != server_to.scheme\n    ), \"Invalid test case, host or scheme must differ\"\n\n    protocol_port_map = {\n        \"http\": 80,\n        \"https\": 443,\n    }\n    etc_hosts = {\n        (url_from.host, protocol_port_map[server_from.scheme]): server_from,\n        (url_to.host, protocol_port_map[server_to.scheme]): server_to,\n    }\n\n    class FakeResolver(AbstractResolver):\n        async def resolve(self, host, port=0, family=socket.AF_INET):\n            server = etc_hosts[(host, port)]\n\n            return [\n                {\n                    \"hostname\": host,\n                    \"host\": server.host,\n                    \"port\": server.port,\n                    \"family\": socket.AF_INET,\n                    \"proto\": 0,\n                    \"flags\": socket.AI_NUMERICHOST,\n                }\n            ]\n\n        async def close(self):\n            pass\n\n    connector = aiohttp.TCPConnector(resolver=FakeResolver(), ssl=False)\n\n    async with aiohttp.ClientSession(connector=connector) as client:\n        resp = await client.get(\n            url_from,\n            auth=aiohttp.BasicAuth(\"user\", \"pass\"),\n        )\n        assert resp.status == 200\n        resp = await client.get(\n            url_from,\n            headers={\"Authorization\": \"Basic dXNlcjpwYXNz\"},\n        )\n        assert resp.status == 200\n\n\nasync def test_async_with_session() -> None:\n    async with aiohttp.ClientSession() as session:\n        pass\n\n    assert session.closed\n\n\nasync def test_session_close_awaitable() -> None:\n    session = aiohttp.ClientSession()\n    await session.close()\n\n    assert session.closed\n\n\nasync def test_close_resp_on_error_async_with_session(aiohttp_server) -> None:\n    async def handler(request):\n        resp = web.StreamResponse(headers={\"content-length\": \"100\"})\n        await resp.prepare(request)\n        await asyncio.sleep(0.1)\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    server = await aiohttp_server(app)\n\n    async with aiohttp.ClientSession() as session:\n        with pytest.raises(RuntimeError):\n            async with session.get(server.make_url(\"/\")) as resp:\n                resp.content.set_exception(RuntimeError())\n                await resp.read()\n\n        assert len(session._connector._conns) == 0\n\n\nasync def test_release_resp_on_normal_exit_from_cm(aiohttp_server) -> None:\n    async def handler(request):\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    server = await aiohttp_server(app)\n\n    async with aiohttp.ClientSession() as session:\n        async with session.get(server.make_url(\"/\")) as resp:\n            await resp.read()\n\n        assert len(session._connector._conns) == 1\n\n\nasync def test_non_close_detached_session_on_error_cm(aiohttp_server) -> None:\n    async def handler(request):\n        resp = web.StreamResponse(headers={\"content-length\": \"100\"})\n        await resp.prepare(request)\n        await asyncio.sleep(0.1)\n        return resp\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    server = await aiohttp_server(app)\n\n    session = aiohttp.ClientSession()\n    cm = session.get(server.make_url(\"/\"))\n    assert not session.closed\n    with pytest.raises(RuntimeError):\n        async with cm as resp:\n            resp.content.set_exception(RuntimeError())\n            await resp.read()\n    assert not session.closed\n\n\nasync def test_close_detached_session_on_non_existing_addr() -> None:\n    class FakeResolver(AbstractResolver):\n        async def resolve(host, port=0, family=socket.AF_INET):\n            return {}\n\n        async def close(self):\n            pass\n\n    connector = aiohttp.TCPConnector(resolver=FakeResolver())\n\n    session = aiohttp.ClientSession(connector=connector)\n\n    async with session:\n        cm = session.get(\"http://non-existing.example.com\")\n        assert not session.closed\n        with pytest.raises(Exception):\n            await cm\n\n    assert session.closed\n\n\nasync def test_aiohttp_request_context_manager(aiohttp_server) -> None:\n    async def handler(request):\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    server = await aiohttp_server(app)\n\n    async with aiohttp.request(\"GET\", server.make_url(\"/\")) as resp:\n        await resp.read()\n        assert resp.status == 200\n\n\nasync def test_aiohttp_request_ctx_manager_close_sess_on_error(\n    ssl_ctx, aiohttp_server\n) -> None:\n    async def handler(request):\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    server = await aiohttp_server(app, ssl=ssl_ctx)\n\n    cm = aiohttp.request(\"GET\", server.make_url(\"/\"))\n\n    with pytest.raises(aiohttp.ClientConnectionError):\n        async with cm:\n            pass\n\n    assert cm._session.closed\n\n\nasync def test_aiohttp_request_ctx_manager_not_found() -> None:\n\n    with pytest.raises(aiohttp.ClientConnectionError):\n        async with aiohttp.request(\"GET\", \"http://wrong-dns-name.com\"):\n            assert False, \"never executed\"  # pragma: no cover\n\n\nasync def test_yield_from_in_session_request(aiohttp_client) -> None:\n    # a test for backward compatibility with yield from syntax\n    async def handler(request):\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n\n    client = await aiohttp_client(app)\n    async with client.get(\"/\") as resp:\n        assert resp.status == 200\n\n\nasync def test_close_context_manager(aiohttp_client) -> None:\n    # a test for backward compatibility with yield from syntax\n    async def handler(request):\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n\n    client = await aiohttp_client(app)\n    ctx = client.get(\"/\")\n    ctx.close()\n    assert not ctx._coro.cr_running\n\n\nasync def test_session_auth(aiohttp_client) -> None:\n    async def handler(request):\n        return web.json_response({\"headers\": dict(request.headers)})\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n\n    client = await aiohttp_client(app, auth=aiohttp.BasicAuth(\"login\", \"pass\"))\n\n    r = await client.get(\"/\")\n    assert r.status == 200\n    content = await r.json()\n    assert content[\"headers\"][\"Authorization\"] == \"Basic bG9naW46cGFzcw==\"\n\n\nasync def test_session_auth_override(aiohttp_client) -> None:\n    async def handler(request):\n        return web.json_response({\"headers\": dict(request.headers)})\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n\n    client = await aiohttp_client(app, auth=aiohttp.BasicAuth(\"login\", \"pass\"))\n\n    r = await client.get(\"/\", auth=aiohttp.BasicAuth(\"other_login\", \"pass\"))\n    assert r.status == 200\n    content = await r.json()\n    val = content[\"headers\"][\"Authorization\"]\n    assert val == \"Basic b3RoZXJfbG9naW46cGFzcw==\"\n\n\nasync def test_session_auth_header_conflict(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n\n    client = await aiohttp_client(app, auth=aiohttp.BasicAuth(\"login\", \"pass\"))\n    headers = {\"Authorization\": \"Basic b3RoZXJfbG9naW46cGFzcw==\"}\n    with pytest.raises(ValueError):\n        await client.get(\"/\", headers=headers)\n\n\nasync def test_session_headers(aiohttp_client) -> None:\n    async def handler(request):\n        return web.json_response({\"headers\": dict(request.headers)})\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n\n    client = await aiohttp_client(app, headers={\"X-Real-IP\": \"192.168.0.1\"})\n\n    r = await client.get(\"/\")\n    assert r.status == 200\n    content = await r.json()\n    assert content[\"headers\"][\"X-Real-IP\"] == \"192.168.0.1\"\n\n\nasync def test_session_headers_merge(aiohttp_client) -> None:\n    async def handler(request):\n        return web.json_response({\"headers\": dict(request.headers)})\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n\n    client = await aiohttp_client(\n        app, headers=[(\"X-Real-IP\", \"192.168.0.1\"), (\"X-Sent-By\", \"requests\")]\n    )\n\n    r = await client.get(\"/\", headers={\"X-Sent-By\": \"aiohttp\"})\n    assert r.status == 200\n    content = await r.json()\n    assert content[\"headers\"][\"X-Real-IP\"] == \"192.168.0.1\"\n    assert content[\"headers\"][\"X-Sent-By\"] == \"aiohttp\"\n\n\nasync def test_multidict_headers(aiohttp_client) -> None:\n    async def handler(request):\n        assert await request.read() == data\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n\n    client = await aiohttp_client(app)\n\n    data = b\"sample data\"\n\n    async with client.post(\n        \"/\", data=data, headers=MultiDict({\"Content-Length\": str(len(data))})\n    ) as r:\n        assert r.status == 200\n\n\nasync def test_request_conn_closed(aiohttp_client) -> None:\n    async def handler(request):\n        request.transport.close()\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n\n    client = await aiohttp_client(app)\n    with pytest.raises(aiohttp.ServerDisconnectedError) as excinfo:\n        resp = await client.get(\"/\")\n        await resp.read()\n\n    assert str(excinfo.value) != \"\"\n\n\nasync def test_dont_close_explicit_connector(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n\n    client = await aiohttp_client(app)\n    r = await client.get(\"/\")\n    await r.read()\n\n    assert 1 == len(client.session.connector._conns)\n\n\nasync def test_server_close_keepalive_connection() -> None:\n    loop = asyncio.get_event_loop()\n\n    class Proto(asyncio.Protocol):\n        def connection_made(self, transport):\n            self.transp = transport\n            self.data = b\"\"\n\n        def data_received(self, data):\n            self.data += data\n            if data.endswith(b\"\\r\\n\\r\\n\"):\n                self.transp.write(\n                    b\"HTTP/1.1 200 OK\\r\\n\"\n                    b\"CONTENT-LENGTH: 2\\r\\n\"\n                    b\"CONNECTION: close\\r\\n\"\n                    b\"\\r\\n\"\n                    b\"ok\"\n                )\n                self.transp.close()\n\n        def connection_lost(self, exc):\n            self.transp = None\n\n    server = await loop.create_server(Proto, \"127.0.0.1\", unused_port())\n\n    addr = server.sockets[0].getsockname()\n\n    connector = aiohttp.TCPConnector(limit=1)\n    session = aiohttp.ClientSession(connector=connector)\n\n    url = \"http://{}:{}/\".format(*addr)\n    for i in range(2):\n        r = await session.request(\"GET\", url)\n        await r.read()\n        assert 0 == len(connector._conns)\n    await session.close()\n    await connector.close()\n    server.close()\n    await server.wait_closed()\n\n\nasync def test_handle_keepalive_on_closed_connection() -> None:\n    loop = asyncio.get_event_loop()\n\n    class Proto(asyncio.Protocol):\n        def connection_made(self, transport):\n            self.transp = transport\n            self.data = b\"\"\n\n        def data_received(self, data):\n            self.data += data\n            if data.endswith(b\"\\r\\n\\r\\n\"):\n                self.transp.write(\n                    b\"HTTP/1.1 200 OK\\r\\n\" b\"CONTENT-LENGTH: 2\\r\\n\" b\"\\r\\n\" b\"ok\"\n                )\n                self.transp.close()\n\n        def connection_lost(self, exc):\n            self.transp = None\n\n    server = await loop.create_server(Proto, \"127.0.0.1\", unused_port())\n\n    addr = server.sockets[0].getsockname()\n\n    async with aiohttp.TCPConnector(limit=1) as connector:\n        async with aiohttp.ClientSession(connector=connector) as session:\n            url = \"http://{}:{}/\".format(*addr)\n\n            r = await session.request(\"GET\", url)\n            await r.read()\n            assert 1 == len(connector._conns)\n            closed_conn = next(iter(connector._conns.values()))\n\n            await session.request(\"GET\", url)\n            assert 1 == len(connector._conns)\n            new_conn = next(iter(connector._conns.values()))\n            assert closed_conn is not new_conn\n\n    server.close()\n    await server.wait_closed()\n\n\nasync def test_error_in_performing_request(ssl_ctx, aiohttp_client, aiohttp_server):\n    async def handler(request):\n        return web.Response()\n\n    def exception_handler(loop, context):\n        # skip log messages about destroyed but pending tasks\n        pass\n\n    loop = asyncio.get_event_loop()\n    loop.set_exception_handler(exception_handler)\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    server = await aiohttp_server(app, ssl=ssl_ctx)\n\n    conn = aiohttp.TCPConnector(limit=1)\n    client = await aiohttp_client(server, connector=conn)\n\n    with pytest.raises(aiohttp.ClientConnectionError):\n        await client.get(\"/\")\n\n    # second try should not hang\n    with pytest.raises(aiohttp.ClientConnectionError):\n        await client.get(\"/\")\n\n\nasync def test_await_after_cancelling(aiohttp_client) -> None:\n    loop = asyncio.get_event_loop()\n\n    async def handler(request):\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n\n    client = await aiohttp_client(app)\n\n    fut1 = loop.create_future()\n    fut2 = loop.create_future()\n\n    async def fetch1():\n        resp = await client.get(\"/\")\n        assert resp.status == 200\n        fut1.set_result(None)\n        with pytest.raises(asyncio.CancelledError):\n            await fut2\n        resp.release()\n\n    async def fetch2():\n        await fut1\n        resp = await client.get(\"/\")\n        assert resp.status == 200\n\n    async def canceller():\n        await fut1\n        fut2.cancel()\n\n    await asyncio.gather(fetch1(), fetch2(), canceller())\n\n\nasync def test_async_payload_generator(aiohttp_client) -> None:\n    async def handler(request):\n        data = await request.read()\n        assert data == b\"1234567890\" * 100\n        return web.Response()\n\n    app = web.Application()\n    app.add_routes([web.post(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n\n    async def gen():\n        for i in range(100):\n            yield b\"1234567890\"\n\n    async with client.post(\"/\", data=gen()) as resp:\n        assert resp.status == 200\n\n\nasync def test_read_from_closed_response(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(body=b\"data\")\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/\") as resp:\n        assert resp.status == 200\n\n    with pytest.raises(aiohttp.ClientConnectionError):\n        await resp.read()\n\n\nasync def test_read_from_closed_response2(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(body=b\"data\")\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/\") as resp:\n        assert resp.status == 200\n        await resp.read()\n\n    with pytest.raises(aiohttp.ClientConnectionError):\n        await resp.read()\n\n\nasync def test_read_from_closed_content(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(body=b\"data\")\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n\n    async with client.get(\"/\") as resp:\n        assert resp.status == 200\n\n    with pytest.raises(aiohttp.ClientConnectionError):\n        await resp.content.readline()\n\n\nasync def test_read_timeout(aiohttp_client) -> None:\n    async def handler(request):\n        await asyncio.sleep(5)\n        return web.Response()\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    timeout = aiohttp.ClientTimeout(sock_read=0.1)\n    client = await aiohttp_client(app, timeout=timeout)\n\n    with pytest.raises(aiohttp.ServerTimeoutError):\n        await client.get(\"/\")\n\n\nasync def test_socket_timeout(aiohttp_client: Any) -> None:\n    async def handler(request):\n        await asyncio.sleep(5)\n        return web.Response()\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    timeout = aiohttp.ClientTimeout(sock_read=0.1)\n    client = await aiohttp_client(app, timeout=timeout)\n\n    with pytest.raises(SocketTimeoutError):\n        await client.get(\"/\")\n\n\nasync def test_read_timeout_closes_connection(aiohttp_client: AiohttpClient) -> None:\n    request_count = 0\n\n    async def handler(request):\n        nonlocal request_count\n        request_count += 1\n        if request_count < 3:\n            await asyncio.sleep(0.5)\n        return web.Response(body=f\"request:{request_count}\")\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    timeout = aiohttp.ClientTimeout(total=0.1)\n    client: TestClient = await aiohttp_client(app, timeout=timeout)\n    with pytest.raises(asyncio.TimeoutError):\n        await client.get(\"/\")\n\n    # Make sure its really closed\n    assert not client.session.connector._conns\n\n    with pytest.raises(asyncio.TimeoutError):\n        await client.get(\"/\")\n\n    # Make sure its really closed\n    assert not client.session.connector._conns\n    result = await client.get(\"/\")\n    assert await result.read() == b\"request:3\"\n\n    # Make sure its not closed\n    assert client.session.connector._conns\n\n\nasync def test_read_timeout_on_prepared_response(aiohttp_client: Any) -> None:\n    async def handler(request):\n        resp = aiohttp.web.StreamResponse()\n        await resp.prepare(request)\n        await asyncio.sleep(5)\n        await resp.drain()\n        return resp\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    timeout = aiohttp.ClientTimeout(sock_read=0.1)\n    client = await aiohttp_client(app, timeout=timeout)\n\n    with pytest.raises(aiohttp.ServerTimeoutError):\n        async with await client.get(\"/\") as resp:\n            await resp.read()\n\n\nasync def test_timeout_with_full_buffer(aiohttp_client) -> None:\n    async def handler(request):\n        \"\"\"Server response that never ends and always has more data available.\"\"\"\n        resp = web.StreamResponse()\n        await resp.prepare(request)\n        while True:\n            await resp.write(b\"1\" * 1000)\n            await asyncio.sleep(0.01)\n\n    async def request(client):\n        timeout = aiohttp.ClientTimeout(total=0.5)\n        async with await client.get(\"/\", timeout=timeout) as resp:\n            with pytest.raises(asyncio.TimeoutError):\n                async for data in resp.content.iter_chunked(1):\n                    await asyncio.sleep(0.01)\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n    # wait_for() used just to ensure that a failing test doesn't hang.\n    await asyncio.wait_for(request(client), 1)\n\n\nasync def test_read_bufsize_session_default(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(body=b\"1234567\")\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app, read_bufsize=2)\n\n    async with await client.get(\"/\") as resp:\n        assert resp.content.get_read_buffer_limits() == (2, 4)\n\n\nasync def test_read_bufsize_explicit(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(body=b\"1234567\")\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n\n    async with await client.get(\"/\", read_bufsize=4) as resp:\n        assert resp.content.get_read_buffer_limits() == (4, 8)\n\n\nasync def test_http_empty_data_text(aiohttp_client) -> None:\n    async def handler(request):\n        data = await request.read()\n        ret = \"ok\" if data == b\"\" else \"fail\"\n        resp = web.Response(text=ret)\n        resp.headers[\"Content-Type\"] = request.headers[\"Content-Type\"]\n        return resp\n\n    app = web.Application()\n    app.add_routes([web.post(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n\n    async with await client.post(\"/\", data=\"\") as resp:\n        assert resp.status == 200\n        assert await resp.text() == \"ok\"\n        assert resp.headers[\"Content-Type\"] == \"text/plain; charset=utf-8\"\n\n\nasync def test_max_field_size_session_default(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(headers={\"Custom\": \"x\" * 8190})\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n\n    async with await client.get(\"/\") as resp:\n        assert resp.headers[\"Custom\"] == \"x\" * 8190\n\n\nasync def test_max_field_size_session_default_fail(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(headers={\"Custom\": \"x\" * 8191})\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n    with pytest.raises(aiohttp.ClientResponseError):\n        await client.get(\"/\")\n\n\nasync def test_max_field_size_session_explicit(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(headers={\"Custom\": \"x\" * 8191})\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app, max_field_size=8191)\n\n    async with await client.get(\"/\") as resp:\n        assert resp.headers[\"Custom\"] == \"x\" * 8191\n\n\nasync def test_max_field_size_request_explicit(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(headers={\"Custom\": \"x\" * 8191})\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n\n    async with await client.get(\"/\", max_field_size=8191) as resp:\n        assert resp.headers[\"Custom\"] == \"x\" * 8191\n\n\nasync def test_max_line_size_session_default(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(status=200, reason=\"x\" * 8190)\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n\n    async with await client.get(\"/\") as resp:\n        assert resp.reason == \"x\" * 8190\n\n\nasync def test_max_line_size_session_default_fail(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(status=200, reason=\"x\" * 8192)\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n    with pytest.raises(aiohttp.ClientResponseError):\n        await client.get(\"/\")\n\n\nasync def test_max_line_size_session_explicit(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(status=200, reason=\"x\" * 8191)\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app, max_line_size=8191)\n\n    async with await client.get(\"/\") as resp:\n        assert resp.reason == \"x\" * 8191\n\n\nasync def test_max_line_size_request_explicit(aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response(status=200, reason=\"x\" * 8191)\n\n    app = web.Application()\n    app.add_routes([web.get(\"/\", handler)])\n\n    client = await aiohttp_client(app)\n\n    async with await client.get(\"/\", max_line_size=8191) as resp:\n        assert resp.reason == \"x\" * 8191\n\n\nasync def test_rejected_upload(\n    aiohttp_client: AiohttpClient, tmp_path: pathlib.Path\n) -> None:\n    async def ok_handler(request: web.Request) -> web.Response:\n        return web.Response()\n\n    async def not_ok_handler(request):\n        raise web.HTTPBadRequest()\n\n    app = web.Application()\n    app.router.add_get(\"/ok\", ok_handler)\n    app.router.add_post(\"/not_ok\", not_ok_handler)\n    client = await aiohttp_client(app)\n\n    file_size_bytes = 1024 * 1024\n    file_path = tmp_path / \"uploaded.txt\"\n    file_path.write_text(\"0\" * file_size_bytes, encoding=\"utf8\")\n\n    with open(file_path, \"rb\") as file:\n        data = {\"file\": file}\n        async with client.post(\"/not_ok\", data=data) as resp_not_ok:\n            assert resp_not_ok.status == 400\n\n    async with client.get(\"/ok\", timeout=aiohttp.ClientTimeout(total=1)) as resp_ok:\n        assert resp_ok.status == 200\n\n\n@pytest.mark.parametrize(\n    (\"value\", \"exc_type\"),\n    [(42, TypeError), (\"InvalidUrl\", InvalidURL)],\n)\nasync def test_request_with_wrong_proxy(\n    aiohttp_client: AiohttpClient, value: Any, exc_type: Type[Exception]\n) -> None:\n    app = web.Application()\n    session = await aiohttp_client(app)\n\n    with pytest.raises(exc_type):\n        await session.get(\"/\", proxy=value)  # type: ignore[arg-type]\n\n\nasync def test_raise_for_status_is_none(aiohttp_client: AiohttpClient) -> None:\n    async def handler(_: web.Request) -> web.Response:\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n    session = await aiohttp_client(app, raise_for_status=None)  # type: ignore[arg-type]\n\n    await session.get(\"/\")\n\n\nasync def test_exception_when_read_outside_of_session(\n    aiohttp_server: AiohttpServer,\n) -> None:\n    async def handler(request: web.Request) -> web.Response:\n        return web.Response(body=b\"1\" * 1000000)\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n\n    server = await aiohttp_server(app)\n    async with aiohttp.ClientSession() as sess:\n        resp = await sess.get(server.make_url(\"/\"))\n\n    with pytest.raises(RuntimeError, match=\"Connection closed\"):\n        await resp.read()\n",
        "import asyncio\nimport base64\nimport os\nimport socket\nimport ssl\nimport sys\nfrom hashlib import md5, sha1, sha256\nfrom pathlib import Path\nfrom tempfile import TemporaryDirectory\nfrom typing import Any\nfrom unittest import mock\nfrom uuid import uuid4\n\nimport pytest\n\nfrom aiohttp.http import WS_KEY\nfrom aiohttp.test_utils import loop_context\n\ntry:\n    import trustme\n\n    # Check if the CA is available in runtime, MacOS on Py3.10 fails somehow\n    trustme.CA()\n\n    TRUSTME: bool = True\nexcept ImportError:\n    TRUSTME = False\n\npytest_plugins = [\"aiohttp.pytest_plugin\", \"pytester\"]\n\nIS_HPUX = sys.platform.startswith(\"hp-ux\")\nIS_LINUX = sys.platform.startswith(\"linux\")\n\n\n@pytest.fixture\ndef tls_certificate_authority():\n    if not TRUSTME:\n        pytest.xfail(\"trustme is not supported\")\n    return trustme.CA()\n\n\n@pytest.fixture\ndef tls_certificate(tls_certificate_authority):\n    return tls_certificate_authority.issue_cert(\n        \"localhost\",\n        \"xn--prklad-4va.localhost\",\n        \"127.0.0.1\",\n        \"::1\",\n    )\n\n\n@pytest.fixture\ndef ssl_ctx(tls_certificate):\n    ssl_ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)\n    tls_certificate.configure_cert(ssl_ctx)\n    return ssl_ctx\n\n\n@pytest.fixture\ndef client_ssl_ctx(tls_certificate_authority):\n    ssl_ctx = ssl.create_default_context(purpose=ssl.Purpose.SERVER_AUTH)\n    tls_certificate_authority.configure_trust(ssl_ctx)\n    return ssl_ctx\n\n\n@pytest.fixture\ndef tls_ca_certificate_pem_path(tls_certificate_authority):\n    with tls_certificate_authority.cert_pem.tempfile() as ca_cert_pem:\n        yield ca_cert_pem\n\n\n@pytest.fixture\ndef tls_certificate_pem_path(tls_certificate):\n    with tls_certificate.private_key_and_cert_chain_pem.tempfile() as cert_pem:\n        yield cert_pem\n\n\n@pytest.fixture\ndef tls_certificate_pem_bytes(tls_certificate):\n    return tls_certificate.cert_chain_pems[0].bytes()\n\n\n@pytest.fixture\ndef tls_certificate_fingerprint_sha256(tls_certificate_pem_bytes):\n    tls_cert_der = ssl.PEM_cert_to_DER_cert(tls_certificate_pem_bytes.decode())\n    return sha256(tls_cert_der).digest()\n\n\n@pytest.fixture\ndef unix_sockname(tmp_path, tmp_path_factory):\n    \"\"\"Generate an fs path to the UNIX domain socket for testing.\n\n    N.B. Different OS kernels have different fs path length limitations\n    for it. For Linux, it's 108, for HP-UX it's 92 (or higher) depending\n    on its version. For for most of the BSDs (Open, Free, macOS) it's\n    mostly 104 but sometimes it can be down to 100.\n\n    Ref: https://github.com/aio-libs/aiohttp/issues/3572\n    \"\"\"\n    if not hasattr(socket, \"AF_UNIX\"):\n        pytest.skip(\"requires UNIX sockets\")\n\n    max_sock_len = 92 if IS_HPUX else 108 if IS_LINUX else 100\n    \"\"\"Amount of bytes allocated for the UNIX socket path by OS kernel.\n\n    Ref: https://unix.stackexchange.com/a/367012/27133\n    \"\"\"\n\n    sock_file_name = \"unix.sock\"\n    unique_prefix = f\"{uuid4()!s}-\"\n    unique_prefix_len = len(unique_prefix.encode())\n\n    root_tmp_dir = Path(\"/tmp\").resolve()\n    os_tmp_dir = Path(os.getenv(\"TMPDIR\", \"/tmp\")).resolve()\n    original_base_tmp_path = Path(\n        str(tmp_path_factory.getbasetemp()),\n    ).resolve()\n\n    original_base_tmp_path_hash = md5(\n        str(original_base_tmp_path).encode(),\n    ).hexdigest()\n\n    def make_tmp_dir(base_tmp_dir):\n        return TemporaryDirectory(\n            dir=str(base_tmp_dir),\n            prefix=\"pt-\",\n            suffix=f\"-{original_base_tmp_path_hash!s}\",\n        )\n\n    def assert_sock_fits(sock_path):\n        sock_path_len = len(sock_path.encode())\n        # exit-check to verify that it's correct and simplify debugging\n        # in the future\n        assert sock_path_len <= max_sock_len, (\n            \"Suggested UNIX socket ({sock_path}) is {sock_path_len} bytes \"\n            \"long but the current kernel only has {max_sock_len} bytes \"\n            \"allocated to hold it so it must be shorter. \"\n            \"See https://github.com/aio-libs/aiohttp/issues/3572 \"\n            \"for more info.\"\n        ).format_map(locals())\n\n    paths = original_base_tmp_path, os_tmp_dir, root_tmp_dir\n    unique_paths = [p for n, p in enumerate(paths) if p not in paths[:n]]\n    paths_num = len(unique_paths)\n\n    for num, tmp_dir_path in enumerate(paths, 1):\n        with make_tmp_dir(tmp_dir_path) as tmpd:\n            tmpd = Path(tmpd).resolve()\n            sock_path = str(tmpd / sock_file_name)\n            sock_path_len = len(sock_path.encode())\n\n            if num >= paths_num:\n                # exit-check to verify that it's correct and simplify\n                # debugging in the future\n                assert_sock_fits(sock_path)\n\n            if sock_path_len <= max_sock_len:\n                if max_sock_len - sock_path_len >= unique_prefix_len:\n                    # If we're lucky to have extra space in the path,\n                    # let's also make it more unique\n                    sock_path = str(tmpd / \"\".join((unique_prefix, sock_file_name)))\n                    # Double-checking it:\n                    assert_sock_fits(sock_path)\n                yield sock_path\n                return\n\n\n@pytest.fixture\ndef pipe_name():\n    name = rf\"\\\\.\\pipe\\{uuid4().hex}\"\n    return name\n\n\n@pytest.fixture\ndef create_mocked_conn(loop: Any):\n    def _proto_factory(conn_closing_result=None, **kwargs):\n        proto = mock.Mock(**kwargs)\n        proto.closed = loop.create_future()\n        proto.closed.set_result(conn_closing_result)\n        return proto\n\n    yield _proto_factory\n\n\n@pytest.fixture\ndef selector_loop():\n    policy = asyncio.WindowsSelectorEventLoopPolicy()\n    asyncio.set_event_loop_policy(policy)\n\n    with loop_context(policy.new_event_loop) as _loop:\n        asyncio.set_event_loop(_loop)\n        yield _loop\n\n\n@pytest.fixture\ndef netrc_contents(\n    tmp_path: Path,\n    monkeypatch: pytest.MonkeyPatch,\n    request: pytest.FixtureRequest,\n):\n    \"\"\"\n    Prepare :file:`.netrc` with given contents.\n\n    Monkey-patches :envvar:`NETRC` to point to created file.\n    \"\"\"\n    netrc_contents = getattr(request, \"param\", None)\n\n    netrc_file_path = tmp_path / \".netrc\"\n    if netrc_contents is not None:\n        netrc_file_path.write_text(netrc_contents)\n\n    monkeypatch.setenv(\"NETRC\", str(netrc_file_path))\n\n    return netrc_file_path\n\n\n@pytest.fixture\ndef start_connection():\n    with mock.patch(\n        \"aiohttp.connector.aiohappyeyeballs.start_connection\",\n        autospec=True,\n        spec_set=True,\n    ) as start_connection_mock:\n        yield start_connection_mock\n\n\n@pytest.fixture\ndef key_data():\n    return os.urandom(16)\n\n\n@pytest.fixture\ndef key(key_data: Any):\n    return base64.b64encode(key_data)\n\n\n@pytest.fixture\ndef ws_key(key: Any):\n    return base64.b64encode(sha1(key + WS_KEY).digest()).decode()\n"
    ],
    "test_file_names": [
        "test_1.py",
        "conftest.py"
    ],
    "setup_res_code": 0,
    "setup_res_stdout": "re-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/requirements/cython.txt\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/tools/gen.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/hdrs.py\n./tools/gen.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/_helpers.pyx\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/_http_parser.pyx\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/_http_writer.pyx\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/_websocket.pyx\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/_helpers.pyi\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/_cparser.pxd\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/_find_header.pxd\ncython -3 -o aiohttp/_helpers.c aiohttp/_helpers.pyx -I aiohttp -Werror\ncython -3 -o aiohttp/_http_parser.c aiohttp/_http_parser.pyx -I aiohttp -Werror\ncython -3 -o aiohttp/_http_writer.c aiohttp/_http_writer.pyx -I aiohttp -Werror\ncython -3 -o aiohttp/_websocket.c aiohttp/_websocket.pyx -I aiohttp -Werror\ncd vendor/llhttp; npm ci\n\n> llhttp@9.2.1 prepare\n> npm run clean && npm run build-ts\n\n\n> llhttp@9.2.1 clean\n> rm -rf lib && rm -rf test/tmp\n\n\n> llhttp@9.2.1 build-ts\n> tsc\n\n\nadded 213 packages, and audited 214 packages in 5s\n\n41 packages are looking for funding\n  run `npm fund` for details\n\n5 vulnerabilities (3 moderate, 2 high)\n\nTo address issues that do not require attention, run:\n  npm audit fix\n\nSome issues need review, and may require choosing\na different dependency.\n\nRun `npm audit` for details.\nmake -C vendor/llhttp generate\nmake[1]: Entering directory '/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/vendor/llhttp'\nnpx ts-node bin/generate.ts\nmake[1]: Leaving directory '/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/vendor/llhttp'\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/__init__.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/abc.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/base_protocol.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/client.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/client_exceptions.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/client_proto.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/client_reqrep.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/client_ws.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/compression_utils.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/connector.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/cookiejar.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/formdata.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/helpers.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/http.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/http_exceptions.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/http_parser.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/http_websocket.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/http_writer.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/locks.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/log.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/multipart.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/payload.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/payload_streamer.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/pytest_plugin.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/resolver.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/streams.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/tcp_helpers.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/test_utils.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/tracing.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/typedefs.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/web.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/web_app.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/web_exceptions.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/web_fileresponse.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/web_log.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/web_middlewares.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/web_protocol.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/web_request.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/web_response.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/web_routedef.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/web_runner.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/web_server.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/web_urldispatcher.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/web_ws.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/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 39ms\nPrepared 1 package in 0.26ms\nInstalled 1 package in 11ms\n + pip==24.3.1\nResolved 2 packages in 9ms\nInstalled 2 packages in 36ms\n + cython==3.0.10\n + multidict==6.0.5\nResolved 96 packages in 47ms\nUninstalled 1 package in 8ms\nInstalled 95 packages in 146ms\n + aiodns==3.2.0\n + aiohappyeyeballs==2.3.4\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.2.0\n + babel==2.12.1\n + blockdiag==3.0.0\n + brotli==1.1.0\n + build==1.0.3\n + certifi==2023.7.22\n + cffi==1.17.0\n + cfgv==3.3.1\n + charset-normalizer==3.2.0\n + cherry-picker==2.2.0\n + click==8.1.6\n + coverage==7.6.0\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.5.1\n + frozenlist==1.4.1\n + funcparserlib==1.0.1\n + gidgethub==5.3.0\n + gunicorn==22.0.0\n + identify==2.5.26\n + idna==3.4\n + imagesize==1.4.1\n + importlib-metadata==7.0.0\n + importlib-resources==6.1.1\n + incremental==22.10.0\n + iniconfig==2.0.0\n + jinja2==3.1.2\n + markupsafe==2.1.3\n + mypy==1.11.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.4.1\n + platformdirs==3.10.0\n + pluggy==1.5.0\n + pre-commit==3.5.0\n + proxy-py==2.4.4\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==8.3.2\n + pytest-cov==5.0.0\n + pytest-mock==3.14.0\n + python-dateutil==2.8.2\n + python-on-whales==0.72.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.19.0\n + snowballstemmer==2.2.0\n + sphinx==7.1.2\n + sphinxcontrib-applehelp==1.0.4\n + sphinxcontrib-blockdiag==3.0.0\n + sphinxcontrib-devhelp==1.0.2\n + sphinxcontrib-htmlhelp==2.0.1\n + sphinxcontrib-jsmath==1.0.1\n + sphinxcontrib-qthelp==1.0.3\n + sphinxcontrib-serializinghtml==1.1.5\n + sphinxcontrib-towncrier==0.4.0a0\n + tomli==2.0.1\n + towncrier==23.11.0\n + tqdm==4.65.0\n + trustme==1.1.0\n + typer==0.9.0\n + typing-extensions==4.11.0\n + uritemplate==4.1.1\n + urllib3==2.0.4\n + uvloop==0.19.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.6\n + zipp==3.17.0\nwarning: `yarl==1.9.6` is yanked (reason: \"Performance regression: https://github.com/aio-libs/yarl/pull/1198\")\nResolved 9 packages in 1.69s\nPrepared 1 package in 17.19s\nInstalled 1 package in 0.54ms\n + aiohttp==3.10.6.dev0 (from file:///home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860)\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.25.1\n",
    "new_commit_res_code": 0,
    "new_commit_res_stdout": "============================= test session starts ==============================\nplatform linux -- Python 3.9.21, pytest-8.3.2, pluggy-1.5.0 -- /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/.venv/bin/python\ncachedir: .pytest_cache\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860\nconfigfile: setup.cfg\nplugins: cov-5.0.0, mock-3.14.0, asyncio-0.25.1\nasyncio: mode=strict, asyncio_default_fixture_loop_scope=None\ncollecting ... collected 223 items\n\nr2e_tests/test_1.py::test_keepalive_two_requests_success[pyloop] PASSED  [  0%]\nr2e_tests/test_1.py::test_keepalive_after_head_requests_success[pyloop] PASSED [  0%]\nr2e_tests/test_1.py::test_keepalive_after_empty_body_status[pyloop-101] PASSED [  1%]\nr2e_tests/test_1.py::test_keepalive_after_empty_body_status[pyloop-204] PASSED [  1%]\nr2e_tests/test_1.py::test_keepalive_after_empty_body_status[pyloop-304] PASSED [  2%]\nr2e_tests/test_1.py::test_keepalive_after_empty_body_status_stream_response[pyloop-101] PASSED [  2%]\nr2e_tests/test_1.py::test_keepalive_after_empty_body_status_stream_response[pyloop-204] PASSED [  3%]\nr2e_tests/test_1.py::test_keepalive_after_empty_body_status_stream_response[pyloop-304] PASSED [  3%]\nr2e_tests/test_1.py::test_keepalive_response_released[pyloop] PASSED     [  4%]\nr2e_tests/test_1.py::test_upgrade_connection_not_released_after_read[pyloop] PASSED [  4%]\nr2e_tests/test_1.py::test_keepalive_server_force_close_connection[pyloop] PASSED [  4%]\nr2e_tests/test_1.py::test_keepalive_timeout_async_sleep PASSED           [  5%]\nr2e_tests/test_1.py::test_keepalive_timeout_sync_sleep PASSED            [  5%]\nr2e_tests/test_1.py::test_release_early[pyloop] PASSED                   [  6%]\nr2e_tests/test_1.py::test_HTTP_304[pyloop] PASSED                        [  6%]\nr2e_tests/test_1.py::test_stream_request_on_server_eof[pyloop] PASSED    [  7%]\nr2e_tests/test_1.py::test_stream_request_on_server_eof_nested[pyloop] PASSED [  7%]\nr2e_tests/test_1.py::test_HTTP_304_WITH_BODY[pyloop] PASSED              [  8%]\nr2e_tests/test_1.py::test_auto_header_user_agent[pyloop] PASSED          [  8%]\nr2e_tests/test_1.py::test_skip_auto_headers_user_agent[pyloop] PASSED    [  8%]\nr2e_tests/test_1.py::test_skip_default_auto_headers_user_agent[pyloop] PASSED [  9%]\nr2e_tests/test_1.py::test_skip_auto_headers_content_type[pyloop] PASSED  [  9%]\nr2e_tests/test_1.py::test_post_data_bytesio[pyloop] PASSED               [ 10%]\nr2e_tests/test_1.py::test_post_data_with_bytesio_file[pyloop] PASSED     [ 10%]\nr2e_tests/test_1.py::test_post_data_stringio[pyloop] PASSED              [ 11%]\nr2e_tests/test_1.py::test_post_data_textio_encoding[pyloop] PASSED       [ 11%]\nr2e_tests/test_1.py::test_post_data_zipfile_filelike[pyloop] PASSED      [ 12%]\nr2e_tests/test_1.py::test_post_data_tarfile_filelike[pyloop] PASSED      [ 12%]\nr2e_tests/test_1.py::test_ssl_client[pyloop] PASSED                      [ 13%]\nr2e_tests/test_1.py::test_tcp_connector_fingerprint_ok[pyloop] PASSED    [ 13%]\nr2e_tests/test_1.py::test_tcp_connector_fingerprint_fail[pyloop] PASSED  [ 13%]\nr2e_tests/test_1.py::test_format_task_get[pyloop] PASSED                 [ 14%]\nr2e_tests/test_1.py::test_str_params[pyloop] PASSED                      [ 14%]\nr2e_tests/test_1.py::test_drop_params_on_redirect[pyloop] PASSED         [ 15%]\nr2e_tests/test_1.py::test_drop_fragment_on_redirect[pyloop] PASSED       [ 15%]\nr2e_tests/test_1.py::test_drop_fragment[pyloop] PASSED                   [ 16%]\nr2e_tests/test_1.py::test_history[pyloop] PASSED                         [ 16%]\nr2e_tests/test_1.py::test_keepalive_closed_by_server[pyloop] PASSED      [ 17%]\nr2e_tests/test_1.py::test_wait_for[pyloop] PASSED                        [ 17%]\nr2e_tests/test_1.py::test_raw_headers[pyloop] PASSED                     [ 17%]\nr2e_tests/test_1.py::test_host_header_first[pyloop] PASSED               [ 18%]\nr2e_tests/test_1.py::test_empty_header_values[pyloop] PASSED             [ 18%]\nr2e_tests/test_1.py::test_204_with_gzipped_content_encoding[pyloop] PASSED [ 19%]\nr2e_tests/test_1.py::test_timeout_on_reading_headers[pyloop] PASSED      [ 19%]\nr2e_tests/test_1.py::test_timeout_on_conn_reading_headers[pyloop] PASSED [ 20%]\nr2e_tests/test_1.py::test_timeout_on_session_read_timeout[pyloop] PASSED [ 20%]\nr2e_tests/test_1.py::test_read_timeout_between_chunks[pyloop] PASSED     [ 21%]\nr2e_tests/test_1.py::test_read_timeout_on_reading_chunks[pyloop] PASSED  [ 21%]\nr2e_tests/test_1.py::test_read_timeout_on_write[pyloop] PASSED           [ 21%]\nr2e_tests/test_1.py::test_timeout_on_reading_data[pyloop] PASSED         [ 22%]\nr2e_tests/test_1.py::test_timeout_none[pyloop] PASSED                    [ 22%]\nr2e_tests/test_1.py::test_readline_error_on_conn_close[pyloop] PASSED    [ 23%]\nr2e_tests/test_1.py::test_no_error_on_conn_close_if_eof[pyloop] PASSED   [ 23%]\nr2e_tests/test_1.py::test_error_not_overwrote_on_conn_close[pyloop] PASSED [ 24%]\nr2e_tests/test_1.py::test_HTTP_200_OK_METHOD[pyloop] PASSED              [ 24%]\nr2e_tests/test_1.py::test_HTTP_200_OK_METHOD_connector[pyloop] PASSED    [ 25%]\nr2e_tests/test_1.py::test_HTTP_302_REDIRECT_GET[pyloop] PASSED           [ 25%]\nr2e_tests/test_1.py::test_HTTP_302_REDIRECT_HEAD[pyloop] PASSED          [ 26%]\nr2e_tests/test_1.py::test_HTTP_302_REDIRECT_NON_HTTP[pyloop] PASSED      [ 26%]\nr2e_tests/test_1.py::test_HTTP_302_REDIRECT_POST[pyloop] PASSED          [ 26%]\nr2e_tests/test_1.py::test_HTTP_302_REDIRECT_POST_with_content_length_hdr[pyloop] PASSED [ 27%]\nr2e_tests/test_1.py::test_HTTP_307_REDIRECT_POST[pyloop] PASSED          [ 27%]\nr2e_tests/test_1.py::test_HTTP_308_PERMANENT_REDIRECT_POST[pyloop] PASSED [ 28%]\nr2e_tests/test_1.py::test_HTTP_302_max_redirects[pyloop] PASSED          [ 28%]\nr2e_tests/test_1.py::test_HTTP_200_GET_WITH_PARAMS[pyloop] PASSED        [ 29%]\nr2e_tests/test_1.py::test_HTTP_200_GET_WITH_MultiDict_PARAMS[pyloop] PASSED [ 29%]\nr2e_tests/test_1.py::test_HTTP_200_GET_WITH_MIXED_PARAMS[pyloop] PASSED  [ 30%]\nr2e_tests/test_1.py::test_POST_DATA[pyloop] PASSED                       [ 30%]\nr2e_tests/test_1.py::test_POST_DATA_with_explicit_formdata[pyloop] PASSED [ 30%]\nr2e_tests/test_1.py::test_POST_DATA_with_charset[pyloop] PASSED          [ 31%]\nr2e_tests/test_1.py::test_POST_DATA_formdats_with_charset[pyloop] PASSED [ 31%]\nr2e_tests/test_1.py::test_POST_DATA_with_charset_post[pyloop] PASSED     [ 32%]\nr2e_tests/test_1.py::test_POST_MultiDict[pyloop] PASSED                  [ 32%]\nr2e_tests/test_1.py::test_POST_DATA_DEFLATE[pyloop] PASSED               [ 33%]\nr2e_tests/test_1.py::test_POST_FILES[pyloop] PASSED                      [ 33%]\nr2e_tests/test_1.py::test_POST_FILES_DEFLATE[pyloop] PASSED              [ 34%]\nr2e_tests/test_1.py::test_POST_bytes[pyloop] PASSED                      [ 34%]\nr2e_tests/test_1.py::test_POST_bytes_too_large[pyloop] PASSED            [ 34%]\nr2e_tests/test_1.py::test_POST_FILES_STR[pyloop] PASSED                  [ 35%]\nr2e_tests/test_1.py::test_POST_FILES_STR_SIMPLE[pyloop] PASSED           [ 35%]\nr2e_tests/test_1.py::test_POST_FILES_LIST[pyloop] PASSED                 [ 36%]\nr2e_tests/test_1.py::test_POST_FILES_CT[pyloop] PASSED                   [ 36%]\nr2e_tests/test_1.py::test_POST_FILES_SINGLE[pyloop] PASSED               [ 37%]\nr2e_tests/test_1.py::test_POST_FILES_SINGLE_content_disposition[pyloop] PASSED [ 37%]\nr2e_tests/test_1.py::test_POST_FILES_SINGLE_BINARY[pyloop] PASSED        [ 38%]\nr2e_tests/test_1.py::test_POST_FILES_IO[pyloop] PASSED                   [ 38%]\nr2e_tests/test_1.py::test_POST_FILES_IO_WITH_PARAMS[pyloop] PASSED       [ 39%]\nr2e_tests/test_1.py::test_POST_FILES_WITH_DATA[pyloop] PASSED            [ 39%]\nr2e_tests/test_1.py::test_POST_STREAM_DATA[pyloop] PASSED                [ 39%]\nr2e_tests/test_1.py::test_POST_STREAM_DATA_no_params[pyloop] PASSED      [ 40%]\nr2e_tests/test_1.py::test_json[pyloop] PASSED                            [ 40%]\nr2e_tests/test_1.py::test_json_custom[pyloop] PASSED                     [ 41%]\nr2e_tests/test_1.py::test_expect_continue[pyloop] PASSED                 [ 41%]\nr2e_tests/test_1.py::test_encoding_deflate[pyloop] PASSED                [ 42%]\nr2e_tests/test_1.py::test_encoding_deflate_nochunk[pyloop] PASSED        [ 42%]\nr2e_tests/test_1.py::test_encoding_gzip[pyloop] PASSED                   [ 43%]\nr2e_tests/test_1.py::test_encoding_gzip_write_by_chunks[pyloop] PASSED   [ 43%]\nr2e_tests/test_1.py::test_encoding_gzip_nochunk[pyloop] PASSED           [ 43%]\nr2e_tests/test_1.py::test_bad_payload_compression[pyloop] PASSED         [ 44%]\nr2e_tests/test_1.py::test_bad_payload_chunked_encoding[pyloop] PASSED    [ 44%]\nr2e_tests/test_1.py::test_no_payload_304_with_chunked_encoding[pyloop] PASSED [ 45%]\nr2e_tests/test_1.py::test_head_request_with_chunked_encoding[pyloop] PASSED [ 45%]\nr2e_tests/test_1.py::test_no_payload_200_with_chunked_encoding[pyloop] PASSED [ 46%]\nr2e_tests/test_1.py::test_bad_payload_content_length[pyloop] PASSED      [ 46%]\nr2e_tests/test_1.py::test_payload_content_length_by_chunks[pyloop] PASSED [ 47%]\nr2e_tests/test_1.py::test_chunked[pyloop] PASSED                         [ 47%]\nr2e_tests/test_1.py::test_shortcuts[pyloop] PASSED                       [ 47%]\nr2e_tests/test_1.py::test_cookies[pyloop] PASSED                         [ 48%]\nr2e_tests/test_1.py::test_cookies_per_request[pyloop] PASSED             [ 48%]\nr2e_tests/test_1.py::test_cookies_redirect[pyloop] PASSED                [ 49%]\nr2e_tests/test_1.py::test_cookies_on_empty_session_jar[pyloop] PASSED    [ 49%]\nr2e_tests/test_1.py::test_morsel_with_attributes[pyloop] PASSED          [ 50%]\nr2e_tests/test_1.py::test_set_cookies[pyloop] PASSED                     [ 50%]\nr2e_tests/test_1.py::test_set_cookies_expired[pyloop] PASSED             [ 51%]\nr2e_tests/test_1.py::test_set_cookies_max_age[pyloop] PASSED             [ 51%]\nr2e_tests/test_1.py::test_set_cookies_max_age_overflow[pyloop] PASSED    [ 52%]\nr2e_tests/test_1.py::test_request_conn_error PASSED                      [ 52%]\nr2e_tests/test_1.py::test_broken_connection[pyloop] XFAIL                [ 52%]\nr2e_tests/test_1.py::test_broken_connection_2[pyloop] PASSED             [ 53%]\nr2e_tests/test_1.py::test_custom_headers[pyloop] PASSED                  [ 53%]\nr2e_tests/test_1.py::test_redirect_to_absolute_url[pyloop] PASSED        [ 54%]\nr2e_tests/test_1.py::test_redirect_without_location_header[pyloop] PASSED [ 54%]\nr2e_tests/test_1.py::test_chunked_deprecated[pyloop] PASSED              [ 55%]\nr2e_tests/test_1.py::test_invalid_and_non_http_url[http://:/-http://:/-InvalidUrlClientError] PASSED [ 55%]\nr2e_tests/test_1.py::test_invalid_and_non_http_url[http://example.org:non_int_port/-http://example.org:non_int_port/-InvalidUrlClientError] PASSED [ 56%]\nr2e_tests/test_1.py::test_invalid_and_non_http_url[http:/-http:///-InvalidUrlClientError] PASSED [ 56%]\nr2e_tests/test_1.py::test_invalid_and_non_http_url[http:/example.com-http:///example.com-InvalidUrlClientError] PASSED [ 56%]\nr2e_tests/test_1.py::test_invalid_and_non_http_url[http:///example.com-http:///example.com-InvalidUrlClientError] PASSED [ 57%]\nr2e_tests/test_1.py::test_invalid_and_non_http_url[call:+380123456789-call:\\\\+380123456789-NonHttpUrlClientError] PASSED [ 57%]\nr2e_tests/test_1.py::test_invalid_and_non_http_url[skype:handle-skype:handle-NonHttpUrlClientError] PASSED [ 58%]\nr2e_tests/test_1.py::test_invalid_and_non_http_url[slack://instance/room-slack://instance/room-NonHttpUrlClientError] PASSED [ 58%]\nr2e_tests/test_1.py::test_invalid_and_non_http_url[steam:code-steam:code-NonHttpUrlClientError] PASSED [ 59%]\nr2e_tests/test_1.py::test_invalid_and_non_http_url[twitter://handle-twitter://handle-NonHttpUrlClientError] PASSED [ 59%]\nr2e_tests/test_1.py::test_invalid_and_non_http_url[bluesky://profile/d:i:d-bluesky://profile/d:i:d-NonHttpUrlClientError] PASSED [ 60%]\nr2e_tests/test_1.py::test_invalid_redirect_url[pyloop-http:/-http:///-InvalidUrlRedirectClientError] PASSED [ 60%]\nr2e_tests/test_1.py::test_invalid_redirect_url[pyloop-http:/example.com-http:///example.com-InvalidUrlRedirectClientError] PASSED [ 60%]\nr2e_tests/test_1.py::test_invalid_redirect_url[pyloop-http:///example.com-http:///example.com-InvalidUrlRedirectClientError] PASSED [ 61%]\nr2e_tests/test_1.py::test_invalid_redirect_url[pyloop-http://:/-http://:/-InvalidUrlRedirectClientError] PASSED [ 61%]\nr2e_tests/test_1.py::test_invalid_redirect_url[pyloop-http://example.org:non_int_port/-http://example.org:non_int_port/-InvalidUrlRedirectClientError] PASSED [ 62%]\nr2e_tests/test_1.py::test_invalid_redirect_url[pyloop-call:+380123456789-call:\\\\+380123456789-NonHttpUrlRedirectClientError] PASSED [ 62%]\nr2e_tests/test_1.py::test_invalid_redirect_url[pyloop-skype:handle-skype:handle-NonHttpUrlRedirectClientError] PASSED [ 63%]\nr2e_tests/test_1.py::test_invalid_redirect_url[pyloop-slack://instance/room-slack://instance/room-NonHttpUrlRedirectClientError] PASSED [ 63%]\nr2e_tests/test_1.py::test_invalid_redirect_url[pyloop-steam:code-steam:code-NonHttpUrlRedirectClientError] PASSED [ 64%]\nr2e_tests/test_1.py::test_invalid_redirect_url[pyloop-twitter://handle-twitter://handle-NonHttpUrlRedirectClientError] PASSED [ 64%]\nr2e_tests/test_1.py::test_invalid_redirect_url[pyloop-bluesky://profile/d:i:d-bluesky://profile/d:i:d-NonHttpUrlRedirectClientError] PASSED [ 65%]\nr2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-http:/-http:///-InvalidUrlRedirectClientError] PASSED [ 65%]\nr2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-http:/example.com-http:///example.com-InvalidUrlRedirectClientError] PASSED [ 65%]\nr2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-http:///example.com-http:///example.com-InvalidUrlRedirectClientError] PASSED [ 66%]\nr2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-http://:/-http://:/-InvalidUrlRedirectClientError] PASSED [ 66%]\nr2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-http://example.org:non_int_port/-http://example.org:non_int_port/-InvalidUrlRedirectClientError] PASSED [ 67%]\nr2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-call:+380123456789-call:\\\\+380123456789-NonHttpUrlRedirectClientError] PASSED [ 67%]\nr2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-skype:handle-skype:handle-NonHttpUrlRedirectClientError] PASSED [ 68%]\nr2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-slack://instance/room-slack://instance/room-NonHttpUrlRedirectClientError] PASSED [ 68%]\nr2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-steam:code-steam:code-NonHttpUrlRedirectClientError] PASSED [ 69%]\nr2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-twitter://handle-twitter://handle-NonHttpUrlRedirectClientError] PASSED [ 69%]\nr2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-bluesky://profile/d:i:d-bluesky://profile/d:i:d-NonHttpUrlRedirectClientError] PASSED [ 69%]\nr2e_tests/test_1.py::test_ok_from_status[pyloop-200-True] PASSED         [ 70%]\nr2e_tests/test_1.py::test_ok_from_status[pyloop-201-True] PASSED         [ 70%]\nr2e_tests/test_1.py::test_ok_from_status[pyloop-301-True] PASSED         [ 71%]\nr2e_tests/test_1.py::test_ok_from_status[pyloop-400-False] PASSED        [ 71%]\nr2e_tests/test_1.py::test_ok_from_status[pyloop-403-False] PASSED        [ 72%]\nr2e_tests/test_1.py::test_ok_from_status[pyloop-500-False] PASSED        [ 72%]\nr2e_tests/test_1.py::test_raise_for_status[pyloop] PASSED                [ 73%]\nr2e_tests/test_1.py::test_raise_for_status_per_request[pyloop] PASSED    [ 73%]\nr2e_tests/test_1.py::test_raise_for_status_disable_per_request[pyloop] PASSED [ 73%]\nr2e_tests/test_1.py::test_request_raise_for_status_default[pyloop] PASSED [ 74%]\nr2e_tests/test_1.py::test_request_raise_for_status_disabled[pyloop] PASSED [ 74%]\nr2e_tests/test_1.py::test_request_raise_for_status_enabled[pyloop] PASSED [ 75%]\nr2e_tests/test_1.py::test_session_raise_for_status_coro[pyloop] PASSED   [ 75%]\nr2e_tests/test_1.py::test_request_raise_for_status_coro[pyloop] PASSED   [ 76%]\nr2e_tests/test_1.py::test_invalid_idna PASSED                            [ 76%]\nr2e_tests/test_1.py::test_creds_in_auth_and_url PASSED                   [ 77%]\nr2e_tests/test_1.py::test_drop_auth_on_redirect_to_other_host[pyloop-entirely different hosts] PASSED [ 77%]\nr2e_tests/test_1.py::test_drop_auth_on_redirect_to_other_host[pyloop-http -> https] PASSED [ 78%]\nr2e_tests/test_1.py::test_drop_auth_on_redirect_to_other_host[pyloop-https -> http] PASSED [ 78%]\nr2e_tests/test_1.py::test_async_with_session PASSED                      [ 78%]\nr2e_tests/test_1.py::test_session_close_awaitable PASSED                 [ 79%]\nr2e_tests/test_1.py::test_close_resp_on_error_async_with_session[pyloop] PASSED [ 79%]\nr2e_tests/test_1.py::test_release_resp_on_normal_exit_from_cm[pyloop] PASSED [ 80%]\nr2e_tests/test_1.py::test_non_close_detached_session_on_error_cm[pyloop] PASSED [ 80%]\nr2e_tests/test_1.py::test_close_detached_session_on_non_existing_addr PASSED [ 81%]\nr2e_tests/test_1.py::test_aiohttp_request_context_manager[pyloop] PASSED [ 81%]\nr2e_tests/test_1.py::test_aiohttp_request_ctx_manager_close_sess_on_error[pyloop] PASSED [ 82%]\nr2e_tests/test_1.py::test_aiohttp_request_ctx_manager_not_found PASSED   [ 82%]\nr2e_tests/test_1.py::test_yield_from_in_session_request[pyloop] PASSED   [ 82%]\nr2e_tests/test_1.py::test_close_context_manager[pyloop] PASSED           [ 83%]\nr2e_tests/test_1.py::test_session_auth[pyloop] PASSED                    [ 83%]\nr2e_tests/test_1.py::test_session_auth_override[pyloop] PASSED           [ 84%]\nr2e_tests/test_1.py::test_session_auth_header_conflict[pyloop] PASSED    [ 84%]\nr2e_tests/test_1.py::test_session_headers[pyloop] PASSED                 [ 85%]\nr2e_tests/test_1.py::test_session_headers_merge[pyloop] PASSED           [ 85%]\nr2e_tests/test_1.py::test_multidict_headers[pyloop] PASSED               [ 86%]\nr2e_tests/test_1.py::test_request_conn_closed[pyloop] PASSED             [ 86%]\nr2e_tests/test_1.py::test_dont_close_explicit_connector[pyloop] PASSED   [ 86%]\nr2e_tests/test_1.py::test_server_close_keepalive_connection PASSED       [ 87%]\nr2e_tests/test_1.py::test_handle_keepalive_on_closed_connection PASSED   [ 87%]\nr2e_tests/test_1.py::test_error_in_performing_request[pyloop] PASSED     [ 88%]\nr2e_tests/test_1.py::test_await_after_cancelling[pyloop] PASSED          [ 88%]\nr2e_tests/test_1.py::test_async_payload_generator[pyloop] PASSED         [ 89%]\nr2e_tests/test_1.py::test_read_from_closed_response[pyloop] PASSED       [ 89%]\nr2e_tests/test_1.py::test_read_from_closed_response2[pyloop] PASSED      [ 90%]\nr2e_tests/test_1.py::test_read_from_closed_content[pyloop] PASSED        [ 90%]\nr2e_tests/test_1.py::test_read_timeout[pyloop] PASSED                    [ 91%]\nr2e_tests/test_1.py::test_socket_timeout[pyloop] PASSED                  [ 91%]\nr2e_tests/test_1.py::test_read_timeout_closes_connection[pyloop] PASSED  [ 91%]\nr2e_tests/test_1.py::test_read_timeout_on_prepared_response[pyloop] PASSED [ 92%]\nr2e_tests/test_1.py::test_timeout_with_full_buffer[pyloop] PASSED        [ 92%]\nr2e_tests/test_1.py::test_read_bufsize_session_default[pyloop] PASSED    [ 93%]\nr2e_tests/test_1.py::test_read_bufsize_explicit[pyloop] PASSED           [ 93%]\nr2e_tests/test_1.py::test_http_empty_data_text[pyloop] PASSED            [ 94%]\nr2e_tests/test_1.py::test_max_field_size_session_default[pyloop] PASSED  [ 94%]\nr2e_tests/test_1.py::test_max_field_size_session_default_fail[pyloop] PASSED [ 95%]\nr2e_tests/test_1.py::test_max_field_size_session_explicit[pyloop] PASSED [ 95%]\nr2e_tests/test_1.py::test_max_field_size_request_explicit[pyloop] PASSED [ 95%]\nr2e_tests/test_1.py::test_max_line_size_session_default[pyloop] PASSED   [ 96%]\nr2e_tests/test_1.py::test_max_line_size_session_default_fail[pyloop] PASSED [ 96%]\nr2e_tests/test_1.py::test_max_line_size_session_explicit[pyloop] PASSED  [ 97%]\nr2e_tests/test_1.py::test_max_line_size_request_explicit[pyloop] PASSED  [ 97%]\nr2e_tests/test_1.py::test_rejected_upload[pyloop] PASSED                 [ 98%]\nr2e_tests/test_1.py::test_request_with_wrong_proxy[pyloop-42-TypeError] PASSED [ 98%]\nr2e_tests/test_1.py::test_request_with_wrong_proxy[pyloop-InvalidUrl-InvalidURL] PASSED [ 99%]\nr2e_tests/test_1.py::test_raise_for_status_is_none[pyloop] PASSED        [ 99%]\nr2e_tests/test_1.py::test_exception_when_read_outside_of_session[pyloop] PASSED [100%]\n\n==================================== PASSES ====================================\n______________________ test_keepalive_timeout_sync_sleep _______________________\n------------------------------ Captured log call -------------------------------\nERROR    asyncio:base_events.py:1753 Task exception was never retrieved\nfuture: <Task finished name='Task-116' coro=<RequestHandler.start() done, defined at /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/web_protocol.py:484> exception=AssertionError()>\nTraceback (most recent call last):\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/web_protocol.py\", line 527, in start\n    request = self._request_factory(message, payload, self, writer, handler)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/web_app.py\", line 479, in _make_request\n    return _cls(\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/web_request.py\", line 845, in __init__\n    super().__init__(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/web_request.py\", line 204, in __init__\n    assert transport is not None\nAssertionError\n__________________ test_readline_error_on_conn_close[pyloop] ___________________\n------------------------------ Captured log call -------------------------------\nERROR    asyncio:base_events.py:1753 Exception in callback test_readline_error_on_conn_close.<locals>.do_release() at /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/r2e_tests/test_1.py:1038\nhandle: <TimerHandle when=94818.635935624 test_readline_error_on_conn_close.<locals>.do_release() at /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/r2e_tests/test_1.py:1038>\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/asyncio/events.py\", line 80, in _run\n    self._context.run(self._callback, *self._args)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/r2e_tests/test_1.py\", line 1039, in do_release\n    loop.create_task(resp.release())\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/asyncio/base_events.py\", line 438, in create_task\n    task = tasks.Task(coro, loop=self, name=name)\nTypeError: a coroutine was expected, got <aiohttp.helpers.noop object at 0x7494497a4760>\n---------------------------- Captured log teardown -----------------------------\nERROR    asyncio:base_events.py:1753 Unclosed client session\nclient_session: <aiohttp.client.ClientSession object at 0x7494497a4ca0>\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                              97      2      0      0    98%\naiohttp/base_protocol.py                    67     28     22      5    49%\naiohttp/client.py                          545    117    196     23    76%\naiohttp/client_exceptions.py               154     35     20      3    74%\naiohttp/client_proto.py                    165     29     56     10    79%\naiohttp/client_reqrep.py                   695    135    300     64    76%\naiohttp/client_ws.py                       259    212     80      1    14%\naiohttp/compression_utils.py                70     15     14      1    71%\naiohttp/connector.py                       775    288    321     53    56%\naiohttp/cookiejar.py                       255     59    118     23    74%\naiohttp/formdata.py                         97     16     46      7    81%\naiohttp/hdrs.py                             90      0      0      0   100%\naiohttp/helpers.py                         501    173    172     25    61%\naiohttp/http.py                             11      0      2      0   100%\naiohttp/http_exceptions.py                  50     10      4      1    76%\naiohttp/http_parser.py                     504    349    208     11    24%\naiohttp/http_websocket.py                  393    287    152      0    20%\naiohttp/http_writer.py                     118     12     50      5    86%\naiohttp/locks.py                            24     10      4      0    50%\naiohttp/log.py                               7      0      0      0   100%\naiohttp/multipart.py                       623    292    266     48    46%\naiohttp/payload.py                         237     22     58     12    86%\naiohttp/payload_streamer.py                 31      1      4      0    97%\naiohttp/pytest_plugin.py                   162     47     42      7    69%\naiohttp/resolver.py                         80     39     26      4    44%\naiohttp/streams.py                         398    115    146     19    67%\naiohttp/tcp_helpers.py                      19      2      6      3    80%\naiohttp/test_utils.py                      315    110     50     11    61%\naiohttp/tracing.py                         191     17     32      0    92%\naiohttp/typedefs.py                         23      0      0      0   100%\naiohttp/web.py                             122     84     52      0    23%\naiohttp/web_app.py                         282     97     74     18    59%\naiohttp/web_exceptions.py                  157     16      8      3    87%\naiohttp/web_fileresponse.py                163    127     54      1    19%\naiohttp/web_log.py                         102     37     20      1    59%\naiohttp/web_middlewares.py                  55     37     20      0    24%\naiohttp/web_protocol.py                    354     95    155     48    66%\naiohttp/web_request.py                     445    180    138     21    53%\naiohttp/web_response.py                    479    119    220     53    69%\naiohttp/web_routedef.py                    100     37     10      1    62%\naiohttp/web_runner.py                      213     61     36     12    67%\naiohttp/web_server.py                       42      5     12      1    85%\naiohttp/web_urldispatcher.py               742    324    161     23    52%\naiohttp/web_ws.py                          382    310    132      1    15%\naiohttp/worker.py                          126    126     30      0     0%\ntests/conftest.py                          130    130     16      0     0%\ntests/test_base_protocol.py                198    198      2      0     0%\ntests/test_circular_imports.py              29     29     13      0     0%\ntests/test_classbasedview.py                39     39      0      0     0%\ntests/test_client_connection.py             94     94      2      0     0%\ntests/test_client_exceptions.py            199    199     14      0     0%\ntests/test_client_fingerprint.py            59     59      0      0     0%\ntests/test_client_functional.py           2459   2459     86      0     0%\ntests/test_client_proto.py                  99     99      0      0     0%\ntests/test_client_request.py               808    808     18      0     0%\ntests/test_client_response.py              466    466      4      0     0%\ntests/test_client_session.py               556    556     29      0     0%\ntests/test_client_ws.py                    486    486      2      0     0%\ntests/test_client_ws_functional.py         750    750     32      0     0%\ntests/test_connector.py                   1697   1697     82      0     0%\ntests/test_cookiejar.py                    350    350     24      0     0%\ntests/test_flowcontrol_streams.py          100    100      0      0     0%\ntests/test_formdata.py                      81     81      6      0     0%\ntests/test_helpers.py                      470    470     24      0     0%\ntests/test_http_exceptions.py              109    109     10      0     0%\ntests/test_http_parser.py                 1088   1088     66      0     0%\ntests/test_http_writer.py                  182    182     10      0     0%\ntests/test_imports.py                       34     34      6      0     0%\ntests/test_locks.py                         39     39      0      0     0%\ntests/test_loop.py                          36     36      0      0     0%\ntests/test_multipart.py                    826    826     32      0     0%\ntests/test_multipart_helpers.py            446    446      0      0     0%\ntests/test_payload.py                       95     95      0      0     0%\ntests/test_proxy.py                        301    301      0      0     0%\ntests/test_proxy_functional.py             459    459     18      0     0%\ntests/test_pytest_plugin.py                 27     27      0      0     0%\ntests/test_resolver.py                     193    193     20      0     0%\ntests/test_route_def.py                    210    210      0      0     0%\ntests/test_run_app.py                      563    563     30      0     0%\ntests/test_streams.py                     1076   1076     38      0     0%\ntests/test_tcp_helpers.py                   52     52      2      0     0%\ntests/test_test_utils.py                   244    244      6      0     0%\ntests/test_tracing.py                       48     48      0      0     0%\ntests/test_urldispatch.py                  851    851     24      0     0%\ntests/test_web_app.py                      454    454      6      0     0%\ntests/test_web_cli.py                       75     75      0      0     0%\ntests/test_web_exceptions.py               176    176     22      0     0%\ntests/test_web_functional.py              1552   1552     34      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                  507    507      8      0     0%\ntests/test_web_request_handler.py           42     42      0      0     0%\ntests/test_web_response.py                 885    885      6      0     0%\ntests/test_web_runner.py                   151    151      4      0     0%\ntests/test_web_sendfile.py                  84     84      0      0     0%\ntests/test_web_sendfile_functional.py      655    655     18      0     0%\ntests/test_web_server.py                   162    162      0      0     0%\ntests/test_web_urldispatcher.py            517    517     24      0     0%\ntests/test_web_websocket.py                401    401      8      0     0%\ntests/test_web_websocket_functional.py     769    769     28      0     0%\ntests/test_websocket_handshake.py          152    152     12      0     0%\ntests/test_websocket_parser.py             300    300     12      0     0%\ntests/test_websocket_writer.py              95     95      6      0     0%\ntests/test_worker.py                       191    191      2      0     0%\n--------------------------------------------------------------------------\nTOTAL                                    34246  27584   4339    520    21%\n\n============================= slowest 10 durations =============================\n2.01s call     r2e_tests/test_1.py::test_read_timeout_between_chunks[pyloop]\n2.01s call     r2e_tests/test_1.py::test_set_cookies_max_age[pyloop]\n1.01s call     r2e_tests/test_1.py::test_readline_error_on_conn_close[pyloop]\n1.00s call     r2e_tests/test_1.py::test_timeout_on_reading_data[pyloop]\n0.51s call     r2e_tests/test_1.py::test_timeout_with_full_buffer[pyloop]\n0.50s call     r2e_tests/test_1.py::test_read_timeout_on_write[pyloop]\n0.50s call     r2e_tests/test_1.py::test_no_error_on_conn_close_if_eof[pyloop]\n0.21s call     r2e_tests/test_1.py::test_read_timeout_closes_connection[pyloop]\n0.20s call     r2e_tests/test_1.py::test_read_timeout_on_reading_chunks[pyloop]\n0.11s setup    r2e_tests/test_1.py::test_ssl_client[pyloop]\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::test_keepalive_two_requests_success[pyloop]\nPASSED r2e_tests/test_1.py::test_keepalive_after_head_requests_success[pyloop]\nPASSED r2e_tests/test_1.py::test_keepalive_after_empty_body_status[pyloop-101]\nPASSED r2e_tests/test_1.py::test_keepalive_after_empty_body_status[pyloop-204]\nPASSED r2e_tests/test_1.py::test_keepalive_after_empty_body_status[pyloop-304]\nPASSED r2e_tests/test_1.py::test_keepalive_after_empty_body_status_stream_response[pyloop-101]\nPASSED r2e_tests/test_1.py::test_keepalive_after_empty_body_status_stream_response[pyloop-204]\nPASSED r2e_tests/test_1.py::test_keepalive_after_empty_body_status_stream_response[pyloop-304]\nPASSED r2e_tests/test_1.py::test_keepalive_response_released[pyloop]\nPASSED r2e_tests/test_1.py::test_upgrade_connection_not_released_after_read[pyloop]\nPASSED r2e_tests/test_1.py::test_keepalive_server_force_close_connection[pyloop]\nPASSED r2e_tests/test_1.py::test_keepalive_timeout_async_sleep\nPASSED r2e_tests/test_1.py::test_keepalive_timeout_sync_sleep\nPASSED r2e_tests/test_1.py::test_release_early[pyloop]\nPASSED r2e_tests/test_1.py::test_HTTP_304[pyloop]\nPASSED r2e_tests/test_1.py::test_stream_request_on_server_eof[pyloop]\nPASSED r2e_tests/test_1.py::test_stream_request_on_server_eof_nested[pyloop]\nPASSED r2e_tests/test_1.py::test_HTTP_304_WITH_BODY[pyloop]\nPASSED r2e_tests/test_1.py::test_auto_header_user_agent[pyloop]\nPASSED r2e_tests/test_1.py::test_skip_auto_headers_user_agent[pyloop]\nPASSED r2e_tests/test_1.py::test_skip_default_auto_headers_user_agent[pyloop]\nPASSED r2e_tests/test_1.py::test_skip_auto_headers_content_type[pyloop]\nPASSED r2e_tests/test_1.py::test_post_data_bytesio[pyloop]\nPASSED r2e_tests/test_1.py::test_post_data_with_bytesio_file[pyloop]\nPASSED r2e_tests/test_1.py::test_post_data_stringio[pyloop]\nPASSED r2e_tests/test_1.py::test_post_data_textio_encoding[pyloop]\nPASSED r2e_tests/test_1.py::test_post_data_zipfile_filelike[pyloop]\nPASSED r2e_tests/test_1.py::test_post_data_tarfile_filelike[pyloop]\nPASSED r2e_tests/test_1.py::test_ssl_client[pyloop]\nPASSED r2e_tests/test_1.py::test_tcp_connector_fingerprint_ok[pyloop]\nPASSED r2e_tests/test_1.py::test_tcp_connector_fingerprint_fail[pyloop]\nPASSED r2e_tests/test_1.py::test_format_task_get[pyloop]\nPASSED r2e_tests/test_1.py::test_str_params[pyloop]\nPASSED r2e_tests/test_1.py::test_drop_params_on_redirect[pyloop]\nPASSED r2e_tests/test_1.py::test_drop_fragment_on_redirect[pyloop]\nPASSED r2e_tests/test_1.py::test_drop_fragment[pyloop]\nPASSED r2e_tests/test_1.py::test_history[pyloop]\nPASSED r2e_tests/test_1.py::test_keepalive_closed_by_server[pyloop]\nPASSED r2e_tests/test_1.py::test_wait_for[pyloop]\nPASSED r2e_tests/test_1.py::test_raw_headers[pyloop]\nPASSED r2e_tests/test_1.py::test_host_header_first[pyloop]\nPASSED r2e_tests/test_1.py::test_empty_header_values[pyloop]\nPASSED r2e_tests/test_1.py::test_204_with_gzipped_content_encoding[pyloop]\nPASSED r2e_tests/test_1.py::test_timeout_on_reading_headers[pyloop]\nPASSED r2e_tests/test_1.py::test_timeout_on_conn_reading_headers[pyloop]\nPASSED r2e_tests/test_1.py::test_timeout_on_session_read_timeout[pyloop]\nPASSED r2e_tests/test_1.py::test_read_timeout_between_chunks[pyloop]\nPASSED r2e_tests/test_1.py::test_read_timeout_on_reading_chunks[pyloop]\nPASSED r2e_tests/test_1.py::test_read_timeout_on_write[pyloop]\nPASSED r2e_tests/test_1.py::test_timeout_on_reading_data[pyloop]\nPASSED r2e_tests/test_1.py::test_timeout_none[pyloop]\nPASSED r2e_tests/test_1.py::test_readline_error_on_conn_close[pyloop]\nPASSED r2e_tests/test_1.py::test_no_error_on_conn_close_if_eof[pyloop]\nPASSED r2e_tests/test_1.py::test_error_not_overwrote_on_conn_close[pyloop]\nPASSED r2e_tests/test_1.py::test_HTTP_200_OK_METHOD[pyloop]\nPASSED r2e_tests/test_1.py::test_HTTP_200_OK_METHOD_connector[pyloop]\nPASSED r2e_tests/test_1.py::test_HTTP_302_REDIRECT_GET[pyloop]\nPASSED r2e_tests/test_1.py::test_HTTP_302_REDIRECT_HEAD[pyloop]\nPASSED r2e_tests/test_1.py::test_HTTP_302_REDIRECT_NON_HTTP[pyloop]\nPASSED r2e_tests/test_1.py::test_HTTP_302_REDIRECT_POST[pyloop]\nPASSED r2e_tests/test_1.py::test_HTTP_302_REDIRECT_POST_with_content_length_hdr[pyloop]\nPASSED r2e_tests/test_1.py::test_HTTP_307_REDIRECT_POST[pyloop]\nPASSED r2e_tests/test_1.py::test_HTTP_308_PERMANENT_REDIRECT_POST[pyloop]\nPASSED r2e_tests/test_1.py::test_HTTP_302_max_redirects[pyloop]\nPASSED r2e_tests/test_1.py::test_HTTP_200_GET_WITH_PARAMS[pyloop]\nPASSED r2e_tests/test_1.py::test_HTTP_200_GET_WITH_MultiDict_PARAMS[pyloop]\nPASSED r2e_tests/test_1.py::test_HTTP_200_GET_WITH_MIXED_PARAMS[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_DATA[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_DATA_with_explicit_formdata[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_DATA_with_charset[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_DATA_formdats_with_charset[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_DATA_with_charset_post[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_MultiDict[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_DATA_DEFLATE[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_FILES[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_FILES_DEFLATE[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_bytes[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_bytes_too_large[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_FILES_STR[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_FILES_STR_SIMPLE[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_FILES_LIST[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_FILES_CT[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_FILES_SINGLE[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_FILES_SINGLE_content_disposition[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_FILES_SINGLE_BINARY[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_FILES_IO[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_FILES_IO_WITH_PARAMS[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_FILES_WITH_DATA[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_STREAM_DATA[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_STREAM_DATA_no_params[pyloop]\nPASSED r2e_tests/test_1.py::test_json[pyloop]\nPASSED r2e_tests/test_1.py::test_json_custom[pyloop]\nPASSED r2e_tests/test_1.py::test_expect_continue[pyloop]\nPASSED r2e_tests/test_1.py::test_encoding_deflate[pyloop]\nPASSED r2e_tests/test_1.py::test_encoding_deflate_nochunk[pyloop]\nPASSED r2e_tests/test_1.py::test_encoding_gzip[pyloop]\nPASSED r2e_tests/test_1.py::test_encoding_gzip_write_by_chunks[pyloop]\nPASSED r2e_tests/test_1.py::test_encoding_gzip_nochunk[pyloop]\nPASSED r2e_tests/test_1.py::test_bad_payload_compression[pyloop]\nPASSED r2e_tests/test_1.py::test_bad_payload_chunked_encoding[pyloop]\nPASSED r2e_tests/test_1.py::test_no_payload_304_with_chunked_encoding[pyloop]\nPASSED r2e_tests/test_1.py::test_head_request_with_chunked_encoding[pyloop]\nPASSED r2e_tests/test_1.py::test_no_payload_200_with_chunked_encoding[pyloop]\nPASSED r2e_tests/test_1.py::test_bad_payload_content_length[pyloop]\nPASSED r2e_tests/test_1.py::test_payload_content_length_by_chunks[pyloop]\nPASSED r2e_tests/test_1.py::test_chunked[pyloop]\nPASSED r2e_tests/test_1.py::test_shortcuts[pyloop]\nPASSED r2e_tests/test_1.py::test_cookies[pyloop]\nPASSED r2e_tests/test_1.py::test_cookies_per_request[pyloop]\nPASSED r2e_tests/test_1.py::test_cookies_redirect[pyloop]\nPASSED r2e_tests/test_1.py::test_cookies_on_empty_session_jar[pyloop]\nPASSED r2e_tests/test_1.py::test_morsel_with_attributes[pyloop]\nPASSED r2e_tests/test_1.py::test_set_cookies[pyloop]\nPASSED r2e_tests/test_1.py::test_set_cookies_expired[pyloop]\nPASSED r2e_tests/test_1.py::test_set_cookies_max_age[pyloop]\nPASSED r2e_tests/test_1.py::test_set_cookies_max_age_overflow[pyloop]\nPASSED r2e_tests/test_1.py::test_request_conn_error\nPASSED r2e_tests/test_1.py::test_broken_connection_2[pyloop]\nPASSED r2e_tests/test_1.py::test_custom_headers[pyloop]\nPASSED r2e_tests/test_1.py::test_redirect_to_absolute_url[pyloop]\nPASSED r2e_tests/test_1.py::test_redirect_without_location_header[pyloop]\nPASSED r2e_tests/test_1.py::test_chunked_deprecated[pyloop]\nPASSED r2e_tests/test_1.py::test_invalid_and_non_http_url[http://:/-http://:/-InvalidUrlClientError]\nPASSED r2e_tests/test_1.py::test_invalid_and_non_http_url[http://example.org:non_int_port/-http://example.org:non_int_port/-InvalidUrlClientError]\nPASSED r2e_tests/test_1.py::test_invalid_and_non_http_url[http:/-http:///-InvalidUrlClientError]\nPASSED r2e_tests/test_1.py::test_invalid_and_non_http_url[http:/example.com-http:///example.com-InvalidUrlClientError]\nPASSED r2e_tests/test_1.py::test_invalid_and_non_http_url[http:///example.com-http:///example.com-InvalidUrlClientError]\nPASSED r2e_tests/test_1.py::test_invalid_and_non_http_url[call:+380123456789-call:\\\\+380123456789-NonHttpUrlClientError]\nPASSED r2e_tests/test_1.py::test_invalid_and_non_http_url[skype:handle-skype:handle-NonHttpUrlClientError]\nPASSED r2e_tests/test_1.py::test_invalid_and_non_http_url[slack://instance/room-slack://instance/room-NonHttpUrlClientError]\nPASSED r2e_tests/test_1.py::test_invalid_and_non_http_url[steam:code-steam:code-NonHttpUrlClientError]\nPASSED r2e_tests/test_1.py::test_invalid_and_non_http_url[twitter://handle-twitter://handle-NonHttpUrlClientError]\nPASSED r2e_tests/test_1.py::test_invalid_and_non_http_url[bluesky://profile/d:i:d-bluesky://profile/d:i:d-NonHttpUrlClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url[pyloop-http:/-http:///-InvalidUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url[pyloop-http:/example.com-http:///example.com-InvalidUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url[pyloop-http:///example.com-http:///example.com-InvalidUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url[pyloop-http://:/-http://:/-InvalidUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url[pyloop-http://example.org:non_int_port/-http://example.org:non_int_port/-InvalidUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url[pyloop-call:+380123456789-call:\\\\+380123456789-NonHttpUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url[pyloop-skype:handle-skype:handle-NonHttpUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url[pyloop-slack://instance/room-slack://instance/room-NonHttpUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url[pyloop-steam:code-steam:code-NonHttpUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url[pyloop-twitter://handle-twitter://handle-NonHttpUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url[pyloop-bluesky://profile/d:i:d-bluesky://profile/d:i:d-NonHttpUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-http:/-http:///-InvalidUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-http:/example.com-http:///example.com-InvalidUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-http:///example.com-http:///example.com-InvalidUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-http://:/-http://:/-InvalidUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-http://example.org:non_int_port/-http://example.org:non_int_port/-InvalidUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-call:+380123456789-call:\\\\+380123456789-NonHttpUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-skype:handle-skype:handle-NonHttpUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-slack://instance/room-slack://instance/room-NonHttpUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-steam:code-steam:code-NonHttpUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-twitter://handle-twitter://handle-NonHttpUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-bluesky://profile/d:i:d-bluesky://profile/d:i:d-NonHttpUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_ok_from_status[pyloop-200-True]\nPASSED r2e_tests/test_1.py::test_ok_from_status[pyloop-201-True]\nPASSED r2e_tests/test_1.py::test_ok_from_status[pyloop-301-True]\nPASSED r2e_tests/test_1.py::test_ok_from_status[pyloop-400-False]\nPASSED r2e_tests/test_1.py::test_ok_from_status[pyloop-403-False]\nPASSED r2e_tests/test_1.py::test_ok_from_status[pyloop-500-False]\nPASSED r2e_tests/test_1.py::test_raise_for_status[pyloop]\nPASSED r2e_tests/test_1.py::test_raise_for_status_per_request[pyloop]\nPASSED r2e_tests/test_1.py::test_raise_for_status_disable_per_request[pyloop]\nPASSED r2e_tests/test_1.py::test_request_raise_for_status_default[pyloop]\nPASSED r2e_tests/test_1.py::test_request_raise_for_status_disabled[pyloop]\nPASSED r2e_tests/test_1.py::test_request_raise_for_status_enabled[pyloop]\nPASSED r2e_tests/test_1.py::test_session_raise_for_status_coro[pyloop]\nPASSED r2e_tests/test_1.py::test_request_raise_for_status_coro[pyloop]\nPASSED r2e_tests/test_1.py::test_invalid_idna\nPASSED r2e_tests/test_1.py::test_creds_in_auth_and_url\nPASSED r2e_tests/test_1.py::test_drop_auth_on_redirect_to_other_host[pyloop-entirely different hosts]\nPASSED r2e_tests/test_1.py::test_drop_auth_on_redirect_to_other_host[pyloop-http -> https]\nPASSED r2e_tests/test_1.py::test_drop_auth_on_redirect_to_other_host[pyloop-https -> http]\nPASSED r2e_tests/test_1.py::test_async_with_session\nPASSED r2e_tests/test_1.py::test_session_close_awaitable\nPASSED r2e_tests/test_1.py::test_close_resp_on_error_async_with_session[pyloop]\nPASSED r2e_tests/test_1.py::test_release_resp_on_normal_exit_from_cm[pyloop]\nPASSED r2e_tests/test_1.py::test_non_close_detached_session_on_error_cm[pyloop]\nPASSED r2e_tests/test_1.py::test_close_detached_session_on_non_existing_addr\nPASSED r2e_tests/test_1.py::test_aiohttp_request_context_manager[pyloop]\nPASSED r2e_tests/test_1.py::test_aiohttp_request_ctx_manager_close_sess_on_error[pyloop]\nPASSED r2e_tests/test_1.py::test_aiohttp_request_ctx_manager_not_found\nPASSED r2e_tests/test_1.py::test_yield_from_in_session_request[pyloop]\nPASSED r2e_tests/test_1.py::test_close_context_manager[pyloop]\nPASSED r2e_tests/test_1.py::test_session_auth[pyloop]\nPASSED r2e_tests/test_1.py::test_session_auth_override[pyloop]\nPASSED r2e_tests/test_1.py::test_session_auth_header_conflict[pyloop]\nPASSED r2e_tests/test_1.py::test_session_headers[pyloop]\nPASSED r2e_tests/test_1.py::test_session_headers_merge[pyloop]\nPASSED r2e_tests/test_1.py::test_multidict_headers[pyloop]\nPASSED r2e_tests/test_1.py::test_request_conn_closed[pyloop]\nPASSED r2e_tests/test_1.py::test_dont_close_explicit_connector[pyloop]\nPASSED r2e_tests/test_1.py::test_server_close_keepalive_connection\nPASSED r2e_tests/test_1.py::test_handle_keepalive_on_closed_connection\nPASSED r2e_tests/test_1.py::test_error_in_performing_request[pyloop]\nPASSED r2e_tests/test_1.py::test_await_after_cancelling[pyloop]\nPASSED r2e_tests/test_1.py::test_async_payload_generator[pyloop]\nPASSED r2e_tests/test_1.py::test_read_from_closed_response[pyloop]\nPASSED r2e_tests/test_1.py::test_read_from_closed_response2[pyloop]\nPASSED r2e_tests/test_1.py::test_read_from_closed_content[pyloop]\nPASSED r2e_tests/test_1.py::test_read_timeout[pyloop]\nPASSED r2e_tests/test_1.py::test_socket_timeout[pyloop]\nPASSED r2e_tests/test_1.py::test_read_timeout_closes_connection[pyloop]\nPASSED r2e_tests/test_1.py::test_read_timeout_on_prepared_response[pyloop]\nPASSED r2e_tests/test_1.py::test_timeout_with_full_buffer[pyloop]\nPASSED r2e_tests/test_1.py::test_read_bufsize_session_default[pyloop]\nPASSED r2e_tests/test_1.py::test_read_bufsize_explicit[pyloop]\nPASSED r2e_tests/test_1.py::test_http_empty_data_text[pyloop]\nPASSED r2e_tests/test_1.py::test_max_field_size_session_default[pyloop]\nPASSED r2e_tests/test_1.py::test_max_field_size_session_default_fail[pyloop]\nPASSED r2e_tests/test_1.py::test_max_field_size_session_explicit[pyloop]\nPASSED r2e_tests/test_1.py::test_max_field_size_request_explicit[pyloop]\nPASSED r2e_tests/test_1.py::test_max_line_size_session_default[pyloop]\nPASSED r2e_tests/test_1.py::test_max_line_size_session_default_fail[pyloop]\nPASSED r2e_tests/test_1.py::test_max_line_size_session_explicit[pyloop]\nPASSED r2e_tests/test_1.py::test_max_line_size_request_explicit[pyloop]\nPASSED r2e_tests/test_1.py::test_rejected_upload[pyloop]\nPASSED r2e_tests/test_1.py::test_request_with_wrong_proxy[pyloop-42-TypeError]\nPASSED r2e_tests/test_1.py::test_request_with_wrong_proxy[pyloop-InvalidUrl-InvalidURL]\nPASSED r2e_tests/test_1.py::test_raise_for_status_is_none[pyloop]\nPASSED r2e_tests/test_1.py::test_exception_when_read_outside_of_session[pyloop]\nXFAIL r2e_tests/test_1.py::test_broken_connection[pyloop]\n======================= 222 passed, 1 xfailed in 18.01s ========================\n",
    "new_commit_res_stderr": "/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/.venv/lib/python3.9/site-packages/pytest_asyncio/plugin.py:207: PytestDeprecationWarning: The configuration option \"asyncio_default_fixture_loop_scope\" is unset.\nThe event loop scope for asynchronous fixtures will default to the fixture caching scope. Future versions of pytest-asyncio will default the loop scope for asynchronous fixtures to function scope. Set the default fixture loop scope explicitly in order to avoid unexpected behavior in the future. Valid fixture loop scopes are: \"function\", \"class\", \"module\", \"package\", \"session\"\n\n  warnings.warn(PytestDeprecationWarning(_DEFAULT_FIXTURE_LOOP_SCOPE_UNSET))\n",
    "old_commit_res_code": 1,
    "old_commit_res_stdout": "============================= test session starts ==============================\nplatform linux -- Python 3.9.21, pytest-8.3.2, pluggy-1.5.0 -- /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/.venv/bin/python\ncachedir: .pytest_cache\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860\nconfigfile: setup.cfg\nplugins: cov-5.0.0, mock-3.14.0, asyncio-0.25.1\nasyncio: mode=strict, asyncio_default_fixture_loop_scope=None\ncollecting ... collected 223 items\n\nr2e_tests/test_1.py::test_keepalive_two_requests_success[pyloop] PASSED  [  0%]\nr2e_tests/test_1.py::test_keepalive_after_head_requests_success[pyloop] PASSED [  0%]\nr2e_tests/test_1.py::test_keepalive_after_empty_body_status[pyloop-101] PASSED [  1%]\nr2e_tests/test_1.py::test_keepalive_after_empty_body_status[pyloop-204] PASSED [  1%]\nr2e_tests/test_1.py::test_keepalive_after_empty_body_status[pyloop-304] PASSED [  2%]\nr2e_tests/test_1.py::test_keepalive_after_empty_body_status_stream_response[pyloop-101] PASSED [  2%]\nr2e_tests/test_1.py::test_keepalive_after_empty_body_status_stream_response[pyloop-204] PASSED [  3%]\nr2e_tests/test_1.py::test_keepalive_after_empty_body_status_stream_response[pyloop-304] PASSED [  3%]\nr2e_tests/test_1.py::test_keepalive_response_released[pyloop] PASSED     [  4%]\nr2e_tests/test_1.py::test_upgrade_connection_not_released_after_read[pyloop] PASSED [  4%]\nr2e_tests/test_1.py::test_keepalive_server_force_close_connection[pyloop] PASSED [  4%]\nr2e_tests/test_1.py::test_keepalive_timeout_async_sleep PASSED           [  5%]\nr2e_tests/test_1.py::test_keepalive_timeout_sync_sleep PASSED            [  5%]\nr2e_tests/test_1.py::test_release_early[pyloop] PASSED                   [  6%]\nr2e_tests/test_1.py::test_HTTP_304[pyloop] PASSED                        [  6%]\nr2e_tests/test_1.py::test_stream_request_on_server_eof[pyloop] FAILED    [  7%]\nr2e_tests/test_1.py::test_stream_request_on_server_eof_nested[pyloop] FAILED [  7%]\nr2e_tests/test_1.py::test_HTTP_304_WITH_BODY[pyloop] PASSED              [  8%]\nr2e_tests/test_1.py::test_auto_header_user_agent[pyloop] PASSED          [  8%]\nr2e_tests/test_1.py::test_skip_auto_headers_user_agent[pyloop] PASSED    [  8%]\nr2e_tests/test_1.py::test_skip_default_auto_headers_user_agent[pyloop] PASSED [  9%]\nr2e_tests/test_1.py::test_skip_auto_headers_content_type[pyloop] PASSED  [  9%]\nr2e_tests/test_1.py::test_post_data_bytesio[pyloop] PASSED               [ 10%]\nr2e_tests/test_1.py::test_post_data_with_bytesio_file[pyloop] PASSED     [ 10%]\nr2e_tests/test_1.py::test_post_data_stringio[pyloop] PASSED              [ 11%]\nr2e_tests/test_1.py::test_post_data_textio_encoding[pyloop] PASSED       [ 11%]\nr2e_tests/test_1.py::test_post_data_zipfile_filelike[pyloop] PASSED      [ 12%]\nr2e_tests/test_1.py::test_post_data_tarfile_filelike[pyloop] PASSED      [ 12%]\nr2e_tests/test_1.py::test_ssl_client[pyloop] PASSED                      [ 13%]\nr2e_tests/test_1.py::test_tcp_connector_fingerprint_ok[pyloop] PASSED    [ 13%]\nr2e_tests/test_1.py::test_tcp_connector_fingerprint_fail[pyloop] PASSED  [ 13%]\nr2e_tests/test_1.py::test_format_task_get[pyloop] PASSED                 [ 14%]\nr2e_tests/test_1.py::test_str_params[pyloop] PASSED                      [ 14%]\nr2e_tests/test_1.py::test_drop_params_on_redirect[pyloop] PASSED         [ 15%]\nr2e_tests/test_1.py::test_drop_fragment_on_redirect[pyloop] PASSED       [ 15%]\nr2e_tests/test_1.py::test_drop_fragment[pyloop] PASSED                   [ 16%]\nr2e_tests/test_1.py::test_history[pyloop] PASSED                         [ 16%]\nr2e_tests/test_1.py::test_keepalive_closed_by_server[pyloop] PASSED      [ 17%]\nr2e_tests/test_1.py::test_wait_for[pyloop] PASSED                        [ 17%]\nr2e_tests/test_1.py::test_raw_headers[pyloop] PASSED                     [ 17%]\nr2e_tests/test_1.py::test_host_header_first[pyloop] PASSED               [ 18%]\nr2e_tests/test_1.py::test_empty_header_values[pyloop] PASSED             [ 18%]\nr2e_tests/test_1.py::test_204_with_gzipped_content_encoding[pyloop] PASSED [ 19%]\nr2e_tests/test_1.py::test_timeout_on_reading_headers[pyloop] PASSED      [ 19%]\nr2e_tests/test_1.py::test_timeout_on_conn_reading_headers[pyloop] PASSED [ 20%]\nr2e_tests/test_1.py::test_timeout_on_session_read_timeout[pyloop] PASSED [ 20%]\nr2e_tests/test_1.py::test_read_timeout_between_chunks[pyloop] PASSED     [ 21%]\nr2e_tests/test_1.py::test_read_timeout_on_reading_chunks[pyloop] PASSED  [ 21%]\nr2e_tests/test_1.py::test_read_timeout_on_write[pyloop] PASSED           [ 21%]\nr2e_tests/test_1.py::test_timeout_on_reading_data[pyloop] PASSED         [ 22%]\nr2e_tests/test_1.py::test_timeout_none[pyloop] PASSED                    [ 22%]\nr2e_tests/test_1.py::test_readline_error_on_conn_close[pyloop] PASSED    [ 23%]\nr2e_tests/test_1.py::test_no_error_on_conn_close_if_eof[pyloop] PASSED   [ 23%]\nr2e_tests/test_1.py::test_error_not_overwrote_on_conn_close[pyloop] PASSED [ 24%]\nr2e_tests/test_1.py::test_HTTP_200_OK_METHOD[pyloop] PASSED              [ 24%]\nr2e_tests/test_1.py::test_HTTP_200_OK_METHOD_connector[pyloop] PASSED    [ 25%]\nr2e_tests/test_1.py::test_HTTP_302_REDIRECT_GET[pyloop] PASSED           [ 25%]\nr2e_tests/test_1.py::test_HTTP_302_REDIRECT_HEAD[pyloop] PASSED          [ 26%]\nr2e_tests/test_1.py::test_HTTP_302_REDIRECT_NON_HTTP[pyloop] PASSED      [ 26%]\nr2e_tests/test_1.py::test_HTTP_302_REDIRECT_POST[pyloop] PASSED          [ 26%]\nr2e_tests/test_1.py::test_HTTP_302_REDIRECT_POST_with_content_length_hdr[pyloop] PASSED [ 27%]\nr2e_tests/test_1.py::test_HTTP_307_REDIRECT_POST[pyloop] PASSED          [ 27%]\nr2e_tests/test_1.py::test_HTTP_308_PERMANENT_REDIRECT_POST[pyloop] PASSED [ 28%]\nr2e_tests/test_1.py::test_HTTP_302_max_redirects[pyloop] PASSED          [ 28%]\nr2e_tests/test_1.py::test_HTTP_200_GET_WITH_PARAMS[pyloop] PASSED        [ 29%]\nr2e_tests/test_1.py::test_HTTP_200_GET_WITH_MultiDict_PARAMS[pyloop] PASSED [ 29%]\nr2e_tests/test_1.py::test_HTTP_200_GET_WITH_MIXED_PARAMS[pyloop] PASSED  [ 30%]\nr2e_tests/test_1.py::test_POST_DATA[pyloop] PASSED                       [ 30%]\nr2e_tests/test_1.py::test_POST_DATA_with_explicit_formdata[pyloop] PASSED [ 30%]\nr2e_tests/test_1.py::test_POST_DATA_with_charset[pyloop] PASSED          [ 31%]\nr2e_tests/test_1.py::test_POST_DATA_formdats_with_charset[pyloop] PASSED [ 31%]\nr2e_tests/test_1.py::test_POST_DATA_with_charset_post[pyloop] PASSED     [ 32%]\nr2e_tests/test_1.py::test_POST_MultiDict[pyloop] PASSED                  [ 32%]\nr2e_tests/test_1.py::test_POST_DATA_DEFLATE[pyloop] PASSED               [ 33%]\nr2e_tests/test_1.py::test_POST_FILES[pyloop] PASSED                      [ 33%]\nr2e_tests/test_1.py::test_POST_FILES_DEFLATE[pyloop] PASSED              [ 34%]\nr2e_tests/test_1.py::test_POST_bytes[pyloop] PASSED                      [ 34%]\nr2e_tests/test_1.py::test_POST_bytes_too_large[pyloop] PASSED            [ 34%]\nr2e_tests/test_1.py::test_POST_FILES_STR[pyloop] PASSED                  [ 35%]\nr2e_tests/test_1.py::test_POST_FILES_STR_SIMPLE[pyloop] PASSED           [ 35%]\nr2e_tests/test_1.py::test_POST_FILES_LIST[pyloop] PASSED                 [ 36%]\nr2e_tests/test_1.py::test_POST_FILES_CT[pyloop] PASSED                   [ 36%]\nr2e_tests/test_1.py::test_POST_FILES_SINGLE[pyloop] PASSED               [ 37%]\nr2e_tests/test_1.py::test_POST_FILES_SINGLE_content_disposition[pyloop] PASSED [ 37%]\nr2e_tests/test_1.py::test_POST_FILES_SINGLE_BINARY[pyloop] PASSED        [ 38%]\nr2e_tests/test_1.py::test_POST_FILES_IO[pyloop] PASSED                   [ 38%]\nr2e_tests/test_1.py::test_POST_FILES_IO_WITH_PARAMS[pyloop] PASSED       [ 39%]\nr2e_tests/test_1.py::test_POST_FILES_WITH_DATA[pyloop] PASSED            [ 39%]\nr2e_tests/test_1.py::test_POST_STREAM_DATA[pyloop] PASSED                [ 39%]\nr2e_tests/test_1.py::test_POST_STREAM_DATA_no_params[pyloop] PASSED      [ 40%]\nr2e_tests/test_1.py::test_json[pyloop] PASSED                            [ 40%]\nr2e_tests/test_1.py::test_json_custom[pyloop] PASSED                     [ 41%]\nr2e_tests/test_1.py::test_expect_continue[pyloop] PASSED                 [ 41%]\nr2e_tests/test_1.py::test_encoding_deflate[pyloop] PASSED                [ 42%]\nr2e_tests/test_1.py::test_encoding_deflate_nochunk[pyloop] PASSED        [ 42%]\nr2e_tests/test_1.py::test_encoding_gzip[pyloop] PASSED                   [ 43%]\nr2e_tests/test_1.py::test_encoding_gzip_write_by_chunks[pyloop] PASSED   [ 43%]\nr2e_tests/test_1.py::test_encoding_gzip_nochunk[pyloop] PASSED           [ 43%]\nr2e_tests/test_1.py::test_bad_payload_compression[pyloop] PASSED         [ 44%]\nr2e_tests/test_1.py::test_bad_payload_chunked_encoding[pyloop] PASSED    [ 44%]\nr2e_tests/test_1.py::test_no_payload_304_with_chunked_encoding[pyloop] PASSED [ 45%]\nr2e_tests/test_1.py::test_head_request_with_chunked_encoding[pyloop] PASSED [ 45%]\nr2e_tests/test_1.py::test_no_payload_200_with_chunked_encoding[pyloop] PASSED [ 46%]\nr2e_tests/test_1.py::test_bad_payload_content_length[pyloop] PASSED      [ 46%]\nr2e_tests/test_1.py::test_payload_content_length_by_chunks[pyloop] PASSED [ 47%]\nr2e_tests/test_1.py::test_chunked[pyloop] PASSED                         [ 47%]\nr2e_tests/test_1.py::test_shortcuts[pyloop] PASSED                       [ 47%]\nr2e_tests/test_1.py::test_cookies[pyloop] PASSED                         [ 48%]\nr2e_tests/test_1.py::test_cookies_per_request[pyloop] PASSED             [ 48%]\nr2e_tests/test_1.py::test_cookies_redirect[pyloop] PASSED                [ 49%]\nr2e_tests/test_1.py::test_cookies_on_empty_session_jar[pyloop] PASSED    [ 49%]\nr2e_tests/test_1.py::test_morsel_with_attributes[pyloop] PASSED          [ 50%]\nr2e_tests/test_1.py::test_set_cookies[pyloop] PASSED                     [ 50%]\nr2e_tests/test_1.py::test_set_cookies_expired[pyloop] PASSED             [ 51%]\nr2e_tests/test_1.py::test_set_cookies_max_age[pyloop] PASSED             [ 51%]\nr2e_tests/test_1.py::test_set_cookies_max_age_overflow[pyloop] PASSED    [ 52%]\nr2e_tests/test_1.py::test_request_conn_error PASSED                      [ 52%]\nr2e_tests/test_1.py::test_broken_connection[pyloop] XFAIL                [ 52%]\nr2e_tests/test_1.py::test_broken_connection_2[pyloop] PASSED             [ 53%]\nr2e_tests/test_1.py::test_custom_headers[pyloop] PASSED                  [ 53%]\nr2e_tests/test_1.py::test_redirect_to_absolute_url[pyloop] PASSED        [ 54%]\nr2e_tests/test_1.py::test_redirect_without_location_header[pyloop] PASSED [ 54%]\nr2e_tests/test_1.py::test_chunked_deprecated[pyloop] PASSED              [ 55%]\nr2e_tests/test_1.py::test_invalid_and_non_http_url[http://:/-http://:/-InvalidUrlClientError] PASSED [ 55%]\nr2e_tests/test_1.py::test_invalid_and_non_http_url[http://example.org:non_int_port/-http://example.org:non_int_port/-InvalidUrlClientError] PASSED [ 56%]\nr2e_tests/test_1.py::test_invalid_and_non_http_url[http:/-http:///-InvalidUrlClientError] PASSED [ 56%]\nr2e_tests/test_1.py::test_invalid_and_non_http_url[http:/example.com-http:///example.com-InvalidUrlClientError] PASSED [ 56%]\nr2e_tests/test_1.py::test_invalid_and_non_http_url[http:///example.com-http:///example.com-InvalidUrlClientError] PASSED [ 57%]\nr2e_tests/test_1.py::test_invalid_and_non_http_url[call:+380123456789-call:\\\\+380123456789-NonHttpUrlClientError] PASSED [ 57%]\nr2e_tests/test_1.py::test_invalid_and_non_http_url[skype:handle-skype:handle-NonHttpUrlClientError] PASSED [ 58%]\nr2e_tests/test_1.py::test_invalid_and_non_http_url[slack://instance/room-slack://instance/room-NonHttpUrlClientError] PASSED [ 58%]\nr2e_tests/test_1.py::test_invalid_and_non_http_url[steam:code-steam:code-NonHttpUrlClientError] PASSED [ 59%]\nr2e_tests/test_1.py::test_invalid_and_non_http_url[twitter://handle-twitter://handle-NonHttpUrlClientError] PASSED [ 59%]\nr2e_tests/test_1.py::test_invalid_and_non_http_url[bluesky://profile/d:i:d-bluesky://profile/d:i:d-NonHttpUrlClientError] PASSED [ 60%]\nr2e_tests/test_1.py::test_invalid_redirect_url[pyloop-http:/-http:///-InvalidUrlRedirectClientError] PASSED [ 60%]\nr2e_tests/test_1.py::test_invalid_redirect_url[pyloop-http:/example.com-http:///example.com-InvalidUrlRedirectClientError] PASSED [ 60%]\nr2e_tests/test_1.py::test_invalid_redirect_url[pyloop-http:///example.com-http:///example.com-InvalidUrlRedirectClientError] PASSED [ 61%]\nr2e_tests/test_1.py::test_invalid_redirect_url[pyloop-http://:/-http://:/-InvalidUrlRedirectClientError] PASSED [ 61%]\nr2e_tests/test_1.py::test_invalid_redirect_url[pyloop-http://example.org:non_int_port/-http://example.org:non_int_port/-InvalidUrlRedirectClientError] PASSED [ 62%]\nr2e_tests/test_1.py::test_invalid_redirect_url[pyloop-call:+380123456789-call:\\\\+380123456789-NonHttpUrlRedirectClientError] PASSED [ 62%]\nr2e_tests/test_1.py::test_invalid_redirect_url[pyloop-skype:handle-skype:handle-NonHttpUrlRedirectClientError] PASSED [ 63%]\nr2e_tests/test_1.py::test_invalid_redirect_url[pyloop-slack://instance/room-slack://instance/room-NonHttpUrlRedirectClientError] PASSED [ 63%]\nr2e_tests/test_1.py::test_invalid_redirect_url[pyloop-steam:code-steam:code-NonHttpUrlRedirectClientError] PASSED [ 64%]\nr2e_tests/test_1.py::test_invalid_redirect_url[pyloop-twitter://handle-twitter://handle-NonHttpUrlRedirectClientError] PASSED [ 64%]\nr2e_tests/test_1.py::test_invalid_redirect_url[pyloop-bluesky://profile/d:i:d-bluesky://profile/d:i:d-NonHttpUrlRedirectClientError] PASSED [ 65%]\nr2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-http:/-http:///-InvalidUrlRedirectClientError] PASSED [ 65%]\nr2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-http:/example.com-http:///example.com-InvalidUrlRedirectClientError] PASSED [ 65%]\nr2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-http:///example.com-http:///example.com-InvalidUrlRedirectClientError] PASSED [ 66%]\nr2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-http://:/-http://:/-InvalidUrlRedirectClientError] PASSED [ 66%]\nr2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-http://example.org:non_int_port/-http://example.org:non_int_port/-InvalidUrlRedirectClientError] PASSED [ 67%]\nr2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-call:+380123456789-call:\\\\+380123456789-NonHttpUrlRedirectClientError] PASSED [ 67%]\nr2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-skype:handle-skype:handle-NonHttpUrlRedirectClientError] PASSED [ 68%]\nr2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-slack://instance/room-slack://instance/room-NonHttpUrlRedirectClientError] PASSED [ 68%]\nr2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-steam:code-steam:code-NonHttpUrlRedirectClientError] PASSED [ 69%]\nr2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-twitter://handle-twitter://handle-NonHttpUrlRedirectClientError] PASSED [ 69%]\nr2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-bluesky://profile/d:i:d-bluesky://profile/d:i:d-NonHttpUrlRedirectClientError] PASSED [ 69%]\nr2e_tests/test_1.py::test_ok_from_status[pyloop-200-True] PASSED         [ 70%]\nr2e_tests/test_1.py::test_ok_from_status[pyloop-201-True] PASSED         [ 70%]\nr2e_tests/test_1.py::test_ok_from_status[pyloop-301-True] PASSED         [ 71%]\nr2e_tests/test_1.py::test_ok_from_status[pyloop-400-False] PASSED        [ 71%]\nr2e_tests/test_1.py::test_ok_from_status[pyloop-403-False] PASSED        [ 72%]\nr2e_tests/test_1.py::test_ok_from_status[pyloop-500-False] PASSED        [ 72%]\nr2e_tests/test_1.py::test_raise_for_status[pyloop] PASSED                [ 73%]\nr2e_tests/test_1.py::test_raise_for_status_per_request[pyloop] PASSED    [ 73%]\nr2e_tests/test_1.py::test_raise_for_status_disable_per_request[pyloop] PASSED [ 73%]\nr2e_tests/test_1.py::test_request_raise_for_status_default[pyloop] PASSED [ 74%]\nr2e_tests/test_1.py::test_request_raise_for_status_disabled[pyloop] PASSED [ 74%]\nr2e_tests/test_1.py::test_request_raise_for_status_enabled[pyloop] PASSED [ 75%]\nr2e_tests/test_1.py::test_session_raise_for_status_coro[pyloop] PASSED   [ 75%]\nr2e_tests/test_1.py::test_request_raise_for_status_coro[pyloop] PASSED   [ 76%]\nr2e_tests/test_1.py::test_invalid_idna PASSED                            [ 76%]\nr2e_tests/test_1.py::test_creds_in_auth_and_url PASSED                   [ 77%]\nr2e_tests/test_1.py::test_drop_auth_on_redirect_to_other_host[pyloop-entirely different hosts] PASSED [ 77%]\nr2e_tests/test_1.py::test_drop_auth_on_redirect_to_other_host[pyloop-http -> https] PASSED [ 78%]\nr2e_tests/test_1.py::test_drop_auth_on_redirect_to_other_host[pyloop-https -> http] PASSED [ 78%]\nr2e_tests/test_1.py::test_async_with_session PASSED                      [ 78%]\nr2e_tests/test_1.py::test_session_close_awaitable PASSED                 [ 79%]\nr2e_tests/test_1.py::test_close_resp_on_error_async_with_session[pyloop] PASSED [ 79%]\nr2e_tests/test_1.py::test_release_resp_on_normal_exit_from_cm[pyloop] PASSED [ 80%]\nr2e_tests/test_1.py::test_non_close_detached_session_on_error_cm[pyloop] PASSED [ 80%]\nr2e_tests/test_1.py::test_close_detached_session_on_non_existing_addr PASSED [ 81%]\nr2e_tests/test_1.py::test_aiohttp_request_context_manager[pyloop] PASSED [ 81%]\nr2e_tests/test_1.py::test_aiohttp_request_ctx_manager_close_sess_on_error[pyloop] PASSED [ 82%]\nr2e_tests/test_1.py::test_aiohttp_request_ctx_manager_not_found PASSED   [ 82%]\nr2e_tests/test_1.py::test_yield_from_in_session_request[pyloop] PASSED   [ 82%]\nr2e_tests/test_1.py::test_close_context_manager[pyloop] PASSED           [ 83%]\nr2e_tests/test_1.py::test_session_auth[pyloop] PASSED                    [ 83%]\nr2e_tests/test_1.py::test_session_auth_override[pyloop] PASSED           [ 84%]\nr2e_tests/test_1.py::test_session_auth_header_conflict[pyloop] PASSED    [ 84%]\nr2e_tests/test_1.py::test_session_headers[pyloop] PASSED                 [ 85%]\nr2e_tests/test_1.py::test_session_headers_merge[pyloop] PASSED           [ 85%]\nr2e_tests/test_1.py::test_multidict_headers[pyloop] PASSED               [ 86%]\nr2e_tests/test_1.py::test_request_conn_closed[pyloop] PASSED             [ 86%]\nr2e_tests/test_1.py::test_dont_close_explicit_connector[pyloop] PASSED   [ 86%]\nr2e_tests/test_1.py::test_server_close_keepalive_connection PASSED       [ 87%]\nr2e_tests/test_1.py::test_handle_keepalive_on_closed_connection PASSED   [ 87%]\nr2e_tests/test_1.py::test_error_in_performing_request[pyloop] PASSED     [ 88%]\nr2e_tests/test_1.py::test_await_after_cancelling[pyloop] PASSED          [ 88%]\nr2e_tests/test_1.py::test_async_payload_generator[pyloop] PASSED         [ 89%]\nr2e_tests/test_1.py::test_read_from_closed_response[pyloop] PASSED       [ 89%]\nr2e_tests/test_1.py::test_read_from_closed_response2[pyloop] PASSED      [ 90%]\nr2e_tests/test_1.py::test_read_from_closed_content[pyloop] PASSED        [ 90%]\nr2e_tests/test_1.py::test_read_timeout[pyloop] PASSED                    [ 91%]\nr2e_tests/test_1.py::test_socket_timeout[pyloop] PASSED                  [ 91%]\nr2e_tests/test_1.py::test_read_timeout_closes_connection[pyloop] PASSED  [ 91%]\nr2e_tests/test_1.py::test_read_timeout_on_prepared_response[pyloop] PASSED [ 92%]\nr2e_tests/test_1.py::test_timeout_with_full_buffer[pyloop] PASSED        [ 92%]\nr2e_tests/test_1.py::test_read_bufsize_session_default[pyloop] PASSED    [ 93%]\nr2e_tests/test_1.py::test_read_bufsize_explicit[pyloop] PASSED           [ 93%]\nr2e_tests/test_1.py::test_http_empty_data_text[pyloop] PASSED            [ 94%]\nr2e_tests/test_1.py::test_max_field_size_session_default[pyloop] PASSED  [ 94%]\nr2e_tests/test_1.py::test_max_field_size_session_default_fail[pyloop] PASSED [ 95%]\nr2e_tests/test_1.py::test_max_field_size_session_explicit[pyloop] PASSED [ 95%]\nr2e_tests/test_1.py::test_max_field_size_request_explicit[pyloop] PASSED [ 95%]\nr2e_tests/test_1.py::test_max_line_size_session_default[pyloop] PASSED   [ 96%]\nr2e_tests/test_1.py::test_max_line_size_session_default_fail[pyloop] PASSED [ 96%]\nr2e_tests/test_1.py::test_max_line_size_session_explicit[pyloop] PASSED  [ 97%]\nr2e_tests/test_1.py::test_max_line_size_request_explicit[pyloop] PASSED  [ 97%]\nr2e_tests/test_1.py::test_rejected_upload[pyloop] FAILED                 [ 98%]\nr2e_tests/test_1.py::test_request_with_wrong_proxy[pyloop-42-TypeError] PASSED [ 98%]\nr2e_tests/test_1.py::test_request_with_wrong_proxy[pyloop-InvalidUrl-InvalidURL] PASSED [ 99%]\nr2e_tests/test_1.py::test_raise_for_status_is_none[pyloop] PASSED        [ 99%]\nr2e_tests/test_1.py::test_exception_when_read_outside_of_session[pyloop] PASSED [100%]\n\n=================================== FAILURES ===================================\n__________________ test_stream_request_on_server_eof[pyloop] ___________________\n\naiohttp_client = <function aiohttp_client.<locals>.go at 0x7b0ebdc56670>\n\n    async def test_stream_request_on_server_eof(aiohttp_client) -> None:\n        async def handler(request):\n            return web.Response(text=\"OK\", status=200)\n    \n        app = web.Application()\n        app.add_routes([web.get(\"/\", handler)])\n        app.add_routes([web.put(\"/\", handler)])\n    \n        client = await aiohttp_client(app)\n    \n        async def data_gen():\n            for _ in range(2):\n                yield b\"just data\"\n                await asyncio.sleep(0.1)\n    \n        async with client.put(\"/\", data=data_gen()) as resp:\n            assert 200 == resp.status\n            assert len(client.session.connector._acquired) == 1\n            conn = next(iter(client.session.connector._acquired))\n    \n        async with client.get(\"/\") as resp:\n            assert 200 == resp.status\n    \n        # First connection should have been closed, otherwise server won't know if it\n        # received the full message.\n        conns = next(iter(client.session.connector._conns.values()))\n        assert len(conns) == 1\n>       assert conns[0][0] is not conn\nE       assert <aiohttp.client_proto.ResponseHandler object at 0x7b0ebdbc4e20> is not <aiohttp.client_proto.ResponseHandler object at 0x7b0ebdbc4e20>\n\naiohttp_client = <function aiohttp_client.<locals>.go at 0x7b0ebdc56670>\napp        = <Application 0x7b0ebdc61160>\nclient     = <aiohttp.test_utils.TestClient object at 0x7b0ebdc0bf40>\nconn       = <aiohttp.client_proto.ResponseHandler object at 0x7b0ebdbc4e20>\nconns      = [(<aiohttp.client_proto.ResponseHandler object at 0x7b0ebdbc4e20>, 94831.913279226)]\ndata_gen   = <function test_stream_request_on_server_eof.<locals>.data_gen at 0x7b0ebdb7faf0>\nhandler    = <function test_stream_request_on_server_eof.<locals>.handler at 0x7b0ebdc56700>\nresp       = <ClientResponse(http://127.0.0.1:42115/) [200 OK]>\n<CIMultiDictProxy('Content-Type': 'text/plain; charset=utf-8', 'Content-Length': '2', 'Date': 'Thu, 02 Jan 2025 05:41:15 GMT', 'Server': 'Python/3.9 aiohttp/3.10.6.dev0')>\n\n\nr2e_tests/test_1.py:348: AssertionError\n_______________ test_stream_request_on_server_eof_nested[pyloop] _______________\n\naiohttp_client = <function aiohttp_client.<locals>.go at 0x7b0ebdb55d30>\n\n    async def test_stream_request_on_server_eof_nested(aiohttp_client) -> None:\n        async def handler(request):\n            return web.Response(text=\"OK\", status=200)\n    \n        app = web.Application()\n        app.add_routes([web.get(\"/\", handler)])\n        app.add_routes([web.put(\"/\", handler)])\n    \n        client = await aiohttp_client(app)\n    \n        async def data_gen():\n            for _ in range(2):\n                yield b\"just data\"\n                await asyncio.sleep(0.1)\n    \n        assert client.session.connector is not None\n        async with client.put(\"/\", data=data_gen()) as resp:\n            first_conn = next(iter(client.session.connector._acquired))\n            assert 200 == resp.status\n    \n            async with client.get(\"/\") as resp2:\n                assert 200 == resp2.status\n    \n        # Should be 2 separate connections\n        conns = next(iter(client.session.connector._conns.values()))\n>       assert len(conns) == 1\nE       assert 2 == 1\nE        +  where 2 = len([(<aiohttp.client_proto.ResponseHandler object at 0x7b0ebdbc4e80>, 94832.043685309), (<aiohttp.client_proto.ResponseHandler object at 0x7b0ebdbc4340>, 94832.044673175)])\n\naiohttp_client = <function aiohttp_client.<locals>.go at 0x7b0ebdb55d30>\napp        = <Application 0x7b0ebde157c0>\nclient     = <aiohttp.test_utils.TestClient object at 0x7b0ebdac8e50>\nconns      = [(<aiohttp.client_proto.ResponseHandler object at 0x7b0ebdbc4e80>, 94832.043685309), (<aiohttp.client_proto.ResponseHandler object at 0x7b0ebdbc4340>, 94832.044673175)]\ndata_gen   = <function test_stream_request_on_server_eof_nested.<locals>.data_gen at 0x7b0ebdaf7280>\nfirst_conn = <aiohttp.client_proto.ResponseHandler object at 0x7b0ebdbc4e80>\nhandler    = <function test_stream_request_on_server_eof_nested.<locals>.handler at 0x7b0ebdaf70d0>\nresp       = <ClientResponse(http://127.0.0.1:38875/) [200 OK]>\n<CIMultiDictProxy('Content-Type': 'text/plain; charset=utf-8', 'Content-Length': '2', 'Date': 'Thu, 02 Jan 2025 05:41:15 GMT', 'Server': 'Python/3.9 aiohttp/3.10.6.dev0')>\n\nresp2      = <ClientResponse(http://127.0.0.1:38875/) [200 OK]>\n<CIMultiDictProxy('Content-Type': 'text/plain; charset=utf-8', 'Content-Length': '2', 'Date': 'Thu, 02 Jan 2025 05:41:15 GMT', 'Server': 'Python/3.9 aiohttp/3.10.6.dev0')>\n\n\nr2e_tests/test_1.py:376: AssertionError\n_________________________ test_rejected_upload[pyloop] _________________________\n\naiohttp_client = <function aiohttp_client.<locals>.go at 0x7b0ebdb55d30>\ntmp_path = PosixPath('/tmp/pytest-of-gcpuser/pytest-618/test_rejected_upload_pyloop_0')\n\n    async def test_rejected_upload(\n        aiohttp_client: AiohttpClient, tmp_path: pathlib.Path\n    ) -> None:\n        async def ok_handler(request: web.Request) -> web.Response:\n            return web.Response()\n    \n        async def not_ok_handler(request):\n            raise web.HTTPBadRequest()\n    \n        app = web.Application()\n        app.router.add_get(\"/ok\", ok_handler)\n        app.router.add_post(\"/not_ok\", not_ok_handler)\n        client = await aiohttp_client(app)\n    \n        file_size_bytes = 1024 * 1024\n        file_path = tmp_path / \"uploaded.txt\"\n        file_path.write_text(\"0\" * file_size_bytes, encoding=\"utf8\")\n    \n        with open(file_path, \"rb\") as file:\n            data = {\"file\": file}\n            async with client.post(\"/not_ok\", data=data) as resp_not_ok:\n                assert resp_not_ok.status == 400\n    \n>       async with client.get(\"/ok\", timeout=aiohttp.ClientTimeout(total=1)) as resp_ok:\n\naiohttp_client = <function aiohttp_client.<locals>.go at 0x7b0ebdb55d30>\napp        = <Application 0x7b0ebd143730>\nclient     = <aiohttp.test_utils.TestClient object at 0x7b0ebd143310>\ndata       = {'file': <_io.BufferedReader name='/tmp/pytest-of-gcpuser/pytest-618/test_rejected_upload_pyloop_0/uploaded.txt'>}\nfile       = <_io.BufferedReader name='/tmp/pytest-of-gcpuser/pytest-618/test_rejected_upload_pyloop_0/uploaded.txt'>\nfile_path  = PosixPath('/tmp/pytest-of-gcpuser/pytest-618/test_rejected_upload_pyloop_0/uploaded.txt')\nfile_size_bytes = 1048576\nnot_ok_handler = <function test_rejected_upload.<locals>.not_ok_handler at 0x7b0ebd16e4c0>\nok_handler = <function test_rejected_upload.<locals>.ok_handler at 0x7b0ebd16e430>\nresp_not_ok = <ClientResponse(http://127.0.0.1:45999/not_ok) [400 Bad Request]>\n<CIMultiDictProxy('Content-Type': 'text/plain; charset=utf-8', 'Content-Length': '16', 'Date': 'Thu, 02 Jan 2025 05:41:28 GMT', 'Server': 'Python/3.9 aiohttp/3.10.6.dev0')>\n\ntmp_path   = PosixPath('/tmp/pytest-of-gcpuser/pytest-618/test_rejected_upload_pyloop_0')\n\nr2e_tests/test_1.py:3685: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \naiohttp/client.py:1353: in __aenter__\n    self._resp = await self._coro\n        self       = <aiohttp.client._RequestContextManager object at 0x7b0ebd1ba8e0>\naiohttp/test_utils.py:316: in _request\n    resp = await self._session.request(method, self.make_url(path), **kwargs)\n        kwargs     = {'timeout': ClientTimeout(total=1, connect=None, sock_read=None, sock_connect=None, ceil_threshold=5)}\n        method     = 'GET'\n        path       = '/ok'\n        self       = <aiohttp.test_utils.TestClient object at 0x7b0ebd143310>\naiohttp/client.py:684: in _request\n    await resp.start(conn)\n        all_cookies = <SimpleCookie: >\n        allow_redirects = True\n        auth       = None\n        auth_from_url = None\n        auto_decompress = True\n        chunked    = None\n        compress   = None\n        conn       = Connection<ConnectionKey(host='127.0.0.1', port=45999, is_ssl=False, ssl=True, proxy=None, proxy_auth=None, proxy_headers_hash=None)>\n        cookies    = None\n        data       = None\n        expect100  = False\n        fingerprint = None\n        handle     = None\n        headers    = <CIMultiDict()>\n        history    = []\n        json       = None\n        max_field_size = 8190\n        max_line_size = 8190\n        max_redirects = 10\n        method     = 'GET'\n        params     = {}\n        proxy      = None\n        proxy_auth = None\n        proxy_headers = <CIMultiDict()>\n        raise_for_status = None\n        read_bufsize = 65536\n        read_until_eof = True\n        real_timeout = ClientTimeout(total=1, connect=None, sock_read=None, sock_connect=None, ceil_threshold=5)\n        redirects  = 0\n        req        = <aiohttp.client_reqrep.ClientRequest object at 0x7b0ebd1ba4f0>\n        resp       = <ClientResponse(http://127.0.0.1:45999/ok) [None None]>\nNone\n\n        retry_persistent_connection = True\n        self       = <aiohttp.client.ClientSession object at 0x7b0ebd143e50>\n        server_hostname = None\n        skip_auto_headers = None\n        skip_headers = set()\n        ssl        = True\n        ssl_context = None\n        str_or_url = URL('http://127.0.0.1:45999/ok')\n        timeout    = ClientTimeout(total=1, connect=None, sock_read=None, sock_connect=None, ceil_threshold=5)\n        timer      = <aiohttp.helpers.TimerContext object at 0x7b0ebd1baca0>\n        tm         = <aiohttp.helpers.TimeoutHandle object at 0x7b0ebd1baf40>\n        trace_request_ctx = None\n        traces     = []\n        url        = URL('http://127.0.0.1:45999/ok')\n        verify_ssl = None\n        version    = HttpVersion(major=1, minor=1)\naiohttp/client_reqrep.py:1017: in start\n    self._continue = None\n        connection = Connection<ConnectionKey(host='127.0.0.1', port=45999, is_ssl=False, ssl=True, proxy=None, proxy_auth=None, proxy_headers_hash=None)>\n        protocol   = <aiohttp.client_proto.ResponseHandler object at 0x7b0ebd0a19a0>\n        self       = <ClientResponse(http://127.0.0.1:45999/ok) [None None]>\nNone\n\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = <aiohttp.helpers.TimerContext object at 0x7b0ebd1baca0>\nexc_type = <class 'asyncio.exceptions.CancelledError'>\nexc_val = CancelledError(), exc_tb = <traceback object at 0x7b0ebd14b800>\n\n    def __exit__(\n        self,\n        exc_type: Optional[Type[BaseException]],\n        exc_val: Optional[BaseException],\n        exc_tb: Optional[TracebackType],\n    ) -> Optional[bool]:\n        if self._tasks:\n            self._tasks.pop()\n    \n        if exc_type is asyncio.CancelledError and self._cancelled:\n>           raise asyncio.TimeoutError from None\nE           asyncio.exceptions.TimeoutError\n\nexc_tb     = <traceback object at 0x7b0ebd14b800>\nexc_type   = <class 'asyncio.exceptions.CancelledError'>\nexc_val    = CancelledError()\nself       = <aiohttp.helpers.TimerContext object at 0x7b0ebd1baca0>\n\naiohttp/helpers.py:713: TimeoutError\n==================================== PASSES ====================================\n______________________ test_keepalive_timeout_sync_sleep _______________________\n------------------------------ Captured log call -------------------------------\nERROR    asyncio:base_events.py:1753 Task exception was never retrieved\nfuture: <Task finished name='Task-116' coro=<RequestHandler.start() done, defined at /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/web_protocol.py:484> exception=AssertionError()>\nTraceback (most recent call last):\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/web_protocol.py\", line 527, in start\n    request = self._request_factory(message, payload, self, writer, handler)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/web_app.py\", line 479, in _make_request\n    return _cls(\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/web_request.py\", line 845, in __init__\n    super().__init__(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/aiohttp/web_request.py\", line 204, in __init__\n    assert transport is not None\nAssertionError\n__________________ test_readline_error_on_conn_close[pyloop] ___________________\n------------------------------ Captured log call -------------------------------\nERROR    asyncio:base_events.py:1753 Exception in callback test_readline_error_on_conn_close.<locals>.do_release() at /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/r2e_tests/test_1.py:1038\nhandle: <TimerHandle when=94837.610124833 test_readline_error_on_conn_close.<locals>.do_release() at /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/r2e_tests/test_1.py:1038>\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/asyncio/events.py\", line 80, in _run\n    self._context.run(self._callback, *self._args)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/r2e_tests/test_1.py\", line 1039, in do_release\n    loop.create_task(resp.release())\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/asyncio/base_events.py\", line 438, in create_task\n    task = tasks.Task(coro, loop=self, name=name)\nTypeError: a coroutine was expected, got <aiohttp.helpers.noop object at 0x7b0ebd098d30>\n---------------------------- Captured log teardown -----------------------------\nERROR    asyncio:base_events.py:1753 Unclosed client session\nclient_session: <aiohttp.client.ClientSession object at 0x7b0ebcea8b50>\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                              97      2      0      0    98%\naiohttp/base_protocol.py                    67     28     22      5    49%\naiohttp/client.py                          545    117    196     23    76%\naiohttp/client_exceptions.py               154     35     20      3    74%\naiohttp/client_proto.py                    165     29     56     10    79%\naiohttp/client_reqrep.py                   695    134    300     63    76%\naiohttp/client_ws.py                       259    212     80      1    14%\naiohttp/compression_utils.py                70     15     14      1    71%\naiohttp/connector.py                       775    288    321     53    56%\naiohttp/cookiejar.py                       255     59    118     23    74%\naiohttp/formdata.py                         97     16     46      7    81%\naiohttp/hdrs.py                             90      0      0      0   100%\naiohttp/helpers.py                         501    173    172     25    61%\naiohttp/http.py                             11      0      2      0   100%\naiohttp/http_exceptions.py                  50     10      4      1    76%\naiohttp/http_parser.py                     504    349    208     11    24%\naiohttp/http_websocket.py                  393    287    152      0    20%\naiohttp/http_writer.py                     118     12     50      5    86%\naiohttp/locks.py                            24     10      4      0    50%\naiohttp/log.py                               7      0      0      0   100%\naiohttp/multipart.py                       623    292    266     48    46%\naiohttp/payload.py                         237     22     58     12    86%\naiohttp/payload_streamer.py                 31      1      4      0    97%\naiohttp/pytest_plugin.py                   162     47     42      7    69%\naiohttp/resolver.py                         80     39     26      4    44%\naiohttp/streams.py                         398    115    146     19    67%\naiohttp/tcp_helpers.py                      19      2      6      3    80%\naiohttp/test_utils.py                      315    110     50     11    61%\naiohttp/tracing.py                         191     17     32      0    92%\naiohttp/typedefs.py                         23      0      0      0   100%\naiohttp/web.py                             122     84     52      0    23%\naiohttp/web_app.py                         282     97     74     18    59%\naiohttp/web_exceptions.py                  157     16      8      3    87%\naiohttp/web_fileresponse.py                163    127     54      1    19%\naiohttp/web_log.py                         102     37     20      1    59%\naiohttp/web_middlewares.py                  55     37     20      0    24%\naiohttp/web_protocol.py                    354     95    155     47    66%\naiohttp/web_request.py                     445    180    138     21    53%\naiohttp/web_response.py                    479    119    220     53    69%\naiohttp/web_routedef.py                    100     37     10      1    62%\naiohttp/web_runner.py                      213     61     36     12    67%\naiohttp/web_server.py                       42      5     12      1    85%\naiohttp/web_urldispatcher.py               742    324    161     23    52%\naiohttp/web_ws.py                          382    310    132      1    15%\naiohttp/worker.py                          126    126     30      0     0%\ntests/conftest.py                          130    130     16      0     0%\ntests/test_base_protocol.py                198    198      2      0     0%\ntests/test_circular_imports.py              29     29     13      0     0%\ntests/test_classbasedview.py                39     39      0      0     0%\ntests/test_client_connection.py             94     94      2      0     0%\ntests/test_client_exceptions.py            199    199     14      0     0%\ntests/test_client_fingerprint.py            59     59      0      0     0%\ntests/test_client_functional.py           2455   2455     86      0     0%\ntests/test_client_proto.py                  99     99      0      0     0%\ntests/test_client_request.py               808    808     18      0     0%\ntests/test_client_response.py              466    466      4      0     0%\ntests/test_client_session.py               556    556     29      0     0%\ntests/test_client_ws.py                    486    486      2      0     0%\ntests/test_client_ws_functional.py         750    750     32      0     0%\ntests/test_connector.py                   1697   1697     82      0     0%\ntests/test_cookiejar.py                    350    350     24      0     0%\ntests/test_flowcontrol_streams.py          100    100      0      0     0%\ntests/test_formdata.py                      81     81      6      0     0%\ntests/test_helpers.py                      470    470     24      0     0%\ntests/test_http_exceptions.py              109    109     10      0     0%\ntests/test_http_parser.py                 1088   1088     66      0     0%\ntests/test_http_writer.py                  182    182     10      0     0%\ntests/test_imports.py                       34     34      6      0     0%\ntests/test_locks.py                         39     39      0      0     0%\ntests/test_loop.py                          36     36      0      0     0%\ntests/test_multipart.py                    826    826     32      0     0%\ntests/test_multipart_helpers.py            446    446      0      0     0%\ntests/test_payload.py                       95     95      0      0     0%\ntests/test_proxy.py                        301    301      0      0     0%\ntests/test_proxy_functional.py             459    459     18      0     0%\ntests/test_pytest_plugin.py                 27     27      0      0     0%\ntests/test_resolver.py                     193    193     20      0     0%\ntests/test_route_def.py                    210    210      0      0     0%\ntests/test_run_app.py                      563    563     30      0     0%\ntests/test_streams.py                     1076   1076     38      0     0%\ntests/test_tcp_helpers.py                   52     52      2      0     0%\ntests/test_test_utils.py                   244    244      6      0     0%\ntests/test_tracing.py                       48     48      0      0     0%\ntests/test_urldispatch.py                  851    851     24      0     0%\ntests/test_web_app.py                      454    454      6      0     0%\ntests/test_web_cli.py                       75     75      0      0     0%\ntests/test_web_exceptions.py               176    176     22      0     0%\ntests/test_web_functional.py              1552   1552     34      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                  507    507      8      0     0%\ntests/test_web_request_handler.py           42     42      0      0     0%\ntests/test_web_response.py                 885    885      6      0     0%\ntests/test_web_runner.py                   151    151      4      0     0%\ntests/test_web_sendfile.py                  84     84      0      0     0%\ntests/test_web_sendfile_functional.py      655    655     18      0     0%\ntests/test_web_server.py                   162    162      0      0     0%\ntests/test_web_urldispatcher.py            517    517     24      0     0%\ntests/test_web_websocket.py                401    401      8      0     0%\ntests/test_web_websocket_functional.py     769    769     28      0     0%\ntests/test_websocket_handshake.py          152    152     12      0     0%\ntests/test_websocket_parser.py             300    300     12      0     0%\ntests/test_websocket_writer.py              95     95      6      0     0%\ntests/test_worker.py                       191    191      2      0     0%\n--------------------------------------------------------------------------\nTOTAL                                    34242  27579   4339    518    21%\n\n============================= slowest 10 durations =============================\n2.01s call     r2e_tests/test_1.py::test_read_timeout_between_chunks[pyloop]\n2.00s call     r2e_tests/test_1.py::test_set_cookies_max_age[pyloop]\n1.01s call     r2e_tests/test_1.py::test_rejected_upload[pyloop]\n1.01s call     r2e_tests/test_1.py::test_readline_error_on_conn_close[pyloop]\n1.00s call     r2e_tests/test_1.py::test_timeout_on_reading_data[pyloop]\n0.51s call     r2e_tests/test_1.py::test_timeout_with_full_buffer[pyloop]\n0.50s call     r2e_tests/test_1.py::test_no_error_on_conn_close_if_eof[pyloop]\n0.50s call     r2e_tests/test_1.py::test_read_timeout_on_write[pyloop]\n0.21s call     r2e_tests/test_1.py::test_read_timeout_closes_connection[pyloop]\n0.20s call     r2e_tests/test_1.py::test_read_timeout_on_reading_chunks[pyloop]\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::test_keepalive_two_requests_success[pyloop]\nPASSED r2e_tests/test_1.py::test_keepalive_after_head_requests_success[pyloop]\nPASSED r2e_tests/test_1.py::test_keepalive_after_empty_body_status[pyloop-101]\nPASSED r2e_tests/test_1.py::test_keepalive_after_empty_body_status[pyloop-204]\nPASSED r2e_tests/test_1.py::test_keepalive_after_empty_body_status[pyloop-304]\nPASSED r2e_tests/test_1.py::test_keepalive_after_empty_body_status_stream_response[pyloop-101]\nPASSED r2e_tests/test_1.py::test_keepalive_after_empty_body_status_stream_response[pyloop-204]\nPASSED r2e_tests/test_1.py::test_keepalive_after_empty_body_status_stream_response[pyloop-304]\nPASSED r2e_tests/test_1.py::test_keepalive_response_released[pyloop]\nPASSED r2e_tests/test_1.py::test_upgrade_connection_not_released_after_read[pyloop]\nPASSED r2e_tests/test_1.py::test_keepalive_server_force_close_connection[pyloop]\nPASSED r2e_tests/test_1.py::test_keepalive_timeout_async_sleep\nPASSED r2e_tests/test_1.py::test_keepalive_timeout_sync_sleep\nPASSED r2e_tests/test_1.py::test_release_early[pyloop]\nPASSED r2e_tests/test_1.py::test_HTTP_304[pyloop]\nPASSED r2e_tests/test_1.py::test_HTTP_304_WITH_BODY[pyloop]\nPASSED r2e_tests/test_1.py::test_auto_header_user_agent[pyloop]\nPASSED r2e_tests/test_1.py::test_skip_auto_headers_user_agent[pyloop]\nPASSED r2e_tests/test_1.py::test_skip_default_auto_headers_user_agent[pyloop]\nPASSED r2e_tests/test_1.py::test_skip_auto_headers_content_type[pyloop]\nPASSED r2e_tests/test_1.py::test_post_data_bytesio[pyloop]\nPASSED r2e_tests/test_1.py::test_post_data_with_bytesio_file[pyloop]\nPASSED r2e_tests/test_1.py::test_post_data_stringio[pyloop]\nPASSED r2e_tests/test_1.py::test_post_data_textio_encoding[pyloop]\nPASSED r2e_tests/test_1.py::test_post_data_zipfile_filelike[pyloop]\nPASSED r2e_tests/test_1.py::test_post_data_tarfile_filelike[pyloop]\nPASSED r2e_tests/test_1.py::test_ssl_client[pyloop]\nPASSED r2e_tests/test_1.py::test_tcp_connector_fingerprint_ok[pyloop]\nPASSED r2e_tests/test_1.py::test_tcp_connector_fingerprint_fail[pyloop]\nPASSED r2e_tests/test_1.py::test_format_task_get[pyloop]\nPASSED r2e_tests/test_1.py::test_str_params[pyloop]\nPASSED r2e_tests/test_1.py::test_drop_params_on_redirect[pyloop]\nPASSED r2e_tests/test_1.py::test_drop_fragment_on_redirect[pyloop]\nPASSED r2e_tests/test_1.py::test_drop_fragment[pyloop]\nPASSED r2e_tests/test_1.py::test_history[pyloop]\nPASSED r2e_tests/test_1.py::test_keepalive_closed_by_server[pyloop]\nPASSED r2e_tests/test_1.py::test_wait_for[pyloop]\nPASSED r2e_tests/test_1.py::test_raw_headers[pyloop]\nPASSED r2e_tests/test_1.py::test_host_header_first[pyloop]\nPASSED r2e_tests/test_1.py::test_empty_header_values[pyloop]\nPASSED r2e_tests/test_1.py::test_204_with_gzipped_content_encoding[pyloop]\nPASSED r2e_tests/test_1.py::test_timeout_on_reading_headers[pyloop]\nPASSED r2e_tests/test_1.py::test_timeout_on_conn_reading_headers[pyloop]\nPASSED r2e_tests/test_1.py::test_timeout_on_session_read_timeout[pyloop]\nPASSED r2e_tests/test_1.py::test_read_timeout_between_chunks[pyloop]\nPASSED r2e_tests/test_1.py::test_read_timeout_on_reading_chunks[pyloop]\nPASSED r2e_tests/test_1.py::test_read_timeout_on_write[pyloop]\nPASSED r2e_tests/test_1.py::test_timeout_on_reading_data[pyloop]\nPASSED r2e_tests/test_1.py::test_timeout_none[pyloop]\nPASSED r2e_tests/test_1.py::test_readline_error_on_conn_close[pyloop]\nPASSED r2e_tests/test_1.py::test_no_error_on_conn_close_if_eof[pyloop]\nPASSED r2e_tests/test_1.py::test_error_not_overwrote_on_conn_close[pyloop]\nPASSED r2e_tests/test_1.py::test_HTTP_200_OK_METHOD[pyloop]\nPASSED r2e_tests/test_1.py::test_HTTP_200_OK_METHOD_connector[pyloop]\nPASSED r2e_tests/test_1.py::test_HTTP_302_REDIRECT_GET[pyloop]\nPASSED r2e_tests/test_1.py::test_HTTP_302_REDIRECT_HEAD[pyloop]\nPASSED r2e_tests/test_1.py::test_HTTP_302_REDIRECT_NON_HTTP[pyloop]\nPASSED r2e_tests/test_1.py::test_HTTP_302_REDIRECT_POST[pyloop]\nPASSED r2e_tests/test_1.py::test_HTTP_302_REDIRECT_POST_with_content_length_hdr[pyloop]\nPASSED r2e_tests/test_1.py::test_HTTP_307_REDIRECT_POST[pyloop]\nPASSED r2e_tests/test_1.py::test_HTTP_308_PERMANENT_REDIRECT_POST[pyloop]\nPASSED r2e_tests/test_1.py::test_HTTP_302_max_redirects[pyloop]\nPASSED r2e_tests/test_1.py::test_HTTP_200_GET_WITH_PARAMS[pyloop]\nPASSED r2e_tests/test_1.py::test_HTTP_200_GET_WITH_MultiDict_PARAMS[pyloop]\nPASSED r2e_tests/test_1.py::test_HTTP_200_GET_WITH_MIXED_PARAMS[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_DATA[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_DATA_with_explicit_formdata[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_DATA_with_charset[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_DATA_formdats_with_charset[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_DATA_with_charset_post[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_MultiDict[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_DATA_DEFLATE[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_FILES[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_FILES_DEFLATE[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_bytes[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_bytes_too_large[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_FILES_STR[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_FILES_STR_SIMPLE[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_FILES_LIST[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_FILES_CT[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_FILES_SINGLE[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_FILES_SINGLE_content_disposition[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_FILES_SINGLE_BINARY[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_FILES_IO[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_FILES_IO_WITH_PARAMS[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_FILES_WITH_DATA[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_STREAM_DATA[pyloop]\nPASSED r2e_tests/test_1.py::test_POST_STREAM_DATA_no_params[pyloop]\nPASSED r2e_tests/test_1.py::test_json[pyloop]\nPASSED r2e_tests/test_1.py::test_json_custom[pyloop]\nPASSED r2e_tests/test_1.py::test_expect_continue[pyloop]\nPASSED r2e_tests/test_1.py::test_encoding_deflate[pyloop]\nPASSED r2e_tests/test_1.py::test_encoding_deflate_nochunk[pyloop]\nPASSED r2e_tests/test_1.py::test_encoding_gzip[pyloop]\nPASSED r2e_tests/test_1.py::test_encoding_gzip_write_by_chunks[pyloop]\nPASSED r2e_tests/test_1.py::test_encoding_gzip_nochunk[pyloop]\nPASSED r2e_tests/test_1.py::test_bad_payload_compression[pyloop]\nPASSED r2e_tests/test_1.py::test_bad_payload_chunked_encoding[pyloop]\nPASSED r2e_tests/test_1.py::test_no_payload_304_with_chunked_encoding[pyloop]\nPASSED r2e_tests/test_1.py::test_head_request_with_chunked_encoding[pyloop]\nPASSED r2e_tests/test_1.py::test_no_payload_200_with_chunked_encoding[pyloop]\nPASSED r2e_tests/test_1.py::test_bad_payload_content_length[pyloop]\nPASSED r2e_tests/test_1.py::test_payload_content_length_by_chunks[pyloop]\nPASSED r2e_tests/test_1.py::test_chunked[pyloop]\nPASSED r2e_tests/test_1.py::test_shortcuts[pyloop]\nPASSED r2e_tests/test_1.py::test_cookies[pyloop]\nPASSED r2e_tests/test_1.py::test_cookies_per_request[pyloop]\nPASSED r2e_tests/test_1.py::test_cookies_redirect[pyloop]\nPASSED r2e_tests/test_1.py::test_cookies_on_empty_session_jar[pyloop]\nPASSED r2e_tests/test_1.py::test_morsel_with_attributes[pyloop]\nPASSED r2e_tests/test_1.py::test_set_cookies[pyloop]\nPASSED r2e_tests/test_1.py::test_set_cookies_expired[pyloop]\nPASSED r2e_tests/test_1.py::test_set_cookies_max_age[pyloop]\nPASSED r2e_tests/test_1.py::test_set_cookies_max_age_overflow[pyloop]\nPASSED r2e_tests/test_1.py::test_request_conn_error\nPASSED r2e_tests/test_1.py::test_broken_connection_2[pyloop]\nPASSED r2e_tests/test_1.py::test_custom_headers[pyloop]\nPASSED r2e_tests/test_1.py::test_redirect_to_absolute_url[pyloop]\nPASSED r2e_tests/test_1.py::test_redirect_without_location_header[pyloop]\nPASSED r2e_tests/test_1.py::test_chunked_deprecated[pyloop]\nPASSED r2e_tests/test_1.py::test_invalid_and_non_http_url[http://:/-http://:/-InvalidUrlClientError]\nPASSED r2e_tests/test_1.py::test_invalid_and_non_http_url[http://example.org:non_int_port/-http://example.org:non_int_port/-InvalidUrlClientError]\nPASSED r2e_tests/test_1.py::test_invalid_and_non_http_url[http:/-http:///-InvalidUrlClientError]\nPASSED r2e_tests/test_1.py::test_invalid_and_non_http_url[http:/example.com-http:///example.com-InvalidUrlClientError]\nPASSED r2e_tests/test_1.py::test_invalid_and_non_http_url[http:///example.com-http:///example.com-InvalidUrlClientError]\nPASSED r2e_tests/test_1.py::test_invalid_and_non_http_url[call:+380123456789-call:\\\\+380123456789-NonHttpUrlClientError]\nPASSED r2e_tests/test_1.py::test_invalid_and_non_http_url[skype:handle-skype:handle-NonHttpUrlClientError]\nPASSED r2e_tests/test_1.py::test_invalid_and_non_http_url[slack://instance/room-slack://instance/room-NonHttpUrlClientError]\nPASSED r2e_tests/test_1.py::test_invalid_and_non_http_url[steam:code-steam:code-NonHttpUrlClientError]\nPASSED r2e_tests/test_1.py::test_invalid_and_non_http_url[twitter://handle-twitter://handle-NonHttpUrlClientError]\nPASSED r2e_tests/test_1.py::test_invalid_and_non_http_url[bluesky://profile/d:i:d-bluesky://profile/d:i:d-NonHttpUrlClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url[pyloop-http:/-http:///-InvalidUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url[pyloop-http:/example.com-http:///example.com-InvalidUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url[pyloop-http:///example.com-http:///example.com-InvalidUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url[pyloop-http://:/-http://:/-InvalidUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url[pyloop-http://example.org:non_int_port/-http://example.org:non_int_port/-InvalidUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url[pyloop-call:+380123456789-call:\\\\+380123456789-NonHttpUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url[pyloop-skype:handle-skype:handle-NonHttpUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url[pyloop-slack://instance/room-slack://instance/room-NonHttpUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url[pyloop-steam:code-steam:code-NonHttpUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url[pyloop-twitter://handle-twitter://handle-NonHttpUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url[pyloop-bluesky://profile/d:i:d-bluesky://profile/d:i:d-NonHttpUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-http:/-http:///-InvalidUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-http:/example.com-http:///example.com-InvalidUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-http:///example.com-http:///example.com-InvalidUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-http://:/-http://:/-InvalidUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-http://example.org:non_int_port/-http://example.org:non_int_port/-InvalidUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-call:+380123456789-call:\\\\+380123456789-NonHttpUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-skype:handle-skype:handle-NonHttpUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-slack://instance/room-slack://instance/room-NonHttpUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-steam:code-steam:code-NonHttpUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-twitter://handle-twitter://handle-NonHttpUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_invalid_redirect_url_multiple_redirects[pyloop-bluesky://profile/d:i:d-bluesky://profile/d:i:d-NonHttpUrlRedirectClientError]\nPASSED r2e_tests/test_1.py::test_ok_from_status[pyloop-200-True]\nPASSED r2e_tests/test_1.py::test_ok_from_status[pyloop-201-True]\nPASSED r2e_tests/test_1.py::test_ok_from_status[pyloop-301-True]\nPASSED r2e_tests/test_1.py::test_ok_from_status[pyloop-400-False]\nPASSED r2e_tests/test_1.py::test_ok_from_status[pyloop-403-False]\nPASSED r2e_tests/test_1.py::test_ok_from_status[pyloop-500-False]\nPASSED r2e_tests/test_1.py::test_raise_for_status[pyloop]\nPASSED r2e_tests/test_1.py::test_raise_for_status_per_request[pyloop]\nPASSED r2e_tests/test_1.py::test_raise_for_status_disable_per_request[pyloop]\nPASSED r2e_tests/test_1.py::test_request_raise_for_status_default[pyloop]\nPASSED r2e_tests/test_1.py::test_request_raise_for_status_disabled[pyloop]\nPASSED r2e_tests/test_1.py::test_request_raise_for_status_enabled[pyloop]\nPASSED r2e_tests/test_1.py::test_session_raise_for_status_coro[pyloop]\nPASSED r2e_tests/test_1.py::test_request_raise_for_status_coro[pyloop]\nPASSED r2e_tests/test_1.py::test_invalid_idna\nPASSED r2e_tests/test_1.py::test_creds_in_auth_and_url\nPASSED r2e_tests/test_1.py::test_drop_auth_on_redirect_to_other_host[pyloop-entirely different hosts]\nPASSED r2e_tests/test_1.py::test_drop_auth_on_redirect_to_other_host[pyloop-http -> https]\nPASSED r2e_tests/test_1.py::test_drop_auth_on_redirect_to_other_host[pyloop-https -> http]\nPASSED r2e_tests/test_1.py::test_async_with_session\nPASSED r2e_tests/test_1.py::test_session_close_awaitable\nPASSED r2e_tests/test_1.py::test_close_resp_on_error_async_with_session[pyloop]\nPASSED r2e_tests/test_1.py::test_release_resp_on_normal_exit_from_cm[pyloop]\nPASSED r2e_tests/test_1.py::test_non_close_detached_session_on_error_cm[pyloop]\nPASSED r2e_tests/test_1.py::test_close_detached_session_on_non_existing_addr\nPASSED r2e_tests/test_1.py::test_aiohttp_request_context_manager[pyloop]\nPASSED r2e_tests/test_1.py::test_aiohttp_request_ctx_manager_close_sess_on_error[pyloop]\nPASSED r2e_tests/test_1.py::test_aiohttp_request_ctx_manager_not_found\nPASSED r2e_tests/test_1.py::test_yield_from_in_session_request[pyloop]\nPASSED r2e_tests/test_1.py::test_close_context_manager[pyloop]\nPASSED r2e_tests/test_1.py::test_session_auth[pyloop]\nPASSED r2e_tests/test_1.py::test_session_auth_override[pyloop]\nPASSED r2e_tests/test_1.py::test_session_auth_header_conflict[pyloop]\nPASSED r2e_tests/test_1.py::test_session_headers[pyloop]\nPASSED r2e_tests/test_1.py::test_session_headers_merge[pyloop]\nPASSED r2e_tests/test_1.py::test_multidict_headers[pyloop]\nPASSED r2e_tests/test_1.py::test_request_conn_closed[pyloop]\nPASSED r2e_tests/test_1.py::test_dont_close_explicit_connector[pyloop]\nPASSED r2e_tests/test_1.py::test_server_close_keepalive_connection\nPASSED r2e_tests/test_1.py::test_handle_keepalive_on_closed_connection\nPASSED r2e_tests/test_1.py::test_error_in_performing_request[pyloop]\nPASSED r2e_tests/test_1.py::test_await_after_cancelling[pyloop]\nPASSED r2e_tests/test_1.py::test_async_payload_generator[pyloop]\nPASSED r2e_tests/test_1.py::test_read_from_closed_response[pyloop]\nPASSED r2e_tests/test_1.py::test_read_from_closed_response2[pyloop]\nPASSED r2e_tests/test_1.py::test_read_from_closed_content[pyloop]\nPASSED r2e_tests/test_1.py::test_read_timeout[pyloop]\nPASSED r2e_tests/test_1.py::test_socket_timeout[pyloop]\nPASSED r2e_tests/test_1.py::test_read_timeout_closes_connection[pyloop]\nPASSED r2e_tests/test_1.py::test_read_timeout_on_prepared_response[pyloop]\nPASSED r2e_tests/test_1.py::test_timeout_with_full_buffer[pyloop]\nPASSED r2e_tests/test_1.py::test_read_bufsize_session_default[pyloop]\nPASSED r2e_tests/test_1.py::test_read_bufsize_explicit[pyloop]\nPASSED r2e_tests/test_1.py::test_http_empty_data_text[pyloop]\nPASSED r2e_tests/test_1.py::test_max_field_size_session_default[pyloop]\nPASSED r2e_tests/test_1.py::test_max_field_size_session_default_fail[pyloop]\nPASSED r2e_tests/test_1.py::test_max_field_size_session_explicit[pyloop]\nPASSED r2e_tests/test_1.py::test_max_field_size_request_explicit[pyloop]\nPASSED r2e_tests/test_1.py::test_max_line_size_session_default[pyloop]\nPASSED r2e_tests/test_1.py::test_max_line_size_session_default_fail[pyloop]\nPASSED r2e_tests/test_1.py::test_max_line_size_session_explicit[pyloop]\nPASSED r2e_tests/test_1.py::test_max_line_size_request_explicit[pyloop]\nPASSED r2e_tests/test_1.py::test_request_with_wrong_proxy[pyloop-42-TypeError]\nPASSED r2e_tests/test_1.py::test_request_with_wrong_proxy[pyloop-InvalidUrl-InvalidURL]\nPASSED r2e_tests/test_1.py::test_raise_for_status_is_none[pyloop]\nPASSED r2e_tests/test_1.py::test_exception_when_read_outside_of_session[pyloop]\nXFAIL r2e_tests/test_1.py::test_broken_connection[pyloop]\nFAILED r2e_tests/test_1.py::test_stream_request_on_server_eof[pyloop] - asser...\nFAILED r2e_tests/test_1.py::test_stream_request_on_server_eof_nested[pyloop]\nFAILED r2e_tests/test_1.py::test_rejected_upload[pyloop] - asyncio.exceptions...\n================== 3 failed, 219 passed, 1 xfailed in 18.52s ===================\n",
    "old_commit_res_stderr": "/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_fecb85a9291d4cae6c06999c388421cde02c9860/.venv/lib/python3.9/site-packages/pytest_asyncio/plugin.py:207: PytestDeprecationWarning: The configuration option \"asyncio_default_fixture_loop_scope\" is unset.\nThe event loop scope for asynchronous fixtures will default to the fixture caching scope. Future versions of pytest-asyncio will default the loop scope for asynchronous fixtures to function scope. Set the default fixture loop scope explicitly in order to avoid unexpected behavior in the future. Valid fixture loop scopes are: \"function\", \"class\", \"module\", \"package\", \"session\"\n\n  warnings.warn(PytestDeprecationWarning(_DEFAULT_FIXTURE_LOOP_SCOPE_UNSET))\n"
}
CHANGES/8992.bugfix.rst aiohttp/client_reqrep.py tests/test_client_functional.py
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]

**Title:** Canceling Payload Send Causes Connection to Hang and Prevents Reuse

**Description:**
When a client cancels sending the payload during a request, the connection remains open instead of being properly closed. This prevents the connection from being reused for subsequent requests, leading to hung connections and timeout errors.

**Example Code:**
```python
async def upload_file(client, file_path):
    with open(file_path, "rb") as file:
        data = {'file': file}
        await client.post("/upload", data=data)
        await client.get("/status", timeout=0.01)  # This request hangs due to the open connection
```

**Expected Behavior:**
After canceling the payload send, the connection should be closed properly, allowing the client to reuse connections for new requests without any hanging or timeout issues.

**Actual Behavior:**
The connection remains open after the payload send is canceled, causing subsequent requests to hang and eventually timeout because the connection cannot be reused.

[/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_reqrep.py
import asyncio
import codecs
import contextlib
import functools
import io
import re
import sys
import traceback
import warnings
from hashlib import md5, sha1, sha256
from http.cookies import CookieError, Morsel, SimpleCookie
from types import MappingProxyType, TracebackType
from typing import (
    TYPE_CHECKING,
    Any,
    Callable,
    Dict,
    Iterable,
    List,
    Mapping,
    Optional,
    Tuple,
    Type,
    Union,
    cast,
)

import attr
from multidict import CIMultiDict, CIMultiDictProxy, MultiDict, MultiDictProxy
from yarl import URL

from . import hdrs, helpers, http, multipart, payload
from .abc import AbstractStreamWriter
from .client_exceptions import (
    ClientConnectionError,
    ClientOSError,
    ClientResponseError,
    ContentTypeError,
    InvalidURL,
    ServerFingerprintMismatch,
)
from .compression_utils import HAS_BROTLI
from .formdata import FormData
from .helpers import (
    BaseTimerContext,
    BasicAuth,
    HeadersMixin,
    TimerNoop,
    basicauth_from_netrc,
    netrc_from_env,
    noop,
    reify,
    set_exception,
    set_result,
)
from .http import (
    SERVER_SOFTWARE,
    HttpVersion,
    HttpVersion10,
    HttpVersion11,
    StreamWriter,
)
from .log import client_logger
from .streams import StreamReader
from .typedefs import (
    DEFAULT_JSON_DECODER,
    JSONDecoder,
    LooseCookies,
    LooseHeaders,
    RawHeaders,
)

try:
    import ssl
    from ssl import SSLContext
except ImportError:  # pragma: no cover
    ssl = None  # type: ignore[assignment]
    SSLContext = object  # type: ignore[misc,assignment]


__all__ = ("ClientRequest", "ClientResponse", "RequestInfo", "Fingerprint")


if TYPE_CHECKING:
    from .client import ClientSession
    from .connector import Connection
    from .tracing import Trace


_CONTAINS_CONTROL_CHAR_RE = re.compile(r"[^-!#$%&'*+.^_`|~0-9a-zA-Z]")
json_re = re.compile(r"^application/(?:[\w.+-]+?\+)?json")


def _gen_default_accept_encoding() -> str:
    return "gzip, deflate, br" if HAS_BROTLI else "gzip, deflate"


@attr.s(auto_attribs=True, frozen=True, slots=True)
class ContentDisposition:
    type: Optional[str]
    parameters: "MappingProxyType[str, str]"
    filename: Optional[str]


@attr.s(auto_attribs=True, frozen=True, slots=True)
class RequestInfo:
    url: URL
    method: str
    headers: "CIMultiDictProxy[str]"
    real_url: URL = attr.ib()

    @real_url.default
    def real_url_default(self) -> URL:
        return self.url


class Fingerprint:
    HASHFUNC_BY_DIGESTLEN = {
        16: md5,
        20: sha1,
        32: sha256,
    }

    def __init__(self, fingerprint: bytes) -> None:
        digestlen = len(fingerprint)
        hashfunc = self.HASHFUNC_BY_DIGESTLEN.get(digestlen)
        if not hashfunc:
            raise ValueError("fingerprint has invalid length")
        elif hashfunc is md5 or hashfunc is sha1:
            raise ValueError(
                "md5 and sha1 are insecure and " "not supported. Use sha256."
            )
        self._hashfunc = hashfunc
        self._fingerprint = fingerprint

    @property
    def fingerprint(self) -> bytes:
        return self._fingerprint

    def check(self, transport: asyncio.Transport) -> None:
        if not transport.get_extra_info("sslcontext"):
            return
        sslobj = transport.get_extra_info("ssl_object")
        cert = sslobj.getpeercert(binary_form=True)
        got = self._hashfunc(cert).digest()
        if got != self._fingerprint:
            host, port, *_ = transport.get_extra_info("peername")
            raise ServerFingerprintMismatch(self._fingerprint, got, host, port)


if ssl is not None:
    SSL_ALLOWED_TYPES = (ssl.SSLContext, bool, Fingerprint, type(None))
else:  # pragma: no cover
    SSL_ALLOWED_TYPES = (bool, type(None))


def _merge_ssl_params(
    ssl: Union["SSLContext", bool, Fingerprint],
    verify_ssl: Optional[bool],
    ssl_context: Optional["SSLContext"],
    fingerprint: Optional[bytes],
) -> Union["SSLContext", bool, Fingerprint]:
    if ssl is None:
        ssl = True  # Double check for backwards compatibility
    if verify_ssl is not None and not verify_ssl:
        warnings.warn(
            "verify_ssl is deprecated, use ssl=False instead",
            DeprecationWarning,
            stacklevel=3,
        )
        if ssl is not True:
            raise ValueError(
                "verify_ssl, ssl_context, fingerprint and ssl "
                "parameters are mutually exclusive"
            )
        else:
            ssl = False
    if ssl_context is not None:
        warnings.warn(
            "ssl_context is deprecated, use ssl=context instead",
            DeprecationWarning,
            stacklevel=3,
        )
        if ssl is not True:
            raise ValueError(
                "verify_ssl, ssl_context, fingerprint and ssl "
                "parameters are mutually exclusive"
            )
        else:
            ssl = ssl_context
    if fingerprint is not None:
        warnings.warn(
            "fingerprint is deprecated, " "use ssl=Fingerprint(fingerprint) instead",
            DeprecationWarning,
            stacklevel=3,
        )
        if ssl is not True:
            raise ValueError(
                "verify_ssl, ssl_context, fingerprint and ssl "
                "parameters are mutually exclusive"
            )
        else:
            ssl = Fingerprint(fingerprint)
    if not isinstance(ssl, SSL_ALLOWED_TYPES):
        raise TypeError(
            "ssl should be SSLContext, bool, Fingerprint or None, "
            "got {!r} instead.".format(ssl)
        )
    return ssl


@attr.s(auto_attribs=True, slots=True, frozen=True, cache_hash=True)
class ConnectionKey:
    # the key should contain an information about used proxy / TLS
    # to prevent reusing wrong connections from a pool
    host: str
    port: Optional[int]
    is_ssl: bool
    ssl: Union[SSLContext, bool, Fingerprint]
    proxy: Optional[URL]
    proxy_auth: Optional[BasicAuth]
    proxy_headers_hash: Optional[int]  # hash(CIMultiDict)


def _is_expected_content_type(
    response_content_type: str, expected_content_type: str
) -> bool:
    if expected_content_type == "application/json":
        return json_re.match(response_content_type) is not None
    return expected_content_type in response_content_type


class ClientRequest:
    GET_METHODS = {
        hdrs.METH_GET,
        hdrs.METH_HEAD,
        hdrs.METH_OPTIONS,
        hdrs.METH_TRACE,
    }
    POST_METHODS = {hdrs.METH_PATCH, hdrs.METH_POST, hdrs.METH_PUT}
    ALL_METHODS = GET_METHODS.union(POST_METHODS).union({hdrs.METH_DELETE})

    DEFAULT_HEADERS = {
        hdrs.ACCEPT: "*/*",
        hdrs.ACCEPT_ENCODING: _gen_default_accept_encoding(),
    }

    # Type of body depends on PAYLOAD_REGISTRY, which is dynamic.
    body: Any = b""
    auth = None
    response = None

    __writer = None  # async task for streaming data
    _continue = None  # waiter future for '100 Continue' response

    # N.B.
    # Adding __del__ method with self._writer closing doesn't make sense
    # because _writer is instance method, thus it keeps a reference to self.
    # Until writer has finished finalizer will not be called.

    def __init__(
        self,
        method: str,
        url: URL,
        *,
        params: Optional[Mapping[str, str]] = None,
        headers: Optional[LooseHeaders] = None,
        skip_auto_headers: Optional[Iterable[str]] = None,
        data: Any = None,
        cookies: Optional[LooseCookies] = None,
        auth: Optional[BasicAuth] = None,
        version: http.HttpVersion = http.HttpVersion11,
        compress: Optional[str] = None,
        chunked: Optional[bool] = None,
        expect100: bool = False,
        loop: Optional[asyncio.AbstractEventLoop] = None,
        response_class: Optional[Type["ClientResponse"]] = None,
        proxy: Optional[URL] = None,
        proxy_auth: Optional[BasicAuth] = None,
        timer: Optional[BaseTimerContext] = None,
        session: Optional["ClientSession"] = None,
        ssl: Union[SSLContext, bool, Fingerprint] = True,
        proxy_headers: Optional[LooseHeaders] = None,
        traces: Optional[List["Trace"]] = None,
        trust_env: bool = False,
        server_hostname: Optional[str] = None,
    ):
        if loop is None:
            loop = asyncio.get_event_loop()

        match = _CONTAINS_CONTROL_CHAR_RE.search(method)
        if match:
            raise ValueError(
                f"Method cannot contain non-token characters {method!r} "
                "(found at least {match.group()!r})"
            )

        assert isinstance(url, URL), url
        assert isinstance(proxy, (URL, type(None))), proxy
        # FIXME: session is None in tests only, need to fix tests
        # assert session is not None
        self._session = cast("ClientSession", session)
        if params:
            q = MultiDict(url.query)
            url2 = url.with_query(params)
            q.extend(url2.query)
            url = url.with_query(q)
        self.original_url = url
        self.url = url.with_fragment(None)
        self.method = method.upper()
        self.chunked = chunked
        self.compress = compress
        self.loop = loop
        self.length = None
        if response_class is None:
            real_response_class = ClientResponse
        else:
            real_response_class = response_class
        self.response_class: Type[ClientResponse] = real_response_class
        self._timer = timer if timer is not None else TimerNoop()
        self._ssl = ssl if ssl is not None else True
        self.server_hostname = server_hostname

        if loop.get_debug():
            self._source_traceback = traceback.extract_stack(sys._getframe(1))

        self.update_version(version)
        self.update_host(url)
        self.update_headers(headers)
        self.update_auto_headers(skip_auto_headers)
        self.update_cookies(cookies)
        self.update_content_encoding(data)
        self.update_auth(auth, trust_env)
        self.update_proxy(proxy, proxy_auth, proxy_headers)

        self.update_body_from_data(data)
        if data is not None or self.method not in self.GET_METHODS:
            self.update_transfer_encoding()
        self.update_expect_continue(expect100)
        if traces is None:
            traces = []
        self._traces = traces

    def __reset_writer(self, _: object = None) -> None:
        self.__writer = None

    @property
    def _writer(self) -> Optional["asyncio.Task[None]"]:
        return self.__writer

    @_writer.setter
    def _writer(self, writer: Optional["asyncio.Task[None]"]) -> None:
        if self.__writer is not None:
            self.__writer.remove_done_callback(self.__reset_writer)
        self.__writer = writer
        if writer is None:
            return
        if writer.done():
            # The writer is already done, so we can reset it immediately.
            self.__reset_writer()
        else:
            writer.add_done_callback(self.__reset_writer)

    def is_ssl(self) -> bool:
        return self.url.scheme in ("https", "wss")

    @property
    def ssl(self) -> Union["SSLContext", bool, Fingerprint]:
        return self._ssl

    @property
    def connection_key(self) -> ConnectionKey:
        proxy_headers = self.proxy_headers
        if proxy_headers:
            h: Optional[int] = hash(tuple((k, v) for k, v in proxy_headers.items()))
        else:
            h = None
        return ConnectionKey(
            self.host,
            self.port,
            self.is_ssl(),
            self.ssl,
            self.proxy,
            self.proxy_auth,
            h,
        )

    @property
    def host(self) -> str:
        ret = self.url.raw_host
        assert ret is not None
        return ret

    @property
    def port(self) -> Optional[int]:
        return self.url.port

    @property
    def request_info(self) -> RequestInfo:
        headers: CIMultiDictProxy[str] = CIMultiDictProxy(self.headers)
        return RequestInfo(self.url, self.method, headers, self.original_url)

    def update_host(self, url: URL) -> None:
        """Update destination host, port and connection type (ssl)."""
        # get host/port
        if not url.raw_host:
            raise InvalidURL(url)

        # basic auth info
        username, password = url.user, url.password
        if username or password:
            self.auth = helpers.BasicAuth(username or "", password or "")

    def update_version(self, version: Union[http.HttpVersion, str]) -> None:
        """Convert request version to two elements tuple.

        parser HTTP version '1.1' => (1, 1)
        """
        if isinstance(version, str):
            v = [part.strip() for part in version.split(".", 1)]
            try:
                version = http.HttpVersion(int(v[0]), int(v[1]))
            except ValueError:
                raise ValueError(
                    f"Can not parse http version number: {version}"
                ) from None
        self.version = version

    def update_headers(self, headers: Optional[LooseHeaders]) -> None:
        """Update request headers."""
        self.headers: CIMultiDict[str] = CIMultiDict()

        # add host
        netloc = cast(str, self.url.raw_host)
        if helpers.is_ipv6_address(netloc):
            netloc = f"[{netloc}]"
        # See https://github.com/aio-libs/aiohttp/issues/3636.
        netloc = netloc.rstrip(".")
        if self.url.port is not None and not self.url.is_default_port():
            netloc += ":" + str(self.url.port)
        self.headers[hdrs.HOST] = netloc

        if headers:
            if isinstance(headers, (dict, MultiDictProxy, MultiDict)):
                headers = headers.items()

            for key, value in headers:  # type: ignore[misc]
                # A special case for Host header
                if key.lower() == "host":
                    self.headers[key] = value
                else:
                    self.headers.add(key, value)

    def update_auto_headers(self, skip_auto_headers: Optional[Iterable[str]]) -> None:
        if skip_auto_headers is not None:
            self.skip_auto_headers = CIMultiDict(
                (hdr, None) for hdr in sorted(skip_auto_headers)
            )
            used_headers = self.headers.copy()
            used_headers.extend(self.skip_auto_headers)  # type: ignore[arg-type]
        else:
            # Fast path when there are no headers to skip
            # which is the most common case.
            self.skip_auto_headers = CIMultiDict()
            used_headers = self.headers

        for hdr, val in self.DEFAULT_HEADERS.items():
            if hdr not in used_headers:
                self.headers.add(hdr, val)

        if hdrs.USER_AGENT not in used_headers:
            self.headers[hdrs.USER_AGENT] = SERVER_SOFTWARE

    def update_cookies(self, cookies: Optional[LooseCookies]) -> None:
        """Update request cookies header."""
        if not cookies:
            return

        c = SimpleCookie()
        if hdrs.COOKIE in self.headers:
            c.load(self.headers.get(hdrs.COOKIE, ""))
            del self.headers[hdrs.COOKIE]

        if isinstance(cookies, Mapping):
            iter_cookies = cookies.items()
        else:
            iter_cookies = cookies  # type: ignore[assignment]
        for name, value in iter_cookies:
            if isinstance(value, Morsel):
                # Preserve coded_value
                mrsl_val = value.get(value.key, Morsel())
                mrsl_val.set(value.key, value.value, value.coded_value)
                c[name] = mrsl_val
            else:
                c[name] = value  # type: ignore[assignment]

        self.headers[hdrs.COOKIE] = c.output(header="", sep=";").strip()

    def update_content_encoding(self, data: Any) -> None:
        """Set request content encoding."""
        if data is None:
            return

        enc = self.headers.get(hdrs.CONTENT_ENCODING, "").lower()
        if enc:
            if self.compress:
                raise ValueError(
                    "compress can not be set " "if Content-Encoding header is set"
                )
        elif self.compress:
            if not isinstance(self.compress, str):
                self.compress = "deflate"
            self.headers[hdrs.CONTENT_ENCODING] = self.compress
            self.chunked = True  # enable chunked, no need to deal with length

    def update_transfer_encoding(self) -> None:
        """Analyze transfer-encoding header."""
        te = self.headers.get(hdrs.TRANSFER_ENCODING, "").lower()

        if "chunked" in te:
            if self.chunked:
                raise ValueError(
                    "chunked can not be set "
                    'if "Transfer-Encoding: chunked" header is set'
                )

        elif self.chunked:
            if hdrs.CONTENT_LENGTH in self.headers:
                raise ValueError(
                    "chunked can not be set " "if Content-Length header is set"
                )

            self.headers[hdrs.TRANSFER_ENCODING] = "chunked"
        else:
            if hdrs.CONTENT_LENGTH not in self.headers:
                self.headers[hdrs.CONTENT_LENGTH] = str(len(self.body))

    def update_auth(self, auth: Optional[BasicAuth], trust_env: bool = False) -> None:
        """Set basic auth."""
        if auth is None:
            auth = self.auth
        if auth is None and trust_env and self.url.host is not None:
            netrc_obj = netrc_from_env()
            with contextlib.suppress(LookupError):
                auth = basicauth_from_netrc(netrc_obj, self.url.host)
        if auth is None:
            return

        if not isinstance(auth, helpers.BasicAuth):
            raise TypeError("BasicAuth() tuple is required instead")

        self.headers[hdrs.AUTHORIZATION] = auth.encode()

    def update_body_from_data(self, body: Any) -> None:
        if body is None:
            return

        # FormData
        if isinstance(body, FormData):
            body = body()

        try:
            body = payload.PAYLOAD_REGISTRY.get(body, disposition=None)
        except payload.LookupError:
            body = FormData(body)()

        self.body = body

        # enable chunked encoding if needed
        if not self.chunked:
            if hdrs.CONTENT_LENGTH not in self.headers:
                size = body.size
                if size is None:
                    self.chunked = True
                else:
                    if hdrs.CONTENT_LENGTH not in self.headers:
                        self.headers[hdrs.CONTENT_LENGTH] = str(size)

        # copy payload headers
        assert body.headers
        for key, value in body.headers.items():
            if key in self.headers or key in self.skip_auto_headers:
                continue
            self.headers[key] = value

    def update_expect_continue(self, expect: bool = False) -> None:
        if expect:
            self.headers[hdrs.EXPECT] = "100-continue"
        elif self.headers.get(hdrs.EXPECT, "").lower() == "100-continue":
            expect = True

        if expect:
            self._continue = self.loop.create_future()

    def update_proxy(
        self,
        proxy: Optional[URL],
        proxy_auth: Optional[BasicAuth],
        proxy_headers: Optional[LooseHeaders],
    ) -> None:
        if proxy_auth and not isinstance(proxy_auth, helpers.BasicAuth):
            raise ValueError("proxy_auth must be None or BasicAuth() tuple")
        self.proxy = proxy
        self.proxy_auth = proxy_auth
        if proxy_headers is not None and not isinstance(
            proxy_headers, (MultiDict, MultiDictProxy)
        ):
            proxy_headers = CIMultiDict(proxy_headers)
        self.proxy_headers = proxy_headers

    def keep_alive(self) -> bool:
        if self.version < HttpVersion10:
            # keep alive not supported at all
            return False
        if self.version == HttpVersion10:
            if self.headers.get(hdrs.CONNECTION) == "keep-alive":
                return True
            else:  # no headers means we close for Http 1.0
                return False
        elif self.headers.get(hdrs.CONNECTION) == "close":
            return False

        return True

    async def write_bytes(
        self, writer: AbstractStreamWriter, conn: "Connection"
    ) -> None:
        """Support coroutines that yields bytes objects."""
        # 100 response
        if self._continue is not None:
            try:
                await writer.drain()
                await self._continue
            except asyncio.CancelledError:
                return

        protocol = conn.protocol
        assert protocol is not None
        try:
            if isinstance(self.body, payload.Payload):
                await self.body.write(writer)
            else:
                if isinstance(self.body, (bytes, bytearray)):
                    self.body = (self.body,)

                for chunk in self.body:
                    await writer.write(chunk)
        except OSError as underlying_exc:
            reraised_exc = underlying_exc

            exc_is_not_timeout = underlying_exc.errno is not None or not isinstance(
                underlying_exc, asyncio.TimeoutError
            )
            if exc_is_not_timeout:
                reraised_exc = ClientOSError(
                    underlying_exc.errno,
                    f"Can not write request body for {self.url !s}",
                )

            set_exception(protocol, reraised_exc, underlying_exc)
        except asyncio.CancelledError:
            await writer.write_eof()
        except Exception as underlying_exc:
            set_exception(
                protocol,
                ClientConnectionError(
                    f"Failed to send bytes into the underlying connection {conn !s}",
                ),
                underlying_exc,
            )
        else:
            await writer.write_eof()
            protocol.start_timeout()

    async def send(self, conn: "Connection") -> "ClientResponse":
        # Specify request target:
        # - CONNECT request must send authority form URI
        # - not CONNECT proxy must send absolute form URI
        # - most common is origin form URI
        if self.method == hdrs.METH_CONNECT:
            connect_host = self.url.raw_host
            assert connect_host is not None
            if helpers.is_ipv6_address(connect_host):
                connect_host = f"[{connect_host}]"
            path = f"{connect_host}:{self.url.port}"
        elif self.proxy and not self.is_ssl():
            path = str(self.url)
        else:
            path = self.url.raw_path
            if self.url.raw_query_string:
                path += "?" + self.url.raw_query_string

        protocol = conn.protocol
        assert protocol is not None
        writer = StreamWriter(
            protocol,
            self.loop,
            on_chunk_sent=functools.partial(
                self._on_chunk_request_sent, self.method, self.url
            ),
            on_headers_sent=functools.partial(
                self._on_headers_request_sent, self.method, self.url
            ),
        )

        if self.compress:
            writer.enable_compression(self.compress)

        if self.chunked is not None:
            writer.enable_chunking()

        # set default content-type
        if (
            self.method in self.POST_METHODS
            and hdrs.CONTENT_TYPE not in self.skip_auto_headers
            and hdrs.CONTENT_TYPE not in self.headers
        ):
            self.headers[hdrs.CONTENT_TYPE] = "application/octet-stream"

        # set the connection header
        connection = self.headers.get(hdrs.CONNECTION)
        if not connection:
            if self.keep_alive():
                if self.version == HttpVersion10:
                    connection = "keep-alive"
            else:
                if self.version == HttpVersion11:
                    connection = "close"

        if connection is not None:
            self.headers[hdrs.CONNECTION] = connection

        # status + headers
        v = self.version
        status_line = f"{self.method} {path} HTTP/{v.major}.{v.minor}"
        await writer.write_headers(status_line, self.headers)
        coro = self.write_bytes(writer, conn)

        if sys.version_info >= (3, 12):
            # Optimization for Python 3.12, try to write
            # bytes immediately to avoid having to schedule
            # the task on the event loop.
            task = asyncio.Task(coro, loop=self.loop, eager_start=True)
        else:
            task = self.loop.create_task(coro)

        self._writer = task
        response_class = self.response_class
        assert response_class is not None
        self.response = response_class(
            self.method,
            self.original_url,
            writer=self._writer,
            continue100=self._continue,
            timer=self._timer,
            request_info=self.request_info,
            traces=self._traces,
            loop=self.loop,
            session=self._session,
        )
        return self.response

    async def close(self) -> None:
        if self._writer is not None:
            with contextlib.suppress(asyncio.CancelledError):
                await self._writer

    def terminate(self) -> None:
        if self._writer is not None:
            if not self.loop.is_closed():
                self._writer.cancel()
            self._writer.remove_done_callback(self.__reset_writer)
            self._writer = None

    async def _on_chunk_request_sent(self, method: str, url: URL, chunk: bytes) -> None:
        for trace in self._traces:
            await trace.send_request_chunk_sent(method, url, chunk)

    async def _on_headers_request_sent(
        self, method: str, url: URL, headers: "CIMultiDict[str]"
    ) -> None:
        for trace in self._traces:
            await trace.send_request_headers(method, url, headers)


class ClientResponse(HeadersMixin):

    # Some of these attributes are None when created,
    # but will be set by the start() method.
    # As the end user will likely never see the None values, we cheat the types below.
    # from the Status-Line of the response
    version: Optional[HttpVersion] = None  # HTTP-Version
    status: int = None  # type: ignore[assignment] # Status-Code
    reason: Optional[str] = None  # Reason-Phrase

    content: StreamReader = None  # type: ignore[assignment]  # Payload stream
    _headers: CIMultiDictProxy[str] = None  # type: ignore[assignment]
    _raw_headers: RawHeaders = None  # type: ignore[assignment]

    _connection = None  # current connection
    _source_traceback: Optional[traceback.StackSummary] = None
    # set up by ClientRequest after ClientResponse object creation
    # post-init stage allows to not change ctor signature
    _closed = True  # to allow __del__ for non-initialized properly response
    _released = False
    __writer = None

    def __init__(
        self,
        method: str,
        url: URL,
        *,
        writer: "asyncio.Task[None]",
        continue100: Optional["asyncio.Future[bool]"],
        timer: BaseTimerContext,
        request_info: RequestInfo,
        traces: List["Trace"],
        loop: asyncio.AbstractEventLoop,
        session: "ClientSession",
    ) -> None:
        assert isinstance(url, URL)

        self.method = method
        self.cookies = SimpleCookie()

        self._real_url = url
        self._url = url.with_fragment(None)
        self._body: Any = None
        self._writer: Optional[asyncio.Task[None]] = writer
        self._continue = continue100  # None by default
        self._closed = True
        self._history: Tuple[ClientResponse, ...] = ()
        self._request_info = request_info
        self._timer = timer if timer is not None else TimerNoop()
        self._cache: Dict[str, Any] = {}
        self._traces = traces
        self._loop = loop
        # store a reference to session #1985
        self._session: Optional[ClientSession] = session
        # Save reference to _resolve_charset, so that get_encoding() will still
        # work after the response has finished reading the body.
        if session is None:
            # TODO: Fix session=None in tests (see ClientRequest.__init__).
            self._resolve_charset: Callable[["ClientResponse", bytes], str] = (
                lambda *_: "utf-8"
            )
        else:
            self._resolve_charset = session._resolve_charset
        if loop.get_debug():
            self._source_traceback = traceback.extract_stack(sys._getframe(1))

    def __reset_writer(self, _: object = None) -> None:
        self.__writer = None

    @property
    def _writer(self) -> Optional["asyncio.Task[None]"]:
        return self.__writer

    @_writer.setter
    def _writer(self, writer: Optional["asyncio.Task[None]"]) -> None:
        if self.__writer is not None:
            self.__writer.remove_done_callback(self.__reset_writer)
        self.__writer = writer
        if writer is None:
            return
        if writer.done():
            # The writer is already done, so we can reset it immediately.
            self.__reset_writer()
        else:
            writer.add_done_callback(self.__reset_writer)

    @reify
    def url(self) -> URL:
        return self._url

    @reify
    def url_obj(self) -> URL:
        warnings.warn("Deprecated, use .url #1654", DeprecationWarning, stacklevel=2)
        return self._url

    @reify
    def real_url(self) -> URL:
        return self._real_url

    @reify
    def host(self) -> str:
        assert self._url.host is not None
        return self._url.host

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

    @reify
    def raw_headers(self) -> RawHeaders:
        return self._raw_headers

    @reify
    def request_info(self) -> RequestInfo:
        return self._request_info

    @reify
    def content_disposition(self) -> Optional[ContentDisposition]:
        raw = self._headers.get(hdrs.CONTENT_DISPOSITION)
        if raw is None:
            return None
        disposition_type, params_dct = multipart.parse_content_disposition(raw)
        params = MappingProxyType(params_dct)
        filename = multipart.content_disposition_filename(params)
        return ContentDisposition(disposition_type, params, filename)

    def __del__(self, _warnings: Any = warnings) -> None:
        if self._closed:
            return

        if self._connection is not None:
            self._connection.release()
            self._cleanup_writer()

            if self._loop.get_debug():
                kwargs = {"source": self}
                _warnings.warn(f"Unclosed response {self!r}", ResourceWarning, **kwargs)
                context = {"client_response": self, "message": "Unclosed response"}
                if self._source_traceback:
                    context["source_traceback"] = self._source_traceback
                self._loop.call_exception_handler(context)

    def __repr__(self) -> str:
        out = io.StringIO()
        ascii_encodable_url = str(self.url)
        if self.reason:
            ascii_encodable_reason = self.reason.encode(
                "ascii", "backslashreplace"
            ).decode("ascii")
        else:
            ascii_encodable_reason = "None"
        print(
            "<ClientResponse({}) [{} {}]>".format(
                ascii_encodable_url, self.status, ascii_encodable_reason
            ),
            file=out,
        )
        print(self.headers, file=out)
        return out.getvalue()

    @property
    def connection(self) -> Optional["Connection"]:
        return self._connection

    @reify
    def history(self) -> Tuple["ClientResponse", ...]:
        """A sequence of of responses, if redirects occurred."""
        return self._history

    @reify
    def links(self) -> "MultiDictProxy[MultiDictProxy[Union[str, URL]]]":
        links_str = ", ".join(self.headers.getall("link", []))

        if not links_str:
            return MultiDictProxy(MultiDict())

        links: MultiDict[MultiDictProxy[Union[str, URL]]] = MultiDict()

        for val in re.split(r",(?=\s*<)", links_str):
            match = re.match(r"\s*<(.*)>(.*)", val)
            if match is None:  # pragma: no cover
                # the check exists to suppress mypy error
                continue
            url, params_str = match.groups()
            params = params_str.split(";")[1:]

            link: MultiDict[Union[str, URL]] = MultiDict()

            for param in params:
                match = re.match(r"^\s*(\S*)\s*=\s*(['\"]?)(.*?)(\2)\s*$", param, re.M)
                if match is None:  # pragma: no cover
                    # the check exists to suppress mypy error
                    continue
                key, _, value, _ = match.groups()

                link.add(key, value)

            key = link.get("rel", url)

            link.add("url", self.url.join(URL(url)))

            links.add(str(key), MultiDictProxy(link))

        return MultiDictProxy(links)

    async def start(self, connection: "Connection") -> "ClientResponse":
        """Start response processing."""
        self._closed = False
        self._protocol = connection.protocol
        self._connection = connection

        with self._timer:
            while True:
                # read response
                try:
                    protocol = self._protocol
                    message, payload = await protocol.read()  # type: ignore[union-attr]
                except http.HttpProcessingError as exc:
                    raise ClientResponseError(
                        self.request_info,
                        self.history,
                        status=exc.code,
                        message=exc.message,
                        headers=exc.headers,
                    ) from exc

                if message.code < 100 or message.code > 199 or message.code == 101:
                    break

                if self._continue is not None:
                    set_result(self._continue, True)
                    self._continue = None

        # payload eof handler
        payload.on_eof(self._response_eof)

        # response status
        self.version = message.version
        self.status = message.code
        self.reason = message.reason

        # headers
        self._headers = message.headers  # type is CIMultiDictProxy
        self._raw_headers = message.raw_headers  # type is Tuple[bytes, bytes]

        # payload
        self.content = payload

        # cookies
        for hdr in self.headers.getall(hdrs.SET_COOKIE, ()):
            try:
                self.cookies.load(hdr)
            except CookieError as exc:
                client_logger.warning("Can not load response cookies: %s", exc)
        return self

    def _response_eof(self) -> None:
        if self._closed:
            return

        # protocol could be None because connection could be detached
        protocol = self._connection and self._connection.protocol
        if protocol is not None and protocol.upgraded:
            return

        self._closed = True
        self._cleanup_writer()
        self._release_connection()

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

    def close(self) -> None:
        if not self._released:
            self._notify_content()

        self._closed = True
        if self._loop is None or self._loop.is_closed():
            return

        self._cleanup_writer()
        if self._connection is not None:
            self._connection.close()
            self._connection = None

    def release(self) -> Any:
        if not self._released:
            self._notify_content()

        self._closed = True

        self._cleanup_writer()
        self._release_connection()
        return noop()

    @property
    def ok(self) -> bool:
        """Returns ``True`` if ``status`` is less than ``400``, ``False`` if not.

        This is **not** a check for ``200 OK`` but a check that the response
        status is under 400.
        """
        return 400 > self.status

    def raise_for_status(self) -> None:
        if not self.ok:
            # reason should always be not None for a started response
            assert self.reason is not None
            self.release()
            raise ClientResponseError(
                self.request_info,
                self.history,
                status=self.status,
                message=self.reason,
                headers=self.headers,
            )

    def _release_connection(self) -> None:
        if self._connection is not None:
            if self._writer is None:
                self._connection.release()
                self._connection = None
            else:
                self._writer.add_done_callback(lambda f: self._release_connection())

    async def _wait_released(self) -> None:
        if self._writer is not None:
            await self._writer
        self._release_connection()

    def _cleanup_writer(self) -> None:
        if self._writer is not None:
            self._writer.cancel()
        self._session = None

    def _notify_content(self) -> None:
        content = self.content
        if content and content.exception() is None:
            set_exception(content, ClientConnectionError("Connection closed"))
        self._released = True

    async def wait_for_close(self) -> None:
        if self._writer is not None:
            await self._writer
        self.release()

    async def read(self) -> bytes:
        """Read response payload."""
        if self._body is None:
            try:
                self._body = await self.content.read()
                for trace in self._traces:
                    await trace.send_response_chunk_received(
                        self.method, self.url, self._body
                    )
            except BaseException:
                self.close()
                raise
        elif self._released:  # Response explicitly released
            raise ClientConnectionError("Connection closed")

        protocol = self._connection and self._connection.protocol
        if protocol is None or not protocol.upgraded:
            await self._wait_released()  # Underlying connection released
        return self._body  # type: ignore[no-any-return]

    def get_encoding(self) -> str:
        ctype = self.headers.get(hdrs.CONTENT_TYPE, "").lower()
        mimetype = helpers.parse_mimetype(ctype)

        encoding = mimetype.parameters.get("charset")
        if encoding:
            with contextlib.suppress(LookupError):
                return codecs.lookup(encoding).name

        if mimetype.type == "application" and (
            mimetype.subtype == "json" or mimetype.subtype == "rdap"
        ):
            # RFC 7159 states that the default encoding is UTF-8.
            # RFC 7483 defines application/rdap+json
            return "utf-8"

        if self._body is None:
            raise RuntimeError(
                "Cannot compute fallback encoding of a not yet read body"
            )

        return self._resolve_charset(self, self._body)

    async def text(self, encoding: Optional[str] = None, errors: str = "strict") -> str:
        """Read response payload and decode."""
        if self._body is None:
            await self.read()

        if encoding is None:
            encoding = self.get_encoding()

        return self._body.decode(  # type: ignore[no-any-return,union-attr]
            encoding, errors=errors
        )

    async def json(
        self,
        *,
        encoding: Optional[str] = None,
        loads: JSONDecoder = DEFAULT_JSON_DECODER,
        content_type: Optional[str] = "application/json",
    ) -> Any:
        """Read and decodes JSON response."""
        if self._body is None:
            await self.read()

        if content_type:
            ctype = self.headers.get(hdrs.CONTENT_TYPE, "").lower()
            if not _is_expected_content_type(ctype, content_type):
                raise ContentTypeError(
                    self.request_info,
                    self.history,
                    status=self.status,
                    message=(
                        "Attempt to decode JSON with " "unexpected mimetype: %s" % ctype
                    ),
                    headers=self.headers,
                )

        stripped = self._body.strip()  # type: ignore[union-attr]
        if not stripped:
            return None

        if encoding is None:
            encoding = self.get_encoding()

        return loads(stripped.decode(encoding))

    async def __aenter__(self) -> "ClientResponse":
        return self

    async def __aexit__(
        self,
        exc_type: Optional[Type[BaseException]],
        exc_val: Optional[BaseException],
        exc_tb: Optional[TracebackType],
    ) -> None:
        # similar to _RequestContextManager, we do not need to check
        # for exceptions, response object can close connection
        # if state is broken
        self.release()
        await self.wait_for_close()

```
--- 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:** Canceling Payload Send Causes Connection to Hang and Prevents Reuse

**Description:**
When a client cancels sending the payload during a request, the connection remains open instead of being properly closed. This prevents the connection from being reused for subsequent requests, leading to hung connections and timeout errors.

**Example Code:**
```python
async def upload_file(client, file_path):
    with open(file_path, "rb") as file:
        data = {'file': file}
        await client.post("/upload", data=data)
        await client.get("/status", timeout=0.01)  # This request hangs due to the open connection
```

**Expected Behavior:**
After canceling the payload send, the connection should be closed properly, allowing the client to reuse connections for new requests without any hanging or timeout issues.

**Actual Behavior:**
The connection remains open after the payload send is canceled, causing subsequent requests to hang and eventually timeout because the connection cannot be reused.

[/ISSUE]
{
    "test_keepalive_two_requests_success[pyloop]": "PASSED",
    "test_keepalive_after_head_requests_success[pyloop]": "PASSED",
    "test_keepalive_after_empty_body_status[pyloop-101]": "PASSED",
    "test_keepalive_after_empty_body_status[pyloop-204]": "PASSED",
    "test_keepalive_after_empty_body_status[pyloop-304]": "PASSED",
    "test_keepalive_after_empty_body_status_stream_response[pyloop-101]": "PASSED",
    "test_keepalive_after_empty_body_status_stream_response[pyloop-204]": "PASSED",
    "test_keepalive_after_empty_body_status_stream_response[pyloop-304]": "PASSED",
    "test_keepalive_response_released[pyloop]": "PASSED",
    "test_upgrade_connection_not_released_after_read[pyloop]": "PASSED",
    "test_keepalive_server_force_close_connection[pyloop]": "PASSED",
    "test_keepalive_timeout_async_sleep": "PASSED",
    "test_keepalive_timeout_sync_sleep": "PASSED",
    "test_release_early[pyloop]": "PASSED",
    "test_HTTP_304[pyloop]": "PASSED",
    "test_stream_request_on_server_eof[pyloop]": "PASSED",
    "test_stream_request_on_server_eof_nested[pyloop]": "PASSED",
    "test_HTTP_304_WITH_BODY[pyloop]": "PASSED",
    "test_auto_header_user_agent[pyloop]": "PASSED",
    "test_skip_auto_headers_user_agent[pyloop]": "PASSED",
    "test_skip_default_auto_headers_user_agent[pyloop]": "PASSED",
    "test_skip_auto_headers_content_type[pyloop]": "PASSED",
    "test_post_data_bytesio[pyloop]": "PASSED",
    "test_post_data_with_bytesio_file[pyloop]": "PASSED",
    "test_post_data_stringio[pyloop]": "PASSED",
    "test_post_data_textio_encoding[pyloop]": "PASSED",
    "test_post_data_zipfile_filelike[pyloop]": "PASSED",
    "test_post_data_tarfile_filelike[pyloop]": "PASSED",
    "test_ssl_client[pyloop]": "PASSED",
    "test_tcp_connector_fingerprint_ok[pyloop]": "PASSED",
    "test_tcp_connector_fingerprint_fail[pyloop]": "PASSED",
    "test_format_task_get[pyloop]": "PASSED",
    "test_str_params[pyloop]": "PASSED",
    "test_drop_params_on_redirect[pyloop]": "PASSED",
    "test_drop_fragment_on_redirect[pyloop]": "PASSED",
    "test_drop_fragment[pyloop]": "PASSED",
    "test_history[pyloop]": "PASSED",
    "test_keepalive_closed_by_server[pyloop]": "PASSED",
    "test_wait_for[pyloop]": "PASSED",
    "test_raw_headers[pyloop]": "PASSED",
    "test_host_header_first[pyloop]": "PASSED",
    "test_empty_header_values[pyloop]": "PASSED",
    "test_204_with_gzipped_content_encoding[pyloop]": "PASSED",
    "test_timeout_on_reading_headers[pyloop]": "PASSED",
    "test_timeout_on_conn_reading_headers[pyloop]": "PASSED",
    "test_timeout_on_session_read_timeout[pyloop]": "PASSED",
    "test_read_timeout_between_chunks[pyloop]": "PASSED",
    "test_read_timeout_on_reading_chunks[pyloop]": "PASSED",
    "test_read_timeout_on_write[pyloop]": "PASSED",
    "test_timeout_on_reading_data[pyloop]": "PASSED",
    "test_timeout_none[pyloop]": "PASSED",
    "test_readline_error_on_conn_close[pyloop]": "PASSED",
    "test_no_error_on_conn_close_if_eof[pyloop]": "PASSED",
    "test_error_not_overwrote_on_conn_close[pyloop]": "PASSED",
    "test_HTTP_200_OK_METHOD[pyloop]": "PASSED",
    "test_HTTP_200_OK_METHOD_connector[pyloop]": "PASSED",
    "test_HTTP_302_REDIRECT_GET[pyloop]": "PASSED",
    "test_HTTP_302_REDIRECT_HEAD[pyloop]": "PASSED",
    "test_HTTP_302_REDIRECT_NON_HTTP[pyloop]": "PASSED",
    "test_HTTP_302_REDIRECT_POST[pyloop]": "PASSED",
    "test_HTTP_302_REDIRECT_POST_with_content_length_hdr[pyloop]": "PASSED",
    "test_HTTP_307_REDIRECT_POST[pyloop]": "PASSED",
    "test_HTTP_308_PERMANENT_REDIRECT_POST[pyloop]": "PASSED",
    "test_HTTP_302_max_redirects[pyloop]": "PASSED",
    "test_HTTP_200_GET_WITH_PARAMS[pyloop]": "PASSED",
    "test_HTTP_200_GET_WITH_MultiDict_PARAMS[pyloop]": "PASSED",
    "test_HTTP_200_GET_WITH_MIXED_PARAMS[pyloop]": "PASSED",
    "test_POST_DATA[pyloop]": "PASSED",
    "test_POST_DATA_with_explicit_formdata[pyloop]": "PASSED",
    "test_POST_DATA_with_charset[pyloop]": "PASSED",
    "test_POST_DATA_formdats_with_charset[pyloop]": "PASSED",
    "test_POST_DATA_with_charset_post[pyloop]": "PASSED",
    "test_POST_MultiDict[pyloop]": "PASSED",
    "test_POST_DATA_DEFLATE[pyloop]": "PASSED",
    "test_POST_FILES[pyloop]": "PASSED",
    "test_POST_FILES_DEFLATE[pyloop]": "PASSED",
    "test_POST_bytes[pyloop]": "PASSED",
    "test_POST_bytes_too_large[pyloop]": "PASSED",
    "test_POST_FILES_STR[pyloop]": "PASSED",
    "test_POST_FILES_STR_SIMPLE[pyloop]": "PASSED",
    "test_POST_FILES_LIST[pyloop]": "PASSED",
    "test_POST_FILES_CT[pyloop]": "PASSED",
    "test_POST_FILES_SINGLE[pyloop]": "PASSED",
    "test_POST_FILES_SINGLE_content_disposition[pyloop]": "PASSED",
    "test_POST_FILES_SINGLE_BINARY[pyloop]": "PASSED",
    "test_POST_FILES_IO[pyloop]": "PASSED",
    "test_POST_FILES_IO_WITH_PARAMS[pyloop]": "PASSED",
    "test_POST_FILES_WITH_DATA[pyloop]": "PASSED",
    "test_POST_STREAM_DATA[pyloop]": "PASSED",
    "test_POST_STREAM_DATA_no_params[pyloop]": "PASSED",
    "test_json[pyloop]": "PASSED",
    "test_json_custom[pyloop]": "PASSED",
    "test_expect_continue[pyloop]": "PASSED",
    "test_encoding_deflate[pyloop]": "PASSED",
    "test_encoding_deflate_nochunk[pyloop]": "PASSED",
    "test_encoding_gzip[pyloop]": "PASSED",
    "test_encoding_gzip_write_by_chunks[pyloop]": "PASSED",
    "test_encoding_gzip_nochunk[pyloop]": "PASSED",
    "test_bad_payload_compression[pyloop]": "PASSED",
    "test_bad_payload_chunked_encoding[pyloop]": "PASSED",
    "test_no_payload_304_with_chunked_encoding[pyloop]": "PASSED",
    "test_head_request_with_chunked_encoding[pyloop]": "PASSED",
    "test_no_payload_200_with_chunked_encoding[pyloop]": "PASSED",
    "test_bad_payload_content_length[pyloop]": "PASSED",
    "test_payload_content_length_by_chunks[pyloop]": "PASSED",
    "test_chunked[pyloop]": "PASSED",
    "test_shortcuts[pyloop]": "PASSED",
    "test_cookies[pyloop]": "PASSED",
    "test_cookies_per_request[pyloop]": "PASSED",
    "test_cookies_redirect[pyloop]": "PASSED",
    "test_cookies_on_empty_session_jar[pyloop]": "PASSED",
    "test_morsel_with_attributes[pyloop]": "PASSED",
    "test_set_cookies[pyloop]": "PASSED",
    "test_set_cookies_expired[pyloop]": "PASSED",
    "test_set_cookies_max_age[pyloop]": "PASSED",
    "test_set_cookies_max_age_overflow[pyloop]": "PASSED",
    "test_request_conn_error": "PASSED",
    "test_broken_connection_2[pyloop]": "PASSED",
    "test_custom_headers[pyloop]": "PASSED",
    "test_redirect_to_absolute_url[pyloop]": "PASSED",
    "test_redirect_without_location_header[pyloop]": "PASSED",
    "test_chunked_deprecated[pyloop]": "PASSED",
    "test_invalid_and_non_http_url[http://:/-http://:/-InvalidUrlClientError]": "PASSED",
    "test_invalid_and_non_http_url[http://example.org:non_int_port/-http://example.org:non_int_port/-InvalidUrlClientError]": "PASSED",
    "test_invalid_and_non_http_url[http:/-http:///-InvalidUrlClientError]": "PASSED",
    "test_invalid_and_non_http_url[http:/example.com-http:///example.com-InvalidUrlClientError]": "PASSED",
    "test_invalid_and_non_http_url[http:///example.com-http:///example.com-InvalidUrlClientError]": "PASSED",
    "test_invalid_and_non_http_url[call:+380123456789-call:\\\\+380123456789-NonHttpUrlClientError]": "PASSED",
    "test_invalid_and_non_http_url[skype:handle-skype:handle-NonHttpUrlClientError]": "PASSED",
    "test_invalid_and_non_http_url[slack://instance/room-slack://instance/room-NonHttpUrlClientError]": "PASSED",
    "test_invalid_and_non_http_url[steam:code-steam:code-NonHttpUrlClientError]": "PASSED",
    "test_invalid_and_non_http_url[twitter://handle-twitter://handle-NonHttpUrlClientError]": "PASSED",
    "test_invalid_and_non_http_url[bluesky://profile/d:i:d-bluesky://profile/d:i:d-NonHttpUrlClientError]": "PASSED",
    "test_invalid_redirect_url[pyloop-http:/-http:///-InvalidUrlRedirectClientError]": "PASSED",
    "test_invalid_redirect_url[pyloop-http:/example.com-http:///example.com-InvalidUrlRedirectClientError]": "PASSED",
    "test_invalid_redirect_url[pyloop-http:///example.com-http:///example.com-InvalidUrlRedirectClientError]": "PASSED",
    "test_invalid_redirect_url[pyloop-http://:/-http://:/-InvalidUrlRedirectClientError]": "PASSED",
    "test_invalid_redirect_url[pyloop-http://example.org:non_int_port/-http://example.org:non_int_port/-InvalidUrlRedirectClientError]": "PASSED",
    "test_invalid_redirect_url[pyloop-call:+380123456789-call:\\\\+380123456789-NonHttpUrlRedirectClientError]": "PASSED",
    "test_invalid_redirect_url[pyloop-skype:handle-skype:handle-NonHttpUrlRedirectClientError]": "PASSED",
    "test_invalid_redirect_url[pyloop-slack://instance/room-slack://instance/room-NonHttpUrlRedirectClientError]": "PASSED",
    "test_invalid_redirect_url[pyloop-steam:code-steam:code-NonHttpUrlRedirectClientError]": "PASSED",
    "test_invalid_redirect_url[pyloop-twitter://handle-twitter://handle-NonHttpUrlRedirectClientError]": "PASSED",
    "test_invalid_redirect_url[pyloop-bluesky://profile/d:i:d-bluesky://profile/d:i:d-NonHttpUrlRedirectClientError]": "PASSED",
    "test_invalid_redirect_url_multiple_redirects[pyloop-http:/-http:///-InvalidUrlRedirectClientError]": "PASSED",
    "test_invalid_redirect_url_multiple_redirects[pyloop-http:/example.com-http:///example.com-InvalidUrlRedirectClientError]": "PASSED",
    "test_invalid_redirect_url_multiple_redirects[pyloop-http:///example.com-http:///example.com-InvalidUrlRedirectClientError]": "PASSED",
    "test_invalid_redirect_url_multiple_redirects[pyloop-http://:/-http://:/-InvalidUrlRedirectClientError]": "PASSED",
    "test_invalid_redirect_url_multiple_redirects[pyloop-http://example.org:non_int_port/-http://example.org:non_int_port/-InvalidUrlRedirectClientError]": "PASSED",
    "test_invalid_redirect_url_multiple_redirects[pyloop-call:+380123456789-call:\\\\+380123456789-NonHttpUrlRedirectClientError]": "PASSED",
    "test_invalid_redirect_url_multiple_redirects[pyloop-skype:handle-skype:handle-NonHttpUrlRedirectClientError]": "PASSED",
    "test_invalid_redirect_url_multiple_redirects[pyloop-slack://instance/room-slack://instance/room-NonHttpUrlRedirectClientError]": "PASSED",
    "test_invalid_redirect_url_multiple_redirects[pyloop-steam:code-steam:code-NonHttpUrlRedirectClientError]": "PASSED",
    "test_invalid_redirect_url_multiple_redirects[pyloop-twitter://handle-twitter://handle-NonHttpUrlRedirectClientError]": "PASSED",
    "test_invalid_redirect_url_multiple_redirects[pyloop-bluesky://profile/d:i:d-bluesky://profile/d:i:d-NonHttpUrlRedirectClientError]": "PASSED",
    "test_ok_from_status[pyloop-200-True]": "PASSED",
    "test_ok_from_status[pyloop-201-True]": "PASSED",
    "test_ok_from_status[pyloop-301-True]": "PASSED",
    "test_ok_from_status[pyloop-400-False]": "PASSED",
    "test_ok_from_status[pyloop-403-False]": "PASSED",
    "test_ok_from_status[pyloop-500-False]": "PASSED",
    "test_raise_for_status[pyloop]": "PASSED",
    "test_raise_for_status_per_request[pyloop]": "PASSED",
    "test_raise_for_status_disable_per_request[pyloop]": "PASSED",
    "test_request_raise_for_status_default[pyloop]": "PASSED",
    "test_request_raise_for_status_disabled[pyloop]": "PASSED",
    "test_request_raise_for_status_enabled[pyloop]": "PASSED",
    "test_session_raise_for_status_coro[pyloop]": "PASSED",
    "test_request_raise_for_status_coro[pyloop]": "PASSED",
    "test_invalid_idna": "PASSED",
    "test_creds_in_auth_and_url": "PASSED",
    "test_drop_auth_on_redirect_to_other_host[pyloop-entirely different hosts]": "PASSED",
    "test_drop_auth_on_redirect_to_other_host[pyloop-http -> https]": "PASSED",
    "test_drop_auth_on_redirect_to_other_host[pyloop-https -> http]": "PASSED",
    "test_async_with_session": "PASSED",
    "test_session_close_awaitable": "PASSED",
    "test_close_resp_on_error_async_with_session[pyloop]": "PASSED",
    "test_release_resp_on_normal_exit_from_cm[pyloop]": "PASSED",
    "test_non_close_detached_session_on_error_cm[pyloop]": "PASSED",
    "test_close_detached_session_on_non_existing_addr": "PASSED",
    "test_aiohttp_request_context_manager[pyloop]": "PASSED",
    "test_aiohttp_request_ctx_manager_close_sess_on_error[pyloop]": "PASSED",
    "test_aiohttp_request_ctx_manager_not_found": "PASSED",
    "test_yield_from_in_session_request[pyloop]": "PASSED",
    "test_close_context_manager[pyloop]": "PASSED",
    "test_session_auth[pyloop]": "PASSED",
    "test_session_auth_override[pyloop]": "PASSED",
    "test_session_auth_header_conflict[pyloop]": "PASSED",
    "test_session_headers[pyloop]": "PASSED",
    "test_session_headers_merge[pyloop]": "PASSED",
    "test_multidict_headers[pyloop]": "PASSED",
    "test_request_conn_closed[pyloop]": "PASSED",
    "test_dont_close_explicit_connector[pyloop]": "PASSED",
    "test_server_close_keepalive_connection": "PASSED",
    "test_handle_keepalive_on_closed_connection": "PASSED",
    "test_error_in_performing_request[pyloop]": "PASSED",
    "test_await_after_cancelling[pyloop]": "PASSED",
    "test_async_payload_generator[pyloop]": "PASSED",
    "test_read_from_closed_response[pyloop]": "PASSED",
    "test_read_from_closed_response2[pyloop]": "PASSED",
    "test_read_from_closed_content[pyloop]": "PASSED",
    "test_read_timeout[pyloop]": "PASSED",
    "test_socket_timeout[pyloop]": "PASSED",
    "test_read_timeout_closes_connection[pyloop]": "PASSED",
    "test_read_timeout_on_prepared_response[pyloop]": "PASSED",
    "test_timeout_with_full_buffer[pyloop]": "PASSED",
    "test_read_bufsize_session_default[pyloop]": "PASSED",
    "test_read_bufsize_explicit[pyloop]": "PASSED",
    "test_http_empty_data_text[pyloop]": "PASSED",
    "test_max_field_size_session_default[pyloop]": "PASSED",
    "test_max_field_size_session_default_fail[pyloop]": "PASSED",
    "test_max_field_size_session_explicit[pyloop]": "PASSED",
    "test_max_field_size_request_explicit[pyloop]": "PASSED",
    "test_max_line_size_session_default[pyloop]": "PASSED",
    "test_max_line_size_session_default_fail[pyloop]": "PASSED",
    "test_max_line_size_session_explicit[pyloop]": "PASSED",
    "test_max_line_size_request_explicit[pyloop]": "PASSED",
    "test_rejected_upload[pyloop]": "PASSED",
    "test_request_with_wrong_proxy[pyloop-42-TypeError]": "PASSED",
    "test_request_with_wrong_proxy[pyloop-InvalidUrl-InvalidURL]": "PASSED",
    "test_raise_for_status_is_none[pyloop]": "PASSED",
    "test_exception_when_read_outside_of_session[pyloop]": "PASSED"
}
diff --git a/aiohttp/client_reqrep.py b/aiohttp/client_reqrep.py
index 933f3275..d2c5f16d 100644
--- a/aiohttp/client_reqrep.py
+++ b/aiohttp/client_reqrep.py
@@ -659,7 +659,8 @@ class ClientRequest:
 
             set_exception(protocol, reraised_exc, underlying_exc)
         except asyncio.CancelledError:
-            await writer.write_eof()
+            # Body hasn't been fully sent, so connection can't be reused.
+            conn.close()
         except Exception as underlying_exc:
             set_exception(
                 protocol,

{"aiohttp/client_reqrep.py": "import asyncio\nimport codecs\nimport contextlib\nimport functools\nimport io\nimport re\nimport sys\nimport traceback\nimport warnings\nfrom hashlib import md5, sha1, sha256\nfrom http.cookies import CookieError, Morsel, SimpleCookie\nfrom types import MappingProxyType, TracebackType\nfrom typing import (\n    TYPE_CHECKING,\n    Any,\n    Callable,\n    Dict,\n    Iterable,\n    List,\n    Mapping,\n    Optional,\n    Tuple,\n    Type,\n    Union,\n    cast,\n)\n\nimport attr\nfrom multidict import CIMultiDict, CIMultiDictProxy, MultiDict, MultiDictProxy\nfrom yarl import URL\n\nfrom . import hdrs, helpers, http, multipart, payload\nfrom .abc import AbstractStreamWriter\nfrom .client_exceptions import (\n    ClientConnectionError,\n    ClientOSError,\n    ClientResponseError,\n    ContentTypeError,\n    InvalidURL,\n    ServerFingerprintMismatch,\n)\nfrom .compression_utils import HAS_BROTLI\nfrom .formdata import FormData\nfrom .helpers import (\n    BaseTimerContext,\n    BasicAuth,\n    HeadersMixin,\n    TimerNoop,\n    basicauth_from_netrc,\n    netrc_from_env,\n    noop,\n    reify,\n    set_exception,\n    set_result,\n)\nfrom .http import (\n    SERVER_SOFTWARE,\n    HttpVersion,\n    HttpVersion10,\n    HttpVersion11,\n    StreamWriter,\n)\nfrom .log import client_logger\nfrom .streams import StreamReader\nfrom .typedefs import (\n    DEFAULT_JSON_DECODER,\n    JSONDecoder,\n    LooseCookies,\n    LooseHeaders,\n    RawHeaders,\n)\n\ntry:\n    import ssl\n    from ssl import SSLContext\nexcept ImportError:  # pragma: no cover\n    ssl = None  # type: ignore[assignment]\n    SSLContext = object  # type: ignore[misc,assignment]\n\n\n__all__ = (\"ClientRequest\", \"ClientResponse\", \"RequestInfo\", \"Fingerprint\")\n\n\nif TYPE_CHECKING:\n    from .client import ClientSession\n    from .connector import Connection\n    from .tracing import Trace\n\n\n_CONTAINS_CONTROL_CHAR_RE = re.compile(r\"[^-!#$%&'*+.^_`|~0-9a-zA-Z]\")\njson_re = re.compile(r\"^application/(?:[\\w.+-]+?\\+)?json\")\n\n\ndef _gen_default_accept_encoding() -> str:\n    return \"gzip, deflate, br\" if HAS_BROTLI else \"gzip, deflate\"\n\n\n@attr.s(auto_attribs=True, frozen=True, slots=True)\nclass ContentDisposition:\n    type: Optional[str]\n    parameters: \"MappingProxyType[str, str]\"\n    filename: Optional[str]\n\n\n@attr.s(auto_attribs=True, frozen=True, slots=True)\nclass RequestInfo:\n    url: URL\n    method: str\n    headers: \"CIMultiDictProxy[str]\"\n    real_url: URL = attr.ib()\n\n    @real_url.default\n    def real_url_default(self) -> URL:\n        return self.url\n\n\nclass Fingerprint:\n    HASHFUNC_BY_DIGESTLEN = {\n        16: md5,\n        20: sha1,\n        32: sha256,\n    }\n\n    def __init__(self, fingerprint: bytes) -> None:\n        digestlen = len(fingerprint)\n        hashfunc = self.HASHFUNC_BY_DIGESTLEN.get(digestlen)\n        if not hashfunc:\n            raise ValueError(\"fingerprint has invalid length\")\n        elif hashfunc is md5 or hashfunc is sha1:\n            raise ValueError(\n                \"md5 and sha1 are insecure and \" \"not supported. Use sha256.\"\n            )\n        self._hashfunc = hashfunc\n        self._fingerprint = fingerprint\n\n    @property\n    def fingerprint(self) -> bytes:\n        return self._fingerprint\n\n    def check(self, transport: asyncio.Transport) -> None:\n        if not transport.get_extra_info(\"sslcontext\"):\n            return\n        sslobj = transport.get_extra_info(\"ssl_object\")\n        cert = sslobj.getpeercert(binary_form=True)\n        got = self._hashfunc(cert).digest()\n        if got != self._fingerprint:\n            host, port, *_ = transport.get_extra_info(\"peername\")\n            raise ServerFingerprintMismatch(self._fingerprint, got, host, port)\n\n\nif ssl is not None:\n    SSL_ALLOWED_TYPES = (ssl.SSLContext, bool, Fingerprint, type(None))\nelse:  # pragma: no cover\n    SSL_ALLOWED_TYPES = (bool, type(None))\n\n\ndef _merge_ssl_params(\n    ssl: Union[\"SSLContext\", bool, Fingerprint],\n    verify_ssl: Optional[bool],\n    ssl_context: Optional[\"SSLContext\"],\n    fingerprint: Optional[bytes],\n) -> Union[\"SSLContext\", bool, Fingerprint]:\n    if ssl is None:\n        ssl = True  # Double check for backwards compatibility\n    if verify_ssl is not None and not verify_ssl:\n        warnings.warn(\n            \"verify_ssl is deprecated, use ssl=False instead\",\n            DeprecationWarning,\n            stacklevel=3,\n        )\n        if ssl is not True:\n            raise ValueError(\n                \"verify_ssl, ssl_context, fingerprint and ssl \"\n                \"parameters are mutually exclusive\"\n            )\n        else:\n            ssl = False\n    if ssl_context is not None:\n        warnings.warn(\n            \"ssl_context is deprecated, use ssl=context instead\",\n            DeprecationWarning,\n            stacklevel=3,\n        )\n        if ssl is not True:\n            raise ValueError(\n                \"verify_ssl, ssl_context, fingerprint and ssl \"\n                \"parameters are mutually exclusive\"\n            )\n        else:\n            ssl = ssl_context\n    if fingerprint is not None:\n        warnings.warn(\n            \"fingerprint is deprecated, \" \"use ssl=Fingerprint(fingerprint) instead\",\n            DeprecationWarning,\n            stacklevel=3,\n        )\n        if ssl is not True:\n            raise ValueError(\n                \"verify_ssl, ssl_context, fingerprint and ssl \"\n                \"parameters are mutually exclusive\"\n            )\n        else:\n            ssl = Fingerprint(fingerprint)\n    if not isinstance(ssl, SSL_ALLOWED_TYPES):\n        raise TypeError(\n            \"ssl should be SSLContext, bool, Fingerprint or None, \"\n            \"got {!r} instead.\".format(ssl)\n        )\n    return ssl\n\n\n@attr.s(auto_attribs=True, slots=True, frozen=True, cache_hash=True)\nclass ConnectionKey:\n    # the key should contain an information about used proxy / TLS\n    # to prevent reusing wrong connections from a pool\n    host: str\n    port: Optional[int]\n    is_ssl: bool\n    ssl: Union[SSLContext, bool, Fingerprint]\n    proxy: Optional[URL]\n    proxy_auth: Optional[BasicAuth]\n    proxy_headers_hash: Optional[int]  # hash(CIMultiDict)\n\n\ndef _is_expected_content_type(\n    response_content_type: str, expected_content_type: str\n) -> bool:\n    if expected_content_type == \"application/json\":\n        return json_re.match(response_content_type) is not None\n    return expected_content_type in response_content_type\n\n\nclass ClientRequest:\n    GET_METHODS = {\n        hdrs.METH_GET,\n        hdrs.METH_HEAD,\n        hdrs.METH_OPTIONS,\n        hdrs.METH_TRACE,\n    }\n    POST_METHODS = {hdrs.METH_PATCH, hdrs.METH_POST, hdrs.METH_PUT}\n    ALL_METHODS = GET_METHODS.union(POST_METHODS).union({hdrs.METH_DELETE})\n\n    DEFAULT_HEADERS = {\n        hdrs.ACCEPT: \"*/*\",\n        hdrs.ACCEPT_ENCODING: _gen_default_accept_encoding(),\n    }\n\n    # Type of body depends on PAYLOAD_REGISTRY, which is dynamic.\n    body: Any = b\"\"\n    auth = None\n    response = None\n\n    __writer = None  # async task for streaming data\n    _continue = None  # waiter future for '100 Continue' response\n\n    # N.B.\n    # Adding __del__ method with self._writer closing doesn't make sense\n    # because _writer is instance method, thus it keeps a reference to self.\n    # Until writer has finished finalizer will not be called.\n\n    def __init__(\n        self,\n        method: str,\n        url: URL,\n        *,\n        params: Optional[Mapping[str, str]] = None,\n        headers: Optional[LooseHeaders] = None,\n        skip_auto_headers: Optional[Iterable[str]] = None,\n        data: Any = None,\n        cookies: Optional[LooseCookies] = None,\n        auth: Optional[BasicAuth] = None,\n        version: http.HttpVersion = http.HttpVersion11,\n        compress: Optional[str] = None,\n        chunked: Optional[bool] = None,\n        expect100: bool = False,\n        loop: Optional[asyncio.AbstractEventLoop] = None,\n        response_class: Optional[Type[\"ClientResponse\"]] = None,\n        proxy: Optional[URL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        timer: Optional[BaseTimerContext] = None,\n        session: Optional[\"ClientSession\"] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        proxy_headers: Optional[LooseHeaders] = None,\n        traces: Optional[List[\"Trace\"]] = None,\n        trust_env: bool = False,\n        server_hostname: Optional[str] = None,\n    ):\n        if loop is None:\n            loop = asyncio.get_event_loop()\n\n        match = _CONTAINS_CONTROL_CHAR_RE.search(method)\n        if match:\n            raise ValueError(\n                f\"Method cannot contain non-token characters {method!r} \"\n                \"(found at least {match.group()!r})\"\n            )\n\n        assert isinstance(url, URL), url\n        assert isinstance(proxy, (URL, type(None))), proxy\n        # FIXME: session is None in tests only, need to fix tests\n        # assert session is not None\n        self._session = cast(\"ClientSession\", session)\n        if params:\n            q = MultiDict(url.query)\n            url2 = url.with_query(params)\n            q.extend(url2.query)\n            url = url.with_query(q)\n        self.original_url = url\n        self.url = url.with_fragment(None)\n        self.method = method.upper()\n        self.chunked = chunked\n        self.compress = compress\n        self.loop = loop\n        self.length = None\n        if response_class is None:\n            real_response_class = ClientResponse\n        else:\n            real_response_class = response_class\n        self.response_class: Type[ClientResponse] = real_response_class\n        self._timer = timer if timer is not None else TimerNoop()\n        self._ssl = ssl if ssl is not None else True\n        self.server_hostname = server_hostname\n\n        if loop.get_debug():\n            self._source_traceback = traceback.extract_stack(sys._getframe(1))\n\n        self.update_version(version)\n        self.update_host(url)\n        self.update_headers(headers)\n        self.update_auto_headers(skip_auto_headers)\n        self.update_cookies(cookies)\n        self.update_content_encoding(data)\n        self.update_auth(auth, trust_env)\n        self.update_proxy(proxy, proxy_auth, proxy_headers)\n\n        self.update_body_from_data(data)\n        if data is not None or self.method not in self.GET_METHODS:\n            self.update_transfer_encoding()\n        self.update_expect_continue(expect100)\n        if traces is None:\n            traces = []\n        self._traces = traces\n\n    def __reset_writer(self, _: object = None) -> None:\n        self.__writer = None\n\n    @property\n    def _writer(self) -> Optional[\"asyncio.Task[None]\"]:\n        return self.__writer\n\n    @_writer.setter\n    def _writer(self, writer: Optional[\"asyncio.Task[None]\"]) -> None:\n        if self.__writer is not None:\n            self.__writer.remove_done_callback(self.__reset_writer)\n        self.__writer = writer\n        if writer is None:\n            return\n        if writer.done():\n            # The writer is already done, so we can reset it immediately.\n            self.__reset_writer()\n        else:\n            writer.add_done_callback(self.__reset_writer)\n\n    def is_ssl(self) -> bool:\n        return self.url.scheme in (\"https\", \"wss\")\n\n    @property\n    def ssl(self) -> Union[\"SSLContext\", bool, Fingerprint]:\n        return self._ssl\n\n    @property\n    def connection_key(self) -> ConnectionKey:\n        proxy_headers = self.proxy_headers\n        if proxy_headers:\n            h: Optional[int] = hash(tuple((k, v) for k, v in proxy_headers.items()))\n        else:\n            h = None\n        return ConnectionKey(\n            self.host,\n            self.port,\n            self.is_ssl(),\n            self.ssl,\n            self.proxy,\n            self.proxy_auth,\n            h,\n        )\n\n    @property\n    def host(self) -> str:\n        ret = self.url.raw_host\n        assert ret is not None\n        return ret\n\n    @property\n    def port(self) -> Optional[int]:\n        return self.url.port\n\n    @property\n    def request_info(self) -> RequestInfo:\n        headers: CIMultiDictProxy[str] = CIMultiDictProxy(self.headers)\n        return RequestInfo(self.url, self.method, headers, self.original_url)\n\n    def update_host(self, url: URL) -> None:\n        \"\"\"Update destination host, port and connection type (ssl).\"\"\"\n        # get host/port\n        if not url.raw_host:\n            raise InvalidURL(url)\n\n        # basic auth info\n        username, password = url.user, url.password\n        if username or password:\n            self.auth = helpers.BasicAuth(username or \"\", password or \"\")\n\n    def update_version(self, version: Union[http.HttpVersion, str]) -> None:\n        \"\"\"Convert request version to two elements tuple.\n\n        parser HTTP version '1.1' => (1, 1)\n        \"\"\"\n        if isinstance(version, str):\n            v = [part.strip() for part in version.split(\".\", 1)]\n            try:\n                version = http.HttpVersion(int(v[0]), int(v[1]))\n            except ValueError:\n                raise ValueError(\n                    f\"Can not parse http version number: {version}\"\n                ) from None\n        self.version = version\n\n    def update_headers(self, headers: Optional[LooseHeaders]) -> None:\n        \"\"\"Update request headers.\"\"\"\n        self.headers: CIMultiDict[str] = CIMultiDict()\n\n        # add host\n        netloc = cast(str, self.url.raw_host)\n        if helpers.is_ipv6_address(netloc):\n            netloc = f\"[{netloc}]\"\n        # See https://github.com/aio-libs/aiohttp/issues/3636.\n        netloc = netloc.rstrip(\".\")\n        if self.url.port is not None and not self.url.is_default_port():\n            netloc += \":\" + str(self.url.port)\n        self.headers[hdrs.HOST] = netloc\n\n        if headers:\n            if isinstance(headers, (dict, MultiDictProxy, MultiDict)):\n                headers = headers.items()\n\n            for key, value in headers:  # type: ignore[misc]\n                # A special case for Host header\n                if key.lower() == \"host\":\n                    self.headers[key] = value\n                else:\n                    self.headers.add(key, value)\n\n    def update_auto_headers(self, skip_auto_headers: Optional[Iterable[str]]) -> None:\n        if skip_auto_headers is not None:\n            self.skip_auto_headers = CIMultiDict(\n                (hdr, None) for hdr in sorted(skip_auto_headers)\n            )\n            used_headers = self.headers.copy()\n            used_headers.extend(self.skip_auto_headers)  # type: ignore[arg-type]\n        else:\n            # Fast path when there are no headers to skip\n            # which is the most common case.\n            self.skip_auto_headers = CIMultiDict()\n            used_headers = self.headers\n\n        for hdr, val in self.DEFAULT_HEADERS.items():\n            if hdr not in used_headers:\n                self.headers.add(hdr, val)\n\n        if hdrs.USER_AGENT not in used_headers:\n            self.headers[hdrs.USER_AGENT] = SERVER_SOFTWARE\n\n    def update_cookies(self, cookies: Optional[LooseCookies]) -> None:\n        \"\"\"Update request cookies header.\"\"\"\n        if not cookies:\n            return\n\n        c = SimpleCookie()\n        if hdrs.COOKIE in self.headers:\n            c.load(self.headers.get(hdrs.COOKIE, \"\"))\n            del self.headers[hdrs.COOKIE]\n\n        if isinstance(cookies, Mapping):\n            iter_cookies = cookies.items()\n        else:\n            iter_cookies = cookies  # type: ignore[assignment]\n        for name, value in iter_cookies:\n            if isinstance(value, Morsel):\n                # Preserve coded_value\n                mrsl_val = value.get(value.key, Morsel())\n                mrsl_val.set(value.key, value.value, value.coded_value)\n                c[name] = mrsl_val\n            else:\n                c[name] = value  # type: ignore[assignment]\n\n        self.headers[hdrs.COOKIE] = c.output(header=\"\", sep=\";\").strip()\n\n    def update_content_encoding(self, data: Any) -> None:\n        \"\"\"Set request content encoding.\"\"\"\n        if data is None:\n            return\n\n        enc = self.headers.get(hdrs.CONTENT_ENCODING, \"\").lower()\n        if enc:\n            if self.compress:\n                raise ValueError(\n                    \"compress can not be set \" \"if Content-Encoding header is set\"\n                )\n        elif self.compress:\n            if not isinstance(self.compress, str):\n                self.compress = \"deflate\"\n            self.headers[hdrs.CONTENT_ENCODING] = self.compress\n            self.chunked = True  # enable chunked, no need to deal with length\n\n    def update_transfer_encoding(self) -> None:\n        \"\"\"Analyze transfer-encoding header.\"\"\"\n        te = self.headers.get(hdrs.TRANSFER_ENCODING, \"\").lower()\n\n        if \"chunked\" in te:\n            if self.chunked:\n                raise ValueError(\n                    \"chunked can not be set \"\n                    'if \"Transfer-Encoding: chunked\" header is set'\n                )\n\n        elif self.chunked:\n            if hdrs.CONTENT_LENGTH in self.headers:\n                raise ValueError(\n                    \"chunked can not be set \" \"if Content-Length header is set\"\n                )\n\n            self.headers[hdrs.TRANSFER_ENCODING] = \"chunked\"\n        else:\n            if hdrs.CONTENT_LENGTH not in self.headers:\n                self.headers[hdrs.CONTENT_LENGTH] = str(len(self.body))\n\n    def update_auth(self, auth: Optional[BasicAuth], trust_env: bool = False) -> None:\n        \"\"\"Set basic auth.\"\"\"\n        if auth is None:\n            auth = self.auth\n        if auth is None and trust_env and self.url.host is not None:\n            netrc_obj = netrc_from_env()\n            with contextlib.suppress(LookupError):\n                auth = basicauth_from_netrc(netrc_obj, self.url.host)\n        if auth is None:\n            return\n\n        if not isinstance(auth, helpers.BasicAuth):\n            raise TypeError(\"BasicAuth() tuple is required instead\")\n\n        self.headers[hdrs.AUTHORIZATION] = auth.encode()\n\n    def update_body_from_data(self, body: Any) -> None:\n        if body is None:\n            return\n\n        # FormData\n        if isinstance(body, FormData):\n            body = body()\n\n        try:\n            body = payload.PAYLOAD_REGISTRY.get(body, disposition=None)\n        except payload.LookupError:\n            body = FormData(body)()\n\n        self.body = body\n\n        # enable chunked encoding if needed\n        if not self.chunked:\n            if hdrs.CONTENT_LENGTH not in self.headers:\n                size = body.size\n                if size is None:\n                    self.chunked = True\n                else:\n                    if hdrs.CONTENT_LENGTH not in self.headers:\n                        self.headers[hdrs.CONTENT_LENGTH] = str(size)\n\n        # copy payload headers\n        assert body.headers\n        for key, value in body.headers.items():\n            if key in self.headers or key in self.skip_auto_headers:\n                continue\n            self.headers[key] = value\n\n    def update_expect_continue(self, expect: bool = False) -> None:\n        if expect:\n            self.headers[hdrs.EXPECT] = \"100-continue\"\n        elif self.headers.get(hdrs.EXPECT, \"\").lower() == \"100-continue\":\n            expect = True\n\n        if expect:\n            self._continue = self.loop.create_future()\n\n    def update_proxy(\n        self,\n        proxy: Optional[URL],\n        proxy_auth: Optional[BasicAuth],\n        proxy_headers: Optional[LooseHeaders],\n    ) -> None:\n        if proxy_auth and not isinstance(proxy_auth, helpers.BasicAuth):\n            raise ValueError(\"proxy_auth must be None or BasicAuth() tuple\")\n        self.proxy = proxy\n        self.proxy_auth = proxy_auth\n        if proxy_headers is not None and not isinstance(\n            proxy_headers, (MultiDict, MultiDictProxy)\n        ):\n            proxy_headers = CIMultiDict(proxy_headers)\n        self.proxy_headers = proxy_headers\n\n    def keep_alive(self) -> bool:\n        if self.version < HttpVersion10:\n            # keep alive not supported at all\n            return False\n        if self.version == HttpVersion10:\n            if self.headers.get(hdrs.CONNECTION) == \"keep-alive\":\n                return True\n            else:  # no headers means we close for Http 1.0\n                return False\n        elif self.headers.get(hdrs.CONNECTION) == \"close\":\n            return False\n\n        return True\n\n    async def write_bytes(\n        self, writer: AbstractStreamWriter, conn: \"Connection\"\n    ) -> None:\n        \"\"\"Support coroutines that yields bytes objects.\"\"\"\n        # 100 response\n        if self._continue is not None:\n            try:\n                await writer.drain()\n                await self._continue\n            except asyncio.CancelledError:\n                return\n\n        protocol = conn.protocol\n        assert protocol is not None\n        try:\n            if isinstance(self.body, payload.Payload):\n                await self.body.write(writer)\n            else:\n                if isinstance(self.body, (bytes, bytearray)):\n                    self.body = (self.body,)\n\n                for chunk in self.body:\n                    await writer.write(chunk)\n        except OSError as underlying_exc:\n            reraised_exc = underlying_exc\n\n            exc_is_not_timeout = underlying_exc.errno is not None or not isinstance(\n                underlying_exc, asyncio.TimeoutError\n            )\n            if exc_is_not_timeout:\n                reraised_exc = ClientOSError(\n                    underlying_exc.errno,\n                    f\"Can not write request body for {self.url !s}\",\n                )\n\n            set_exception(protocol, reraised_exc, underlying_exc)\n        except asyncio.CancelledError:\n            await writer.write_eof()\n        except Exception as underlying_exc:\n            set_exception(\n                protocol,\n                ClientConnectionError(\n                    f\"Failed to send bytes into the underlying connection {conn !s}\",\n                ),\n                underlying_exc,\n            )\n        else:\n            await writer.write_eof()\n            protocol.start_timeout()\n\n    async def send(self, conn: \"Connection\") -> \"ClientResponse\":\n        # Specify request target:\n        # - CONNECT request must send authority form URI\n        # - not CONNECT proxy must send absolute form URI\n        # - most common is origin form URI\n        if self.method == hdrs.METH_CONNECT:\n            connect_host = self.url.raw_host\n            assert connect_host is not None\n            if helpers.is_ipv6_address(connect_host):\n                connect_host = f\"[{connect_host}]\"\n            path = f\"{connect_host}:{self.url.port}\"\n        elif self.proxy and not self.is_ssl():\n            path = str(self.url)\n        else:\n            path = self.url.raw_path\n            if self.url.raw_query_string:\n                path += \"?\" + self.url.raw_query_string\n\n        protocol = conn.protocol\n        assert protocol is not None\n        writer = StreamWriter(\n            protocol,\n            self.loop,\n            on_chunk_sent=functools.partial(\n                self._on_chunk_request_sent, self.method, self.url\n            ),\n            on_headers_sent=functools.partial(\n                self._on_headers_request_sent, self.method, self.url\n            ),\n        )\n\n        if self.compress:\n            writer.enable_compression(self.compress)\n\n        if self.chunked is not None:\n            writer.enable_chunking()\n\n        # set default content-type\n        if (\n            self.method in self.POST_METHODS\n            and hdrs.CONTENT_TYPE not in self.skip_auto_headers\n            and hdrs.CONTENT_TYPE not in self.headers\n        ):\n            self.headers[hdrs.CONTENT_TYPE] = \"application/octet-stream\"\n\n        # set the connection header\n        connection = self.headers.get(hdrs.CONNECTION)\n        if not connection:\n            if self.keep_alive():\n                if self.version == HttpVersion10:\n                    connection = \"keep-alive\"\n            else:\n                if self.version == HttpVersion11:\n                    connection = \"close\"\n\n        if connection is not None:\n            self.headers[hdrs.CONNECTION] = connection\n\n        # status + headers\n        v = self.version\n        status_line = f\"{self.method} {path} HTTP/{v.major}.{v.minor}\"\n        await writer.write_headers(status_line, self.headers)\n        coro = self.write_bytes(writer, conn)\n\n        if sys.version_info >= (3, 12):\n            # Optimization for Python 3.12, try to write\n            # bytes immediately to avoid having to schedule\n            # the task on the event loop.\n            task = asyncio.Task(coro, loop=self.loop, eager_start=True)\n        else:\n            task = self.loop.create_task(coro)\n\n        self._writer = task\n        response_class = self.response_class\n        assert response_class is not None\n        self.response = response_class(\n            self.method,\n            self.original_url,\n            writer=self._writer,\n            continue100=self._continue,\n            timer=self._timer,\n            request_info=self.request_info,\n            traces=self._traces,\n            loop=self.loop,\n            session=self._session,\n        )\n        return self.response\n\n    async def close(self) -> None:\n        if self._writer is not None:\n            with contextlib.suppress(asyncio.CancelledError):\n                await self._writer\n\n    def terminate(self) -> None:\n        if self._writer is not None:\n            if not self.loop.is_closed():\n                self._writer.cancel()\n            self._writer.remove_done_callback(self.__reset_writer)\n            self._writer = None\n\n    async def _on_chunk_request_sent(self, method: str, url: URL, chunk: bytes) -> None:\n        for trace in self._traces:\n            await trace.send_request_chunk_sent(method, url, chunk)\n\n    async def _on_headers_request_sent(\n        self, method: str, url: URL, headers: \"CIMultiDict[str]\"\n    ) -> None:\n        for trace in self._traces:\n            await trace.send_request_headers(method, url, headers)\n\n\nclass ClientResponse(HeadersMixin):\n\n    # Some of these attributes are None when created,\n    # but will be set by the start() method.\n    # As the end user will likely never see the None values, we cheat the types below.\n    # from the Status-Line of the response\n    version: Optional[HttpVersion] = None  # HTTP-Version\n    status: int = None  # type: ignore[assignment] # Status-Code\n    reason: Optional[str] = None  # Reason-Phrase\n\n    content: StreamReader = None  # type: ignore[assignment]  # Payload stream\n    _headers: CIMultiDictProxy[str] = None  # type: ignore[assignment]\n    _raw_headers: RawHeaders = None  # type: ignore[assignment]\n\n    _connection = None  # current connection\n    _source_traceback: Optional[traceback.StackSummary] = None\n    # set up by ClientRequest after ClientResponse object creation\n    # post-init stage allows to not change ctor signature\n    _closed = True  # to allow __del__ for non-initialized properly response\n    _released = False\n    __writer = None\n\n    def __init__(\n        self,\n        method: str,\n        url: URL,\n        *,\n        writer: \"asyncio.Task[None]\",\n        continue100: Optional[\"asyncio.Future[bool]\"],\n        timer: BaseTimerContext,\n        request_info: RequestInfo,\n        traces: List[\"Trace\"],\n        loop: asyncio.AbstractEventLoop,\n        session: \"ClientSession\",\n    ) -> None:\n        assert isinstance(url, URL)\n\n        self.method = method\n        self.cookies = SimpleCookie()\n\n        self._real_url = url\n        self._url = url.with_fragment(None)\n        self._body: Any = None\n        self._writer: Optional[asyncio.Task[None]] = writer\n        self._continue = continue100  # None by default\n        self._closed = True\n        self._history: Tuple[ClientResponse, ...] = ()\n        self._request_info = request_info\n        self._timer = timer if timer is not None else TimerNoop()\n        self._cache: Dict[str, Any] = {}\n        self._traces = traces\n        self._loop = loop\n        # store a reference to session #1985\n        self._session: Optional[ClientSession] = session\n        # Save reference to _resolve_charset, so that get_encoding() will still\n        # work after the response has finished reading the body.\n        if session is None:\n            # TODO: Fix session=None in tests (see ClientRequest.__init__).\n            self._resolve_charset: Callable[[\"ClientResponse\", bytes], str] = (\n                lambda *_: \"utf-8\"\n            )\n        else:\n            self._resolve_charset = session._resolve_charset\n        if loop.get_debug():\n            self._source_traceback = traceback.extract_stack(sys._getframe(1))\n\n    def __reset_writer(self, _: object = None) -> None:\n        self.__writer = None\n\n    @property\n    def _writer(self) -> Optional[\"asyncio.Task[None]\"]:\n        return self.__writer\n\n    @_writer.setter\n    def _writer(self, writer: Optional[\"asyncio.Task[None]\"]) -> None:\n        if self.__writer is not None:\n            self.__writer.remove_done_callback(self.__reset_writer)\n        self.__writer = writer\n        if writer is None:\n            return\n        if writer.done():\n            # The writer is already done, so we can reset it immediately.\n            self.__reset_writer()\n        else:\n            writer.add_done_callback(self.__reset_writer)\n\n    @reify\n    def url(self) -> URL:\n        return self._url\n\n    @reify\n    def url_obj(self) -> URL:\n        warnings.warn(\"Deprecated, use .url #1654\", DeprecationWarning, stacklevel=2)\n        return self._url\n\n    @reify\n    def real_url(self) -> URL:\n        return self._real_url\n\n    @reify\n    def host(self) -> str:\n        assert self._url.host is not None\n        return self._url.host\n\n    @reify\n    def headers(self) -> \"CIMultiDictProxy[str]\":\n        return self._headers\n\n    @reify\n    def raw_headers(self) -> RawHeaders:\n        return self._raw_headers\n\n    @reify\n    def request_info(self) -> RequestInfo:\n        return self._request_info\n\n    @reify\n    def content_disposition(self) -> Optional[ContentDisposition]:\n        raw = self._headers.get(hdrs.CONTENT_DISPOSITION)\n        if raw is None:\n            return None\n        disposition_type, params_dct = multipart.parse_content_disposition(raw)\n        params = MappingProxyType(params_dct)\n        filename = multipart.content_disposition_filename(params)\n        return ContentDisposition(disposition_type, params, filename)\n\n    def __del__(self, _warnings: Any = warnings) -> None:\n        if self._closed:\n            return\n\n        if self._connection is not None:\n            self._connection.release()\n            self._cleanup_writer()\n\n            if self._loop.get_debug():\n                kwargs = {\"source\": self}\n                _warnings.warn(f\"Unclosed response {self!r}\", ResourceWarning, **kwargs)\n                context = {\"client_response\": self, \"message\": \"Unclosed response\"}\n                if self._source_traceback:\n                    context[\"source_traceback\"] = self._source_traceback\n                self._loop.call_exception_handler(context)\n\n    def __repr__(self) -> str:\n        out = io.StringIO()\n        ascii_encodable_url = str(self.url)\n        if self.reason:\n            ascii_encodable_reason = self.reason.encode(\n                \"ascii\", \"backslashreplace\"\n            ).decode(\"ascii\")\n        else:\n            ascii_encodable_reason = \"None\"\n        print(\n            \"<ClientResponse({}) [{} {}]>\".format(\n                ascii_encodable_url, self.status, ascii_encodable_reason\n            ),\n            file=out,\n        )\n        print(self.headers, file=out)\n        return out.getvalue()\n\n    @property\n    def connection(self) -> Optional[\"Connection\"]:\n        return self._connection\n\n    @reify\n    def history(self) -> Tuple[\"ClientResponse\", ...]:\n        \"\"\"A sequence of of responses, if redirects occurred.\"\"\"\n        return self._history\n\n    @reify\n    def links(self) -> \"MultiDictProxy[MultiDictProxy[Union[str, URL]]]\":\n        links_str = \", \".join(self.headers.getall(\"link\", []))\n\n        if not links_str:\n            return MultiDictProxy(MultiDict())\n\n        links: MultiDict[MultiDictProxy[Union[str, URL]]] = MultiDict()\n\n        for val in re.split(r\",(?=\\s*<)\", links_str):\n            match = re.match(r\"\\s*<(.*)>(.*)\", val)\n            if match is None:  # pragma: no cover\n                # the check exists to suppress mypy error\n                continue\n            url, params_str = match.groups()\n            params = params_str.split(\";\")[1:]\n\n            link: MultiDict[Union[str, URL]] = MultiDict()\n\n            for param in params:\n                match = re.match(r\"^\\s*(\\S*)\\s*=\\s*(['\\\"]?)(.*?)(\\2)\\s*$\", param, re.M)\n                if match is None:  # pragma: no cover\n                    # the check exists to suppress mypy error\n                    continue\n                key, _, value, _ = match.groups()\n\n                link.add(key, value)\n\n            key = link.get(\"rel\", url)\n\n            link.add(\"url\", self.url.join(URL(url)))\n\n            links.add(str(key), MultiDictProxy(link))\n\n        return MultiDictProxy(links)\n\n    async def start(self, connection: \"Connection\") -> \"ClientResponse\":\n        \"\"\"Start response processing.\"\"\"\n        self._closed = False\n        self._protocol = connection.protocol\n        self._connection = connection\n\n        with self._timer:\n            while True:\n                # read response\n                try:\n                    protocol = self._protocol\n                    message, payload = await protocol.read()  # type: ignore[union-attr]\n                except http.HttpProcessingError as exc:\n                    raise ClientResponseError(\n                        self.request_info,\n                        self.history,\n                        status=exc.code,\n                        message=exc.message,\n                        headers=exc.headers,\n                    ) from exc\n\n                if message.code < 100 or message.code > 199 or message.code == 101:\n                    break\n\n                if self._continue is not None:\n                    set_result(self._continue, True)\n                    self._continue = None\n\n        # payload eof handler\n        payload.on_eof(self._response_eof)\n\n        # response status\n        self.version = message.version\n        self.status = message.code\n        self.reason = message.reason\n\n        # headers\n        self._headers = message.headers  # type is CIMultiDictProxy\n        self._raw_headers = message.raw_headers  # type is Tuple[bytes, bytes]\n\n        # payload\n        self.content = payload\n\n        # cookies\n        for hdr in self.headers.getall(hdrs.SET_COOKIE, ()):\n            try:\n                self.cookies.load(hdr)\n            except CookieError as exc:\n                client_logger.warning(\"Can not load response cookies: %s\", exc)\n        return self\n\n    def _response_eof(self) -> None:\n        if self._closed:\n            return\n\n        # protocol could be None because connection could be detached\n        protocol = self._connection and self._connection.protocol\n        if protocol is not None and protocol.upgraded:\n            return\n\n        self._closed = True\n        self._cleanup_writer()\n        self._release_connection()\n\n    @property\n    def closed(self) -> bool:\n        return self._closed\n\n    def close(self) -> None:\n        if not self._released:\n            self._notify_content()\n\n        self._closed = True\n        if self._loop is None or self._loop.is_closed():\n            return\n\n        self._cleanup_writer()\n        if self._connection is not None:\n            self._connection.close()\n            self._connection = None\n\n    def release(self) -> Any:\n        if not self._released:\n            self._notify_content()\n\n        self._closed = True\n\n        self._cleanup_writer()\n        self._release_connection()\n        return noop()\n\n    @property\n    def ok(self) -> bool:\n        \"\"\"Returns ``True`` if ``status`` is less than ``400``, ``False`` if not.\n\n        This is **not** a check for ``200 OK`` but a check that the response\n        status is under 400.\n        \"\"\"\n        return 400 > self.status\n\n    def raise_for_status(self) -> None:\n        if not self.ok:\n            # reason should always be not None for a started response\n            assert self.reason is not None\n            self.release()\n            raise ClientResponseError(\n                self.request_info,\n                self.history,\n                status=self.status,\n                message=self.reason,\n                headers=self.headers,\n            )\n\n    def _release_connection(self) -> None:\n        if self._connection is not None:\n            if self._writer is None:\n                self._connection.release()\n                self._connection = None\n            else:\n                self._writer.add_done_callback(lambda f: self._release_connection())\n\n    async def _wait_released(self) -> None:\n        if self._writer is not None:\n            await self._writer\n        self._release_connection()\n\n    def _cleanup_writer(self) -> None:\n        if self._writer is not None:\n            self._writer.cancel()\n        self._session = None\n\n    def _notify_content(self) -> None:\n        content = self.content\n        if content and content.exception() is None:\n            set_exception(content, ClientConnectionError(\"Connection closed\"))\n        self._released = True\n\n    async def wait_for_close(self) -> None:\n        if self._writer is not None:\n            await self._writer\n        self.release()\n\n    async def read(self) -> bytes:\n        \"\"\"Read response payload.\"\"\"\n        if self._body is None:\n            try:\n                self._body = await self.content.read()\n                for trace in self._traces:\n                    await trace.send_response_chunk_received(\n                        self.method, self.url, self._body\n                    )\n            except BaseException:\n                self.close()\n                raise\n        elif self._released:  # Response explicitly released\n            raise ClientConnectionError(\"Connection closed\")\n\n        protocol = self._connection and self._connection.protocol\n        if protocol is None or not protocol.upgraded:\n            await self._wait_released()  # Underlying connection released\n        return self._body  # type: ignore[no-any-return]\n\n    def get_encoding(self) -> str:\n        ctype = self.headers.get(hdrs.CONTENT_TYPE, \"\").lower()\n        mimetype = helpers.parse_mimetype(ctype)\n\n        encoding = mimetype.parameters.get(\"charset\")\n        if encoding:\n            with contextlib.suppress(LookupError):\n                return codecs.lookup(encoding).name\n\n        if mimetype.type == \"application\" and (\n            mimetype.subtype == \"json\" or mimetype.subtype == \"rdap\"\n        ):\n            # RFC 7159 states that the default encoding is UTF-8.\n            # RFC 7483 defines application/rdap+json\n            return \"utf-8\"\n\n        if self._body is None:\n            raise RuntimeError(\n                \"Cannot compute fallback encoding of a not yet read body\"\n            )\n\n        return self._resolve_charset(self, self._body)\n\n    async def text(self, encoding: Optional[str] = None, errors: str = \"strict\") -> str:\n        \"\"\"Read response payload and decode.\"\"\"\n        if self._body is None:\n            await self.read()\n\n        if encoding is None:\n            encoding = self.get_encoding()\n\n        return self._body.decode(  # type: ignore[no-any-return,union-attr]\n            encoding, errors=errors\n        )\n\n    async def json(\n        self,\n        *,\n        encoding: Optional[str] = None,\n        loads: JSONDecoder = DEFAULT_JSON_DECODER,\n        content_type: Optional[str] = \"application/json\",\n    ) -> Any:\n        \"\"\"Read and decodes JSON response.\"\"\"\n        if self._body is None:\n            await self.read()\n\n        if content_type:\n            ctype = self.headers.get(hdrs.CONTENT_TYPE, \"\").lower()\n            if not _is_expected_content_type(ctype, content_type):\n                raise ContentTypeError(\n                    self.request_info,\n                    self.history,\n                    status=self.status,\n                    message=(\n                        \"Attempt to decode JSON with \" \"unexpected mimetype: %s\" % ctype\n                    ),\n                    headers=self.headers,\n                )\n\n        stripped = self._body.strip()  # type: ignore[union-attr]\n        if not stripped:\n            return None\n\n        if encoding is None:\n            encoding = self.get_encoding()\n\n        return loads(stripped.decode(encoding))\n\n    async def __aenter__(self) -> \"ClientResponse\":\n        return self\n\n    async def __aexit__(\n        self,\n        exc_type: Optional[Type[BaseException]],\n        exc_val: Optional[BaseException],\n        exc_tb: Optional[TracebackType],\n    ) -> None:\n        # similar to _RequestContextManager, we do not need to check\n        # for exceptions, response object can close connection\n        # if state is broken\n        self.release()\n        await self.wait_for_close()\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:** Canceling Payload Send Causes Connection to Hang and Prevents Reuse

**Description:**
When a client cancels sending the payload during a request, the connection remains open instead of being properly closed. This prevents the connection from being reused for subsequent requests, leading to hung connections and timeout errors.

**Example Code:**
```python
async def upload_file(client, file_path):
    with open(file_path, "rb") as file:
        data = {'file': file}
        await client.post("/upload", data=data)
        await client.get("/status", timeout=0.01)  # This request hangs due to the open connection
```

**Expected Behavior:**
After canceling the payload send, the connection should be closed properly, allowing the client to reuse connections for new requests without any hanging or timeout issues.

**Actual Behavior:**
The connection remains open after the payload send is canceled, causing subsequent requests to hang and eventually timeout because the connection cannot be reused.

[/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_reqrep.py
import asyncio
import codecs
import contextlib
import functools
import io
import re
import sys
import traceback
import warnings
from hashlib import md5, sha1, sha256
from http.cookies import CookieError, Morsel, SimpleCookie
from types import MappingProxyType, TracebackType
from typing import (
    TYPE_CHECKING,
    Any,
    Callable,
    Dict,
    Iterable,
    List,
    Mapping,
    Optional,
    Tuple,
    Type,
    Union,
    cast,
)

import attr
from multidict import CIMultiDict, CIMultiDictProxy, MultiDict, MultiDictProxy
from yarl import URL

from . import hdrs, helpers, http, multipart, payload
from .abc import AbstractStreamWriter
from .client_exceptions import (
    ClientConnectionError,
    ClientOSError,
    ClientResponseError,
    ContentTypeError,
    InvalidURL,
    ServerFingerprintMismatch,
)
from .compression_utils import HAS_BROTLI
from .formdata import FormData
from .helpers import (
    BaseTimerContext,
    BasicAuth,
    HeadersMixin,
    TimerNoop,
    basicauth_from_netrc,
    netrc_from_env,
    noop,
    reify,
    set_exception,
    set_result,
)
from .http import (
    SERVER_SOFTWARE,
    HttpVersion,
    HttpVersion10,
    HttpVersion11,
    StreamWriter,
)
from .log import client_logger
from .streams import StreamReader
from .typedefs import (
    DEFAULT_JSON_DECODER,
    JSONDecoder,
    LooseCookies,
    LooseHeaders,
    RawHeaders,
)

try:
    import ssl
    from ssl import SSLContext
except ImportError:  # pragma: no cover
    ssl = None  # type: ignore[assignment]
    SSLContext = object  # type: ignore[misc,assignment]


__all__ = ("ClientRequest", "ClientResponse", "RequestInfo", "Fingerprint")


if TYPE_CHECKING:
    from .client import ClientSession
    from .connector import Connection
    from .tracing import Trace


_CONTAINS_CONTROL_CHAR_RE = re.compile(r"[^-!#$%&'*+.^_`|~0-9a-zA-Z]")
json_re = re.compile(r"^application/(?:[\w.+-]+?\+)?json")


def _gen_default_accept_encoding() -> str:
    return "gzip, deflate, br" if HAS_BROTLI else "gzip, deflate"


@attr.s(auto_attribs=True, frozen=True, slots=True)
class ContentDisposition:
    type: Optional[str]
    parameters: "MappingProxyType[str, str]"
    filename: Optional[str]


@attr.s(auto_attribs=True, frozen=True, slots=True)
class RequestInfo:
    url: URL
    method: str
    headers: "CIMultiDictProxy[str]"
    real_url: URL = attr.ib()

    @real_url.default
    def real_url_default(self) -> URL:
        return self.url


class Fingerprint:
    HASHFUNC_BY_DIGESTLEN = {
        16: md5,
        20: sha1,
        32: sha256,
    }

    def __init__(self, fingerprint: bytes) -> None:
        digestlen = len(fingerprint)
        hashfunc = self.HASHFUNC_BY_DIGESTLEN.get(digestlen)
        if not hashfunc:
            raise ValueError("fingerprint has invalid length")
        elif hashfunc is md5 or hashfunc is sha1:
            raise ValueError(
                "md5 and sha1 are insecure and " "not supported. Use sha256."
            )
        self._hashfunc = hashfunc
        self._fingerprint = fingerprint

    @property
    def fingerprint(self) -> bytes:
        return self._fingerprint

    def check(self, transport: asyncio.Transport) -> None:
        if not transport.get_extra_info("sslcontext"):
            return
        sslobj = transport.get_extra_info("ssl_object")
        cert = sslobj.getpeercert(binary_form=True)
        got = self._hashfunc(cert).digest()
        if got != self._fingerprint:
            host, port, *_ = transport.get_extra_info("peername")
            raise ServerFingerprintMismatch(self._fingerprint, got, host, port)


if ssl is not None:
    SSL_ALLOWED_TYPES = (ssl.SSLContext, bool, Fingerprint, type(None))
else:  # pragma: no cover
    SSL_ALLOWED_TYPES = (bool, type(None))


def _merge_ssl_params(
    ssl: Union["SSLContext", bool, Fingerprint],
    verify_ssl: Optional[bool],
    ssl_context: Optional["SSLContext"],
    fingerprint: Optional[bytes],
) -> Union["SSLContext", bool, Fingerprint]:
    if ssl is None:
        ssl = True  # Double check for backwards compatibility
    if verify_ssl is not None and not verify_ssl:
        warnings.warn(
            "verify_ssl is deprecated, use ssl=False instead",
            DeprecationWarning,
            stacklevel=3,
        )
        if ssl is not True:
            raise ValueError(
                "verify_ssl, ssl_context, fingerprint and ssl "
                "parameters are mutually exclusive"
            )
        else:
            ssl = False
    if ssl_context is not None:
        warnings.warn(
            "ssl_context is deprecated, use ssl=context instead",
            DeprecationWarning,
            stacklevel=3,
        )
        if ssl is not True:
            raise ValueError(
                "verify_ssl, ssl_context, fingerprint and ssl "
                "parameters are mutually exclusive"
            )
        else:
            ssl = ssl_context
    if fingerprint is not None:
        warnings.warn(
            "fingerprint is deprecated, " "use ssl=Fingerprint(fingerprint) instead",
            DeprecationWarning,
            stacklevel=3,
        )
        if ssl is not True:
            raise ValueError(
                "verify_ssl, ssl_context, fingerprint and ssl "
                "parameters are mutually exclusive"
            )
        else:
            ssl = Fingerprint(fingerprint)
    if not isinstance(ssl, SSL_ALLOWED_TYPES):
        raise TypeError(
            "ssl should be SSLContext, bool, Fingerprint or None, "
            "got {!r} instead.".format(ssl)
        )
    return ssl


@attr.s(auto_attribs=True, slots=True, frozen=True, cache_hash=True)
class ConnectionKey:
    # the key should contain an information about used proxy / TLS
    # to prevent reusing wrong connections from a pool
    host: str
    port: Optional[int]
    is_ssl: bool
    ssl: Union[SSLContext, bool, Fingerprint]
    proxy: Optional[URL]
    proxy_auth: Optional[BasicAuth]
    proxy_headers_hash: Optional[int]  # hash(CIMultiDict)


def _is_expected_content_type(
    response_content_type: str, expected_content_type: str
) -> bool:
    if expected_content_type == "application/json":
        return json_re.match(response_content_type) is not None
    return expected_content_type in response_content_type


class ClientRequest:
    GET_METHODS = {
        hdrs.METH_GET,
        hdrs.METH_HEAD,
        hdrs.METH_OPTIONS,
        hdrs.METH_TRACE,
    }
    POST_METHODS = {hdrs.METH_PATCH, hdrs.METH_POST, hdrs.METH_PUT}
    ALL_METHODS = GET_METHODS.union(POST_METHODS).union({hdrs.METH_DELETE})

    DEFAULT_HEADERS = {
        hdrs.ACCEPT: "*/*",
        hdrs.ACCEPT_ENCODING: _gen_default_accept_encoding(),
    }

    # Type of body depends on PAYLOAD_REGISTRY, which is dynamic.
    body: Any = b""
    auth = None
    response = None

    __writer = None  # async task for streaming data
    _continue = None  # waiter future for '100 Continue' response

    # N.B.
    # Adding __del__ method with self._writer closing doesn't make sense
    # because _writer is instance method, thus it keeps a reference to self.
    # Until writer has finished finalizer will not be called.

    def __init__(
        self,
        method: str,
        url: URL,
        *,
        params: Optional[Mapping[str, str]] = None,
        headers: Optional[LooseHeaders] = None,
        skip_auto_headers: Optional[Iterable[str]] = None,
        data: Any = None,
        cookies: Optional[LooseCookies] = None,
        auth: Optional[BasicAuth] = None,
        version: http.HttpVersion = http.HttpVersion11,
        compress: Optional[str] = None,
        chunked: Optional[bool] = None,
        expect100: bool = False,
        loop: Optional[asyncio.AbstractEventLoop] = None,
        response_class: Optional[Type["ClientResponse"]] = None,
        proxy: Optional[URL] = None,
        proxy_auth: Optional[BasicAuth] = None,
        timer: Optional[BaseTimerContext] = None,
        session: Optional["ClientSession"] = None,
        ssl: Union[SSLContext, bool, Fingerprint] = True,
        proxy_headers: Optional[LooseHeaders] = None,
        traces: Optional[List["Trace"]] = None,
        trust_env: bool = False,
        server_hostname: Optional[str] = None,
    ):
        if loop is None:
            loop = asyncio.get_event_loop()

        match = _CONTAINS_CONTROL_CHAR_RE.search(method)
        if match:
            raise ValueError(
                f"Method cannot contain non-token characters {method!r} "
                "(found at least {match.group()!r})"
            )

        assert isinstance(url, URL), url
        assert isinstance(proxy, (URL, type(None))), proxy
        # FIXME: session is None in tests only, need to fix tests
        # assert session is not None
        self._session = cast("ClientSession", session)
        if params:
            q = MultiDict(url.query)
            url2 = url.with_query(params)
            q.extend(url2.query)
            url = url.with_query(q)
        self.original_url = url
        self.url = url.with_fragment(None)
        self.method = method.upper()
        self.chunked = chunked
        self.compress = compress
        self.loop = loop
        self.length = None
        if response_class is None:
            real_response_class = ClientResponse
        else:
            real_response_class = response_class
        self.response_class: Type[ClientResponse] = real_response_class
        self._timer = timer if timer is not None else TimerNoop()
        self._ssl = ssl if ssl is not None else True
        self.server_hostname = server_hostname

        if loop.get_debug():
            self._source_traceback = traceback.extract_stack(sys._getframe(1))

        self.update_version(version)
        self.update_host(url)
        self.update_headers(headers)
        self.update_auto_headers(skip_auto_headers)
        self.update_cookies(cookies)
        self.update_content_encoding(data)
        self.update_auth(auth, trust_env)
        self.update_proxy(proxy, proxy_auth, proxy_headers)

        self.update_body_from_data(data)
        if data is not None or self.method not in self.GET_METHODS:
            self.update_transfer_encoding()
        self.update_expect_continue(expect100)
        if traces is None:
            traces = []
        self._traces = traces

    def __reset_writer(self, _: object = None) -> None:
        self.__writer = None

    @property
    def _writer(self) -> Optional["asyncio.Task[None]"]:
        return self.__writer

    @_writer.setter
    def _writer(self, writer: Optional["asyncio.Task[None]"]) -> None:
        if self.__writer is not None:
            self.__writer.remove_done_callback(self.__reset_writer)
        self.__writer = writer
        if writer is None:
            return
        if writer.done():
            # The writer is already done, so we can reset it immediately.
            self.__reset_writer()
        else:
            writer.add_done_callback(self.__reset_writer)

    def is_ssl(self) -> bool:
        return self.url.scheme in ("https", "wss")

    @property
    def ssl(self) -> Union["SSLContext", bool, Fingerprint]:
        return self._ssl

    @property
    def connection_key(self) -> ConnectionKey:
        proxy_headers = self.proxy_headers
        if proxy_headers:
            h: Optional[int] = hash(tuple((k, v) for k, v in proxy_headers.items()))
        else:
            h = None
        return ConnectionKey(
            self.host,
            self.port,
            self.is_ssl(),
            self.ssl,
            self.proxy,
            self.proxy_auth,
            h,
        )

    @property
    def host(self) -> str:
        ret = self.url.raw_host
        assert ret is not None
        return ret

    @property
    def port(self) -> Optional[int]:
        return self.url.port

    @property
    def request_info(self) -> RequestInfo:
        headers: CIMultiDictProxy[str] = CIMultiDictProxy(self.headers)
        return RequestInfo(self.url, self.method, headers, self.original_url)

    def update_host(self, url: URL) -> None:
        """Update destination host, port and connection type (ssl)."""
        # get host/port
        if not url.raw_host:
            raise InvalidURL(url)

        # basic auth info
        username, password = url.user, url.password
        if username or password:
            self.auth = helpers.BasicAuth(username or "", password or "")

    def update_version(self, version: Union[http.HttpVersion, str]) -> None:
        """Convert request version to two elements tuple.

        parser HTTP version '1.1' => (1, 1)
        """
        if isinstance(version, str):
            v = [part.strip() for part in version.split(".", 1)]
            try:
                version = http.HttpVersion(int(v[0]), int(v[1]))
            except ValueError:
                raise ValueError(
                    f"Can not parse http version number: {version}"
                ) from None
        self.version = version

    def update_headers(self, headers: Optional[LooseHeaders]) -> None:
        """Update request headers."""
        self.headers: CIMultiDict[str] = CIMultiDict()

        # add host
        netloc = cast(str, self.url.raw_host)
        if helpers.is_ipv6_address(netloc):
            netloc = f"[{netloc}]"
        # See https://github.com/aio-libs/aiohttp/issues/3636.
        netloc = netloc.rstrip(".")
        if self.url.port is not None and not self.url.is_default_port():
            netloc += ":" + str(self.url.port)
        self.headers[hdrs.HOST] = netloc

        if headers:
            if isinstance(headers, (dict, MultiDictProxy, MultiDict)):
                headers = headers.items()

            for key, value in headers:  # type: ignore[misc]
                # A special case for Host header
                if key.lower() == "host":
                    self.headers[key] = value
                else:
                    self.headers.add(key, value)

    def update_auto_headers(self, skip_auto_headers: Optional[Iterable[str]]) -> None:
        if skip_auto_headers is not None:
            self.skip_auto_headers = CIMultiDict(
                (hdr, None) for hdr in sorted(skip_auto_headers)
            )
            used_headers = self.headers.copy()
            used_headers.extend(self.skip_auto_headers)  # type: ignore[arg-type]
        else:
            # Fast path when there are no headers to skip
            # which is the most common case.
            self.skip_auto_headers = CIMultiDict()
            used_headers = self.headers

        for hdr, val in self.DEFAULT_HEADERS.items():
            if hdr not in used_headers:
                self.headers.add(hdr, val)

        if hdrs.USER_AGENT not in used_headers:
            self.headers[hdrs.USER_AGENT] = SERVER_SOFTWARE

    def update_cookies(self, cookies: Optional[LooseCookies]) -> None:
        """Update request cookies header."""
        if not cookies:
            return

        c = SimpleCookie()
        if hdrs.COOKIE in self.headers:
            c.load(self.headers.get(hdrs.COOKIE, ""))
            del self.headers[hdrs.COOKIE]

        if isinstance(cookies, Mapping):
            iter_cookies = cookies.items()
        else:
            iter_cookies = cookies  # type: ignore[assignment]
        for name, value in iter_cookies:
            if isinstance(value, Morsel):
                # Preserve coded_value
                mrsl_val = value.get(value.key, Morsel())
                mrsl_val.set(value.key, value.value, value.coded_value)
                c[name] = mrsl_val
            else:
                c[name] = value  # type: ignore[assignment]

        self.headers[hdrs.COOKIE] = c.output(header="", sep=";").strip()

    def update_content_encoding(self, data: Any) -> None:
        """Set request content encoding."""
        if data is None:
            return

        enc = self.headers.get(hdrs.CONTENT_ENCODING, "").lower()
        if enc:
            if self.compress:
                raise ValueError(
                    "compress can not be set " "if Content-Encoding header is set"
                )
        elif self.compress:
            if not isinstance(self.compress, str):
                self.compress = "deflate"
            self.headers[hdrs.CONTENT_ENCODING] = self.compress
            self.chunked = True  # enable chunked, no need to deal with length

    def update_transfer_encoding(self) -> None:
        """Analyze transfer-encoding header."""
        te = self.headers.get(hdrs.TRANSFER_ENCODING, "").lower()

        if "chunked" in te:
            if self.chunked:
                raise ValueError(
                    "chunked can not be set "
                    'if "Transfer-Encoding: chunked" header is set'
                )

        elif self.chunked:
            if hdrs.CONTENT_LENGTH in self.headers:
                raise ValueError(
                    "chunked can not be set " "if Content-Length header is set"
                )

            self.headers[hdrs.TRANSFER_ENCODING] = "chunked"
        else:
            if hdrs.CONTENT_LENGTH not in self.headers:
                self.headers[hdrs.CONTENT_LENGTH] = str(len(self.body))

    def update_auth(self, auth: Optional[BasicAuth], trust_env: bool = False) -> None:
        """Set basic auth."""
        if auth is None:
            auth = self.auth
        if auth is None and trust_env and self.url.host is not None:
            netrc_obj = netrc_from_env()
            with contextlib.suppress(LookupError):
                auth = basicauth_from_netrc(netrc_obj, self.url.host)
        if auth is None:
            return

        if not isinstance(auth, helpers.BasicAuth):
            raise TypeError("BasicAuth() tuple is required instead")

        self.headers[hdrs.AUTHORIZATION] = auth.encode()

    def update_body_from_data(self, body: Any) -> None:
        if body is None:
            return

        # FormData
        if isinstance(body, FormData):
            body = body()

        try:
            body = payload.PAYLOAD_REGISTRY.get(body, disposition=None)
        except payload.LookupError:
            body = FormData(body)()

        self.body = body

        # enable chunked encoding if needed
        if not self.chunked:
            if hdrs.CONTENT_LENGTH not in self.headers:
                size = body.size
                if size is None:
                    self.chunked = True
                else:
                    if hdrs.CONTENT_LENGTH not in self.headers:
                        self.headers[hdrs.CONTENT_LENGTH] = str(size)

        # copy payload headers
        assert body.headers
        for key, value in body.headers.items():
            if key in self.headers or key in self.skip_auto_headers:
                continue
            self.headers[key] = value

    def update_expect_continue(self, expect: bool = False) -> None:
        if expect:
            self.headers[hdrs.EXPECT] = "100-continue"
        elif self.headers.get(hdrs.EXPECT, "").lower() == "100-continue":
            expect = True

        if expect:
            self._continue = self.loop.create_future()

    def update_proxy(
        self,
        proxy: Optional[URL],
        proxy_auth: Optional[BasicAuth],
        proxy_headers: Optional[LooseHeaders],
    ) -> None:
        if proxy_auth and not isinstance(proxy_auth, helpers.BasicAuth):
            raise ValueError("proxy_auth must be None or BasicAuth() tuple")
        self.proxy = proxy
        self.proxy_auth = proxy_auth
        if proxy_headers is not None and not isinstance(
            proxy_headers, (MultiDict, MultiDictProxy)
        ):
            proxy_headers = CIMultiDict(proxy_headers)
        self.proxy_headers = proxy_headers

    def keep_alive(self) -> bool:
        if self.version < HttpVersion10:
            # keep alive not supported at all
            return False
        if self.version == HttpVersion10:
            if self.headers.get(hdrs.CONNECTION) == "keep-alive":
                return True
            else:  # no headers means we close for Http 1.0
                return False
        elif self.headers.get(hdrs.CONNECTION) == "close":
            return False

        return True

    async def write_bytes(
        self, writer: AbstractStreamWriter, conn: "Connection"
    ) -> None:
        """Support coroutines that yields bytes objects."""
        # 100 response
        if self._continue is not None:
            try:
                await writer.drain()
                await self._continue
            except asyncio.CancelledError:
                return

        protocol = conn.protocol
        assert protocol is not None
        try:
            if isinstance(self.body, payload.Payload):
                await self.body.write(writer)
            else:
                if isinstance(self.body, (bytes, bytearray)):
                    self.body = (self.body,)

                for chunk in self.body:
                    await writer.write(chunk)
        except OSError as underlying_exc:
            reraised_exc = underlying_exc

            exc_is_not_timeout = underlying_exc.errno is not None or not isinstance(
                underlying_exc, asyncio.TimeoutError
            )
            if exc_is_not_timeout:
                reraised_exc = ClientOSError(
                    underlying_exc.errno,
                    f"Can not write request body for {self.url !s}",
                )

            set_exception(protocol, reraised_exc, underlying_exc)
        except asyncio.CancelledError:
            await writer.write_eof()
        except Exception as underlying_exc:
            set_exception(
                protocol,
                ClientConnectionError(
                    f"Failed to send bytes into the underlying connection {conn !s}",
                ),
                underlying_exc,
            )
        else:
            await writer.write_eof()
            protocol.start_timeout()

    async def send(self, conn: "Connection") -> "ClientResponse":
        # Specify request target:
        # - CONNECT request must send authority form URI
        # - not CONNECT proxy must send absolute form URI
        # - most common is origin form URI
        if self.method == hdrs.METH_CONNECT:
            connect_host = self.url.raw_host
            assert connect_host is not None
            if helpers.is_ipv6_address(connect_host):
                connect_host = f"[{connect_host}]"
            path = f"{connect_host}:{self.url.port}"
        elif self.proxy and not self.is_ssl():
            path = str(self.url)
        else:
            path = self.url.raw_path
            if self.url.raw_query_string:
                path += "?" + self.url.raw_query_string

        protocol = conn.protocol
        assert protocol is not None
        writer = StreamWriter(
            protocol,
            self.loop,
            on_chunk_sent=functools.partial(
                self._on_chunk_request_sent, self.method, self.url
            ),
            on_headers_sent=functools.partial(
                self._on_headers_request_sent, self.method, self.url
            ),
        )

        if self.compress:
            writer.enable_compression(self.compress)

        if self.chunked is not None:
            writer.enable_chunking()

        # set default content-type
        if (
            self.method in self.POST_METHODS
            and hdrs.CONTENT_TYPE not in self.skip_auto_headers
            and hdrs.CONTENT_TYPE not in self.headers
        ):
            self.headers[hdrs.CONTENT_TYPE] = "application/octet-stream"

        # set the connection header
        connection = self.headers.get(hdrs.CONNECTION)
        if not connection:
            if self.keep_alive():
                if self.version == HttpVersion10:
                    connection = "keep-alive"
            else:
                if self.version == HttpVersion11:
                    connection = "close"

        if connection is not None:
            self.headers[hdrs.CONNECTION] = connection

        # status + headers
        v = self.version
        status_line = f"{self.method} {path} HTTP/{v.major}.{v.minor}"
        await writer.write_headers(status_line, self.headers)
        coro = self.write_bytes(writer, conn)

        if sys.version_info >= (3, 12):
            # Optimization for Python 3.12, try to write
            # bytes immediately to avoid having to schedule
            # the task on the event loop.
            task = asyncio.Task(coro, loop=self.loop, eager_start=True)
        else:
            task = self.loop.create_task(coro)

        self._writer = task
        response_class = self.response_class
        assert response_class is not None
        self.response = response_class(
            self.method,
            self.original_url,
            writer=self._writer,
            continue100=self._continue,
            timer=self._timer,
            request_info=self.request_info,
            traces=self._traces,
            loop=self.loop,
            session=self._session,
        )
        return self.response

    async def close(self) -> None:
        if self._writer is not None:
            with contextlib.suppress(asyncio.CancelledError):
                await self._writer

    def terminate(self) -> None:
        if self._writer is not None:
            if not self.loop.is_closed():
                self._writer.cancel()
            self._writer.remove_done_callback(self.__reset_writer)
            self._writer = None

    async def _on_chunk_request_sent(self, method: str, url: URL, chunk: bytes) -> None:
        for trace in self._traces:
            await trace.send_request_chunk_sent(method, url, chunk)

    async def _on_headers_request_sent(
        self, method: str, url: URL, headers: "CIMultiDict[str]"
    ) -> None:
        for trace in self._traces:
            await trace.send_request_headers(method, url, headers)


class ClientResponse(HeadersMixin):

    # Some of these attributes are None when created,
    # but will be set by the start() method.
    # As the end user will likely never see the None values, we cheat the types below.
    # from the Status-Line of the response
    version: Optional[HttpVersion] = None  # HTTP-Version
    status: int = None  # type: ignore[assignment] # Status-Code
    reason: Optional[str] = None  # Reason-Phrase

    content: StreamReader = None  # type: ignore[assignment]  # Payload stream
    _headers: CIMultiDictProxy[str] = None  # type: ignore[assignment]
    _raw_headers: RawHeaders = None  # type: ignore[assignment]

    _connection = None  # current connection
    _source_traceback: Optional[traceback.StackSummary] = None
    # set up by ClientRequest after ClientResponse object creation
    # post-init stage allows to not change ctor signature
    _closed = True  # to allow __del__ for non-initialized properly response
    _released = False
    __writer = None

    def __init__(
        self,
        method: str,
        url: URL,
        *,
        writer: "asyncio.Task[None]",
        continue100: Optional["asyncio.Future[bool]"],
        timer: BaseTimerContext,
        request_info: RequestInfo,
        traces: List["Trace"],
        loop: asyncio.AbstractEventLoop,
        session: "ClientSession",
    ) -> None:
        assert isinstance(url, URL)

        self.method = method
        self.cookies = SimpleCookie()

        self._real_url = url
        self._url = url.with_fragment(None)
        self._body: Any = None
        self._writer: Optional[asyncio.Task[None]] = writer
        self._continue = continue100  # None by default
        self._closed = True
        self._history: Tuple[ClientResponse, ...] = ()
        self._request_info = request_info
        self._timer = timer if timer is not None else TimerNoop()
        self._cache: Dict[str, Any] = {}
        self._traces = traces
        self._loop = loop
        # store a reference to session #1985
        self._session: Optional[ClientSession] = session
        # Save reference to _resolve_charset, so that get_encoding() will still
        # work after the response has finished reading the body.
        if session is None:
            # TODO: Fix session=None in tests (see ClientRequest.__init__).
            self._resolve_charset: Callable[["ClientResponse", bytes], str] = (
                lambda *_: "utf-8"
            )
        else:
            self._resolve_charset = session._resolve_charset
        if loop.get_debug():
            self._source_traceback = traceback.extract_stack(sys._getframe(1))

    def __reset_writer(self, _: object = None) -> None:
        self.__writer = None

    @property
    def _writer(self) -> Optional["asyncio.Task[None]"]:
        return self.__writer

    @_writer.setter
    def _writer(self, writer: Optional["asyncio.Task[None]"]) -> None:
        if self.__writer is not None:
            self.__writer.remove_done_callback(self.__reset_writer)
        self.__writer = writer
        if writer is None:
            return
        if writer.done():
            # The writer is already done, so we can reset it immediately.
            self.__reset_writer()
        else:
            writer.add_done_callback(self.__reset_writer)

    @reify
    def url(self) -> URL:
        return self._url

    @reify
    def url_obj(self) -> URL:
        warnings.warn("Deprecated, use .url #1654", DeprecationWarning, stacklevel=2)
        return self._url

    @reify
    def real_url(self) -> URL:
        return self._real_url

    @reify
    def host(self) -> str:
        assert self._url.host is not None
        return self._url.host

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

    @reify
    def raw_headers(self) -> RawHeaders:
        return self._raw_headers

    @reify
    def request_info(self) -> RequestInfo:
        return self._request_info

    @reify
    def content_disposition(self) -> Optional[ContentDisposition]:
        raw = self._headers.get(hdrs.CONTENT_DISPOSITION)
        if raw is None:
            return None
        disposition_type, params_dct = multipart.parse_content_disposition(raw)
        params = MappingProxyType(params_dct)
        filename = multipart.content_disposition_filename(params)
        return ContentDisposition(disposition_type, params, filename)

    def __del__(self, _warnings: Any = warnings) -> None:
        if self._closed:
            return

        if self._connection is not None:
            self._connection.release()
            self._cleanup_writer()

            if self._loop.get_debug():
                kwargs = {"source": self}
                _warnings.warn(f"Unclosed response {self!r}", ResourceWarning, **kwargs)
                context = {"client_response": self, "message": "Unclosed response"}
                if self._source_traceback:
                    context["source_traceback"] = self._source_traceback
                self._loop.call_exception_handler(context)

    def __repr__(self) -> str:
        out = io.StringIO()
        ascii_encodable_url = str(self.url)
        if self.reason:
            ascii_encodable_reason = self.reason.encode(
                "ascii", "backslashreplace"
            ).decode("ascii")
        else:
            ascii_encodable_reason = "None"
        print(
            "<ClientResponse({}) [{} {}]>".format(
                ascii_encodable_url, self.status, ascii_encodable_reason
            ),
            file=out,
        )
        print(self.headers, file=out)
        return out.getvalue()

    @property
    def connection(self) -> Optional["Connection"]:
        return self._connection

    @reify
    def history(self) -> Tuple["ClientResponse", ...]:
        """A sequence of of responses, if redirects occurred."""
        return self._history

    @reify
    def links(self) -> "MultiDictProxy[MultiDictProxy[Union[str, URL]]]":
        links_str = ", ".join(self.headers.getall("link", []))

        if not links_str:
            return MultiDictProxy(MultiDict())

        links: MultiDict[MultiDictProxy[Union[str, URL]]] = MultiDict()

        for val in re.split(r",(?=\s*<)", links_str):
            match = re.match(r"\s*<(.*)>(.*)", val)
            if match is None:  # pragma: no cover
                # the check exists to suppress mypy error
                continue
            url, params_str = match.groups()
            params = params_str.split(";")[1:]

            link: MultiDict[Union[str, URL]] = MultiDict()

            for param in params:
                match = re.match(r"^\s*(\S*)\s*=\s*(['\"]?)(.*?)(\2)\s*$", param, re.M)
                if match is None:  # pragma: no cover
                    # the check exists to suppress mypy error
                    continue
                key, _, value, _ = match.groups()

                link.add(key, value)

            key = link.get("rel", url)

            link.add("url", self.url.join(URL(url)))

            links.add(str(key), MultiDictProxy(link))

        return MultiDictProxy(links)

    async def start(self, connection: "Connection") -> "ClientResponse":
        """Start response processing."""
        self._closed = False
        self._protocol = connection.protocol
        self._connection = connection

        with self._timer:
            while True:
                # read response
                try:
                    protocol = self._protocol
                    message, payload = await protocol.read()  # type: ignore[union-attr]
                except http.HttpProcessingError as exc:
                    raise ClientResponseError(
                        self.request_info,
                        self.history,
                        status=exc.code,
                        message=exc.message,
                        headers=exc.headers,
                    ) from exc

                if message.code < 100 or message.code > 199 or message.code == 101:
                    break

                if self._continue is not None:
                    set_result(self._continue, True)
                    self._continue = None

        # payload eof handler
        payload.on_eof(self._response_eof)

        # response status
        self.version = message.version
        self.status = message.code
        self.reason = message.reason

        # headers
        self._headers = message.headers  # type is CIMultiDictProxy
        self._raw_headers = message.raw_headers  # type is Tuple[bytes, bytes]

        # payload
        self.content = payload

        # cookies
        for hdr in self.headers.getall(hdrs.SET_COOKIE, ()):
            try:
                self.cookies.load(hdr)
            except CookieError as exc:
                client_logger.warning("Can not load response cookies: %s", exc)
        return self

    def _response_eof(self) -> None:
        if self._closed:
            return

        # protocol could be None because connection could be detached
        protocol = self._connection and self._connection.protocol
        if protocol is not None and protocol.upgraded:
            return

        self._closed = True
        self._cleanup_writer()
        self._release_connection()

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

    def close(self) -> None:
        if not self._released:
            self._notify_content()

        self._closed = True
        if self._loop is None or self._loop.is_closed():
            return

        self._cleanup_writer()
        if self._connection is not None:
            self._connection.close()
            self._connection = None

    def release(self) -> Any:
        if not self._released:
            self._notify_content()

        self._closed = True

        self._cleanup_writer()
        self._release_connection()
        return noop()

    @property
    def ok(self) -> bool:
        """Returns ``True`` if ``status`` is less than ``400``, ``False`` if not.

        This is **not** a check for ``200 OK`` but a check that the response
        status is under 400.
        """
        return 400 > self.status

    def raise_for_status(self) -> None:
        if not self.ok:
            # reason should always be not None for a started response
            assert self.reason is not None
            self.release()
            raise ClientResponseError(
                self.request_info,
                self.history,
                status=self.status,
                message=self.reason,
                headers=self.headers,
            )

    def _release_connection(self) -> None:
        if self._connection is not None:
            if self._writer is None:
                self._connection.release()
                self._connection = None
            else:
                self._writer.add_done_callback(lambda f: self._release_connection())

    async def _wait_released(self) -> None:
        if self._writer is not None:
            await self._writer
        self._release_connection()

    def _cleanup_writer(self) -> None:
        if self._writer is not None:
            self._writer.cancel()
        self._session = None

    def _notify_content(self) -> None:
        content = self.content
        if content and content.exception() is None:
            set_exception(content, ClientConnectionError("Connection closed"))
        self._released = True

    async def wait_for_close(self) -> None:
        if self._writer is not None:
            await self._writer
        self.release()

    async def read(self) -> bytes:
        """Read response payload."""
        if self._body is None:
            try:
                self._body = await self.content.read()
                for trace in self._traces:
                    await trace.send_response_chunk_received(
                        self.method, self.url, self._body
                    )
            except BaseException:
                self.close()
                raise
        elif self._released:  # Response explicitly released
            raise ClientConnectionError("Connection closed")

        protocol = self._connection and self._connection.protocol
        if protocol is None or not protocol.upgraded:
            await self._wait_released()  # Underlying connection released
        return self._body  # type: ignore[no-any-return]

    def get_encoding(self) -> str:
        ctype = self.headers.get(hdrs.CONTENT_TYPE, "").lower()
        mimetype = helpers.parse_mimetype(ctype)

        encoding = mimetype.parameters.get("charset")
        if encoding:
            with contextlib.suppress(LookupError):
                return codecs.lookup(encoding).name

        if mimetype.type == "application" and (
            mimetype.subtype == "json" or mimetype.subtype == "rdap"
        ):
            # RFC 7159 states that the default encoding is UTF-8.
            # RFC 7483 defines application/rdap+json
            return "utf-8"

        if self._body is None:
            raise RuntimeError(
                "Cannot compute fallback encoding of a not yet read body"
            )

        return self._resolve_charset(self, self._body)

    async def text(self, encoding: Optional[str] = None, errors: str = "strict") -> str:
        """Read response payload and decode."""
        if self._body is None:
            await self.read()

        if encoding is None:
            encoding = self.get_encoding()

        return self._body.decode(  # type: ignore[no-any-return,union-attr]
            encoding, errors=errors
        )

    async def json(
        self,
        *,
        encoding: Optional[str] = None,
        loads: JSONDecoder = DEFAULT_JSON_DECODER,
        content_type: Optional[str] = "application/json",
    ) -> Any:
        """Read and decodes JSON response."""
        if self._body is None:
            await self.read()

        if content_type:
            ctype = self.headers.get(hdrs.CONTENT_TYPE, "").lower()
            if not _is_expected_content_type(ctype, content_type):
                raise ContentTypeError(
                    self.request_info,
                    self.history,
                    status=self.status,
                    message=(
                        "Attempt to decode JSON with " "unexpected mimetype: %s" % ctype
                    ),
                    headers=self.headers,
                )

        stripped = self._body.strip()  # type: ignore[union-attr]
        if not stripped:
            return None

        if encoding is None:
            encoding = self.get_encoding()

        return loads(stripped.decode(encoding))

    async def __aenter__(self) -> "ClientResponse":
        return self

    async def __aexit__(
        self,
        exc_type: Optional[Type[BaseException]],
        exc_val: Optional[BaseException],
        exc_tb: Optional[TracebackType],
    ) -> None:
        # similar to _RequestContextManager, we do not need to check
        # for exceptions, response object can close connection
        # if state is broken
        self.release()
        await self.wait_for_close()

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