{
    "file_diffs": [
        {
            "old_file_content": "",
            "new_file_content": "Fixed proxy headers being used in the ``ConnectionKey`` hash when a proxy was not being used -- by :user:`bdraco`.\n\nIf default headers are used, they are also used for proxy headers. This could have led to creating connections that were not needed when one was already available.\n",
            "header": {
                "file": {
                    "path": "CHANGES/9368.bugfix.rst"
                },
                "misc_line": "new file mode 100644"
            },
            "index_line": {
                "old_commit_hash": "00000000",
                "new_commit_hash": "7a9d8c70",
                "mode": ""
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "/dev/null"
            },
            "plus_file": {
                "path": "b/CHANGES/9368.bugfix.rst"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 0,
                            "length": 0
                        },
                        "new_range": {
                            "start": 1,
                            "length": 3
                        },
                        "section": ""
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "Fixed proxy headers being used in the ``ConnectionKey`` hash when a proxy was not being used -- by :user:`bdraco`.",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "If default headers are used, they are also used for proxy headers. This could have led to creating connections that were not needed when one was already available.",
                                "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, __version__ as yarl_version\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    Query,\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_YARL_SUPPORTS_HOST_SUBCOMPONENT = tuple(map(int, yarl_version.split(\".\")[:2])) >= (\n    1,\n    13,\n)\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: Query = 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: Union[str, bool, None] = 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            url = url.extend_query(params)\n        self.original_url = url\n        self.url = url.with_fragment(None) if url.raw_fragment else url\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(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        if url.raw_user or url.raw_password:\n            self.auth = helpers.BasicAuth(url.user or \"\", url.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        # Build the host header\n        if _YARL_SUPPORTS_HOST_SUBCOMPONENT:\n            host = self.url.host_subcomponent\n            # host_subcomponent is None when the URL is a relative URL.\n            # but we know we do not have a relative URL here.\n            assert host is not None\n        else:\n            host = cast(str, self.url.raw_host)\n            if helpers.is_ipv6_address(host):\n                host = f\"[{host}]\"\n\n        if host[-1] == \".\":\n            # Remove all trailing dots from the netloc as while\n            # they are valid FQDNs in DNS, TLS validation fails.\n            # See https://github.com/aio-libs/aiohttp/issues/3636.\n            # To avoid string manipulation we only call rstrip if\n            # the last character is a dot.\n            host = host.rstrip(\".\")\n\n        # If explicit port is not None, it means that the port was\n        # explicitly specified in the URL. In this case we check\n        # if its not the default port for the scheme and add it to\n        # the host header. We check explicit_port first because\n        # yarl caches explicit_port and its likely to already be\n        # in the cache and non-default port URLs are far less common.\n        explicit_port = self.url.explicit_port\n        if explicit_port is not None and not self.url.is_default_port():\n            host = f\"{host}:{explicit_port}\"\n\n        self.headers[hdrs.HOST] = host\n\n        if not headers:\n            return\n\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 not data:\n            # Don't compress an empty body.\n            self.compress = None\n            return\n\n        if self.headers.get(hdrs.CONTENT_ENCODING):\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 (\n            hdrs.EXPECT in self.headers\n            and self.headers[hdrs.EXPECT].lower() == \"100-continue\"\n        ):\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            await writer.drain()\n            await self._continue\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            raise\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            if _YARL_SUPPORTS_HOST_SUBCOMPONENT:\n                connect_host = self.url.host_subcomponent\n                assert connect_host is not None\n            else:\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_qs\n\n        protocol = conn.protocol\n        assert protocol is not None\n        writer = StreamWriter(\n            protocol,\n            self.loop,\n            on_chunk_sent=(\n                functools.partial(self._on_chunk_request_sent, self.method, self.url)\n                if self._traces\n                else None\n            ),\n            on_headers_sent=(\n                functools.partial(self._on_headers_request_sent, self.method, self.url)\n                if self._traces\n                else None\n            ),\n        )\n\n        if self.compress:\n            writer.enable_compression(self.compress)  # type: ignore[arg-type]\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=task,\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            try:\n                await self.__writer\n            except asyncio.CancelledError:\n                if (\n                    sys.version_info >= (3, 11)\n                    and (task := asyncio.current_task())\n                    and task.cancelling()\n                ):\n                    raise\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    _in_context = 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) if url.raw_fragment else url\n        self._body: Optional[bytes] = None\n        self._writer = 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        \"\"\"The writer task for streaming data.\n\n        _writer is only provided for backwards compatibility\n        for subclasses that may need to access it.\n        \"\"\"\n        return self.__writer\n\n    @_writer.setter\n    def _writer(self, writer: Optional[\"asyncio.Task[None]\"]) -> None:\n        \"\"\"Set the writer task for streaming data.\"\"\"\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\n            # If we're in a context we can rely on __aexit__() to release as the\n            # exception propagates.\n            if not self._in_context:\n                self.release()\n\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            try:\n                await self.__writer\n            except asyncio.CancelledError:\n                if (\n                    sys.version_info >= (3, 11)\n                    and (task := asyncio.current_task())\n                    and task.cancelling()\n                ):\n                    raise\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            try:\n                await self.__writer\n            except asyncio.CancelledError:\n                if (\n                    sys.version_info >= (3, 11)\n                    and (task := asyncio.current_task())\n                    and task.cancelling()\n                ):\n                    raise\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\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, ValueError):\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(encoding, errors=errors)  # type: ignore[union-attr]\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        self._in_context = True\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        self._in_context = False\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, __version__ as yarl_version\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    Query,\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_YARL_SUPPORTS_HOST_SUBCOMPONENT = tuple(map(int, yarl_version.split(\".\")[:2])) >= (\n    1,\n    13,\n)\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: Query = 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: Union[str, bool, None] = 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            url = url.extend_query(params)\n        self.original_url = url\n        self.url = url.with_fragment(None) if url.raw_fragment else url\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(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        if url.raw_user or url.raw_password:\n            self.auth = helpers.BasicAuth(url.user or \"\", url.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        # Build the host header\n        if _YARL_SUPPORTS_HOST_SUBCOMPONENT:\n            host = self.url.host_subcomponent\n            # host_subcomponent is None when the URL is a relative URL.\n            # but we know we do not have a relative URL here.\n            assert host is not None\n        else:\n            host = cast(str, self.url.raw_host)\n            if helpers.is_ipv6_address(host):\n                host = f\"[{host}]\"\n\n        if host[-1] == \".\":\n            # Remove all trailing dots from the netloc as while\n            # they are valid FQDNs in DNS, TLS validation fails.\n            # See https://github.com/aio-libs/aiohttp/issues/3636.\n            # To avoid string manipulation we only call rstrip if\n            # the last character is a dot.\n            host = host.rstrip(\".\")\n\n        # If explicit port is not None, it means that the port was\n        # explicitly specified in the URL. In this case we check\n        # if its not the default port for the scheme and add it to\n        # the host header. We check explicit_port first because\n        # yarl caches explicit_port and its likely to already be\n        # in the cache and non-default port URLs are far less common.\n        explicit_port = self.url.explicit_port\n        if explicit_port is not None and not self.url.is_default_port():\n            host = f\"{host}:{explicit_port}\"\n\n        self.headers[hdrs.HOST] = host\n\n        if not headers:\n            return\n\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 not data:\n            # Don't compress an empty body.\n            self.compress = None\n            return\n\n        if self.headers.get(hdrs.CONTENT_ENCODING):\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 (\n            hdrs.EXPECT in self.headers\n            and self.headers[hdrs.EXPECT].lower() == \"100-continue\"\n        ):\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        self.proxy = proxy\n        if proxy is None:\n            self.proxy_auth = None\n            self.proxy_headers = None\n            return\n\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_auth = proxy_auth\n\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            await writer.drain()\n            await self._continue\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            raise\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            if _YARL_SUPPORTS_HOST_SUBCOMPONENT:\n                connect_host = self.url.host_subcomponent\n                assert connect_host is not None\n            else:\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_qs\n\n        protocol = conn.protocol\n        assert protocol is not None\n        writer = StreamWriter(\n            protocol,\n            self.loop,\n            on_chunk_sent=(\n                functools.partial(self._on_chunk_request_sent, self.method, self.url)\n                if self._traces\n                else None\n            ),\n            on_headers_sent=(\n                functools.partial(self._on_headers_request_sent, self.method, self.url)\n                if self._traces\n                else None\n            ),\n        )\n\n        if self.compress:\n            writer.enable_compression(self.compress)  # type: ignore[arg-type]\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=task,\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            try:\n                await self.__writer\n            except asyncio.CancelledError:\n                if (\n                    sys.version_info >= (3, 11)\n                    and (task := asyncio.current_task())\n                    and task.cancelling()\n                ):\n                    raise\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    _in_context = 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) if url.raw_fragment else url\n        self._body: Optional[bytes] = None\n        self._writer = 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        \"\"\"The writer task for streaming data.\n\n        _writer is only provided for backwards compatibility\n        for subclasses that may need to access it.\n        \"\"\"\n        return self.__writer\n\n    @_writer.setter\n    def _writer(self, writer: Optional[\"asyncio.Task[None]\"]) -> None:\n        \"\"\"Set the writer task for streaming data.\"\"\"\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\n            # If we're in a context we can rely on __aexit__() to release as the\n            # exception propagates.\n            if not self._in_context:\n                self.release()\n\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            try:\n                await self.__writer\n            except asyncio.CancelledError:\n                if (\n                    sys.version_info >= (3, 11)\n                    and (task := asyncio.current_task())\n                    and task.cancelling()\n                ):\n                    raise\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            try:\n                await self.__writer\n            except asyncio.CancelledError:\n                if (\n                    sys.version_info >= (3, 11)\n                    and (task := asyncio.current_task())\n                    and task.cancelling()\n                ):\n                    raise\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\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, ValueError):\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(encoding, errors=errors)  # type: ignore[union-attr]\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        self._in_context = True\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        self._in_context = False\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": "3648e9cb",
                "new_commit_hash": "6ebc6969",
                "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": 626,
                            "length": 10
                        },
                        "new_range": {
                            "start": 626,
                            "length": 16
                        },
                        "section": "class ClientRequest:"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        proxy_auth: Optional[BasicAuth],",
                                "type": "context"
                            },
                            {
                                "content": "        proxy_headers: Optional[LooseHeaders],",
                                "type": "context"
                            },
                            {
                                "content": "    ) -> None:",
                                "type": "context"
                            },
                            {
                                "content": "        self.proxy = proxy",
                                "type": "added"
                            },
                            {
                                "content": "        if proxy is None:",
                                "type": "added"
                            },
                            {
                                "content": "            self.proxy_auth = None",
                                "type": "added"
                            },
                            {
                                "content": "            self.proxy_headers = None",
                                "type": "added"
                            },
                            {
                                "content": "            return",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "        if proxy_auth and not isinstance(proxy_auth, helpers.BasicAuth):",
                                "type": "context"
                            },
                            {
                                "content": "            raise ValueError(\"proxy_auth must be None or BasicAuth() tuple\")",
                                "type": "context"
                            },
                            {
                                "content": "        self.proxy = proxy",
                                "type": "deleted"
                            },
                            {
                                "content": "        self.proxy_auth = proxy_auth",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "        if proxy_headers is not None and not isinstance(",
                                "type": "context"
                            },
                            {
                                "content": "            proxy_headers, (MultiDict, MultiDictProxy)",
                                "type": "context"
                            },
                            {
                                "content": "        ):",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "aiohttp/client_reqrep.py",
                            "type": "method",
                            "name": "ClientRequest.update_proxy",
                            "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: Query = 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: Union[str, bool, None] = 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            url = url.extend_query(params)\n        self.original_url = url\n        self.url = url.with_fragment(None) if url.raw_fragment else url\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(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        if url.raw_user or url.raw_password:\n            self.auth = helpers.BasicAuth(url.user or \"\", url.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        # Build the host header\n        if _YARL_SUPPORTS_HOST_SUBCOMPONENT:\n            host = self.url.host_subcomponent\n            # host_subcomponent is None when the URL is a relative URL.\n            # but we know we do not have a relative URL here.\n            assert host is not None\n        else:\n            host = cast(str, self.url.raw_host)\n            if helpers.is_ipv6_address(host):\n                host = f\"[{host}]\"\n\n        if host[-1] == \".\":\n            # Remove all trailing dots from the netloc as while\n            # they are valid FQDNs in DNS, TLS validation fails.\n            # See https://github.com/aio-libs/aiohttp/issues/3636.\n            # To avoid string manipulation we only call rstrip if\n            # the last character is a dot.\n            host = host.rstrip(\".\")\n\n        # If explicit port is not None, it means that the port was\n        # explicitly specified in the URL. In this case we check\n        # if its not the default port for the scheme and add it to\n        # the host header. We check explicit_port first because\n        # yarl caches explicit_port and its likely to already be\n        # in the cache and non-default port URLs are far less common.\n        explicit_port = self.url.explicit_port\n        if explicit_port is not None and not self.url.is_default_port():\n            host = f\"{host}:{explicit_port}\"\n\n        self.headers[hdrs.HOST] = host\n\n        if not headers:\n            return\n\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 not data:\n            # Don't compress an empty body.\n            self.compress = None\n            return\n\n        if self.headers.get(hdrs.CONTENT_ENCODING):\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 (\n            hdrs.EXPECT in self.headers\n            and self.headers[hdrs.EXPECT].lower() == \"100-continue\"\n        ):\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            await writer.drain()\n            await self._continue\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            raise\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            if _YARL_SUPPORTS_HOST_SUBCOMPONENT:\n                connect_host = self.url.host_subcomponent\n                assert connect_host is not None\n            else:\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_qs\n\n        protocol = conn.protocol\n        assert protocol is not None\n        writer = StreamWriter(\n            protocol,\n            self.loop,\n            on_chunk_sent=(\n                functools.partial(self._on_chunk_request_sent, self.method, self.url)\n                if self._traces\n                else None\n            ),\n            on_headers_sent=(\n                functools.partial(self._on_headers_request_sent, self.method, self.url)\n                if self._traces\n                else None\n            ),\n        )\n\n        if self.compress:\n            writer.enable_compression(self.compress)  # type: ignore[arg-type]\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=task,\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            try:\n                await self.__writer\n            except asyncio.CancelledError:\n                if (\n                    sys.version_info >= (3, 11)\n                    and (task := asyncio.current_task())\n                    and task.cancelling()\n                ):\n                    raise\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": 623,
                            "end_lineno": 637,
                            "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: Query = 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: Union[str, bool, None] = 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            url = url.extend_query(params)\n        self.original_url = url\n        self.url = url.with_fragment(None) if url.raw_fragment else url\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(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        if url.raw_user or url.raw_password:\n            self.auth = helpers.BasicAuth(url.user or \"\", url.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        # Build the host header\n        if _YARL_SUPPORTS_HOST_SUBCOMPONENT:\n            host = self.url.host_subcomponent\n            # host_subcomponent is None when the URL is a relative URL.\n            # but we know we do not have a relative URL here.\n            assert host is not None\n        else:\n            host = cast(str, self.url.raw_host)\n            if helpers.is_ipv6_address(host):\n                host = f\"[{host}]\"\n\n        if host[-1] == \".\":\n            # Remove all trailing dots from the netloc as while\n            # they are valid FQDNs in DNS, TLS validation fails.\n            # See https://github.com/aio-libs/aiohttp/issues/3636.\n            # To avoid string manipulation we only call rstrip if\n            # the last character is a dot.\n            host = host.rstrip(\".\")\n\n        # If explicit port is not None, it means that the port was\n        # explicitly specified in the URL. In this case we check\n        # if its not the default port for the scheme and add it to\n        # the host header. We check explicit_port first because\n        # yarl caches explicit_port and its likely to already be\n        # in the cache and non-default port URLs are far less common.\n        explicit_port = self.url.explicit_port\n        if explicit_port is not None and not self.url.is_default_port():\n            host = f\"{host}:{explicit_port}\"\n\n        self.headers[hdrs.HOST] = host\n\n        if not headers:\n            return\n\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 not data:\n            # Don't compress an empty body.\n            self.compress = None\n            return\n\n        if self.headers.get(hdrs.CONTENT_ENCODING):\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 (\n            hdrs.EXPECT in self.headers\n            and self.headers[hdrs.EXPECT].lower() == \"100-continue\"\n        ):\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            await writer.drain()\n            await self._continue\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            raise\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            if _YARL_SUPPORTS_HOST_SUBCOMPONENT:\n                connect_host = self.url.host_subcomponent\n                assert connect_host is not None\n            else:\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_qs\n\n        protocol = conn.protocol\n        assert protocol is not None\n        writer = StreamWriter(\n            protocol,\n            self.loop,\n            on_chunk_sent=(\n                functools.partial(self._on_chunk_request_sent, self.method, self.url)\n                if self._traces\n                else None\n            ),\n            on_headers_sent=(\n                functools.partial(self._on_headers_request_sent, self.method, self.url)\n                if self._traces\n                else None\n            ),\n        )\n\n        if self.compress:\n            writer.enable_compression(self.compress)  # type: ignore[arg-type]\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=task,\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            try:\n                await self.__writer\n            except asyncio.CancelledError:\n                if (\n                    sys.version_info >= (3, 11)\n                    and (task := asyncio.current_task())\n                    and task.cancelling()\n                ):\n                    raise\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": 238,
                                "end_lineno": 823,
                                "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: Query = 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: Union[str, bool, None] = 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            url = url.extend_query(params)\n        self.original_url = url\n        self.url = url.with_fragment(None) if url.raw_fragment else url\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(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        if url.raw_user or url.raw_password:\n            self.auth = helpers.BasicAuth(url.user or \"\", url.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        # Build the host header\n        if _YARL_SUPPORTS_HOST_SUBCOMPONENT:\n            host = self.url.host_subcomponent\n            # host_subcomponent is None when the URL is a relative URL.\n            # but we know we do not have a relative URL here.\n            assert host is not None\n        else:\n            host = cast(str, self.url.raw_host)\n            if helpers.is_ipv6_address(host):\n                host = f\"[{host}]\"\n\n        if host[-1] == \".\":\n            # Remove all trailing dots from the netloc as while\n            # they are valid FQDNs in DNS, TLS validation fails.\n            # See https://github.com/aio-libs/aiohttp/issues/3636.\n            # To avoid string manipulation we only call rstrip if\n            # the last character is a dot.\n            host = host.rstrip(\".\")\n\n        # If explicit port is not None, it means that the port was\n        # explicitly specified in the URL. In this case we check\n        # if its not the default port for the scheme and add it to\n        # the host header. We check explicit_port first because\n        # yarl caches explicit_port and its likely to already be\n        # in the cache and non-default port URLs are far less common.\n        explicit_port = self.url.explicit_port\n        if explicit_port is not None and not self.url.is_default_port():\n            host = f\"{host}:{explicit_port}\"\n\n        self.headers[hdrs.HOST] = host\n\n        if not headers:\n            return\n\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 not data:\n            # Don't compress an empty body.\n            self.compress = None\n            return\n\n        if self.headers.get(hdrs.CONTENT_ENCODING):\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 (\n            hdrs.EXPECT in self.headers\n            and self.headers[hdrs.EXPECT].lower() == \"100-continue\"\n        ):\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            await writer.drain()\n            await self._continue\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            raise\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            if _YARL_SUPPORTS_HOST_SUBCOMPONENT:\n                connect_host = self.url.host_subcomponent\n                assert connect_host is not None\n            else:\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_qs\n\n        protocol = conn.protocol\n        assert protocol is not None\n        writer = StreamWriter(\n            protocol,\n            self.loop,\n            on_chunk_sent=(\n                functools.partial(self._on_chunk_request_sent, self.method, self.url)\n                if self._traces\n                else None\n            ),\n            on_headers_sent=(\n                functools.partial(self._on_headers_request_sent, self.method, self.url)\n                if self._traces\n                else None\n            ),\n        )\n\n        if self.compress:\n            writer.enable_compression(self.compress)  # type: ignore[arg-type]\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=task,\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            try:\n                await self.__writer\n            except asyncio.CancelledError:\n                if (\n                    sys.version_info >= (3, 11)\n                    and (task := asyncio.current_task())\n                    and task.cancelling()\n                ):\n                    raise\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": 238,
                            "end_lineno": 823,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "import asyncio\nimport hashlib\nimport io\nimport pathlib\nimport sys\nimport urllib.parse\nimport zlib\nfrom http.cookies import BaseCookie, Morsel, SimpleCookie\nfrom typing import Any, Callable, Dict, Optional\nfrom unittest import mock\n\nimport pytest\nfrom multidict import CIMultiDict, CIMultiDictProxy, istr\nfrom yarl import URL\n\nimport aiohttp\nfrom aiohttp import BaseConnector, client_reqrep, hdrs, helpers, payload\nfrom aiohttp.client_exceptions import ClientConnectionError\nfrom aiohttp.client_reqrep import (\n    ClientRequest,\n    ClientResponse,\n    Fingerprint,\n    _gen_default_accept_encoding,\n    _merge_ssl_params,\n)\nfrom aiohttp.http import HttpVersion\nfrom aiohttp.test_utils import make_mocked_coro\n\n\nclass WriterMock(mock.AsyncMock):\n    def __await__(self) -> None:\n        return self().__await__()\n\n    def add_done_callback(self, cb: Callable[[], None]) -> None:\n        \"\"\"Dummy method.\"\"\"\n\n    def remove_done_callback(self, cb: Callable[[], None]) -> None:\n        \"\"\"Dummy method.\"\"\"\n\n\n@pytest.fixture\ndef make_request(loop):\n    request = None\n\n    def maker(method, url, *args, **kwargs):\n        nonlocal request\n        request = ClientRequest(method, URL(url), *args, loop=loop, **kwargs)\n        return request\n\n    yield maker\n    if request is not None:\n        loop.run_until_complete(request.close())\n\n\n@pytest.fixture\ndef buf():\n    return bytearray()\n\n\n@pytest.fixture\ndef protocol(loop, transport):\n    protocol = mock.Mock()\n    protocol.transport = transport\n    protocol._drain_helper.return_value = loop.create_future()\n    protocol._drain_helper.return_value.set_result(None)\n    return protocol\n\n\n@pytest.fixture\ndef transport(buf):\n    transport = mock.Mock()\n\n    def write(chunk):\n        buf.extend(chunk)\n\n    async def write_eof():\n        pass\n\n    transport.write.side_effect = write\n    transport.write_eof.side_effect = write_eof\n    transport.is_closing.return_value = False\n\n    return transport\n\n\n@pytest.fixture\ndef conn(transport, protocol):\n    return mock.Mock(transport=transport, protocol=protocol)\n\n\ndef test_method1(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org/\")\n    assert req.method == \"GET\"\n\n\ndef test_method2(make_request) -> None:\n    req = make_request(\"head\", \"http://python.org/\")\n    assert req.method == \"HEAD\"\n\n\ndef test_method3(make_request) -> None:\n    req = make_request(\"HEAD\", \"http://python.org/\")\n    assert req.method == \"HEAD\"\n\n\ndef test_method_invalid(make_request) -> None:\n    with pytest.raises(ValueError, match=\"Method cannot contain non-token characters\"):\n        make_request(\"METHOD WITH\\nWHITESPACES\", \"http://python.org/\")\n\n\ndef test_version_1_0(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org/\", version=\"1.0\")\n    assert req.version == (1, 0)\n\n\ndef test_version_default(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org/\")\n    assert req.version == (1, 1)\n\n\ndef test_request_info(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org/\")\n    assert req.request_info == aiohttp.RequestInfo(\n        URL(\"http://python.org/\"), \"GET\", req.headers\n    )\n\n\ndef test_request_info_with_fragment(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org/#urlfragment\")\n    assert req.request_info == aiohttp.RequestInfo(\n        URL(\"http://python.org/\"),\n        \"GET\",\n        req.headers,\n        URL(\"http://python.org/#urlfragment\"),\n    )\n\n\ndef test_version_err(make_request) -> None:\n    with pytest.raises(ValueError):\n        make_request(\"get\", \"http://python.org/\", version=\"1.c\")\n\n\ndef test_keep_alive(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org/\", version=(0, 9))\n    assert not req.keep_alive()\n\n    req = make_request(\"get\", \"http://python.org/\", version=(1, 0))\n    assert not req.keep_alive()\n\n    req = make_request(\n        \"get\",\n        \"http://python.org/\",\n        version=(1, 0),\n        headers={\"connection\": \"keep-alive\"},\n    )\n    assert req.keep_alive()\n\n    req = make_request(\"get\", \"http://python.org/\", version=(1, 1))\n    assert req.keep_alive()\n\n    req = make_request(\n        \"get\", \"http://python.org/\", version=(1, 1), headers={\"connection\": \"close\"}\n    )\n    assert not req.keep_alive()\n\n\ndef test_host_port_default_http(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org/\")\n    assert req.host == \"python.org\"\n    assert req.port == 80\n    assert not req.is_ssl()\n\n\ndef test_host_port_default_https(make_request) -> None:\n    req = make_request(\"get\", \"https://python.org/\")\n    assert req.host == \"python.org\"\n    assert req.port == 443\n    assert req.is_ssl()\n\n\ndef test_host_port_nondefault_http(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org:960/\")\n    assert req.host == \"python.org\"\n    assert req.port == 960\n    assert not req.is_ssl()\n\n\ndef test_host_port_nondefault_https(make_request) -> None:\n    req = make_request(\"get\", \"https://python.org:960/\")\n    assert req.host == \"python.org\"\n    assert req.port == 960\n    assert req.is_ssl()\n\n\ndef test_host_port_default_ws(make_request) -> None:\n    req = make_request(\"get\", \"ws://python.org/\")\n    assert req.host == \"python.org\"\n    assert req.port == 80\n    assert not req.is_ssl()\n\n\ndef test_host_port_default_wss(make_request) -> None:\n    req = make_request(\"get\", \"wss://python.org/\")\n    assert req.host == \"python.org\"\n    assert req.port == 443\n    assert req.is_ssl()\n\n\ndef test_host_port_nondefault_ws(make_request) -> None:\n    req = make_request(\"get\", \"ws://python.org:960/\")\n    assert req.host == \"python.org\"\n    assert req.port == 960\n    assert not req.is_ssl()\n\n\ndef test_host_port_nondefault_wss(make_request) -> None:\n    req = make_request(\"get\", \"wss://python.org:960/\")\n    assert req.host == \"python.org\"\n    assert req.port == 960\n    assert req.is_ssl()\n\n\ndef test_host_port_none_port(make_request) -> None:\n    req = make_request(\"get\", \"unix://localhost/path\")\n    assert req.headers[\"Host\"] == \"localhost\"\n\n\ndef test_host_port_err(make_request) -> None:\n    with pytest.raises(ValueError):\n        make_request(\"get\", \"http://python.org:123e/\")\n\n\ndef test_hostname_err(make_request) -> None:\n    with pytest.raises(ValueError):\n        make_request(\"get\", \"http://:8080/\")\n\n\ndef test_host_header_host_first(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org/\")\n    assert list(req.headers)[0] == \"Host\"\n\n\ndef test_host_header_host_without_port(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org/\")\n    assert req.headers[\"HOST\"] == \"python.org\"\n\n\ndef test_host_header_host_with_default_port(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org:80/\")\n    assert req.headers[\"HOST\"] == \"python.org\"\n\n\ndef test_host_header_host_with_nondefault_port(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org:99/\")\n    assert req.headers[\"HOST\"] == \"python.org:99\"\n\n\ndef test_host_header_host_idna_encode(make_request) -> None:\n    req = make_request(\"get\", \"http://xn--9caa.com\")\n    assert req.headers[\"HOST\"] == \"xn--9caa.com\"\n\n\ndef test_host_header_host_unicode(make_request) -> None:\n    req = make_request(\"get\", \"http://éé.com\")\n    assert req.headers[\"HOST\"] == \"xn--9caa.com\"\n\n\ndef test_host_header_explicit_host(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org/\", headers={\"host\": \"example.com\"})\n    assert req.headers[\"HOST\"] == \"example.com\"\n\n\ndef test_host_header_explicit_host_with_port(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org/\", headers={\"host\": \"example.com:99\"})\n    assert req.headers[\"HOST\"] == \"example.com:99\"\n\n\ndef test_host_header_ipv4(make_request) -> None:\n    req = make_request(\"get\", \"http://127.0.0.2\")\n    assert req.headers[\"HOST\"] == \"127.0.0.2\"\n\n\n@pytest.mark.parametrize(\"yarl_supports_host_subcomponent\", [True, False])\ndef test_host_header_ipv6(make_request, yarl_supports_host_subcomponent: bool) -> None:\n    # Ensure the old path is tested for old yarl versions\n    with mock.patch.object(\n        client_reqrep,\n        \"_YARL_SUPPORTS_HOST_SUBCOMPONENT\",\n        yarl_supports_host_subcomponent,\n    ):\n        req = make_request(\"get\", \"http://[::2]\")\n        assert req.headers[\"HOST\"] == \"[::2]\"\n\n\ndef test_host_header_ipv4_with_port(make_request) -> None:\n    req = make_request(\"get\", \"http://127.0.0.2:99\")\n    assert req.headers[\"HOST\"] == \"127.0.0.2:99\"\n\n\ndef test_host_header_ipv6_with_port(make_request) -> None:\n    req = make_request(\"get\", \"http://[::2]:99\")\n    assert req.headers[\"HOST\"] == \"[::2]:99\"\n\n\ndef test_default_loop(loop) -> None:\n    asyncio.set_event_loop(loop)\n    req = ClientRequest(\"get\", URL(\"http://python.org/\"))\n    assert req.loop is loop\n    loop.run_until_complete(req.close())\n\n\n@pytest.mark.parametrize(\n    (\"url\", \"headers\", \"expected\"),\n    (\n        pytest.param(\"http://localhost.\", None, \"localhost\", id=\"dot only at the end\"),\n        pytest.param(\"http://python.org.\", None, \"python.org\", id=\"single dot\"),\n        pytest.param(\n            \"http://python.org.:99\", None, \"python.org:99\", id=\"single dot with port\"\n        ),\n        pytest.param(\n            \"http://python.org...:99\",\n            None,\n            \"python.org:99\",\n            id=\"multiple dots with port\",\n        ),\n        pytest.param(\n            \"http://python.org.:99\",\n            {\"host\": \"example.com.:99\"},\n            \"example.com.:99\",\n            id=\"explicit host header\",\n        ),\n        pytest.param(\"https://python.org.\", None, \"python.org\", id=\"https\"),\n        pytest.param(\"https://...\", None, \"\", id=\"only dots\"),\n        pytest.param(\n            \"http://príklad.example.org.:99\",\n            None,\n            \"xn--prklad-4va.example.org:99\",\n            id=\"single dot with port idna\",\n        ),\n    ),\n)\ndef test_host_header_fqdn(\n    make_request: Any, url: str, headers: Dict[str, str], expected: str\n) -> None:\n    req = make_request(\"get\", url, headers=headers)\n    assert req.headers[\"HOST\"] == expected\n\n\ndef test_default_headers_useragent(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org/\")\n\n    assert \"SERVER\" not in req.headers\n    assert \"USER-AGENT\" in req.headers\n\n\ndef test_default_headers_useragent_custom(make_request) -> None:\n    req = make_request(\n        \"get\", \"http://python.org/\", headers={\"user-agent\": \"my custom agent\"}\n    )\n\n    assert \"USER-Agent\" in req.headers\n    assert \"my custom agent\" == req.headers[\"User-Agent\"]\n\n\ndef test_skip_default_useragent_header(make_request) -> None:\n    req = make_request(\n        \"get\", \"http://python.org/\", skip_auto_headers={istr(\"user-agent\")}\n    )\n\n    assert \"User-Agent\" not in req.headers\n\n\ndef test_headers(make_request) -> None:\n    req = make_request(\n        \"post\", \"http://python.org/\", headers={\"Content-Type\": \"text/plain\"}\n    )\n\n    assert \"CONTENT-TYPE\" in req.headers\n    assert req.headers[\"CONTENT-TYPE\"] == \"text/plain\"\n    assert req.headers[\"ACCEPT-ENCODING\"] == \"gzip, deflate, br\"\n\n\ndef test_headers_list(make_request) -> None:\n    req = make_request(\n        \"post\", \"http://python.org/\", headers=[(\"Content-Type\", \"text/plain\")]\n    )\n    assert \"CONTENT-TYPE\" in req.headers\n    assert req.headers[\"CONTENT-TYPE\"] == \"text/plain\"\n\n\ndef test_headers_default(make_request) -> None:\n    req = make_request(\n        \"get\", \"http://python.org/\", headers={\"ACCEPT-ENCODING\": \"deflate\"}\n    )\n    assert req.headers[\"ACCEPT-ENCODING\"] == \"deflate\"\n\n\ndef test_invalid_url(make_request) -> None:\n    with pytest.raises(aiohttp.InvalidURL):\n        make_request(\"get\", \"hiwpefhipowhefopw\")\n\n\ndef test_no_path(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org\")\n    assert \"/\" == req.url.path\n\n\ndef test_ipv6_default_http_port(make_request) -> None:\n    req = make_request(\"get\", \"http://[2001:db8::1]/\")\n    assert req.host == \"2001:db8::1\"\n    assert req.port == 80\n    assert not req.is_ssl()\n\n\ndef test_ipv6_default_https_port(make_request) -> None:\n    req = make_request(\"get\", \"https://[2001:db8::1]/\")\n    assert req.host == \"2001:db8::1\"\n    assert req.port == 443\n    assert req.is_ssl()\n\n\ndef test_ipv6_nondefault_http_port(make_request) -> None:\n    req = make_request(\"get\", \"http://[2001:db8::1]:960/\")\n    assert req.host == \"2001:db8::1\"\n    assert req.port == 960\n    assert not req.is_ssl()\n\n\ndef test_ipv6_nondefault_https_port(make_request) -> None:\n    req = make_request(\"get\", \"https://[2001:db8::1]:960/\")\n    assert req.host == \"2001:db8::1\"\n    assert req.port == 960\n    assert req.is_ssl()\n\n\ndef test_basic_auth(make_request) -> None:\n    req = make_request(\n        \"get\", \"http://python.org\", auth=aiohttp.BasicAuth(\"nkim\", \"1234\")\n    )\n    assert \"AUTHORIZATION\" in req.headers\n    assert \"Basic bmtpbToxMjM0\" == req.headers[\"AUTHORIZATION\"]\n\n\ndef test_basic_auth_utf8(make_request) -> None:\n    req = make_request(\n        \"get\", \"http://python.org\", auth=aiohttp.BasicAuth(\"nkim\", \"секрет\", \"utf-8\")\n    )\n    assert \"AUTHORIZATION\" in req.headers\n    assert \"Basic bmtpbTrRgdC10LrRgNC10YI=\" == req.headers[\"AUTHORIZATION\"]\n\n\ndef test_basic_auth_tuple_forbidden(make_request) -> None:\n    with pytest.raises(TypeError):\n        make_request(\"get\", \"http://python.org\", auth=(\"nkim\", \"1234\"))\n\n\ndef test_basic_auth_from_url(make_request) -> None:\n    req = make_request(\"get\", \"http://nkim:1234@python.org\")\n    assert \"AUTHORIZATION\" in req.headers\n    assert \"Basic bmtpbToxMjM0\" == req.headers[\"AUTHORIZATION\"]\n    assert \"python.org\" == req.host\n\n\ndef test_basic_auth_no_user_from_url(make_request) -> None:\n    req = make_request(\"get\", \"http://:1234@python.org\")\n    assert \"AUTHORIZATION\" in req.headers\n    assert \"Basic OjEyMzQ=\" == req.headers[\"AUTHORIZATION\"]\n    assert \"python.org\" == req.host\n\n\ndef test_basic_auth_from_url_overridden(make_request) -> None:\n    req = make_request(\n        \"get\", \"http://garbage@python.org\", auth=aiohttp.BasicAuth(\"nkim\", \"1234\")\n    )\n    assert \"AUTHORIZATION\" in req.headers\n    assert \"Basic bmtpbToxMjM0\" == req.headers[\"AUTHORIZATION\"]\n    assert \"python.org\" == req.host\n\n\ndef test_path_is_not_double_encoded1(make_request) -> None:\n    req = make_request(\"get\", \"http://0.0.0.0/get/test case\")\n    assert req.url.raw_path == \"/get/test%20case\"\n\n\ndef test_path_is_not_double_encoded2(make_request) -> None:\n    req = make_request(\"get\", \"http://0.0.0.0/get/test%2fcase\")\n    assert req.url.raw_path == \"/get/test%2Fcase\"\n\n\ndef test_path_is_not_double_encoded3(make_request) -> None:\n    req = make_request(\"get\", \"http://0.0.0.0/get/test%20case\")\n    assert req.url.raw_path == \"/get/test%20case\"\n\n\ndef test_path_safe_chars_preserved(make_request) -> None:\n    req = make_request(\"get\", \"http://0.0.0.0/get/:=+/%2B/\")\n    assert req.url.path == \"/get/:=+/+/\"\n\n\ndef test_params_are_added_before_fragment1(make_request) -> None:\n    req = make_request(\"GET\", \"http://example.com/path#fragment\", params={\"a\": \"b\"})\n    assert str(req.url) == \"http://example.com/path?a=b\"\n\n\ndef test_params_are_added_before_fragment2(make_request) -> None:\n    req = make_request(\n        \"GET\", \"http://example.com/path?key=value#fragment\", params={\"a\": \"b\"}\n    )\n    assert str(req.url) == \"http://example.com/path?key=value&a=b\"\n\n\ndef test_path_not_contain_fragment1(make_request) -> None:\n    req = make_request(\"GET\", \"http://example.com/path#fragment\")\n    assert req.url.path == \"/path\"\n\n\ndef test_path_not_contain_fragment2(make_request) -> None:\n    req = make_request(\"GET\", \"http://example.com/path?key=value#fragment\")\n    assert str(req.url) == \"http://example.com/path?key=value\"\n\n\ndef test_cookies(make_request) -> None:\n    req = make_request(\"get\", \"http://test.com/path\", cookies={\"cookie1\": \"val1\"})\n\n    assert \"COOKIE\" in req.headers\n    assert \"cookie1=val1\" == req.headers[\"COOKIE\"]\n\n\ndef test_cookies_is_quoted_with_special_characters(make_request) -> None:\n    req = make_request(\"get\", \"http://test.com/path\", cookies={\"cookie1\": \"val/one\"})\n\n    assert \"COOKIE\" in req.headers\n    assert 'cookie1=\"val/one\"' == req.headers[\"COOKIE\"]\n\n\ndef test_cookies_merge_with_headers(make_request) -> None:\n    req = make_request(\n        \"get\",\n        \"http://test.com/path\",\n        headers={\"cookie\": \"cookie1=val1\"},\n        cookies={\"cookie2\": \"val2\"},\n    )\n\n    assert \"cookie1=val1; cookie2=val2\" == req.headers[\"COOKIE\"]\n\n\ndef test_unicode_get1(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org\", params={\"foo\": \"f\\xf8\\xf8\"})\n    assert \"http://python.org/?foo=f%C3%B8%C3%B8\" == str(req.url)\n\n\ndef test_unicode_get2(make_request) -> None:\n    req = make_request(\"\", \"http://python.org\", params={\"f\\xf8\\xf8\": \"f\\xf8\\xf8\"})\n\n    assert \"http://python.org/?f%C3%B8%C3%B8=f%C3%B8%C3%B8\" == str(req.url)\n\n\ndef test_unicode_get3(make_request) -> None:\n    req = make_request(\"\", \"http://python.org\", params={\"foo\": \"foo\"})\n    assert \"http://python.org/?foo=foo\" == str(req.url)\n\n\ndef test_unicode_get4(make_request) -> None:\n    def join(*suffix):\n        return urllib.parse.urljoin(\"http://python.org/\", \"/\".join(suffix))\n\n    req = make_request(\"\", join(\"\\xf8\"), params={\"foo\": \"foo\"})\n    assert \"http://python.org/%C3%B8?foo=foo\" == str(req.url)\n\n\ndef test_query_multivalued_param(make_request) -> None:\n    for meth in ClientRequest.ALL_METHODS:\n        req = make_request(\n            meth, \"http://python.org\", params=((\"test\", \"foo\"), (\"test\", \"baz\"))\n        )\n\n        assert str(req.url) == \"http://python.org/?test=foo&test=baz\"\n\n\ndef test_query_str_param(make_request) -> None:\n    for meth in ClientRequest.ALL_METHODS:\n        req = make_request(meth, \"http://python.org\", params=\"test=foo\")\n        assert str(req.url) == \"http://python.org/?test=foo\"\n\n\ndef test_query_bytes_param_raises(make_request) -> None:\n    for meth in ClientRequest.ALL_METHODS:\n        with pytest.raises(TypeError):\n            make_request(meth, \"http://python.org\", params=b\"test=foo\")\n\n\ndef test_query_str_param_is_not_encoded(make_request) -> None:\n    for meth in ClientRequest.ALL_METHODS:\n        req = make_request(meth, \"http://python.org\", params=\"test=f+oo\")\n        assert str(req.url) == \"http://python.org/?test=f+oo\"\n\n\ndef test_params_update_path_and_url(make_request) -> None:\n    req = make_request(\n        \"get\", \"http://python.org\", params=((\"test\", \"foo\"), (\"test\", \"baz\"))\n    )\n    assert str(req.url) == \"http://python.org/?test=foo&test=baz\"\n\n\ndef test_params_empty_path_and_url(make_request) -> None:\n    req_empty = make_request(\"get\", \"http://python.org\", params={})\n    assert str(req_empty.url) == \"http://python.org\"\n    req_none = make_request(\"get\", \"http://python.org\")\n    assert str(req_none.url) == \"http://python.org\"\n\n\ndef test_gen_netloc_all(make_request) -> None:\n    req = make_request(\n        \"get\",\n        \"https://aiohttp:pwpwpw@\"\n        + \"12345678901234567890123456789\"\n        + \"012345678901234567890:8080\",\n    )\n    assert (\n        req.headers[\"HOST\"]\n        == \"12345678901234567890123456789\" + \"012345678901234567890:8080\"\n    )\n\n\ndef test_gen_netloc_no_port(make_request) -> None:\n    req = make_request(\n        \"get\",\n        \"https://aiohttp:pwpwpw@\"\n        + \"12345678901234567890123456789\"\n        + \"012345678901234567890/\",\n    )\n    assert (\n        req.headers[\"HOST\"] == \"12345678901234567890123456789\" + \"012345678901234567890\"\n    )\n\n\nasync def test_connection_header(loop, conn) -> None:\n    req = ClientRequest(\"get\", URL(\"http://python.org\"), loop=loop)\n    req.keep_alive = mock.Mock()\n    req.headers.clear()\n\n    req.keep_alive.return_value = True\n    req.version = HttpVersion(1, 1)\n    req.headers.clear()\n    await req.send(conn)\n    assert req.headers.get(\"CONNECTION\") is None\n\n    req.version = HttpVersion(1, 0)\n    req.headers.clear()\n    await req.send(conn)\n    assert req.headers.get(\"CONNECTION\") == \"keep-alive\"\n\n    req.keep_alive.return_value = False\n    req.version = HttpVersion(1, 1)\n    req.headers.clear()\n    await req.send(conn)\n    assert req.headers.get(\"CONNECTION\") == \"close\"\n\n    await req.close()\n\n\nasync def test_no_content_length(loop, conn) -> None:\n    req = ClientRequest(\"get\", URL(\"http://python.org\"), loop=loop)\n    resp = await req.send(conn)\n    assert req.headers.get(\"CONTENT-LENGTH\") is None\n    await req.close()\n    resp.close()\n\n\nasync def test_no_content_length_head(loop, conn) -> None:\n    req = ClientRequest(\"head\", URL(\"http://python.org\"), loop=loop)\n    resp = await req.send(conn)\n    assert req.headers.get(\"CONTENT-LENGTH\") is None\n    await req.close()\n    resp.close()\n\n\nasync def test_content_type_auto_header_get(loop, conn) -> None:\n    req = ClientRequest(\"get\", URL(\"http://python.org\"), loop=loop)\n    resp = await req.send(conn)\n    assert \"CONTENT-TYPE\" not in req.headers\n    resp.close()\n    await req.close()\n\n\nasync def test_content_type_auto_header_form(loop, conn) -> None:\n    req = ClientRequest(\n        \"post\", URL(\"http://python.org\"), data={\"hey\": \"you\"}, loop=loop\n    )\n    resp = await req.send(conn)\n    assert \"application/x-www-form-urlencoded\" == req.headers.get(\"CONTENT-TYPE\")\n    resp.close()\n    await req.close()\n\n\nasync def test_content_type_auto_header_bytes(loop, conn) -> None:\n    req = ClientRequest(\"post\", URL(\"http://python.org\"), data=b\"hey you\", loop=loop)\n    resp = await req.send(conn)\n    assert \"application/octet-stream\" == req.headers.get(\"CONTENT-TYPE\")\n    resp.close()\n    await req.close()\n\n\nasync def test_content_type_skip_auto_header_bytes(loop, conn) -> None:\n    req = ClientRequest(\n        \"post\",\n        URL(\"http://python.org\"),\n        data=b\"hey you\",\n        skip_auto_headers={\"Content-Type\"},\n        loop=loop,\n    )\n    resp = await req.send(conn)\n    assert \"CONTENT-TYPE\" not in req.headers\n    resp.close()\n    await req.close()\n\n\nasync def test_content_type_skip_auto_header_form(loop, conn) -> None:\n    req = ClientRequest(\n        \"post\",\n        URL(\"http://python.org\"),\n        data={\"hey\": \"you\"},\n        loop=loop,\n        skip_auto_headers={\"Content-Type\"},\n    )\n    resp = await req.send(conn)\n    assert \"CONTENT-TYPE\" not in req.headers\n    resp.close()\n    await req.close()\n\n\nasync def test_content_type_auto_header_content_length_no_skip(loop, conn) -> None:\n    with io.BytesIO(b\"hey\") as file_handle:\n        req = ClientRequest(\n            \"post\",\n            URL(\"http://python.org\"),\n            data=file_handle,\n            skip_auto_headers={\"Content-Length\"},\n            loop=loop,\n        )\n        resp = await req.send(conn)\n        assert req.headers.get(\"CONTENT-LENGTH\") == \"3\"\n        resp.close()\n        await req.close()\n\n\nasync def test_urlencoded_formdata_charset(loop, conn) -> None:\n    req = ClientRequest(\n        \"post\",\n        URL(\"http://python.org\"),\n        data=aiohttp.FormData({\"hey\": \"you\"}, charset=\"koi8-r\"),\n        loop=loop,\n    )\n    await req.send(conn)\n    assert \"application/x-www-form-urlencoded; charset=koi8-r\" == req.headers.get(\n        \"CONTENT-TYPE\"\n    )\n    await req.close()\n\n\nasync def test_post_data(loop, conn) -> None:\n    for meth in ClientRequest.POST_METHODS:\n        req = ClientRequest(\n            meth, URL(\"http://python.org/\"), data={\"life\": \"42\"}, loop=loop\n        )\n        resp = await req.send(conn)\n        assert \"/\" == req.url.path\n        assert b\"life=42\" == req.body._value\n        assert \"application/x-www-form-urlencoded\" == req.headers[\"CONTENT-TYPE\"]\n        await req.close()\n        resp.close()\n\n\nasync def test_pass_falsy_data(loop) -> None:\n    with mock.patch(\"aiohttp.client_reqrep.ClientRequest.update_body_from_data\"):\n        req = ClientRequest(\"post\", URL(\"http://python.org/\"), data={}, loop=loop)\n        req.update_body_from_data.assert_called_once_with({})\n    await req.close()\n\n\nasync def test_pass_falsy_data_file(loop, tmp_path) -> None:\n    testfile = (tmp_path / \"tmpfile\").open(\"w+b\")\n    testfile.write(b\"data\")\n    testfile.seek(0)\n    skip = frozenset([hdrs.CONTENT_TYPE])\n    req = ClientRequest(\n        \"post\",\n        URL(\"http://python.org/\"),\n        data=testfile,\n        skip_auto_headers=skip,\n        loop=loop,\n    )\n    assert req.headers.get(\"CONTENT-LENGTH\", None) is not None\n    await req.close()\n    testfile.close()\n\n\n# Elasticsearch API requires to send request body with GET-requests\nasync def test_get_with_data(loop) -> None:\n    for meth in ClientRequest.GET_METHODS:\n        req = ClientRequest(\n            meth, URL(\"http://python.org/\"), data={\"life\": \"42\"}, loop=loop\n        )\n        assert \"/\" == req.url.path\n        assert b\"life=42\" == req.body._value\n        await req.close()\n\n\nasync def test_bytes_data(loop, conn) -> None:\n    for meth in ClientRequest.POST_METHODS:\n        req = ClientRequest(\n            meth, URL(\"http://python.org/\"), data=b\"binary data\", loop=loop\n        )\n        resp = await req.send(conn)\n        assert \"/\" == req.url.path\n        assert isinstance(req.body, payload.BytesPayload)\n        assert b\"binary data\" == req.body._value\n        assert \"application/octet-stream\" == req.headers[\"CONTENT-TYPE\"]\n        await req.close()\n        resp.close()\n\n\nasync def test_content_encoding(loop, conn) -> None:\n    req = ClientRequest(\n        \"post\", URL(\"http://python.org/\"), data=\"foo\", compress=\"deflate\", loop=loop\n    )\n    with mock.patch(\"aiohttp.client_reqrep.StreamWriter\") as m_writer:\n        m_writer.return_value.write_headers = make_mocked_coro()\n        resp = await req.send(conn)\n    assert req.headers[\"TRANSFER-ENCODING\"] == \"chunked\"\n    assert req.headers[\"CONTENT-ENCODING\"] == \"deflate\"\n    m_writer.return_value.enable_compression.assert_called_with(\"deflate\")\n    await req.close()\n    resp.close()\n\n\nasync def test_content_encoding_dont_set_headers_if_no_body(loop, conn) -> None:\n    req = ClientRequest(\n        \"post\", URL(\"http://python.org/\"), compress=\"deflate\", loop=loop\n    )\n    with mock.patch(\"aiohttp.client_reqrep.http\"):\n        resp = await req.send(conn)\n    assert \"TRANSFER-ENCODING\" not in req.headers\n    assert \"CONTENT-ENCODING\" not in req.headers\n    await req.close()\n    resp.close()\n\n\nasync def test_content_encoding_header(loop, conn) -> None:\n    req = ClientRequest(\n        \"post\",\n        URL(\"http://python.org/\"),\n        data=\"foo\",\n        headers={\"Content-Encoding\": \"deflate\"},\n        loop=loop,\n    )\n    with mock.patch(\"aiohttp.client_reqrep.StreamWriter\") as m_writer:\n        m_writer.return_value.write_headers = make_mocked_coro()\n        resp = await req.send(conn)\n\n    assert not m_writer.return_value.enable_compression.called\n    assert not m_writer.return_value.enable_chunking.called\n    await req.close()\n    resp.close()\n\n\nasync def test_compress_and_content_encoding(loop, conn) -> None:\n    with pytest.raises(ValueError):\n        ClientRequest(\n            \"post\",\n            URL(\"http://python.org/\"),\n            data=\"foo\",\n            headers={\"content-encoding\": \"deflate\"},\n            compress=\"deflate\",\n            loop=loop,\n        )\n\n\nasync def test_chunked(loop, conn) -> None:\n    req = ClientRequest(\n        \"post\",\n        URL(\"http://python.org/\"),\n        headers={\"TRANSFER-ENCODING\": \"gzip\"},\n        loop=loop,\n    )\n    resp = await req.send(conn)\n    assert \"gzip\" == req.headers[\"TRANSFER-ENCODING\"]\n    await req.close()\n    resp.close()\n\n\nasync def test_chunked2(loop, conn) -> None:\n    req = ClientRequest(\n        \"post\",\n        URL(\"http://python.org/\"),\n        headers={\"Transfer-encoding\": \"chunked\"},\n        loop=loop,\n    )\n    resp = await req.send(conn)\n    assert \"chunked\" == req.headers[\"TRANSFER-ENCODING\"]\n    await req.close()\n    resp.close()\n\n\nasync def test_chunked_explicit(loop, conn) -> None:\n    req = ClientRequest(\"post\", URL(\"http://python.org/\"), chunked=True, loop=loop)\n    with mock.patch(\"aiohttp.client_reqrep.StreamWriter\") as m_writer:\n        m_writer.return_value.write_headers = make_mocked_coro()\n        resp = await req.send(conn)\n\n    assert \"chunked\" == req.headers[\"TRANSFER-ENCODING\"]\n    m_writer.return_value.enable_chunking.assert_called_with()\n    await req.close()\n    resp.close()\n\n\nasync def test_chunked_length(loop, conn) -> None:\n    with pytest.raises(ValueError):\n        ClientRequest(\n            \"post\",\n            URL(\"http://python.org/\"),\n            headers={\"CONTENT-LENGTH\": \"1000\"},\n            chunked=True,\n            loop=loop,\n        )\n\n\nasync def test_chunked_transfer_encoding(loop, conn) -> None:\n    with pytest.raises(ValueError):\n        ClientRequest(\n            \"post\",\n            URL(\"http://python.org/\"),\n            headers={\"TRANSFER-ENCODING\": \"chunked\"},\n            chunked=True,\n            loop=loop,\n        )\n\n\nasync def test_file_upload_not_chunked(loop) -> None:\n    file_path = pathlib.Path(__file__).parent / \"aiohttp.png\"\n    with file_path.open(\"rb\") as f:\n        req = ClientRequest(\"post\", URL(\"http://python.org/\"), data=f, loop=loop)\n        assert not req.chunked\n        assert req.headers[\"CONTENT-LENGTH\"] == str(file_path.stat().st_size)\n        await req.close()\n\n\nasync def test_precompressed_data_stays_intact(loop) -> None:\n    data = zlib.compress(b\"foobar\")\n    req = ClientRequest(\n        \"post\",\n        URL(\"http://python.org/\"),\n        data=data,\n        headers={\"CONTENT-ENCODING\": \"deflate\"},\n        compress=False,\n        loop=loop,\n    )\n    assert not req.compress\n    assert not req.chunked\n    assert req.headers[\"CONTENT-ENCODING\"] == \"deflate\"\n    await req.close()\n\n\nasync def test_file_upload_not_chunked_seek(loop) -> None:\n    file_path = pathlib.Path(__file__).parent / \"aiohttp.png\"\n    with file_path.open(\"rb\") as f:\n        f.seek(100)\n        req = ClientRequest(\"post\", URL(\"http://python.org/\"), data=f, loop=loop)\n        assert req.headers[\"CONTENT-LENGTH\"] == str(file_path.stat().st_size - 100)\n        await req.close()\n\n\nasync def test_file_upload_force_chunked(loop) -> None:\n    file_path = pathlib.Path(__file__).parent / \"aiohttp.png\"\n    with file_path.open(\"rb\") as f:\n        req = ClientRequest(\n            \"post\", URL(\"http://python.org/\"), data=f, chunked=True, loop=loop\n        )\n        assert req.chunked\n        assert \"CONTENT-LENGTH\" not in req.headers\n        await req.close()\n\n\nasync def test_expect100(loop, conn) -> None:\n    req = ClientRequest(\"get\", URL(\"http://python.org/\"), expect100=True, loop=loop)\n    resp = await req.send(conn)\n    assert \"100-continue\" == req.headers[\"EXPECT\"]\n    assert req._continue is not None\n    req.terminate()\n    resp.close()\n    await req.close()\n\n\nasync def test_expect_100_continue_header(loop, conn) -> None:\n    req = ClientRequest(\n        \"get\", URL(\"http://python.org/\"), headers={\"expect\": \"100-continue\"}, loop=loop\n    )\n    resp = await req.send(conn)\n    assert \"100-continue\" == req.headers[\"EXPECT\"]\n    assert req._continue is not None\n    req.terminate()\n    resp.close()\n    await req.close()\n\n\nasync def test_data_stream(loop, buf, conn) -> None:\n    async def gen():\n        yield b\"binary data\"\n        yield b\" result\"\n\n    req = ClientRequest(\"POST\", URL(\"http://python.org/\"), data=gen(), loop=loop)\n    assert req.chunked\n    assert req.headers[\"TRANSFER-ENCODING\"] == \"chunked\"\n    original_write_bytes = req.write_bytes\n\n    async def _mock_write_bytes(*args, **kwargs):\n        # Ensure the task is scheduled\n        await asyncio.sleep(0)\n        return await original_write_bytes(*args, **kwargs)\n\n    with mock.patch.object(req, \"write_bytes\", _mock_write_bytes):\n        resp = await req.send(conn)\n    assert asyncio.isfuture(req._writer)\n    await resp.wait_for_close()\n    assert req._writer is None\n    assert (\n        buf.split(b\"\\r\\n\\r\\n\", 1)[1] == b\"b\\r\\nbinary data\\r\\n7\\r\\n result\\r\\n0\\r\\n\\r\\n\"\n    )\n    await req.close()\n\n\nasync def test_data_stream_deprecated(loop, buf, conn) -> None:\n    with pytest.warns(DeprecationWarning):\n\n        @aiohttp.streamer\n        async def gen(writer):\n            await writer.write(b\"binary data\")\n            await writer.write(b\" result\")\n\n    req = ClientRequest(\"POST\", URL(\"http://python.org/\"), data=gen(), loop=loop)\n    assert req.chunked\n    assert req.headers[\"TRANSFER-ENCODING\"] == \"chunked\"\n\n    resp = await req.send(conn)\n    await resp.wait_for_close()\n    assert (\n        buf.split(b\"\\r\\n\\r\\n\", 1)[1] == b\"b\\r\\nbinary data\\r\\n7\\r\\n result\\r\\n0\\r\\n\\r\\n\"\n    )\n    await req.close()\n\n\nasync def test_data_file(loop, buf, conn) -> None:\n    with io.BufferedReader(io.BytesIO(b\"*\" * 2)) as file_handle:\n        req = ClientRequest(\n            \"POST\",\n            URL(\"http://python.org/\"),\n            data=file_handle,\n            loop=loop,\n        )\n        assert req.chunked\n        assert isinstance(req.body, payload.BufferedReaderPayload)\n        assert req.headers[\"TRANSFER-ENCODING\"] == \"chunked\"\n\n        resp = await req.send(conn)\n        assert asyncio.isfuture(req._writer)\n        await resp.wait_for_close()\n\n        assert req._writer is None\n        assert buf.split(b\"\\r\\n\\r\\n\", 1)[1] == b\"2\\r\\n\" + b\"*\" * 2 + b\"\\r\\n0\\r\\n\\r\\n\"\n        await req.close()\n\n\nasync def test_data_stream_exc(loop, conn) -> None:\n    fut = loop.create_future()\n\n    async def gen():\n        yield b\"binary data\"\n        await fut\n\n    req = ClientRequest(\"POST\", URL(\"http://python.org/\"), data=gen(), loop=loop)\n    assert req.chunked\n    assert req.headers[\"TRANSFER-ENCODING\"] == \"chunked\"\n\n    async def throw_exc():\n        await asyncio.sleep(0.01)\n        fut.set_exception(ValueError)\n\n    loop.create_task(throw_exc())\n\n    await req.send(conn)\n    await req._writer\n    # assert conn.close.called\n    assert conn.protocol.set_exception.called\n    await req.close()\n\n\nasync def test_data_stream_exc_chain(loop, conn) -> None:\n    fut = loop.create_future()\n\n    async def gen():\n        await fut\n        return\n        yield\n\n    req = ClientRequest(\"POST\", URL(\"http://python.org/\"), data=gen(), loop=loop)\n\n    inner_exc = ValueError()\n\n    async def throw_exc():\n        await asyncio.sleep(0.01)\n        fut.set_exception(inner_exc)\n\n    loop.create_task(throw_exc())\n\n    await req.send(conn)\n    await req._writer\n    # assert connection.close.called\n    assert conn.protocol.set_exception.called\n    outer_exc = conn.protocol.set_exception.call_args[0][0]\n    assert isinstance(outer_exc, ClientConnectionError)\n    assert outer_exc.__cause__ is inner_exc\n    await req.close()\n\n\nasync def test_data_stream_continue(loop, buf, conn) -> None:\n    async def gen():\n        yield b\"binary data\"\n        yield b\" result\"\n\n    req = ClientRequest(\n        \"POST\", URL(\"http://python.org/\"), data=gen(), expect100=True, loop=loop\n    )\n    assert req.chunked\n\n    async def coro():\n        await asyncio.sleep(0.0001)\n        req._continue.set_result(1)\n\n    loop.create_task(coro())\n\n    resp = await req.send(conn)\n    await req._writer\n    assert (\n        buf.split(b\"\\r\\n\\r\\n\", 1)[1] == b\"b\\r\\nbinary data\\r\\n7\\r\\n result\\r\\n0\\r\\n\\r\\n\"\n    )\n    await req.close()\n    resp.close()\n\n\nasync def test_data_continue(loop, buf, conn) -> None:\n    req = ClientRequest(\n        \"POST\", URL(\"http://python.org/\"), data=b\"data\", expect100=True, loop=loop\n    )\n\n    async def coro():\n        await asyncio.sleep(0.0001)\n        req._continue.set_result(1)\n\n    loop.create_task(coro())\n\n    resp = await req.send(conn)\n\n    await req._writer\n    assert buf.split(b\"\\r\\n\\r\\n\", 1)[1] == b\"data\"\n    await req.close()\n    resp.close()\n\n\nasync def test_close(loop, buf, conn) -> None:\n    async def gen():\n        await asyncio.sleep(0.00001)\n        yield b\"result\"\n\n    req = ClientRequest(\"POST\", URL(\"http://python.org/\"), data=gen(), loop=loop)\n    resp = await req.send(conn)\n    await req.close()\n    assert buf.split(b\"\\r\\n\\r\\n\", 1)[1] == b\"6\\r\\nresult\\r\\n0\\r\\n\\r\\n\"\n    await req.close()\n    resp.close()\n\n\nasync def test_bad_version(loop, conn) -> None:\n    req = ClientRequest(\n        \"GET\",\n        URL(\"http://python.org\"),\n        loop=loop,\n        headers={\"Connection\": \"Close\"},\n        version=(\"1\", \"1\\r\\nInjected-Header: not allowed\"),\n    )\n\n    with pytest.raises(AttributeError):\n        await req.send(conn)\n\n\nasync def test_custom_response_class(loop, conn) -> None:\n    class CustomResponse(ClientResponse):\n        def read(self, decode=False):\n            return \"customized!\"\n\n    req = ClientRequest(\n        \"GET\", URL(\"http://python.org/\"), response_class=CustomResponse, loop=loop\n    )\n    resp = await req.send(conn)\n    assert \"customized!\" == resp.read()\n    await req.close()\n    resp.close()\n\n\nasync def test_oserror_on_write_bytes(loop, conn) -> None:\n    req = ClientRequest(\"POST\", URL(\"http://python.org/\"), loop=loop)\n\n    writer = WriterMock()\n    writer.write.side_effect = OSError\n\n    await req.write_bytes(writer, conn)\n\n    assert conn.protocol.set_exception.called\n    exc = conn.protocol.set_exception.call_args[0][0]\n    assert isinstance(exc, aiohttp.ClientOSError)\n\n    await req.close()\n\n\n@pytest.mark.skipif(sys.version_info < (3, 11), reason=\"Needs Task.cancelling()\")\nasync def test_cancel_close(loop: asyncio.AbstractEventLoop, conn: mock.Mock) -> None:\n    req = ClientRequest(\"get\", URL(\"http://python.org\"), loop=loop)\n    req._writer = asyncio.Future()  # type: ignore[assignment]\n\n    t = asyncio.create_task(req.close())\n\n    # Start waiting on _writer\n    await asyncio.sleep(0)\n\n    t.cancel()\n    # Cancellation should not be suppressed.\n    with pytest.raises(asyncio.CancelledError):\n        await t\n\n\nasync def test_terminate(loop: asyncio.AbstractEventLoop, conn: mock.Mock) -> None:\n    req = ClientRequest(\"get\", URL(\"http://python.org\"), loop=loop)\n\n    async def _mock_write_bytes(*args, **kwargs):\n        # Ensure the task is scheduled\n        await asyncio.sleep(0)\n\n    with mock.patch.object(req, \"write_bytes\", _mock_write_bytes):\n        resp = await req.send(conn)\n\n    assert req._writer is not None\n    assert resp._writer is not None\n    await resp._writer\n    writer = WriterMock()\n    writer.done = mock.Mock(return_value=False)\n    writer.cancel = mock.Mock()\n    req._writer = writer\n    resp._writer = writer\n\n    assert req._writer is not None\n    assert resp._writer is not None\n    req.terminate()\n    writer.cancel.assert_called_with()\n    writer.done.assert_called_with()\n    resp.close()\n\n    await req.close()\n\n\ndef test_terminate_with_closed_loop(loop, conn) -> None:\n    req = resp = writer = None\n\n    async def go():\n        nonlocal req, resp, writer\n        req = ClientRequest(\"get\", URL(\"http://python.org\"))\n\n        async def _mock_write_bytes(*args, **kwargs):\n            # Ensure the task is scheduled\n            await asyncio.sleep(0)\n\n        with mock.patch.object(req, \"write_bytes\", _mock_write_bytes):\n            resp = await req.send(conn)\n\n        assert req._writer is not None\n        writer = WriterMock()\n        writer.done = mock.Mock(return_value=False)\n        req._writer = writer\n        resp._writer = writer\n\n        await asyncio.sleep(0.05)\n\n    loop.run_until_complete(go())\n\n    loop.run_until_complete(req.close())\n    loop.close()\n    req.terminate()\n    assert req._writer is None\n    assert not writer.cancel.called\n    resp.close()\n\n\ndef test_terminate_without_writer(loop) -> None:\n    req = ClientRequest(\"get\", URL(\"http://python.org\"), loop=loop)\n    assert req._writer is None\n\n    req.terminate()\n    assert req._writer is None\n\n    loop.run_until_complete(req.close())\n\n\nasync def test_custom_req_rep(loop) -> None:\n    conn = None\n\n    class CustomResponse(ClientResponse):\n        async def start(self, connection, read_until_eof=False):\n            nonlocal conn\n            conn = connection\n            self.status = 123\n            self.reason = \"Test OK\"\n            self._headers = CIMultiDictProxy(CIMultiDict())\n            self.cookies = SimpleCookie()\n            return\n\n    called = False\n\n    class CustomRequest(ClientRequest):\n        async def send(self, conn):\n            resp = self.response_class(\n                self.method,\n                self.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            self.response = resp\n            nonlocal called\n            called = True\n            return resp\n\n    async def create_connection(req, traces, timeout):\n        assert isinstance(req, CustomRequest)\n        return mock.Mock()\n\n    connector = BaseConnector(loop=loop)\n    connector._create_connection = create_connection\n\n    session = aiohttp.ClientSession(\n        request_class=CustomRequest,\n        response_class=CustomResponse,\n        connector=connector,\n        loop=loop,\n    )\n\n    resp = await session.request(\"get\", URL(\"http://example.com/path/to\"))\n    assert isinstance(resp, CustomResponse)\n    assert called\n    resp.close()\n    await session.close()\n    conn.close()\n\n\ndef test_verify_ssl_false_with_ssl_context(loop, ssl_ctx) -> None:\n    with pytest.warns(DeprecationWarning):\n        with pytest.raises(ValueError):\n            _merge_ssl_params(\n                None, verify_ssl=False, ssl_context=ssl_ctx, fingerprint=None\n            )\n\n\ndef test_bad_fingerprint(loop) -> None:\n    with pytest.raises(ValueError):\n        Fingerprint(b\"invalid\")\n\n\ndef test_insecure_fingerprint_md5(loop) -> None:\n    with pytest.raises(ValueError):\n        Fingerprint(hashlib.md5(b\"foo\").digest())\n\n\ndef test_insecure_fingerprint_sha1(loop) -> None:\n    with pytest.raises(ValueError):\n        Fingerprint(hashlib.sha1(b\"foo\").digest())\n\n\ndef test_loose_cookies_types(loop) -> None:\n    req = ClientRequest(\"get\", URL(\"http://python.org\"), loop=loop)\n    morsel = Morsel()\n    morsel.set(key=\"string\", val=\"Another string\", coded_val=\"really\")\n\n    accepted_types = [\n        [(\"str\", BaseCookie())],\n        [(\"str\", morsel)],\n        [\n            (\"str\", \"str\"),\n        ],\n        {\"str\": BaseCookie()},\n        {\"str\": morsel},\n        {\"str\": \"str\"},\n        SimpleCookie(),\n    ]\n\n    for loose_cookies_type in accepted_types:\n        req.update_cookies(cookies=loose_cookies_type)\n\n    loop.run_until_complete(req.close())\n\n\n@pytest.mark.parametrize(\n    \"has_brotli,expected\",\n    [\n        (False, \"gzip, deflate\"),\n        (True, \"gzip, deflate, br\"),\n    ],\n)\ndef test_gen_default_accept_encoding(has_brotli, expected) -> None:\n    with mock.patch(\"aiohttp.client_reqrep.HAS_BROTLI\", has_brotli):\n        assert _gen_default_accept_encoding() == expected\n\n\n@pytest.mark.parametrize(\n    (\"netrc_contents\", \"expected_auth\"),\n    [\n        (\n            \"machine example.com login username password pass\\n\",\n            helpers.BasicAuth(\"username\", \"pass\"),\n        )\n    ],\n    indirect=(\"netrc_contents\",),\n)\n@pytest.mark.usefixtures(\"netrc_contents\")\ndef test_basicauth_from_netrc_present(\n    make_request: Any,\n    expected_auth: Optional[helpers.BasicAuth],\n):\n    \"\"\"Test appropriate Authorization header is sent when netrc is not empty.\"\"\"\n    req = make_request(\"get\", \"http://example.com\", trust_env=True)\n    assert req.headers[hdrs.AUTHORIZATION] == expected_auth.encode()\n\n\n@pytest.mark.parametrize(\n    \"netrc_contents\",\n    (\"machine example.com login username password pass\\n\",),\n    indirect=(\"netrc_contents\",),\n)\n@pytest.mark.usefixtures(\"netrc_contents\")\ndef test_basicauth_from_netrc_present_untrusted_env(\n    make_request: Any,\n):\n    \"\"\"Test no authorization header is sent via netrc if trust_env is False\"\"\"\n    req = make_request(\"get\", \"http://example.com\", trust_env=False)\n    assert hdrs.AUTHORIZATION not in req.headers\n\n\n@pytest.mark.parametrize(\n    \"netrc_contents\",\n    (\"\",),\n    indirect=(\"netrc_contents\",),\n)\n@pytest.mark.usefixtures(\"netrc_contents\")\ndef test_basicauth_from_empty_netrc(\n    make_request: Any,\n):\n    \"\"\"Test that no Authorization header is sent when netrc is empty\"\"\"\n    req = make_request(\"get\", \"http://example.com\", trust_env=True)\n    assert hdrs.AUTHORIZATION not in req.headers\n",
            "new_file_content": "import asyncio\nimport hashlib\nimport io\nimport pathlib\nimport sys\nimport urllib.parse\nimport zlib\nfrom http.cookies import BaseCookie, Morsel, SimpleCookie\nfrom typing import Any, Callable, Dict, Optional\nfrom unittest import mock\n\nimport pytest\nfrom multidict import CIMultiDict, CIMultiDictProxy, istr\nfrom yarl import URL\n\nimport aiohttp\nfrom aiohttp import BaseConnector, client_reqrep, hdrs, helpers, payload\nfrom aiohttp.client_exceptions import ClientConnectionError\nfrom aiohttp.client_reqrep import (\n    ClientRequest,\n    ClientResponse,\n    Fingerprint,\n    _gen_default_accept_encoding,\n    _merge_ssl_params,\n)\nfrom aiohttp.http import HttpVersion\nfrom aiohttp.test_utils import make_mocked_coro\n\n\nclass WriterMock(mock.AsyncMock):\n    def __await__(self) -> None:\n        return self().__await__()\n\n    def add_done_callback(self, cb: Callable[[], None]) -> None:\n        \"\"\"Dummy method.\"\"\"\n\n    def remove_done_callback(self, cb: Callable[[], None]) -> None:\n        \"\"\"Dummy method.\"\"\"\n\n\n@pytest.fixture\ndef make_request(loop):\n    request = None\n\n    def maker(method, url, *args, **kwargs):\n        nonlocal request\n        request = ClientRequest(method, URL(url), *args, loop=loop, **kwargs)\n        return request\n\n    yield maker\n    if request is not None:\n        loop.run_until_complete(request.close())\n\n\n@pytest.fixture\ndef buf():\n    return bytearray()\n\n\n@pytest.fixture\ndef protocol(loop, transport):\n    protocol = mock.Mock()\n    protocol.transport = transport\n    protocol._drain_helper.return_value = loop.create_future()\n    protocol._drain_helper.return_value.set_result(None)\n    return protocol\n\n\n@pytest.fixture\ndef transport(buf):\n    transport = mock.Mock()\n\n    def write(chunk):\n        buf.extend(chunk)\n\n    async def write_eof():\n        pass\n\n    transport.write.side_effect = write\n    transport.write_eof.side_effect = write_eof\n    transport.is_closing.return_value = False\n\n    return transport\n\n\n@pytest.fixture\ndef conn(transport, protocol):\n    return mock.Mock(transport=transport, protocol=protocol)\n\n\ndef test_method1(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org/\")\n    assert req.method == \"GET\"\n\n\ndef test_method2(make_request) -> None:\n    req = make_request(\"head\", \"http://python.org/\")\n    assert req.method == \"HEAD\"\n\n\ndef test_method3(make_request) -> None:\n    req = make_request(\"HEAD\", \"http://python.org/\")\n    assert req.method == \"HEAD\"\n\n\ndef test_method_invalid(make_request) -> None:\n    with pytest.raises(ValueError, match=\"Method cannot contain non-token characters\"):\n        make_request(\"METHOD WITH\\nWHITESPACES\", \"http://python.org/\")\n\n\ndef test_version_1_0(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org/\", version=\"1.0\")\n    assert req.version == (1, 0)\n\n\ndef test_version_default(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org/\")\n    assert req.version == (1, 1)\n\n\ndef test_request_info(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org/\")\n    assert req.request_info == aiohttp.RequestInfo(\n        URL(\"http://python.org/\"), \"GET\", req.headers\n    )\n\n\ndef test_request_info_with_fragment(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org/#urlfragment\")\n    assert req.request_info == aiohttp.RequestInfo(\n        URL(\"http://python.org/\"),\n        \"GET\",\n        req.headers,\n        URL(\"http://python.org/#urlfragment\"),\n    )\n\n\ndef test_version_err(make_request) -> None:\n    with pytest.raises(ValueError):\n        make_request(\"get\", \"http://python.org/\", version=\"1.c\")\n\n\ndef test_keep_alive(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org/\", version=(0, 9))\n    assert not req.keep_alive()\n\n    req = make_request(\"get\", \"http://python.org/\", version=(1, 0))\n    assert not req.keep_alive()\n\n    req = make_request(\n        \"get\",\n        \"http://python.org/\",\n        version=(1, 0),\n        headers={\"connection\": \"keep-alive\"},\n    )\n    assert req.keep_alive()\n\n    req = make_request(\"get\", \"http://python.org/\", version=(1, 1))\n    assert req.keep_alive()\n\n    req = make_request(\n        \"get\", \"http://python.org/\", version=(1, 1), headers={\"connection\": \"close\"}\n    )\n    assert not req.keep_alive()\n\n\ndef test_host_port_default_http(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org/\")\n    assert req.host == \"python.org\"\n    assert req.port == 80\n    assert not req.is_ssl()\n\n\ndef test_host_port_default_https(make_request) -> None:\n    req = make_request(\"get\", \"https://python.org/\")\n    assert req.host == \"python.org\"\n    assert req.port == 443\n    assert req.is_ssl()\n\n\ndef test_host_port_nondefault_http(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org:960/\")\n    assert req.host == \"python.org\"\n    assert req.port == 960\n    assert not req.is_ssl()\n\n\ndef test_host_port_nondefault_https(make_request) -> None:\n    req = make_request(\"get\", \"https://python.org:960/\")\n    assert req.host == \"python.org\"\n    assert req.port == 960\n    assert req.is_ssl()\n\n\ndef test_host_port_default_ws(make_request) -> None:\n    req = make_request(\"get\", \"ws://python.org/\")\n    assert req.host == \"python.org\"\n    assert req.port == 80\n    assert not req.is_ssl()\n\n\ndef test_host_port_default_wss(make_request) -> None:\n    req = make_request(\"get\", \"wss://python.org/\")\n    assert req.host == \"python.org\"\n    assert req.port == 443\n    assert req.is_ssl()\n\n\ndef test_host_port_nondefault_ws(make_request) -> None:\n    req = make_request(\"get\", \"ws://python.org:960/\")\n    assert req.host == \"python.org\"\n    assert req.port == 960\n    assert not req.is_ssl()\n\n\ndef test_host_port_nondefault_wss(make_request) -> None:\n    req = make_request(\"get\", \"wss://python.org:960/\")\n    assert req.host == \"python.org\"\n    assert req.port == 960\n    assert req.is_ssl()\n\n\ndef test_host_port_none_port(make_request) -> None:\n    req = make_request(\"get\", \"unix://localhost/path\")\n    assert req.headers[\"Host\"] == \"localhost\"\n\n\ndef test_host_port_err(make_request) -> None:\n    with pytest.raises(ValueError):\n        make_request(\"get\", \"http://python.org:123e/\")\n\n\ndef test_hostname_err(make_request) -> None:\n    with pytest.raises(ValueError):\n        make_request(\"get\", \"http://:8080/\")\n\n\ndef test_host_header_host_first(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org/\")\n    assert list(req.headers)[0] == \"Host\"\n\n\ndef test_host_header_host_without_port(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org/\")\n    assert req.headers[\"HOST\"] == \"python.org\"\n\n\ndef test_host_header_host_with_default_port(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org:80/\")\n    assert req.headers[\"HOST\"] == \"python.org\"\n\n\ndef test_host_header_host_with_nondefault_port(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org:99/\")\n    assert req.headers[\"HOST\"] == \"python.org:99\"\n\n\ndef test_host_header_host_idna_encode(make_request) -> None:\n    req = make_request(\"get\", \"http://xn--9caa.com\")\n    assert req.headers[\"HOST\"] == \"xn--9caa.com\"\n\n\ndef test_host_header_host_unicode(make_request) -> None:\n    req = make_request(\"get\", \"http://éé.com\")\n    assert req.headers[\"HOST\"] == \"xn--9caa.com\"\n\n\ndef test_host_header_explicit_host(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org/\", headers={\"host\": \"example.com\"})\n    assert req.headers[\"HOST\"] == \"example.com\"\n\n\ndef test_host_header_explicit_host_with_port(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org/\", headers={\"host\": \"example.com:99\"})\n    assert req.headers[\"HOST\"] == \"example.com:99\"\n\n\ndef test_host_header_ipv4(make_request) -> None:\n    req = make_request(\"get\", \"http://127.0.0.2\")\n    assert req.headers[\"HOST\"] == \"127.0.0.2\"\n\n\n@pytest.mark.parametrize(\"yarl_supports_host_subcomponent\", [True, False])\ndef test_host_header_ipv6(make_request, yarl_supports_host_subcomponent: bool) -> None:\n    # Ensure the old path is tested for old yarl versions\n    with mock.patch.object(\n        client_reqrep,\n        \"_YARL_SUPPORTS_HOST_SUBCOMPONENT\",\n        yarl_supports_host_subcomponent,\n    ):\n        req = make_request(\"get\", \"http://[::2]\")\n        assert req.headers[\"HOST\"] == \"[::2]\"\n\n\ndef test_host_header_ipv4_with_port(make_request) -> None:\n    req = make_request(\"get\", \"http://127.0.0.2:99\")\n    assert req.headers[\"HOST\"] == \"127.0.0.2:99\"\n\n\ndef test_host_header_ipv6_with_port(make_request) -> None:\n    req = make_request(\"get\", \"http://[::2]:99\")\n    assert req.headers[\"HOST\"] == \"[::2]:99\"\n\n\ndef test_default_loop(loop) -> None:\n    asyncio.set_event_loop(loop)\n    req = ClientRequest(\"get\", URL(\"http://python.org/\"))\n    assert req.loop is loop\n    loop.run_until_complete(req.close())\n\n\n@pytest.mark.parametrize(\n    (\"url\", \"headers\", \"expected\"),\n    (\n        pytest.param(\"http://localhost.\", None, \"localhost\", id=\"dot only at the end\"),\n        pytest.param(\"http://python.org.\", None, \"python.org\", id=\"single dot\"),\n        pytest.param(\n            \"http://python.org.:99\", None, \"python.org:99\", id=\"single dot with port\"\n        ),\n        pytest.param(\n            \"http://python.org...:99\",\n            None,\n            \"python.org:99\",\n            id=\"multiple dots with port\",\n        ),\n        pytest.param(\n            \"http://python.org.:99\",\n            {\"host\": \"example.com.:99\"},\n            \"example.com.:99\",\n            id=\"explicit host header\",\n        ),\n        pytest.param(\"https://python.org.\", None, \"python.org\", id=\"https\"),\n        pytest.param(\"https://...\", None, \"\", id=\"only dots\"),\n        pytest.param(\n            \"http://príklad.example.org.:99\",\n            None,\n            \"xn--prklad-4va.example.org:99\",\n            id=\"single dot with port idna\",\n        ),\n    ),\n)\ndef test_host_header_fqdn(\n    make_request: Any, url: str, headers: Dict[str, str], expected: str\n) -> None:\n    req = make_request(\"get\", url, headers=headers)\n    assert req.headers[\"HOST\"] == expected\n\n\ndef test_default_headers_useragent(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org/\")\n\n    assert \"SERVER\" not in req.headers\n    assert \"USER-AGENT\" in req.headers\n\n\ndef test_default_headers_useragent_custom(make_request) -> None:\n    req = make_request(\n        \"get\", \"http://python.org/\", headers={\"user-agent\": \"my custom agent\"}\n    )\n\n    assert \"USER-Agent\" in req.headers\n    assert \"my custom agent\" == req.headers[\"User-Agent\"]\n\n\ndef test_skip_default_useragent_header(make_request) -> None:\n    req = make_request(\n        \"get\", \"http://python.org/\", skip_auto_headers={istr(\"user-agent\")}\n    )\n\n    assert \"User-Agent\" not in req.headers\n\n\ndef test_headers(make_request) -> None:\n    req = make_request(\n        \"post\", \"http://python.org/\", headers={\"Content-Type\": \"text/plain\"}\n    )\n\n    assert \"CONTENT-TYPE\" in req.headers\n    assert req.headers[\"CONTENT-TYPE\"] == \"text/plain\"\n    assert req.headers[\"ACCEPT-ENCODING\"] == \"gzip, deflate, br\"\n\n\ndef test_headers_list(make_request) -> None:\n    req = make_request(\n        \"post\", \"http://python.org/\", headers=[(\"Content-Type\", \"text/plain\")]\n    )\n    assert \"CONTENT-TYPE\" in req.headers\n    assert req.headers[\"CONTENT-TYPE\"] == \"text/plain\"\n\n\ndef test_headers_default(make_request) -> None:\n    req = make_request(\n        \"get\", \"http://python.org/\", headers={\"ACCEPT-ENCODING\": \"deflate\"}\n    )\n    assert req.headers[\"ACCEPT-ENCODING\"] == \"deflate\"\n\n\ndef test_invalid_url(make_request) -> None:\n    with pytest.raises(aiohttp.InvalidURL):\n        make_request(\"get\", \"hiwpefhipowhefopw\")\n\n\ndef test_no_path(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org\")\n    assert \"/\" == req.url.path\n\n\ndef test_ipv6_default_http_port(make_request) -> None:\n    req = make_request(\"get\", \"http://[2001:db8::1]/\")\n    assert req.host == \"2001:db8::1\"\n    assert req.port == 80\n    assert not req.is_ssl()\n\n\ndef test_ipv6_default_https_port(make_request) -> None:\n    req = make_request(\"get\", \"https://[2001:db8::1]/\")\n    assert req.host == \"2001:db8::1\"\n    assert req.port == 443\n    assert req.is_ssl()\n\n\ndef test_ipv6_nondefault_http_port(make_request) -> None:\n    req = make_request(\"get\", \"http://[2001:db8::1]:960/\")\n    assert req.host == \"2001:db8::1\"\n    assert req.port == 960\n    assert not req.is_ssl()\n\n\ndef test_ipv6_nondefault_https_port(make_request) -> None:\n    req = make_request(\"get\", \"https://[2001:db8::1]:960/\")\n    assert req.host == \"2001:db8::1\"\n    assert req.port == 960\n    assert req.is_ssl()\n\n\ndef test_basic_auth(make_request) -> None:\n    req = make_request(\n        \"get\", \"http://python.org\", auth=aiohttp.BasicAuth(\"nkim\", \"1234\")\n    )\n    assert \"AUTHORIZATION\" in req.headers\n    assert \"Basic bmtpbToxMjM0\" == req.headers[\"AUTHORIZATION\"]\n\n\ndef test_basic_auth_utf8(make_request) -> None:\n    req = make_request(\n        \"get\", \"http://python.org\", auth=aiohttp.BasicAuth(\"nkim\", \"секрет\", \"utf-8\")\n    )\n    assert \"AUTHORIZATION\" in req.headers\n    assert \"Basic bmtpbTrRgdC10LrRgNC10YI=\" == req.headers[\"AUTHORIZATION\"]\n\n\ndef test_basic_auth_tuple_forbidden(make_request) -> None:\n    with pytest.raises(TypeError):\n        make_request(\"get\", \"http://python.org\", auth=(\"nkim\", \"1234\"))\n\n\ndef test_basic_auth_from_url(make_request) -> None:\n    req = make_request(\"get\", \"http://nkim:1234@python.org\")\n    assert \"AUTHORIZATION\" in req.headers\n    assert \"Basic bmtpbToxMjM0\" == req.headers[\"AUTHORIZATION\"]\n    assert \"python.org\" == req.host\n\n\ndef test_basic_auth_no_user_from_url(make_request) -> None:\n    req = make_request(\"get\", \"http://:1234@python.org\")\n    assert \"AUTHORIZATION\" in req.headers\n    assert \"Basic OjEyMzQ=\" == req.headers[\"AUTHORIZATION\"]\n    assert \"python.org\" == req.host\n\n\ndef test_basic_auth_from_url_overridden(make_request) -> None:\n    req = make_request(\n        \"get\", \"http://garbage@python.org\", auth=aiohttp.BasicAuth(\"nkim\", \"1234\")\n    )\n    assert \"AUTHORIZATION\" in req.headers\n    assert \"Basic bmtpbToxMjM0\" == req.headers[\"AUTHORIZATION\"]\n    assert \"python.org\" == req.host\n\n\ndef test_path_is_not_double_encoded1(make_request) -> None:\n    req = make_request(\"get\", \"http://0.0.0.0/get/test case\")\n    assert req.url.raw_path == \"/get/test%20case\"\n\n\ndef test_path_is_not_double_encoded2(make_request) -> None:\n    req = make_request(\"get\", \"http://0.0.0.0/get/test%2fcase\")\n    assert req.url.raw_path == \"/get/test%2Fcase\"\n\n\ndef test_path_is_not_double_encoded3(make_request) -> None:\n    req = make_request(\"get\", \"http://0.0.0.0/get/test%20case\")\n    assert req.url.raw_path == \"/get/test%20case\"\n\n\ndef test_path_safe_chars_preserved(make_request) -> None:\n    req = make_request(\"get\", \"http://0.0.0.0/get/:=+/%2B/\")\n    assert req.url.path == \"/get/:=+/+/\"\n\n\ndef test_params_are_added_before_fragment1(make_request) -> None:\n    req = make_request(\"GET\", \"http://example.com/path#fragment\", params={\"a\": \"b\"})\n    assert str(req.url) == \"http://example.com/path?a=b\"\n\n\ndef test_params_are_added_before_fragment2(make_request) -> None:\n    req = make_request(\n        \"GET\", \"http://example.com/path?key=value#fragment\", params={\"a\": \"b\"}\n    )\n    assert str(req.url) == \"http://example.com/path?key=value&a=b\"\n\n\ndef test_path_not_contain_fragment1(make_request) -> None:\n    req = make_request(\"GET\", \"http://example.com/path#fragment\")\n    assert req.url.path == \"/path\"\n\n\ndef test_path_not_contain_fragment2(make_request) -> None:\n    req = make_request(\"GET\", \"http://example.com/path?key=value#fragment\")\n    assert str(req.url) == \"http://example.com/path?key=value\"\n\n\ndef test_cookies(make_request) -> None:\n    req = make_request(\"get\", \"http://test.com/path\", cookies={\"cookie1\": \"val1\"})\n\n    assert \"COOKIE\" in req.headers\n    assert \"cookie1=val1\" == req.headers[\"COOKIE\"]\n\n\ndef test_cookies_is_quoted_with_special_characters(make_request) -> None:\n    req = make_request(\"get\", \"http://test.com/path\", cookies={\"cookie1\": \"val/one\"})\n\n    assert \"COOKIE\" in req.headers\n    assert 'cookie1=\"val/one\"' == req.headers[\"COOKIE\"]\n\n\ndef test_cookies_merge_with_headers(make_request) -> None:\n    req = make_request(\n        \"get\",\n        \"http://test.com/path\",\n        headers={\"cookie\": \"cookie1=val1\"},\n        cookies={\"cookie2\": \"val2\"},\n    )\n\n    assert \"cookie1=val1; cookie2=val2\" == req.headers[\"COOKIE\"]\n\n\ndef test_unicode_get1(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org\", params={\"foo\": \"f\\xf8\\xf8\"})\n    assert \"http://python.org/?foo=f%C3%B8%C3%B8\" == str(req.url)\n\n\ndef test_unicode_get2(make_request) -> None:\n    req = make_request(\"\", \"http://python.org\", params={\"f\\xf8\\xf8\": \"f\\xf8\\xf8\"})\n\n    assert \"http://python.org/?f%C3%B8%C3%B8=f%C3%B8%C3%B8\" == str(req.url)\n\n\ndef test_unicode_get3(make_request) -> None:\n    req = make_request(\"\", \"http://python.org\", params={\"foo\": \"foo\"})\n    assert \"http://python.org/?foo=foo\" == str(req.url)\n\n\ndef test_unicode_get4(make_request) -> None:\n    def join(*suffix):\n        return urllib.parse.urljoin(\"http://python.org/\", \"/\".join(suffix))\n\n    req = make_request(\"\", join(\"\\xf8\"), params={\"foo\": \"foo\"})\n    assert \"http://python.org/%C3%B8?foo=foo\" == str(req.url)\n\n\ndef test_query_multivalued_param(make_request) -> None:\n    for meth in ClientRequest.ALL_METHODS:\n        req = make_request(\n            meth, \"http://python.org\", params=((\"test\", \"foo\"), (\"test\", \"baz\"))\n        )\n\n        assert str(req.url) == \"http://python.org/?test=foo&test=baz\"\n\n\ndef test_query_str_param(make_request) -> None:\n    for meth in ClientRequest.ALL_METHODS:\n        req = make_request(meth, \"http://python.org\", params=\"test=foo\")\n        assert str(req.url) == \"http://python.org/?test=foo\"\n\n\ndef test_query_bytes_param_raises(make_request) -> None:\n    for meth in ClientRequest.ALL_METHODS:\n        with pytest.raises(TypeError):\n            make_request(meth, \"http://python.org\", params=b\"test=foo\")\n\n\ndef test_query_str_param_is_not_encoded(make_request) -> None:\n    for meth in ClientRequest.ALL_METHODS:\n        req = make_request(meth, \"http://python.org\", params=\"test=f+oo\")\n        assert str(req.url) == \"http://python.org/?test=f+oo\"\n\n\ndef test_params_update_path_and_url(make_request) -> None:\n    req = make_request(\n        \"get\", \"http://python.org\", params=((\"test\", \"foo\"), (\"test\", \"baz\"))\n    )\n    assert str(req.url) == \"http://python.org/?test=foo&test=baz\"\n\n\ndef test_params_empty_path_and_url(make_request) -> None:\n    req_empty = make_request(\"get\", \"http://python.org\", params={})\n    assert str(req_empty.url) == \"http://python.org\"\n    req_none = make_request(\"get\", \"http://python.org\")\n    assert str(req_none.url) == \"http://python.org\"\n\n\ndef test_gen_netloc_all(make_request) -> None:\n    req = make_request(\n        \"get\",\n        \"https://aiohttp:pwpwpw@\"\n        + \"12345678901234567890123456789\"\n        + \"012345678901234567890:8080\",\n    )\n    assert (\n        req.headers[\"HOST\"]\n        == \"12345678901234567890123456789\" + \"012345678901234567890:8080\"\n    )\n\n\ndef test_gen_netloc_no_port(make_request) -> None:\n    req = make_request(\n        \"get\",\n        \"https://aiohttp:pwpwpw@\"\n        + \"12345678901234567890123456789\"\n        + \"012345678901234567890/\",\n    )\n    assert (\n        req.headers[\"HOST\"] == \"12345678901234567890123456789\" + \"012345678901234567890\"\n    )\n\n\nasync def test_connection_header(loop, conn) -> None:\n    req = ClientRequest(\"get\", URL(\"http://python.org\"), loop=loop)\n    req.keep_alive = mock.Mock()\n    req.headers.clear()\n\n    req.keep_alive.return_value = True\n    req.version = HttpVersion(1, 1)\n    req.headers.clear()\n    await req.send(conn)\n    assert req.headers.get(\"CONNECTION\") is None\n\n    req.version = HttpVersion(1, 0)\n    req.headers.clear()\n    await req.send(conn)\n    assert req.headers.get(\"CONNECTION\") == \"keep-alive\"\n\n    req.keep_alive.return_value = False\n    req.version = HttpVersion(1, 1)\n    req.headers.clear()\n    await req.send(conn)\n    assert req.headers.get(\"CONNECTION\") == \"close\"\n\n    await req.close()\n\n\nasync def test_no_content_length(loop, conn) -> None:\n    req = ClientRequest(\"get\", URL(\"http://python.org\"), loop=loop)\n    resp = await req.send(conn)\n    assert req.headers.get(\"CONTENT-LENGTH\") is None\n    await req.close()\n    resp.close()\n\n\nasync def test_no_content_length_head(loop, conn) -> None:\n    req = ClientRequest(\"head\", URL(\"http://python.org\"), loop=loop)\n    resp = await req.send(conn)\n    assert req.headers.get(\"CONTENT-LENGTH\") is None\n    await req.close()\n    resp.close()\n\n\nasync def test_content_type_auto_header_get(loop, conn) -> None:\n    req = ClientRequest(\"get\", URL(\"http://python.org\"), loop=loop)\n    resp = await req.send(conn)\n    assert \"CONTENT-TYPE\" not in req.headers\n    resp.close()\n    await req.close()\n\n\nasync def test_content_type_auto_header_form(loop, conn) -> None:\n    req = ClientRequest(\n        \"post\", URL(\"http://python.org\"), data={\"hey\": \"you\"}, loop=loop\n    )\n    resp = await req.send(conn)\n    assert \"application/x-www-form-urlencoded\" == req.headers.get(\"CONTENT-TYPE\")\n    resp.close()\n    await req.close()\n\n\nasync def test_content_type_auto_header_bytes(loop, conn) -> None:\n    req = ClientRequest(\"post\", URL(\"http://python.org\"), data=b\"hey you\", loop=loop)\n    resp = await req.send(conn)\n    assert \"application/octet-stream\" == req.headers.get(\"CONTENT-TYPE\")\n    resp.close()\n    await req.close()\n\n\nasync def test_content_type_skip_auto_header_bytes(loop, conn) -> None:\n    req = ClientRequest(\n        \"post\",\n        URL(\"http://python.org\"),\n        data=b\"hey you\",\n        skip_auto_headers={\"Content-Type\"},\n        loop=loop,\n    )\n    resp = await req.send(conn)\n    assert \"CONTENT-TYPE\" not in req.headers\n    resp.close()\n    await req.close()\n\n\nasync def test_content_type_skip_auto_header_form(loop, conn) -> None:\n    req = ClientRequest(\n        \"post\",\n        URL(\"http://python.org\"),\n        data={\"hey\": \"you\"},\n        loop=loop,\n        skip_auto_headers={\"Content-Type\"},\n    )\n    resp = await req.send(conn)\n    assert \"CONTENT-TYPE\" not in req.headers\n    resp.close()\n    await req.close()\n\n\nasync def test_content_type_auto_header_content_length_no_skip(loop, conn) -> None:\n    with io.BytesIO(b\"hey\") as file_handle:\n        req = ClientRequest(\n            \"post\",\n            URL(\"http://python.org\"),\n            data=file_handle,\n            skip_auto_headers={\"Content-Length\"},\n            loop=loop,\n        )\n        resp = await req.send(conn)\n        assert req.headers.get(\"CONTENT-LENGTH\") == \"3\"\n        resp.close()\n        await req.close()\n\n\nasync def test_urlencoded_formdata_charset(loop, conn) -> None:\n    req = ClientRequest(\n        \"post\",\n        URL(\"http://python.org\"),\n        data=aiohttp.FormData({\"hey\": \"you\"}, charset=\"koi8-r\"),\n        loop=loop,\n    )\n    await req.send(conn)\n    assert \"application/x-www-form-urlencoded; charset=koi8-r\" == req.headers.get(\n        \"CONTENT-TYPE\"\n    )\n    await req.close()\n\n\nasync def test_post_data(loop, conn) -> None:\n    for meth in ClientRequest.POST_METHODS:\n        req = ClientRequest(\n            meth, URL(\"http://python.org/\"), data={\"life\": \"42\"}, loop=loop\n        )\n        resp = await req.send(conn)\n        assert \"/\" == req.url.path\n        assert b\"life=42\" == req.body._value\n        assert \"application/x-www-form-urlencoded\" == req.headers[\"CONTENT-TYPE\"]\n        await req.close()\n        resp.close()\n\n\nasync def test_pass_falsy_data(loop) -> None:\n    with mock.patch(\"aiohttp.client_reqrep.ClientRequest.update_body_from_data\"):\n        req = ClientRequest(\"post\", URL(\"http://python.org/\"), data={}, loop=loop)\n        req.update_body_from_data.assert_called_once_with({})\n    await req.close()\n\n\nasync def test_pass_falsy_data_file(loop, tmp_path) -> None:\n    testfile = (tmp_path / \"tmpfile\").open(\"w+b\")\n    testfile.write(b\"data\")\n    testfile.seek(0)\n    skip = frozenset([hdrs.CONTENT_TYPE])\n    req = ClientRequest(\n        \"post\",\n        URL(\"http://python.org/\"),\n        data=testfile,\n        skip_auto_headers=skip,\n        loop=loop,\n    )\n    assert req.headers.get(\"CONTENT-LENGTH\", None) is not None\n    await req.close()\n    testfile.close()\n\n\n# Elasticsearch API requires to send request body with GET-requests\nasync def test_get_with_data(loop) -> None:\n    for meth in ClientRequest.GET_METHODS:\n        req = ClientRequest(\n            meth, URL(\"http://python.org/\"), data={\"life\": \"42\"}, loop=loop\n        )\n        assert \"/\" == req.url.path\n        assert b\"life=42\" == req.body._value\n        await req.close()\n\n\nasync def test_bytes_data(loop, conn) -> None:\n    for meth in ClientRequest.POST_METHODS:\n        req = ClientRequest(\n            meth, URL(\"http://python.org/\"), data=b\"binary data\", loop=loop\n        )\n        resp = await req.send(conn)\n        assert \"/\" == req.url.path\n        assert isinstance(req.body, payload.BytesPayload)\n        assert b\"binary data\" == req.body._value\n        assert \"application/octet-stream\" == req.headers[\"CONTENT-TYPE\"]\n        await req.close()\n        resp.close()\n\n\nasync def test_content_encoding(loop, conn) -> None:\n    req = ClientRequest(\n        \"post\", URL(\"http://python.org/\"), data=\"foo\", compress=\"deflate\", loop=loop\n    )\n    with mock.patch(\"aiohttp.client_reqrep.StreamWriter\") as m_writer:\n        m_writer.return_value.write_headers = make_mocked_coro()\n        resp = await req.send(conn)\n    assert req.headers[\"TRANSFER-ENCODING\"] == \"chunked\"\n    assert req.headers[\"CONTENT-ENCODING\"] == \"deflate\"\n    m_writer.return_value.enable_compression.assert_called_with(\"deflate\")\n    await req.close()\n    resp.close()\n\n\nasync def test_content_encoding_dont_set_headers_if_no_body(loop, conn) -> None:\n    req = ClientRequest(\n        \"post\", URL(\"http://python.org/\"), compress=\"deflate\", loop=loop\n    )\n    with mock.patch(\"aiohttp.client_reqrep.http\"):\n        resp = await req.send(conn)\n    assert \"TRANSFER-ENCODING\" not in req.headers\n    assert \"CONTENT-ENCODING\" not in req.headers\n    await req.close()\n    resp.close()\n\n\nasync def test_content_encoding_header(loop, conn) -> None:\n    req = ClientRequest(\n        \"post\",\n        URL(\"http://python.org/\"),\n        data=\"foo\",\n        headers={\"Content-Encoding\": \"deflate\"},\n        loop=loop,\n    )\n    with mock.patch(\"aiohttp.client_reqrep.StreamWriter\") as m_writer:\n        m_writer.return_value.write_headers = make_mocked_coro()\n        resp = await req.send(conn)\n\n    assert not m_writer.return_value.enable_compression.called\n    assert not m_writer.return_value.enable_chunking.called\n    await req.close()\n    resp.close()\n\n\nasync def test_compress_and_content_encoding(loop, conn) -> None:\n    with pytest.raises(ValueError):\n        ClientRequest(\n            \"post\",\n            URL(\"http://python.org/\"),\n            data=\"foo\",\n            headers={\"content-encoding\": \"deflate\"},\n            compress=\"deflate\",\n            loop=loop,\n        )\n\n\nasync def test_chunked(loop, conn) -> None:\n    req = ClientRequest(\n        \"post\",\n        URL(\"http://python.org/\"),\n        headers={\"TRANSFER-ENCODING\": \"gzip\"},\n        loop=loop,\n    )\n    resp = await req.send(conn)\n    assert \"gzip\" == req.headers[\"TRANSFER-ENCODING\"]\n    await req.close()\n    resp.close()\n\n\nasync def test_chunked2(loop, conn) -> None:\n    req = ClientRequest(\n        \"post\",\n        URL(\"http://python.org/\"),\n        headers={\"Transfer-encoding\": \"chunked\"},\n        loop=loop,\n    )\n    resp = await req.send(conn)\n    assert \"chunked\" == req.headers[\"TRANSFER-ENCODING\"]\n    await req.close()\n    resp.close()\n\n\nasync def test_chunked_explicit(loop, conn) -> None:\n    req = ClientRequest(\"post\", URL(\"http://python.org/\"), chunked=True, loop=loop)\n    with mock.patch(\"aiohttp.client_reqrep.StreamWriter\") as m_writer:\n        m_writer.return_value.write_headers = make_mocked_coro()\n        resp = await req.send(conn)\n\n    assert \"chunked\" == req.headers[\"TRANSFER-ENCODING\"]\n    m_writer.return_value.enable_chunking.assert_called_with()\n    await req.close()\n    resp.close()\n\n\nasync def test_chunked_length(loop, conn) -> None:\n    with pytest.raises(ValueError):\n        ClientRequest(\n            \"post\",\n            URL(\"http://python.org/\"),\n            headers={\"CONTENT-LENGTH\": \"1000\"},\n            chunked=True,\n            loop=loop,\n        )\n\n\nasync def test_chunked_transfer_encoding(loop, conn) -> None:\n    with pytest.raises(ValueError):\n        ClientRequest(\n            \"post\",\n            URL(\"http://python.org/\"),\n            headers={\"TRANSFER-ENCODING\": \"chunked\"},\n            chunked=True,\n            loop=loop,\n        )\n\n\nasync def test_file_upload_not_chunked(loop) -> None:\n    file_path = pathlib.Path(__file__).parent / \"aiohttp.png\"\n    with file_path.open(\"rb\") as f:\n        req = ClientRequest(\"post\", URL(\"http://python.org/\"), data=f, loop=loop)\n        assert not req.chunked\n        assert req.headers[\"CONTENT-LENGTH\"] == str(file_path.stat().st_size)\n        await req.close()\n\n\nasync def test_precompressed_data_stays_intact(loop) -> None:\n    data = zlib.compress(b\"foobar\")\n    req = ClientRequest(\n        \"post\",\n        URL(\"http://python.org/\"),\n        data=data,\n        headers={\"CONTENT-ENCODING\": \"deflate\"},\n        compress=False,\n        loop=loop,\n    )\n    assert not req.compress\n    assert not req.chunked\n    assert req.headers[\"CONTENT-ENCODING\"] == \"deflate\"\n    await req.close()\n\n\nasync def test_file_upload_not_chunked_seek(loop) -> None:\n    file_path = pathlib.Path(__file__).parent / \"aiohttp.png\"\n    with file_path.open(\"rb\") as f:\n        f.seek(100)\n        req = ClientRequest(\"post\", URL(\"http://python.org/\"), data=f, loop=loop)\n        assert req.headers[\"CONTENT-LENGTH\"] == str(file_path.stat().st_size - 100)\n        await req.close()\n\n\nasync def test_file_upload_force_chunked(loop) -> None:\n    file_path = pathlib.Path(__file__).parent / \"aiohttp.png\"\n    with file_path.open(\"rb\") as f:\n        req = ClientRequest(\n            \"post\", URL(\"http://python.org/\"), data=f, chunked=True, loop=loop\n        )\n        assert req.chunked\n        assert \"CONTENT-LENGTH\" not in req.headers\n        await req.close()\n\n\nasync def test_expect100(loop, conn) -> None:\n    req = ClientRequest(\"get\", URL(\"http://python.org/\"), expect100=True, loop=loop)\n    resp = await req.send(conn)\n    assert \"100-continue\" == req.headers[\"EXPECT\"]\n    assert req._continue is not None\n    req.terminate()\n    resp.close()\n    await req.close()\n\n\nasync def test_expect_100_continue_header(loop, conn) -> None:\n    req = ClientRequest(\n        \"get\", URL(\"http://python.org/\"), headers={\"expect\": \"100-continue\"}, loop=loop\n    )\n    resp = await req.send(conn)\n    assert \"100-continue\" == req.headers[\"EXPECT\"]\n    assert req._continue is not None\n    req.terminate()\n    resp.close()\n    await req.close()\n\n\nasync def test_data_stream(loop, buf, conn) -> None:\n    async def gen():\n        yield b\"binary data\"\n        yield b\" result\"\n\n    req = ClientRequest(\"POST\", URL(\"http://python.org/\"), data=gen(), loop=loop)\n    assert req.chunked\n    assert req.headers[\"TRANSFER-ENCODING\"] == \"chunked\"\n    original_write_bytes = req.write_bytes\n\n    async def _mock_write_bytes(*args, **kwargs):\n        # Ensure the task is scheduled\n        await asyncio.sleep(0)\n        return await original_write_bytes(*args, **kwargs)\n\n    with mock.patch.object(req, \"write_bytes\", _mock_write_bytes):\n        resp = await req.send(conn)\n    assert asyncio.isfuture(req._writer)\n    await resp.wait_for_close()\n    assert req._writer is None\n    assert (\n        buf.split(b\"\\r\\n\\r\\n\", 1)[1] == b\"b\\r\\nbinary data\\r\\n7\\r\\n result\\r\\n0\\r\\n\\r\\n\"\n    )\n    await req.close()\n\n\nasync def test_data_stream_deprecated(loop, buf, conn) -> None:\n    with pytest.warns(DeprecationWarning):\n\n        @aiohttp.streamer\n        async def gen(writer):\n            await writer.write(b\"binary data\")\n            await writer.write(b\" result\")\n\n    req = ClientRequest(\"POST\", URL(\"http://python.org/\"), data=gen(), loop=loop)\n    assert req.chunked\n    assert req.headers[\"TRANSFER-ENCODING\"] == \"chunked\"\n\n    resp = await req.send(conn)\n    await resp.wait_for_close()\n    assert (\n        buf.split(b\"\\r\\n\\r\\n\", 1)[1] == b\"b\\r\\nbinary data\\r\\n7\\r\\n result\\r\\n0\\r\\n\\r\\n\"\n    )\n    await req.close()\n\n\nasync def test_data_file(loop, buf, conn) -> None:\n    with io.BufferedReader(io.BytesIO(b\"*\" * 2)) as file_handle:\n        req = ClientRequest(\n            \"POST\",\n            URL(\"http://python.org/\"),\n            data=file_handle,\n            loop=loop,\n        )\n        assert req.chunked\n        assert isinstance(req.body, payload.BufferedReaderPayload)\n        assert req.headers[\"TRANSFER-ENCODING\"] == \"chunked\"\n\n        resp = await req.send(conn)\n        assert asyncio.isfuture(req._writer)\n        await resp.wait_for_close()\n\n        assert req._writer is None\n        assert buf.split(b\"\\r\\n\\r\\n\", 1)[1] == b\"2\\r\\n\" + b\"*\" * 2 + b\"\\r\\n0\\r\\n\\r\\n\"\n        await req.close()\n\n\nasync def test_data_stream_exc(loop, conn) -> None:\n    fut = loop.create_future()\n\n    async def gen():\n        yield b\"binary data\"\n        await fut\n\n    req = ClientRequest(\"POST\", URL(\"http://python.org/\"), data=gen(), loop=loop)\n    assert req.chunked\n    assert req.headers[\"TRANSFER-ENCODING\"] == \"chunked\"\n\n    async def throw_exc():\n        await asyncio.sleep(0.01)\n        fut.set_exception(ValueError)\n\n    loop.create_task(throw_exc())\n\n    await req.send(conn)\n    await req._writer\n    # assert conn.close.called\n    assert conn.protocol.set_exception.called\n    await req.close()\n\n\nasync def test_data_stream_exc_chain(loop, conn) -> None:\n    fut = loop.create_future()\n\n    async def gen():\n        await fut\n        return\n        yield\n\n    req = ClientRequest(\"POST\", URL(\"http://python.org/\"), data=gen(), loop=loop)\n\n    inner_exc = ValueError()\n\n    async def throw_exc():\n        await asyncio.sleep(0.01)\n        fut.set_exception(inner_exc)\n\n    loop.create_task(throw_exc())\n\n    await req.send(conn)\n    await req._writer\n    # assert connection.close.called\n    assert conn.protocol.set_exception.called\n    outer_exc = conn.protocol.set_exception.call_args[0][0]\n    assert isinstance(outer_exc, ClientConnectionError)\n    assert outer_exc.__cause__ is inner_exc\n    await req.close()\n\n\nasync def test_data_stream_continue(loop, buf, conn) -> None:\n    async def gen():\n        yield b\"binary data\"\n        yield b\" result\"\n\n    req = ClientRequest(\n        \"POST\", URL(\"http://python.org/\"), data=gen(), expect100=True, loop=loop\n    )\n    assert req.chunked\n\n    async def coro():\n        await asyncio.sleep(0.0001)\n        req._continue.set_result(1)\n\n    loop.create_task(coro())\n\n    resp = await req.send(conn)\n    await req._writer\n    assert (\n        buf.split(b\"\\r\\n\\r\\n\", 1)[1] == b\"b\\r\\nbinary data\\r\\n7\\r\\n result\\r\\n0\\r\\n\\r\\n\"\n    )\n    await req.close()\n    resp.close()\n\n\nasync def test_data_continue(loop, buf, conn) -> None:\n    req = ClientRequest(\n        \"POST\", URL(\"http://python.org/\"), data=b\"data\", expect100=True, loop=loop\n    )\n\n    async def coro():\n        await asyncio.sleep(0.0001)\n        req._continue.set_result(1)\n\n    loop.create_task(coro())\n\n    resp = await req.send(conn)\n\n    await req._writer\n    assert buf.split(b\"\\r\\n\\r\\n\", 1)[1] == b\"data\"\n    await req.close()\n    resp.close()\n\n\nasync def test_close(loop, buf, conn) -> None:\n    async def gen():\n        await asyncio.sleep(0.00001)\n        yield b\"result\"\n\n    req = ClientRequest(\"POST\", URL(\"http://python.org/\"), data=gen(), loop=loop)\n    resp = await req.send(conn)\n    await req.close()\n    assert buf.split(b\"\\r\\n\\r\\n\", 1)[1] == b\"6\\r\\nresult\\r\\n0\\r\\n\\r\\n\"\n    await req.close()\n    resp.close()\n\n\nasync def test_bad_version(loop, conn) -> None:\n    req = ClientRequest(\n        \"GET\",\n        URL(\"http://python.org\"),\n        loop=loop,\n        headers={\"Connection\": \"Close\"},\n        version=(\"1\", \"1\\r\\nInjected-Header: not allowed\"),\n    )\n\n    with pytest.raises(AttributeError):\n        await req.send(conn)\n\n\nasync def test_custom_response_class(loop, conn) -> None:\n    class CustomResponse(ClientResponse):\n        def read(self, decode=False):\n            return \"customized!\"\n\n    req = ClientRequest(\n        \"GET\", URL(\"http://python.org/\"), response_class=CustomResponse, loop=loop\n    )\n    resp = await req.send(conn)\n    assert \"customized!\" == resp.read()\n    await req.close()\n    resp.close()\n\n\nasync def test_oserror_on_write_bytes(loop, conn) -> None:\n    req = ClientRequest(\"POST\", URL(\"http://python.org/\"), loop=loop)\n\n    writer = WriterMock()\n    writer.write.side_effect = OSError\n\n    await req.write_bytes(writer, conn)\n\n    assert conn.protocol.set_exception.called\n    exc = conn.protocol.set_exception.call_args[0][0]\n    assert isinstance(exc, aiohttp.ClientOSError)\n\n    await req.close()\n\n\n@pytest.mark.skipif(sys.version_info < (3, 11), reason=\"Needs Task.cancelling()\")\nasync def test_cancel_close(loop: asyncio.AbstractEventLoop, conn: mock.Mock) -> None:\n    req = ClientRequest(\"get\", URL(\"http://python.org\"), loop=loop)\n    req._writer = asyncio.Future()  # type: ignore[assignment]\n\n    t = asyncio.create_task(req.close())\n\n    # Start waiting on _writer\n    await asyncio.sleep(0)\n\n    t.cancel()\n    # Cancellation should not be suppressed.\n    with pytest.raises(asyncio.CancelledError):\n        await t\n\n\nasync def test_terminate(loop: asyncio.AbstractEventLoop, conn: mock.Mock) -> None:\n    req = ClientRequest(\"get\", URL(\"http://python.org\"), loop=loop)\n\n    async def _mock_write_bytes(*args, **kwargs):\n        # Ensure the task is scheduled\n        await asyncio.sleep(0)\n\n    with mock.patch.object(req, \"write_bytes\", _mock_write_bytes):\n        resp = await req.send(conn)\n\n    assert req._writer is not None\n    assert resp._writer is not None\n    await resp._writer\n    writer = WriterMock()\n    writer.done = mock.Mock(return_value=False)\n    writer.cancel = mock.Mock()\n    req._writer = writer\n    resp._writer = writer\n\n    assert req._writer is not None\n    assert resp._writer is not None\n    req.terminate()\n    writer.cancel.assert_called_with()\n    writer.done.assert_called_with()\n    resp.close()\n\n    await req.close()\n\n\ndef test_terminate_with_closed_loop(loop, conn) -> None:\n    req = resp = writer = None\n\n    async def go():\n        nonlocal req, resp, writer\n        req = ClientRequest(\"get\", URL(\"http://python.org\"))\n\n        async def _mock_write_bytes(*args, **kwargs):\n            # Ensure the task is scheduled\n            await asyncio.sleep(0)\n\n        with mock.patch.object(req, \"write_bytes\", _mock_write_bytes):\n            resp = await req.send(conn)\n\n        assert req._writer is not None\n        writer = WriterMock()\n        writer.done = mock.Mock(return_value=False)\n        req._writer = writer\n        resp._writer = writer\n\n        await asyncio.sleep(0.05)\n\n    loop.run_until_complete(go())\n\n    loop.run_until_complete(req.close())\n    loop.close()\n    req.terminate()\n    assert req._writer is None\n    assert not writer.cancel.called\n    resp.close()\n\n\ndef test_terminate_without_writer(loop) -> None:\n    req = ClientRequest(\"get\", URL(\"http://python.org\"), loop=loop)\n    assert req._writer is None\n\n    req.terminate()\n    assert req._writer is None\n\n    loop.run_until_complete(req.close())\n\n\nasync def test_custom_req_rep(loop) -> None:\n    conn = None\n\n    class CustomResponse(ClientResponse):\n        async def start(self, connection, read_until_eof=False):\n            nonlocal conn\n            conn = connection\n            self.status = 123\n            self.reason = \"Test OK\"\n            self._headers = CIMultiDictProxy(CIMultiDict())\n            self.cookies = SimpleCookie()\n            return\n\n    called = False\n\n    class CustomRequest(ClientRequest):\n        async def send(self, conn):\n            resp = self.response_class(\n                self.method,\n                self.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            self.response = resp\n            nonlocal called\n            called = True\n            return resp\n\n    async def create_connection(req, traces, timeout):\n        assert isinstance(req, CustomRequest)\n        return mock.Mock()\n\n    connector = BaseConnector(loop=loop)\n    connector._create_connection = create_connection\n\n    session = aiohttp.ClientSession(\n        request_class=CustomRequest,\n        response_class=CustomResponse,\n        connector=connector,\n        loop=loop,\n    )\n\n    resp = await session.request(\"get\", URL(\"http://example.com/path/to\"))\n    assert isinstance(resp, CustomResponse)\n    assert called\n    resp.close()\n    await session.close()\n    conn.close()\n\n\ndef test_verify_ssl_false_with_ssl_context(loop, ssl_ctx) -> None:\n    with pytest.warns(DeprecationWarning):\n        with pytest.raises(ValueError):\n            _merge_ssl_params(\n                None, verify_ssl=False, ssl_context=ssl_ctx, fingerprint=None\n            )\n\n\ndef test_bad_fingerprint(loop) -> None:\n    with pytest.raises(ValueError):\n        Fingerprint(b\"invalid\")\n\n\ndef test_insecure_fingerprint_md5(loop) -> None:\n    with pytest.raises(ValueError):\n        Fingerprint(hashlib.md5(b\"foo\").digest())\n\n\ndef test_insecure_fingerprint_sha1(loop) -> None:\n    with pytest.raises(ValueError):\n        Fingerprint(hashlib.sha1(b\"foo\").digest())\n\n\ndef test_loose_cookies_types(loop) -> None:\n    req = ClientRequest(\"get\", URL(\"http://python.org\"), loop=loop)\n    morsel = Morsel()\n    morsel.set(key=\"string\", val=\"Another string\", coded_val=\"really\")\n\n    accepted_types = [\n        [(\"str\", BaseCookie())],\n        [(\"str\", morsel)],\n        [\n            (\"str\", \"str\"),\n        ],\n        {\"str\": BaseCookie()},\n        {\"str\": morsel},\n        {\"str\": \"str\"},\n        SimpleCookie(),\n    ]\n\n    for loose_cookies_type in accepted_types:\n        req.update_cookies(cookies=loose_cookies_type)\n\n    loop.run_until_complete(req.close())\n\n\n@pytest.mark.parametrize(\n    \"has_brotli,expected\",\n    [\n        (False, \"gzip, deflate\"),\n        (True, \"gzip, deflate, br\"),\n    ],\n)\ndef test_gen_default_accept_encoding(has_brotli, expected) -> None:\n    with mock.patch(\"aiohttp.client_reqrep.HAS_BROTLI\", has_brotli):\n        assert _gen_default_accept_encoding() == expected\n\n\n@pytest.mark.parametrize(\n    (\"netrc_contents\", \"expected_auth\"),\n    [\n        (\n            \"machine example.com login username password pass\\n\",\n            helpers.BasicAuth(\"username\", \"pass\"),\n        )\n    ],\n    indirect=(\"netrc_contents\",),\n)\n@pytest.mark.usefixtures(\"netrc_contents\")\ndef test_basicauth_from_netrc_present(\n    make_request: Any,\n    expected_auth: Optional[helpers.BasicAuth],\n):\n    \"\"\"Test appropriate Authorization header is sent when netrc is not empty.\"\"\"\n    req = make_request(\"get\", \"http://example.com\", trust_env=True)\n    assert req.headers[hdrs.AUTHORIZATION] == expected_auth.encode()\n\n\n@pytest.mark.parametrize(\n    \"netrc_contents\",\n    (\"machine example.com login username password pass\\n\",),\n    indirect=(\"netrc_contents\",),\n)\n@pytest.mark.usefixtures(\"netrc_contents\")\ndef test_basicauth_from_netrc_present_untrusted_env(\n    make_request: Any,\n):\n    \"\"\"Test no authorization header is sent via netrc if trust_env is False\"\"\"\n    req = make_request(\"get\", \"http://example.com\", trust_env=False)\n    assert hdrs.AUTHORIZATION not in req.headers\n\n\n@pytest.mark.parametrize(\n    \"netrc_contents\",\n    (\"\",),\n    indirect=(\"netrc_contents\",),\n)\n@pytest.mark.usefixtures(\"netrc_contents\")\ndef test_basicauth_from_empty_netrc(\n    make_request: Any,\n):\n    \"\"\"Test that no Authorization header is sent when netrc is empty\"\"\"\n    req = make_request(\"get\", \"http://example.com\", trust_env=True)\n    assert hdrs.AUTHORIZATION not in req.headers\n\n\nasync def test_connection_key_with_proxy() -> None:\n    \"\"\"Verify the proxy headers are included in the ConnectionKey when a proxy is used.\"\"\"\n    proxy = URL(\"http://proxy.example.com\")\n    req = ClientRequest(\n        \"GET\",\n        URL(\"http://example.com\"),\n        proxy=proxy,\n        proxy_headers={\"X-Proxy\": \"true\"},\n        loop=asyncio.get_running_loop(),\n    )\n    assert req.connection_key.proxy_headers_hash is not None\n    await req.close()\n\n\nasync def test_connection_key_without_proxy() -> None:\n    \"\"\"Verify the proxy headers are not included in the ConnectionKey when a proxy is used.\"\"\"\n    # If proxy is unspecified, proxy_headers should be ignored\n    req = ClientRequest(\n        \"GET\",\n        URL(\"http://example.com\"),\n        proxy_headers={\"X-Proxy\": \"true\"},\n        loop=asyncio.get_running_loop(),\n    )\n    assert req.connection_key.proxy_headers_hash is None\n    await req.close()\n",
            "header": {
                "file": {
                    "path": "tests/test_client_request.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "7853b541",
                "new_commit_hash": "c9d61bf1",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/tests/test_client_request.py"
            },
            "plus_file": {
                "path": "b/tests/test_client_request.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 1467,
                            "length": 3
                        },
                        "new_range": {
                            "start": 1467,
                            "length": 30
                        },
                        "section": "def test_basicauth_from_empty_netrc("
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "    \"\"\"Test that no Authorization header is sent when netrc is empty\"\"\"",
                                "type": "context"
                            },
                            {
                                "content": "    req = make_request(\"get\", \"http://example.com\", trust_env=True)",
                                "type": "context"
                            },
                            {
                                "content": "    assert hdrs.AUTHORIZATION not in req.headers",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "async def test_connection_key_with_proxy() -> None:",
                                "type": "added"
                            },
                            {
                                "content": "    \"\"\"Verify the proxy headers are included in the ConnectionKey when a proxy is used.\"\"\"",
                                "type": "added"
                            },
                            {
                                "content": "    proxy = URL(\"http://proxy.example.com\")",
                                "type": "added"
                            },
                            {
                                "content": "    req = ClientRequest(",
                                "type": "added"
                            },
                            {
                                "content": "        \"GET\",",
                                "type": "added"
                            },
                            {
                                "content": "        URL(\"http://example.com\"),",
                                "type": "added"
                            },
                            {
                                "content": "        proxy=proxy,",
                                "type": "added"
                            },
                            {
                                "content": "        proxy_headers={\"X-Proxy\": \"true\"},",
                                "type": "added"
                            },
                            {
                                "content": "        loop=asyncio.get_running_loop(),",
                                "type": "added"
                            },
                            {
                                "content": "    )",
                                "type": "added"
                            },
                            {
                                "content": "    assert req.connection_key.proxy_headers_hash is not None",
                                "type": "added"
                            },
                            {
                                "content": "    await req.close()",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "async def test_connection_key_without_proxy() -> None:",
                                "type": "added"
                            },
                            {
                                "content": "    \"\"\"Verify the proxy headers are not included in the ConnectionKey when a proxy is used.\"\"\"",
                                "type": "added"
                            },
                            {
                                "content": "    # If proxy is unspecified, proxy_headers should be ignored",
                                "type": "added"
                            },
                            {
                                "content": "    req = ClientRequest(",
                                "type": "added"
                            },
                            {
                                "content": "        \"GET\",",
                                "type": "added"
                            },
                            {
                                "content": "        URL(\"http://example.com\"),",
                                "type": "added"
                            },
                            {
                                "content": "        proxy_headers={\"X-Proxy\": \"true\"},",
                                "type": "added"
                            },
                            {
                                "content": "        loop=asyncio.get_running_loop(),",
                                "type": "added"
                            },
                            {
                                "content": "    )",
                                "type": "added"
                            },
                            {
                                "content": "    assert req.connection_key.proxy_headers_hash is None",
                                "type": "added"
                            },
                            {
                                "content": "    await req.close()",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [
                        {
                            "file_name": "tests/test_client_request.py",
                            "type": "function",
                            "name": "test_connection_key_without_proxy",
                            "content": "async def test_connection_key_without_proxy() -> None:\n    \"\"\"Verify the proxy headers are not included in the ConnectionKey when a proxy is used.\"\"\"\n    # If proxy is unspecified, proxy_headers should be ignored\n    req = ClientRequest(\n        \"GET\",\n        URL(\"http://example.com\"),\n        proxy_headers={\"X-Proxy\": \"true\"},\n        loop=asyncio.get_running_loop(),\n    )\n    assert req.connection_key.proxy_headers_hash is None\n    await req.close()",
                            "ast_type_str": "AsyncFunctionDef",
                            "start_lineno": 1486,
                            "end_lineno": 1496,
                            "parent": null
                        },
                        {
                            "file_name": "tests/test_client_request.py",
                            "type": "function",
                            "name": "test_connection_key_with_proxy",
                            "content": "async def test_connection_key_with_proxy() -> None:\n    \"\"\"Verify the proxy headers are included in the ConnectionKey when a proxy is used.\"\"\"\n    proxy = URL(\"http://proxy.example.com\")\n    req = ClientRequest(\n        \"GET\",\n        URL(\"http://example.com\"),\n        proxy=proxy,\n        proxy_headers={\"X-Proxy\": \"true\"},\n        loop=asyncio.get_running_loop(),\n    )\n    assert req.connection_key.proxy_headers_hash is not None\n    await req.close()",
                            "ast_type_str": "AsyncFunctionDef",
                            "start_lineno": 1472,
                            "end_lineno": 1483,
                            "parent": null
                        }
                    ],
                    "deleted_entities": []
                }
            ]
        }
    ],
    "old_commit_hash": "6198a56e67a65a4bc68d1661a1c4cb9201d455cd^",
    "new_commit_hash": "6198a56e67a65a4bc68d1661a1c4cb9201d455cd",
    "commit_message": "[PR #9368/02d8dba9 backport][3.10] Avoid using the proxy headers in the ConnectionKey if no proxy is in use (#9378)\n\nCo-authored-by: J. Nick Koston <nick@koston.org>",
    "commit_date": "2024-10-01T18:45:14-05:00",
    "metadata": {}
}
{
    "repo_name": "aiohttp",
    "new_commit_hash": "6198a56e67a65a4bc68d1661a1c4cb9201d455cd",
    "test_file_codes": [
        "import asyncio\nimport hashlib\nimport io\nimport pathlib\nimport sys\nimport urllib.parse\nimport zlib\nfrom http.cookies import BaseCookie, Morsel, SimpleCookie\nfrom typing import Any, Callable, Dict, Optional\nfrom unittest import mock\n\nimport pytest\nfrom multidict import CIMultiDict, CIMultiDictProxy, istr\nfrom yarl import URL\n\nimport aiohttp\nfrom aiohttp import BaseConnector, client_reqrep, hdrs, helpers, payload\nfrom aiohttp.client_exceptions import ClientConnectionError\nfrom aiohttp.client_reqrep import (\n    ClientRequest,\n    ClientResponse,\n    Fingerprint,\n    _gen_default_accept_encoding,\n    _merge_ssl_params,\n)\nfrom aiohttp.http import HttpVersion\nfrom aiohttp.test_utils import make_mocked_coro\n\n\nclass WriterMock(mock.AsyncMock):\n    def __await__(self) -> None:\n        return self().__await__()\n\n    def add_done_callback(self, cb: Callable[[], None]) -> None:\n        \"\"\"Dummy method.\"\"\"\n\n    def remove_done_callback(self, cb: Callable[[], None]) -> None:\n        \"\"\"Dummy method.\"\"\"\n\n\n@pytest.fixture\ndef make_request(loop):\n    request = None\n\n    def maker(method, url, *args, **kwargs):\n        nonlocal request\n        request = ClientRequest(method, URL(url), *args, loop=loop, **kwargs)\n        return request\n\n    yield maker\n    if request is not None:\n        loop.run_until_complete(request.close())\n\n\n@pytest.fixture\ndef buf():\n    return bytearray()\n\n\n@pytest.fixture\ndef protocol(loop, transport):\n    protocol = mock.Mock()\n    protocol.transport = transport\n    protocol._drain_helper.return_value = loop.create_future()\n    protocol._drain_helper.return_value.set_result(None)\n    return protocol\n\n\n@pytest.fixture\ndef transport(buf):\n    transport = mock.Mock()\n\n    def write(chunk):\n        buf.extend(chunk)\n\n    async def write_eof():\n        pass\n\n    transport.write.side_effect = write\n    transport.write_eof.side_effect = write_eof\n    transport.is_closing.return_value = False\n\n    return transport\n\n\n@pytest.fixture\ndef conn(transport, protocol):\n    return mock.Mock(transport=transport, protocol=protocol)\n\n\ndef test_method1(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org/\")\n    assert req.method == \"GET\"\n\n\ndef test_method2(make_request) -> None:\n    req = make_request(\"head\", \"http://python.org/\")\n    assert req.method == \"HEAD\"\n\n\ndef test_method3(make_request) -> None:\n    req = make_request(\"HEAD\", \"http://python.org/\")\n    assert req.method == \"HEAD\"\n\n\ndef test_method_invalid(make_request) -> None:\n    with pytest.raises(ValueError, match=\"Method cannot contain non-token characters\"):\n        make_request(\"METHOD WITH\\nWHITESPACES\", \"http://python.org/\")\n\n\ndef test_version_1_0(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org/\", version=\"1.0\")\n    assert req.version == (1, 0)\n\n\ndef test_version_default(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org/\")\n    assert req.version == (1, 1)\n\n\ndef test_request_info(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org/\")\n    assert req.request_info == aiohttp.RequestInfo(\n        URL(\"http://python.org/\"), \"GET\", req.headers\n    )\n\n\ndef test_request_info_with_fragment(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org/#urlfragment\")\n    assert req.request_info == aiohttp.RequestInfo(\n        URL(\"http://python.org/\"),\n        \"GET\",\n        req.headers,\n        URL(\"http://python.org/#urlfragment\"),\n    )\n\n\ndef test_version_err(make_request) -> None:\n    with pytest.raises(ValueError):\n        make_request(\"get\", \"http://python.org/\", version=\"1.c\")\n\n\ndef test_keep_alive(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org/\", version=(0, 9))\n    assert not req.keep_alive()\n\n    req = make_request(\"get\", \"http://python.org/\", version=(1, 0))\n    assert not req.keep_alive()\n\n    req = make_request(\n        \"get\",\n        \"http://python.org/\",\n        version=(1, 0),\n        headers={\"connection\": \"keep-alive\"},\n    )\n    assert req.keep_alive()\n\n    req = make_request(\"get\", \"http://python.org/\", version=(1, 1))\n    assert req.keep_alive()\n\n    req = make_request(\n        \"get\", \"http://python.org/\", version=(1, 1), headers={\"connection\": \"close\"}\n    )\n    assert not req.keep_alive()\n\n\ndef test_host_port_default_http(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org/\")\n    assert req.host == \"python.org\"\n    assert req.port == 80\n    assert not req.is_ssl()\n\n\ndef test_host_port_default_https(make_request) -> None:\n    req = make_request(\"get\", \"https://python.org/\")\n    assert req.host == \"python.org\"\n    assert req.port == 443\n    assert req.is_ssl()\n\n\ndef test_host_port_nondefault_http(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org:960/\")\n    assert req.host == \"python.org\"\n    assert req.port == 960\n    assert not req.is_ssl()\n\n\ndef test_host_port_nondefault_https(make_request) -> None:\n    req = make_request(\"get\", \"https://python.org:960/\")\n    assert req.host == \"python.org\"\n    assert req.port == 960\n    assert req.is_ssl()\n\n\ndef test_host_port_default_ws(make_request) -> None:\n    req = make_request(\"get\", \"ws://python.org/\")\n    assert req.host == \"python.org\"\n    assert req.port == 80\n    assert not req.is_ssl()\n\n\ndef test_host_port_default_wss(make_request) -> None:\n    req = make_request(\"get\", \"wss://python.org/\")\n    assert req.host == \"python.org\"\n    assert req.port == 443\n    assert req.is_ssl()\n\n\ndef test_host_port_nondefault_ws(make_request) -> None:\n    req = make_request(\"get\", \"ws://python.org:960/\")\n    assert req.host == \"python.org\"\n    assert req.port == 960\n    assert not req.is_ssl()\n\n\ndef test_host_port_nondefault_wss(make_request) -> None:\n    req = make_request(\"get\", \"wss://python.org:960/\")\n    assert req.host == \"python.org\"\n    assert req.port == 960\n    assert req.is_ssl()\n\n\ndef test_host_port_none_port(make_request) -> None:\n    req = make_request(\"get\", \"unix://localhost/path\")\n    assert req.headers[\"Host\"] == \"localhost\"\n\n\ndef test_host_port_err(make_request) -> None:\n    with pytest.raises(ValueError):\n        make_request(\"get\", \"http://python.org:123e/\")\n\n\ndef test_hostname_err(make_request) -> None:\n    with pytest.raises(ValueError):\n        make_request(\"get\", \"http://:8080/\")\n\n\ndef test_host_header_host_first(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org/\")\n    assert list(req.headers)[0] == \"Host\"\n\n\ndef test_host_header_host_without_port(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org/\")\n    assert req.headers[\"HOST\"] == \"python.org\"\n\n\ndef test_host_header_host_with_default_port(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org:80/\")\n    assert req.headers[\"HOST\"] == \"python.org\"\n\n\ndef test_host_header_host_with_nondefault_port(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org:99/\")\n    assert req.headers[\"HOST\"] == \"python.org:99\"\n\n\ndef test_host_header_host_idna_encode(make_request) -> None:\n    req = make_request(\"get\", \"http://xn--9caa.com\")\n    assert req.headers[\"HOST\"] == \"xn--9caa.com\"\n\n\ndef test_host_header_host_unicode(make_request) -> None:\n    req = make_request(\"get\", \"http://éé.com\")\n    assert req.headers[\"HOST\"] == \"xn--9caa.com\"\n\n\ndef test_host_header_explicit_host(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org/\", headers={\"host\": \"example.com\"})\n    assert req.headers[\"HOST\"] == \"example.com\"\n\n\ndef test_host_header_explicit_host_with_port(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org/\", headers={\"host\": \"example.com:99\"})\n    assert req.headers[\"HOST\"] == \"example.com:99\"\n\n\ndef test_host_header_ipv4(make_request) -> None:\n    req = make_request(\"get\", \"http://127.0.0.2\")\n    assert req.headers[\"HOST\"] == \"127.0.0.2\"\n\n\n@pytest.mark.parametrize(\"yarl_supports_host_subcomponent\", [True, False])\ndef test_host_header_ipv6(make_request, yarl_supports_host_subcomponent: bool) -> None:\n    # Ensure the old path is tested for old yarl versions\n    with mock.patch.object(\n        client_reqrep,\n        \"_YARL_SUPPORTS_HOST_SUBCOMPONENT\",\n        yarl_supports_host_subcomponent,\n    ):\n        req = make_request(\"get\", \"http://[::2]\")\n        assert req.headers[\"HOST\"] == \"[::2]\"\n\n\ndef test_host_header_ipv4_with_port(make_request) -> None:\n    req = make_request(\"get\", \"http://127.0.0.2:99\")\n    assert req.headers[\"HOST\"] == \"127.0.0.2:99\"\n\n\ndef test_host_header_ipv6_with_port(make_request) -> None:\n    req = make_request(\"get\", \"http://[::2]:99\")\n    assert req.headers[\"HOST\"] == \"[::2]:99\"\n\n\ndef test_default_loop(loop) -> None:\n    asyncio.set_event_loop(loop)\n    req = ClientRequest(\"get\", URL(\"http://python.org/\"))\n    assert req.loop is loop\n    loop.run_until_complete(req.close())\n\n\n@pytest.mark.parametrize(\n    (\"url\", \"headers\", \"expected\"),\n    (\n        pytest.param(\"http://localhost.\", None, \"localhost\", id=\"dot only at the end\"),\n        pytest.param(\"http://python.org.\", None, \"python.org\", id=\"single dot\"),\n        pytest.param(\n            \"http://python.org.:99\", None, \"python.org:99\", id=\"single dot with port\"\n        ),\n        pytest.param(\n            \"http://python.org...:99\",\n            None,\n            \"python.org:99\",\n            id=\"multiple dots with port\",\n        ),\n        pytest.param(\n            \"http://python.org.:99\",\n            {\"host\": \"example.com.:99\"},\n            \"example.com.:99\",\n            id=\"explicit host header\",\n        ),\n        pytest.param(\"https://python.org.\", None, \"python.org\", id=\"https\"),\n        pytest.param(\"https://...\", None, \"\", id=\"only dots\"),\n        pytest.param(\n            \"http://príklad.example.org.:99\",\n            None,\n            \"xn--prklad-4va.example.org:99\",\n            id=\"single dot with port idna\",\n        ),\n    ),\n)\ndef test_host_header_fqdn(\n    make_request: Any, url: str, headers: Dict[str, str], expected: str\n) -> None:\n    req = make_request(\"get\", url, headers=headers)\n    assert req.headers[\"HOST\"] == expected\n\n\ndef test_default_headers_useragent(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org/\")\n\n    assert \"SERVER\" not in req.headers\n    assert \"USER-AGENT\" in req.headers\n\n\ndef test_default_headers_useragent_custom(make_request) -> None:\n    req = make_request(\n        \"get\", \"http://python.org/\", headers={\"user-agent\": \"my custom agent\"}\n    )\n\n    assert \"USER-Agent\" in req.headers\n    assert \"my custom agent\" == req.headers[\"User-Agent\"]\n\n\ndef test_skip_default_useragent_header(make_request) -> None:\n    req = make_request(\n        \"get\", \"http://python.org/\", skip_auto_headers={istr(\"user-agent\")}\n    )\n\n    assert \"User-Agent\" not in req.headers\n\n\ndef test_headers(make_request) -> None:\n    req = make_request(\n        \"post\", \"http://python.org/\", headers={\"Content-Type\": \"text/plain\"}\n    )\n\n    assert \"CONTENT-TYPE\" in req.headers\n    assert req.headers[\"CONTENT-TYPE\"] == \"text/plain\"\n    assert req.headers[\"ACCEPT-ENCODING\"] == \"gzip, deflate, br\"\n\n\ndef test_headers_list(make_request) -> None:\n    req = make_request(\n        \"post\", \"http://python.org/\", headers=[(\"Content-Type\", \"text/plain\")]\n    )\n    assert \"CONTENT-TYPE\" in req.headers\n    assert req.headers[\"CONTENT-TYPE\"] == \"text/plain\"\n\n\ndef test_headers_default(make_request) -> None:\n    req = make_request(\n        \"get\", \"http://python.org/\", headers={\"ACCEPT-ENCODING\": \"deflate\"}\n    )\n    assert req.headers[\"ACCEPT-ENCODING\"] == \"deflate\"\n\n\ndef test_invalid_url(make_request) -> None:\n    with pytest.raises(aiohttp.InvalidURL):\n        make_request(\"get\", \"hiwpefhipowhefopw\")\n\n\ndef test_no_path(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org\")\n    assert \"/\" == req.url.path\n\n\ndef test_ipv6_default_http_port(make_request) -> None:\n    req = make_request(\"get\", \"http://[2001:db8::1]/\")\n    assert req.host == \"2001:db8::1\"\n    assert req.port == 80\n    assert not req.is_ssl()\n\n\ndef test_ipv6_default_https_port(make_request) -> None:\n    req = make_request(\"get\", \"https://[2001:db8::1]/\")\n    assert req.host == \"2001:db8::1\"\n    assert req.port == 443\n    assert req.is_ssl()\n\n\ndef test_ipv6_nondefault_http_port(make_request) -> None:\n    req = make_request(\"get\", \"http://[2001:db8::1]:960/\")\n    assert req.host == \"2001:db8::1\"\n    assert req.port == 960\n    assert not req.is_ssl()\n\n\ndef test_ipv6_nondefault_https_port(make_request) -> None:\n    req = make_request(\"get\", \"https://[2001:db8::1]:960/\")\n    assert req.host == \"2001:db8::1\"\n    assert req.port == 960\n    assert req.is_ssl()\n\n\ndef test_basic_auth(make_request) -> None:\n    req = make_request(\n        \"get\", \"http://python.org\", auth=aiohttp.BasicAuth(\"nkim\", \"1234\")\n    )\n    assert \"AUTHORIZATION\" in req.headers\n    assert \"Basic bmtpbToxMjM0\" == req.headers[\"AUTHORIZATION\"]\n\n\ndef test_basic_auth_utf8(make_request) -> None:\n    req = make_request(\n        \"get\", \"http://python.org\", auth=aiohttp.BasicAuth(\"nkim\", \"секрет\", \"utf-8\")\n    )\n    assert \"AUTHORIZATION\" in req.headers\n    assert \"Basic bmtpbTrRgdC10LrRgNC10YI=\" == req.headers[\"AUTHORIZATION\"]\n\n\ndef test_basic_auth_tuple_forbidden(make_request) -> None:\n    with pytest.raises(TypeError):\n        make_request(\"get\", \"http://python.org\", auth=(\"nkim\", \"1234\"))\n\n\ndef test_basic_auth_from_url(make_request) -> None:\n    req = make_request(\"get\", \"http://nkim:1234@python.org\")\n    assert \"AUTHORIZATION\" in req.headers\n    assert \"Basic bmtpbToxMjM0\" == req.headers[\"AUTHORIZATION\"]\n    assert \"python.org\" == req.host\n\n\ndef test_basic_auth_no_user_from_url(make_request) -> None:\n    req = make_request(\"get\", \"http://:1234@python.org\")\n    assert \"AUTHORIZATION\" in req.headers\n    assert \"Basic OjEyMzQ=\" == req.headers[\"AUTHORIZATION\"]\n    assert \"python.org\" == req.host\n\n\ndef test_basic_auth_from_url_overridden(make_request) -> None:\n    req = make_request(\n        \"get\", \"http://garbage@python.org\", auth=aiohttp.BasicAuth(\"nkim\", \"1234\")\n    )\n    assert \"AUTHORIZATION\" in req.headers\n    assert \"Basic bmtpbToxMjM0\" == req.headers[\"AUTHORIZATION\"]\n    assert \"python.org\" == req.host\n\n\ndef test_path_is_not_double_encoded1(make_request) -> None:\n    req = make_request(\"get\", \"http://0.0.0.0/get/test case\")\n    assert req.url.raw_path == \"/get/test%20case\"\n\n\ndef test_path_is_not_double_encoded2(make_request) -> None:\n    req = make_request(\"get\", \"http://0.0.0.0/get/test%2fcase\")\n    assert req.url.raw_path == \"/get/test%2Fcase\"\n\n\ndef test_path_is_not_double_encoded3(make_request) -> None:\n    req = make_request(\"get\", \"http://0.0.0.0/get/test%20case\")\n    assert req.url.raw_path == \"/get/test%20case\"\n\n\ndef test_path_safe_chars_preserved(make_request) -> None:\n    req = make_request(\"get\", \"http://0.0.0.0/get/:=+/%2B/\")\n    assert req.url.path == \"/get/:=+/+/\"\n\n\ndef test_params_are_added_before_fragment1(make_request) -> None:\n    req = make_request(\"GET\", \"http://example.com/path#fragment\", params={\"a\": \"b\"})\n    assert str(req.url) == \"http://example.com/path?a=b\"\n\n\ndef test_params_are_added_before_fragment2(make_request) -> None:\n    req = make_request(\n        \"GET\", \"http://example.com/path?key=value#fragment\", params={\"a\": \"b\"}\n    )\n    assert str(req.url) == \"http://example.com/path?key=value&a=b\"\n\n\ndef test_path_not_contain_fragment1(make_request) -> None:\n    req = make_request(\"GET\", \"http://example.com/path#fragment\")\n    assert req.url.path == \"/path\"\n\n\ndef test_path_not_contain_fragment2(make_request) -> None:\n    req = make_request(\"GET\", \"http://example.com/path?key=value#fragment\")\n    assert str(req.url) == \"http://example.com/path?key=value\"\n\n\ndef test_cookies(make_request) -> None:\n    req = make_request(\"get\", \"http://test.com/path\", cookies={\"cookie1\": \"val1\"})\n\n    assert \"COOKIE\" in req.headers\n    assert \"cookie1=val1\" == req.headers[\"COOKIE\"]\n\n\ndef test_cookies_is_quoted_with_special_characters(make_request) -> None:\n    req = make_request(\"get\", \"http://test.com/path\", cookies={\"cookie1\": \"val/one\"})\n\n    assert \"COOKIE\" in req.headers\n    assert 'cookie1=\"val/one\"' == req.headers[\"COOKIE\"]\n\n\ndef test_cookies_merge_with_headers(make_request) -> None:\n    req = make_request(\n        \"get\",\n        \"http://test.com/path\",\n        headers={\"cookie\": \"cookie1=val1\"},\n        cookies={\"cookie2\": \"val2\"},\n    )\n\n    assert \"cookie1=val1; cookie2=val2\" == req.headers[\"COOKIE\"]\n\n\ndef test_unicode_get1(make_request) -> None:\n    req = make_request(\"get\", \"http://python.org\", params={\"foo\": \"f\\xf8\\xf8\"})\n    assert \"http://python.org/?foo=f%C3%B8%C3%B8\" == str(req.url)\n\n\ndef test_unicode_get2(make_request) -> None:\n    req = make_request(\"\", \"http://python.org\", params={\"f\\xf8\\xf8\": \"f\\xf8\\xf8\"})\n\n    assert \"http://python.org/?f%C3%B8%C3%B8=f%C3%B8%C3%B8\" == str(req.url)\n\n\ndef test_unicode_get3(make_request) -> None:\n    req = make_request(\"\", \"http://python.org\", params={\"foo\": \"foo\"})\n    assert \"http://python.org/?foo=foo\" == str(req.url)\n\n\ndef test_unicode_get4(make_request) -> None:\n    def join(*suffix):\n        return urllib.parse.urljoin(\"http://python.org/\", \"/\".join(suffix))\n\n    req = make_request(\"\", join(\"\\xf8\"), params={\"foo\": \"foo\"})\n    assert \"http://python.org/%C3%B8?foo=foo\" == str(req.url)\n\n\ndef test_query_multivalued_param(make_request) -> None:\n    for meth in ClientRequest.ALL_METHODS:\n        req = make_request(\n            meth, \"http://python.org\", params=((\"test\", \"foo\"), (\"test\", \"baz\"))\n        )\n\n        assert str(req.url) == \"http://python.org/?test=foo&test=baz\"\n\n\ndef test_query_str_param(make_request) -> None:\n    for meth in ClientRequest.ALL_METHODS:\n        req = make_request(meth, \"http://python.org\", params=\"test=foo\")\n        assert str(req.url) == \"http://python.org/?test=foo\"\n\n\ndef test_query_bytes_param_raises(make_request) -> None:\n    for meth in ClientRequest.ALL_METHODS:\n        with pytest.raises(TypeError):\n            make_request(meth, \"http://python.org\", params=b\"test=foo\")\n\n\ndef test_query_str_param_is_not_encoded(make_request) -> None:\n    for meth in ClientRequest.ALL_METHODS:\n        req = make_request(meth, \"http://python.org\", params=\"test=f+oo\")\n        assert str(req.url) == \"http://python.org/?test=f+oo\"\n\n\ndef test_params_update_path_and_url(make_request) -> None:\n    req = make_request(\n        \"get\", \"http://python.org\", params=((\"test\", \"foo\"), (\"test\", \"baz\"))\n    )\n    assert str(req.url) == \"http://python.org/?test=foo&test=baz\"\n\n\ndef test_params_empty_path_and_url(make_request) -> None:\n    req_empty = make_request(\"get\", \"http://python.org\", params={})\n    assert str(req_empty.url) == \"http://python.org\"\n    req_none = make_request(\"get\", \"http://python.org\")\n    assert str(req_none.url) == \"http://python.org\"\n\n\ndef test_gen_netloc_all(make_request) -> None:\n    req = make_request(\n        \"get\",\n        \"https://aiohttp:pwpwpw@\"\n        + \"12345678901234567890123456789\"\n        + \"012345678901234567890:8080\",\n    )\n    assert (\n        req.headers[\"HOST\"]\n        == \"12345678901234567890123456789\" + \"012345678901234567890:8080\"\n    )\n\n\ndef test_gen_netloc_no_port(make_request) -> None:\n    req = make_request(\n        \"get\",\n        \"https://aiohttp:pwpwpw@\"\n        + \"12345678901234567890123456789\"\n        + \"012345678901234567890/\",\n    )\n    assert (\n        req.headers[\"HOST\"] == \"12345678901234567890123456789\" + \"012345678901234567890\"\n    )\n\n\nasync def test_connection_header(loop, conn) -> None:\n    req = ClientRequest(\"get\", URL(\"http://python.org\"), loop=loop)\n    req.keep_alive = mock.Mock()\n    req.headers.clear()\n\n    req.keep_alive.return_value = True\n    req.version = HttpVersion(1, 1)\n    req.headers.clear()\n    await req.send(conn)\n    assert req.headers.get(\"CONNECTION\") is None\n\n    req.version = HttpVersion(1, 0)\n    req.headers.clear()\n    await req.send(conn)\n    assert req.headers.get(\"CONNECTION\") == \"keep-alive\"\n\n    req.keep_alive.return_value = False\n    req.version = HttpVersion(1, 1)\n    req.headers.clear()\n    await req.send(conn)\n    assert req.headers.get(\"CONNECTION\") == \"close\"\n\n    await req.close()\n\n\nasync def test_no_content_length(loop, conn) -> None:\n    req = ClientRequest(\"get\", URL(\"http://python.org\"), loop=loop)\n    resp = await req.send(conn)\n    assert req.headers.get(\"CONTENT-LENGTH\") is None\n    await req.close()\n    resp.close()\n\n\nasync def test_no_content_length_head(loop, conn) -> None:\n    req = ClientRequest(\"head\", URL(\"http://python.org\"), loop=loop)\n    resp = await req.send(conn)\n    assert req.headers.get(\"CONTENT-LENGTH\") is None\n    await req.close()\n    resp.close()\n\n\nasync def test_content_type_auto_header_get(loop, conn) -> None:\n    req = ClientRequest(\"get\", URL(\"http://python.org\"), loop=loop)\n    resp = await req.send(conn)\n    assert \"CONTENT-TYPE\" not in req.headers\n    resp.close()\n    await req.close()\n\n\nasync def test_content_type_auto_header_form(loop, conn) -> None:\n    req = ClientRequest(\n        \"post\", URL(\"http://python.org\"), data={\"hey\": \"you\"}, loop=loop\n    )\n    resp = await req.send(conn)\n    assert \"application/x-www-form-urlencoded\" == req.headers.get(\"CONTENT-TYPE\")\n    resp.close()\n    await req.close()\n\n\nasync def test_content_type_auto_header_bytes(loop, conn) -> None:\n    req = ClientRequest(\"post\", URL(\"http://python.org\"), data=b\"hey you\", loop=loop)\n    resp = await req.send(conn)\n    assert \"application/octet-stream\" == req.headers.get(\"CONTENT-TYPE\")\n    resp.close()\n    await req.close()\n\n\nasync def test_content_type_skip_auto_header_bytes(loop, conn) -> None:\n    req = ClientRequest(\n        \"post\",\n        URL(\"http://python.org\"),\n        data=b\"hey you\",\n        skip_auto_headers={\"Content-Type\"},\n        loop=loop,\n    )\n    resp = await req.send(conn)\n    assert \"CONTENT-TYPE\" not in req.headers\n    resp.close()\n    await req.close()\n\n\nasync def test_content_type_skip_auto_header_form(loop, conn) -> None:\n    req = ClientRequest(\n        \"post\",\n        URL(\"http://python.org\"),\n        data={\"hey\": \"you\"},\n        loop=loop,\n        skip_auto_headers={\"Content-Type\"},\n    )\n    resp = await req.send(conn)\n    assert \"CONTENT-TYPE\" not in req.headers\n    resp.close()\n    await req.close()\n\n\nasync def test_content_type_auto_header_content_length_no_skip(loop, conn) -> None:\n    with io.BytesIO(b\"hey\") as file_handle:\n        req = ClientRequest(\n            \"post\",\n            URL(\"http://python.org\"),\n            data=file_handle,\n            skip_auto_headers={\"Content-Length\"},\n            loop=loop,\n        )\n        resp = await req.send(conn)\n        assert req.headers.get(\"CONTENT-LENGTH\") == \"3\"\n        resp.close()\n        await req.close()\n\n\nasync def test_urlencoded_formdata_charset(loop, conn) -> None:\n    req = ClientRequest(\n        \"post\",\n        URL(\"http://python.org\"),\n        data=aiohttp.FormData({\"hey\": \"you\"}, charset=\"koi8-r\"),\n        loop=loop,\n    )\n    await req.send(conn)\n    assert \"application/x-www-form-urlencoded; charset=koi8-r\" == req.headers.get(\n        \"CONTENT-TYPE\"\n    )\n    await req.close()\n\n\nasync def test_post_data(loop, conn) -> None:\n    for meth in ClientRequest.POST_METHODS:\n        req = ClientRequest(\n            meth, URL(\"http://python.org/\"), data={\"life\": \"42\"}, loop=loop\n        )\n        resp = await req.send(conn)\n        assert \"/\" == req.url.path\n        assert b\"life=42\" == req.body._value\n        assert \"application/x-www-form-urlencoded\" == req.headers[\"CONTENT-TYPE\"]\n        await req.close()\n        resp.close()\n\n\nasync def test_pass_falsy_data(loop) -> None:\n    with mock.patch(\"aiohttp.client_reqrep.ClientRequest.update_body_from_data\"):\n        req = ClientRequest(\"post\", URL(\"http://python.org/\"), data={}, loop=loop)\n        req.update_body_from_data.assert_called_once_with({})\n    await req.close()\n\n\nasync def test_pass_falsy_data_file(loop, tmp_path) -> None:\n    testfile = (tmp_path / \"tmpfile\").open(\"w+b\")\n    testfile.write(b\"data\")\n    testfile.seek(0)\n    skip = frozenset([hdrs.CONTENT_TYPE])\n    req = ClientRequest(\n        \"post\",\n        URL(\"http://python.org/\"),\n        data=testfile,\n        skip_auto_headers=skip,\n        loop=loop,\n    )\n    assert req.headers.get(\"CONTENT-LENGTH\", None) is not None\n    await req.close()\n    testfile.close()\n\n\n# Elasticsearch API requires to send request body with GET-requests\nasync def test_get_with_data(loop) -> None:\n    for meth in ClientRequest.GET_METHODS:\n        req = ClientRequest(\n            meth, URL(\"http://python.org/\"), data={\"life\": \"42\"}, loop=loop\n        )\n        assert \"/\" == req.url.path\n        assert b\"life=42\" == req.body._value\n        await req.close()\n\n\nasync def test_bytes_data(loop, conn) -> None:\n    for meth in ClientRequest.POST_METHODS:\n        req = ClientRequest(\n            meth, URL(\"http://python.org/\"), data=b\"binary data\", loop=loop\n        )\n        resp = await req.send(conn)\n        assert \"/\" == req.url.path\n        assert isinstance(req.body, payload.BytesPayload)\n        assert b\"binary data\" == req.body._value\n        assert \"application/octet-stream\" == req.headers[\"CONTENT-TYPE\"]\n        await req.close()\n        resp.close()\n\n\nasync def test_content_encoding(loop, conn) -> None:\n    req = ClientRequest(\n        \"post\", URL(\"http://python.org/\"), data=\"foo\", compress=\"deflate\", loop=loop\n    )\n    with mock.patch(\"aiohttp.client_reqrep.StreamWriter\") as m_writer:\n        m_writer.return_value.write_headers = make_mocked_coro()\n        resp = await req.send(conn)\n    assert req.headers[\"TRANSFER-ENCODING\"] == \"chunked\"\n    assert req.headers[\"CONTENT-ENCODING\"] == \"deflate\"\n    m_writer.return_value.enable_compression.assert_called_with(\"deflate\")\n    await req.close()\n    resp.close()\n\n\nasync def test_content_encoding_dont_set_headers_if_no_body(loop, conn) -> None:\n    req = ClientRequest(\n        \"post\", URL(\"http://python.org/\"), compress=\"deflate\", loop=loop\n    )\n    with mock.patch(\"aiohttp.client_reqrep.http\"):\n        resp = await req.send(conn)\n    assert \"TRANSFER-ENCODING\" not in req.headers\n    assert \"CONTENT-ENCODING\" not in req.headers\n    await req.close()\n    resp.close()\n\n\nasync def test_content_encoding_header(loop, conn) -> None:\n    req = ClientRequest(\n        \"post\",\n        URL(\"http://python.org/\"),\n        data=\"foo\",\n        headers={\"Content-Encoding\": \"deflate\"},\n        loop=loop,\n    )\n    with mock.patch(\"aiohttp.client_reqrep.StreamWriter\") as m_writer:\n        m_writer.return_value.write_headers = make_mocked_coro()\n        resp = await req.send(conn)\n\n    assert not m_writer.return_value.enable_compression.called\n    assert not m_writer.return_value.enable_chunking.called\n    await req.close()\n    resp.close()\n\n\nasync def test_compress_and_content_encoding(loop, conn) -> None:\n    with pytest.raises(ValueError):\n        ClientRequest(\n            \"post\",\n            URL(\"http://python.org/\"),\n            data=\"foo\",\n            headers={\"content-encoding\": \"deflate\"},\n            compress=\"deflate\",\n            loop=loop,\n        )\n\n\nasync def test_chunked(loop, conn) -> None:\n    req = ClientRequest(\n        \"post\",\n        URL(\"http://python.org/\"),\n        headers={\"TRANSFER-ENCODING\": \"gzip\"},\n        loop=loop,\n    )\n    resp = await req.send(conn)\n    assert \"gzip\" == req.headers[\"TRANSFER-ENCODING\"]\n    await req.close()\n    resp.close()\n\n\nasync def test_chunked2(loop, conn) -> None:\n    req = ClientRequest(\n        \"post\",\n        URL(\"http://python.org/\"),\n        headers={\"Transfer-encoding\": \"chunked\"},\n        loop=loop,\n    )\n    resp = await req.send(conn)\n    assert \"chunked\" == req.headers[\"TRANSFER-ENCODING\"]\n    await req.close()\n    resp.close()\n\n\nasync def test_chunked_explicit(loop, conn) -> None:\n    req = ClientRequest(\"post\", URL(\"http://python.org/\"), chunked=True, loop=loop)\n    with mock.patch(\"aiohttp.client_reqrep.StreamWriter\") as m_writer:\n        m_writer.return_value.write_headers = make_mocked_coro()\n        resp = await req.send(conn)\n\n    assert \"chunked\" == req.headers[\"TRANSFER-ENCODING\"]\n    m_writer.return_value.enable_chunking.assert_called_with()\n    await req.close()\n    resp.close()\n\n\nasync def test_chunked_length(loop, conn) -> None:\n    with pytest.raises(ValueError):\n        ClientRequest(\n            \"post\",\n            URL(\"http://python.org/\"),\n            headers={\"CONTENT-LENGTH\": \"1000\"},\n            chunked=True,\n            loop=loop,\n        )\n\n\nasync def test_chunked_transfer_encoding(loop, conn) -> None:\n    with pytest.raises(ValueError):\n        ClientRequest(\n            \"post\",\n            URL(\"http://python.org/\"),\n            headers={\"TRANSFER-ENCODING\": \"chunked\"},\n            chunked=True,\n            loop=loop,\n        )\n\n\nasync def test_file_upload_not_chunked(loop) -> None:\n    file_path = pathlib.Path(__file__).parent / \"aiohttp.png\"\n    with file_path.open(\"rb\") as f:\n        req = ClientRequest(\"post\", URL(\"http://python.org/\"), data=f, loop=loop)\n        assert not req.chunked\n        assert req.headers[\"CONTENT-LENGTH\"] == str(file_path.stat().st_size)\n        await req.close()\n\n\nasync def test_precompressed_data_stays_intact(loop) -> None:\n    data = zlib.compress(b\"foobar\")\n    req = ClientRequest(\n        \"post\",\n        URL(\"http://python.org/\"),\n        data=data,\n        headers={\"CONTENT-ENCODING\": \"deflate\"},\n        compress=False,\n        loop=loop,\n    )\n    assert not req.compress\n    assert not req.chunked\n    assert req.headers[\"CONTENT-ENCODING\"] == \"deflate\"\n    await req.close()\n\n\nasync def test_file_upload_not_chunked_seek(loop) -> None:\n    file_path = pathlib.Path(__file__).parent / \"aiohttp.png\"\n    with file_path.open(\"rb\") as f:\n        f.seek(100)\n        req = ClientRequest(\"post\", URL(\"http://python.org/\"), data=f, loop=loop)\n        assert req.headers[\"CONTENT-LENGTH\"] == str(file_path.stat().st_size - 100)\n        await req.close()\n\n\nasync def test_file_upload_force_chunked(loop) -> None:\n    file_path = pathlib.Path(__file__).parent / \"aiohttp.png\"\n    with file_path.open(\"rb\") as f:\n        req = ClientRequest(\n            \"post\", URL(\"http://python.org/\"), data=f, chunked=True, loop=loop\n        )\n        assert req.chunked\n        assert \"CONTENT-LENGTH\" not in req.headers\n        await req.close()\n\n\nasync def test_expect100(loop, conn) -> None:\n    req = ClientRequest(\"get\", URL(\"http://python.org/\"), expect100=True, loop=loop)\n    resp = await req.send(conn)\n    assert \"100-continue\" == req.headers[\"EXPECT\"]\n    assert req._continue is not None\n    req.terminate()\n    resp.close()\n    await req.close()\n\n\nasync def test_expect_100_continue_header(loop, conn) -> None:\n    req = ClientRequest(\n        \"get\", URL(\"http://python.org/\"), headers={\"expect\": \"100-continue\"}, loop=loop\n    )\n    resp = await req.send(conn)\n    assert \"100-continue\" == req.headers[\"EXPECT\"]\n    assert req._continue is not None\n    req.terminate()\n    resp.close()\n    await req.close()\n\n\nasync def test_data_stream(loop, buf, conn) -> None:\n    async def gen():\n        yield b\"binary data\"\n        yield b\" result\"\n\n    req = ClientRequest(\"POST\", URL(\"http://python.org/\"), data=gen(), loop=loop)\n    assert req.chunked\n    assert req.headers[\"TRANSFER-ENCODING\"] == \"chunked\"\n    original_write_bytes = req.write_bytes\n\n    async def _mock_write_bytes(*args, **kwargs):\n        # Ensure the task is scheduled\n        await asyncio.sleep(0)\n        return await original_write_bytes(*args, **kwargs)\n\n    with mock.patch.object(req, \"write_bytes\", _mock_write_bytes):\n        resp = await req.send(conn)\n    assert asyncio.isfuture(req._writer)\n    await resp.wait_for_close()\n    assert req._writer is None\n    assert (\n        buf.split(b\"\\r\\n\\r\\n\", 1)[1] == b\"b\\r\\nbinary data\\r\\n7\\r\\n result\\r\\n0\\r\\n\\r\\n\"\n    )\n    await req.close()\n\n\nasync def test_data_stream_deprecated(loop, buf, conn) -> None:\n    with pytest.warns(DeprecationWarning):\n\n        @aiohttp.streamer\n        async def gen(writer):\n            await writer.write(b\"binary data\")\n            await writer.write(b\" result\")\n\n    req = ClientRequest(\"POST\", URL(\"http://python.org/\"), data=gen(), loop=loop)\n    assert req.chunked\n    assert req.headers[\"TRANSFER-ENCODING\"] == \"chunked\"\n\n    resp = await req.send(conn)\n    await resp.wait_for_close()\n    assert (\n        buf.split(b\"\\r\\n\\r\\n\", 1)[1] == b\"b\\r\\nbinary data\\r\\n7\\r\\n result\\r\\n0\\r\\n\\r\\n\"\n    )\n    await req.close()\n\n\nasync def test_data_file(loop, buf, conn) -> None:\n    with io.BufferedReader(io.BytesIO(b\"*\" * 2)) as file_handle:\n        req = ClientRequest(\n            \"POST\",\n            URL(\"http://python.org/\"),\n            data=file_handle,\n            loop=loop,\n        )\n        assert req.chunked\n        assert isinstance(req.body, payload.BufferedReaderPayload)\n        assert req.headers[\"TRANSFER-ENCODING\"] == \"chunked\"\n\n        resp = await req.send(conn)\n        assert asyncio.isfuture(req._writer)\n        await resp.wait_for_close()\n\n        assert req._writer is None\n        assert buf.split(b\"\\r\\n\\r\\n\", 1)[1] == b\"2\\r\\n\" + b\"*\" * 2 + b\"\\r\\n0\\r\\n\\r\\n\"\n        await req.close()\n\n\nasync def test_data_stream_exc(loop, conn) -> None:\n    fut = loop.create_future()\n\n    async def gen():\n        yield b\"binary data\"\n        await fut\n\n    req = ClientRequest(\"POST\", URL(\"http://python.org/\"), data=gen(), loop=loop)\n    assert req.chunked\n    assert req.headers[\"TRANSFER-ENCODING\"] == \"chunked\"\n\n    async def throw_exc():\n        await asyncio.sleep(0.01)\n        fut.set_exception(ValueError)\n\n    loop.create_task(throw_exc())\n\n    await req.send(conn)\n    await req._writer\n    # assert conn.close.called\n    assert conn.protocol.set_exception.called\n    await req.close()\n\n\nasync def test_data_stream_exc_chain(loop, conn) -> None:\n    fut = loop.create_future()\n\n    async def gen():\n        await fut\n        return\n        yield\n\n    req = ClientRequest(\"POST\", URL(\"http://python.org/\"), data=gen(), loop=loop)\n\n    inner_exc = ValueError()\n\n    async def throw_exc():\n        await asyncio.sleep(0.01)\n        fut.set_exception(inner_exc)\n\n    loop.create_task(throw_exc())\n\n    await req.send(conn)\n    await req._writer\n    # assert connection.close.called\n    assert conn.protocol.set_exception.called\n    outer_exc = conn.protocol.set_exception.call_args[0][0]\n    assert isinstance(outer_exc, ClientConnectionError)\n    assert outer_exc.__cause__ is inner_exc\n    await req.close()\n\n\nasync def test_data_stream_continue(loop, buf, conn) -> None:\n    async def gen():\n        yield b\"binary data\"\n        yield b\" result\"\n\n    req = ClientRequest(\n        \"POST\", URL(\"http://python.org/\"), data=gen(), expect100=True, loop=loop\n    )\n    assert req.chunked\n\n    async def coro():\n        await asyncio.sleep(0.0001)\n        req._continue.set_result(1)\n\n    loop.create_task(coro())\n\n    resp = await req.send(conn)\n    await req._writer\n    assert (\n        buf.split(b\"\\r\\n\\r\\n\", 1)[1] == b\"b\\r\\nbinary data\\r\\n7\\r\\n result\\r\\n0\\r\\n\\r\\n\"\n    )\n    await req.close()\n    resp.close()\n\n\nasync def test_data_continue(loop, buf, conn) -> None:\n    req = ClientRequest(\n        \"POST\", URL(\"http://python.org/\"), data=b\"data\", expect100=True, loop=loop\n    )\n\n    async def coro():\n        await asyncio.sleep(0.0001)\n        req._continue.set_result(1)\n\n    loop.create_task(coro())\n\n    resp = await req.send(conn)\n\n    await req._writer\n    assert buf.split(b\"\\r\\n\\r\\n\", 1)[1] == b\"data\"\n    await req.close()\n    resp.close()\n\n\nasync def test_close(loop, buf, conn) -> None:\n    async def gen():\n        await asyncio.sleep(0.00001)\n        yield b\"result\"\n\n    req = ClientRequest(\"POST\", URL(\"http://python.org/\"), data=gen(), loop=loop)\n    resp = await req.send(conn)\n    await req.close()\n    assert buf.split(b\"\\r\\n\\r\\n\", 1)[1] == b\"6\\r\\nresult\\r\\n0\\r\\n\\r\\n\"\n    await req.close()\n    resp.close()\n\n\nasync def test_bad_version(loop, conn) -> None:\n    req = ClientRequest(\n        \"GET\",\n        URL(\"http://python.org\"),\n        loop=loop,\n        headers={\"Connection\": \"Close\"},\n        version=(\"1\", \"1\\r\\nInjected-Header: not allowed\"),\n    )\n\n    with pytest.raises(AttributeError):\n        await req.send(conn)\n\n\nasync def test_custom_response_class(loop, conn) -> None:\n    class CustomResponse(ClientResponse):\n        def read(self, decode=False):\n            return \"customized!\"\n\n    req = ClientRequest(\n        \"GET\", URL(\"http://python.org/\"), response_class=CustomResponse, loop=loop\n    )\n    resp = await req.send(conn)\n    assert \"customized!\" == resp.read()\n    await req.close()\n    resp.close()\n\n\nasync def test_oserror_on_write_bytes(loop, conn) -> None:\n    req = ClientRequest(\"POST\", URL(\"http://python.org/\"), loop=loop)\n\n    writer = WriterMock()\n    writer.write.side_effect = OSError\n\n    await req.write_bytes(writer, conn)\n\n    assert conn.protocol.set_exception.called\n    exc = conn.protocol.set_exception.call_args[0][0]\n    assert isinstance(exc, aiohttp.ClientOSError)\n\n    await req.close()\n\n\n@pytest.mark.skipif(sys.version_info < (3, 11), reason=\"Needs Task.cancelling()\")\nasync def test_cancel_close(loop: asyncio.AbstractEventLoop, conn: mock.Mock) -> None:\n    req = ClientRequest(\"get\", URL(\"http://python.org\"), loop=loop)\n    req._writer = asyncio.Future()  # type: ignore[assignment]\n\n    t = asyncio.create_task(req.close())\n\n    # Start waiting on _writer\n    await asyncio.sleep(0)\n\n    t.cancel()\n    # Cancellation should not be suppressed.\n    with pytest.raises(asyncio.CancelledError):\n        await t\n\n\nasync def test_terminate(loop: asyncio.AbstractEventLoop, conn: mock.Mock) -> None:\n    req = ClientRequest(\"get\", URL(\"http://python.org\"), loop=loop)\n\n    async def _mock_write_bytes(*args, **kwargs):\n        # Ensure the task is scheduled\n        await asyncio.sleep(0)\n\n    with mock.patch.object(req, \"write_bytes\", _mock_write_bytes):\n        resp = await req.send(conn)\n\n    assert req._writer is not None\n    assert resp._writer is not None\n    await resp._writer\n    writer = WriterMock()\n    writer.done = mock.Mock(return_value=False)\n    writer.cancel = mock.Mock()\n    req._writer = writer\n    resp._writer = writer\n\n    assert req._writer is not None\n    assert resp._writer is not None\n    req.terminate()\n    writer.cancel.assert_called_with()\n    writer.done.assert_called_with()\n    resp.close()\n\n    await req.close()\n\n\ndef test_terminate_with_closed_loop(loop, conn) -> None:\n    req = resp = writer = None\n\n    async def go():\n        nonlocal req, resp, writer\n        req = ClientRequest(\"get\", URL(\"http://python.org\"))\n\n        async def _mock_write_bytes(*args, **kwargs):\n            # Ensure the task is scheduled\n            await asyncio.sleep(0)\n\n        with mock.patch.object(req, \"write_bytes\", _mock_write_bytes):\n            resp = await req.send(conn)\n\n        assert req._writer is not None\n        writer = WriterMock()\n        writer.done = mock.Mock(return_value=False)\n        req._writer = writer\n        resp._writer = writer\n\n        await asyncio.sleep(0.05)\n\n    loop.run_until_complete(go())\n\n    loop.run_until_complete(req.close())\n    loop.close()\n    req.terminate()\n    assert req._writer is None\n    assert not writer.cancel.called\n    resp.close()\n\n\ndef test_terminate_without_writer(loop) -> None:\n    req = ClientRequest(\"get\", URL(\"http://python.org\"), loop=loop)\n    assert req._writer is None\n\n    req.terminate()\n    assert req._writer is None\n\n    loop.run_until_complete(req.close())\n\n\nasync def test_custom_req_rep(loop) -> None:\n    conn = None\n\n    class CustomResponse(ClientResponse):\n        async def start(self, connection, read_until_eof=False):\n            nonlocal conn\n            conn = connection\n            self.status = 123\n            self.reason = \"Test OK\"\n            self._headers = CIMultiDictProxy(CIMultiDict())\n            self.cookies = SimpleCookie()\n            return\n\n    called = False\n\n    class CustomRequest(ClientRequest):\n        async def send(self, conn):\n            resp = self.response_class(\n                self.method,\n                self.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            self.response = resp\n            nonlocal called\n            called = True\n            return resp\n\n    async def create_connection(req, traces, timeout):\n        assert isinstance(req, CustomRequest)\n        return mock.Mock()\n\n    connector = BaseConnector(loop=loop)\n    connector._create_connection = create_connection\n\n    session = aiohttp.ClientSession(\n        request_class=CustomRequest,\n        response_class=CustomResponse,\n        connector=connector,\n        loop=loop,\n    )\n\n    resp = await session.request(\"get\", URL(\"http://example.com/path/to\"))\n    assert isinstance(resp, CustomResponse)\n    assert called\n    resp.close()\n    await session.close()\n    conn.close()\n\n\ndef test_verify_ssl_false_with_ssl_context(loop, ssl_ctx) -> None:\n    with pytest.warns(DeprecationWarning):\n        with pytest.raises(ValueError):\n            _merge_ssl_params(\n                None, verify_ssl=False, ssl_context=ssl_ctx, fingerprint=None\n            )\n\n\ndef test_bad_fingerprint(loop) -> None:\n    with pytest.raises(ValueError):\n        Fingerprint(b\"invalid\")\n\n\ndef test_insecure_fingerprint_md5(loop) -> None:\n    with pytest.raises(ValueError):\n        Fingerprint(hashlib.md5(b\"foo\").digest())\n\n\ndef test_insecure_fingerprint_sha1(loop) -> None:\n    with pytest.raises(ValueError):\n        Fingerprint(hashlib.sha1(b\"foo\").digest())\n\n\ndef test_loose_cookies_types(loop) -> None:\n    req = ClientRequest(\"get\", URL(\"http://python.org\"), loop=loop)\n    morsel = Morsel()\n    morsel.set(key=\"string\", val=\"Another string\", coded_val=\"really\")\n\n    accepted_types = [\n        [(\"str\", BaseCookie())],\n        [(\"str\", morsel)],\n        [\n            (\"str\", \"str\"),\n        ],\n        {\"str\": BaseCookie()},\n        {\"str\": morsel},\n        {\"str\": \"str\"},\n        SimpleCookie(),\n    ]\n\n    for loose_cookies_type in accepted_types:\n        req.update_cookies(cookies=loose_cookies_type)\n\n    loop.run_until_complete(req.close())\n\n\n@pytest.mark.parametrize(\n    \"has_brotli,expected\",\n    [\n        (False, \"gzip, deflate\"),\n        (True, \"gzip, deflate, br\"),\n    ],\n)\ndef test_gen_default_accept_encoding(has_brotli, expected) -> None:\n    with mock.patch(\"aiohttp.client_reqrep.HAS_BROTLI\", has_brotli):\n        assert _gen_default_accept_encoding() == expected\n\n\n@pytest.mark.parametrize(\n    (\"netrc_contents\", \"expected_auth\"),\n    [\n        (\n            \"machine example.com login username password pass\\n\",\n            helpers.BasicAuth(\"username\", \"pass\"),\n        )\n    ],\n    indirect=(\"netrc_contents\",),\n)\n@pytest.mark.usefixtures(\"netrc_contents\")\ndef test_basicauth_from_netrc_present(\n    make_request: Any,\n    expected_auth: Optional[helpers.BasicAuth],\n):\n    \"\"\"Test appropriate Authorization header is sent when netrc is not empty.\"\"\"\n    req = make_request(\"get\", \"http://example.com\", trust_env=True)\n    assert req.headers[hdrs.AUTHORIZATION] == expected_auth.encode()\n\n\n@pytest.mark.parametrize(\n    \"netrc_contents\",\n    (\"machine example.com login username password pass\\n\",),\n    indirect=(\"netrc_contents\",),\n)\n@pytest.mark.usefixtures(\"netrc_contents\")\ndef test_basicauth_from_netrc_present_untrusted_env(\n    make_request: Any,\n):\n    \"\"\"Test no authorization header is sent via netrc if trust_env is False\"\"\"\n    req = make_request(\"get\", \"http://example.com\", trust_env=False)\n    assert hdrs.AUTHORIZATION not in req.headers\n\n\n@pytest.mark.parametrize(\n    \"netrc_contents\",\n    (\"\",),\n    indirect=(\"netrc_contents\",),\n)\n@pytest.mark.usefixtures(\"netrc_contents\")\ndef test_basicauth_from_empty_netrc(\n    make_request: Any,\n):\n    \"\"\"Test that no Authorization header is sent when netrc is empty\"\"\"\n    req = make_request(\"get\", \"http://example.com\", trust_env=True)\n    assert hdrs.AUTHORIZATION not in req.headers\n\n\nasync def test_connection_key_with_proxy() -> None:\n    \"\"\"Verify the proxy headers are included in the ConnectionKey when a proxy is used.\"\"\"\n    proxy = URL(\"http://proxy.example.com\")\n    req = ClientRequest(\n        \"GET\",\n        URL(\"http://example.com\"),\n        proxy=proxy,\n        proxy_headers={\"X-Proxy\": \"true\"},\n        loop=asyncio.get_running_loop(),\n    )\n    assert req.connection_key.proxy_headers_hash is not None\n    await req.close()\n\n\nasync def test_connection_key_without_proxy() -> None:\n    \"\"\"Verify the proxy headers are not included in the ConnectionKey when a proxy is used.\"\"\"\n    # If proxy is unspecified, proxy_headers should be ignored\n    req = ClientRequest(\n        \"GET\",\n        URL(\"http://example.com\"),\n        proxy_headers={\"X-Proxy\": \"true\"},\n        loop=asyncio.get_running_loop(),\n    )\n    assert req.connection_key.proxy_headers_hash is None\n    await req.close()\n",
        "import asyncio\nimport base64\nimport os\nimport socket\nimport ssl\nimport sys\nfrom hashlib import md5, sha1, sha256\nfrom pathlib import Path\nfrom tempfile import TemporaryDirectory\nfrom typing import Any\nfrom unittest import mock\nfrom uuid import uuid4\n\nimport pytest\n\nfrom aiohttp.client_proto import ResponseHandler\nfrom aiohttp.http import WS_KEY\nfrom aiohttp.test_utils import loop_context\n\ntry:\n    import trustme\n\n    # Check if the CA is available in runtime, MacOS on Py3.10 fails somehow\n    trustme.CA()\n\n    TRUSTME: bool = True\nexcept ImportError:\n    TRUSTME = False\n\npytest_plugins = [\"aiohttp.pytest_plugin\", \"pytester\"]\n\nIS_HPUX = sys.platform.startswith(\"hp-ux\")\nIS_LINUX = sys.platform.startswith(\"linux\")\n\n\n@pytest.fixture\ndef tls_certificate_authority():\n    if not TRUSTME:\n        pytest.xfail(\"trustme is not supported\")\n    return trustme.CA()\n\n\n@pytest.fixture\ndef tls_certificate(tls_certificate_authority):\n    return tls_certificate_authority.issue_cert(\n        \"localhost\",\n        \"xn--prklad-4va.localhost\",\n        \"127.0.0.1\",\n        \"::1\",\n    )\n\n\n@pytest.fixture\ndef ssl_ctx(tls_certificate):\n    ssl_ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)\n    tls_certificate.configure_cert(ssl_ctx)\n    return ssl_ctx\n\n\n@pytest.fixture\ndef client_ssl_ctx(tls_certificate_authority):\n    ssl_ctx = ssl.create_default_context(purpose=ssl.Purpose.SERVER_AUTH)\n    tls_certificate_authority.configure_trust(ssl_ctx)\n    return ssl_ctx\n\n\n@pytest.fixture\ndef tls_ca_certificate_pem_path(tls_certificate_authority):\n    with tls_certificate_authority.cert_pem.tempfile() as ca_cert_pem:\n        yield ca_cert_pem\n\n\n@pytest.fixture\ndef tls_certificate_pem_path(tls_certificate):\n    with tls_certificate.private_key_and_cert_chain_pem.tempfile() as cert_pem:\n        yield cert_pem\n\n\n@pytest.fixture\ndef tls_certificate_pem_bytes(tls_certificate):\n    return tls_certificate.cert_chain_pems[0].bytes()\n\n\n@pytest.fixture\ndef tls_certificate_fingerprint_sha256(tls_certificate_pem_bytes):\n    tls_cert_der = ssl.PEM_cert_to_DER_cert(tls_certificate_pem_bytes.decode())\n    return sha256(tls_cert_der).digest()\n\n\n@pytest.fixture\ndef unix_sockname(tmp_path, tmp_path_factory):\n    \"\"\"Generate an fs path to the UNIX domain socket for testing.\n\n    N.B. Different OS kernels have different fs path length limitations\n    for it. For Linux, it's 108, for HP-UX it's 92 (or higher) depending\n    on its version. For for most of the BSDs (Open, Free, macOS) it's\n    mostly 104 but sometimes it can be down to 100.\n\n    Ref: https://github.com/aio-libs/aiohttp/issues/3572\n    \"\"\"\n    if not hasattr(socket, \"AF_UNIX\"):\n        pytest.skip(\"requires UNIX sockets\")\n\n    max_sock_len = 92 if IS_HPUX else 108 if IS_LINUX else 100\n    \"\"\"Amount of bytes allocated for the UNIX socket path by OS kernel.\n\n    Ref: https://unix.stackexchange.com/a/367012/27133\n    \"\"\"\n\n    sock_file_name = \"unix.sock\"\n    unique_prefix = f\"{uuid4()!s}-\"\n    unique_prefix_len = len(unique_prefix.encode())\n\n    root_tmp_dir = Path(\"/tmp\").resolve()\n    os_tmp_dir = Path(os.getenv(\"TMPDIR\", \"/tmp\")).resolve()\n    original_base_tmp_path = Path(\n        str(tmp_path_factory.getbasetemp()),\n    ).resolve()\n\n    original_base_tmp_path_hash = md5(\n        str(original_base_tmp_path).encode(),\n    ).hexdigest()\n\n    def make_tmp_dir(base_tmp_dir):\n        return TemporaryDirectory(\n            dir=str(base_tmp_dir),\n            prefix=\"pt-\",\n            suffix=f\"-{original_base_tmp_path_hash!s}\",\n        )\n\n    def assert_sock_fits(sock_path):\n        sock_path_len = len(sock_path.encode())\n        # exit-check to verify that it's correct and simplify debugging\n        # in the future\n        assert sock_path_len <= max_sock_len, (\n            \"Suggested UNIX socket ({sock_path}) is {sock_path_len} bytes \"\n            \"long but the current kernel only has {max_sock_len} bytes \"\n            \"allocated to hold it so it must be shorter. \"\n            \"See https://github.com/aio-libs/aiohttp/issues/3572 \"\n            \"for more info.\"\n        ).format_map(locals())\n\n    paths = original_base_tmp_path, os_tmp_dir, root_tmp_dir\n    unique_paths = [p for n, p in enumerate(paths) if p not in paths[:n]]\n    paths_num = len(unique_paths)\n\n    for num, tmp_dir_path in enumerate(paths, 1):\n        with make_tmp_dir(tmp_dir_path) as tmpd:\n            tmpd = Path(tmpd).resolve()\n            sock_path = str(tmpd / sock_file_name)\n            sock_path_len = len(sock_path.encode())\n\n            if num >= paths_num:\n                # exit-check to verify that it's correct and simplify\n                # debugging in the future\n                assert_sock_fits(sock_path)\n\n            if sock_path_len <= max_sock_len:\n                if max_sock_len - sock_path_len >= unique_prefix_len:\n                    # If we're lucky to have extra space in the path,\n                    # let's also make it more unique\n                    sock_path = str(tmpd / \"\".join((unique_prefix, sock_file_name)))\n                    # Double-checking it:\n                    assert_sock_fits(sock_path)\n                yield sock_path\n                return\n\n\n@pytest.fixture\ndef pipe_name():\n    name = rf\"\\\\.\\pipe\\{uuid4().hex}\"\n    return name\n\n\n@pytest.fixture\ndef create_mocked_conn(loop: Any):\n    def _proto_factory(conn_closing_result=None, **kwargs):\n        proto = mock.create_autospec(ResponseHandler, **kwargs)\n        proto.closed = loop.create_future()\n        proto.closed.set_result(conn_closing_result)\n        return proto\n\n    yield _proto_factory\n\n\n@pytest.fixture\ndef selector_loop():\n    policy = asyncio.WindowsSelectorEventLoopPolicy()\n    asyncio.set_event_loop_policy(policy)\n\n    with loop_context(policy.new_event_loop) as _loop:\n        asyncio.set_event_loop(_loop)\n        yield _loop\n\n\n@pytest.fixture\ndef netrc_contents(\n    tmp_path: Path,\n    monkeypatch: pytest.MonkeyPatch,\n    request: pytest.FixtureRequest,\n):\n    \"\"\"\n    Prepare :file:`.netrc` with given contents.\n\n    Monkey-patches :envvar:`NETRC` to point to created file.\n    \"\"\"\n    netrc_contents = getattr(request, \"param\", None)\n\n    netrc_file_path = tmp_path / \".netrc\"\n    if netrc_contents is not None:\n        netrc_file_path.write_text(netrc_contents)\n\n    monkeypatch.setenv(\"NETRC\", str(netrc_file_path))\n\n    return netrc_file_path\n\n\n@pytest.fixture\ndef start_connection():\n    with mock.patch(\n        \"aiohttp.connector.aiohappyeyeballs.start_connection\",\n        autospec=True,\n        spec_set=True,\n    ) as start_connection_mock:\n        yield start_connection_mock\n\n\n@pytest.fixture\ndef key_data():\n    return os.urandom(16)\n\n\n@pytest.fixture\ndef key(key_data: Any):\n    return base64.b64encode(key_data)\n\n\n@pytest.fixture\ndef ws_key(key: Any):\n    return base64.b64encode(sha1(key + WS_KEY).digest()).decode()\n"
    ],
    "test_file_names": [
        "test_1.py",
        "conftest.py"
    ],
    "setup_res_code": 0,
    "setup_res_stdout": "re-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/requirements/cython.txt\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/tools/gen.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/hdrs.py\n./tools/gen.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/_helpers.pyx\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/_http_parser.pyx\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/_http_writer.pyx\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/_websocket.pyx\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/_helpers.pyi\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/_cparser.pxd\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/_find_header.pxd\ncython -3 -o aiohttp/_helpers.c aiohttp/_helpers.pyx -I aiohttp -Werror\ncython -3 -o aiohttp/_http_parser.c aiohttp/_http_parser.pyx -I aiohttp -Werror\ncython -3 -o aiohttp/_http_writer.c aiohttp/_http_writer.pyx -I aiohttp -Werror\ncython -3 -o aiohttp/_websocket.c aiohttp/_websocket.pyx -I aiohttp -Werror\ncd vendor/llhttp; npm ci\n\n> llhttp@9.2.1 prepare\n> npm run clean && npm run build-ts\n\n\n> llhttp@9.2.1 clean\n> rm -rf lib && rm -rf test/tmp\n\n\n> llhttp@9.2.1 build-ts\n> tsc\n\n\nadded 213 packages, and audited 214 packages in 6s\n\n41 packages are looking for funding\n  run `npm fund` for details\n\n5 vulnerabilities (3 moderate, 2 high)\n\nTo address issues that do not require attention, run:\n  npm audit fix\n\nSome issues need review, and may require choosing\na different dependency.\n\nRun `npm audit` for details.\nmake -C vendor/llhttp generate\nmake[1]: Entering directory '/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/vendor/llhttp'\nnpx ts-node bin/generate.ts\nmake[1]: Leaving directory '/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/vendor/llhttp'\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/__init__.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/abc.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/base_protocol.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/client.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/client_exceptions.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/client_proto.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/client_reqrep.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/client_ws.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/compression_utils.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/connector.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/cookiejar.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/formdata.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/helpers.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/http.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/http_exceptions.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/http_parser.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/http_websocket.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/http_writer.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/locks.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/log.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/multipart.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/payload.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/payload_streamer.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/pytest_plugin.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/resolver.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/streams.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/tcp_helpers.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/test_utils.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/tracing.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/typedefs.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/web.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/web_app.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/web_exceptions.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/web_fileresponse.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/web_log.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/web_middlewares.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/web_protocol.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/web_request.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/web_response.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/web_routedef.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/web_runner.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/web_server.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/web_urldispatcher.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/aiohttp/web_ws.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/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 1ms\nPrepared 1 package in 0.21ms\nInstalled 1 package in 22ms\n + pip==24.3.1\nResolved 2 packages in 8ms\nInstalled 2 packages in 10ms\n + cython==3.0.10\n + multidict==6.0.5\nResolved 96 packages in 47ms\nUninstalled 1 package in 4ms\nInstalled 95 packages in 662ms\n + aiodns==3.2.0\n + aiohappyeyeballs==2.3.4\n + aiohttp-theme==0.1.7\n + aioredis==2.0.1\n + aiosignal==1.3.1\n + alabaster==0.7.13\n + annotated-types==0.7.0\n + async-timeout==4.0.3\n + attrs==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.9.2\n + pydantic-core==2.23.4\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==2024.9.11\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.12.2\n + uritemplate==4.1.1\n + urllib3==2.0.4\n + uvloop==0.21.0b1\n + virtualenv==20.24.2\n + wait-for-it==2.2.2\n + webcolors==1.13\n + wheel==0.41.0\n + yarl==1.13.0\n + zipp==3.17.0\nResolved 9 packages in 1.67s\nPrepared 1 package in 16.43s\nInstalled 1 package in 0.55ms\n + aiohttp==3.10.9.dev0 (from file:///home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd)\nResolved 24 packages in 14ms\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.0\n",
    "new_commit_res_code": 1,
    "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_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/.venv/bin/python\ncachedir: .pytest_cache\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd\nconfigfile: setup.cfg\nplugins: cov-5.0.0, asyncio-0.25.0, mock-3.14.0\nasyncio: mode=strict, asyncio_default_fixture_loop_scope=None\ncollecting ... collected 142 items\n\nr2e_tests/test_1.py::test_method1[pyloop] PASSED                         [  0%]\nr2e_tests/test_1.py::test_method2[pyloop] PASSED                         [  1%]\nr2e_tests/test_1.py::test_method3[pyloop] PASSED                         [  2%]\nr2e_tests/test_1.py::test_method_invalid[pyloop] PASSED                  [  2%]\nr2e_tests/test_1.py::test_version_1_0[pyloop] PASSED                     [  3%]\nr2e_tests/test_1.py::test_version_default[pyloop] PASSED                 [  4%]\nr2e_tests/test_1.py::test_request_info[pyloop] PASSED                    [  4%]\nr2e_tests/test_1.py::test_request_info_with_fragment[pyloop] PASSED      [  5%]\nr2e_tests/test_1.py::test_version_err[pyloop] PASSED                     [  6%]\nr2e_tests/test_1.py::test_keep_alive[pyloop] PASSED                      [  7%]\nr2e_tests/test_1.py::test_host_port_default_http[pyloop] PASSED          [  7%]\nr2e_tests/test_1.py::test_host_port_default_https[pyloop] PASSED         [  8%]\nr2e_tests/test_1.py::test_host_port_nondefault_http[pyloop] PASSED       [  9%]\nr2e_tests/test_1.py::test_host_port_nondefault_https[pyloop] PASSED      [  9%]\nr2e_tests/test_1.py::test_host_port_default_ws[pyloop] PASSED            [ 10%]\nr2e_tests/test_1.py::test_host_port_default_wss[pyloop] PASSED           [ 11%]\nr2e_tests/test_1.py::test_host_port_nondefault_ws[pyloop] PASSED         [ 11%]\nr2e_tests/test_1.py::test_host_port_nondefault_wss[pyloop] PASSED        [ 12%]\nr2e_tests/test_1.py::test_host_port_none_port[pyloop] PASSED             [ 13%]\nr2e_tests/test_1.py::test_host_port_err[pyloop] PASSED                   [ 14%]\nr2e_tests/test_1.py::test_hostname_err[pyloop] PASSED                    [ 14%]\nr2e_tests/test_1.py::test_host_header_host_first[pyloop] PASSED          [ 15%]\nr2e_tests/test_1.py::test_host_header_host_without_port[pyloop] PASSED   [ 16%]\nr2e_tests/test_1.py::test_host_header_host_with_default_port[pyloop] PASSED [ 16%]\nr2e_tests/test_1.py::test_host_header_host_with_nondefault_port[pyloop] PASSED [ 17%]\nr2e_tests/test_1.py::test_host_header_host_idna_encode[pyloop] PASSED    [ 18%]\nr2e_tests/test_1.py::test_host_header_host_unicode[pyloop] PASSED        [ 19%]\nr2e_tests/test_1.py::test_host_header_explicit_host[pyloop] PASSED       [ 19%]\nr2e_tests/test_1.py::test_host_header_explicit_host_with_port[pyloop] PASSED [ 20%]\nr2e_tests/test_1.py::test_host_header_ipv4[pyloop] PASSED                [ 21%]\nr2e_tests/test_1.py::test_host_header_ipv6[pyloop-True] PASSED           [ 21%]\nr2e_tests/test_1.py::test_host_header_ipv6[pyloop-False] PASSED          [ 22%]\nr2e_tests/test_1.py::test_host_header_ipv4_with_port[pyloop] PASSED      [ 23%]\nr2e_tests/test_1.py::test_host_header_ipv6_with_port[pyloop] PASSED      [ 23%]\nr2e_tests/test_1.py::test_default_loop[pyloop] PASSED                    [ 24%]\nr2e_tests/test_1.py::test_host_header_fqdn[pyloop-dot only at the end] PASSED [ 25%]\nr2e_tests/test_1.py::test_host_header_fqdn[pyloop-single dot] PASSED     [ 26%]\nr2e_tests/test_1.py::test_host_header_fqdn[pyloop-single dot with port] PASSED [ 26%]\nr2e_tests/test_1.py::test_host_header_fqdn[pyloop-multiple dots with port] PASSED [ 27%]\nr2e_tests/test_1.py::test_host_header_fqdn[pyloop-explicit host header] PASSED [ 28%]\nr2e_tests/test_1.py::test_host_header_fqdn[pyloop-https] PASSED          [ 28%]\nr2e_tests/test_1.py::test_host_header_fqdn[pyloop-only dots] PASSED      [ 29%]\nr2e_tests/test_1.py::test_host_header_fqdn[pyloop-single dot with port idna] PASSED [ 30%]\nr2e_tests/test_1.py::test_default_headers_useragent[pyloop] PASSED       [ 30%]\nr2e_tests/test_1.py::test_default_headers_useragent_custom[pyloop] PASSED [ 31%]\nr2e_tests/test_1.py::test_skip_default_useragent_header[pyloop] PASSED   [ 32%]\nr2e_tests/test_1.py::test_headers[pyloop] PASSED                         [ 33%]\nr2e_tests/test_1.py::test_headers_list[pyloop] PASSED                    [ 33%]\nr2e_tests/test_1.py::test_headers_default[pyloop] PASSED                 [ 34%]\nr2e_tests/test_1.py::test_invalid_url[pyloop] PASSED                     [ 35%]\nr2e_tests/test_1.py::test_no_path[pyloop] PASSED                         [ 35%]\nr2e_tests/test_1.py::test_ipv6_default_http_port[pyloop] PASSED          [ 36%]\nr2e_tests/test_1.py::test_ipv6_default_https_port[pyloop] PASSED         [ 37%]\nr2e_tests/test_1.py::test_ipv6_nondefault_http_port[pyloop] PASSED       [ 38%]\nr2e_tests/test_1.py::test_ipv6_nondefault_https_port[pyloop] PASSED      [ 38%]\nr2e_tests/test_1.py::test_basic_auth[pyloop] PASSED                      [ 39%]\nr2e_tests/test_1.py::test_basic_auth_utf8[pyloop] PASSED                 [ 40%]\nr2e_tests/test_1.py::test_basic_auth_tuple_forbidden[pyloop] PASSED      [ 40%]\nr2e_tests/test_1.py::test_basic_auth_from_url[pyloop] PASSED             [ 41%]\nr2e_tests/test_1.py::test_basic_auth_no_user_from_url[pyloop] PASSED     [ 42%]\nr2e_tests/test_1.py::test_basic_auth_from_url_overridden[pyloop] PASSED  [ 42%]\nr2e_tests/test_1.py::test_path_is_not_double_encoded1[pyloop] PASSED     [ 43%]\nr2e_tests/test_1.py::test_path_is_not_double_encoded2[pyloop] PASSED     [ 44%]\nr2e_tests/test_1.py::test_path_is_not_double_encoded3[pyloop] PASSED     [ 45%]\nr2e_tests/test_1.py::test_path_safe_chars_preserved[pyloop] PASSED       [ 45%]\nr2e_tests/test_1.py::test_params_are_added_before_fragment1[pyloop] PASSED [ 46%]\nr2e_tests/test_1.py::test_params_are_added_before_fragment2[pyloop] PASSED [ 47%]\nr2e_tests/test_1.py::test_path_not_contain_fragment1[pyloop] PASSED      [ 47%]\nr2e_tests/test_1.py::test_path_not_contain_fragment2[pyloop] PASSED      [ 48%]\nr2e_tests/test_1.py::test_cookies[pyloop] PASSED                         [ 49%]\nr2e_tests/test_1.py::test_cookies_is_quoted_with_special_characters[pyloop] PASSED [ 50%]\nr2e_tests/test_1.py::test_cookies_merge_with_headers[pyloop] PASSED      [ 50%]\nr2e_tests/test_1.py::test_unicode_get1[pyloop] PASSED                    [ 51%]\nr2e_tests/test_1.py::test_unicode_get2[pyloop] PASSED                    [ 52%]\nr2e_tests/test_1.py::test_unicode_get3[pyloop] PASSED                    [ 52%]\nr2e_tests/test_1.py::test_unicode_get4[pyloop] PASSED                    [ 53%]\nr2e_tests/test_1.py::test_query_multivalued_param[pyloop] PASSED         [ 54%]\nr2e_tests/test_1.py::test_query_str_param[pyloop] PASSED                 [ 54%]\nr2e_tests/test_1.py::test_query_bytes_param_raises[pyloop] PASSED        [ 55%]\nr2e_tests/test_1.py::test_query_str_param_is_not_encoded[pyloop] PASSED  [ 56%]\nr2e_tests/test_1.py::test_params_update_path_and_url[pyloop] PASSED      [ 57%]\nr2e_tests/test_1.py::test_params_empty_path_and_url[pyloop] PASSED       [ 57%]\nr2e_tests/test_1.py::test_gen_netloc_all[pyloop] PASSED                  [ 58%]\nr2e_tests/test_1.py::test_gen_netloc_no_port[pyloop] PASSED              [ 59%]\nr2e_tests/test_1.py::test_connection_header[pyloop] PASSED               [ 59%]\nr2e_tests/test_1.py::test_no_content_length[pyloop] PASSED               [ 60%]\nr2e_tests/test_1.py::test_no_content_length_head[pyloop] PASSED          [ 61%]\nr2e_tests/test_1.py::test_content_type_auto_header_get[pyloop] PASSED    [ 61%]\nr2e_tests/test_1.py::test_content_type_auto_header_form[pyloop] PASSED   [ 62%]\nr2e_tests/test_1.py::test_content_type_auto_header_bytes[pyloop] PASSED  [ 63%]\nr2e_tests/test_1.py::test_content_type_skip_auto_header_bytes[pyloop] PASSED [ 64%]\nr2e_tests/test_1.py::test_content_type_skip_auto_header_form[pyloop] PASSED [ 64%]\nr2e_tests/test_1.py::test_content_type_auto_header_content_length_no_skip[pyloop] PASSED [ 65%]\nr2e_tests/test_1.py::test_urlencoded_formdata_charset[pyloop] PASSED     [ 66%]\nr2e_tests/test_1.py::test_post_data[pyloop] PASSED                       [ 66%]\nr2e_tests/test_1.py::test_pass_falsy_data[pyloop] PASSED                 [ 67%]\nr2e_tests/test_1.py::test_pass_falsy_data_file[pyloop] PASSED            [ 68%]\nr2e_tests/test_1.py::test_get_with_data[pyloop] PASSED                   [ 69%]\nr2e_tests/test_1.py::test_bytes_data[pyloop] PASSED                      [ 69%]\nr2e_tests/test_1.py::test_content_encoding[pyloop] PASSED                [ 70%]\nr2e_tests/test_1.py::test_content_encoding_dont_set_headers_if_no_body[pyloop] PASSED [ 71%]\nr2e_tests/test_1.py::test_content_encoding_header[pyloop] PASSED         [ 71%]\nr2e_tests/test_1.py::test_compress_and_content_encoding[pyloop] PASSED   [ 72%]\nr2e_tests/test_1.py::test_chunked[pyloop] PASSED                         [ 73%]\nr2e_tests/test_1.py::test_chunked2[pyloop] PASSED                        [ 73%]\nr2e_tests/test_1.py::test_chunked_explicit[pyloop] PASSED                [ 74%]\nr2e_tests/test_1.py::test_chunked_length[pyloop] PASSED                  [ 75%]\nr2e_tests/test_1.py::test_chunked_transfer_encoding[pyloop] PASSED       [ 76%]\nr2e_tests/test_1.py::test_file_upload_not_chunked[pyloop] FAILED         [ 76%]\nr2e_tests/test_1.py::test_precompressed_data_stays_intact[pyloop] PASSED [ 77%]\nr2e_tests/test_1.py::test_file_upload_not_chunked_seek[pyloop] FAILED    [ 78%]\nr2e_tests/test_1.py::test_file_upload_force_chunked[pyloop] FAILED       [ 78%]\nr2e_tests/test_1.py::test_expect100[pyloop] PASSED                       [ 79%]\nr2e_tests/test_1.py::test_expect_100_continue_header[pyloop] PASSED      [ 80%]\nr2e_tests/test_1.py::test_data_stream[pyloop] PASSED                     [ 80%]\nr2e_tests/test_1.py::test_data_stream_deprecated[pyloop] PASSED          [ 81%]\nr2e_tests/test_1.py::test_data_file[pyloop] PASSED                       [ 82%]\nr2e_tests/test_1.py::test_data_stream_exc[pyloop] PASSED                 [ 83%]\nr2e_tests/test_1.py::test_data_stream_exc_chain[pyloop] PASSED           [ 83%]\nr2e_tests/test_1.py::test_data_stream_continue[pyloop] PASSED            [ 84%]\nr2e_tests/test_1.py::test_data_continue[pyloop] PASSED                   [ 85%]\nr2e_tests/test_1.py::test_close[pyloop] PASSED                           [ 85%]\nr2e_tests/test_1.py::test_bad_version[pyloop] PASSED                     [ 86%]\nr2e_tests/test_1.py::test_custom_response_class[pyloop] PASSED           [ 87%]\nr2e_tests/test_1.py::test_oserror_on_write_bytes[pyloop] PASSED          [ 88%]\nr2e_tests/test_1.py::test_cancel_close[pyloop] SKIPPED (Needs Task.c...) [ 88%]\nr2e_tests/test_1.py::test_terminate[pyloop] PASSED                       [ 89%]\nr2e_tests/test_1.py::test_terminate_with_closed_loop[pyloop] PASSED      [ 90%]\nr2e_tests/test_1.py::test_terminate_without_writer[pyloop] PASSED        [ 90%]\nr2e_tests/test_1.py::test_custom_req_rep[pyloop] PASSED                  [ 91%]\nr2e_tests/test_1.py::test_verify_ssl_false_with_ssl_context[pyloop] PASSED [ 92%]\nr2e_tests/test_1.py::test_bad_fingerprint[pyloop] PASSED                 [ 92%]\nr2e_tests/test_1.py::test_insecure_fingerprint_md5[pyloop] PASSED        [ 93%]\nr2e_tests/test_1.py::test_insecure_fingerprint_sha1[pyloop] PASSED       [ 94%]\nr2e_tests/test_1.py::test_loose_cookies_types[pyloop] PASSED             [ 95%]\nr2e_tests/test_1.py::test_gen_default_accept_encoding[False-gzip, deflate] PASSED [ 95%]\nr2e_tests/test_1.py::test_gen_default_accept_encoding[True-gzip, deflate, br] PASSED [ 96%]\nr2e_tests/test_1.py::test_basicauth_from_netrc_present[pyloop-machine example.com login username password pass\\n-expected_auth0] PASSED [ 97%]\nr2e_tests/test_1.py::test_basicauth_from_netrc_present_untrusted_env[pyloop-machine example.com login username password pass\\n] PASSED [ 97%]\nr2e_tests/test_1.py::test_basicauth_from_empty_netrc[pyloop-] PASSED     [ 98%]\nr2e_tests/test_1.py::test_connection_key_with_proxy PASSED               [ 99%]\nr2e_tests/test_1.py::test_connection_key_without_proxy PASSED            [100%]\n\n=================================== FAILURES ===================================\n_____________________ test_file_upload_not_chunked[pyloop] _____________________\n\nloop = <_UnixSelectorEventLoop running=False closed=False debug=False>\n\n    async def test_file_upload_not_chunked(loop) -> None:\n        file_path = pathlib.Path(__file__).parent / \"aiohttp.png\"\n>       with file_path.open(\"rb\") as f:\n\nfile_path  = PosixPath('/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png')\nloop       = <_UnixSelectorEventLoop running=False closed=False debug=False>\n\nr2e_tests/test_1.py:941: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n../../../../.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/pathlib.py:1252: in open\n    return io.open(self, mode, buffering, encoding, errors, newline,\n        buffering  = -1\n        encoding   = None\n        errors     = None\n        mode       = 'rb'\n        newline    = None\n        self       = PosixPath('/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png')\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = PosixPath('/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png')\nname = '/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png'\nflags = 524288, mode = 438\n\n    def _opener(self, name, flags, mode=0o666):\n        # A stub for the opener argument to built-in open()\n>       return self._accessor.open(self, flags, mode)\nE       FileNotFoundError: [Errno 2] No such file or directory: '/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png'\n\nflags      = 524288\nmode       = 438\nname       = '/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png'\nself       = PosixPath('/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png')\n\n../../../../.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/pathlib.py:1120: FileNotFoundError\n__________________ test_file_upload_not_chunked_seek[pyloop] ___________________\n\nloop = <_UnixSelectorEventLoop running=False closed=False debug=False>\n\n    async def test_file_upload_not_chunked_seek(loop) -> None:\n        file_path = pathlib.Path(__file__).parent / \"aiohttp.png\"\n>       with file_path.open(\"rb\") as f:\n\nfile_path  = PosixPath('/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png')\nloop       = <_UnixSelectorEventLoop running=False closed=False debug=False>\n\nr2e_tests/test_1.py:966: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n../../../../.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/pathlib.py:1252: in open\n    return io.open(self, mode, buffering, encoding, errors, newline,\n        buffering  = -1\n        encoding   = None\n        errors     = None\n        mode       = 'rb'\n        newline    = None\n        self       = PosixPath('/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png')\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = PosixPath('/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png')\nname = '/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png'\nflags = 524288, mode = 438\n\n    def _opener(self, name, flags, mode=0o666):\n        # A stub for the opener argument to built-in open()\n>       return self._accessor.open(self, flags, mode)\nE       FileNotFoundError: [Errno 2] No such file or directory: '/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png'\n\nflags      = 524288\nmode       = 438\nname       = '/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png'\nself       = PosixPath('/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png')\n\n../../../../.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/pathlib.py:1120: FileNotFoundError\n____________________ test_file_upload_force_chunked[pyloop] ____________________\n\nloop = <_UnixSelectorEventLoop running=False closed=False debug=False>\n\n    async def test_file_upload_force_chunked(loop) -> None:\n        file_path = pathlib.Path(__file__).parent / \"aiohttp.png\"\n>       with file_path.open(\"rb\") as f:\n\nfile_path  = PosixPath('/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png')\nloop       = <_UnixSelectorEventLoop running=False closed=False debug=False>\n\nr2e_tests/test_1.py:975: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n../../../../.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/pathlib.py:1252: in open\n    return io.open(self, mode, buffering, encoding, errors, newline,\n        buffering  = -1\n        encoding   = None\n        errors     = None\n        mode       = 'rb'\n        newline    = None\n        self       = PosixPath('/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png')\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = PosixPath('/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png')\nname = '/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png'\nflags = 524288, mode = 438\n\n    def _opener(self, name, flags, mode=0o666):\n        # A stub for the opener argument to built-in open()\n>       return self._accessor.open(self, flags, mode)\nE       FileNotFoundError: [Errno 2] No such file or directory: '/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png'\n\nflags      = 524288\nmode       = 438\nname       = '/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png'\nself       = PosixPath('/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png')\n\n../../../../.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/pathlib.py:1120: FileNotFoundError\n==================================== PASSES ====================================\n\n---------- coverage: platform linux, python 3.9.21-final-0 -----------\nName                                     Stmts   Miss Branch BrPart  Cover\n--------------------------------------------------------------------------\naiohttp/__init__.py                         27      8      2      1    69%\naiohttp/abc.py                              97      7      0      0    93%\naiohttp/base_protocol.py                    68     51     22      0    19%\naiohttp/client.py                          541    263    196     51    45%\naiohttp/client_exceptions.py               154     65     20      1    52%\naiohttp/client_proto.py                    166    132     56      0    15%\naiohttp/client_reqrep.py                   716    202    312     31    69%\naiohttp/client_ws.py                       264    214     80      1    15%\naiohttp/compression_utils.py                70     36     14      0    40%\naiohttp/connector.py                       765    514    327     32    26%\naiohttp/cookiejar.py                       274    195    130      6    21%\naiohttp/formdata.py                         97     42     46     12    51%\naiohttp/hdrs.py                             90      0      0      0   100%\naiohttp/helpers.py                         509    267    184     24    41%\naiohttp/http.py                             11      0      2      0   100%\naiohttp/http_exceptions.py                  50     20      4      0    56%\naiohttp/http_parser.py                     508    408    210      1    14%\naiohttp/http_websocket.py                  394    287    152      0    20%\naiohttp/http_writer.py                     119     38     50     13    60%\naiohttp/locks.py                            24     16      4      0    29%\naiohttp/log.py                               7      0      0      0   100%\naiohttp/multipart.py                       623    498    266      2    15%\naiohttp/payload.py                         237     49     58     12    74%\naiohttp/payload_streamer.py                 31      3      4      0    91%\naiohttp/pytest_plugin.py                   163     76     42      4    51%\naiohttp/resolver.py                         81     58     26      0    21%\naiohttp/streams.py                         398    315    146      0    15%\naiohttp/tcp_helpers.py                      19     11      6      0    32%\naiohttp/test_utils.py                      318    192     52      4    36%\naiohttp/tracing.py                         191     69     32      0    69%\naiohttp/typedefs.py                         24      0      0      0   100%\naiohttp/web.py                             122     84     52      0    23%\naiohttp/web_app.py                         292    196     82      0    26%\naiohttp/web_exceptions.py                  157     25      8      0    80%\naiohttp/web_fileresponse.py                163    127     54      1    19%\naiohttp/web_log.py                         102     58     20      0    36%\naiohttp/web_middlewares.py                  59     46     22      0    16%\naiohttp/web_protocol.py                    367    306    158      0    12%\naiohttp/web_request.py                     445    294    140      1    27%\naiohttp/web_response.py                    482    365    226      0    17%\naiohttp/web_routedef.py                    100     44     10      0    55%\naiohttp/web_runner.py                      213    130     36      0    33%\naiohttp/web_server.py                       42     24     12      0    33%\naiohttp/web_urldispatcher.py               740    474    163      0    29%\naiohttp/web_ws.py                          382    310    132      1    15%\naiohttp/worker.py                          126    126     30      0     0%\ntests/conftest.py                          131    131     16      0     0%\ntests/test_base_protocol.py                198    198      2      0     0%\ntests/test_circular_imports.py              29     29     13      0     0%\ntests/test_classbasedview.py                39     39      0      0     0%\ntests/test_client_connection.py             94     94      2      0     0%\ntests/test_client_exceptions.py            199    199     14      0     0%\ntests/test_client_fingerprint.py            59     59      0      0     0%\ntests/test_client_functional.py           2523   2523     86      0     0%\ntests/test_client_proto.py                  99     99      0      0     0%\ntests/test_client_request.py               829    829     18      0     0%\ntests/test_client_response.py              480    480      6      0     0%\ntests/test_client_session.py               566    566     29      0     0%\ntests/test_client_ws.py                    486    486      2      0     0%\ntests/test_client_ws_functional.py         750    750     32      0     0%\ntests/test_connector.py                   1700   1700     88      0     0%\ntests/test_cookiejar.py                    461    461     32      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                      509    509     24      0     0%\ntests/test_http_exceptions.py              109    109     10      0     0%\ntests/test_http_parser.py                 1092   1092     66      0     0%\ntests/test_http_writer.py                  182    182     10      0     0%\ntests/test_imports.py                       34     34      6      0     0%\ntests/test_locks.py                         39     39      0      0     0%\ntests/test_loop.py                          36     36      0      0     0%\ntests/test_multipart.py                    826    826     32      0     0%\ntests/test_multipart_helpers.py            446    446      0      0     0%\ntests/test_payload.py                       95     95      0      0     0%\ntests/test_proxy.py                        302    302      0      0     0%\ntests/test_proxy_functional.py             461    461     18      0     0%\ntests/test_pytest_plugin.py                 27     27      0      0     0%\ntests/test_resolver.py                     199    199     20      0     0%\ntests/test_route_def.py                    210    210      0      0     0%\ntests/test_run_app.py                      563    563     30      0     0%\ntests/test_streams.py                     1077   1077     38      0     0%\ntests/test_tcp_helpers.py                   52     52      2      0     0%\ntests/test_test_utils.py                   251    251      6      0     0%\ntests/test_tracing.py                       48     48      0      0     0%\ntests/test_urldispatch.py                  859    859     24      0     0%\ntests/test_web_app.py                      454    454      6      0     0%\ntests/test_web_cli.py                       75     75      0      0     0%\ntests/test_web_exceptions.py               179    179     22      0     0%\ntests/test_web_functional.py              1605   1605     36      0     0%\ntests/test_web_log.py                      116    116      2      0     0%\ntests/test_web_middleware.py               268    268     16      0     0%\ntests/test_web_request.py                  513    513      8      0     0%\ntests/test_web_request_handler.py           42     42      0      0     0%\ntests/test_web_response.py                 904    904      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      673    673     18      0     0%\ntests/test_web_server.py                   162    162      0      0     0%\ntests/test_web_urldispatcher.py            524    524     24      0     0%\ntests/test_web_websocket.py                401    401      8      0     0%\ntests/test_web_websocket_functional.py     799    799     28      0     0%\ntests/test_websocket_handshake.py          152    152     12      0     0%\ntests/test_websocket_parser.py             300    300     12      0     0%\ntests/test_websocket_writer.py              95     95      6      0     0%\ntests/test_worker.py                       191    191      2      0     0%\n--------------------------------------------------------------------------\nTOTAL                                    34757  30574   4430    198    12%\n\n============================= slowest 10 durations =============================\n0.05s call     r2e_tests/test_1.py::test_host_header_host_unicode[pyloop]\n0.05s call     r2e_tests/test_1.py::test_terminate_with_closed_loop[pyloop]\n0.03s teardown r2e_tests/test_1.py::test_chunked[pyloop]\n0.03s teardown r2e_tests/test_1.py::test_chunked2[pyloop]\n0.02s teardown r2e_tests/test_1.py::test_urlencoded_formdata_charset[pyloop]\n0.02s teardown r2e_tests/test_1.py::test_content_encoding[pyloop]\n0.02s teardown r2e_tests/test_1.py::test_content_encoding_dont_set_headers_if_no_body[pyloop]\n0.02s teardown r2e_tests/test_1.py::test_post_data[pyloop]\n0.02s teardown r2e_tests/test_1.py::test_bytes_data[pyloop]\n0.02s teardown r2e_tests/test_1.py::test_pass_falsy_data_file[pyloop]\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::test_method1[pyloop]\nPASSED r2e_tests/test_1.py::test_method2[pyloop]\nPASSED r2e_tests/test_1.py::test_method3[pyloop]\nPASSED r2e_tests/test_1.py::test_method_invalid[pyloop]\nPASSED r2e_tests/test_1.py::test_version_1_0[pyloop]\nPASSED r2e_tests/test_1.py::test_version_default[pyloop]\nPASSED r2e_tests/test_1.py::test_request_info[pyloop]\nPASSED r2e_tests/test_1.py::test_request_info_with_fragment[pyloop]\nPASSED r2e_tests/test_1.py::test_version_err[pyloop]\nPASSED r2e_tests/test_1.py::test_keep_alive[pyloop]\nPASSED r2e_tests/test_1.py::test_host_port_default_http[pyloop]\nPASSED r2e_tests/test_1.py::test_host_port_default_https[pyloop]\nPASSED r2e_tests/test_1.py::test_host_port_nondefault_http[pyloop]\nPASSED r2e_tests/test_1.py::test_host_port_nondefault_https[pyloop]\nPASSED r2e_tests/test_1.py::test_host_port_default_ws[pyloop]\nPASSED r2e_tests/test_1.py::test_host_port_default_wss[pyloop]\nPASSED r2e_tests/test_1.py::test_host_port_nondefault_ws[pyloop]\nPASSED r2e_tests/test_1.py::test_host_port_nondefault_wss[pyloop]\nPASSED r2e_tests/test_1.py::test_host_port_none_port[pyloop]\nPASSED r2e_tests/test_1.py::test_host_port_err[pyloop]\nPASSED r2e_tests/test_1.py::test_hostname_err[pyloop]\nPASSED r2e_tests/test_1.py::test_host_header_host_first[pyloop]\nPASSED r2e_tests/test_1.py::test_host_header_host_without_port[pyloop]\nPASSED r2e_tests/test_1.py::test_host_header_host_with_default_port[pyloop]\nPASSED r2e_tests/test_1.py::test_host_header_host_with_nondefault_port[pyloop]\nPASSED r2e_tests/test_1.py::test_host_header_host_idna_encode[pyloop]\nPASSED r2e_tests/test_1.py::test_host_header_host_unicode[pyloop]\nPASSED r2e_tests/test_1.py::test_host_header_explicit_host[pyloop]\nPASSED r2e_tests/test_1.py::test_host_header_explicit_host_with_port[pyloop]\nPASSED r2e_tests/test_1.py::test_host_header_ipv4[pyloop]\nPASSED r2e_tests/test_1.py::test_host_header_ipv6[pyloop-True]\nPASSED r2e_tests/test_1.py::test_host_header_ipv6[pyloop-False]\nPASSED r2e_tests/test_1.py::test_host_header_ipv4_with_port[pyloop]\nPASSED r2e_tests/test_1.py::test_host_header_ipv6_with_port[pyloop]\nPASSED r2e_tests/test_1.py::test_default_loop[pyloop]\nPASSED r2e_tests/test_1.py::test_host_header_fqdn[pyloop-dot only at the end]\nPASSED r2e_tests/test_1.py::test_host_header_fqdn[pyloop-single dot]\nPASSED r2e_tests/test_1.py::test_host_header_fqdn[pyloop-single dot with port]\nPASSED r2e_tests/test_1.py::test_host_header_fqdn[pyloop-multiple dots with port]\nPASSED r2e_tests/test_1.py::test_host_header_fqdn[pyloop-explicit host header]\nPASSED r2e_tests/test_1.py::test_host_header_fqdn[pyloop-https]\nPASSED r2e_tests/test_1.py::test_host_header_fqdn[pyloop-only dots]\nPASSED r2e_tests/test_1.py::test_host_header_fqdn[pyloop-single dot with port idna]\nPASSED r2e_tests/test_1.py::test_default_headers_useragent[pyloop]\nPASSED r2e_tests/test_1.py::test_default_headers_useragent_custom[pyloop]\nPASSED r2e_tests/test_1.py::test_skip_default_useragent_header[pyloop]\nPASSED r2e_tests/test_1.py::test_headers[pyloop]\nPASSED r2e_tests/test_1.py::test_headers_list[pyloop]\nPASSED r2e_tests/test_1.py::test_headers_default[pyloop]\nPASSED r2e_tests/test_1.py::test_invalid_url[pyloop]\nPASSED r2e_tests/test_1.py::test_no_path[pyloop]\nPASSED r2e_tests/test_1.py::test_ipv6_default_http_port[pyloop]\nPASSED r2e_tests/test_1.py::test_ipv6_default_https_port[pyloop]\nPASSED r2e_tests/test_1.py::test_ipv6_nondefault_http_port[pyloop]\nPASSED r2e_tests/test_1.py::test_ipv6_nondefault_https_port[pyloop]\nPASSED r2e_tests/test_1.py::test_basic_auth[pyloop]\nPASSED r2e_tests/test_1.py::test_basic_auth_utf8[pyloop]\nPASSED r2e_tests/test_1.py::test_basic_auth_tuple_forbidden[pyloop]\nPASSED r2e_tests/test_1.py::test_basic_auth_from_url[pyloop]\nPASSED r2e_tests/test_1.py::test_basic_auth_no_user_from_url[pyloop]\nPASSED r2e_tests/test_1.py::test_basic_auth_from_url_overridden[pyloop]\nPASSED r2e_tests/test_1.py::test_path_is_not_double_encoded1[pyloop]\nPASSED r2e_tests/test_1.py::test_path_is_not_double_encoded2[pyloop]\nPASSED r2e_tests/test_1.py::test_path_is_not_double_encoded3[pyloop]\nPASSED r2e_tests/test_1.py::test_path_safe_chars_preserved[pyloop]\nPASSED r2e_tests/test_1.py::test_params_are_added_before_fragment1[pyloop]\nPASSED r2e_tests/test_1.py::test_params_are_added_before_fragment2[pyloop]\nPASSED r2e_tests/test_1.py::test_path_not_contain_fragment1[pyloop]\nPASSED r2e_tests/test_1.py::test_path_not_contain_fragment2[pyloop]\nPASSED r2e_tests/test_1.py::test_cookies[pyloop]\nPASSED r2e_tests/test_1.py::test_cookies_is_quoted_with_special_characters[pyloop]\nPASSED r2e_tests/test_1.py::test_cookies_merge_with_headers[pyloop]\nPASSED r2e_tests/test_1.py::test_unicode_get1[pyloop]\nPASSED r2e_tests/test_1.py::test_unicode_get2[pyloop]\nPASSED r2e_tests/test_1.py::test_unicode_get3[pyloop]\nPASSED r2e_tests/test_1.py::test_unicode_get4[pyloop]\nPASSED r2e_tests/test_1.py::test_query_multivalued_param[pyloop]\nPASSED r2e_tests/test_1.py::test_query_str_param[pyloop]\nPASSED r2e_tests/test_1.py::test_query_bytes_param_raises[pyloop]\nPASSED r2e_tests/test_1.py::test_query_str_param_is_not_encoded[pyloop]\nPASSED r2e_tests/test_1.py::test_params_update_path_and_url[pyloop]\nPASSED r2e_tests/test_1.py::test_params_empty_path_and_url[pyloop]\nPASSED r2e_tests/test_1.py::test_gen_netloc_all[pyloop]\nPASSED r2e_tests/test_1.py::test_gen_netloc_no_port[pyloop]\nPASSED r2e_tests/test_1.py::test_connection_header[pyloop]\nPASSED r2e_tests/test_1.py::test_no_content_length[pyloop]\nPASSED r2e_tests/test_1.py::test_no_content_length_head[pyloop]\nPASSED r2e_tests/test_1.py::test_content_type_auto_header_get[pyloop]\nPASSED r2e_tests/test_1.py::test_content_type_auto_header_form[pyloop]\nPASSED r2e_tests/test_1.py::test_content_type_auto_header_bytes[pyloop]\nPASSED r2e_tests/test_1.py::test_content_type_skip_auto_header_bytes[pyloop]\nPASSED r2e_tests/test_1.py::test_content_type_skip_auto_header_form[pyloop]\nPASSED r2e_tests/test_1.py::test_content_type_auto_header_content_length_no_skip[pyloop]\nPASSED r2e_tests/test_1.py::test_urlencoded_formdata_charset[pyloop]\nPASSED r2e_tests/test_1.py::test_post_data[pyloop]\nPASSED r2e_tests/test_1.py::test_pass_falsy_data[pyloop]\nPASSED r2e_tests/test_1.py::test_pass_falsy_data_file[pyloop]\nPASSED r2e_tests/test_1.py::test_get_with_data[pyloop]\nPASSED r2e_tests/test_1.py::test_bytes_data[pyloop]\nPASSED r2e_tests/test_1.py::test_content_encoding[pyloop]\nPASSED r2e_tests/test_1.py::test_content_encoding_dont_set_headers_if_no_body[pyloop]\nPASSED r2e_tests/test_1.py::test_content_encoding_header[pyloop]\nPASSED r2e_tests/test_1.py::test_compress_and_content_encoding[pyloop]\nPASSED r2e_tests/test_1.py::test_chunked[pyloop]\nPASSED r2e_tests/test_1.py::test_chunked2[pyloop]\nPASSED r2e_tests/test_1.py::test_chunked_explicit[pyloop]\nPASSED r2e_tests/test_1.py::test_chunked_length[pyloop]\nPASSED r2e_tests/test_1.py::test_chunked_transfer_encoding[pyloop]\nPASSED r2e_tests/test_1.py::test_precompressed_data_stays_intact[pyloop]\nPASSED r2e_tests/test_1.py::test_expect100[pyloop]\nPASSED r2e_tests/test_1.py::test_expect_100_continue_header[pyloop]\nPASSED r2e_tests/test_1.py::test_data_stream[pyloop]\nPASSED r2e_tests/test_1.py::test_data_stream_deprecated[pyloop]\nPASSED r2e_tests/test_1.py::test_data_file[pyloop]\nPASSED r2e_tests/test_1.py::test_data_stream_exc[pyloop]\nPASSED r2e_tests/test_1.py::test_data_stream_exc_chain[pyloop]\nPASSED r2e_tests/test_1.py::test_data_stream_continue[pyloop]\nPASSED r2e_tests/test_1.py::test_data_continue[pyloop]\nPASSED r2e_tests/test_1.py::test_close[pyloop]\nPASSED r2e_tests/test_1.py::test_bad_version[pyloop]\nPASSED r2e_tests/test_1.py::test_custom_response_class[pyloop]\nPASSED r2e_tests/test_1.py::test_oserror_on_write_bytes[pyloop]\nPASSED r2e_tests/test_1.py::test_terminate[pyloop]\nPASSED r2e_tests/test_1.py::test_terminate_with_closed_loop[pyloop]\nPASSED r2e_tests/test_1.py::test_terminate_without_writer[pyloop]\nPASSED r2e_tests/test_1.py::test_custom_req_rep[pyloop]\nPASSED r2e_tests/test_1.py::test_verify_ssl_false_with_ssl_context[pyloop]\nPASSED r2e_tests/test_1.py::test_bad_fingerprint[pyloop]\nPASSED r2e_tests/test_1.py::test_insecure_fingerprint_md5[pyloop]\nPASSED r2e_tests/test_1.py::test_insecure_fingerprint_sha1[pyloop]\nPASSED r2e_tests/test_1.py::test_loose_cookies_types[pyloop]\nPASSED r2e_tests/test_1.py::test_gen_default_accept_encoding[False-gzip, deflate]\nPASSED r2e_tests/test_1.py::test_gen_default_accept_encoding[True-gzip, deflate, br]\nPASSED r2e_tests/test_1.py::test_basicauth_from_netrc_present[pyloop-machine example.com login username password pass\\n-expected_auth0]\nPASSED r2e_tests/test_1.py::test_basicauth_from_netrc_present_untrusted_env[pyloop-machine example.com login username password pass\\n]\nPASSED r2e_tests/test_1.py::test_basicauth_from_empty_netrc[pyloop-]\nPASSED r2e_tests/test_1.py::test_connection_key_with_proxy\nPASSED r2e_tests/test_1.py::test_connection_key_without_proxy\nSKIPPED [1] r2e_tests/test_1.py:1224: Needs Task.cancelling()\nFAILED r2e_tests/test_1.py::test_file_upload_not_chunked[pyloop] - FileNotFou...\nFAILED r2e_tests/test_1.py::test_file_upload_not_chunked_seek[pyloop] - FileN...\nFAILED r2e_tests/test_1.py::test_file_upload_force_chunked[pyloop] - FileNotF...\n=================== 3 failed, 138 passed, 1 skipped in 9.08s ===================\n",
    "new_commit_res_stderr": "/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/.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_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/.venv/bin/python\ncachedir: .pytest_cache\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd\nconfigfile: setup.cfg\nplugins: cov-5.0.0, asyncio-0.25.0, mock-3.14.0\nasyncio: mode=strict, asyncio_default_fixture_loop_scope=None\ncollecting ... collected 142 items\n\nr2e_tests/test_1.py::test_method1[pyloop] PASSED                         [  0%]\nr2e_tests/test_1.py::test_method2[pyloop] PASSED                         [  1%]\nr2e_tests/test_1.py::test_method3[pyloop] PASSED                         [  2%]\nr2e_tests/test_1.py::test_method_invalid[pyloop] PASSED                  [  2%]\nr2e_tests/test_1.py::test_version_1_0[pyloop] PASSED                     [  3%]\nr2e_tests/test_1.py::test_version_default[pyloop] PASSED                 [  4%]\nr2e_tests/test_1.py::test_request_info[pyloop] PASSED                    [  4%]\nr2e_tests/test_1.py::test_request_info_with_fragment[pyloop] PASSED      [  5%]\nr2e_tests/test_1.py::test_version_err[pyloop] PASSED                     [  6%]\nr2e_tests/test_1.py::test_keep_alive[pyloop] PASSED                      [  7%]\nr2e_tests/test_1.py::test_host_port_default_http[pyloop] PASSED          [  7%]\nr2e_tests/test_1.py::test_host_port_default_https[pyloop] PASSED         [  8%]\nr2e_tests/test_1.py::test_host_port_nondefault_http[pyloop] PASSED       [  9%]\nr2e_tests/test_1.py::test_host_port_nondefault_https[pyloop] PASSED      [  9%]\nr2e_tests/test_1.py::test_host_port_default_ws[pyloop] PASSED            [ 10%]\nr2e_tests/test_1.py::test_host_port_default_wss[pyloop] PASSED           [ 11%]\nr2e_tests/test_1.py::test_host_port_nondefault_ws[pyloop] PASSED         [ 11%]\nr2e_tests/test_1.py::test_host_port_nondefault_wss[pyloop] PASSED        [ 12%]\nr2e_tests/test_1.py::test_host_port_none_port[pyloop] PASSED             [ 13%]\nr2e_tests/test_1.py::test_host_port_err[pyloop] PASSED                   [ 14%]\nr2e_tests/test_1.py::test_hostname_err[pyloop] PASSED                    [ 14%]\nr2e_tests/test_1.py::test_host_header_host_first[pyloop] PASSED          [ 15%]\nr2e_tests/test_1.py::test_host_header_host_without_port[pyloop] PASSED   [ 16%]\nr2e_tests/test_1.py::test_host_header_host_with_default_port[pyloop] PASSED [ 16%]\nr2e_tests/test_1.py::test_host_header_host_with_nondefault_port[pyloop] PASSED [ 17%]\nr2e_tests/test_1.py::test_host_header_host_idna_encode[pyloop] PASSED    [ 18%]\nr2e_tests/test_1.py::test_host_header_host_unicode[pyloop] PASSED        [ 19%]\nr2e_tests/test_1.py::test_host_header_explicit_host[pyloop] PASSED       [ 19%]\nr2e_tests/test_1.py::test_host_header_explicit_host_with_port[pyloop] PASSED [ 20%]\nr2e_tests/test_1.py::test_host_header_ipv4[pyloop] PASSED                [ 21%]\nr2e_tests/test_1.py::test_host_header_ipv6[pyloop-True] PASSED           [ 21%]\nr2e_tests/test_1.py::test_host_header_ipv6[pyloop-False] PASSED          [ 22%]\nr2e_tests/test_1.py::test_host_header_ipv4_with_port[pyloop] PASSED      [ 23%]\nr2e_tests/test_1.py::test_host_header_ipv6_with_port[pyloop] PASSED      [ 23%]\nr2e_tests/test_1.py::test_default_loop[pyloop] PASSED                    [ 24%]\nr2e_tests/test_1.py::test_host_header_fqdn[pyloop-dot only at the end] PASSED [ 25%]\nr2e_tests/test_1.py::test_host_header_fqdn[pyloop-single dot] PASSED     [ 26%]\nr2e_tests/test_1.py::test_host_header_fqdn[pyloop-single dot with port] PASSED [ 26%]\nr2e_tests/test_1.py::test_host_header_fqdn[pyloop-multiple dots with port] PASSED [ 27%]\nr2e_tests/test_1.py::test_host_header_fqdn[pyloop-explicit host header] PASSED [ 28%]\nr2e_tests/test_1.py::test_host_header_fqdn[pyloop-https] PASSED          [ 28%]\nr2e_tests/test_1.py::test_host_header_fqdn[pyloop-only dots] PASSED      [ 29%]\nr2e_tests/test_1.py::test_host_header_fqdn[pyloop-single dot with port idna] PASSED [ 30%]\nr2e_tests/test_1.py::test_default_headers_useragent[pyloop] PASSED       [ 30%]\nr2e_tests/test_1.py::test_default_headers_useragent_custom[pyloop] PASSED [ 31%]\nr2e_tests/test_1.py::test_skip_default_useragent_header[pyloop] PASSED   [ 32%]\nr2e_tests/test_1.py::test_headers[pyloop] PASSED                         [ 33%]\nr2e_tests/test_1.py::test_headers_list[pyloop] PASSED                    [ 33%]\nr2e_tests/test_1.py::test_headers_default[pyloop] PASSED                 [ 34%]\nr2e_tests/test_1.py::test_invalid_url[pyloop] PASSED                     [ 35%]\nr2e_tests/test_1.py::test_no_path[pyloop] PASSED                         [ 35%]\nr2e_tests/test_1.py::test_ipv6_default_http_port[pyloop] PASSED          [ 36%]\nr2e_tests/test_1.py::test_ipv6_default_https_port[pyloop] PASSED         [ 37%]\nr2e_tests/test_1.py::test_ipv6_nondefault_http_port[pyloop] PASSED       [ 38%]\nr2e_tests/test_1.py::test_ipv6_nondefault_https_port[pyloop] PASSED      [ 38%]\nr2e_tests/test_1.py::test_basic_auth[pyloop] PASSED                      [ 39%]\nr2e_tests/test_1.py::test_basic_auth_utf8[pyloop] PASSED                 [ 40%]\nr2e_tests/test_1.py::test_basic_auth_tuple_forbidden[pyloop] PASSED      [ 40%]\nr2e_tests/test_1.py::test_basic_auth_from_url[pyloop] PASSED             [ 41%]\nr2e_tests/test_1.py::test_basic_auth_no_user_from_url[pyloop] PASSED     [ 42%]\nr2e_tests/test_1.py::test_basic_auth_from_url_overridden[pyloop] PASSED  [ 42%]\nr2e_tests/test_1.py::test_path_is_not_double_encoded1[pyloop] PASSED     [ 43%]\nr2e_tests/test_1.py::test_path_is_not_double_encoded2[pyloop] PASSED     [ 44%]\nr2e_tests/test_1.py::test_path_is_not_double_encoded3[pyloop] PASSED     [ 45%]\nr2e_tests/test_1.py::test_path_safe_chars_preserved[pyloop] PASSED       [ 45%]\nr2e_tests/test_1.py::test_params_are_added_before_fragment1[pyloop] PASSED [ 46%]\nr2e_tests/test_1.py::test_params_are_added_before_fragment2[pyloop] PASSED [ 47%]\nr2e_tests/test_1.py::test_path_not_contain_fragment1[pyloop] PASSED      [ 47%]\nr2e_tests/test_1.py::test_path_not_contain_fragment2[pyloop] PASSED      [ 48%]\nr2e_tests/test_1.py::test_cookies[pyloop] PASSED                         [ 49%]\nr2e_tests/test_1.py::test_cookies_is_quoted_with_special_characters[pyloop] PASSED [ 50%]\nr2e_tests/test_1.py::test_cookies_merge_with_headers[pyloop] PASSED      [ 50%]\nr2e_tests/test_1.py::test_unicode_get1[pyloop] PASSED                    [ 51%]\nr2e_tests/test_1.py::test_unicode_get2[pyloop] PASSED                    [ 52%]\nr2e_tests/test_1.py::test_unicode_get3[pyloop] PASSED                    [ 52%]\nr2e_tests/test_1.py::test_unicode_get4[pyloop] PASSED                    [ 53%]\nr2e_tests/test_1.py::test_query_multivalued_param[pyloop] PASSED         [ 54%]\nr2e_tests/test_1.py::test_query_str_param[pyloop] PASSED                 [ 54%]\nr2e_tests/test_1.py::test_query_bytes_param_raises[pyloop] PASSED        [ 55%]\nr2e_tests/test_1.py::test_query_str_param_is_not_encoded[pyloop] PASSED  [ 56%]\nr2e_tests/test_1.py::test_params_update_path_and_url[pyloop] PASSED      [ 57%]\nr2e_tests/test_1.py::test_params_empty_path_and_url[pyloop] PASSED       [ 57%]\nr2e_tests/test_1.py::test_gen_netloc_all[pyloop] PASSED                  [ 58%]\nr2e_tests/test_1.py::test_gen_netloc_no_port[pyloop] PASSED              [ 59%]\nr2e_tests/test_1.py::test_connection_header[pyloop] PASSED               [ 59%]\nr2e_tests/test_1.py::test_no_content_length[pyloop] PASSED               [ 60%]\nr2e_tests/test_1.py::test_no_content_length_head[pyloop] PASSED          [ 61%]\nr2e_tests/test_1.py::test_content_type_auto_header_get[pyloop] PASSED    [ 61%]\nr2e_tests/test_1.py::test_content_type_auto_header_form[pyloop] PASSED   [ 62%]\nr2e_tests/test_1.py::test_content_type_auto_header_bytes[pyloop] PASSED  [ 63%]\nr2e_tests/test_1.py::test_content_type_skip_auto_header_bytes[pyloop] PASSED [ 64%]\nr2e_tests/test_1.py::test_content_type_skip_auto_header_form[pyloop] PASSED [ 64%]\nr2e_tests/test_1.py::test_content_type_auto_header_content_length_no_skip[pyloop] PASSED [ 65%]\nr2e_tests/test_1.py::test_urlencoded_formdata_charset[pyloop] PASSED     [ 66%]\nr2e_tests/test_1.py::test_post_data[pyloop] PASSED                       [ 66%]\nr2e_tests/test_1.py::test_pass_falsy_data[pyloop] PASSED                 [ 67%]\nr2e_tests/test_1.py::test_pass_falsy_data_file[pyloop] PASSED            [ 68%]\nr2e_tests/test_1.py::test_get_with_data[pyloop] PASSED                   [ 69%]\nr2e_tests/test_1.py::test_bytes_data[pyloop] PASSED                      [ 69%]\nr2e_tests/test_1.py::test_content_encoding[pyloop] PASSED                [ 70%]\nr2e_tests/test_1.py::test_content_encoding_dont_set_headers_if_no_body[pyloop] PASSED [ 71%]\nr2e_tests/test_1.py::test_content_encoding_header[pyloop] PASSED         [ 71%]\nr2e_tests/test_1.py::test_compress_and_content_encoding[pyloop] PASSED   [ 72%]\nr2e_tests/test_1.py::test_chunked[pyloop] PASSED                         [ 73%]\nr2e_tests/test_1.py::test_chunked2[pyloop] PASSED                        [ 73%]\nr2e_tests/test_1.py::test_chunked_explicit[pyloop] PASSED                [ 74%]\nr2e_tests/test_1.py::test_chunked_length[pyloop] PASSED                  [ 75%]\nr2e_tests/test_1.py::test_chunked_transfer_encoding[pyloop] PASSED       [ 76%]\nr2e_tests/test_1.py::test_file_upload_not_chunked[pyloop] FAILED         [ 76%]\nr2e_tests/test_1.py::test_precompressed_data_stays_intact[pyloop] PASSED [ 77%]\nr2e_tests/test_1.py::test_file_upload_not_chunked_seek[pyloop] FAILED    [ 78%]\nr2e_tests/test_1.py::test_file_upload_force_chunked[pyloop] FAILED       [ 78%]\nr2e_tests/test_1.py::test_expect100[pyloop] PASSED                       [ 79%]\nr2e_tests/test_1.py::test_expect_100_continue_header[pyloop] PASSED      [ 80%]\nr2e_tests/test_1.py::test_data_stream[pyloop] PASSED                     [ 80%]\nr2e_tests/test_1.py::test_data_stream_deprecated[pyloop] PASSED          [ 81%]\nr2e_tests/test_1.py::test_data_file[pyloop] PASSED                       [ 82%]\nr2e_tests/test_1.py::test_data_stream_exc[pyloop] PASSED                 [ 83%]\nr2e_tests/test_1.py::test_data_stream_exc_chain[pyloop] PASSED           [ 83%]\nr2e_tests/test_1.py::test_data_stream_continue[pyloop] PASSED            [ 84%]\nr2e_tests/test_1.py::test_data_continue[pyloop] PASSED                   [ 85%]\nr2e_tests/test_1.py::test_close[pyloop] PASSED                           [ 85%]\nr2e_tests/test_1.py::test_bad_version[pyloop] PASSED                     [ 86%]\nr2e_tests/test_1.py::test_custom_response_class[pyloop] PASSED           [ 87%]\nr2e_tests/test_1.py::test_oserror_on_write_bytes[pyloop] PASSED          [ 88%]\nr2e_tests/test_1.py::test_cancel_close[pyloop] SKIPPED (Needs Task.c...) [ 88%]\nr2e_tests/test_1.py::test_terminate[pyloop] PASSED                       [ 89%]\nr2e_tests/test_1.py::test_terminate_with_closed_loop[pyloop] PASSED      [ 90%]\nr2e_tests/test_1.py::test_terminate_without_writer[pyloop] PASSED        [ 90%]\nr2e_tests/test_1.py::test_custom_req_rep[pyloop] PASSED                  [ 91%]\nr2e_tests/test_1.py::test_verify_ssl_false_with_ssl_context[pyloop] PASSED [ 92%]\nr2e_tests/test_1.py::test_bad_fingerprint[pyloop] PASSED                 [ 92%]\nr2e_tests/test_1.py::test_insecure_fingerprint_md5[pyloop] PASSED        [ 93%]\nr2e_tests/test_1.py::test_insecure_fingerprint_sha1[pyloop] PASSED       [ 94%]\nr2e_tests/test_1.py::test_loose_cookies_types[pyloop] PASSED             [ 95%]\nr2e_tests/test_1.py::test_gen_default_accept_encoding[False-gzip, deflate] PASSED [ 95%]\nr2e_tests/test_1.py::test_gen_default_accept_encoding[True-gzip, deflate, br] PASSED [ 96%]\nr2e_tests/test_1.py::test_basicauth_from_netrc_present[pyloop-machine example.com login username password pass\\n-expected_auth0] PASSED [ 97%]\nr2e_tests/test_1.py::test_basicauth_from_netrc_present_untrusted_env[pyloop-machine example.com login username password pass\\n] PASSED [ 97%]\nr2e_tests/test_1.py::test_basicauth_from_empty_netrc[pyloop-] PASSED     [ 98%]\nr2e_tests/test_1.py::test_connection_key_with_proxy PASSED               [ 99%]\nr2e_tests/test_1.py::test_connection_key_without_proxy FAILED            [100%]\n\n=================================== FAILURES ===================================\n_____________________ test_file_upload_not_chunked[pyloop] _____________________\n\nloop = <_UnixSelectorEventLoop running=False closed=False debug=False>\n\n    async def test_file_upload_not_chunked(loop) -> None:\n        file_path = pathlib.Path(__file__).parent / \"aiohttp.png\"\n>       with file_path.open(\"rb\") as f:\n\nfile_path  = PosixPath('/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png')\nloop       = <_UnixSelectorEventLoop running=False closed=False debug=False>\n\nr2e_tests/test_1.py:941: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n../../../../.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/pathlib.py:1252: in open\n    return io.open(self, mode, buffering, encoding, errors, newline,\n        buffering  = -1\n        encoding   = None\n        errors     = None\n        mode       = 'rb'\n        newline    = None\n        self       = PosixPath('/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png')\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = PosixPath('/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png')\nname = '/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png'\nflags = 524288, mode = 438\n\n    def _opener(self, name, flags, mode=0o666):\n        # A stub for the opener argument to built-in open()\n>       return self._accessor.open(self, flags, mode)\nE       FileNotFoundError: [Errno 2] No such file or directory: '/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png'\n\nflags      = 524288\nmode       = 438\nname       = '/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png'\nself       = PosixPath('/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png')\n\n../../../../.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/pathlib.py:1120: FileNotFoundError\n__________________ test_file_upload_not_chunked_seek[pyloop] ___________________\n\nloop = <_UnixSelectorEventLoop running=False closed=False debug=False>\n\n    async def test_file_upload_not_chunked_seek(loop) -> None:\n        file_path = pathlib.Path(__file__).parent / \"aiohttp.png\"\n>       with file_path.open(\"rb\") as f:\n\nfile_path  = PosixPath('/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png')\nloop       = <_UnixSelectorEventLoop running=False closed=False debug=False>\n\nr2e_tests/test_1.py:966: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n../../../../.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/pathlib.py:1252: in open\n    return io.open(self, mode, buffering, encoding, errors, newline,\n        buffering  = -1\n        encoding   = None\n        errors     = None\n        mode       = 'rb'\n        newline    = None\n        self       = PosixPath('/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png')\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = PosixPath('/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png')\nname = '/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png'\nflags = 524288, mode = 438\n\n    def _opener(self, name, flags, mode=0o666):\n        # A stub for the opener argument to built-in open()\n>       return self._accessor.open(self, flags, mode)\nE       FileNotFoundError: [Errno 2] No such file or directory: '/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png'\n\nflags      = 524288\nmode       = 438\nname       = '/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png'\nself       = PosixPath('/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png')\n\n../../../../.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/pathlib.py:1120: FileNotFoundError\n____________________ test_file_upload_force_chunked[pyloop] ____________________\n\nloop = <_UnixSelectorEventLoop running=False closed=False debug=False>\n\n    async def test_file_upload_force_chunked(loop) -> None:\n        file_path = pathlib.Path(__file__).parent / \"aiohttp.png\"\n>       with file_path.open(\"rb\") as f:\n\nfile_path  = PosixPath('/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png')\nloop       = <_UnixSelectorEventLoop running=False closed=False debug=False>\n\nr2e_tests/test_1.py:975: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n../../../../.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/pathlib.py:1252: in open\n    return io.open(self, mode, buffering, encoding, errors, newline,\n        buffering  = -1\n        encoding   = None\n        errors     = None\n        mode       = 'rb'\n        newline    = None\n        self       = PosixPath('/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png')\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = PosixPath('/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png')\nname = '/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png'\nflags = 524288, mode = 438\n\n    def _opener(self, name, flags, mode=0o666):\n        # A stub for the opener argument to built-in open()\n>       return self._accessor.open(self, flags, mode)\nE       FileNotFoundError: [Errno 2] No such file or directory: '/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png'\n\nflags      = 524288\nmode       = 438\nname       = '/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png'\nself       = PosixPath('/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/r2e_tests/aiohttp.png')\n\n../../../../.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/pathlib.py:1120: FileNotFoundError\n______________________ test_connection_key_without_proxy _______________________\n\n    async def test_connection_key_without_proxy() -> None:\n        \"\"\"Verify the proxy headers are not included in the ConnectionKey when a proxy is used.\"\"\"\n        # If proxy is unspecified, proxy_headers should be ignored\n        req = ClientRequest(\n            \"GET\",\n            URL(\"http://example.com\"),\n            proxy_headers={\"X-Proxy\": \"true\"},\n            loop=asyncio.get_running_loop(),\n        )\n>       assert req.connection_key.proxy_headers_hash is None\nE       AssertionError: assert -256113387895688042 is None\nE        +  where -256113387895688042 = ConnectionKey(host='example.com', port=80, is_ssl=False, ssl=True, proxy=None, proxy_auth=None, proxy_headers_hash=-256113387895688042).proxy_headers_hash\nE        +    where ConnectionKey(host='example.com', port=80, is_ssl=False, ssl=True, proxy=None, proxy_auth=None, proxy_headers_hash=-256113387895688042) = <aiohttp.client_reqrep.ClientRequest object at 0x7995aa538310>.connection_key\n\nreq        = <aiohttp.client_reqrep.ClientRequest object at 0x7995aa538310>\n\nr2e_tests/test_1.py:1495: AssertionError\n==================================== PASSES ====================================\n\n---------- coverage: platform linux, python 3.9.21-final-0 -----------\nName                                     Stmts   Miss Branch BrPart  Cover\n--------------------------------------------------------------------------\naiohttp/__init__.py                         27      8      2      1    69%\naiohttp/abc.py                              97      7      0      0    93%\naiohttp/base_protocol.py                    68     51     22      0    19%\naiohttp/client.py                          541    263    196     51    45%\naiohttp/client_exceptions.py               154     65     20      1    52%\naiohttp/client_proto.py                    166    132     56      0    15%\naiohttp/client_reqrep.py                   712    202    310     30    69%\naiohttp/client_ws.py                       264    214     80      1    15%\naiohttp/compression_utils.py                70     36     14      0    40%\naiohttp/connector.py                       765    514    327     32    26%\naiohttp/cookiejar.py                       274    195    130      6    21%\naiohttp/formdata.py                         97     42     46     12    51%\naiohttp/hdrs.py                             90      0      0      0   100%\naiohttp/helpers.py                         509    267    184     24    41%\naiohttp/http.py                             11      0      2      0   100%\naiohttp/http_exceptions.py                  50     20      4      0    56%\naiohttp/http_parser.py                     508    408    210      1    14%\naiohttp/http_websocket.py                  394    287    152      0    20%\naiohttp/http_writer.py                     119     38     50     13    60%\naiohttp/locks.py                            24     16      4      0    29%\naiohttp/log.py                               7      0      0      0   100%\naiohttp/multipart.py                       623    498    266      2    15%\naiohttp/payload.py                         237     49     58     12    74%\naiohttp/payload_streamer.py                 31      3      4      0    91%\naiohttp/pytest_plugin.py                   163     76     42      4    51%\naiohttp/resolver.py                         81     58     26      0    21%\naiohttp/streams.py                         398    315    146      0    15%\naiohttp/tcp_helpers.py                      19     11      6      0    32%\naiohttp/test_utils.py                      318    192     52      4    36%\naiohttp/tracing.py                         191     69     32      0    69%\naiohttp/typedefs.py                         24      0      0      0   100%\naiohttp/web.py                             122     84     52      0    23%\naiohttp/web_app.py                         292    196     82      0    26%\naiohttp/web_exceptions.py                  157     25      8      0    80%\naiohttp/web_fileresponse.py                163    127     54      1    19%\naiohttp/web_log.py                         102     58     20      0    36%\naiohttp/web_middlewares.py                  59     46     22      0    16%\naiohttp/web_protocol.py                    367    306    158      0    12%\naiohttp/web_request.py                     445    294    140      1    27%\naiohttp/web_response.py                    482    365    226      0    17%\naiohttp/web_routedef.py                    100     44     10      0    55%\naiohttp/web_runner.py                      213    130     36      0    33%\naiohttp/web_server.py                       42     24     12      0    33%\naiohttp/web_urldispatcher.py               740    474    163      0    29%\naiohttp/web_ws.py                          382    310    132      1    15%\naiohttp/worker.py                          126    126     30      0     0%\ntests/conftest.py                          131    131     16      0     0%\ntests/test_base_protocol.py                198    198      2      0     0%\ntests/test_circular_imports.py              29     29     13      0     0%\ntests/test_classbasedview.py                39     39      0      0     0%\ntests/test_client_connection.py             94     94      2      0     0%\ntests/test_client_exceptions.py            199    199     14      0     0%\ntests/test_client_fingerprint.py            59     59      0      0     0%\ntests/test_client_functional.py           2523   2523     86      0     0%\ntests/test_client_proto.py                  99     99      0      0     0%\ntests/test_client_request.py               820    820     18      0     0%\ntests/test_client_response.py              480    480      6      0     0%\ntests/test_client_session.py               566    566     29      0     0%\ntests/test_client_ws.py                    486    486      2      0     0%\ntests/test_client_ws_functional.py         750    750     32      0     0%\ntests/test_connector.py                   1700   1700     88      0     0%\ntests/test_cookiejar.py                    461    461     32      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                      509    509     24      0     0%\ntests/test_http_exceptions.py              109    109     10      0     0%\ntests/test_http_parser.py                 1092   1092     66      0     0%\ntests/test_http_writer.py                  182    182     10      0     0%\ntests/test_imports.py                       34     34      6      0     0%\ntests/test_locks.py                         39     39      0      0     0%\ntests/test_loop.py                          36     36      0      0     0%\ntests/test_multipart.py                    826    826     32      0     0%\ntests/test_multipart_helpers.py            446    446      0      0     0%\ntests/test_payload.py                       95     95      0      0     0%\ntests/test_proxy.py                        302    302      0      0     0%\ntests/test_proxy_functional.py             461    461     18      0     0%\ntests/test_pytest_plugin.py                 27     27      0      0     0%\ntests/test_resolver.py                     199    199     20      0     0%\ntests/test_route_def.py                    210    210      0      0     0%\ntests/test_run_app.py                      563    563     30      0     0%\ntests/test_streams.py                     1077   1077     38      0     0%\ntests/test_tcp_helpers.py                   52     52      2      0     0%\ntests/test_test_utils.py                   251    251      6      0     0%\ntests/test_tracing.py                       48     48      0      0     0%\ntests/test_urldispatch.py                  859    859     24      0     0%\ntests/test_web_app.py                      454    454      6      0     0%\ntests/test_web_cli.py                       75     75      0      0     0%\ntests/test_web_exceptions.py               179    179     22      0     0%\ntests/test_web_functional.py              1605   1605     36      0     0%\ntests/test_web_log.py                      116    116      2      0     0%\ntests/test_web_middleware.py               268    268     16      0     0%\ntests/test_web_request.py                  513    513      8      0     0%\ntests/test_web_request_handler.py           42     42      0      0     0%\ntests/test_web_response.py                 904    904      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      673    673     18      0     0%\ntests/test_web_server.py                   162    162      0      0     0%\ntests/test_web_urldispatcher.py            524    524     24      0     0%\ntests/test_web_websocket.py                401    401      8      0     0%\ntests/test_web_websocket_functional.py     799    799     28      0     0%\ntests/test_websocket_handshake.py          152    152     12      0     0%\ntests/test_websocket_parser.py             300    300     12      0     0%\ntests/test_websocket_writer.py              95     95      6      0     0%\ntests/test_worker.py                       191    191      2      0     0%\n--------------------------------------------------------------------------\nTOTAL                                    34744  30565   4428    197    12%\n\n============================= slowest 10 durations =============================\n0.05s call     r2e_tests/test_1.py::test_terminate_with_closed_loop[pyloop]\n0.04s teardown r2e_tests/test_1.py::test_host_header_ipv4_with_port[pyloop]\n0.03s teardown r2e_tests/test_1.py::test_basic_auth[pyloop]\n0.03s teardown r2e_tests/test_1.py::test_data_stream_continue[pyloop]\n0.03s teardown r2e_tests/test_1.py::test_oserror_on_write_bytes[pyloop]\n0.03s teardown r2e_tests/test_1.py::test_host_header_ipv6_with_port[pyloop]\n0.03s teardown r2e_tests/test_1.py::test_terminate[pyloop]\n0.02s teardown r2e_tests/test_1.py::test_data_continue[pyloop]\n0.02s teardown r2e_tests/test_1.py::test_custom_response_class[pyloop]\n0.02s teardown r2e_tests/test_1.py::test_bad_version[pyloop]\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::test_method1[pyloop]\nPASSED r2e_tests/test_1.py::test_method2[pyloop]\nPASSED r2e_tests/test_1.py::test_method3[pyloop]\nPASSED r2e_tests/test_1.py::test_method_invalid[pyloop]\nPASSED r2e_tests/test_1.py::test_version_1_0[pyloop]\nPASSED r2e_tests/test_1.py::test_version_default[pyloop]\nPASSED r2e_tests/test_1.py::test_request_info[pyloop]\nPASSED r2e_tests/test_1.py::test_request_info_with_fragment[pyloop]\nPASSED r2e_tests/test_1.py::test_version_err[pyloop]\nPASSED r2e_tests/test_1.py::test_keep_alive[pyloop]\nPASSED r2e_tests/test_1.py::test_host_port_default_http[pyloop]\nPASSED r2e_tests/test_1.py::test_host_port_default_https[pyloop]\nPASSED r2e_tests/test_1.py::test_host_port_nondefault_http[pyloop]\nPASSED r2e_tests/test_1.py::test_host_port_nondefault_https[pyloop]\nPASSED r2e_tests/test_1.py::test_host_port_default_ws[pyloop]\nPASSED r2e_tests/test_1.py::test_host_port_default_wss[pyloop]\nPASSED r2e_tests/test_1.py::test_host_port_nondefault_ws[pyloop]\nPASSED r2e_tests/test_1.py::test_host_port_nondefault_wss[pyloop]\nPASSED r2e_tests/test_1.py::test_host_port_none_port[pyloop]\nPASSED r2e_tests/test_1.py::test_host_port_err[pyloop]\nPASSED r2e_tests/test_1.py::test_hostname_err[pyloop]\nPASSED r2e_tests/test_1.py::test_host_header_host_first[pyloop]\nPASSED r2e_tests/test_1.py::test_host_header_host_without_port[pyloop]\nPASSED r2e_tests/test_1.py::test_host_header_host_with_default_port[pyloop]\nPASSED r2e_tests/test_1.py::test_host_header_host_with_nondefault_port[pyloop]\nPASSED r2e_tests/test_1.py::test_host_header_host_idna_encode[pyloop]\nPASSED r2e_tests/test_1.py::test_host_header_host_unicode[pyloop]\nPASSED r2e_tests/test_1.py::test_host_header_explicit_host[pyloop]\nPASSED r2e_tests/test_1.py::test_host_header_explicit_host_with_port[pyloop]\nPASSED r2e_tests/test_1.py::test_host_header_ipv4[pyloop]\nPASSED r2e_tests/test_1.py::test_host_header_ipv6[pyloop-True]\nPASSED r2e_tests/test_1.py::test_host_header_ipv6[pyloop-False]\nPASSED r2e_tests/test_1.py::test_host_header_ipv4_with_port[pyloop]\nPASSED r2e_tests/test_1.py::test_host_header_ipv6_with_port[pyloop]\nPASSED r2e_tests/test_1.py::test_default_loop[pyloop]\nPASSED r2e_tests/test_1.py::test_host_header_fqdn[pyloop-dot only at the end]\nPASSED r2e_tests/test_1.py::test_host_header_fqdn[pyloop-single dot]\nPASSED r2e_tests/test_1.py::test_host_header_fqdn[pyloop-single dot with port]\nPASSED r2e_tests/test_1.py::test_host_header_fqdn[pyloop-multiple dots with port]\nPASSED r2e_tests/test_1.py::test_host_header_fqdn[pyloop-explicit host header]\nPASSED r2e_tests/test_1.py::test_host_header_fqdn[pyloop-https]\nPASSED r2e_tests/test_1.py::test_host_header_fqdn[pyloop-only dots]\nPASSED r2e_tests/test_1.py::test_host_header_fqdn[pyloop-single dot with port idna]\nPASSED r2e_tests/test_1.py::test_default_headers_useragent[pyloop]\nPASSED r2e_tests/test_1.py::test_default_headers_useragent_custom[pyloop]\nPASSED r2e_tests/test_1.py::test_skip_default_useragent_header[pyloop]\nPASSED r2e_tests/test_1.py::test_headers[pyloop]\nPASSED r2e_tests/test_1.py::test_headers_list[pyloop]\nPASSED r2e_tests/test_1.py::test_headers_default[pyloop]\nPASSED r2e_tests/test_1.py::test_invalid_url[pyloop]\nPASSED r2e_tests/test_1.py::test_no_path[pyloop]\nPASSED r2e_tests/test_1.py::test_ipv6_default_http_port[pyloop]\nPASSED r2e_tests/test_1.py::test_ipv6_default_https_port[pyloop]\nPASSED r2e_tests/test_1.py::test_ipv6_nondefault_http_port[pyloop]\nPASSED r2e_tests/test_1.py::test_ipv6_nondefault_https_port[pyloop]\nPASSED r2e_tests/test_1.py::test_basic_auth[pyloop]\nPASSED r2e_tests/test_1.py::test_basic_auth_utf8[pyloop]\nPASSED r2e_tests/test_1.py::test_basic_auth_tuple_forbidden[pyloop]\nPASSED r2e_tests/test_1.py::test_basic_auth_from_url[pyloop]\nPASSED r2e_tests/test_1.py::test_basic_auth_no_user_from_url[pyloop]\nPASSED r2e_tests/test_1.py::test_basic_auth_from_url_overridden[pyloop]\nPASSED r2e_tests/test_1.py::test_path_is_not_double_encoded1[pyloop]\nPASSED r2e_tests/test_1.py::test_path_is_not_double_encoded2[pyloop]\nPASSED r2e_tests/test_1.py::test_path_is_not_double_encoded3[pyloop]\nPASSED r2e_tests/test_1.py::test_path_safe_chars_preserved[pyloop]\nPASSED r2e_tests/test_1.py::test_params_are_added_before_fragment1[pyloop]\nPASSED r2e_tests/test_1.py::test_params_are_added_before_fragment2[pyloop]\nPASSED r2e_tests/test_1.py::test_path_not_contain_fragment1[pyloop]\nPASSED r2e_tests/test_1.py::test_path_not_contain_fragment2[pyloop]\nPASSED r2e_tests/test_1.py::test_cookies[pyloop]\nPASSED r2e_tests/test_1.py::test_cookies_is_quoted_with_special_characters[pyloop]\nPASSED r2e_tests/test_1.py::test_cookies_merge_with_headers[pyloop]\nPASSED r2e_tests/test_1.py::test_unicode_get1[pyloop]\nPASSED r2e_tests/test_1.py::test_unicode_get2[pyloop]\nPASSED r2e_tests/test_1.py::test_unicode_get3[pyloop]\nPASSED r2e_tests/test_1.py::test_unicode_get4[pyloop]\nPASSED r2e_tests/test_1.py::test_query_multivalued_param[pyloop]\nPASSED r2e_tests/test_1.py::test_query_str_param[pyloop]\nPASSED r2e_tests/test_1.py::test_query_bytes_param_raises[pyloop]\nPASSED r2e_tests/test_1.py::test_query_str_param_is_not_encoded[pyloop]\nPASSED r2e_tests/test_1.py::test_params_update_path_and_url[pyloop]\nPASSED r2e_tests/test_1.py::test_params_empty_path_and_url[pyloop]\nPASSED r2e_tests/test_1.py::test_gen_netloc_all[pyloop]\nPASSED r2e_tests/test_1.py::test_gen_netloc_no_port[pyloop]\nPASSED r2e_tests/test_1.py::test_connection_header[pyloop]\nPASSED r2e_tests/test_1.py::test_no_content_length[pyloop]\nPASSED r2e_tests/test_1.py::test_no_content_length_head[pyloop]\nPASSED r2e_tests/test_1.py::test_content_type_auto_header_get[pyloop]\nPASSED r2e_tests/test_1.py::test_content_type_auto_header_form[pyloop]\nPASSED r2e_tests/test_1.py::test_content_type_auto_header_bytes[pyloop]\nPASSED r2e_tests/test_1.py::test_content_type_skip_auto_header_bytes[pyloop]\nPASSED r2e_tests/test_1.py::test_content_type_skip_auto_header_form[pyloop]\nPASSED r2e_tests/test_1.py::test_content_type_auto_header_content_length_no_skip[pyloop]\nPASSED r2e_tests/test_1.py::test_urlencoded_formdata_charset[pyloop]\nPASSED r2e_tests/test_1.py::test_post_data[pyloop]\nPASSED r2e_tests/test_1.py::test_pass_falsy_data[pyloop]\nPASSED r2e_tests/test_1.py::test_pass_falsy_data_file[pyloop]\nPASSED r2e_tests/test_1.py::test_get_with_data[pyloop]\nPASSED r2e_tests/test_1.py::test_bytes_data[pyloop]\nPASSED r2e_tests/test_1.py::test_content_encoding[pyloop]\nPASSED r2e_tests/test_1.py::test_content_encoding_dont_set_headers_if_no_body[pyloop]\nPASSED r2e_tests/test_1.py::test_content_encoding_header[pyloop]\nPASSED r2e_tests/test_1.py::test_compress_and_content_encoding[pyloop]\nPASSED r2e_tests/test_1.py::test_chunked[pyloop]\nPASSED r2e_tests/test_1.py::test_chunked2[pyloop]\nPASSED r2e_tests/test_1.py::test_chunked_explicit[pyloop]\nPASSED r2e_tests/test_1.py::test_chunked_length[pyloop]\nPASSED r2e_tests/test_1.py::test_chunked_transfer_encoding[pyloop]\nPASSED r2e_tests/test_1.py::test_precompressed_data_stays_intact[pyloop]\nPASSED r2e_tests/test_1.py::test_expect100[pyloop]\nPASSED r2e_tests/test_1.py::test_expect_100_continue_header[pyloop]\nPASSED r2e_tests/test_1.py::test_data_stream[pyloop]\nPASSED r2e_tests/test_1.py::test_data_stream_deprecated[pyloop]\nPASSED r2e_tests/test_1.py::test_data_file[pyloop]\nPASSED r2e_tests/test_1.py::test_data_stream_exc[pyloop]\nPASSED r2e_tests/test_1.py::test_data_stream_exc_chain[pyloop]\nPASSED r2e_tests/test_1.py::test_data_stream_continue[pyloop]\nPASSED r2e_tests/test_1.py::test_data_continue[pyloop]\nPASSED r2e_tests/test_1.py::test_close[pyloop]\nPASSED r2e_tests/test_1.py::test_bad_version[pyloop]\nPASSED r2e_tests/test_1.py::test_custom_response_class[pyloop]\nPASSED r2e_tests/test_1.py::test_oserror_on_write_bytes[pyloop]\nPASSED r2e_tests/test_1.py::test_terminate[pyloop]\nPASSED r2e_tests/test_1.py::test_terminate_with_closed_loop[pyloop]\nPASSED r2e_tests/test_1.py::test_terminate_without_writer[pyloop]\nPASSED r2e_tests/test_1.py::test_custom_req_rep[pyloop]\nPASSED r2e_tests/test_1.py::test_verify_ssl_false_with_ssl_context[pyloop]\nPASSED r2e_tests/test_1.py::test_bad_fingerprint[pyloop]\nPASSED r2e_tests/test_1.py::test_insecure_fingerprint_md5[pyloop]\nPASSED r2e_tests/test_1.py::test_insecure_fingerprint_sha1[pyloop]\nPASSED r2e_tests/test_1.py::test_loose_cookies_types[pyloop]\nPASSED r2e_tests/test_1.py::test_gen_default_accept_encoding[False-gzip, deflate]\nPASSED r2e_tests/test_1.py::test_gen_default_accept_encoding[True-gzip, deflate, br]\nPASSED r2e_tests/test_1.py::test_basicauth_from_netrc_present[pyloop-machine example.com login username password pass\\n-expected_auth0]\nPASSED r2e_tests/test_1.py::test_basicauth_from_netrc_present_untrusted_env[pyloop-machine example.com login username password pass\\n]\nPASSED r2e_tests/test_1.py::test_basicauth_from_empty_netrc[pyloop-]\nPASSED r2e_tests/test_1.py::test_connection_key_with_proxy\nSKIPPED [1] r2e_tests/test_1.py:1224: Needs Task.cancelling()\nFAILED r2e_tests/test_1.py::test_file_upload_not_chunked[pyloop] - FileNotFou...\nFAILED r2e_tests/test_1.py::test_file_upload_not_chunked_seek[pyloop] - FileN...\nFAILED r2e_tests/test_1.py::test_file_upload_force_chunked[pyloop] - FileNotF...\nFAILED r2e_tests/test_1.py::test_connection_key_without_proxy - AssertionErro...\n=================== 4 failed, 137 passed, 1 skipped in 7.58s ===================\n",
    "old_commit_res_stderr": "/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_6198a56e67a65a4bc68d1661a1c4cb9201d455cd/.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/9368.bugfix.rst aiohttp/client_reqrep.py tests/test_client_request.py
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]
**Title:** Proxy headers incorrectly included in ConnectionKey when no proxy is used

**Description:**
When creating a client request without specifying a proxy, the proxy headers are still included in the connection key. This leads to the `proxy_headers_hash` being set even when no proxy is in use, which is unexpected behavior.

**Example Code:**
```python
import asyncio
from aiohttp import ClientRequest, URL

async def test_connection_key_without_proxy():
    # Create a client request without specifying a proxy
    req = ClientRequest(
        "GET",
        URL("http://example.com"),
        proxy_headers={"X-Proxy": "true"},
        loop=asyncio.get_running_loop(),
    )
    # The proxy_headers_hash should be None since no proxy is set
    connection_hash = req.connection_key.proxy_headers_hash
    # Currently, connection_hash is not None, which is incorrect
    await req.close()
```

**Expected Behavior:**
When no proxy is specified, the `proxy_headers_hash` in the `ConnectionKey` should be `None`, indicating that no proxy headers are being used.

**Actual Behavior:**
The `proxy_headers_hash` is set to a non-`None` value even when no proxy is configured, incorrectly including proxy headers in the connection key.

[/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, __version__ as yarl_version

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,
    Query,
    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")
_YARL_SUPPORTS_HOST_SUBCOMPONENT = tuple(map(int, yarl_version.split(".")[:2])) >= (
    1,
    13,
)


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: Query = 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: Union[str, bool, None] = 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:
            url = url.extend_query(params)
        self.original_url = url
        self.url = url.with_fragment(None) if url.raw_fragment else url
        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(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
        if url.raw_user or url.raw_password:
            self.auth = helpers.BasicAuth(url.user or "", url.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()

        # Build the host header
        if _YARL_SUPPORTS_HOST_SUBCOMPONENT:
            host = self.url.host_subcomponent
            # host_subcomponent is None when the URL is a relative URL.
            # but we know we do not have a relative URL here.
            assert host is not None
        else:
            host = cast(str, self.url.raw_host)
            if helpers.is_ipv6_address(host):
                host = f"[{host}]"

        if host[-1] == ".":
            # Remove all trailing dots from the netloc as while
            # they are valid FQDNs in DNS, TLS validation fails.
            # See https://github.com/aio-libs/aiohttp/issues/3636.
            # To avoid string manipulation we only call rstrip if
            # the last character is a dot.
            host = host.rstrip(".")

        # If explicit port is not None, it means that the port was
        # explicitly specified in the URL. In this case we check
        # if its not the default port for the scheme and add it to
        # the host header. We check explicit_port first because
        # yarl caches explicit_port and its likely to already be
        # in the cache and non-default port URLs are far less common.
        explicit_port = self.url.explicit_port
        if explicit_port is not None and not self.url.is_default_port():
            host = f"{host}:{explicit_port}"

        self.headers[hdrs.HOST] = host

        if not headers:
            return

        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 not data:
            # Don't compress an empty body.
            self.compress = None
            return

        if self.headers.get(hdrs.CONTENT_ENCODING):
            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 (
            hdrs.EXPECT in self.headers
            and self.headers[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:
            await writer.drain()
            await self._continue

        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:
            # Body hasn't been fully sent, so connection can't be reused.
            conn.close()
            raise
        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:
            if _YARL_SUPPORTS_HOST_SUBCOMPONENT:
                connect_host = self.url.host_subcomponent
                assert connect_host is not None
            else:
                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_qs

        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)
                if self._traces
                else None
            ),
            on_headers_sent=(
                functools.partial(self._on_headers_request_sent, self.method, self.url)
                if self._traces
                else None
            ),
        )

        if self.compress:
            writer.enable_compression(self.compress)  # type: ignore[arg-type]

        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=task,
            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:
            try:
                await self.__writer
            except asyncio.CancelledError:
                if (
                    sys.version_info >= (3, 11)
                    and (task := asyncio.current_task())
                    and task.cancelling()
                ):
                    raise

    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
    _in_context = 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) if url.raw_fragment else url
        self._body: Optional[bytes] = None
        self._writer = 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]"]:
        """The writer task for streaming data.

        _writer is only provided for backwards compatibility
        for subclasses that may need to access it.
        """
        return self.__writer

    @_writer.setter
    def _writer(self, writer: Optional["asyncio.Task[None]"]) -> None:
        """Set the writer task for streaming data."""
        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

            # If we're in a context we can rely on __aexit__() to release as the
            # exception propagates.
            if not self._in_context:
                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:
            try:
                await self.__writer
            except asyncio.CancelledError:
                if (
                    sys.version_info >= (3, 11)
                    and (task := asyncio.current_task())
                    and task.cancelling()
                ):
                    raise
        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:
            try:
                await self.__writer
            except asyncio.CancelledError:
                if (
                    sys.version_info >= (3, 11)
                    and (task := asyncio.current_task())
                    and task.cancelling()
                ):
                    raise
        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

    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, ValueError):
                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(encoding, errors=errors)  # type: ignore[union-attr]

    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":
        self._in_context = True
        return self

    async def __aexit__(
        self,
        exc_type: Optional[Type[BaseException]],
        exc_val: Optional[BaseException],
        exc_tb: Optional[TracebackType],
    ) -> None:
        self._in_context = False
        # 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:** Proxy headers incorrectly included in ConnectionKey when no proxy is used

**Description:**
When creating a client request without specifying a proxy, the proxy headers are still included in the connection key. This leads to the `proxy_headers_hash` being set even when no proxy is in use, which is unexpected behavior.

**Example Code:**
```python
import asyncio
from aiohttp import ClientRequest, URL

async def test_connection_key_without_proxy():
    # Create a client request without specifying a proxy
    req = ClientRequest(
        "GET",
        URL("http://example.com"),
        proxy_headers={"X-Proxy": "true"},
        loop=asyncio.get_running_loop(),
    )
    # The proxy_headers_hash should be None since no proxy is set
    connection_hash = req.connection_key.proxy_headers_hash
    # Currently, connection_hash is not None, which is incorrect
    await req.close()
```

**Expected Behavior:**
When no proxy is specified, the `proxy_headers_hash` in the `ConnectionKey` should be `None`, indicating that no proxy headers are being used.

**Actual Behavior:**
The `proxy_headers_hash` is set to a non-`None` value even when no proxy is configured, incorrectly including proxy headers in the connection key.

[/ISSUE]
{
    "test_method1[pyloop]": "PASSED",
    "test_method2[pyloop]": "PASSED",
    "test_method3[pyloop]": "PASSED",
    "test_method_invalid[pyloop]": "PASSED",
    "test_version_1_0[pyloop]": "PASSED",
    "test_version_default[pyloop]": "PASSED",
    "test_request_info[pyloop]": "PASSED",
    "test_request_info_with_fragment[pyloop]": "PASSED",
    "test_version_err[pyloop]": "PASSED",
    "test_keep_alive[pyloop]": "PASSED",
    "test_host_port_default_http[pyloop]": "PASSED",
    "test_host_port_default_https[pyloop]": "PASSED",
    "test_host_port_nondefault_http[pyloop]": "PASSED",
    "test_host_port_nondefault_https[pyloop]": "PASSED",
    "test_host_port_default_ws[pyloop]": "PASSED",
    "test_host_port_default_wss[pyloop]": "PASSED",
    "test_host_port_nondefault_ws[pyloop]": "PASSED",
    "test_host_port_nondefault_wss[pyloop]": "PASSED",
    "test_host_port_none_port[pyloop]": "PASSED",
    "test_host_port_err[pyloop]": "PASSED",
    "test_hostname_err[pyloop]": "PASSED",
    "test_host_header_host_first[pyloop]": "PASSED",
    "test_host_header_host_without_port[pyloop]": "PASSED",
    "test_host_header_host_with_default_port[pyloop]": "PASSED",
    "test_host_header_host_with_nondefault_port[pyloop]": "PASSED",
    "test_host_header_host_idna_encode[pyloop]": "PASSED",
    "test_host_header_host_unicode[pyloop]": "PASSED",
    "test_host_header_explicit_host[pyloop]": "PASSED",
    "test_host_header_explicit_host_with_port[pyloop]": "PASSED",
    "test_host_header_ipv4[pyloop]": "PASSED",
    "test_host_header_ipv6[pyloop-True]": "PASSED",
    "test_host_header_ipv6[pyloop-False]": "PASSED",
    "test_host_header_ipv4_with_port[pyloop]": "PASSED",
    "test_host_header_ipv6_with_port[pyloop]": "PASSED",
    "test_default_loop[pyloop]": "PASSED",
    "test_host_header_fqdn[pyloop-dot only at the end]": "PASSED",
    "test_host_header_fqdn[pyloop-single dot]": "PASSED",
    "test_host_header_fqdn[pyloop-single dot with port]": "PASSED",
    "test_host_header_fqdn[pyloop-multiple dots with port]": "PASSED",
    "test_host_header_fqdn[pyloop-explicit host header]": "PASSED",
    "test_host_header_fqdn[pyloop-https]": "PASSED",
    "test_host_header_fqdn[pyloop-only dots]": "PASSED",
    "test_host_header_fqdn[pyloop-single dot with port idna]": "PASSED",
    "test_default_headers_useragent[pyloop]": "PASSED",
    "test_default_headers_useragent_custom[pyloop]": "PASSED",
    "test_skip_default_useragent_header[pyloop]": "PASSED",
    "test_headers[pyloop]": "PASSED",
    "test_headers_list[pyloop]": "PASSED",
    "test_headers_default[pyloop]": "PASSED",
    "test_invalid_url[pyloop]": "PASSED",
    "test_no_path[pyloop]": "PASSED",
    "test_ipv6_default_http_port[pyloop]": "PASSED",
    "test_ipv6_default_https_port[pyloop]": "PASSED",
    "test_ipv6_nondefault_http_port[pyloop]": "PASSED",
    "test_ipv6_nondefault_https_port[pyloop]": "PASSED",
    "test_basic_auth[pyloop]": "PASSED",
    "test_basic_auth_utf8[pyloop]": "PASSED",
    "test_basic_auth_tuple_forbidden[pyloop]": "PASSED",
    "test_basic_auth_from_url[pyloop]": "PASSED",
    "test_basic_auth_no_user_from_url[pyloop]": "PASSED",
    "test_basic_auth_from_url_overridden[pyloop]": "PASSED",
    "test_path_is_not_double_encoded1[pyloop]": "PASSED",
    "test_path_is_not_double_encoded2[pyloop]": "PASSED",
    "test_path_is_not_double_encoded3[pyloop]": "PASSED",
    "test_path_safe_chars_preserved[pyloop]": "PASSED",
    "test_params_are_added_before_fragment1[pyloop]": "PASSED",
    "test_params_are_added_before_fragment2[pyloop]": "PASSED",
    "test_path_not_contain_fragment1[pyloop]": "PASSED",
    "test_path_not_contain_fragment2[pyloop]": "PASSED",
    "test_cookies[pyloop]": "PASSED",
    "test_cookies_is_quoted_with_special_characters[pyloop]": "PASSED",
    "test_cookies_merge_with_headers[pyloop]": "PASSED",
    "test_unicode_get1[pyloop]": "PASSED",
    "test_unicode_get2[pyloop]": "PASSED",
    "test_unicode_get3[pyloop]": "PASSED",
    "test_unicode_get4[pyloop]": "PASSED",
    "test_query_multivalued_param[pyloop]": "PASSED",
    "test_query_str_param[pyloop]": "PASSED",
    "test_query_bytes_param_raises[pyloop]": "PASSED",
    "test_query_str_param_is_not_encoded[pyloop]": "PASSED",
    "test_params_update_path_and_url[pyloop]": "PASSED",
    "test_params_empty_path_and_url[pyloop]": "PASSED",
    "test_gen_netloc_all[pyloop]": "PASSED",
    "test_gen_netloc_no_port[pyloop]": "PASSED",
    "test_connection_header[pyloop]": "PASSED",
    "test_no_content_length[pyloop]": "PASSED",
    "test_no_content_length_head[pyloop]": "PASSED",
    "test_content_type_auto_header_get[pyloop]": "PASSED",
    "test_content_type_auto_header_form[pyloop]": "PASSED",
    "test_content_type_auto_header_bytes[pyloop]": "PASSED",
    "test_content_type_skip_auto_header_bytes[pyloop]": "PASSED",
    "test_content_type_skip_auto_header_form[pyloop]": "PASSED",
    "test_content_type_auto_header_content_length_no_skip[pyloop]": "PASSED",
    "test_urlencoded_formdata_charset[pyloop]": "PASSED",
    "test_post_data[pyloop]": "PASSED",
    "test_pass_falsy_data[pyloop]": "PASSED",
    "test_pass_falsy_data_file[pyloop]": "PASSED",
    "test_get_with_data[pyloop]": "PASSED",
    "test_bytes_data[pyloop]": "PASSED",
    "test_content_encoding[pyloop]": "PASSED",
    "test_content_encoding_dont_set_headers_if_no_body[pyloop]": "PASSED",
    "test_content_encoding_header[pyloop]": "PASSED",
    "test_compress_and_content_encoding[pyloop]": "PASSED",
    "test_chunked[pyloop]": "PASSED",
    "test_chunked2[pyloop]": "PASSED",
    "test_chunked_explicit[pyloop]": "PASSED",
    "test_chunked_length[pyloop]": "PASSED",
    "test_chunked_transfer_encoding[pyloop]": "PASSED",
    "test_precompressed_data_stays_intact[pyloop]": "PASSED",
    "test_expect100[pyloop]": "PASSED",
    "test_expect_100_continue_header[pyloop]": "PASSED",
    "test_data_stream[pyloop]": "PASSED",
    "test_data_stream_deprecated[pyloop]": "PASSED",
    "test_data_file[pyloop]": "PASSED",
    "test_data_stream_exc[pyloop]": "PASSED",
    "test_data_stream_exc_chain[pyloop]": "PASSED",
    "test_data_stream_continue[pyloop]": "PASSED",
    "test_data_continue[pyloop]": "PASSED",
    "test_close[pyloop]": "PASSED",
    "test_bad_version[pyloop]": "PASSED",
    "test_custom_response_class[pyloop]": "PASSED",
    "test_oserror_on_write_bytes[pyloop]": "PASSED",
    "test_terminate[pyloop]": "PASSED",
    "test_terminate_with_closed_loop[pyloop]": "PASSED",
    "test_terminate_without_writer[pyloop]": "PASSED",
    "test_custom_req_rep[pyloop]": "PASSED",
    "test_verify_ssl_false_with_ssl_context[pyloop]": "PASSED",
    "test_bad_fingerprint[pyloop]": "PASSED",
    "test_insecure_fingerprint_md5[pyloop]": "PASSED",
    "test_insecure_fingerprint_sha1[pyloop]": "PASSED",
    "test_loose_cookies_types[pyloop]": "PASSED",
    "test_gen_default_accept_encoding[False-gzip, deflate]": "PASSED",
    "test_gen_default_accept_encoding[True-gzip, deflate, br]": "PASSED",
    "test_basicauth_from_netrc_present[pyloop-machine example.com login username password pass\\n-expected_auth0]": "PASSED",
    "test_basicauth_from_netrc_present_untrusted_env[pyloop-machine example.com login username password pass\\n]": "PASSED",
    "test_basicauth_from_empty_netrc[pyloop-]": "PASSED",
    "test_connection_key_with_proxy": "PASSED",
    "test_connection_key_without_proxy": "PASSED",
    "test_file_upload_not_chunked[pyloop]": "FAILED",
    "test_file_upload_not_chunked_seek[pyloop]": "FAILED",
    "test_file_upload_force_chunked[pyloop]": "FAILED"
}
diff --git a/aiohttp/client_reqrep.py b/aiohttp/client_reqrep.py
index 3648e9cb..6ebc6969 100644
--- a/aiohttp/client_reqrep.py
+++ b/aiohttp/client_reqrep.py
@@ -626,10 +626,16 @@ class ClientRequest:
         proxy_auth: Optional[BasicAuth],
         proxy_headers: Optional[LooseHeaders],
     ) -> None:
+        self.proxy = proxy
+        if proxy is None:
+            self.proxy_auth = None
+            self.proxy_headers = None
+            return
+
         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)
         ):

{"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, __version__ as yarl_version\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    Query,\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_YARL_SUPPORTS_HOST_SUBCOMPONENT = tuple(map(int, yarl_version.split(\".\")[:2])) >= (\n    1,\n    13,\n)\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: Query = 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: Union[str, bool, None] = 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            url = url.extend_query(params)\n        self.original_url = url\n        self.url = url.with_fragment(None) if url.raw_fragment else url\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(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        if url.raw_user or url.raw_password:\n            self.auth = helpers.BasicAuth(url.user or \"\", url.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        # Build the host header\n        if _YARL_SUPPORTS_HOST_SUBCOMPONENT:\n            host = self.url.host_subcomponent\n            # host_subcomponent is None when the URL is a relative URL.\n            # but we know we do not have a relative URL here.\n            assert host is not None\n        else:\n            host = cast(str, self.url.raw_host)\n            if helpers.is_ipv6_address(host):\n                host = f\"[{host}]\"\n\n        if host[-1] == \".\":\n            # Remove all trailing dots from the netloc as while\n            # they are valid FQDNs in DNS, TLS validation fails.\n            # See https://github.com/aio-libs/aiohttp/issues/3636.\n            # To avoid string manipulation we only call rstrip if\n            # the last character is a dot.\n            host = host.rstrip(\".\")\n\n        # If explicit port is not None, it means that the port was\n        # explicitly specified in the URL. In this case we check\n        # if its not the default port for the scheme and add it to\n        # the host header. We check explicit_port first because\n        # yarl caches explicit_port and its likely to already be\n        # in the cache and non-default port URLs are far less common.\n        explicit_port = self.url.explicit_port\n        if explicit_port is not None and not self.url.is_default_port():\n            host = f\"{host}:{explicit_port}\"\n\n        self.headers[hdrs.HOST] = host\n\n        if not headers:\n            return\n\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 not data:\n            # Don't compress an empty body.\n            self.compress = None\n            return\n\n        if self.headers.get(hdrs.CONTENT_ENCODING):\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 (\n            hdrs.EXPECT in self.headers\n            and self.headers[hdrs.EXPECT].lower() == \"100-continue\"\n        ):\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            await writer.drain()\n            await self._continue\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            raise\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            if _YARL_SUPPORTS_HOST_SUBCOMPONENT:\n                connect_host = self.url.host_subcomponent\n                assert connect_host is not None\n            else:\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_qs\n\n        protocol = conn.protocol\n        assert protocol is not None\n        writer = StreamWriter(\n            protocol,\n            self.loop,\n            on_chunk_sent=(\n                functools.partial(self._on_chunk_request_sent, self.method, self.url)\n                if self._traces\n                else None\n            ),\n            on_headers_sent=(\n                functools.partial(self._on_headers_request_sent, self.method, self.url)\n                if self._traces\n                else None\n            ),\n        )\n\n        if self.compress:\n            writer.enable_compression(self.compress)  # type: ignore[arg-type]\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=task,\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            try:\n                await self.__writer\n            except asyncio.CancelledError:\n                if (\n                    sys.version_info >= (3, 11)\n                    and (task := asyncio.current_task())\n                    and task.cancelling()\n                ):\n                    raise\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    _in_context = 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) if url.raw_fragment else url\n        self._body: Optional[bytes] = None\n        self._writer = 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        \"\"\"The writer task for streaming data.\n\n        _writer is only provided for backwards compatibility\n        for subclasses that may need to access it.\n        \"\"\"\n        return self.__writer\n\n    @_writer.setter\n    def _writer(self, writer: Optional[\"asyncio.Task[None]\"]) -> None:\n        \"\"\"Set the writer task for streaming data.\"\"\"\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\n            # If we're in a context we can rely on __aexit__() to release as the\n            # exception propagates.\n            if not self._in_context:\n                self.release()\n\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            try:\n                await self.__writer\n            except asyncio.CancelledError:\n                if (\n                    sys.version_info >= (3, 11)\n                    and (task := asyncio.current_task())\n                    and task.cancelling()\n                ):\n                    raise\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            try:\n                await self.__writer\n            except asyncio.CancelledError:\n                if (\n                    sys.version_info >= (3, 11)\n                    and (task := asyncio.current_task())\n                    and task.cancelling()\n                ):\n                    raise\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\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, ValueError):\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(encoding, errors=errors)  # type: ignore[union-attr]\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        self._in_context = True\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        self._in_context = False\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:** Proxy headers incorrectly included in ConnectionKey when no proxy is used

**Description:**
When creating a client request without specifying a proxy, the proxy headers are still included in the connection key. This leads to the `proxy_headers_hash` being set even when no proxy is in use, which is unexpected behavior.

**Example Code:**
```python
import asyncio
from aiohttp import ClientRequest, URL

async def test_connection_key_without_proxy():
    # Create a client request without specifying a proxy
    req = ClientRequest(
        "GET",
        URL("http://example.com"),
        proxy_headers={"X-Proxy": "true"},
        loop=asyncio.get_running_loop(),
    )
    # The proxy_headers_hash should be None since no proxy is set
    connection_hash = req.connection_key.proxy_headers_hash
    # Currently, connection_hash is not None, which is incorrect
    await req.close()
```

**Expected Behavior:**
When no proxy is specified, the `proxy_headers_hash` in the `ConnectionKey` should be `None`, indicating that no proxy headers are being used.

**Actual Behavior:**
The `proxy_headers_hash` is set to a non-`None` value even when no proxy is configured, incorrectly including proxy headers in the connection key.

[/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, __version__ as yarl_version

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,
    Query,
    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")
_YARL_SUPPORTS_HOST_SUBCOMPONENT = tuple(map(int, yarl_version.split(".")[:2])) >= (
    1,
    13,
)


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: Query = 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: Union[str, bool, None] = 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:
            url = url.extend_query(params)
        self.original_url = url
        self.url = url.with_fragment(None) if url.raw_fragment else url
        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(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
        if url.raw_user or url.raw_password:
            self.auth = helpers.BasicAuth(url.user or "", url.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()

        # Build the host header
        if _YARL_SUPPORTS_HOST_SUBCOMPONENT:
            host = self.url.host_subcomponent
            # host_subcomponent is None when the URL is a relative URL.
            # but we know we do not have a relative URL here.
            assert host is not None
        else:
            host = cast(str, self.url.raw_host)
            if helpers.is_ipv6_address(host):
                host = f"[{host}]"

        if host[-1] == ".":
            # Remove all trailing dots from the netloc as while
            # they are valid FQDNs in DNS, TLS validation fails.
            # See https://github.com/aio-libs/aiohttp/issues/3636.
            # To avoid string manipulation we only call rstrip if
            # the last character is a dot.
            host = host.rstrip(".")

        # If explicit port is not None, it means that the port was
        # explicitly specified in the URL. In this case we check
        # if its not the default port for the scheme and add it to
        # the host header. We check explicit_port first because
        # yarl caches explicit_port and its likely to already be
        # in the cache and non-default port URLs are far less common.
        explicit_port = self.url.explicit_port
        if explicit_port is not None and not self.url.is_default_port():
            host = f"{host}:{explicit_port}"

        self.headers[hdrs.HOST] = host

        if not headers:
            return

        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 not data:
            # Don't compress an empty body.
            self.compress = None
            return

        if self.headers.get(hdrs.CONTENT_ENCODING):
            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 (
            hdrs.EXPECT in self.headers
            and self.headers[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:
            await writer.drain()
            await self._continue

        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:
            # Body hasn't been fully sent, so connection can't be reused.
            conn.close()
            raise
        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:
            if _YARL_SUPPORTS_HOST_SUBCOMPONENT:
                connect_host = self.url.host_subcomponent
                assert connect_host is not None
            else:
                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_qs

        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)
                if self._traces
                else None
            ),
            on_headers_sent=(
                functools.partial(self._on_headers_request_sent, self.method, self.url)
                if self._traces
                else None
            ),
        )

        if self.compress:
            writer.enable_compression(self.compress)  # type: ignore[arg-type]

        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=task,
            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:
            try:
                await self.__writer
            except asyncio.CancelledError:
                if (
                    sys.version_info >= (3, 11)
                    and (task := asyncio.current_task())
                    and task.cancelling()
                ):
                    raise

    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
    _in_context = 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) if url.raw_fragment else url
        self._body: Optional[bytes] = None
        self._writer = 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]"]:
        """The writer task for streaming data.

        _writer is only provided for backwards compatibility
        for subclasses that may need to access it.
        """
        return self.__writer

    @_writer.setter
    def _writer(self, writer: Optional["asyncio.Task[None]"]) -> None:
        """Set the writer task for streaming data."""
        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

            # If we're in a context we can rely on __aexit__() to release as the
            # exception propagates.
            if not self._in_context:
                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:
            try:
                await self.__writer
            except asyncio.CancelledError:
                if (
                    sys.version_info >= (3, 11)
                    and (task := asyncio.current_task())
                    and task.cancelling()
                ):
                    raise
        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:
            try:
                await self.__writer
            except asyncio.CancelledError:
                if (
                    sys.version_info >= (3, 11)
                    and (task := asyncio.current_task())
                    and task.cancelling()
                ):
                    raise
        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

    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, ValueError):
                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(encoding, errors=errors)  # type: ignore[union-attr]

    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":
        self._in_context = True
        return self

    async def __aexit__(
        self,
        exc_type: Optional[Type[BaseException]],
        exc_val: Optional[BaseException],
        exc_tb: Optional[TracebackType],
    ) -> None:
        self._in_context = False
        # 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