{
    "file_diffs": [
        {
            "old_file_content": "",
            "new_file_content": "Added ``proxy`` and ``proxy_auth`` parameters to ``ClientSession`` -- by :user:`meshya`.\n",
            "header": {
                "file": {
                    "path": "CHANGES/9207.feature.rst"
                },
                "misc_line": "new file mode 100644"
            },
            "index_line": {
                "old_commit_hash": "00000000",
                "new_commit_hash": "d9ac55c8",
                "mode": ""
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "/dev/null"
            },
            "plus_file": {
                "path": "b/CHANGES/9207.feature.rst"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 0,
                            "length": 0
                        },
                        "new_range": {
                            "start": 1,
                            "length": null
                        },
                        "section": ""
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "Added ``proxy`` and ``proxy_auth`` parameters to ``ClientSession`` -- by :user:`meshya`.",
                                "type": "added"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "- Contributors -\n----------------\nA. Jesse Jiryu Davis\nAdam Bannister\nAdam Cooper\nAdam Horacek\nAdam Mills\nAdrian Krupa\nAdrián Chaves\nAhmed Tahri\nAlan Tse\nAlec Hanefeld\nAlejandro Gómez\nAleksandr Danshyn\nAleksey Kutepov\nAlex Hayes\nAlex Key\nAlex Khomchenko\nAlex Kuzmenko\nAlex Lisovoy\nAlexander Bayandin\nAlexander Karpinsky\nAlexander Koshevoy\nAlexander Malev\nAlexander Mohr\nAlexander Shorin\nAlexander Travov\nAlexandru Mihai\nAlexey Firsov\nAlexey Nikitin\nAlexey Popravka\nAlexey Stepanov\nAmin Etesamian\nAmit Tulshyan\nAmy Boyle\nAnas El Amraoui\nAnders Melchiorsen\nAndrei Ursulenko\nAndrej Antonov\nAndrew Leech\nAndrew Lytvyn\nAndrew Svetlov\nAndrew Zhou\nAndrii Soldatenko\nAnes Abismail\nAntoine Pietri\nAnton Kasyanov\nAnton Zhdan-Pushkin\nArcadiy Ivanov\nArseny Timoniq\nArtem Yushkovskiy\nArthur Darcet\nAustin Scola\nBen Bader\nBen Greiner\nBen Kallus\nBen Timby\nBenedikt Reinartz\nBob Haddleton\nBoris Feld\nBoyi Chen\nBrett Cannon\nBrian Bouterse\nBrian C. Lane\nBrian Muller\nBruce Merry\nBruno Souza Cabral\nBryan Kok\nBryce Drennan\nCarl George\nCecile Tonglet\nChien-Wei Huang\nChih-Yuan Chen\nChris AtLee\nChris Laws\nChris Moore\nChris Shucksmith\nChristopher Schmitt\nClaudiu Popa\nColin Dunklau\nCong Xu\nDamien Nadé\nDan King\nDan Xu\nDaniel García\nDaniel Golding\nDaniel Grossmann-Kavanagh\nDaniel Nelson\nDanny Song\nDavid Bibb\nDavid Michael Brown\nDenilson Amorim\nDenis Matiychuk\nDenis Moshensky\nDennis Kliban\nDima Veselov\nDimitar Dimitrov\nDiogo Dutra da Mata\nDmitriy Safonov\nDmitry Doroshev\nDmitry Erlikh\nDmitry Lukashin\nDmitry Marakasov\nDmitry Shamov\nDmitry Trofimov\nDmytro Bohomiakov\nDmytro Kuznetsov\nDustin J. Mitchell\nEduard Iskandarov\nEli Ribble\nElizabeth Leddy\nEnrique Saez\nEric Sheng\nErich Healy\nErik Peterson\nEugene Chernyshov\nEugene Naydenov\nEugene Nikolaiev\nEugene Tolmachev\nEvan Kepner\nEvert Lammerts\nFelix Yan\nFernanda Guimarães\nFichteFoll\nFlorian Scheffler\nFranek Magiera\nFrederik Gladhorn\nFrederik Peter Aalund\nGabriel Tremblay\nGang Ji\nGary Wilson Jr.\nGennady Andreyev\nGeorges Dubus\nGreg Holt\nGregory Haynes\nGus Goulart\nGustavo Carneiro\nGünther Jena\nHans Adema\nHarmon Y.\nHarry Liu\nHiroshi Ogawa\nHrishikesh Paranjape\nHu Bo\nHugh Young\nHugo Herter\nHugo Hromic\nHugo van Kemenade\nHynek Schlawack\nIgor Alexandrov\nIgor Bolshakov\nIgor Davydenko\nIgor Mozharovsky\nIgor Pavlov\nIllia Volochii\nIlya Chichak\nIlya Gruzinov\nIngmar Steen\nIvan Lakovic\nIvan Larin\nJ. Nick Koston\nJacob Champion\nJaesung Lee\nJake Davis\nJakob Ackermann\nJakub Wilk\nJan Buchar\nJan Gosmann\nJarno Elonen\nJashandeep Sohi\nJean-Baptiste Estival\nJens Steinhauser\nJeonghun Lee\nJeongkyu Shin\nJeroen van der Heijden\nJesus Cea\nJian Zeng\nJinkyu Yi\nJoel Watts\nJohn Parton\nJon Nabozny\nJonas Krüger Svensson\nJonas Obrist\nJonathan Ballet\nJonathan Wright\nJonny Tan\nJoongi Kim\nJordan Borean\nJosep Cugat\nJosh Junon\nJoshu Coats\nJulia Tsemusheva\nJulien Duponchelle\nJungkook Park\nJunjie Tao\nJunyeong Jeong\nJustas Trimailovas\nJustin Foo\nJustin Turner Arthur\nKay Zheng\nKevin Samuel\nKimmo Parviainen-Jalanko\nKirill Klenov\nKirill Malovitsa\nKonstantin Shutkin\nKonstantin Valetov\nKrzysztof Blazewicz\nKyrylo Perevozchikov\nKyungmin Lee\nLars P. Søndergaard\nLee LieWhite\nLiu Hua\nLouis-Philippe Huberdeau\nLoïc Lajeanne\nLu Gong\nLubomir Gelo\nLudovic Gasc\nLuis Pedrosa\nLukasz Marcin Dobrzanski\nMakc Belousow\nManuel Miranda\nMarat Sharafutdinov\nMarc Mueller\nMarco Paolini\nMariano Anaya\nMariusz Masztalerczuk\nMarko Kohtala\nMartijn Pieters\nMartin Melka\nMartin Richard\nMartin Sucha\nMathias Fröjdman\nMathieu Dugré\nMatt VanEseltine\nMatthias Marquardt\nMatthieu Hauglustaine\nMatthieu Rigal\nMatvey Tingaev\nMeet Mangukiya\nMichael Ihnatenko\nMichał Górny\nMikhail Burshteyn\nMikhail Kashkin\nMikhail Lukyanchenko\nMikhail Nacharov\nMisha Behersky\nMitchell Ferree\nMorgan Delahaye-Prat\nMoss Collum\nMun Gwan-gyeong\nNavid Sheikhol\nNicolas Braem\nNikolay Kim\nNikolay Novik\nNikolay Tiunov\nNándor Mátravölgyi\nOisin Aylward\nOlaf Conradi\nPahaz Blinov\nPanagiotis Kolokotronis\nPankaj Pandey\nParag Jain\nPau Freixes\nPaul Colomiets\nPaul J. Dorn\nPaulius Šileikis\nPaulus Schoutsen\nPavel Kamaev\nPavel Polyakov\nPavel Sapezhko\nPavol Vargovčík\nPawel Kowalski\nPawel Miech\nPepe Osca\nPhilipp A.\nPierre-Louis Peeters\nPieter van Beek\nQiao Han\nRafael Viotti\nRahul Nahata\nRaphael Bialon\nRaúl Cumplido\nRequired Field\nRobert Lu\nRobert Nikolich\nRoman Podoliaka\nRong Zhang\nSamir Akarioh\nSamuel Colvin\nSean Hunt\nSebastian Acuna\nSebastian Hanula\nSebastian Hüther\nSebastien Geffroy\nSeongSoo Cho\nSergey Ninua\nSergey Skripnick\nSerhii Charykov\nSerhii Kostel\nSerhiy Storchaka\nSimon Kennedy\nSin-Woo Bang\nStanislas Plum\nStanislav Prokop\nStefan Tjarks\nStepan Pletnev\nStephan Jaensch\nStephen Cirelli\nStephen Granade\nSteve Repsher\nSteven Seguin\nSunghyun Hwang\nSunit Deshpande\nSviatoslav Bulbakha\nSviatoslav Sydorenko\nTaha Jahangir\nTaras Voinarovskyi\nTerence Honles\nThanos Lefteris\nThijs Vermeir\nThomas Forbes\nThomas Grainger\nTolga Tezel\nTomasz Trebski\nToshiaki Tanaka\nTrinh Hoang Nhu\nTymofii Tsiapa\nVadim Suharnikov\nVaibhav Sagar\nVamsi Krishna Avula\nVasiliy Faronov\nVasyl Baran\nViacheslav Greshilov\nVictor Collod\nVictor Kovtun\nVikas Kawadia\nViktor Danyliuk\nVille Skyttä\nVincent Maillol\nVitalik Verhovodov\nVitaly Haritonsky\nVitaly Magerya\nVladimir Kamarzin\nVladimir Kozlovski\nVladimir Rutsky\nVladimir Shulyak\nVladimir Zakharov\nVladyslav Bohaichuk\nVladyslav Bondar\nW. Trevor King\nWei Lin\nWeiwei Wang\nWill Fatherley\nWill McGugan\nWillem de Groot\nWilliam Grzybowski\nWilliam S.\nWilson Ong\nwouter bolsterlee\nXavier Halloran\nXiang Li\nYang Zhou\nYannick Koechlin\nYannick Péroux\nYe Cao\nYegor Roganov\nYifei Kong\nYoung-Ho Cha\nYuriy Shatrov\nYury Pliner\nYury Selivanov\nYusuke Tsutsumi\nYuval Ofir\nYuvi Panda\nZainab Lawal\nZeal Wierslee\nZlatan Sičanica\nŁukasz Setla\nМарк Коренберг\nСемён Марьясин\n",
            "new_file_content": "- Contributors -\n----------------\nA. Jesse Jiryu Davis\nAdam Bannister\nAdam Cooper\nAdam Horacek\nAdam Mills\nAdrian Krupa\nAdrián Chaves\nAhmed Tahri\nAlan Tse\nAlec Hanefeld\nAlejandro Gómez\nAleksandr Danshyn\nAleksey Kutepov\nAlex Hayes\nAlex Key\nAlex Khomchenko\nAlex Kuzmenko\nAlex Lisovoy\nAlexander Bayandin\nAlexander Karpinsky\nAlexander Koshevoy\nAlexander Malev\nAlexander Mohr\nAlexander Shorin\nAlexander Travov\nAlexandru Mihai\nAlexey Firsov\nAlexey Nikitin\nAlexey Popravka\nAlexey Stepanov\nAmin Etesamian\nAmit Tulshyan\nAmy Boyle\nAnas El Amraoui\nAnders Melchiorsen\nAndrei Ursulenko\nAndrej Antonov\nAndrew Leech\nAndrew Lytvyn\nAndrew Svetlov\nAndrew Zhou\nAndrii Soldatenko\nAnes Abismail\nAntoine Pietri\nAnton Kasyanov\nAnton Zhdan-Pushkin\nArcadiy Ivanov\nArseny Timoniq\nArtem Yushkovskiy\nArthur Darcet\nAustin Scola\nBen Bader\nBen Greiner\nBen Kallus\nBen Timby\nBenedikt Reinartz\nBob Haddleton\nBoris Feld\nBoyi Chen\nBrett Cannon\nBrian Bouterse\nBrian C. Lane\nBrian Muller\nBruce Merry\nBruno Souza Cabral\nBryan Kok\nBryce Drennan\nCarl George\nCecile Tonglet\nChien-Wei Huang\nChih-Yuan Chen\nChris AtLee\nChris Laws\nChris Moore\nChris Shucksmith\nChristopher Schmitt\nClaudiu Popa\nColin Dunklau\nCong Xu\nDamien Nadé\nDan King\nDan Xu\nDaniel García\nDaniel Golding\nDaniel Grossmann-Kavanagh\nDaniel Nelson\nDanny Song\nDavid Bibb\nDavid Michael Brown\nDenilson Amorim\nDenis Matiychuk\nDenis Moshensky\nDennis Kliban\nDima Veselov\nDimitar Dimitrov\nDiogo Dutra da Mata\nDmitriy Safonov\nDmitry Doroshev\nDmitry Erlikh\nDmitry Lukashin\nDmitry Marakasov\nDmitry Shamov\nDmitry Trofimov\nDmytro Bohomiakov\nDmytro Kuznetsov\nDustin J. Mitchell\nEduard Iskandarov\nEli Ribble\nElizabeth Leddy\nEnrique Saez\nEric Sheng\nErich Healy\nErik Peterson\nEugene Chernyshov\nEugene Naydenov\nEugene Nikolaiev\nEugene Tolmachev\nEvan Kepner\nEvert Lammerts\nFelix Yan\nFernanda Guimarães\nFichteFoll\nFlorian Scheffler\nFranek Magiera\nFrederik Gladhorn\nFrederik Peter Aalund\nGabriel Tremblay\nGang Ji\nGary Wilson Jr.\nGennady Andreyev\nGeorges Dubus\nGreg Holt\nGregory Haynes\nGus Goulart\nGustavo Carneiro\nGünther Jena\nHans Adema\nHarmon Y.\nHarry Liu\nHiroshi Ogawa\nHrishikesh Paranjape\nHu Bo\nHugh Young\nHugo Herter\nHugo Hromic\nHugo van Kemenade\nHynek Schlawack\nIgor Alexandrov\nIgor Bolshakov\nIgor Davydenko\nIgor Mozharovsky\nIgor Pavlov\nIllia Volochii\nIlya Chichak\nIlya Gruzinov\nIngmar Steen\nIvan Lakovic\nIvan Larin\nJ. Nick Koston\nJacob Champion\nJaesung Lee\nJake Davis\nJakob Ackermann\nJakub Wilk\nJan Buchar\nJan Gosmann\nJarno Elonen\nJashandeep Sohi\nJean-Baptiste Estival\nJens Steinhauser\nJeonghun Lee\nJeongkyu Shin\nJeroen van der Heijden\nJesus Cea\nJian Zeng\nJinkyu Yi\nJoel Watts\nJohn Parton\nJon Nabozny\nJonas Krüger Svensson\nJonas Obrist\nJonathan Ballet\nJonathan Wright\nJonny Tan\nJoongi Kim\nJordan Borean\nJosep Cugat\nJosh Junon\nJoshu Coats\nJulia Tsemusheva\nJulien Duponchelle\nJungkook Park\nJunjie Tao\nJunyeong Jeong\nJustas Trimailovas\nJustin Foo\nJustin Turner Arthur\nKay Zheng\nKevin Samuel\nKimmo Parviainen-Jalanko\nKirill Klenov\nKirill Malovitsa\nKonstantin Shutkin\nKonstantin Valetov\nKrzysztof Blazewicz\nKyrylo Perevozchikov\nKyungmin Lee\nLars P. Søndergaard\nLee LieWhite\nLiu Hua\nLouis-Philippe Huberdeau\nLoïc Lajeanne\nLu Gong\nLubomir Gelo\nLudovic Gasc\nLuis Pedrosa\nLukasz Marcin Dobrzanski\nMakc Belousow\nManuel Miranda\nMarat Sharafutdinov\nMarc Mueller\nMarco Paolini\nMariano Anaya\nMariusz Masztalerczuk\nMarko Kohtala\nMartijn Pieters\nMartin Melka\nMartin Richard\nMartin Sucha\nMathias Fröjdman\nMathieu Dugré\nMatt VanEseltine\nMatthias Marquardt\nMatthieu Hauglustaine\nMatthieu Rigal\nMatvey Tingaev\nMeet Mangukiya\nMeshya\nMichael Ihnatenko\nMichał Górny\nMikhail Burshteyn\nMikhail Kashkin\nMikhail Lukyanchenko\nMikhail Nacharov\nMisha Behersky\nMitchell Ferree\nMorgan Delahaye-Prat\nMoss Collum\nMun Gwan-gyeong\nNavid Sheikhol\nNicolas Braem\nNikolay Kim\nNikolay Novik\nNikolay Tiunov\nNándor Mátravölgyi\nOisin Aylward\nOlaf Conradi\nPahaz Blinov\nPanagiotis Kolokotronis\nPankaj Pandey\nParag Jain\nPau Freixes\nPaul Colomiets\nPaul J. Dorn\nPaulius Šileikis\nPaulus Schoutsen\nPavel Kamaev\nPavel Polyakov\nPavel Sapezhko\nPavol Vargovčík\nPawel Kowalski\nPawel Miech\nPepe Osca\nPhilipp A.\nPierre-Louis Peeters\nPieter van Beek\nQiao Han\nRafael Viotti\nRahul Nahata\nRaphael Bialon\nRaúl Cumplido\nRequired Field\nRobert Lu\nRobert Nikolich\nRoman Podoliaka\nRong Zhang\nSamir Akarioh\nSamuel Colvin\nSean Hunt\nSebastian Acuna\nSebastian Hanula\nSebastian Hüther\nSebastien Geffroy\nSeongSoo Cho\nSergey Ninua\nSergey Skripnick\nSerhii Charykov\nSerhii Kostel\nSerhiy Storchaka\nSimon Kennedy\nSin-Woo Bang\nStanislas Plum\nStanislav Prokop\nStefan Tjarks\nStepan Pletnev\nStephan Jaensch\nStephen Cirelli\nStephen Granade\nSteve Repsher\nSteven Seguin\nSunghyun Hwang\nSunit Deshpande\nSviatoslav Bulbakha\nSviatoslav Sydorenko\nTaha Jahangir\nTaras Voinarovskyi\nTerence Honles\nThanos Lefteris\nThijs Vermeir\nThomas Forbes\nThomas Grainger\nTolga Tezel\nTomasz Trebski\nToshiaki Tanaka\nTrinh Hoang Nhu\nTymofii Tsiapa\nVadim Suharnikov\nVaibhav Sagar\nVamsi Krishna Avula\nVasiliy Faronov\nVasyl Baran\nViacheslav Greshilov\nVictor Collod\nVictor Kovtun\nVikas Kawadia\nViktor Danyliuk\nVille Skyttä\nVincent Maillol\nVitalik Verhovodov\nVitaly Haritonsky\nVitaly Magerya\nVladimir Kamarzin\nVladimir Kozlovski\nVladimir Rutsky\nVladimir Shulyak\nVladimir Zakharov\nVladyslav Bohaichuk\nVladyslav Bondar\nW. Trevor King\nWei Lin\nWeiwei Wang\nWill Fatherley\nWill McGugan\nWillem de Groot\nWilliam Grzybowski\nWilliam S.\nWilson Ong\nwouter bolsterlee\nXavier Halloran\nXiang Li\nYang Zhou\nYannick Koechlin\nYannick Péroux\nYe Cao\nYegor Roganov\nYifei Kong\nYoung-Ho Cha\nYuriy Shatrov\nYury Pliner\nYury Selivanov\nYusuke Tsutsumi\nYuval Ofir\nYuvi Panda\nZainab Lawal\nZeal Wierslee\nZlatan Sičanica\nŁukasz Setla\nМарк Коренберг\nСемён Марьясин\n",
            "header": {
                "file": {
                    "path": "CONTRIBUTORS.txt"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "96403c2a",
                "new_commit_hash": "4bc8f533",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/CONTRIBUTORS.txt"
            },
            "plus_file": {
                "path": "b/CONTRIBUTORS.txt"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 237,
                            "length": 6
                        },
                        "new_range": {
                            "start": 237,
                            "length": 7
                        },
                        "section": "Matthieu Hauglustaine"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "Matthieu Rigal",
                                "type": "context"
                            },
                            {
                                "content": "Matvey Tingaev",
                                "type": "context"
                            },
                            {
                                "content": "Meet Mangukiya",
                                "type": "context"
                            },
                            {
                                "content": "Meshya",
                                "type": "added"
                            },
                            {
                                "content": "Michael Ihnatenko",
                                "type": "context"
                            },
                            {
                                "content": "Michał Górny",
                                "type": "context"
                            },
                            {
                                "content": "Mikhail Burshteyn",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "\"\"\"HTTP Client for asyncio.\"\"\"\n\nimport asyncio\nimport base64\nimport hashlib\nimport json\nimport os\nimport sys\nimport traceback\nimport warnings\nfrom contextlib import suppress\nfrom types import TracebackType\nfrom typing import (\n    TYPE_CHECKING,\n    Any,\n    Awaitable,\n    Callable,\n    Coroutine,\n    Final,\n    FrozenSet,\n    Generator,\n    Generic,\n    Iterable,\n    List,\n    Mapping,\n    Optional,\n    Set,\n    Tuple,\n    Type,\n    TypedDict,\n    TypeVar,\n    Union,\n)\n\nimport attr\nfrom multidict import CIMultiDict, MultiDict, MultiDictProxy, istr\nfrom yarl import URL\n\nfrom . import hdrs, http, payload\nfrom .abc import AbstractCookieJar\nfrom .client_exceptions import (\n    ClientConnectionError,\n    ClientConnectionResetError,\n    ClientConnectorCertificateError,\n    ClientConnectorError,\n    ClientConnectorSSLError,\n    ClientError,\n    ClientHttpProxyError,\n    ClientOSError,\n    ClientPayloadError,\n    ClientProxyConnectionError,\n    ClientResponseError,\n    ClientSSLError,\n    ConnectionTimeoutError,\n    ContentTypeError,\n    InvalidURL,\n    InvalidUrlClientError,\n    InvalidUrlRedirectClientError,\n    NonHttpUrlClientError,\n    NonHttpUrlRedirectClientError,\n    RedirectClientError,\n    ServerConnectionError,\n    ServerDisconnectedError,\n    ServerFingerprintMismatch,\n    ServerTimeoutError,\n    SocketTimeoutError,\n    TooManyRedirects,\n    WSServerHandshakeError,\n)\nfrom .client_reqrep import (\n    ClientRequest as ClientRequest,\n    ClientResponse as ClientResponse,\n    Fingerprint as Fingerprint,\n    RequestInfo as RequestInfo,\n    _merge_ssl_params,\n)\nfrom .client_ws import (\n    DEFAULT_WS_CLIENT_TIMEOUT,\n    ClientWebSocketResponse as ClientWebSocketResponse,\n    ClientWSTimeout as ClientWSTimeout,\n)\nfrom .connector import (\n    HTTP_AND_EMPTY_SCHEMA_SET,\n    BaseConnector as BaseConnector,\n    NamedPipeConnector as NamedPipeConnector,\n    TCPConnector as TCPConnector,\n    UnixConnector as UnixConnector,\n)\nfrom .cookiejar import CookieJar\nfrom .helpers import (\n    _SENTINEL,\n    DEBUG,\n    BasicAuth,\n    TimeoutHandle,\n    ceil_timeout,\n    get_env_proxy_for_url,\n    method_must_be_empty_body,\n    sentinel,\n    strip_auth_from_url,\n)\nfrom .http import WS_KEY, HttpVersion, WebSocketReader, WebSocketWriter\nfrom .http_websocket import WSHandshakeError, WSMessage, ws_ext_gen, ws_ext_parse\nfrom .streams import FlowControlDataQueue\nfrom .tracing import Trace, TraceConfig\nfrom .typedefs import JSONEncoder, LooseCookies, LooseHeaders, Query, StrOrURL\n\n__all__ = (\n    # client_exceptions\n    \"ClientConnectionError\",\n    \"ClientConnectionResetError\",\n    \"ClientConnectorCertificateError\",\n    \"ClientConnectorError\",\n    \"ClientConnectorSSLError\",\n    \"ClientError\",\n    \"ClientHttpProxyError\",\n    \"ClientOSError\",\n    \"ClientPayloadError\",\n    \"ClientProxyConnectionError\",\n    \"ClientResponseError\",\n    \"ClientSSLError\",\n    \"ConnectionTimeoutError\",\n    \"ContentTypeError\",\n    \"InvalidURL\",\n    \"InvalidUrlClientError\",\n    \"RedirectClientError\",\n    \"NonHttpUrlClientError\",\n    \"InvalidUrlRedirectClientError\",\n    \"NonHttpUrlRedirectClientError\",\n    \"ServerConnectionError\",\n    \"ServerDisconnectedError\",\n    \"ServerFingerprintMismatch\",\n    \"ServerTimeoutError\",\n    \"SocketTimeoutError\",\n    \"TooManyRedirects\",\n    \"WSServerHandshakeError\",\n    # client_reqrep\n    \"ClientRequest\",\n    \"ClientResponse\",\n    \"Fingerprint\",\n    \"RequestInfo\",\n    # connector\n    \"BaseConnector\",\n    \"TCPConnector\",\n    \"UnixConnector\",\n    \"NamedPipeConnector\",\n    # client_ws\n    \"ClientWebSocketResponse\",\n    # client\n    \"ClientSession\",\n    \"ClientTimeout\",\n    \"ClientWSTimeout\",\n    \"request\",\n)\n\n\nif TYPE_CHECKING:\n    from ssl import SSLContext\nelse:\n    SSLContext = None\n\nif sys.version_info >= (3, 11) and TYPE_CHECKING:\n    from typing import Unpack\n\n\nclass _RequestOptions(TypedDict, total=False):\n    params: Query\n    data: Any\n    json: Any\n    cookies: Union[LooseCookies, None]\n    headers: Union[LooseHeaders, None]\n    skip_auto_headers: Union[Iterable[str], None]\n    auth: Union[BasicAuth, None]\n    allow_redirects: bool\n    max_redirects: int\n    compress: Union[str, bool, None]\n    chunked: Union[bool, None]\n    expect100: bool\n    raise_for_status: Union[None, bool, Callable[[ClientResponse], Awaitable[None]]]\n    read_until_eof: bool\n    proxy: Union[StrOrURL, None]\n    proxy_auth: Union[BasicAuth, None]\n    timeout: \"Union[ClientTimeout, _SENTINEL, None]\"\n    ssl: Union[SSLContext, bool, Fingerprint]\n    server_hostname: Union[str, None]\n    proxy_headers: Union[LooseHeaders, None]\n    trace_request_ctx: Union[Mapping[str, str], None]\n    read_bufsize: Union[int, None]\n    auto_decompress: Union[bool, None]\n    max_line_size: Union[int, None]\n    max_field_size: Union[int, None]\n\n\n@attr.s(auto_attribs=True, frozen=True, slots=True)\nclass ClientTimeout:\n    total: Optional[float] = None\n    connect: Optional[float] = None\n    sock_read: Optional[float] = None\n    sock_connect: Optional[float] = None\n    ceil_threshold: float = 5\n\n    # pool_queue_timeout: Optional[float] = None\n    # dns_resolution_timeout: Optional[float] = None\n    # socket_connect_timeout: Optional[float] = None\n    # connection_acquiring_timeout: Optional[float] = None\n    # new_connection_timeout: Optional[float] = None\n    # http_header_timeout: Optional[float] = None\n    # response_body_timeout: Optional[float] = None\n\n    # to create a timeout specific for a single request, either\n    # - create a completely new one to overwrite the default\n    # - or use http://www.attrs.org/en/stable/api.html#attr.evolve\n    # to overwrite the defaults\n\n\n# 5 Minute default read timeout\nDEFAULT_TIMEOUT: Final[ClientTimeout] = ClientTimeout(total=5 * 60)\n\n# https://www.rfc-editor.org/rfc/rfc9110#section-9.2.2\nIDEMPOTENT_METHODS = frozenset({\"GET\", \"HEAD\", \"OPTIONS\", \"TRACE\", \"PUT\", \"DELETE\"})\n\n_RetType = TypeVar(\"_RetType\", ClientResponse, ClientWebSocketResponse)\n_CharsetResolver = Callable[[ClientResponse, bytes], str]\n\n\nclass ClientSession:\n    \"\"\"First-class interface for making HTTP requests.\"\"\"\n\n    ATTRS = frozenset(\n        [\n            \"_base_url\",\n            \"_source_traceback\",\n            \"_connector\",\n            \"requote_redirect_url\",\n            \"_loop\",\n            \"_cookie_jar\",\n            \"_connector_owner\",\n            \"_default_auth\",\n            \"_version\",\n            \"_json_serialize\",\n            \"_requote_redirect_url\",\n            \"_timeout\",\n            \"_raise_for_status\",\n            \"_auto_decompress\",\n            \"_trust_env\",\n            \"_default_headers\",\n            \"_skip_auto_headers\",\n            \"_request_class\",\n            \"_response_class\",\n            \"_ws_response_class\",\n            \"_trace_configs\",\n            \"_read_bufsize\",\n            \"_max_line_size\",\n            \"_max_field_size\",\n            \"_resolve_charset\",\n        ]\n    )\n\n    _source_traceback: Optional[traceback.StackSummary] = None\n    _connector: Optional[BaseConnector] = None\n\n    def __init__(\n        self,\n        base_url: Optional[StrOrURL] = None,\n        *,\n        connector: Optional[BaseConnector] = None,\n        loop: Optional[asyncio.AbstractEventLoop] = None,\n        cookies: Optional[LooseCookies] = None,\n        headers: Optional[LooseHeaders] = None,\n        skip_auto_headers: Optional[Iterable[str]] = None,\n        auth: Optional[BasicAuth] = None,\n        json_serialize: JSONEncoder = json.dumps,\n        request_class: Type[ClientRequest] = ClientRequest,\n        response_class: Type[ClientResponse] = ClientResponse,\n        ws_response_class: Type[ClientWebSocketResponse] = ClientWebSocketResponse,\n        version: HttpVersion = http.HttpVersion11,\n        cookie_jar: Optional[AbstractCookieJar] = None,\n        connector_owner: bool = True,\n        raise_for_status: Union[\n            bool, Callable[[ClientResponse], Awaitable[None]]\n        ] = False,\n        read_timeout: Union[float, _SENTINEL] = sentinel,\n        conn_timeout: Optional[float] = None,\n        timeout: Union[object, ClientTimeout] = sentinel,\n        auto_decompress: bool = True,\n        trust_env: bool = False,\n        requote_redirect_url: bool = True,\n        trace_configs: Optional[List[TraceConfig]] = None,\n        read_bufsize: int = 2**16,\n        max_line_size: int = 8190,\n        max_field_size: int = 8190,\n        fallback_charset_resolver: _CharsetResolver = lambda r, b: \"utf-8\",\n    ) -> None:\n        # We initialise _connector to None immediately, as it's referenced in __del__()\n        # and could cause issues if an exception occurs during initialisation.\n        self._connector: Optional[BaseConnector] = None\n\n        if loop is None:\n            if connector is not None:\n                loop = connector._loop\n\n        loop = loop or asyncio.get_running_loop()\n\n        if base_url is None or isinstance(base_url, URL):\n            self._base_url: Optional[URL] = base_url\n        else:\n            self._base_url = URL(base_url)\n            assert (\n                self._base_url.origin() == self._base_url\n            ), \"Only absolute URLs without path part are supported\"\n\n        if timeout is sentinel or timeout is None:\n            self._timeout = DEFAULT_TIMEOUT\n            if read_timeout is not sentinel:\n                warnings.warn(\n                    \"read_timeout is deprecated, use timeout argument instead\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n                self._timeout = attr.evolve(self._timeout, total=read_timeout)\n            if conn_timeout is not None:\n                self._timeout = attr.evolve(self._timeout, connect=conn_timeout)\n                warnings.warn(\n                    \"conn_timeout is deprecated, use timeout argument instead\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n        else:\n            if not isinstance(timeout, ClientTimeout):\n                raise ValueError(\n                    f\"timeout parameter cannot be of {type(timeout)} type, \"\n                    \"please use 'timeout=ClientTimeout(...)'\",\n                )\n            self._timeout = timeout\n            if read_timeout is not sentinel:\n                raise ValueError(\n                    \"read_timeout and timeout parameters \"\n                    \"conflict, please setup \"\n                    \"timeout.read\"\n                )\n            if conn_timeout is not None:\n                raise ValueError(\n                    \"conn_timeout and timeout parameters \"\n                    \"conflict, please setup \"\n                    \"timeout.connect\"\n                )\n\n        if connector is None:\n            connector = TCPConnector(loop=loop)\n\n        if connector._loop is not loop:\n            raise RuntimeError(\"Session and connector has to use same event loop\")\n\n        self._loop = loop\n\n        if loop.get_debug():\n            self._source_traceback = traceback.extract_stack(sys._getframe(1))\n\n        if cookie_jar is None:\n            cookie_jar = CookieJar(loop=loop)\n        self._cookie_jar = cookie_jar\n\n        if cookies is not None:\n            self._cookie_jar.update_cookies(cookies)\n\n        self._connector = connector\n        self._connector_owner = connector_owner\n        self._default_auth = auth\n        self._version = version\n        self._json_serialize = json_serialize\n        self._raise_for_status = raise_for_status\n        self._auto_decompress = auto_decompress\n        self._trust_env = trust_env\n        self._requote_redirect_url = requote_redirect_url\n        self._read_bufsize = read_bufsize\n        self._max_line_size = max_line_size\n        self._max_field_size = max_field_size\n\n        # Convert to list of tuples\n        if headers:\n            real_headers: CIMultiDict[str] = CIMultiDict(headers)\n        else:\n            real_headers = CIMultiDict()\n        self._default_headers: CIMultiDict[str] = real_headers\n        if skip_auto_headers is not None:\n            self._skip_auto_headers = frozenset(istr(i) for i in skip_auto_headers)\n        else:\n            self._skip_auto_headers = frozenset()\n\n        self._request_class = request_class\n        self._response_class = response_class\n        self._ws_response_class = ws_response_class\n\n        self._trace_configs = trace_configs or []\n        for trace_config in self._trace_configs:\n            trace_config.freeze()\n\n        self._resolve_charset = fallback_charset_resolver\n\n    def __init_subclass__(cls: Type[\"ClientSession\"]) -> None:\n        warnings.warn(\n            \"Inheritance class {} from ClientSession \"\n            \"is discouraged\".format(cls.__name__),\n            DeprecationWarning,\n            stacklevel=2,\n        )\n\n    if DEBUG:\n\n        def __setattr__(self, name: str, val: Any) -> None:\n            if name not in self.ATTRS:\n                warnings.warn(\n                    \"Setting custom ClientSession.{} attribute \"\n                    \"is discouraged\".format(name),\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n            super().__setattr__(name, val)\n\n    def __del__(self, _warnings: Any = warnings) -> None:\n        if not self.closed:\n            kwargs = {\"source\": self}\n            _warnings.warn(\n                f\"Unclosed client session {self!r}\", ResourceWarning, **kwargs\n            )\n            context = {\"client_session\": self, \"message\": \"Unclosed client session\"}\n            if self._source_traceback is not None:\n                context[\"source_traceback\"] = self._source_traceback\n            self._loop.call_exception_handler(context)\n\n    if sys.version_info >= (3, 11) and TYPE_CHECKING:\n\n        def request(\n            self,\n            method: str,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n    else:\n\n        def request(\n            self, method: str, url: StrOrURL, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP request.\"\"\"\n            return _RequestContextManager(self._request(method, url, **kwargs))\n\n    def _build_url(self, str_or_url: StrOrURL) -> URL:\n        url = URL(str_or_url)\n        if self._base_url is None:\n            return url\n        else:\n            assert not url.absolute and url.path.startswith(\"/\")\n            return self._base_url.join(url)\n\n    async def _request(\n        self,\n        method: str,\n        str_or_url: StrOrURL,\n        *,\n        params: Query = None,\n        data: Any = None,\n        json: Any = None,\n        cookies: Optional[LooseCookies] = None,\n        headers: Optional[LooseHeaders] = None,\n        skip_auto_headers: Optional[Iterable[str]] = None,\n        auth: Optional[BasicAuth] = None,\n        allow_redirects: bool = True,\n        max_redirects: int = 10,\n        compress: Union[str, bool, None] = None,\n        chunked: Optional[bool] = None,\n        expect100: bool = False,\n        raise_for_status: Union[\n            None, bool, Callable[[ClientResponse], Awaitable[None]]\n        ] = None,\n        read_until_eof: bool = True,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        timeout: Union[ClientTimeout, _SENTINEL] = sentinel,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        server_hostname: Optional[str] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        trace_request_ctx: Optional[Mapping[str, str]] = None,\n        read_bufsize: Optional[int] = None,\n        auto_decompress: Optional[bool] = None,\n        max_line_size: Optional[int] = None,\n        max_field_size: Optional[int] = None,\n    ) -> ClientResponse:\n\n        # NOTE: timeout clamps existing connect and read timeouts.  We cannot\n        # set the default to None because we need to detect if the user wants\n        # to use the existing timeouts by setting timeout to None.\n\n        if self.closed:\n            raise RuntimeError(\"Session is closed\")\n\n        ssl = _merge_ssl_params(ssl, verify_ssl, ssl_context, fingerprint)\n\n        if data is not None and json is not None:\n            raise ValueError(\n                \"data and json parameters can not be used at the same time\"\n            )\n        elif json is not None:\n            data = payload.JsonPayload(json, dumps=self._json_serialize)\n\n        if not isinstance(chunked, bool) and chunked is not None:\n            warnings.warn(\"Chunk size is deprecated #1615\", DeprecationWarning)\n\n        redirects = 0\n        history = []\n        version = self._version\n        params = params or {}\n\n        # Merge with default headers and transform to CIMultiDict\n        headers = self._prepare_headers(headers)\n\n        try:\n            url = self._build_url(str_or_url)\n        except ValueError as e:\n            raise InvalidUrlClientError(str_or_url) from e\n\n        assert self._connector is not None\n        if url.scheme not in self._connector.allowed_protocol_schema_set:\n            raise NonHttpUrlClientError(url)\n\n        skip_headers = set(self._skip_auto_headers)\n        if skip_auto_headers is not None:\n            for i in skip_auto_headers:\n                skip_headers.add(istr(i))\n\n        if proxy is None:\n            proxy_headers = None\n        else:\n            proxy_headers = self._prepare_headers(proxy_headers)\n            try:\n                proxy = URL(proxy)\n            except ValueError as e:\n                raise InvalidURL(proxy) from e\n\n        if timeout is sentinel:\n            real_timeout: ClientTimeout = self._timeout\n        else:\n            if not isinstance(timeout, ClientTimeout):\n                real_timeout = ClientTimeout(total=timeout)\n            else:\n                real_timeout = timeout\n        # timeout is cumulative for all request operations\n        # (request, redirects, responses, data consuming)\n        tm = TimeoutHandle(\n            self._loop, real_timeout.total, ceil_threshold=real_timeout.ceil_threshold\n        )\n        handle = tm.start()\n\n        if read_bufsize is None:\n            read_bufsize = self._read_bufsize\n\n        if auto_decompress is None:\n            auto_decompress = self._auto_decompress\n\n        if max_line_size is None:\n            max_line_size = self._max_line_size\n\n        if max_field_size is None:\n            max_field_size = self._max_field_size\n\n        traces = [\n            Trace(\n                self,\n                trace_config,\n                trace_config.trace_config_ctx(trace_request_ctx=trace_request_ctx),\n            )\n            for trace_config in self._trace_configs\n        ]\n\n        for trace in traces:\n            await trace.send_request_start(method, url.update_query(params), headers)\n\n        timer = tm.timer()\n        try:\n            with timer:\n                # https://www.rfc-editor.org/rfc/rfc9112.html#name-retrying-requests\n                retry_persistent_connection = method in IDEMPOTENT_METHODS\n                while True:\n                    url, auth_from_url = strip_auth_from_url(url)\n                    if not url.raw_host:\n                        # NOTE: Bail early, otherwise, causes `InvalidURL` through\n                        # NOTE: `self._request_class()` below.\n                        err_exc_cls = (\n                            InvalidUrlRedirectClientError\n                            if redirects\n                            else InvalidUrlClientError\n                        )\n                        raise err_exc_cls(url)\n                    if auth and auth_from_url:\n                        raise ValueError(\n                            \"Cannot combine AUTH argument with \"\n                            \"credentials encoded in URL\"\n                        )\n\n                    if auth is None:\n                        auth = auth_from_url\n\n                    if auth is None and (\n                        not self._base_url or self._base_url.origin() == url.origin()\n                    ):\n                        auth = self._default_auth\n                    # It would be confusing if we support explicit\n                    # Authorization header with auth argument\n                    if (\n                        headers is not None\n                        and auth is not None\n                        and hdrs.AUTHORIZATION in headers\n                    ):\n                        raise ValueError(\n                            \"Cannot combine AUTHORIZATION header \"\n                            \"with AUTH argument or credentials \"\n                            \"encoded in URL\"\n                        )\n\n                    all_cookies = self._cookie_jar.filter_cookies(url)\n\n                    if cookies is not None:\n                        tmp_cookie_jar = CookieJar()\n                        tmp_cookie_jar.update_cookies(cookies)\n                        req_cookies = tmp_cookie_jar.filter_cookies(url)\n                        if req_cookies:\n                            all_cookies.load(req_cookies)\n\n                    if proxy is not None:\n                        proxy = URL(proxy)\n                    elif self._trust_env:\n                        with suppress(LookupError):\n                            proxy, proxy_auth = get_env_proxy_for_url(url)\n\n                    req = self._request_class(\n                        method,\n                        url,\n                        params=params,\n                        headers=headers,\n                        skip_auto_headers=skip_headers if skip_headers else None,\n                        data=data,\n                        cookies=all_cookies,\n                        auth=auth,\n                        version=version,\n                        compress=compress,\n                        chunked=chunked,\n                        expect100=expect100,\n                        loop=self._loop,\n                        response_class=self._response_class,\n                        proxy=proxy,\n                        proxy_auth=proxy_auth,\n                        timer=timer,\n                        session=self,\n                        ssl=ssl if ssl is not None else True,\n                        server_hostname=server_hostname,\n                        proxy_headers=proxy_headers,\n                        traces=traces,\n                        trust_env=self.trust_env,\n                    )\n\n                    # connection timeout\n                    try:\n                        async with ceil_timeout(\n                            real_timeout.connect,\n                            ceil_threshold=real_timeout.ceil_threshold,\n                        ):\n                            conn = await self._connector.connect(\n                                req, traces=traces, timeout=real_timeout\n                            )\n                    except asyncio.TimeoutError as exc:\n                        raise ConnectionTimeoutError(\n                            f\"Connection timeout to host {url}\"\n                        ) from exc\n\n                    assert conn.transport is not None\n\n                    assert conn.protocol is not None\n                    conn.protocol.set_response_params(\n                        timer=timer,\n                        skip_payload=method_must_be_empty_body(method),\n                        read_until_eof=read_until_eof,\n                        auto_decompress=auto_decompress,\n                        read_timeout=real_timeout.sock_read,\n                        read_bufsize=read_bufsize,\n                        timeout_ceil_threshold=self._connector._timeout_ceil_threshold,\n                        max_line_size=max_line_size,\n                        max_field_size=max_field_size,\n                    )\n\n                    try:\n                        try:\n                            resp = await req.send(conn)\n                            try:\n                                await resp.start(conn)\n                            except BaseException:\n                                resp.close()\n                                raise\n                        except BaseException:\n                            conn.close()\n                            raise\n                    except (ClientOSError, ServerDisconnectedError):\n                        if retry_persistent_connection:\n                            retry_persistent_connection = False\n                            continue\n                        raise\n                    except ClientError:\n                        raise\n                    except OSError as exc:\n                        if exc.errno is None and isinstance(exc, asyncio.TimeoutError):\n                            raise\n                        raise ClientOSError(*exc.args) from exc\n\n                    self._cookie_jar.update_cookies(resp.cookies, resp.url)\n\n                    # redirects\n                    if resp.status in (301, 302, 303, 307, 308) and allow_redirects:\n\n                        for trace in traces:\n                            await trace.send_request_redirect(\n                                method, url.update_query(params), headers, resp\n                            )\n\n                        redirects += 1\n                        history.append(resp)\n                        if max_redirects and redirects >= max_redirects:\n                            resp.close()\n                            raise TooManyRedirects(\n                                history[0].request_info, tuple(history)\n                            )\n\n                        # For 301 and 302, mimic IE, now changed in RFC\n                        # https://github.com/kennethreitz/requests/pull/269\n                        if (resp.status == 303 and resp.method != hdrs.METH_HEAD) or (\n                            resp.status in (301, 302) and resp.method == hdrs.METH_POST\n                        ):\n                            method = hdrs.METH_GET\n                            data = None\n                            if headers.get(hdrs.CONTENT_LENGTH):\n                                headers.pop(hdrs.CONTENT_LENGTH)\n\n                        r_url = resp.headers.get(hdrs.LOCATION) or resp.headers.get(\n                            hdrs.URI\n                        )\n                        if r_url is None:\n                            # see github.com/aio-libs/aiohttp/issues/2022\n                            break\n                        else:\n                            # reading from correct redirection\n                            # response is forbidden\n                            resp.release()\n\n                        try:\n                            parsed_redirect_url = URL(\n                                r_url, encoded=not self._requote_redirect_url\n                            )\n                        except ValueError as e:\n                            raise InvalidUrlRedirectClientError(\n                                r_url,\n                                \"Server attempted redirecting to a location that does not look like a URL\",\n                            ) from e\n\n                        scheme = parsed_redirect_url.scheme\n                        if scheme not in HTTP_AND_EMPTY_SCHEMA_SET:\n                            resp.close()\n                            raise NonHttpUrlRedirectClientError(r_url)\n                        elif not scheme:\n                            parsed_redirect_url = url.join(parsed_redirect_url)\n\n                        try:\n                            redirect_origin = parsed_redirect_url.origin()\n                        except ValueError as origin_val_err:\n                            raise InvalidUrlRedirectClientError(\n                                parsed_redirect_url,\n                                \"Invalid redirect URL origin\",\n                            ) from origin_val_err\n\n                        if url.origin() != redirect_origin:\n                            auth = None\n                            headers.pop(hdrs.AUTHORIZATION, None)\n\n                        url = parsed_redirect_url\n                        params = {}\n                        resp.release()\n                        continue\n\n                    break\n\n            # check response status\n            if raise_for_status is None:\n                raise_for_status = self._raise_for_status\n\n            if raise_for_status is None:\n                pass\n            elif callable(raise_for_status):\n                await raise_for_status(resp)\n            elif raise_for_status:\n                resp.raise_for_status()\n\n            # register connection\n            if handle is not None:\n                if resp.connection is not None:\n                    resp.connection.add_callback(handle.cancel)\n                else:\n                    handle.cancel()\n\n            resp._history = tuple(history)\n\n            for trace in traces:\n                await trace.send_request_end(\n                    method, url.update_query(params), headers, resp\n                )\n            return resp\n\n        except BaseException as e:\n            # cleanup timer\n            tm.close()\n            if handle:\n                handle.cancel()\n                handle = None\n\n            for trace in traces:\n                await trace.send_request_exception(\n                    method, url.update_query(params), headers, e\n                )\n            raise\n\n    def ws_connect(\n        self,\n        url: StrOrURL,\n        *,\n        method: str = hdrs.METH_GET,\n        protocols: Iterable[str] = (),\n        timeout: Union[ClientWSTimeout, _SENTINEL] = sentinel,\n        receive_timeout: Optional[float] = None,\n        autoclose: bool = True,\n        autoping: bool = True,\n        heartbeat: Optional[float] = None,\n        auth: Optional[BasicAuth] = None,\n        origin: Optional[str] = None,\n        params: Query = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        compress: int = 0,\n        max_msg_size: int = 4 * 1024 * 1024,\n    ) -> \"_WSRequestContextManager\":\n        \"\"\"Initiate websocket connection.\"\"\"\n        return _WSRequestContextManager(\n            self._ws_connect(\n                url,\n                method=method,\n                protocols=protocols,\n                timeout=timeout,\n                receive_timeout=receive_timeout,\n                autoclose=autoclose,\n                autoping=autoping,\n                heartbeat=heartbeat,\n                auth=auth,\n                origin=origin,\n                params=params,\n                headers=headers,\n                proxy=proxy,\n                proxy_auth=proxy_auth,\n                ssl=ssl,\n                verify_ssl=verify_ssl,\n                fingerprint=fingerprint,\n                ssl_context=ssl_context,\n                proxy_headers=proxy_headers,\n                compress=compress,\n                max_msg_size=max_msg_size,\n            )\n        )\n\n    async def _ws_connect(\n        self,\n        url: StrOrURL,\n        *,\n        method: str = hdrs.METH_GET,\n        protocols: Iterable[str] = (),\n        timeout: Union[ClientWSTimeout, _SENTINEL] = sentinel,\n        receive_timeout: Optional[float] = None,\n        autoclose: bool = True,\n        autoping: bool = True,\n        heartbeat: Optional[float] = None,\n        auth: Optional[BasicAuth] = None,\n        origin: Optional[str] = None,\n        params: Query = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        compress: int = 0,\n        max_msg_size: int = 4 * 1024 * 1024,\n    ) -> ClientWebSocketResponse:\n        if timeout is not sentinel:\n            if isinstance(timeout, ClientWSTimeout):\n                ws_timeout = timeout\n            else:\n                warnings.warn(\n                    \"parameter 'timeout' of type 'float' \"\n                    \"is deprecated, please use \"\n                    \"'timeout=ClientWSTimeout(ws_close=...)'\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n                ws_timeout = ClientWSTimeout(ws_close=timeout)\n        else:\n            ws_timeout = DEFAULT_WS_CLIENT_TIMEOUT\n        if receive_timeout is not None:\n            warnings.warn(\n                \"float parameter 'receive_timeout' \"\n                \"is deprecated, please use parameter \"\n                \"'timeout=ClientWSTimeout(ws_receive=...)'\",\n                DeprecationWarning,\n                stacklevel=2,\n            )\n            ws_timeout = attr.evolve(ws_timeout, ws_receive=receive_timeout)\n\n        if headers is None:\n            real_headers: CIMultiDict[str] = CIMultiDict()\n        else:\n            real_headers = CIMultiDict(headers)\n\n        default_headers = {\n            hdrs.UPGRADE: \"websocket\",\n            hdrs.CONNECTION: \"Upgrade\",\n            hdrs.SEC_WEBSOCKET_VERSION: \"13\",\n        }\n\n        for key, value in default_headers.items():\n            real_headers.setdefault(key, value)\n\n        sec_key = base64.b64encode(os.urandom(16))\n        real_headers[hdrs.SEC_WEBSOCKET_KEY] = sec_key.decode()\n\n        if protocols:\n            real_headers[hdrs.SEC_WEBSOCKET_PROTOCOL] = \",\".join(protocols)\n        if origin is not None:\n            real_headers[hdrs.ORIGIN] = origin\n        if compress:\n            extstr = ws_ext_gen(compress=compress)\n            real_headers[hdrs.SEC_WEBSOCKET_EXTENSIONS] = extstr\n\n        # For the sake of backward compatibility, if user passes in None, convert it to True\n        if ssl is None:\n            warnings.warn(\n                \"ssl=None is deprecated, please use ssl=True\",\n                DeprecationWarning,\n                stacklevel=2,\n            )\n            ssl = True\n        ssl = _merge_ssl_params(ssl, verify_ssl, ssl_context, fingerprint)\n\n        # send request\n        resp = await self.request(\n            method,\n            url,\n            params=params,\n            headers=real_headers,\n            read_until_eof=False,\n            auth=auth,\n            proxy=proxy,\n            proxy_auth=proxy_auth,\n            ssl=ssl,\n            proxy_headers=proxy_headers,\n        )\n\n        try:\n            # check handshake\n            if resp.status != 101:\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid response status\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            if resp.headers.get(hdrs.UPGRADE, \"\").lower() != \"websocket\":\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid upgrade header\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            if resp.headers.get(hdrs.CONNECTION, \"\").lower() != \"upgrade\":\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid connection header\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            # key calculation\n            r_key = resp.headers.get(hdrs.SEC_WEBSOCKET_ACCEPT, \"\")\n            match = base64.b64encode(hashlib.sha1(sec_key + WS_KEY).digest()).decode()\n            if r_key != match:\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid challenge response\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            # websocket protocol\n            protocol = None\n            if protocols and hdrs.SEC_WEBSOCKET_PROTOCOL in resp.headers:\n                resp_protocols = [\n                    proto.strip()\n                    for proto in resp.headers[hdrs.SEC_WEBSOCKET_PROTOCOL].split(\",\")\n                ]\n\n                for proto in resp_protocols:\n                    if proto in protocols:\n                        protocol = proto\n                        break\n\n            # websocket compress\n            notakeover = False\n            if compress:\n                compress_hdrs = resp.headers.get(hdrs.SEC_WEBSOCKET_EXTENSIONS)\n                if compress_hdrs:\n                    try:\n                        compress, notakeover = ws_ext_parse(compress_hdrs)\n                    except WSHandshakeError as exc:\n                        raise WSServerHandshakeError(\n                            resp.request_info,\n                            resp.history,\n                            message=exc.args[0],\n                            status=resp.status,\n                            headers=resp.headers,\n                        ) from exc\n                else:\n                    compress = 0\n                    notakeover = False\n\n            conn = resp.connection\n            assert conn is not None\n            conn_proto = conn.protocol\n            assert conn_proto is not None\n\n            # For WS connection the read_timeout must be either receive_timeout or greater\n            # None == no timeout, i.e. infinite timeout, so None is the max timeout possible\n            if ws_timeout.ws_receive is None:\n                # Reset regardless\n                conn_proto.read_timeout = None\n            elif conn_proto.read_timeout is not None:\n                conn_proto.read_timeout = max(\n                    ws_timeout.ws_receive, conn_proto.read_timeout\n                )\n\n            transport = conn.transport\n            assert transport is not None\n            reader: FlowControlDataQueue[WSMessage] = FlowControlDataQueue(\n                conn_proto, 2**16, loop=self._loop\n            )\n            conn_proto.set_parser(WebSocketReader(reader, max_msg_size), reader)\n            writer = WebSocketWriter(\n                conn_proto,\n                transport,\n                use_mask=True,\n                compress=compress,\n                notakeover=notakeover,\n            )\n        except BaseException:\n            resp.close()\n            raise\n        else:\n            return self._ws_response_class(\n                reader,\n                writer,\n                protocol,\n                resp,\n                ws_timeout,\n                autoclose,\n                autoping,\n                self._loop,\n                heartbeat=heartbeat,\n                compress=compress,\n                client_notakeover=notakeover,\n            )\n\n    def _prepare_headers(self, headers: Optional[LooseHeaders]) -> \"CIMultiDict[str]\":\n        \"\"\"Add default headers and transform it to CIMultiDict\"\"\"\n        # Convert headers to MultiDict\n        result = CIMultiDict(self._default_headers)\n        if headers:\n            if not isinstance(headers, (MultiDictProxy, MultiDict)):\n                headers = CIMultiDict(headers)\n            added_names: Set[str] = set()\n            for key, value in headers.items():\n                if key in added_names:\n                    result.add(key, value)\n                else:\n                    result[key] = value\n                    added_names.add(key)\n        return result\n\n    if sys.version_info >= (3, 11) and TYPE_CHECKING:\n\n        def get(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def options(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def head(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def post(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def put(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def patch(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def delete(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n    else:\n\n        def get(\n            self, url: StrOrURL, *, allow_redirects: bool = True, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP GET request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_GET, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def options(\n            self, url: StrOrURL, *, allow_redirects: bool = True, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP OPTIONS request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_OPTIONS, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def head(\n            self, url: StrOrURL, *, allow_redirects: bool = False, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP HEAD request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_HEAD, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def post(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP POST request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_POST, url, data=data, **kwargs)\n            )\n\n        def put(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP PUT request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_PUT, url, data=data, **kwargs)\n            )\n\n        def patch(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP PATCH request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_PATCH, url, data=data, **kwargs)\n            )\n\n        def delete(self, url: StrOrURL, **kwargs: Any) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP DELETE request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_DELETE, url, **kwargs)\n            )\n\n    async def close(self) -> None:\n        \"\"\"Close underlying connector.\n\n        Release all acquired resources.\n        \"\"\"\n        if not self.closed:\n            if self._connector is not None and self._connector_owner:\n                await self._connector.close()\n            self._connector = None\n\n    @property\n    def closed(self) -> bool:\n        \"\"\"Is client session closed.\n\n        A readonly property.\n        \"\"\"\n        return self._connector is None or self._connector.closed\n\n    @property\n    def connector(self) -> Optional[BaseConnector]:\n        \"\"\"Connector instance used for the session.\"\"\"\n        return self._connector\n\n    @property\n    def cookie_jar(self) -> AbstractCookieJar:\n        \"\"\"The session cookies.\"\"\"\n        return self._cookie_jar\n\n    @property\n    def version(self) -> Tuple[int, int]:\n        \"\"\"The session HTTP protocol version.\"\"\"\n        return self._version\n\n    @property\n    def requote_redirect_url(self) -> bool:\n        \"\"\"Do URL requoting on redirection handling.\"\"\"\n        return self._requote_redirect_url\n\n    @requote_redirect_url.setter\n    def requote_redirect_url(self, val: bool) -> None:\n        \"\"\"Do URL requoting on redirection handling.\"\"\"\n        warnings.warn(\n            \"session.requote_redirect_url modification is deprecated #2778\",\n            DeprecationWarning,\n            stacklevel=2,\n        )\n        self._requote_redirect_url = val\n\n    @property\n    def loop(self) -> asyncio.AbstractEventLoop:\n        \"\"\"Session's loop.\"\"\"\n        warnings.warn(\n            \"client.loop property is deprecated\", DeprecationWarning, stacklevel=2\n        )\n        return self._loop\n\n    @property\n    def timeout(self) -> ClientTimeout:\n        \"\"\"Timeout for the session.\"\"\"\n        return self._timeout\n\n    @property\n    def headers(self) -> \"CIMultiDict[str]\":\n        \"\"\"The default headers of the client session.\"\"\"\n        return self._default_headers\n\n    @property\n    def skip_auto_headers(self) -> FrozenSet[istr]:\n        \"\"\"Headers for which autogeneration should be skipped\"\"\"\n        return self._skip_auto_headers\n\n    @property\n    def auth(self) -> Optional[BasicAuth]:\n        \"\"\"An object that represents HTTP Basic Authorization\"\"\"\n        return self._default_auth\n\n    @property\n    def json_serialize(self) -> JSONEncoder:\n        \"\"\"Json serializer callable\"\"\"\n        return self._json_serialize\n\n    @property\n    def connector_owner(self) -> bool:\n        \"\"\"Should connector be closed on session closing\"\"\"\n        return self._connector_owner\n\n    @property\n    def raise_for_status(\n        self,\n    ) -> Union[bool, Callable[[ClientResponse], Awaitable[None]]]:\n        \"\"\"Should `ClientResponse.raise_for_status()` be called for each response.\"\"\"\n        return self._raise_for_status\n\n    @property\n    def auto_decompress(self) -> bool:\n        \"\"\"Should the body response be automatically decompressed.\"\"\"\n        return self._auto_decompress\n\n    @property\n    def trust_env(self) -> bool:\n        \"\"\"\n        Should proxies information from environment or netrc be trusted.\n\n        Information is from HTTP_PROXY / HTTPS_PROXY environment variables\n        or ~/.netrc file if present.\n        \"\"\"\n        return self._trust_env\n\n    @property\n    def trace_configs(self) -> List[TraceConfig]:\n        \"\"\"A list of TraceConfig instances used for client tracing\"\"\"\n        return self._trace_configs\n\n    def detach(self) -> None:\n        \"\"\"Detach connector from session without closing the former.\n\n        Session is switched to closed state anyway.\n        \"\"\"\n        self._connector = None\n\n    def __enter__(self) -> None:\n        raise TypeError(\"Use async with instead\")\n\n    def __exit__(\n        self,\n        exc_type: Optional[Type[BaseException]],\n        exc_val: Optional[BaseException],\n        exc_tb: Optional[TracebackType],\n    ) -> None:\n        # __exit__ should exist in pair with __enter__ but never executed\n        pass  # pragma: no cover\n\n    async def __aenter__(self) -> \"ClientSession\":\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        await self.close()\n\n\nclass _BaseRequestContextManager(Coroutine[Any, Any, _RetType], Generic[_RetType]):\n\n    __slots__ = (\"_coro\", \"_resp\")\n\n    def __init__(self, coro: Coroutine[\"asyncio.Future[Any]\", None, _RetType]) -> None:\n        self._coro: Coroutine[\"asyncio.Future[Any]\", None, _RetType] = coro\n\n    def send(self, arg: None) -> \"asyncio.Future[Any]\":\n        return self._coro.send(arg)\n\n    def throw(self, *args: Any, **kwargs: Any) -> \"asyncio.Future[Any]\":\n        return self._coro.throw(*args, **kwargs)\n\n    def close(self) -> None:\n        return self._coro.close()\n\n    def __await__(self) -> Generator[Any, None, _RetType]:\n        ret = self._coro.__await__()\n        return ret\n\n    def __iter__(self) -> Generator[Any, None, _RetType]:\n        return self.__await__()\n\n    async def __aenter__(self) -> _RetType:\n        self._resp: _RetType = await self._coro\n        return await self._resp.__aenter__()\n\n    async def __aexit__(\n        self,\n        exc_type: Optional[Type[BaseException]],\n        exc: Optional[BaseException],\n        tb: Optional[TracebackType],\n    ) -> None:\n        await self._resp.__aexit__(exc_type, exc, tb)\n\n\n_RequestContextManager = _BaseRequestContextManager[ClientResponse]\n_WSRequestContextManager = _BaseRequestContextManager[ClientWebSocketResponse]\n\n\nclass _SessionRequestContextManager:\n\n    __slots__ = (\"_coro\", \"_resp\", \"_session\")\n\n    def __init__(\n        self,\n        coro: Coroutine[\"asyncio.Future[Any]\", None, ClientResponse],\n        session: ClientSession,\n    ) -> None:\n        self._coro = coro\n        self._resp: Optional[ClientResponse] = None\n        self._session = session\n\n    async def __aenter__(self) -> ClientResponse:\n        try:\n            self._resp = await self._coro\n        except BaseException:\n            await self._session.close()\n            raise\n        else:\n            return self._resp\n\n    async def __aexit__(\n        self,\n        exc_type: Optional[Type[BaseException]],\n        exc: Optional[BaseException],\n        tb: Optional[TracebackType],\n    ) -> None:\n        assert self._resp is not None\n        self._resp.close()\n        await self._session.close()\n\n\ndef request(\n    method: str,\n    url: StrOrURL,\n    *,\n    params: Query = None,\n    data: Any = None,\n    json: Any = None,\n    headers: Optional[LooseHeaders] = None,\n    skip_auto_headers: Optional[Iterable[str]] = None,\n    auth: Optional[BasicAuth] = None,\n    allow_redirects: bool = True,\n    max_redirects: int = 10,\n    compress: Optional[str] = None,\n    chunked: Optional[bool] = None,\n    expect100: bool = False,\n    raise_for_status: Optional[bool] = None,\n    read_until_eof: bool = True,\n    proxy: Optional[StrOrURL] = None,\n    proxy_auth: Optional[BasicAuth] = None,\n    timeout: Union[ClientTimeout, object] = sentinel,\n    cookies: Optional[LooseCookies] = None,\n    version: HttpVersion = http.HttpVersion11,\n    connector: Optional[BaseConnector] = None,\n    read_bufsize: Optional[int] = None,\n    loop: Optional[asyncio.AbstractEventLoop] = None,\n    max_line_size: int = 8190,\n    max_field_size: int = 8190,\n) -> _SessionRequestContextManager:\n    \"\"\"Constructs and sends a request.\n\n    Returns response object.\n    method - HTTP method\n    url - request url\n    params - (optional) Dictionary or bytes to be sent in the query\n      string of the new request\n    data - (optional) Dictionary, bytes, or file-like object to\n      send in the body of the request\n    json - (optional) Any json compatible python object\n    headers - (optional) Dictionary of HTTP Headers to send with\n      the request\n    cookies - (optional) Dict object to send with the request\n    auth - (optional) BasicAuth named tuple represent HTTP Basic Auth\n    auth - aiohttp.helpers.BasicAuth\n    allow_redirects - (optional) If set to False, do not follow\n      redirects\n    version - Request HTTP version.\n    compress - Set to True if request has to be compressed\n       with deflate encoding.\n    chunked - Set to chunk size for chunked transfer encoding.\n    expect100 - Expect 100-continue response from server.\n    connector - BaseConnector sub-class instance to support\n       connection pooling.\n    read_until_eof - Read response until eof if response\n       does not have Content-Length header.\n    loop - Optional event loop.\n    timeout - Optional ClientTimeout settings structure, 5min\n       total timeout by default.\n    Usage::\n      >>> import aiohttp\n      >>> resp = await aiohttp.request('GET', 'http://python.org/')\n      >>> resp\n      <ClientResponse(python.org/) [200]>\n      >>> data = await resp.read()\n    \"\"\"\n    connector_owner = False\n    if connector is None:\n        connector_owner = True\n        connector = TCPConnector(loop=loop, force_close=True)\n\n    session = ClientSession(\n        loop=loop,\n        cookies=cookies,\n        version=version,\n        timeout=timeout,\n        connector=connector,\n        connector_owner=connector_owner,\n    )\n\n    return _SessionRequestContextManager(\n        session._request(\n            method,\n            url,\n            params=params,\n            data=data,\n            json=json,\n            headers=headers,\n            skip_auto_headers=skip_auto_headers,\n            auth=auth,\n            allow_redirects=allow_redirects,\n            max_redirects=max_redirects,\n            compress=compress,\n            chunked=chunked,\n            expect100=expect100,\n            raise_for_status=raise_for_status,\n            read_until_eof=read_until_eof,\n            proxy=proxy,\n            proxy_auth=proxy_auth,\n            read_bufsize=read_bufsize,\n            max_line_size=max_line_size,\n            max_field_size=max_field_size,\n        ),\n        session,\n    )\n",
            "new_file_content": "\"\"\"HTTP Client for asyncio.\"\"\"\n\nimport asyncio\nimport base64\nimport hashlib\nimport json\nimport os\nimport sys\nimport traceback\nimport warnings\nfrom contextlib import suppress\nfrom types import TracebackType\nfrom typing import (\n    TYPE_CHECKING,\n    Any,\n    Awaitable,\n    Callable,\n    Coroutine,\n    Final,\n    FrozenSet,\n    Generator,\n    Generic,\n    Iterable,\n    List,\n    Mapping,\n    Optional,\n    Set,\n    Tuple,\n    Type,\n    TypedDict,\n    TypeVar,\n    Union,\n)\n\nimport attr\nfrom multidict import CIMultiDict, MultiDict, MultiDictProxy, istr\nfrom yarl import URL\n\nfrom . import hdrs, http, payload\nfrom .abc import AbstractCookieJar\nfrom .client_exceptions import (\n    ClientConnectionError,\n    ClientConnectionResetError,\n    ClientConnectorCertificateError,\n    ClientConnectorError,\n    ClientConnectorSSLError,\n    ClientError,\n    ClientHttpProxyError,\n    ClientOSError,\n    ClientPayloadError,\n    ClientProxyConnectionError,\n    ClientResponseError,\n    ClientSSLError,\n    ConnectionTimeoutError,\n    ContentTypeError,\n    InvalidURL,\n    InvalidUrlClientError,\n    InvalidUrlRedirectClientError,\n    NonHttpUrlClientError,\n    NonHttpUrlRedirectClientError,\n    RedirectClientError,\n    ServerConnectionError,\n    ServerDisconnectedError,\n    ServerFingerprintMismatch,\n    ServerTimeoutError,\n    SocketTimeoutError,\n    TooManyRedirects,\n    WSServerHandshakeError,\n)\nfrom .client_reqrep import (\n    ClientRequest as ClientRequest,\n    ClientResponse as ClientResponse,\n    Fingerprint as Fingerprint,\n    RequestInfo as RequestInfo,\n    _merge_ssl_params,\n)\nfrom .client_ws import (\n    DEFAULT_WS_CLIENT_TIMEOUT,\n    ClientWebSocketResponse as ClientWebSocketResponse,\n    ClientWSTimeout as ClientWSTimeout,\n)\nfrom .connector import (\n    HTTP_AND_EMPTY_SCHEMA_SET,\n    BaseConnector as BaseConnector,\n    NamedPipeConnector as NamedPipeConnector,\n    TCPConnector as TCPConnector,\n    UnixConnector as UnixConnector,\n)\nfrom .cookiejar import CookieJar\nfrom .helpers import (\n    _SENTINEL,\n    DEBUG,\n    BasicAuth,\n    TimeoutHandle,\n    ceil_timeout,\n    get_env_proxy_for_url,\n    method_must_be_empty_body,\n    sentinel,\n    strip_auth_from_url,\n)\nfrom .http import WS_KEY, HttpVersion, WebSocketReader, WebSocketWriter\nfrom .http_websocket import WSHandshakeError, WSMessage, ws_ext_gen, ws_ext_parse\nfrom .streams import FlowControlDataQueue\nfrom .tracing import Trace, TraceConfig\nfrom .typedefs import JSONEncoder, LooseCookies, LooseHeaders, Query, StrOrURL\n\n__all__ = (\n    # client_exceptions\n    \"ClientConnectionError\",\n    \"ClientConnectionResetError\",\n    \"ClientConnectorCertificateError\",\n    \"ClientConnectorError\",\n    \"ClientConnectorSSLError\",\n    \"ClientError\",\n    \"ClientHttpProxyError\",\n    \"ClientOSError\",\n    \"ClientPayloadError\",\n    \"ClientProxyConnectionError\",\n    \"ClientResponseError\",\n    \"ClientSSLError\",\n    \"ConnectionTimeoutError\",\n    \"ContentTypeError\",\n    \"InvalidURL\",\n    \"InvalidUrlClientError\",\n    \"RedirectClientError\",\n    \"NonHttpUrlClientError\",\n    \"InvalidUrlRedirectClientError\",\n    \"NonHttpUrlRedirectClientError\",\n    \"ServerConnectionError\",\n    \"ServerDisconnectedError\",\n    \"ServerFingerprintMismatch\",\n    \"ServerTimeoutError\",\n    \"SocketTimeoutError\",\n    \"TooManyRedirects\",\n    \"WSServerHandshakeError\",\n    # client_reqrep\n    \"ClientRequest\",\n    \"ClientResponse\",\n    \"Fingerprint\",\n    \"RequestInfo\",\n    # connector\n    \"BaseConnector\",\n    \"TCPConnector\",\n    \"UnixConnector\",\n    \"NamedPipeConnector\",\n    # client_ws\n    \"ClientWebSocketResponse\",\n    # client\n    \"ClientSession\",\n    \"ClientTimeout\",\n    \"ClientWSTimeout\",\n    \"request\",\n)\n\n\nif TYPE_CHECKING:\n    from ssl import SSLContext\nelse:\n    SSLContext = None\n\nif sys.version_info >= (3, 11) and TYPE_CHECKING:\n    from typing import Unpack\n\n\nclass _RequestOptions(TypedDict, total=False):\n    params: Query\n    data: Any\n    json: Any\n    cookies: Union[LooseCookies, None]\n    headers: Union[LooseHeaders, None]\n    skip_auto_headers: Union[Iterable[str], None]\n    auth: Union[BasicAuth, None]\n    allow_redirects: bool\n    max_redirects: int\n    compress: Union[str, bool, None]\n    chunked: Union[bool, None]\n    expect100: bool\n    raise_for_status: Union[None, bool, Callable[[ClientResponse], Awaitable[None]]]\n    read_until_eof: bool\n    proxy: Union[StrOrURL, None]\n    proxy_auth: Union[BasicAuth, None]\n    timeout: \"Union[ClientTimeout, _SENTINEL, None]\"\n    ssl: Union[SSLContext, bool, Fingerprint]\n    server_hostname: Union[str, None]\n    proxy_headers: Union[LooseHeaders, None]\n    trace_request_ctx: Union[Mapping[str, str], None]\n    read_bufsize: Union[int, None]\n    auto_decompress: Union[bool, None]\n    max_line_size: Union[int, None]\n    max_field_size: Union[int, None]\n\n\n@attr.s(auto_attribs=True, frozen=True, slots=True)\nclass ClientTimeout:\n    total: Optional[float] = None\n    connect: Optional[float] = None\n    sock_read: Optional[float] = None\n    sock_connect: Optional[float] = None\n    ceil_threshold: float = 5\n\n    # pool_queue_timeout: Optional[float] = None\n    # dns_resolution_timeout: Optional[float] = None\n    # socket_connect_timeout: Optional[float] = None\n    # connection_acquiring_timeout: Optional[float] = None\n    # new_connection_timeout: Optional[float] = None\n    # http_header_timeout: Optional[float] = None\n    # response_body_timeout: Optional[float] = None\n\n    # to create a timeout specific for a single request, either\n    # - create a completely new one to overwrite the default\n    # - or use http://www.attrs.org/en/stable/api.html#attr.evolve\n    # to overwrite the defaults\n\n\n# 5 Minute default read timeout\nDEFAULT_TIMEOUT: Final[ClientTimeout] = ClientTimeout(total=5 * 60)\n\n# https://www.rfc-editor.org/rfc/rfc9110#section-9.2.2\nIDEMPOTENT_METHODS = frozenset({\"GET\", \"HEAD\", \"OPTIONS\", \"TRACE\", \"PUT\", \"DELETE\"})\n\n_RetType = TypeVar(\"_RetType\", ClientResponse, ClientWebSocketResponse)\n_CharsetResolver = Callable[[ClientResponse, bytes], str]\n\n\nclass ClientSession:\n    \"\"\"First-class interface for making HTTP requests.\"\"\"\n\n    ATTRS = frozenset(\n        [\n            \"_base_url\",\n            \"_source_traceback\",\n            \"_connector\",\n            \"requote_redirect_url\",\n            \"_loop\",\n            \"_cookie_jar\",\n            \"_connector_owner\",\n            \"_default_auth\",\n            \"_version\",\n            \"_json_serialize\",\n            \"_requote_redirect_url\",\n            \"_timeout\",\n            \"_raise_for_status\",\n            \"_auto_decompress\",\n            \"_trust_env\",\n            \"_default_headers\",\n            \"_skip_auto_headers\",\n            \"_request_class\",\n            \"_response_class\",\n            \"_ws_response_class\",\n            \"_trace_configs\",\n            \"_read_bufsize\",\n            \"_max_line_size\",\n            \"_max_field_size\",\n            \"_resolve_charset\",\n            \"_default_proxy\",\n            \"_default_proxy_auth\",\n        ]\n    )\n\n    _source_traceback: Optional[traceback.StackSummary] = None\n    _connector: Optional[BaseConnector] = None\n\n    def __init__(\n        self,\n        base_url: Optional[StrOrURL] = None,\n        *,\n        connector: Optional[BaseConnector] = None,\n        loop: Optional[asyncio.AbstractEventLoop] = None,\n        cookies: Optional[LooseCookies] = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        skip_auto_headers: Optional[Iterable[str]] = None,\n        auth: Optional[BasicAuth] = None,\n        json_serialize: JSONEncoder = json.dumps,\n        request_class: Type[ClientRequest] = ClientRequest,\n        response_class: Type[ClientResponse] = ClientResponse,\n        ws_response_class: Type[ClientWebSocketResponse] = ClientWebSocketResponse,\n        version: HttpVersion = http.HttpVersion11,\n        cookie_jar: Optional[AbstractCookieJar] = None,\n        connector_owner: bool = True,\n        raise_for_status: Union[\n            bool, Callable[[ClientResponse], Awaitable[None]]\n        ] = False,\n        read_timeout: Union[float, _SENTINEL] = sentinel,\n        conn_timeout: Optional[float] = None,\n        timeout: Union[object, ClientTimeout] = sentinel,\n        auto_decompress: bool = True,\n        trust_env: bool = False,\n        requote_redirect_url: bool = True,\n        trace_configs: Optional[List[TraceConfig]] = None,\n        read_bufsize: int = 2**16,\n        max_line_size: int = 8190,\n        max_field_size: int = 8190,\n        fallback_charset_resolver: _CharsetResolver = lambda r, b: \"utf-8\",\n    ) -> None:\n        # We initialise _connector to None immediately, as it's referenced in __del__()\n        # and could cause issues if an exception occurs during initialisation.\n        self._connector: Optional[BaseConnector] = None\n\n        if loop is None:\n            if connector is not None:\n                loop = connector._loop\n\n        loop = loop or asyncio.get_running_loop()\n\n        if base_url is None or isinstance(base_url, URL):\n            self._base_url: Optional[URL] = base_url\n        else:\n            self._base_url = URL(base_url)\n            assert (\n                self._base_url.origin() == self._base_url\n            ), \"Only absolute URLs without path part are supported\"\n\n        if timeout is sentinel or timeout is None:\n            self._timeout = DEFAULT_TIMEOUT\n            if read_timeout is not sentinel:\n                warnings.warn(\n                    \"read_timeout is deprecated, use timeout argument instead\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n                self._timeout = attr.evolve(self._timeout, total=read_timeout)\n            if conn_timeout is not None:\n                self._timeout = attr.evolve(self._timeout, connect=conn_timeout)\n                warnings.warn(\n                    \"conn_timeout is deprecated, use timeout argument instead\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n        else:\n            if not isinstance(timeout, ClientTimeout):\n                raise ValueError(\n                    f\"timeout parameter cannot be of {type(timeout)} type, \"\n                    \"please use 'timeout=ClientTimeout(...)'\",\n                )\n            self._timeout = timeout\n            if read_timeout is not sentinel:\n                raise ValueError(\n                    \"read_timeout and timeout parameters \"\n                    \"conflict, please setup \"\n                    \"timeout.read\"\n                )\n            if conn_timeout is not None:\n                raise ValueError(\n                    \"conn_timeout and timeout parameters \"\n                    \"conflict, please setup \"\n                    \"timeout.connect\"\n                )\n\n        if connector is None:\n            connector = TCPConnector(loop=loop)\n\n        if connector._loop is not loop:\n            raise RuntimeError(\"Session and connector has to use same event loop\")\n\n        self._loop = loop\n\n        if loop.get_debug():\n            self._source_traceback = traceback.extract_stack(sys._getframe(1))\n\n        if cookie_jar is None:\n            cookie_jar = CookieJar(loop=loop)\n        self._cookie_jar = cookie_jar\n\n        if cookies is not None:\n            self._cookie_jar.update_cookies(cookies)\n\n        self._connector = connector\n        self._connector_owner = connector_owner\n        self._default_auth = auth\n        self._version = version\n        self._json_serialize = json_serialize\n        self._raise_for_status = raise_for_status\n        self._auto_decompress = auto_decompress\n        self._trust_env = trust_env\n        self._requote_redirect_url = requote_redirect_url\n        self._read_bufsize = read_bufsize\n        self._max_line_size = max_line_size\n        self._max_field_size = max_field_size\n\n        # Convert to list of tuples\n        if headers:\n            real_headers: CIMultiDict[str] = CIMultiDict(headers)\n        else:\n            real_headers = CIMultiDict()\n        self._default_headers: CIMultiDict[str] = real_headers\n        if skip_auto_headers is not None:\n            self._skip_auto_headers = frozenset(istr(i) for i in skip_auto_headers)\n        else:\n            self._skip_auto_headers = frozenset()\n\n        self._request_class = request_class\n        self._response_class = response_class\n        self._ws_response_class = ws_response_class\n\n        self._trace_configs = trace_configs or []\n        for trace_config in self._trace_configs:\n            trace_config.freeze()\n\n        self._resolve_charset = fallback_charset_resolver\n\n        self._default_proxy = proxy\n        self._default_proxy_auth = proxy_auth\n\n    def __init_subclass__(cls: Type[\"ClientSession\"]) -> None:\n        warnings.warn(\n            \"Inheritance class {} from ClientSession \"\n            \"is discouraged\".format(cls.__name__),\n            DeprecationWarning,\n            stacklevel=2,\n        )\n\n    if DEBUG:\n\n        def __setattr__(self, name: str, val: Any) -> None:\n            if name not in self.ATTRS:\n                warnings.warn(\n                    \"Setting custom ClientSession.{} attribute \"\n                    \"is discouraged\".format(name),\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n            super().__setattr__(name, val)\n\n    def __del__(self, _warnings: Any = warnings) -> None:\n        if not self.closed:\n            kwargs = {\"source\": self}\n            _warnings.warn(\n                f\"Unclosed client session {self!r}\", ResourceWarning, **kwargs\n            )\n            context = {\"client_session\": self, \"message\": \"Unclosed client session\"}\n            if self._source_traceback is not None:\n                context[\"source_traceback\"] = self._source_traceback\n            self._loop.call_exception_handler(context)\n\n    if sys.version_info >= (3, 11) and TYPE_CHECKING:\n\n        def request(\n            self,\n            method: str,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n    else:\n\n        def request(\n            self, method: str, url: StrOrURL, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP request.\"\"\"\n            return _RequestContextManager(self._request(method, url, **kwargs))\n\n    def _build_url(self, str_or_url: StrOrURL) -> URL:\n        url = URL(str_or_url)\n        if self._base_url is None:\n            return url\n        else:\n            assert not url.absolute and url.path.startswith(\"/\")\n            return self._base_url.join(url)\n\n    async def _request(\n        self,\n        method: str,\n        str_or_url: StrOrURL,\n        *,\n        params: Query = None,\n        data: Any = None,\n        json: Any = None,\n        cookies: Optional[LooseCookies] = None,\n        headers: Optional[LooseHeaders] = None,\n        skip_auto_headers: Optional[Iterable[str]] = None,\n        auth: Optional[BasicAuth] = None,\n        allow_redirects: bool = True,\n        max_redirects: int = 10,\n        compress: Union[str, bool, None] = None,\n        chunked: Optional[bool] = None,\n        expect100: bool = False,\n        raise_for_status: Union[\n            None, bool, Callable[[ClientResponse], Awaitable[None]]\n        ] = None,\n        read_until_eof: bool = True,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        timeout: Union[ClientTimeout, _SENTINEL] = sentinel,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        server_hostname: Optional[str] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        trace_request_ctx: Optional[Mapping[str, str]] = None,\n        read_bufsize: Optional[int] = None,\n        auto_decompress: Optional[bool] = None,\n        max_line_size: Optional[int] = None,\n        max_field_size: Optional[int] = None,\n    ) -> ClientResponse:\n\n        # NOTE: timeout clamps existing connect and read timeouts.  We cannot\n        # set the default to None because we need to detect if the user wants\n        # to use the existing timeouts by setting timeout to None.\n\n        if self.closed:\n            raise RuntimeError(\"Session is closed\")\n\n        ssl = _merge_ssl_params(ssl, verify_ssl, ssl_context, fingerprint)\n\n        if data is not None and json is not None:\n            raise ValueError(\n                \"data and json parameters can not be used at the same time\"\n            )\n        elif json is not None:\n            data = payload.JsonPayload(json, dumps=self._json_serialize)\n\n        if not isinstance(chunked, bool) and chunked is not None:\n            warnings.warn(\"Chunk size is deprecated #1615\", DeprecationWarning)\n\n        redirects = 0\n        history = []\n        version = self._version\n        params = params or {}\n\n        # Merge with default headers and transform to CIMultiDict\n        headers = self._prepare_headers(headers)\n\n        try:\n            url = self._build_url(str_or_url)\n        except ValueError as e:\n            raise InvalidUrlClientError(str_or_url) from e\n\n        assert self._connector is not None\n        if url.scheme not in self._connector.allowed_protocol_schema_set:\n            raise NonHttpUrlClientError(url)\n\n        skip_headers = set(self._skip_auto_headers)\n        if skip_auto_headers is not None:\n            for i in skip_auto_headers:\n                skip_headers.add(istr(i))\n\n        if proxy is None:\n            proxy = self._default_proxy\n        if proxy_auth is None:\n            proxy_auth = self._default_proxy_auth\n\n        if proxy is None:\n            proxy_headers = None\n        else:\n            proxy_headers = self._prepare_headers(proxy_headers)\n            try:\n                proxy = URL(proxy)\n            except ValueError as e:\n                raise InvalidURL(proxy) from e\n\n        if timeout is sentinel:\n            real_timeout: ClientTimeout = self._timeout\n        else:\n            if not isinstance(timeout, ClientTimeout):\n                real_timeout = ClientTimeout(total=timeout)\n            else:\n                real_timeout = timeout\n        # timeout is cumulative for all request operations\n        # (request, redirects, responses, data consuming)\n        tm = TimeoutHandle(\n            self._loop, real_timeout.total, ceil_threshold=real_timeout.ceil_threshold\n        )\n        handle = tm.start()\n\n        if read_bufsize is None:\n            read_bufsize = self._read_bufsize\n\n        if auto_decompress is None:\n            auto_decompress = self._auto_decompress\n\n        if max_line_size is None:\n            max_line_size = self._max_line_size\n\n        if max_field_size is None:\n            max_field_size = self._max_field_size\n\n        traces = [\n            Trace(\n                self,\n                trace_config,\n                trace_config.trace_config_ctx(trace_request_ctx=trace_request_ctx),\n            )\n            for trace_config in self._trace_configs\n        ]\n\n        for trace in traces:\n            await trace.send_request_start(method, url.update_query(params), headers)\n\n        timer = tm.timer()\n        try:\n            with timer:\n                # https://www.rfc-editor.org/rfc/rfc9112.html#name-retrying-requests\n                retry_persistent_connection = method in IDEMPOTENT_METHODS\n                while True:\n                    url, auth_from_url = strip_auth_from_url(url)\n                    if not url.raw_host:\n                        # NOTE: Bail early, otherwise, causes `InvalidURL` through\n                        # NOTE: `self._request_class()` below.\n                        err_exc_cls = (\n                            InvalidUrlRedirectClientError\n                            if redirects\n                            else InvalidUrlClientError\n                        )\n                        raise err_exc_cls(url)\n                    if auth and auth_from_url:\n                        raise ValueError(\n                            \"Cannot combine AUTH argument with \"\n                            \"credentials encoded in URL\"\n                        )\n\n                    if auth is None:\n                        auth = auth_from_url\n\n                    if auth is None and (\n                        not self._base_url or self._base_url.origin() == url.origin()\n                    ):\n                        auth = self._default_auth\n                    # It would be confusing if we support explicit\n                    # Authorization header with auth argument\n                    if (\n                        headers is not None\n                        and auth is not None\n                        and hdrs.AUTHORIZATION in headers\n                    ):\n                        raise ValueError(\n                            \"Cannot combine AUTHORIZATION header \"\n                            \"with AUTH argument or credentials \"\n                            \"encoded in URL\"\n                        )\n\n                    all_cookies = self._cookie_jar.filter_cookies(url)\n\n                    if cookies is not None:\n                        tmp_cookie_jar = CookieJar()\n                        tmp_cookie_jar.update_cookies(cookies)\n                        req_cookies = tmp_cookie_jar.filter_cookies(url)\n                        if req_cookies:\n                            all_cookies.load(req_cookies)\n\n                    if proxy is not None:\n                        proxy = URL(proxy)\n                    elif self._trust_env:\n                        with suppress(LookupError):\n                            proxy, proxy_auth = get_env_proxy_for_url(url)\n\n                    req = self._request_class(\n                        method,\n                        url,\n                        params=params,\n                        headers=headers,\n                        skip_auto_headers=skip_headers if skip_headers else None,\n                        data=data,\n                        cookies=all_cookies,\n                        auth=auth,\n                        version=version,\n                        compress=compress,\n                        chunked=chunked,\n                        expect100=expect100,\n                        loop=self._loop,\n                        response_class=self._response_class,\n                        proxy=proxy,\n                        proxy_auth=proxy_auth,\n                        timer=timer,\n                        session=self,\n                        ssl=ssl if ssl is not None else True,\n                        server_hostname=server_hostname,\n                        proxy_headers=proxy_headers,\n                        traces=traces,\n                        trust_env=self.trust_env,\n                    )\n\n                    # connection timeout\n                    try:\n                        async with ceil_timeout(\n                            real_timeout.connect,\n                            ceil_threshold=real_timeout.ceil_threshold,\n                        ):\n                            conn = await self._connector.connect(\n                                req, traces=traces, timeout=real_timeout\n                            )\n                    except asyncio.TimeoutError as exc:\n                        raise ConnectionTimeoutError(\n                            f\"Connection timeout to host {url}\"\n                        ) from exc\n\n                    assert conn.transport is not None\n\n                    assert conn.protocol is not None\n                    conn.protocol.set_response_params(\n                        timer=timer,\n                        skip_payload=method_must_be_empty_body(method),\n                        read_until_eof=read_until_eof,\n                        auto_decompress=auto_decompress,\n                        read_timeout=real_timeout.sock_read,\n                        read_bufsize=read_bufsize,\n                        timeout_ceil_threshold=self._connector._timeout_ceil_threshold,\n                        max_line_size=max_line_size,\n                        max_field_size=max_field_size,\n                    )\n\n                    try:\n                        try:\n                            resp = await req.send(conn)\n                            try:\n                                await resp.start(conn)\n                            except BaseException:\n                                resp.close()\n                                raise\n                        except BaseException:\n                            conn.close()\n                            raise\n                    except (ClientOSError, ServerDisconnectedError):\n                        if retry_persistent_connection:\n                            retry_persistent_connection = False\n                            continue\n                        raise\n                    except ClientError:\n                        raise\n                    except OSError as exc:\n                        if exc.errno is None and isinstance(exc, asyncio.TimeoutError):\n                            raise\n                        raise ClientOSError(*exc.args) from exc\n\n                    self._cookie_jar.update_cookies(resp.cookies, resp.url)\n\n                    # redirects\n                    if resp.status in (301, 302, 303, 307, 308) and allow_redirects:\n\n                        for trace in traces:\n                            await trace.send_request_redirect(\n                                method, url.update_query(params), headers, resp\n                            )\n\n                        redirects += 1\n                        history.append(resp)\n                        if max_redirects and redirects >= max_redirects:\n                            resp.close()\n                            raise TooManyRedirects(\n                                history[0].request_info, tuple(history)\n                            )\n\n                        # For 301 and 302, mimic IE, now changed in RFC\n                        # https://github.com/kennethreitz/requests/pull/269\n                        if (resp.status == 303 and resp.method != hdrs.METH_HEAD) or (\n                            resp.status in (301, 302) and resp.method == hdrs.METH_POST\n                        ):\n                            method = hdrs.METH_GET\n                            data = None\n                            if headers.get(hdrs.CONTENT_LENGTH):\n                                headers.pop(hdrs.CONTENT_LENGTH)\n\n                        r_url = resp.headers.get(hdrs.LOCATION) or resp.headers.get(\n                            hdrs.URI\n                        )\n                        if r_url is None:\n                            # see github.com/aio-libs/aiohttp/issues/2022\n                            break\n                        else:\n                            # reading from correct redirection\n                            # response is forbidden\n                            resp.release()\n\n                        try:\n                            parsed_redirect_url = URL(\n                                r_url, encoded=not self._requote_redirect_url\n                            )\n                        except ValueError as e:\n                            raise InvalidUrlRedirectClientError(\n                                r_url,\n                                \"Server attempted redirecting to a location that does not look like a URL\",\n                            ) from e\n\n                        scheme = parsed_redirect_url.scheme\n                        if scheme not in HTTP_AND_EMPTY_SCHEMA_SET:\n                            resp.close()\n                            raise NonHttpUrlRedirectClientError(r_url)\n                        elif not scheme:\n                            parsed_redirect_url = url.join(parsed_redirect_url)\n\n                        try:\n                            redirect_origin = parsed_redirect_url.origin()\n                        except ValueError as origin_val_err:\n                            raise InvalidUrlRedirectClientError(\n                                parsed_redirect_url,\n                                \"Invalid redirect URL origin\",\n                            ) from origin_val_err\n\n                        if url.origin() != redirect_origin:\n                            auth = None\n                            headers.pop(hdrs.AUTHORIZATION, None)\n\n                        url = parsed_redirect_url\n                        params = {}\n                        resp.release()\n                        continue\n\n                    break\n\n            # check response status\n            if raise_for_status is None:\n                raise_for_status = self._raise_for_status\n\n            if raise_for_status is None:\n                pass\n            elif callable(raise_for_status):\n                await raise_for_status(resp)\n            elif raise_for_status:\n                resp.raise_for_status()\n\n            # register connection\n            if handle is not None:\n                if resp.connection is not None:\n                    resp.connection.add_callback(handle.cancel)\n                else:\n                    handle.cancel()\n\n            resp._history = tuple(history)\n\n            for trace in traces:\n                await trace.send_request_end(\n                    method, url.update_query(params), headers, resp\n                )\n            return resp\n\n        except BaseException as e:\n            # cleanup timer\n            tm.close()\n            if handle:\n                handle.cancel()\n                handle = None\n\n            for trace in traces:\n                await trace.send_request_exception(\n                    method, url.update_query(params), headers, e\n                )\n            raise\n\n    def ws_connect(\n        self,\n        url: StrOrURL,\n        *,\n        method: str = hdrs.METH_GET,\n        protocols: Iterable[str] = (),\n        timeout: Union[ClientWSTimeout, _SENTINEL] = sentinel,\n        receive_timeout: Optional[float] = None,\n        autoclose: bool = True,\n        autoping: bool = True,\n        heartbeat: Optional[float] = None,\n        auth: Optional[BasicAuth] = None,\n        origin: Optional[str] = None,\n        params: Query = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        compress: int = 0,\n        max_msg_size: int = 4 * 1024 * 1024,\n    ) -> \"_WSRequestContextManager\":\n        \"\"\"Initiate websocket connection.\"\"\"\n        return _WSRequestContextManager(\n            self._ws_connect(\n                url,\n                method=method,\n                protocols=protocols,\n                timeout=timeout,\n                receive_timeout=receive_timeout,\n                autoclose=autoclose,\n                autoping=autoping,\n                heartbeat=heartbeat,\n                auth=auth,\n                origin=origin,\n                params=params,\n                headers=headers,\n                proxy=proxy,\n                proxy_auth=proxy_auth,\n                ssl=ssl,\n                verify_ssl=verify_ssl,\n                fingerprint=fingerprint,\n                ssl_context=ssl_context,\n                proxy_headers=proxy_headers,\n                compress=compress,\n                max_msg_size=max_msg_size,\n            )\n        )\n\n    async def _ws_connect(\n        self,\n        url: StrOrURL,\n        *,\n        method: str = hdrs.METH_GET,\n        protocols: Iterable[str] = (),\n        timeout: Union[ClientWSTimeout, _SENTINEL] = sentinel,\n        receive_timeout: Optional[float] = None,\n        autoclose: bool = True,\n        autoping: bool = True,\n        heartbeat: Optional[float] = None,\n        auth: Optional[BasicAuth] = None,\n        origin: Optional[str] = None,\n        params: Query = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        compress: int = 0,\n        max_msg_size: int = 4 * 1024 * 1024,\n    ) -> ClientWebSocketResponse:\n        if timeout is not sentinel:\n            if isinstance(timeout, ClientWSTimeout):\n                ws_timeout = timeout\n            else:\n                warnings.warn(\n                    \"parameter 'timeout' of type 'float' \"\n                    \"is deprecated, please use \"\n                    \"'timeout=ClientWSTimeout(ws_close=...)'\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n                ws_timeout = ClientWSTimeout(ws_close=timeout)\n        else:\n            ws_timeout = DEFAULT_WS_CLIENT_TIMEOUT\n        if receive_timeout is not None:\n            warnings.warn(\n                \"float parameter 'receive_timeout' \"\n                \"is deprecated, please use parameter \"\n                \"'timeout=ClientWSTimeout(ws_receive=...)'\",\n                DeprecationWarning,\n                stacklevel=2,\n            )\n            ws_timeout = attr.evolve(ws_timeout, ws_receive=receive_timeout)\n\n        if headers is None:\n            real_headers: CIMultiDict[str] = CIMultiDict()\n        else:\n            real_headers = CIMultiDict(headers)\n\n        default_headers = {\n            hdrs.UPGRADE: \"websocket\",\n            hdrs.CONNECTION: \"Upgrade\",\n            hdrs.SEC_WEBSOCKET_VERSION: \"13\",\n        }\n\n        for key, value in default_headers.items():\n            real_headers.setdefault(key, value)\n\n        sec_key = base64.b64encode(os.urandom(16))\n        real_headers[hdrs.SEC_WEBSOCKET_KEY] = sec_key.decode()\n\n        if protocols:\n            real_headers[hdrs.SEC_WEBSOCKET_PROTOCOL] = \",\".join(protocols)\n        if origin is not None:\n            real_headers[hdrs.ORIGIN] = origin\n        if compress:\n            extstr = ws_ext_gen(compress=compress)\n            real_headers[hdrs.SEC_WEBSOCKET_EXTENSIONS] = extstr\n\n        # For the sake of backward compatibility, if user passes in None, convert it to True\n        if ssl is None:\n            warnings.warn(\n                \"ssl=None is deprecated, please use ssl=True\",\n                DeprecationWarning,\n                stacklevel=2,\n            )\n            ssl = True\n        ssl = _merge_ssl_params(ssl, verify_ssl, ssl_context, fingerprint)\n\n        # send request\n        resp = await self.request(\n            method,\n            url,\n            params=params,\n            headers=real_headers,\n            read_until_eof=False,\n            auth=auth,\n            proxy=proxy,\n            proxy_auth=proxy_auth,\n            ssl=ssl,\n            proxy_headers=proxy_headers,\n        )\n\n        try:\n            # check handshake\n            if resp.status != 101:\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid response status\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            if resp.headers.get(hdrs.UPGRADE, \"\").lower() != \"websocket\":\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid upgrade header\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            if resp.headers.get(hdrs.CONNECTION, \"\").lower() != \"upgrade\":\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid connection header\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            # key calculation\n            r_key = resp.headers.get(hdrs.SEC_WEBSOCKET_ACCEPT, \"\")\n            match = base64.b64encode(hashlib.sha1(sec_key + WS_KEY).digest()).decode()\n            if r_key != match:\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid challenge response\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            # websocket protocol\n            protocol = None\n            if protocols and hdrs.SEC_WEBSOCKET_PROTOCOL in resp.headers:\n                resp_protocols = [\n                    proto.strip()\n                    for proto in resp.headers[hdrs.SEC_WEBSOCKET_PROTOCOL].split(\",\")\n                ]\n\n                for proto in resp_protocols:\n                    if proto in protocols:\n                        protocol = proto\n                        break\n\n            # websocket compress\n            notakeover = False\n            if compress:\n                compress_hdrs = resp.headers.get(hdrs.SEC_WEBSOCKET_EXTENSIONS)\n                if compress_hdrs:\n                    try:\n                        compress, notakeover = ws_ext_parse(compress_hdrs)\n                    except WSHandshakeError as exc:\n                        raise WSServerHandshakeError(\n                            resp.request_info,\n                            resp.history,\n                            message=exc.args[0],\n                            status=resp.status,\n                            headers=resp.headers,\n                        ) from exc\n                else:\n                    compress = 0\n                    notakeover = False\n\n            conn = resp.connection\n            assert conn is not None\n            conn_proto = conn.protocol\n            assert conn_proto is not None\n\n            # For WS connection the read_timeout must be either receive_timeout or greater\n            # None == no timeout, i.e. infinite timeout, so None is the max timeout possible\n            if ws_timeout.ws_receive is None:\n                # Reset regardless\n                conn_proto.read_timeout = None\n            elif conn_proto.read_timeout is not None:\n                conn_proto.read_timeout = max(\n                    ws_timeout.ws_receive, conn_proto.read_timeout\n                )\n\n            transport = conn.transport\n            assert transport is not None\n            reader: FlowControlDataQueue[WSMessage] = FlowControlDataQueue(\n                conn_proto, 2**16, loop=self._loop\n            )\n            conn_proto.set_parser(WebSocketReader(reader, max_msg_size), reader)\n            writer = WebSocketWriter(\n                conn_proto,\n                transport,\n                use_mask=True,\n                compress=compress,\n                notakeover=notakeover,\n            )\n        except BaseException:\n            resp.close()\n            raise\n        else:\n            return self._ws_response_class(\n                reader,\n                writer,\n                protocol,\n                resp,\n                ws_timeout,\n                autoclose,\n                autoping,\n                self._loop,\n                heartbeat=heartbeat,\n                compress=compress,\n                client_notakeover=notakeover,\n            )\n\n    def _prepare_headers(self, headers: Optional[LooseHeaders]) -> \"CIMultiDict[str]\":\n        \"\"\"Add default headers and transform it to CIMultiDict\"\"\"\n        # Convert headers to MultiDict\n        result = CIMultiDict(self._default_headers)\n        if headers:\n            if not isinstance(headers, (MultiDictProxy, MultiDict)):\n                headers = CIMultiDict(headers)\n            added_names: Set[str] = set()\n            for key, value in headers.items():\n                if key in added_names:\n                    result.add(key, value)\n                else:\n                    result[key] = value\n                    added_names.add(key)\n        return result\n\n    if sys.version_info >= (3, 11) and TYPE_CHECKING:\n\n        def get(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def options(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def head(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def post(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def put(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def patch(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def delete(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n    else:\n\n        def get(\n            self, url: StrOrURL, *, allow_redirects: bool = True, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP GET request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_GET, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def options(\n            self, url: StrOrURL, *, allow_redirects: bool = True, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP OPTIONS request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_OPTIONS, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def head(\n            self, url: StrOrURL, *, allow_redirects: bool = False, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP HEAD request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_HEAD, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def post(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP POST request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_POST, url, data=data, **kwargs)\n            )\n\n        def put(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP PUT request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_PUT, url, data=data, **kwargs)\n            )\n\n        def patch(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP PATCH request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_PATCH, url, data=data, **kwargs)\n            )\n\n        def delete(self, url: StrOrURL, **kwargs: Any) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP DELETE request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_DELETE, url, **kwargs)\n            )\n\n    async def close(self) -> None:\n        \"\"\"Close underlying connector.\n\n        Release all acquired resources.\n        \"\"\"\n        if not self.closed:\n            if self._connector is not None and self._connector_owner:\n                await self._connector.close()\n            self._connector = None\n\n    @property\n    def closed(self) -> bool:\n        \"\"\"Is client session closed.\n\n        A readonly property.\n        \"\"\"\n        return self._connector is None or self._connector.closed\n\n    @property\n    def connector(self) -> Optional[BaseConnector]:\n        \"\"\"Connector instance used for the session.\"\"\"\n        return self._connector\n\n    @property\n    def cookie_jar(self) -> AbstractCookieJar:\n        \"\"\"The session cookies.\"\"\"\n        return self._cookie_jar\n\n    @property\n    def version(self) -> Tuple[int, int]:\n        \"\"\"The session HTTP protocol version.\"\"\"\n        return self._version\n\n    @property\n    def requote_redirect_url(self) -> bool:\n        \"\"\"Do URL requoting on redirection handling.\"\"\"\n        return self._requote_redirect_url\n\n    @requote_redirect_url.setter\n    def requote_redirect_url(self, val: bool) -> None:\n        \"\"\"Do URL requoting on redirection handling.\"\"\"\n        warnings.warn(\n            \"session.requote_redirect_url modification is deprecated #2778\",\n            DeprecationWarning,\n            stacklevel=2,\n        )\n        self._requote_redirect_url = val\n\n    @property\n    def loop(self) -> asyncio.AbstractEventLoop:\n        \"\"\"Session's loop.\"\"\"\n        warnings.warn(\n            \"client.loop property is deprecated\", DeprecationWarning, stacklevel=2\n        )\n        return self._loop\n\n    @property\n    def timeout(self) -> ClientTimeout:\n        \"\"\"Timeout for the session.\"\"\"\n        return self._timeout\n\n    @property\n    def headers(self) -> \"CIMultiDict[str]\":\n        \"\"\"The default headers of the client session.\"\"\"\n        return self._default_headers\n\n    @property\n    def skip_auto_headers(self) -> FrozenSet[istr]:\n        \"\"\"Headers for which autogeneration should be skipped\"\"\"\n        return self._skip_auto_headers\n\n    @property\n    def auth(self) -> Optional[BasicAuth]:\n        \"\"\"An object that represents HTTP Basic Authorization\"\"\"\n        return self._default_auth\n\n    @property\n    def json_serialize(self) -> JSONEncoder:\n        \"\"\"Json serializer callable\"\"\"\n        return self._json_serialize\n\n    @property\n    def connector_owner(self) -> bool:\n        \"\"\"Should connector be closed on session closing\"\"\"\n        return self._connector_owner\n\n    @property\n    def raise_for_status(\n        self,\n    ) -> Union[bool, Callable[[ClientResponse], Awaitable[None]]]:\n        \"\"\"Should `ClientResponse.raise_for_status()` be called for each response.\"\"\"\n        return self._raise_for_status\n\n    @property\n    def auto_decompress(self) -> bool:\n        \"\"\"Should the body response be automatically decompressed.\"\"\"\n        return self._auto_decompress\n\n    @property\n    def trust_env(self) -> bool:\n        \"\"\"\n        Should proxies information from environment or netrc be trusted.\n\n        Information is from HTTP_PROXY / HTTPS_PROXY environment variables\n        or ~/.netrc file if present.\n        \"\"\"\n        return self._trust_env\n\n    @property\n    def trace_configs(self) -> List[TraceConfig]:\n        \"\"\"A list of TraceConfig instances used for client tracing\"\"\"\n        return self._trace_configs\n\n    def detach(self) -> None:\n        \"\"\"Detach connector from session without closing the former.\n\n        Session is switched to closed state anyway.\n        \"\"\"\n        self._connector = None\n\n    def __enter__(self) -> None:\n        raise TypeError(\"Use async with instead\")\n\n    def __exit__(\n        self,\n        exc_type: Optional[Type[BaseException]],\n        exc_val: Optional[BaseException],\n        exc_tb: Optional[TracebackType],\n    ) -> None:\n        # __exit__ should exist in pair with __enter__ but never executed\n        pass  # pragma: no cover\n\n    async def __aenter__(self) -> \"ClientSession\":\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        await self.close()\n\n\nclass _BaseRequestContextManager(Coroutine[Any, Any, _RetType], Generic[_RetType]):\n\n    __slots__ = (\"_coro\", \"_resp\")\n\n    def __init__(self, coro: Coroutine[\"asyncio.Future[Any]\", None, _RetType]) -> None:\n        self._coro: Coroutine[\"asyncio.Future[Any]\", None, _RetType] = coro\n\n    def send(self, arg: None) -> \"asyncio.Future[Any]\":\n        return self._coro.send(arg)\n\n    def throw(self, *args: Any, **kwargs: Any) -> \"asyncio.Future[Any]\":\n        return self._coro.throw(*args, **kwargs)\n\n    def close(self) -> None:\n        return self._coro.close()\n\n    def __await__(self) -> Generator[Any, None, _RetType]:\n        ret = self._coro.__await__()\n        return ret\n\n    def __iter__(self) -> Generator[Any, None, _RetType]:\n        return self.__await__()\n\n    async def __aenter__(self) -> _RetType:\n        self._resp: _RetType = await self._coro\n        return await self._resp.__aenter__()\n\n    async def __aexit__(\n        self,\n        exc_type: Optional[Type[BaseException]],\n        exc: Optional[BaseException],\n        tb: Optional[TracebackType],\n    ) -> None:\n        await self._resp.__aexit__(exc_type, exc, tb)\n\n\n_RequestContextManager = _BaseRequestContextManager[ClientResponse]\n_WSRequestContextManager = _BaseRequestContextManager[ClientWebSocketResponse]\n\n\nclass _SessionRequestContextManager:\n\n    __slots__ = (\"_coro\", \"_resp\", \"_session\")\n\n    def __init__(\n        self,\n        coro: Coroutine[\"asyncio.Future[Any]\", None, ClientResponse],\n        session: ClientSession,\n    ) -> None:\n        self._coro = coro\n        self._resp: Optional[ClientResponse] = None\n        self._session = session\n\n    async def __aenter__(self) -> ClientResponse:\n        try:\n            self._resp = await self._coro\n        except BaseException:\n            await self._session.close()\n            raise\n        else:\n            return self._resp\n\n    async def __aexit__(\n        self,\n        exc_type: Optional[Type[BaseException]],\n        exc: Optional[BaseException],\n        tb: Optional[TracebackType],\n    ) -> None:\n        assert self._resp is not None\n        self._resp.close()\n        await self._session.close()\n\n\ndef request(\n    method: str,\n    url: StrOrURL,\n    *,\n    params: Query = None,\n    data: Any = None,\n    json: Any = None,\n    headers: Optional[LooseHeaders] = None,\n    skip_auto_headers: Optional[Iterable[str]] = None,\n    auth: Optional[BasicAuth] = None,\n    allow_redirects: bool = True,\n    max_redirects: int = 10,\n    compress: Optional[str] = None,\n    chunked: Optional[bool] = None,\n    expect100: bool = False,\n    raise_for_status: Optional[bool] = None,\n    read_until_eof: bool = True,\n    proxy: Optional[StrOrURL] = None,\n    proxy_auth: Optional[BasicAuth] = None,\n    timeout: Union[ClientTimeout, object] = sentinel,\n    cookies: Optional[LooseCookies] = None,\n    version: HttpVersion = http.HttpVersion11,\n    connector: Optional[BaseConnector] = None,\n    read_bufsize: Optional[int] = None,\n    loop: Optional[asyncio.AbstractEventLoop] = None,\n    max_line_size: int = 8190,\n    max_field_size: int = 8190,\n) -> _SessionRequestContextManager:\n    \"\"\"Constructs and sends a request.\n\n    Returns response object.\n    method - HTTP method\n    url - request url\n    params - (optional) Dictionary or bytes to be sent in the query\n      string of the new request\n    data - (optional) Dictionary, bytes, or file-like object to\n      send in the body of the request\n    json - (optional) Any json compatible python object\n    headers - (optional) Dictionary of HTTP Headers to send with\n      the request\n    cookies - (optional) Dict object to send with the request\n    auth - (optional) BasicAuth named tuple represent HTTP Basic Auth\n    auth - aiohttp.helpers.BasicAuth\n    allow_redirects - (optional) If set to False, do not follow\n      redirects\n    version - Request HTTP version.\n    compress - Set to True if request has to be compressed\n       with deflate encoding.\n    chunked - Set to chunk size for chunked transfer encoding.\n    expect100 - Expect 100-continue response from server.\n    connector - BaseConnector sub-class instance to support\n       connection pooling.\n    read_until_eof - Read response until eof if response\n       does not have Content-Length header.\n    loop - Optional event loop.\n    timeout - Optional ClientTimeout settings structure, 5min\n       total timeout by default.\n    Usage::\n      >>> import aiohttp\n      >>> resp = await aiohttp.request('GET', 'http://python.org/')\n      >>> resp\n      <ClientResponse(python.org/) [200]>\n      >>> data = await resp.read()\n    \"\"\"\n    connector_owner = False\n    if connector is None:\n        connector_owner = True\n        connector = TCPConnector(loop=loop, force_close=True)\n\n    session = ClientSession(\n        loop=loop,\n        cookies=cookies,\n        version=version,\n        timeout=timeout,\n        connector=connector,\n        connector_owner=connector_owner,\n    )\n\n    return _SessionRequestContextManager(\n        session._request(\n            method,\n            url,\n            params=params,\n            data=data,\n            json=json,\n            headers=headers,\n            skip_auto_headers=skip_auto_headers,\n            auth=auth,\n            allow_redirects=allow_redirects,\n            max_redirects=max_redirects,\n            compress=compress,\n            chunked=chunked,\n            expect100=expect100,\n            raise_for_status=raise_for_status,\n            read_until_eof=read_until_eof,\n            proxy=proxy,\n            proxy_auth=proxy_auth,\n            read_bufsize=read_bufsize,\n            max_line_size=max_line_size,\n            max_field_size=max_field_size,\n        ),\n        session,\n    )\n",
            "header": {
                "file": {
                    "path": "aiohttp/client.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "6c129c3a",
                "new_commit_hash": "a5c57bb2",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/aiohttp/client.py"
            },
            "plus_file": {
                "path": "b/aiohttp/client.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 252,
                            "length": 6
                        },
                        "new_range": {
                            "start": 252,
                            "length": 8
                        },
                        "section": "class ClientSession:"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "            \"_max_line_size\",",
                                "type": "context"
                            },
                            {
                                "content": "            \"_max_field_size\",",
                                "type": "context"
                            },
                            {
                                "content": "            \"_resolve_charset\",",
                                "type": "context"
                            },
                            {
                                "content": "            \"_default_proxy\",",
                                "type": "added"
                            },
                            {
                                "content": "            \"_default_proxy_auth\",",
                                "type": "added"
                            },
                            {
                                "content": "        ]",
                                "type": "context"
                            },
                            {
                                "content": "    )",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "aiohttp/client.py",
                            "type": "class",
                            "name": "ClientSession",
                            "content": "class ClientSession:\n    \"\"\"First-class interface for making HTTP requests.\"\"\"\n\n    ATTRS = frozenset(\n        [\n            \"_base_url\",\n            \"_source_traceback\",\n            \"_connector\",\n            \"requote_redirect_url\",\n            \"_loop\",\n            \"_cookie_jar\",\n            \"_connector_owner\",\n            \"_default_auth\",\n            \"_version\",\n            \"_json_serialize\",\n            \"_requote_redirect_url\",\n            \"_timeout\",\n            \"_raise_for_status\",\n            \"_auto_decompress\",\n            \"_trust_env\",\n            \"_default_headers\",\n            \"_skip_auto_headers\",\n            \"_request_class\",\n            \"_response_class\",\n            \"_ws_response_class\",\n            \"_trace_configs\",\n            \"_read_bufsize\",\n            \"_max_line_size\",\n            \"_max_field_size\",\n            \"_resolve_charset\",\n            \"_default_proxy\",\n            \"_default_proxy_auth\",\n        ]\n    )\n\n    _source_traceback: Optional[traceback.StackSummary] = None\n    _connector: Optional[BaseConnector] = None\n\n    def __init__(\n        self,\n        base_url: Optional[StrOrURL] = None,\n        *,\n        connector: Optional[BaseConnector] = None,\n        loop: Optional[asyncio.AbstractEventLoop] = None,\n        cookies: Optional[LooseCookies] = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        skip_auto_headers: Optional[Iterable[str]] = None,\n        auth: Optional[BasicAuth] = None,\n        json_serialize: JSONEncoder = json.dumps,\n        request_class: Type[ClientRequest] = ClientRequest,\n        response_class: Type[ClientResponse] = ClientResponse,\n        ws_response_class: Type[ClientWebSocketResponse] = ClientWebSocketResponse,\n        version: HttpVersion = http.HttpVersion11,\n        cookie_jar: Optional[AbstractCookieJar] = None,\n        connector_owner: bool = True,\n        raise_for_status: Union[\n            bool, Callable[[ClientResponse], Awaitable[None]]\n        ] = False,\n        read_timeout: Union[float, _SENTINEL] = sentinel,\n        conn_timeout: Optional[float] = None,\n        timeout: Union[object, ClientTimeout] = sentinel,\n        auto_decompress: bool = True,\n        trust_env: bool = False,\n        requote_redirect_url: bool = True,\n        trace_configs: Optional[List[TraceConfig]] = None,\n        read_bufsize: int = 2**16,\n        max_line_size: int = 8190,\n        max_field_size: int = 8190,\n        fallback_charset_resolver: _CharsetResolver = lambda r, b: \"utf-8\",\n    ) -> None:\n        # We initialise _connector to None immediately, as it's referenced in __del__()\n        # and could cause issues if an exception occurs during initialisation.\n        self._connector: Optional[BaseConnector] = None\n\n        if loop is None:\n            if connector is not None:\n                loop = connector._loop\n\n        loop = loop or asyncio.get_running_loop()\n\n        if base_url is None or isinstance(base_url, URL):\n            self._base_url: Optional[URL] = base_url\n        else:\n            self._base_url = URL(base_url)\n            assert (\n                self._base_url.origin() == self._base_url\n            ), \"Only absolute URLs without path part are supported\"\n\n        if timeout is sentinel or timeout is None:\n            self._timeout = DEFAULT_TIMEOUT\n            if read_timeout is not sentinel:\n                warnings.warn(\n                    \"read_timeout is deprecated, use timeout argument instead\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n                self._timeout = attr.evolve(self._timeout, total=read_timeout)\n            if conn_timeout is not None:\n                self._timeout = attr.evolve(self._timeout, connect=conn_timeout)\n                warnings.warn(\n                    \"conn_timeout is deprecated, use timeout argument instead\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n        else:\n            if not isinstance(timeout, ClientTimeout):\n                raise ValueError(\n                    f\"timeout parameter cannot be of {type(timeout)} type, \"\n                    \"please use 'timeout=ClientTimeout(...)'\",\n                )\n            self._timeout = timeout\n            if read_timeout is not sentinel:\n                raise ValueError(\n                    \"read_timeout and timeout parameters \"\n                    \"conflict, please setup \"\n                    \"timeout.read\"\n                )\n            if conn_timeout is not None:\n                raise ValueError(\n                    \"conn_timeout and timeout parameters \"\n                    \"conflict, please setup \"\n                    \"timeout.connect\"\n                )\n\n        if connector is None:\n            connector = TCPConnector(loop=loop)\n\n        if connector._loop is not loop:\n            raise RuntimeError(\"Session and connector has to use same event loop\")\n\n        self._loop = loop\n\n        if loop.get_debug():\n            self._source_traceback = traceback.extract_stack(sys._getframe(1))\n\n        if cookie_jar is None:\n            cookie_jar = CookieJar(loop=loop)\n        self._cookie_jar = cookie_jar\n\n        if cookies is not None:\n            self._cookie_jar.update_cookies(cookies)\n\n        self._connector = connector\n        self._connector_owner = connector_owner\n        self._default_auth = auth\n        self._version = version\n        self._json_serialize = json_serialize\n        self._raise_for_status = raise_for_status\n        self._auto_decompress = auto_decompress\n        self._trust_env = trust_env\n        self._requote_redirect_url = requote_redirect_url\n        self._read_bufsize = read_bufsize\n        self._max_line_size = max_line_size\n        self._max_field_size = max_field_size\n\n        # Convert to list of tuples\n        if headers:\n            real_headers: CIMultiDict[str] = CIMultiDict(headers)\n        else:\n            real_headers = CIMultiDict()\n        self._default_headers: CIMultiDict[str] = real_headers\n        if skip_auto_headers is not None:\n            self._skip_auto_headers = frozenset(istr(i) for i in skip_auto_headers)\n        else:\n            self._skip_auto_headers = frozenset()\n\n        self._request_class = request_class\n        self._response_class = response_class\n        self._ws_response_class = ws_response_class\n\n        self._trace_configs = trace_configs or []\n        for trace_config in self._trace_configs:\n            trace_config.freeze()\n\n        self._resolve_charset = fallback_charset_resolver\n\n        self._default_proxy = proxy\n        self._default_proxy_auth = proxy_auth\n\n    def __init_subclass__(cls: Type[\"ClientSession\"]) -> None:\n        warnings.warn(\n            \"Inheritance class {} from ClientSession \"\n            \"is discouraged\".format(cls.__name__),\n            DeprecationWarning,\n            stacklevel=2,\n        )\n\n    if DEBUG:\n\n        def __setattr__(self, name: str, val: Any) -> None:\n            if name not in self.ATTRS:\n                warnings.warn(\n                    \"Setting custom ClientSession.{} attribute \"\n                    \"is discouraged\".format(name),\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n            super().__setattr__(name, val)\n\n    def __del__(self, _warnings: Any = warnings) -> None:\n        if not self.closed:\n            kwargs = {\"source\": self}\n            _warnings.warn(\n                f\"Unclosed client session {self!r}\", ResourceWarning, **kwargs\n            )\n            context = {\"client_session\": self, \"message\": \"Unclosed client session\"}\n            if self._source_traceback is not None:\n                context[\"source_traceback\"] = self._source_traceback\n            self._loop.call_exception_handler(context)\n\n    if sys.version_info >= (3, 11) and TYPE_CHECKING:\n\n        def request(\n            self,\n            method: str,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n    else:\n\n        def request(\n            self, method: str, url: StrOrURL, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP request.\"\"\"\n            return _RequestContextManager(self._request(method, url, **kwargs))\n\n    def _build_url(self, str_or_url: StrOrURL) -> URL:\n        url = URL(str_or_url)\n        if self._base_url is None:\n            return url\n        else:\n            assert not url.absolute and url.path.startswith(\"/\")\n            return self._base_url.join(url)\n\n    async def _request(\n        self,\n        method: str,\n        str_or_url: StrOrURL,\n        *,\n        params: Query = None,\n        data: Any = None,\n        json: Any = None,\n        cookies: Optional[LooseCookies] = None,\n        headers: Optional[LooseHeaders] = None,\n        skip_auto_headers: Optional[Iterable[str]] = None,\n        auth: Optional[BasicAuth] = None,\n        allow_redirects: bool = True,\n        max_redirects: int = 10,\n        compress: Union[str, bool, None] = None,\n        chunked: Optional[bool] = None,\n        expect100: bool = False,\n        raise_for_status: Union[\n            None, bool, Callable[[ClientResponse], Awaitable[None]]\n        ] = None,\n        read_until_eof: bool = True,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        timeout: Union[ClientTimeout, _SENTINEL] = sentinel,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        server_hostname: Optional[str] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        trace_request_ctx: Optional[Mapping[str, str]] = None,\n        read_bufsize: Optional[int] = None,\n        auto_decompress: Optional[bool] = None,\n        max_line_size: Optional[int] = None,\n        max_field_size: Optional[int] = None,\n    ) -> ClientResponse:\n\n        # NOTE: timeout clamps existing connect and read timeouts.  We cannot\n        # set the default to None because we need to detect if the user wants\n        # to use the existing timeouts by setting timeout to None.\n\n        if self.closed:\n            raise RuntimeError(\"Session is closed\")\n\n        ssl = _merge_ssl_params(ssl, verify_ssl, ssl_context, fingerprint)\n\n        if data is not None and json is not None:\n            raise ValueError(\n                \"data and json parameters can not be used at the same time\"\n            )\n        elif json is not None:\n            data = payload.JsonPayload(json, dumps=self._json_serialize)\n\n        if not isinstance(chunked, bool) and chunked is not None:\n            warnings.warn(\"Chunk size is deprecated #1615\", DeprecationWarning)\n\n        redirects = 0\n        history = []\n        version = self._version\n        params = params or {}\n\n        # Merge with default headers and transform to CIMultiDict\n        headers = self._prepare_headers(headers)\n\n        try:\n            url = self._build_url(str_or_url)\n        except ValueError as e:\n            raise InvalidUrlClientError(str_or_url) from e\n\n        assert self._connector is not None\n        if url.scheme not in self._connector.allowed_protocol_schema_set:\n            raise NonHttpUrlClientError(url)\n\n        skip_headers = set(self._skip_auto_headers)\n        if skip_auto_headers is not None:\n            for i in skip_auto_headers:\n                skip_headers.add(istr(i))\n\n        if proxy is None:\n            proxy = self._default_proxy\n        if proxy_auth is None:\n            proxy_auth = self._default_proxy_auth\n\n        if proxy is None:\n            proxy_headers = None\n        else:\n            proxy_headers = self._prepare_headers(proxy_headers)\n            try:\n                proxy = URL(proxy)\n            except ValueError as e:\n                raise InvalidURL(proxy) from e\n\n        if timeout is sentinel:\n            real_timeout: ClientTimeout = self._timeout\n        else:\n            if not isinstance(timeout, ClientTimeout):\n                real_timeout = ClientTimeout(total=timeout)\n            else:\n                real_timeout = timeout\n        # timeout is cumulative for all request operations\n        # (request, redirects, responses, data consuming)\n        tm = TimeoutHandle(\n            self._loop, real_timeout.total, ceil_threshold=real_timeout.ceil_threshold\n        )\n        handle = tm.start()\n\n        if read_bufsize is None:\n            read_bufsize = self._read_bufsize\n\n        if auto_decompress is None:\n            auto_decompress = self._auto_decompress\n\n        if max_line_size is None:\n            max_line_size = self._max_line_size\n\n        if max_field_size is None:\n            max_field_size = self._max_field_size\n\n        traces = [\n            Trace(\n                self,\n                trace_config,\n                trace_config.trace_config_ctx(trace_request_ctx=trace_request_ctx),\n            )\n            for trace_config in self._trace_configs\n        ]\n\n        for trace in traces:\n            await trace.send_request_start(method, url.update_query(params), headers)\n\n        timer = tm.timer()\n        try:\n            with timer:\n                # https://www.rfc-editor.org/rfc/rfc9112.html#name-retrying-requests\n                retry_persistent_connection = method in IDEMPOTENT_METHODS\n                while True:\n                    url, auth_from_url = strip_auth_from_url(url)\n                    if not url.raw_host:\n                        # NOTE: Bail early, otherwise, causes `InvalidURL` through\n                        # NOTE: `self._request_class()` below.\n                        err_exc_cls = (\n                            InvalidUrlRedirectClientError\n                            if redirects\n                            else InvalidUrlClientError\n                        )\n                        raise err_exc_cls(url)\n                    if auth and auth_from_url:\n                        raise ValueError(\n                            \"Cannot combine AUTH argument with \"\n                            \"credentials encoded in URL\"\n                        )\n\n                    if auth is None:\n                        auth = auth_from_url\n\n                    if auth is None and (\n                        not self._base_url or self._base_url.origin() == url.origin()\n                    ):\n                        auth = self._default_auth\n                    # It would be confusing if we support explicit\n                    # Authorization header with auth argument\n                    if (\n                        headers is not None\n                        and auth is not None\n                        and hdrs.AUTHORIZATION in headers\n                    ):\n                        raise ValueError(\n                            \"Cannot combine AUTHORIZATION header \"\n                            \"with AUTH argument or credentials \"\n                            \"encoded in URL\"\n                        )\n\n                    all_cookies = self._cookie_jar.filter_cookies(url)\n\n                    if cookies is not None:\n                        tmp_cookie_jar = CookieJar()\n                        tmp_cookie_jar.update_cookies(cookies)\n                        req_cookies = tmp_cookie_jar.filter_cookies(url)\n                        if req_cookies:\n                            all_cookies.load(req_cookies)\n\n                    if proxy is not None:\n                        proxy = URL(proxy)\n                    elif self._trust_env:\n                        with suppress(LookupError):\n                            proxy, proxy_auth = get_env_proxy_for_url(url)\n\n                    req = self._request_class(\n                        method,\n                        url,\n                        params=params,\n                        headers=headers,\n                        skip_auto_headers=skip_headers if skip_headers else None,\n                        data=data,\n                        cookies=all_cookies,\n                        auth=auth,\n                        version=version,\n                        compress=compress,\n                        chunked=chunked,\n                        expect100=expect100,\n                        loop=self._loop,\n                        response_class=self._response_class,\n                        proxy=proxy,\n                        proxy_auth=proxy_auth,\n                        timer=timer,\n                        session=self,\n                        ssl=ssl if ssl is not None else True,\n                        server_hostname=server_hostname,\n                        proxy_headers=proxy_headers,\n                        traces=traces,\n                        trust_env=self.trust_env,\n                    )\n\n                    # connection timeout\n                    try:\n                        async with ceil_timeout(\n                            real_timeout.connect,\n                            ceil_threshold=real_timeout.ceil_threshold,\n                        ):\n                            conn = await self._connector.connect(\n                                req, traces=traces, timeout=real_timeout\n                            )\n                    except asyncio.TimeoutError as exc:\n                        raise ConnectionTimeoutError(\n                            f\"Connection timeout to host {url}\"\n                        ) from exc\n\n                    assert conn.transport is not None\n\n                    assert conn.protocol is not None\n                    conn.protocol.set_response_params(\n                        timer=timer,\n                        skip_payload=method_must_be_empty_body(method),\n                        read_until_eof=read_until_eof,\n                        auto_decompress=auto_decompress,\n                        read_timeout=real_timeout.sock_read,\n                        read_bufsize=read_bufsize,\n                        timeout_ceil_threshold=self._connector._timeout_ceil_threshold,\n                        max_line_size=max_line_size,\n                        max_field_size=max_field_size,\n                    )\n\n                    try:\n                        try:\n                            resp = await req.send(conn)\n                            try:\n                                await resp.start(conn)\n                            except BaseException:\n                                resp.close()\n                                raise\n                        except BaseException:\n                            conn.close()\n                            raise\n                    except (ClientOSError, ServerDisconnectedError):\n                        if retry_persistent_connection:\n                            retry_persistent_connection = False\n                            continue\n                        raise\n                    except ClientError:\n                        raise\n                    except OSError as exc:\n                        if exc.errno is None and isinstance(exc, asyncio.TimeoutError):\n                            raise\n                        raise ClientOSError(*exc.args) from exc\n\n                    self._cookie_jar.update_cookies(resp.cookies, resp.url)\n\n                    # redirects\n                    if resp.status in (301, 302, 303, 307, 308) and allow_redirects:\n\n                        for trace in traces:\n                            await trace.send_request_redirect(\n                                method, url.update_query(params), headers, resp\n                            )\n\n                        redirects += 1\n                        history.append(resp)\n                        if max_redirects and redirects >= max_redirects:\n                            resp.close()\n                            raise TooManyRedirects(\n                                history[0].request_info, tuple(history)\n                            )\n\n                        # For 301 and 302, mimic IE, now changed in RFC\n                        # https://github.com/kennethreitz/requests/pull/269\n                        if (resp.status == 303 and resp.method != hdrs.METH_HEAD) or (\n                            resp.status in (301, 302) and resp.method == hdrs.METH_POST\n                        ):\n                            method = hdrs.METH_GET\n                            data = None\n                            if headers.get(hdrs.CONTENT_LENGTH):\n                                headers.pop(hdrs.CONTENT_LENGTH)\n\n                        r_url = resp.headers.get(hdrs.LOCATION) or resp.headers.get(\n                            hdrs.URI\n                        )\n                        if r_url is None:\n                            # see github.com/aio-libs/aiohttp/issues/2022\n                            break\n                        else:\n                            # reading from correct redirection\n                            # response is forbidden\n                            resp.release()\n\n                        try:\n                            parsed_redirect_url = URL(\n                                r_url, encoded=not self._requote_redirect_url\n                            )\n                        except ValueError as e:\n                            raise InvalidUrlRedirectClientError(\n                                r_url,\n                                \"Server attempted redirecting to a location that does not look like a URL\",\n                            ) from e\n\n                        scheme = parsed_redirect_url.scheme\n                        if scheme not in HTTP_AND_EMPTY_SCHEMA_SET:\n                            resp.close()\n                            raise NonHttpUrlRedirectClientError(r_url)\n                        elif not scheme:\n                            parsed_redirect_url = url.join(parsed_redirect_url)\n\n                        try:\n                            redirect_origin = parsed_redirect_url.origin()\n                        except ValueError as origin_val_err:\n                            raise InvalidUrlRedirectClientError(\n                                parsed_redirect_url,\n                                \"Invalid redirect URL origin\",\n                            ) from origin_val_err\n\n                        if url.origin() != redirect_origin:\n                            auth = None\n                            headers.pop(hdrs.AUTHORIZATION, None)\n\n                        url = parsed_redirect_url\n                        params = {}\n                        resp.release()\n                        continue\n\n                    break\n\n            # check response status\n            if raise_for_status is None:\n                raise_for_status = self._raise_for_status\n\n            if raise_for_status is None:\n                pass\n            elif callable(raise_for_status):\n                await raise_for_status(resp)\n            elif raise_for_status:\n                resp.raise_for_status()\n\n            # register connection\n            if handle is not None:\n                if resp.connection is not None:\n                    resp.connection.add_callback(handle.cancel)\n                else:\n                    handle.cancel()\n\n            resp._history = tuple(history)\n\n            for trace in traces:\n                await trace.send_request_end(\n                    method, url.update_query(params), headers, resp\n                )\n            return resp\n\n        except BaseException as e:\n            # cleanup timer\n            tm.close()\n            if handle:\n                handle.cancel()\n                handle = None\n\n            for trace in traces:\n                await trace.send_request_exception(\n                    method, url.update_query(params), headers, e\n                )\n            raise\n\n    def ws_connect(\n        self,\n        url: StrOrURL,\n        *,\n        method: str = hdrs.METH_GET,\n        protocols: Iterable[str] = (),\n        timeout: Union[ClientWSTimeout, _SENTINEL] = sentinel,\n        receive_timeout: Optional[float] = None,\n        autoclose: bool = True,\n        autoping: bool = True,\n        heartbeat: Optional[float] = None,\n        auth: Optional[BasicAuth] = None,\n        origin: Optional[str] = None,\n        params: Query = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        compress: int = 0,\n        max_msg_size: int = 4 * 1024 * 1024,\n    ) -> \"_WSRequestContextManager\":\n        \"\"\"Initiate websocket connection.\"\"\"\n        return _WSRequestContextManager(\n            self._ws_connect(\n                url,\n                method=method,\n                protocols=protocols,\n                timeout=timeout,\n                receive_timeout=receive_timeout,\n                autoclose=autoclose,\n                autoping=autoping,\n                heartbeat=heartbeat,\n                auth=auth,\n                origin=origin,\n                params=params,\n                headers=headers,\n                proxy=proxy,\n                proxy_auth=proxy_auth,\n                ssl=ssl,\n                verify_ssl=verify_ssl,\n                fingerprint=fingerprint,\n                ssl_context=ssl_context,\n                proxy_headers=proxy_headers,\n                compress=compress,\n                max_msg_size=max_msg_size,\n            )\n        )\n\n    async def _ws_connect(\n        self,\n        url: StrOrURL,\n        *,\n        method: str = hdrs.METH_GET,\n        protocols: Iterable[str] = (),\n        timeout: Union[ClientWSTimeout, _SENTINEL] = sentinel,\n        receive_timeout: Optional[float] = None,\n        autoclose: bool = True,\n        autoping: bool = True,\n        heartbeat: Optional[float] = None,\n        auth: Optional[BasicAuth] = None,\n        origin: Optional[str] = None,\n        params: Query = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        compress: int = 0,\n        max_msg_size: int = 4 * 1024 * 1024,\n    ) -> ClientWebSocketResponse:\n        if timeout is not sentinel:\n            if isinstance(timeout, ClientWSTimeout):\n                ws_timeout = timeout\n            else:\n                warnings.warn(\n                    \"parameter 'timeout' of type 'float' \"\n                    \"is deprecated, please use \"\n                    \"'timeout=ClientWSTimeout(ws_close=...)'\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n                ws_timeout = ClientWSTimeout(ws_close=timeout)\n        else:\n            ws_timeout = DEFAULT_WS_CLIENT_TIMEOUT\n        if receive_timeout is not None:\n            warnings.warn(\n                \"float parameter 'receive_timeout' \"\n                \"is deprecated, please use parameter \"\n                \"'timeout=ClientWSTimeout(ws_receive=...)'\",\n                DeprecationWarning,\n                stacklevel=2,\n            )\n            ws_timeout = attr.evolve(ws_timeout, ws_receive=receive_timeout)\n\n        if headers is None:\n            real_headers: CIMultiDict[str] = CIMultiDict()\n        else:\n            real_headers = CIMultiDict(headers)\n\n        default_headers = {\n            hdrs.UPGRADE: \"websocket\",\n            hdrs.CONNECTION: \"Upgrade\",\n            hdrs.SEC_WEBSOCKET_VERSION: \"13\",\n        }\n\n        for key, value in default_headers.items():\n            real_headers.setdefault(key, value)\n\n        sec_key = base64.b64encode(os.urandom(16))\n        real_headers[hdrs.SEC_WEBSOCKET_KEY] = sec_key.decode()\n\n        if protocols:\n            real_headers[hdrs.SEC_WEBSOCKET_PROTOCOL] = \",\".join(protocols)\n        if origin is not None:\n            real_headers[hdrs.ORIGIN] = origin\n        if compress:\n            extstr = ws_ext_gen(compress=compress)\n            real_headers[hdrs.SEC_WEBSOCKET_EXTENSIONS] = extstr\n\n        # For the sake of backward compatibility, if user passes in None, convert it to True\n        if ssl is None:\n            warnings.warn(\n                \"ssl=None is deprecated, please use ssl=True\",\n                DeprecationWarning,\n                stacklevel=2,\n            )\n            ssl = True\n        ssl = _merge_ssl_params(ssl, verify_ssl, ssl_context, fingerprint)\n\n        # send request\n        resp = await self.request(\n            method,\n            url,\n            params=params,\n            headers=real_headers,\n            read_until_eof=False,\n            auth=auth,\n            proxy=proxy,\n            proxy_auth=proxy_auth,\n            ssl=ssl,\n            proxy_headers=proxy_headers,\n        )\n\n        try:\n            # check handshake\n            if resp.status != 101:\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid response status\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            if resp.headers.get(hdrs.UPGRADE, \"\").lower() != \"websocket\":\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid upgrade header\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            if resp.headers.get(hdrs.CONNECTION, \"\").lower() != \"upgrade\":\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid connection header\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            # key calculation\n            r_key = resp.headers.get(hdrs.SEC_WEBSOCKET_ACCEPT, \"\")\n            match = base64.b64encode(hashlib.sha1(sec_key + WS_KEY).digest()).decode()\n            if r_key != match:\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid challenge response\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            # websocket protocol\n            protocol = None\n            if protocols and hdrs.SEC_WEBSOCKET_PROTOCOL in resp.headers:\n                resp_protocols = [\n                    proto.strip()\n                    for proto in resp.headers[hdrs.SEC_WEBSOCKET_PROTOCOL].split(\",\")\n                ]\n\n                for proto in resp_protocols:\n                    if proto in protocols:\n                        protocol = proto\n                        break\n\n            # websocket compress\n            notakeover = False\n            if compress:\n                compress_hdrs = resp.headers.get(hdrs.SEC_WEBSOCKET_EXTENSIONS)\n                if compress_hdrs:\n                    try:\n                        compress, notakeover = ws_ext_parse(compress_hdrs)\n                    except WSHandshakeError as exc:\n                        raise WSServerHandshakeError(\n                            resp.request_info,\n                            resp.history,\n                            message=exc.args[0],\n                            status=resp.status,\n                            headers=resp.headers,\n                        ) from exc\n                else:\n                    compress = 0\n                    notakeover = False\n\n            conn = resp.connection\n            assert conn is not None\n            conn_proto = conn.protocol\n            assert conn_proto is not None\n\n            # For WS connection the read_timeout must be either receive_timeout or greater\n            # None == no timeout, i.e. infinite timeout, so None is the max timeout possible\n            if ws_timeout.ws_receive is None:\n                # Reset regardless\n                conn_proto.read_timeout = None\n            elif conn_proto.read_timeout is not None:\n                conn_proto.read_timeout = max(\n                    ws_timeout.ws_receive, conn_proto.read_timeout\n                )\n\n            transport = conn.transport\n            assert transport is not None\n            reader: FlowControlDataQueue[WSMessage] = FlowControlDataQueue(\n                conn_proto, 2**16, loop=self._loop\n            )\n            conn_proto.set_parser(WebSocketReader(reader, max_msg_size), reader)\n            writer = WebSocketWriter(\n                conn_proto,\n                transport,\n                use_mask=True,\n                compress=compress,\n                notakeover=notakeover,\n            )\n        except BaseException:\n            resp.close()\n            raise\n        else:\n            return self._ws_response_class(\n                reader,\n                writer,\n                protocol,\n                resp,\n                ws_timeout,\n                autoclose,\n                autoping,\n                self._loop,\n                heartbeat=heartbeat,\n                compress=compress,\n                client_notakeover=notakeover,\n            )\n\n    def _prepare_headers(self, headers: Optional[LooseHeaders]) -> \"CIMultiDict[str]\":\n        \"\"\"Add default headers and transform it to CIMultiDict\"\"\"\n        # Convert headers to MultiDict\n        result = CIMultiDict(self._default_headers)\n        if headers:\n            if not isinstance(headers, (MultiDictProxy, MultiDict)):\n                headers = CIMultiDict(headers)\n            added_names: Set[str] = set()\n            for key, value in headers.items():\n                if key in added_names:\n                    result.add(key, value)\n                else:\n                    result[key] = value\n                    added_names.add(key)\n        return result\n\n    if sys.version_info >= (3, 11) and TYPE_CHECKING:\n\n        def get(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def options(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def head(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def post(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def put(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def patch(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def delete(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n    else:\n\n        def get(\n            self, url: StrOrURL, *, allow_redirects: bool = True, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP GET request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_GET, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def options(\n            self, url: StrOrURL, *, allow_redirects: bool = True, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP OPTIONS request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_OPTIONS, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def head(\n            self, url: StrOrURL, *, allow_redirects: bool = False, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP HEAD request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_HEAD, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def post(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP POST request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_POST, url, data=data, **kwargs)\n            )\n\n        def put(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP PUT request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_PUT, url, data=data, **kwargs)\n            )\n\n        def patch(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP PATCH request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_PATCH, url, data=data, **kwargs)\n            )\n\n        def delete(self, url: StrOrURL, **kwargs: Any) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP DELETE request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_DELETE, url, **kwargs)\n            )\n\n    async def close(self) -> None:\n        \"\"\"Close underlying connector.\n\n        Release all acquired resources.\n        \"\"\"\n        if not self.closed:\n            if self._connector is not None and self._connector_owner:\n                await self._connector.close()\n            self._connector = None\n\n    @property\n    def closed(self) -> bool:\n        \"\"\"Is client session closed.\n\n        A readonly property.\n        \"\"\"\n        return self._connector is None or self._connector.closed\n\n    @property\n    def connector(self) -> Optional[BaseConnector]:\n        \"\"\"Connector instance used for the session.\"\"\"\n        return self._connector\n\n    @property\n    def cookie_jar(self) -> AbstractCookieJar:\n        \"\"\"The session cookies.\"\"\"\n        return self._cookie_jar\n\n    @property\n    def version(self) -> Tuple[int, int]:\n        \"\"\"The session HTTP protocol version.\"\"\"\n        return self._version\n\n    @property\n    def requote_redirect_url(self) -> bool:\n        \"\"\"Do URL requoting on redirection handling.\"\"\"\n        return self._requote_redirect_url\n\n    @requote_redirect_url.setter\n    def requote_redirect_url(self, val: bool) -> None:\n        \"\"\"Do URL requoting on redirection handling.\"\"\"\n        warnings.warn(\n            \"session.requote_redirect_url modification is deprecated #2778\",\n            DeprecationWarning,\n            stacklevel=2,\n        )\n        self._requote_redirect_url = val\n\n    @property\n    def loop(self) -> asyncio.AbstractEventLoop:\n        \"\"\"Session's loop.\"\"\"\n        warnings.warn(\n            \"client.loop property is deprecated\", DeprecationWarning, stacklevel=2\n        )\n        return self._loop\n\n    @property\n    def timeout(self) -> ClientTimeout:\n        \"\"\"Timeout for the session.\"\"\"\n        return self._timeout\n\n    @property\n    def headers(self) -> \"CIMultiDict[str]\":\n        \"\"\"The default headers of the client session.\"\"\"\n        return self._default_headers\n\n    @property\n    def skip_auto_headers(self) -> FrozenSet[istr]:\n        \"\"\"Headers for which autogeneration should be skipped\"\"\"\n        return self._skip_auto_headers\n\n    @property\n    def auth(self) -> Optional[BasicAuth]:\n        \"\"\"An object that represents HTTP Basic Authorization\"\"\"\n        return self._default_auth\n\n    @property\n    def json_serialize(self) -> JSONEncoder:\n        \"\"\"Json serializer callable\"\"\"\n        return self._json_serialize\n\n    @property\n    def connector_owner(self) -> bool:\n        \"\"\"Should connector be closed on session closing\"\"\"\n        return self._connector_owner\n\n    @property\n    def raise_for_status(\n        self,\n    ) -> Union[bool, Callable[[ClientResponse], Awaitable[None]]]:\n        \"\"\"Should `ClientResponse.raise_for_status()` be called for each response.\"\"\"\n        return self._raise_for_status\n\n    @property\n    def auto_decompress(self) -> bool:\n        \"\"\"Should the body response be automatically decompressed.\"\"\"\n        return self._auto_decompress\n\n    @property\n    def trust_env(self) -> bool:\n        \"\"\"\n        Should proxies information from environment or netrc be trusted.\n\n        Information is from HTTP_PROXY / HTTPS_PROXY environment variables\n        or ~/.netrc file if present.\n        \"\"\"\n        return self._trust_env\n\n    @property\n    def trace_configs(self) -> List[TraceConfig]:\n        \"\"\"A list of TraceConfig instances used for client tracing\"\"\"\n        return self._trace_configs\n\n    def detach(self) -> None:\n        \"\"\"Detach connector from session without closing the former.\n\n        Session is switched to closed state anyway.\n        \"\"\"\n        self._connector = None\n\n    def __enter__(self) -> None:\n        raise TypeError(\"Use async with instead\")\n\n    def __exit__(\n        self,\n        exc_type: Optional[Type[BaseException]],\n        exc_val: Optional[BaseException],\n        exc_tb: Optional[TracebackType],\n    ) -> None:\n        # __exit__ should exist in pair with __enter__ but never executed\n        pass  # pragma: no cover\n\n    async def __aenter__(self) -> \"ClientSession\":\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        await self.close()",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 225,
                            "end_lineno": 1373,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 266,
                            "length": 6
                        },
                        "new_range": {
                            "start": 268,
                            "length": 8
                        },
                        "section": "class ClientSession:"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        loop: Optional[asyncio.AbstractEventLoop] = None,",
                                "type": "context"
                            },
                            {
                                "content": "        cookies: Optional[LooseCookies] = None,",
                                "type": "context"
                            },
                            {
                                "content": "        headers: Optional[LooseHeaders] = None,",
                                "type": "context"
                            },
                            {
                                "content": "        proxy: Optional[StrOrURL] = None,",
                                "type": "added"
                            },
                            {
                                "content": "        proxy_auth: Optional[BasicAuth] = None,",
                                "type": "added"
                            },
                            {
                                "content": "        skip_auto_headers: Optional[Iterable[str]] = None,",
                                "type": "context"
                            },
                            {
                                "content": "        auth: Optional[BasicAuth] = None,",
                                "type": "context"
                            },
                            {
                                "content": "        json_serialize: JSONEncoder = json.dumps,",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "aiohttp/client.py",
                            "type": "method",
                            "name": "ClientSession.__init__",
                            "content": "class ClientSession:\n    \"\"\"First-class interface for making HTTP requests.\"\"\"\n\n    ATTRS = frozenset(\n        [\n            \"_base_url\",\n            \"_source_traceback\",\n            \"_connector\",\n            \"requote_redirect_url\",\n            \"_loop\",\n            \"_cookie_jar\",\n            \"_connector_owner\",\n            \"_default_auth\",\n            \"_version\",\n            \"_json_serialize\",\n            \"_requote_redirect_url\",\n            \"_timeout\",\n            \"_raise_for_status\",\n            \"_auto_decompress\",\n            \"_trust_env\",\n            \"_default_headers\",\n            \"_skip_auto_headers\",\n            \"_request_class\",\n            \"_response_class\",\n            \"_ws_response_class\",\n            \"_trace_configs\",\n            \"_read_bufsize\",\n            \"_max_line_size\",\n            \"_max_field_size\",\n            \"_resolve_charset\",\n            \"_default_proxy\",\n            \"_default_proxy_auth\",\n        ]\n    )\n\n    _source_traceback: Optional[traceback.StackSummary] = None\n    _connector: Optional[BaseConnector] = None\n\n    def __init__(\n        self,\n        base_url: Optional[StrOrURL] = None,\n        *,\n        connector: Optional[BaseConnector] = None,\n        loop: Optional[asyncio.AbstractEventLoop] = None,\n        cookies: Optional[LooseCookies] = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        skip_auto_headers: Optional[Iterable[str]] = None,\n        auth: Optional[BasicAuth] = None,\n        json_serialize: JSONEncoder = json.dumps,\n        request_class: Type[ClientRequest] = ClientRequest,\n        response_class: Type[ClientResponse] = ClientResponse,\n        ws_response_class: Type[ClientWebSocketResponse] = ClientWebSocketResponse,\n        version: HttpVersion = http.HttpVersion11,\n        cookie_jar: Optional[AbstractCookieJar] = None,\n        connector_owner: bool = True,\n        raise_for_status: Union[\n            bool, Callable[[ClientResponse], Awaitable[None]]\n        ] = False,\n        read_timeout: Union[float, _SENTINEL] = sentinel,\n        conn_timeout: Optional[float] = None,\n        timeout: Union[object, ClientTimeout] = sentinel,\n        auto_decompress: bool = True,\n        trust_env: bool = False,\n        requote_redirect_url: bool = True,\n        trace_configs: Optional[List[TraceConfig]] = None,\n        read_bufsize: int = 2**16,\n        max_line_size: int = 8190,\n        max_field_size: int = 8190,\n        fallback_charset_resolver: _CharsetResolver = lambda r, b: \"utf-8\",\n    ) -> None:\n        # We initialise _connector to None immediately, as it's referenced in __del__()\n        # and could cause issues if an exception occurs during initialisation.\n        self._connector: Optional[BaseConnector] = None\n\n        if loop is None:\n            if connector is not None:\n                loop = connector._loop\n\n        loop = loop or asyncio.get_running_loop()\n\n        if base_url is None or isinstance(base_url, URL):\n            self._base_url: Optional[URL] = base_url\n        else:\n            self._base_url = URL(base_url)\n            assert (\n                self._base_url.origin() == self._base_url\n            ), \"Only absolute URLs without path part are supported\"\n\n        if timeout is sentinel or timeout is None:\n            self._timeout = DEFAULT_TIMEOUT\n            if read_timeout is not sentinel:\n                warnings.warn(\n                    \"read_timeout is deprecated, use timeout argument instead\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n                self._timeout = attr.evolve(self._timeout, total=read_timeout)\n            if conn_timeout is not None:\n                self._timeout = attr.evolve(self._timeout, connect=conn_timeout)\n                warnings.warn(\n                    \"conn_timeout is deprecated, use timeout argument instead\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n        else:\n            if not isinstance(timeout, ClientTimeout):\n                raise ValueError(\n                    f\"timeout parameter cannot be of {type(timeout)} type, \"\n                    \"please use 'timeout=ClientTimeout(...)'\",\n                )\n            self._timeout = timeout\n            if read_timeout is not sentinel:\n                raise ValueError(\n                    \"read_timeout and timeout parameters \"\n                    \"conflict, please setup \"\n                    \"timeout.read\"\n                )\n            if conn_timeout is not None:\n                raise ValueError(\n                    \"conn_timeout and timeout parameters \"\n                    \"conflict, please setup \"\n                    \"timeout.connect\"\n                )\n\n        if connector is None:\n            connector = TCPConnector(loop=loop)\n\n        if connector._loop is not loop:\n            raise RuntimeError(\"Session and connector has to use same event loop\")\n\n        self._loop = loop\n\n        if loop.get_debug():\n            self._source_traceback = traceback.extract_stack(sys._getframe(1))\n\n        if cookie_jar is None:\n            cookie_jar = CookieJar(loop=loop)\n        self._cookie_jar = cookie_jar\n\n        if cookies is not None:\n            self._cookie_jar.update_cookies(cookies)\n\n        self._connector = connector\n        self._connector_owner = connector_owner\n        self._default_auth = auth\n        self._version = version\n        self._json_serialize = json_serialize\n        self._raise_for_status = raise_for_status\n        self._auto_decompress = auto_decompress\n        self._trust_env = trust_env\n        self._requote_redirect_url = requote_redirect_url\n        self._read_bufsize = read_bufsize\n        self._max_line_size = max_line_size\n        self._max_field_size = max_field_size\n\n        # Convert to list of tuples\n        if headers:\n            real_headers: CIMultiDict[str] = CIMultiDict(headers)\n        else:\n            real_headers = CIMultiDict()\n        self._default_headers: CIMultiDict[str] = real_headers\n        if skip_auto_headers is not None:\n            self._skip_auto_headers = frozenset(istr(i) for i in skip_auto_headers)\n        else:\n            self._skip_auto_headers = frozenset()\n\n        self._request_class = request_class\n        self._response_class = response_class\n        self._ws_response_class = ws_response_class\n\n        self._trace_configs = trace_configs or []\n        for trace_config in self._trace_configs:\n            trace_config.freeze()\n\n        self._resolve_charset = fallback_charset_resolver\n\n        self._default_proxy = proxy\n        self._default_proxy_auth = proxy_auth\n\n    def __init_subclass__(cls: Type[\"ClientSession\"]) -> None:\n        warnings.warn(\n            \"Inheritance class {} from ClientSession \"\n            \"is discouraged\".format(cls.__name__),\n            DeprecationWarning,\n            stacklevel=2,\n        )\n\n    if DEBUG:\n\n        def __setattr__(self, name: str, val: Any) -> None:\n            if name not in self.ATTRS:\n                warnings.warn(\n                    \"Setting custom ClientSession.{} attribute \"\n                    \"is discouraged\".format(name),\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n            super().__setattr__(name, val)\n\n    def __del__(self, _warnings: Any = warnings) -> None:\n        if not self.closed:\n            kwargs = {\"source\": self}\n            _warnings.warn(\n                f\"Unclosed client session {self!r}\", ResourceWarning, **kwargs\n            )\n            context = {\"client_session\": self, \"message\": \"Unclosed client session\"}\n            if self._source_traceback is not None:\n                context[\"source_traceback\"] = self._source_traceback\n            self._loop.call_exception_handler(context)\n\n    if sys.version_info >= (3, 11) and TYPE_CHECKING:\n\n        def request(\n            self,\n            method: str,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n    else:\n\n        def request(\n            self, method: str, url: StrOrURL, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP request.\"\"\"\n            return _RequestContextManager(self._request(method, url, **kwargs))\n\n    def _build_url(self, str_or_url: StrOrURL) -> URL:\n        url = URL(str_or_url)\n        if self._base_url is None:\n            return url\n        else:\n            assert not url.absolute and url.path.startswith(\"/\")\n            return self._base_url.join(url)\n\n    async def _request(\n        self,\n        method: str,\n        str_or_url: StrOrURL,\n        *,\n        params: Query = None,\n        data: Any = None,\n        json: Any = None,\n        cookies: Optional[LooseCookies] = None,\n        headers: Optional[LooseHeaders] = None,\n        skip_auto_headers: Optional[Iterable[str]] = None,\n        auth: Optional[BasicAuth] = None,\n        allow_redirects: bool = True,\n        max_redirects: int = 10,\n        compress: Union[str, bool, None] = None,\n        chunked: Optional[bool] = None,\n        expect100: bool = False,\n        raise_for_status: Union[\n            None, bool, Callable[[ClientResponse], Awaitable[None]]\n        ] = None,\n        read_until_eof: bool = True,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        timeout: Union[ClientTimeout, _SENTINEL] = sentinel,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        server_hostname: Optional[str] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        trace_request_ctx: Optional[Mapping[str, str]] = None,\n        read_bufsize: Optional[int] = None,\n        auto_decompress: Optional[bool] = None,\n        max_line_size: Optional[int] = None,\n        max_field_size: Optional[int] = None,\n    ) -> ClientResponse:\n\n        # NOTE: timeout clamps existing connect and read timeouts.  We cannot\n        # set the default to None because we need to detect if the user wants\n        # to use the existing timeouts by setting timeout to None.\n\n        if self.closed:\n            raise RuntimeError(\"Session is closed\")\n\n        ssl = _merge_ssl_params(ssl, verify_ssl, ssl_context, fingerprint)\n\n        if data is not None and json is not None:\n            raise ValueError(\n                \"data and json parameters can not be used at the same time\"\n            )\n        elif json is not None:\n            data = payload.JsonPayload(json, dumps=self._json_serialize)\n\n        if not isinstance(chunked, bool) and chunked is not None:\n            warnings.warn(\"Chunk size is deprecated #1615\", DeprecationWarning)\n\n        redirects = 0\n        history = []\n        version = self._version\n        params = params or {}\n\n        # Merge with default headers and transform to CIMultiDict\n        headers = self._prepare_headers(headers)\n\n        try:\n            url = self._build_url(str_or_url)\n        except ValueError as e:\n            raise InvalidUrlClientError(str_or_url) from e\n\n        assert self._connector is not None\n        if url.scheme not in self._connector.allowed_protocol_schema_set:\n            raise NonHttpUrlClientError(url)\n\n        skip_headers = set(self._skip_auto_headers)\n        if skip_auto_headers is not None:\n            for i in skip_auto_headers:\n                skip_headers.add(istr(i))\n\n        if proxy is None:\n            proxy = self._default_proxy\n        if proxy_auth is None:\n            proxy_auth = self._default_proxy_auth\n\n        if proxy is None:\n            proxy_headers = None\n        else:\n            proxy_headers = self._prepare_headers(proxy_headers)\n            try:\n                proxy = URL(proxy)\n            except ValueError as e:\n                raise InvalidURL(proxy) from e\n\n        if timeout is sentinel:\n            real_timeout: ClientTimeout = self._timeout\n        else:\n            if not isinstance(timeout, ClientTimeout):\n                real_timeout = ClientTimeout(total=timeout)\n            else:\n                real_timeout = timeout\n        # timeout is cumulative for all request operations\n        # (request, redirects, responses, data consuming)\n        tm = TimeoutHandle(\n            self._loop, real_timeout.total, ceil_threshold=real_timeout.ceil_threshold\n        )\n        handle = tm.start()\n\n        if read_bufsize is None:\n            read_bufsize = self._read_bufsize\n\n        if auto_decompress is None:\n            auto_decompress = self._auto_decompress\n\n        if max_line_size is None:\n            max_line_size = self._max_line_size\n\n        if max_field_size is None:\n            max_field_size = self._max_field_size\n\n        traces = [\n            Trace(\n                self,\n                trace_config,\n                trace_config.trace_config_ctx(trace_request_ctx=trace_request_ctx),\n            )\n            for trace_config in self._trace_configs\n        ]\n\n        for trace in traces:\n            await trace.send_request_start(method, url.update_query(params), headers)\n\n        timer = tm.timer()\n        try:\n            with timer:\n                # https://www.rfc-editor.org/rfc/rfc9112.html#name-retrying-requests\n                retry_persistent_connection = method in IDEMPOTENT_METHODS\n                while True:\n                    url, auth_from_url = strip_auth_from_url(url)\n                    if not url.raw_host:\n                        # NOTE: Bail early, otherwise, causes `InvalidURL` through\n                        # NOTE: `self._request_class()` below.\n                        err_exc_cls = (\n                            InvalidUrlRedirectClientError\n                            if redirects\n                            else InvalidUrlClientError\n                        )\n                        raise err_exc_cls(url)\n                    if auth and auth_from_url:\n                        raise ValueError(\n                            \"Cannot combine AUTH argument with \"\n                            \"credentials encoded in URL\"\n                        )\n\n                    if auth is None:\n                        auth = auth_from_url\n\n                    if auth is None and (\n                        not self._base_url or self._base_url.origin() == url.origin()\n                    ):\n                        auth = self._default_auth\n                    # It would be confusing if we support explicit\n                    # Authorization header with auth argument\n                    if (\n                        headers is not None\n                        and auth is not None\n                        and hdrs.AUTHORIZATION in headers\n                    ):\n                        raise ValueError(\n                            \"Cannot combine AUTHORIZATION header \"\n                            \"with AUTH argument or credentials \"\n                            \"encoded in URL\"\n                        )\n\n                    all_cookies = self._cookie_jar.filter_cookies(url)\n\n                    if cookies is not None:\n                        tmp_cookie_jar = CookieJar()\n                        tmp_cookie_jar.update_cookies(cookies)\n                        req_cookies = tmp_cookie_jar.filter_cookies(url)\n                        if req_cookies:\n                            all_cookies.load(req_cookies)\n\n                    if proxy is not None:\n                        proxy = URL(proxy)\n                    elif self._trust_env:\n                        with suppress(LookupError):\n                            proxy, proxy_auth = get_env_proxy_for_url(url)\n\n                    req = self._request_class(\n                        method,\n                        url,\n                        params=params,\n                        headers=headers,\n                        skip_auto_headers=skip_headers if skip_headers else None,\n                        data=data,\n                        cookies=all_cookies,\n                        auth=auth,\n                        version=version,\n                        compress=compress,\n                        chunked=chunked,\n                        expect100=expect100,\n                        loop=self._loop,\n                        response_class=self._response_class,\n                        proxy=proxy,\n                        proxy_auth=proxy_auth,\n                        timer=timer,\n                        session=self,\n                        ssl=ssl if ssl is not None else True,\n                        server_hostname=server_hostname,\n                        proxy_headers=proxy_headers,\n                        traces=traces,\n                        trust_env=self.trust_env,\n                    )\n\n                    # connection timeout\n                    try:\n                        async with ceil_timeout(\n                            real_timeout.connect,\n                            ceil_threshold=real_timeout.ceil_threshold,\n                        ):\n                            conn = await self._connector.connect(\n                                req, traces=traces, timeout=real_timeout\n                            )\n                    except asyncio.TimeoutError as exc:\n                        raise ConnectionTimeoutError(\n                            f\"Connection timeout to host {url}\"\n                        ) from exc\n\n                    assert conn.transport is not None\n\n                    assert conn.protocol is not None\n                    conn.protocol.set_response_params(\n                        timer=timer,\n                        skip_payload=method_must_be_empty_body(method),\n                        read_until_eof=read_until_eof,\n                        auto_decompress=auto_decompress,\n                        read_timeout=real_timeout.sock_read,\n                        read_bufsize=read_bufsize,\n                        timeout_ceil_threshold=self._connector._timeout_ceil_threshold,\n                        max_line_size=max_line_size,\n                        max_field_size=max_field_size,\n                    )\n\n                    try:\n                        try:\n                            resp = await req.send(conn)\n                            try:\n                                await resp.start(conn)\n                            except BaseException:\n                                resp.close()\n                                raise\n                        except BaseException:\n                            conn.close()\n                            raise\n                    except (ClientOSError, ServerDisconnectedError):\n                        if retry_persistent_connection:\n                            retry_persistent_connection = False\n                            continue\n                        raise\n                    except ClientError:\n                        raise\n                    except OSError as exc:\n                        if exc.errno is None and isinstance(exc, asyncio.TimeoutError):\n                            raise\n                        raise ClientOSError(*exc.args) from exc\n\n                    self._cookie_jar.update_cookies(resp.cookies, resp.url)\n\n                    # redirects\n                    if resp.status in (301, 302, 303, 307, 308) and allow_redirects:\n\n                        for trace in traces:\n                            await trace.send_request_redirect(\n                                method, url.update_query(params), headers, resp\n                            )\n\n                        redirects += 1\n                        history.append(resp)\n                        if max_redirects and redirects >= max_redirects:\n                            resp.close()\n                            raise TooManyRedirects(\n                                history[0].request_info, tuple(history)\n                            )\n\n                        # For 301 and 302, mimic IE, now changed in RFC\n                        # https://github.com/kennethreitz/requests/pull/269\n                        if (resp.status == 303 and resp.method != hdrs.METH_HEAD) or (\n                            resp.status in (301, 302) and resp.method == hdrs.METH_POST\n                        ):\n                            method = hdrs.METH_GET\n                            data = None\n                            if headers.get(hdrs.CONTENT_LENGTH):\n                                headers.pop(hdrs.CONTENT_LENGTH)\n\n                        r_url = resp.headers.get(hdrs.LOCATION) or resp.headers.get(\n                            hdrs.URI\n                        )\n                        if r_url is None:\n                            # see github.com/aio-libs/aiohttp/issues/2022\n                            break\n                        else:\n                            # reading from correct redirection\n                            # response is forbidden\n                            resp.release()\n\n                        try:\n                            parsed_redirect_url = URL(\n                                r_url, encoded=not self._requote_redirect_url\n                            )\n                        except ValueError as e:\n                            raise InvalidUrlRedirectClientError(\n                                r_url,\n                                \"Server attempted redirecting to a location that does not look like a URL\",\n                            ) from e\n\n                        scheme = parsed_redirect_url.scheme\n                        if scheme not in HTTP_AND_EMPTY_SCHEMA_SET:\n                            resp.close()\n                            raise NonHttpUrlRedirectClientError(r_url)\n                        elif not scheme:\n                            parsed_redirect_url = url.join(parsed_redirect_url)\n\n                        try:\n                            redirect_origin = parsed_redirect_url.origin()\n                        except ValueError as origin_val_err:\n                            raise InvalidUrlRedirectClientError(\n                                parsed_redirect_url,\n                                \"Invalid redirect URL origin\",\n                            ) from origin_val_err\n\n                        if url.origin() != redirect_origin:\n                            auth = None\n                            headers.pop(hdrs.AUTHORIZATION, None)\n\n                        url = parsed_redirect_url\n                        params = {}\n                        resp.release()\n                        continue\n\n                    break\n\n            # check response status\n            if raise_for_status is None:\n                raise_for_status = self._raise_for_status\n\n            if raise_for_status is None:\n                pass\n            elif callable(raise_for_status):\n                await raise_for_status(resp)\n            elif raise_for_status:\n                resp.raise_for_status()\n\n            # register connection\n            if handle is not None:\n                if resp.connection is not None:\n                    resp.connection.add_callback(handle.cancel)\n                else:\n                    handle.cancel()\n\n            resp._history = tuple(history)\n\n            for trace in traces:\n                await trace.send_request_end(\n                    method, url.update_query(params), headers, resp\n                )\n            return resp\n\n        except BaseException as e:\n            # cleanup timer\n            tm.close()\n            if handle:\n                handle.cancel()\n                handle = None\n\n            for trace in traces:\n                await trace.send_request_exception(\n                    method, url.update_query(params), headers, e\n                )\n            raise\n\n    def ws_connect(\n        self,\n        url: StrOrURL,\n        *,\n        method: str = hdrs.METH_GET,\n        protocols: Iterable[str] = (),\n        timeout: Union[ClientWSTimeout, _SENTINEL] = sentinel,\n        receive_timeout: Optional[float] = None,\n        autoclose: bool = True,\n        autoping: bool = True,\n        heartbeat: Optional[float] = None,\n        auth: Optional[BasicAuth] = None,\n        origin: Optional[str] = None,\n        params: Query = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        compress: int = 0,\n        max_msg_size: int = 4 * 1024 * 1024,\n    ) -> \"_WSRequestContextManager\":\n        \"\"\"Initiate websocket connection.\"\"\"\n        return _WSRequestContextManager(\n            self._ws_connect(\n                url,\n                method=method,\n                protocols=protocols,\n                timeout=timeout,\n                receive_timeout=receive_timeout,\n                autoclose=autoclose,\n                autoping=autoping,\n                heartbeat=heartbeat,\n                auth=auth,\n                origin=origin,\n                params=params,\n                headers=headers,\n                proxy=proxy,\n                proxy_auth=proxy_auth,\n                ssl=ssl,\n                verify_ssl=verify_ssl,\n                fingerprint=fingerprint,\n                ssl_context=ssl_context,\n                proxy_headers=proxy_headers,\n                compress=compress,\n                max_msg_size=max_msg_size,\n            )\n        )\n\n    async def _ws_connect(\n        self,\n        url: StrOrURL,\n        *,\n        method: str = hdrs.METH_GET,\n        protocols: Iterable[str] = (),\n        timeout: Union[ClientWSTimeout, _SENTINEL] = sentinel,\n        receive_timeout: Optional[float] = None,\n        autoclose: bool = True,\n        autoping: bool = True,\n        heartbeat: Optional[float] = None,\n        auth: Optional[BasicAuth] = None,\n        origin: Optional[str] = None,\n        params: Query = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        compress: int = 0,\n        max_msg_size: int = 4 * 1024 * 1024,\n    ) -> ClientWebSocketResponse:\n        if timeout is not sentinel:\n            if isinstance(timeout, ClientWSTimeout):\n                ws_timeout = timeout\n            else:\n                warnings.warn(\n                    \"parameter 'timeout' of type 'float' \"\n                    \"is deprecated, please use \"\n                    \"'timeout=ClientWSTimeout(ws_close=...)'\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n                ws_timeout = ClientWSTimeout(ws_close=timeout)\n        else:\n            ws_timeout = DEFAULT_WS_CLIENT_TIMEOUT\n        if receive_timeout is not None:\n            warnings.warn(\n                \"float parameter 'receive_timeout' \"\n                \"is deprecated, please use parameter \"\n                \"'timeout=ClientWSTimeout(ws_receive=...)'\",\n                DeprecationWarning,\n                stacklevel=2,\n            )\n            ws_timeout = attr.evolve(ws_timeout, ws_receive=receive_timeout)\n\n        if headers is None:\n            real_headers: CIMultiDict[str] = CIMultiDict()\n        else:\n            real_headers = CIMultiDict(headers)\n\n        default_headers = {\n            hdrs.UPGRADE: \"websocket\",\n            hdrs.CONNECTION: \"Upgrade\",\n            hdrs.SEC_WEBSOCKET_VERSION: \"13\",\n        }\n\n        for key, value in default_headers.items():\n            real_headers.setdefault(key, value)\n\n        sec_key = base64.b64encode(os.urandom(16))\n        real_headers[hdrs.SEC_WEBSOCKET_KEY] = sec_key.decode()\n\n        if protocols:\n            real_headers[hdrs.SEC_WEBSOCKET_PROTOCOL] = \",\".join(protocols)\n        if origin is not None:\n            real_headers[hdrs.ORIGIN] = origin\n        if compress:\n            extstr = ws_ext_gen(compress=compress)\n            real_headers[hdrs.SEC_WEBSOCKET_EXTENSIONS] = extstr\n\n        # For the sake of backward compatibility, if user passes in None, convert it to True\n        if ssl is None:\n            warnings.warn(\n                \"ssl=None is deprecated, please use ssl=True\",\n                DeprecationWarning,\n                stacklevel=2,\n            )\n            ssl = True\n        ssl = _merge_ssl_params(ssl, verify_ssl, ssl_context, fingerprint)\n\n        # send request\n        resp = await self.request(\n            method,\n            url,\n            params=params,\n            headers=real_headers,\n            read_until_eof=False,\n            auth=auth,\n            proxy=proxy,\n            proxy_auth=proxy_auth,\n            ssl=ssl,\n            proxy_headers=proxy_headers,\n        )\n\n        try:\n            # check handshake\n            if resp.status != 101:\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid response status\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            if resp.headers.get(hdrs.UPGRADE, \"\").lower() != \"websocket\":\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid upgrade header\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            if resp.headers.get(hdrs.CONNECTION, \"\").lower() != \"upgrade\":\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid connection header\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            # key calculation\n            r_key = resp.headers.get(hdrs.SEC_WEBSOCKET_ACCEPT, \"\")\n            match = base64.b64encode(hashlib.sha1(sec_key + WS_KEY).digest()).decode()\n            if r_key != match:\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid challenge response\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            # websocket protocol\n            protocol = None\n            if protocols and hdrs.SEC_WEBSOCKET_PROTOCOL in resp.headers:\n                resp_protocols = [\n                    proto.strip()\n                    for proto in resp.headers[hdrs.SEC_WEBSOCKET_PROTOCOL].split(\",\")\n                ]\n\n                for proto in resp_protocols:\n                    if proto in protocols:\n                        protocol = proto\n                        break\n\n            # websocket compress\n            notakeover = False\n            if compress:\n                compress_hdrs = resp.headers.get(hdrs.SEC_WEBSOCKET_EXTENSIONS)\n                if compress_hdrs:\n                    try:\n                        compress, notakeover = ws_ext_parse(compress_hdrs)\n                    except WSHandshakeError as exc:\n                        raise WSServerHandshakeError(\n                            resp.request_info,\n                            resp.history,\n                            message=exc.args[0],\n                            status=resp.status,\n                            headers=resp.headers,\n                        ) from exc\n                else:\n                    compress = 0\n                    notakeover = False\n\n            conn = resp.connection\n            assert conn is not None\n            conn_proto = conn.protocol\n            assert conn_proto is not None\n\n            # For WS connection the read_timeout must be either receive_timeout or greater\n            # None == no timeout, i.e. infinite timeout, so None is the max timeout possible\n            if ws_timeout.ws_receive is None:\n                # Reset regardless\n                conn_proto.read_timeout = None\n            elif conn_proto.read_timeout is not None:\n                conn_proto.read_timeout = max(\n                    ws_timeout.ws_receive, conn_proto.read_timeout\n                )\n\n            transport = conn.transport\n            assert transport is not None\n            reader: FlowControlDataQueue[WSMessage] = FlowControlDataQueue(\n                conn_proto, 2**16, loop=self._loop\n            )\n            conn_proto.set_parser(WebSocketReader(reader, max_msg_size), reader)\n            writer = WebSocketWriter(\n                conn_proto,\n                transport,\n                use_mask=True,\n                compress=compress,\n                notakeover=notakeover,\n            )\n        except BaseException:\n            resp.close()\n            raise\n        else:\n            return self._ws_response_class(\n                reader,\n                writer,\n                protocol,\n                resp,\n                ws_timeout,\n                autoclose,\n                autoping,\n                self._loop,\n                heartbeat=heartbeat,\n                compress=compress,\n                client_notakeover=notakeover,\n            )\n\n    def _prepare_headers(self, headers: Optional[LooseHeaders]) -> \"CIMultiDict[str]\":\n        \"\"\"Add default headers and transform it to CIMultiDict\"\"\"\n        # Convert headers to MultiDict\n        result = CIMultiDict(self._default_headers)\n        if headers:\n            if not isinstance(headers, (MultiDictProxy, MultiDict)):\n                headers = CIMultiDict(headers)\n            added_names: Set[str] = set()\n            for key, value in headers.items():\n                if key in added_names:\n                    result.add(key, value)\n                else:\n                    result[key] = value\n                    added_names.add(key)\n        return result\n\n    if sys.version_info >= (3, 11) and TYPE_CHECKING:\n\n        def get(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def options(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def head(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def post(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def put(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def patch(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def delete(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n    else:\n\n        def get(\n            self, url: StrOrURL, *, allow_redirects: bool = True, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP GET request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_GET, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def options(\n            self, url: StrOrURL, *, allow_redirects: bool = True, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP OPTIONS request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_OPTIONS, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def head(\n            self, url: StrOrURL, *, allow_redirects: bool = False, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP HEAD request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_HEAD, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def post(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP POST request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_POST, url, data=data, **kwargs)\n            )\n\n        def put(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP PUT request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_PUT, url, data=data, **kwargs)\n            )\n\n        def patch(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP PATCH request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_PATCH, url, data=data, **kwargs)\n            )\n\n        def delete(self, url: StrOrURL, **kwargs: Any) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP DELETE request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_DELETE, url, **kwargs)\n            )\n\n    async def close(self) -> None:\n        \"\"\"Close underlying connector.\n\n        Release all acquired resources.\n        \"\"\"\n        if not self.closed:\n            if self._connector is not None and self._connector_owner:\n                await self._connector.close()\n            self._connector = None\n\n    @property\n    def closed(self) -> bool:\n        \"\"\"Is client session closed.\n\n        A readonly property.\n        \"\"\"\n        return self._connector is None or self._connector.closed\n\n    @property\n    def connector(self) -> Optional[BaseConnector]:\n        \"\"\"Connector instance used for the session.\"\"\"\n        return self._connector\n\n    @property\n    def cookie_jar(self) -> AbstractCookieJar:\n        \"\"\"The session cookies.\"\"\"\n        return self._cookie_jar\n\n    @property\n    def version(self) -> Tuple[int, int]:\n        \"\"\"The session HTTP protocol version.\"\"\"\n        return self._version\n\n    @property\n    def requote_redirect_url(self) -> bool:\n        \"\"\"Do URL requoting on redirection handling.\"\"\"\n        return self._requote_redirect_url\n\n    @requote_redirect_url.setter\n    def requote_redirect_url(self, val: bool) -> None:\n        \"\"\"Do URL requoting on redirection handling.\"\"\"\n        warnings.warn(\n            \"session.requote_redirect_url modification is deprecated #2778\",\n            DeprecationWarning,\n            stacklevel=2,\n        )\n        self._requote_redirect_url = val\n\n    @property\n    def loop(self) -> asyncio.AbstractEventLoop:\n        \"\"\"Session's loop.\"\"\"\n        warnings.warn(\n            \"client.loop property is deprecated\", DeprecationWarning, stacklevel=2\n        )\n        return self._loop\n\n    @property\n    def timeout(self) -> ClientTimeout:\n        \"\"\"Timeout for the session.\"\"\"\n        return self._timeout\n\n    @property\n    def headers(self) -> \"CIMultiDict[str]\":\n        \"\"\"The default headers of the client session.\"\"\"\n        return self._default_headers\n\n    @property\n    def skip_auto_headers(self) -> FrozenSet[istr]:\n        \"\"\"Headers for which autogeneration should be skipped\"\"\"\n        return self._skip_auto_headers\n\n    @property\n    def auth(self) -> Optional[BasicAuth]:\n        \"\"\"An object that represents HTTP Basic Authorization\"\"\"\n        return self._default_auth\n\n    @property\n    def json_serialize(self) -> JSONEncoder:\n        \"\"\"Json serializer callable\"\"\"\n        return self._json_serialize\n\n    @property\n    def connector_owner(self) -> bool:\n        \"\"\"Should connector be closed on session closing\"\"\"\n        return self._connector_owner\n\n    @property\n    def raise_for_status(\n        self,\n    ) -> Union[bool, Callable[[ClientResponse], Awaitable[None]]]:\n        \"\"\"Should `ClientResponse.raise_for_status()` be called for each response.\"\"\"\n        return self._raise_for_status\n\n    @property\n    def auto_decompress(self) -> bool:\n        \"\"\"Should the body response be automatically decompressed.\"\"\"\n        return self._auto_decompress\n\n    @property\n    def trust_env(self) -> bool:\n        \"\"\"\n        Should proxies information from environment or netrc be trusted.\n\n        Information is from HTTP_PROXY / HTTPS_PROXY environment variables\n        or ~/.netrc file if present.\n        \"\"\"\n        return self._trust_env\n\n    @property\n    def trace_configs(self) -> List[TraceConfig]:\n        \"\"\"A list of TraceConfig instances used for client tracing\"\"\"\n        return self._trace_configs\n\n    def detach(self) -> None:\n        \"\"\"Detach connector from session without closing the former.\n\n        Session is switched to closed state anyway.\n        \"\"\"\n        self._connector = None\n\n    def __enter__(self) -> None:\n        raise TypeError(\"Use async with instead\")\n\n    def __exit__(\n        self,\n        exc_type: Optional[Type[BaseException]],\n        exc_val: Optional[BaseException],\n        exc_tb: Optional[TracebackType],\n    ) -> None:\n        # __exit__ should exist in pair with __enter__ but never executed\n        pass  # pragma: no cover\n\n    async def __aenter__(self) -> \"ClientSession\":\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        await self.close()",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 263,
                            "end_lineno": 404,
                            "parent": {
                                "file_name": "aiohttp/client.py",
                                "type": "class",
                                "name": "ClientSession",
                                "content": "class ClientSession:\n    \"\"\"First-class interface for making HTTP requests.\"\"\"\n\n    ATTRS = frozenset(\n        [\n            \"_base_url\",\n            \"_source_traceback\",\n            \"_connector\",\n            \"requote_redirect_url\",\n            \"_loop\",\n            \"_cookie_jar\",\n            \"_connector_owner\",\n            \"_default_auth\",\n            \"_version\",\n            \"_json_serialize\",\n            \"_requote_redirect_url\",\n            \"_timeout\",\n            \"_raise_for_status\",\n            \"_auto_decompress\",\n            \"_trust_env\",\n            \"_default_headers\",\n            \"_skip_auto_headers\",\n            \"_request_class\",\n            \"_response_class\",\n            \"_ws_response_class\",\n            \"_trace_configs\",\n            \"_read_bufsize\",\n            \"_max_line_size\",\n            \"_max_field_size\",\n            \"_resolve_charset\",\n            \"_default_proxy\",\n            \"_default_proxy_auth\",\n        ]\n    )\n\n    _source_traceback: Optional[traceback.StackSummary] = None\n    _connector: Optional[BaseConnector] = None\n\n    def __init__(\n        self,\n        base_url: Optional[StrOrURL] = None,\n        *,\n        connector: Optional[BaseConnector] = None,\n        loop: Optional[asyncio.AbstractEventLoop] = None,\n        cookies: Optional[LooseCookies] = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        skip_auto_headers: Optional[Iterable[str]] = None,\n        auth: Optional[BasicAuth] = None,\n        json_serialize: JSONEncoder = json.dumps,\n        request_class: Type[ClientRequest] = ClientRequest,\n        response_class: Type[ClientResponse] = ClientResponse,\n        ws_response_class: Type[ClientWebSocketResponse] = ClientWebSocketResponse,\n        version: HttpVersion = http.HttpVersion11,\n        cookie_jar: Optional[AbstractCookieJar] = None,\n        connector_owner: bool = True,\n        raise_for_status: Union[\n            bool, Callable[[ClientResponse], Awaitable[None]]\n        ] = False,\n        read_timeout: Union[float, _SENTINEL] = sentinel,\n        conn_timeout: Optional[float] = None,\n        timeout: Union[object, ClientTimeout] = sentinel,\n        auto_decompress: bool = True,\n        trust_env: bool = False,\n        requote_redirect_url: bool = True,\n        trace_configs: Optional[List[TraceConfig]] = None,\n        read_bufsize: int = 2**16,\n        max_line_size: int = 8190,\n        max_field_size: int = 8190,\n        fallback_charset_resolver: _CharsetResolver = lambda r, b: \"utf-8\",\n    ) -> None:\n        # We initialise _connector to None immediately, as it's referenced in __del__()\n        # and could cause issues if an exception occurs during initialisation.\n        self._connector: Optional[BaseConnector] = None\n\n        if loop is None:\n            if connector is not None:\n                loop = connector._loop\n\n        loop = loop or asyncio.get_running_loop()\n\n        if base_url is None or isinstance(base_url, URL):\n            self._base_url: Optional[URL] = base_url\n        else:\n            self._base_url = URL(base_url)\n            assert (\n                self._base_url.origin() == self._base_url\n            ), \"Only absolute URLs without path part are supported\"\n\n        if timeout is sentinel or timeout is None:\n            self._timeout = DEFAULT_TIMEOUT\n            if read_timeout is not sentinel:\n                warnings.warn(\n                    \"read_timeout is deprecated, use timeout argument instead\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n                self._timeout = attr.evolve(self._timeout, total=read_timeout)\n            if conn_timeout is not None:\n                self._timeout = attr.evolve(self._timeout, connect=conn_timeout)\n                warnings.warn(\n                    \"conn_timeout is deprecated, use timeout argument instead\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n        else:\n            if not isinstance(timeout, ClientTimeout):\n                raise ValueError(\n                    f\"timeout parameter cannot be of {type(timeout)} type, \"\n                    \"please use 'timeout=ClientTimeout(...)'\",\n                )\n            self._timeout = timeout\n            if read_timeout is not sentinel:\n                raise ValueError(\n                    \"read_timeout and timeout parameters \"\n                    \"conflict, please setup \"\n                    \"timeout.read\"\n                )\n            if conn_timeout is not None:\n                raise ValueError(\n                    \"conn_timeout and timeout parameters \"\n                    \"conflict, please setup \"\n                    \"timeout.connect\"\n                )\n\n        if connector is None:\n            connector = TCPConnector(loop=loop)\n\n        if connector._loop is not loop:\n            raise RuntimeError(\"Session and connector has to use same event loop\")\n\n        self._loop = loop\n\n        if loop.get_debug():\n            self._source_traceback = traceback.extract_stack(sys._getframe(1))\n\n        if cookie_jar is None:\n            cookie_jar = CookieJar(loop=loop)\n        self._cookie_jar = cookie_jar\n\n        if cookies is not None:\n            self._cookie_jar.update_cookies(cookies)\n\n        self._connector = connector\n        self._connector_owner = connector_owner\n        self._default_auth = auth\n        self._version = version\n        self._json_serialize = json_serialize\n        self._raise_for_status = raise_for_status\n        self._auto_decompress = auto_decompress\n        self._trust_env = trust_env\n        self._requote_redirect_url = requote_redirect_url\n        self._read_bufsize = read_bufsize\n        self._max_line_size = max_line_size\n        self._max_field_size = max_field_size\n\n        # Convert to list of tuples\n        if headers:\n            real_headers: CIMultiDict[str] = CIMultiDict(headers)\n        else:\n            real_headers = CIMultiDict()\n        self._default_headers: CIMultiDict[str] = real_headers\n        if skip_auto_headers is not None:\n            self._skip_auto_headers = frozenset(istr(i) for i in skip_auto_headers)\n        else:\n            self._skip_auto_headers = frozenset()\n\n        self._request_class = request_class\n        self._response_class = response_class\n        self._ws_response_class = ws_response_class\n\n        self._trace_configs = trace_configs or []\n        for trace_config in self._trace_configs:\n            trace_config.freeze()\n\n        self._resolve_charset = fallback_charset_resolver\n\n        self._default_proxy = proxy\n        self._default_proxy_auth = proxy_auth\n\n    def __init_subclass__(cls: Type[\"ClientSession\"]) -> None:\n        warnings.warn(\n            \"Inheritance class {} from ClientSession \"\n            \"is discouraged\".format(cls.__name__),\n            DeprecationWarning,\n            stacklevel=2,\n        )\n\n    if DEBUG:\n\n        def __setattr__(self, name: str, val: Any) -> None:\n            if name not in self.ATTRS:\n                warnings.warn(\n                    \"Setting custom ClientSession.{} attribute \"\n                    \"is discouraged\".format(name),\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n            super().__setattr__(name, val)\n\n    def __del__(self, _warnings: Any = warnings) -> None:\n        if not self.closed:\n            kwargs = {\"source\": self}\n            _warnings.warn(\n                f\"Unclosed client session {self!r}\", ResourceWarning, **kwargs\n            )\n            context = {\"client_session\": self, \"message\": \"Unclosed client session\"}\n            if self._source_traceback is not None:\n                context[\"source_traceback\"] = self._source_traceback\n            self._loop.call_exception_handler(context)\n\n    if sys.version_info >= (3, 11) and TYPE_CHECKING:\n\n        def request(\n            self,\n            method: str,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n    else:\n\n        def request(\n            self, method: str, url: StrOrURL, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP request.\"\"\"\n            return _RequestContextManager(self._request(method, url, **kwargs))\n\n    def _build_url(self, str_or_url: StrOrURL) -> URL:\n        url = URL(str_or_url)\n        if self._base_url is None:\n            return url\n        else:\n            assert not url.absolute and url.path.startswith(\"/\")\n            return self._base_url.join(url)\n\n    async def _request(\n        self,\n        method: str,\n        str_or_url: StrOrURL,\n        *,\n        params: Query = None,\n        data: Any = None,\n        json: Any = None,\n        cookies: Optional[LooseCookies] = None,\n        headers: Optional[LooseHeaders] = None,\n        skip_auto_headers: Optional[Iterable[str]] = None,\n        auth: Optional[BasicAuth] = None,\n        allow_redirects: bool = True,\n        max_redirects: int = 10,\n        compress: Union[str, bool, None] = None,\n        chunked: Optional[bool] = None,\n        expect100: bool = False,\n        raise_for_status: Union[\n            None, bool, Callable[[ClientResponse], Awaitable[None]]\n        ] = None,\n        read_until_eof: bool = True,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        timeout: Union[ClientTimeout, _SENTINEL] = sentinel,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        server_hostname: Optional[str] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        trace_request_ctx: Optional[Mapping[str, str]] = None,\n        read_bufsize: Optional[int] = None,\n        auto_decompress: Optional[bool] = None,\n        max_line_size: Optional[int] = None,\n        max_field_size: Optional[int] = None,\n    ) -> ClientResponse:\n\n        # NOTE: timeout clamps existing connect and read timeouts.  We cannot\n        # set the default to None because we need to detect if the user wants\n        # to use the existing timeouts by setting timeout to None.\n\n        if self.closed:\n            raise RuntimeError(\"Session is closed\")\n\n        ssl = _merge_ssl_params(ssl, verify_ssl, ssl_context, fingerprint)\n\n        if data is not None and json is not None:\n            raise ValueError(\n                \"data and json parameters can not be used at the same time\"\n            )\n        elif json is not None:\n            data = payload.JsonPayload(json, dumps=self._json_serialize)\n\n        if not isinstance(chunked, bool) and chunked is not None:\n            warnings.warn(\"Chunk size is deprecated #1615\", DeprecationWarning)\n\n        redirects = 0\n        history = []\n        version = self._version\n        params = params or {}\n\n        # Merge with default headers and transform to CIMultiDict\n        headers = self._prepare_headers(headers)\n\n        try:\n            url = self._build_url(str_or_url)\n        except ValueError as e:\n            raise InvalidUrlClientError(str_or_url) from e\n\n        assert self._connector is not None\n        if url.scheme not in self._connector.allowed_protocol_schema_set:\n            raise NonHttpUrlClientError(url)\n\n        skip_headers = set(self._skip_auto_headers)\n        if skip_auto_headers is not None:\n            for i in skip_auto_headers:\n                skip_headers.add(istr(i))\n\n        if proxy is None:\n            proxy = self._default_proxy\n        if proxy_auth is None:\n            proxy_auth = self._default_proxy_auth\n\n        if proxy is None:\n            proxy_headers = None\n        else:\n            proxy_headers = self._prepare_headers(proxy_headers)\n            try:\n                proxy = URL(proxy)\n            except ValueError as e:\n                raise InvalidURL(proxy) from e\n\n        if timeout is sentinel:\n            real_timeout: ClientTimeout = self._timeout\n        else:\n            if not isinstance(timeout, ClientTimeout):\n                real_timeout = ClientTimeout(total=timeout)\n            else:\n                real_timeout = timeout\n        # timeout is cumulative for all request operations\n        # (request, redirects, responses, data consuming)\n        tm = TimeoutHandle(\n            self._loop, real_timeout.total, ceil_threshold=real_timeout.ceil_threshold\n        )\n        handle = tm.start()\n\n        if read_bufsize is None:\n            read_bufsize = self._read_bufsize\n\n        if auto_decompress is None:\n            auto_decompress = self._auto_decompress\n\n        if max_line_size is None:\n            max_line_size = self._max_line_size\n\n        if max_field_size is None:\n            max_field_size = self._max_field_size\n\n        traces = [\n            Trace(\n                self,\n                trace_config,\n                trace_config.trace_config_ctx(trace_request_ctx=trace_request_ctx),\n            )\n            for trace_config in self._trace_configs\n        ]\n\n        for trace in traces:\n            await trace.send_request_start(method, url.update_query(params), headers)\n\n        timer = tm.timer()\n        try:\n            with timer:\n                # https://www.rfc-editor.org/rfc/rfc9112.html#name-retrying-requests\n                retry_persistent_connection = method in IDEMPOTENT_METHODS\n                while True:\n                    url, auth_from_url = strip_auth_from_url(url)\n                    if not url.raw_host:\n                        # NOTE: Bail early, otherwise, causes `InvalidURL` through\n                        # NOTE: `self._request_class()` below.\n                        err_exc_cls = (\n                            InvalidUrlRedirectClientError\n                            if redirects\n                            else InvalidUrlClientError\n                        )\n                        raise err_exc_cls(url)\n                    if auth and auth_from_url:\n                        raise ValueError(\n                            \"Cannot combine AUTH argument with \"\n                            \"credentials encoded in URL\"\n                        )\n\n                    if auth is None:\n                        auth = auth_from_url\n\n                    if auth is None and (\n                        not self._base_url or self._base_url.origin() == url.origin()\n                    ):\n                        auth = self._default_auth\n                    # It would be confusing if we support explicit\n                    # Authorization header with auth argument\n                    if (\n                        headers is not None\n                        and auth is not None\n                        and hdrs.AUTHORIZATION in headers\n                    ):\n                        raise ValueError(\n                            \"Cannot combine AUTHORIZATION header \"\n                            \"with AUTH argument or credentials \"\n                            \"encoded in URL\"\n                        )\n\n                    all_cookies = self._cookie_jar.filter_cookies(url)\n\n                    if cookies is not None:\n                        tmp_cookie_jar = CookieJar()\n                        tmp_cookie_jar.update_cookies(cookies)\n                        req_cookies = tmp_cookie_jar.filter_cookies(url)\n                        if req_cookies:\n                            all_cookies.load(req_cookies)\n\n                    if proxy is not None:\n                        proxy = URL(proxy)\n                    elif self._trust_env:\n                        with suppress(LookupError):\n                            proxy, proxy_auth = get_env_proxy_for_url(url)\n\n                    req = self._request_class(\n                        method,\n                        url,\n                        params=params,\n                        headers=headers,\n                        skip_auto_headers=skip_headers if skip_headers else None,\n                        data=data,\n                        cookies=all_cookies,\n                        auth=auth,\n                        version=version,\n                        compress=compress,\n                        chunked=chunked,\n                        expect100=expect100,\n                        loop=self._loop,\n                        response_class=self._response_class,\n                        proxy=proxy,\n                        proxy_auth=proxy_auth,\n                        timer=timer,\n                        session=self,\n                        ssl=ssl if ssl is not None else True,\n                        server_hostname=server_hostname,\n                        proxy_headers=proxy_headers,\n                        traces=traces,\n                        trust_env=self.trust_env,\n                    )\n\n                    # connection timeout\n                    try:\n                        async with ceil_timeout(\n                            real_timeout.connect,\n                            ceil_threshold=real_timeout.ceil_threshold,\n                        ):\n                            conn = await self._connector.connect(\n                                req, traces=traces, timeout=real_timeout\n                            )\n                    except asyncio.TimeoutError as exc:\n                        raise ConnectionTimeoutError(\n                            f\"Connection timeout to host {url}\"\n                        ) from exc\n\n                    assert conn.transport is not None\n\n                    assert conn.protocol is not None\n                    conn.protocol.set_response_params(\n                        timer=timer,\n                        skip_payload=method_must_be_empty_body(method),\n                        read_until_eof=read_until_eof,\n                        auto_decompress=auto_decompress,\n                        read_timeout=real_timeout.sock_read,\n                        read_bufsize=read_bufsize,\n                        timeout_ceil_threshold=self._connector._timeout_ceil_threshold,\n                        max_line_size=max_line_size,\n                        max_field_size=max_field_size,\n                    )\n\n                    try:\n                        try:\n                            resp = await req.send(conn)\n                            try:\n                                await resp.start(conn)\n                            except BaseException:\n                                resp.close()\n                                raise\n                        except BaseException:\n                            conn.close()\n                            raise\n                    except (ClientOSError, ServerDisconnectedError):\n                        if retry_persistent_connection:\n                            retry_persistent_connection = False\n                            continue\n                        raise\n                    except ClientError:\n                        raise\n                    except OSError as exc:\n                        if exc.errno is None and isinstance(exc, asyncio.TimeoutError):\n                            raise\n                        raise ClientOSError(*exc.args) from exc\n\n                    self._cookie_jar.update_cookies(resp.cookies, resp.url)\n\n                    # redirects\n                    if resp.status in (301, 302, 303, 307, 308) and allow_redirects:\n\n                        for trace in traces:\n                            await trace.send_request_redirect(\n                                method, url.update_query(params), headers, resp\n                            )\n\n                        redirects += 1\n                        history.append(resp)\n                        if max_redirects and redirects >= max_redirects:\n                            resp.close()\n                            raise TooManyRedirects(\n                                history[0].request_info, tuple(history)\n                            )\n\n                        # For 301 and 302, mimic IE, now changed in RFC\n                        # https://github.com/kennethreitz/requests/pull/269\n                        if (resp.status == 303 and resp.method != hdrs.METH_HEAD) or (\n                            resp.status in (301, 302) and resp.method == hdrs.METH_POST\n                        ):\n                            method = hdrs.METH_GET\n                            data = None\n                            if headers.get(hdrs.CONTENT_LENGTH):\n                                headers.pop(hdrs.CONTENT_LENGTH)\n\n                        r_url = resp.headers.get(hdrs.LOCATION) or resp.headers.get(\n                            hdrs.URI\n                        )\n                        if r_url is None:\n                            # see github.com/aio-libs/aiohttp/issues/2022\n                            break\n                        else:\n                            # reading from correct redirection\n                            # response is forbidden\n                            resp.release()\n\n                        try:\n                            parsed_redirect_url = URL(\n                                r_url, encoded=not self._requote_redirect_url\n                            )\n                        except ValueError as e:\n                            raise InvalidUrlRedirectClientError(\n                                r_url,\n                                \"Server attempted redirecting to a location that does not look like a URL\",\n                            ) from e\n\n                        scheme = parsed_redirect_url.scheme\n                        if scheme not in HTTP_AND_EMPTY_SCHEMA_SET:\n                            resp.close()\n                            raise NonHttpUrlRedirectClientError(r_url)\n                        elif not scheme:\n                            parsed_redirect_url = url.join(parsed_redirect_url)\n\n                        try:\n                            redirect_origin = parsed_redirect_url.origin()\n                        except ValueError as origin_val_err:\n                            raise InvalidUrlRedirectClientError(\n                                parsed_redirect_url,\n                                \"Invalid redirect URL origin\",\n                            ) from origin_val_err\n\n                        if url.origin() != redirect_origin:\n                            auth = None\n                            headers.pop(hdrs.AUTHORIZATION, None)\n\n                        url = parsed_redirect_url\n                        params = {}\n                        resp.release()\n                        continue\n\n                    break\n\n            # check response status\n            if raise_for_status is None:\n                raise_for_status = self._raise_for_status\n\n            if raise_for_status is None:\n                pass\n            elif callable(raise_for_status):\n                await raise_for_status(resp)\n            elif raise_for_status:\n                resp.raise_for_status()\n\n            # register connection\n            if handle is not None:\n                if resp.connection is not None:\n                    resp.connection.add_callback(handle.cancel)\n                else:\n                    handle.cancel()\n\n            resp._history = tuple(history)\n\n            for trace in traces:\n                await trace.send_request_end(\n                    method, url.update_query(params), headers, resp\n                )\n            return resp\n\n        except BaseException as e:\n            # cleanup timer\n            tm.close()\n            if handle:\n                handle.cancel()\n                handle = None\n\n            for trace in traces:\n                await trace.send_request_exception(\n                    method, url.update_query(params), headers, e\n                )\n            raise\n\n    def ws_connect(\n        self,\n        url: StrOrURL,\n        *,\n        method: str = hdrs.METH_GET,\n        protocols: Iterable[str] = (),\n        timeout: Union[ClientWSTimeout, _SENTINEL] = sentinel,\n        receive_timeout: Optional[float] = None,\n        autoclose: bool = True,\n        autoping: bool = True,\n        heartbeat: Optional[float] = None,\n        auth: Optional[BasicAuth] = None,\n        origin: Optional[str] = None,\n        params: Query = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        compress: int = 0,\n        max_msg_size: int = 4 * 1024 * 1024,\n    ) -> \"_WSRequestContextManager\":\n        \"\"\"Initiate websocket connection.\"\"\"\n        return _WSRequestContextManager(\n            self._ws_connect(\n                url,\n                method=method,\n                protocols=protocols,\n                timeout=timeout,\n                receive_timeout=receive_timeout,\n                autoclose=autoclose,\n                autoping=autoping,\n                heartbeat=heartbeat,\n                auth=auth,\n                origin=origin,\n                params=params,\n                headers=headers,\n                proxy=proxy,\n                proxy_auth=proxy_auth,\n                ssl=ssl,\n                verify_ssl=verify_ssl,\n                fingerprint=fingerprint,\n                ssl_context=ssl_context,\n                proxy_headers=proxy_headers,\n                compress=compress,\n                max_msg_size=max_msg_size,\n            )\n        )\n\n    async def _ws_connect(\n        self,\n        url: StrOrURL,\n        *,\n        method: str = hdrs.METH_GET,\n        protocols: Iterable[str] = (),\n        timeout: Union[ClientWSTimeout, _SENTINEL] = sentinel,\n        receive_timeout: Optional[float] = None,\n        autoclose: bool = True,\n        autoping: bool = True,\n        heartbeat: Optional[float] = None,\n        auth: Optional[BasicAuth] = None,\n        origin: Optional[str] = None,\n        params: Query = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        compress: int = 0,\n        max_msg_size: int = 4 * 1024 * 1024,\n    ) -> ClientWebSocketResponse:\n        if timeout is not sentinel:\n            if isinstance(timeout, ClientWSTimeout):\n                ws_timeout = timeout\n            else:\n                warnings.warn(\n                    \"parameter 'timeout' of type 'float' \"\n                    \"is deprecated, please use \"\n                    \"'timeout=ClientWSTimeout(ws_close=...)'\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n                ws_timeout = ClientWSTimeout(ws_close=timeout)\n        else:\n            ws_timeout = DEFAULT_WS_CLIENT_TIMEOUT\n        if receive_timeout is not None:\n            warnings.warn(\n                \"float parameter 'receive_timeout' \"\n                \"is deprecated, please use parameter \"\n                \"'timeout=ClientWSTimeout(ws_receive=...)'\",\n                DeprecationWarning,\n                stacklevel=2,\n            )\n            ws_timeout = attr.evolve(ws_timeout, ws_receive=receive_timeout)\n\n        if headers is None:\n            real_headers: CIMultiDict[str] = CIMultiDict()\n        else:\n            real_headers = CIMultiDict(headers)\n\n        default_headers = {\n            hdrs.UPGRADE: \"websocket\",\n            hdrs.CONNECTION: \"Upgrade\",\n            hdrs.SEC_WEBSOCKET_VERSION: \"13\",\n        }\n\n        for key, value in default_headers.items():\n            real_headers.setdefault(key, value)\n\n        sec_key = base64.b64encode(os.urandom(16))\n        real_headers[hdrs.SEC_WEBSOCKET_KEY] = sec_key.decode()\n\n        if protocols:\n            real_headers[hdrs.SEC_WEBSOCKET_PROTOCOL] = \",\".join(protocols)\n        if origin is not None:\n            real_headers[hdrs.ORIGIN] = origin\n        if compress:\n            extstr = ws_ext_gen(compress=compress)\n            real_headers[hdrs.SEC_WEBSOCKET_EXTENSIONS] = extstr\n\n        # For the sake of backward compatibility, if user passes in None, convert it to True\n        if ssl is None:\n            warnings.warn(\n                \"ssl=None is deprecated, please use ssl=True\",\n                DeprecationWarning,\n                stacklevel=2,\n            )\n            ssl = True\n        ssl = _merge_ssl_params(ssl, verify_ssl, ssl_context, fingerprint)\n\n        # send request\n        resp = await self.request(\n            method,\n            url,\n            params=params,\n            headers=real_headers,\n            read_until_eof=False,\n            auth=auth,\n            proxy=proxy,\n            proxy_auth=proxy_auth,\n            ssl=ssl,\n            proxy_headers=proxy_headers,\n        )\n\n        try:\n            # check handshake\n            if resp.status != 101:\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid response status\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            if resp.headers.get(hdrs.UPGRADE, \"\").lower() != \"websocket\":\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid upgrade header\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            if resp.headers.get(hdrs.CONNECTION, \"\").lower() != \"upgrade\":\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid connection header\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            # key calculation\n            r_key = resp.headers.get(hdrs.SEC_WEBSOCKET_ACCEPT, \"\")\n            match = base64.b64encode(hashlib.sha1(sec_key + WS_KEY).digest()).decode()\n            if r_key != match:\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid challenge response\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            # websocket protocol\n            protocol = None\n            if protocols and hdrs.SEC_WEBSOCKET_PROTOCOL in resp.headers:\n                resp_protocols = [\n                    proto.strip()\n                    for proto in resp.headers[hdrs.SEC_WEBSOCKET_PROTOCOL].split(\",\")\n                ]\n\n                for proto in resp_protocols:\n                    if proto in protocols:\n                        protocol = proto\n                        break\n\n            # websocket compress\n            notakeover = False\n            if compress:\n                compress_hdrs = resp.headers.get(hdrs.SEC_WEBSOCKET_EXTENSIONS)\n                if compress_hdrs:\n                    try:\n                        compress, notakeover = ws_ext_parse(compress_hdrs)\n                    except WSHandshakeError as exc:\n                        raise WSServerHandshakeError(\n                            resp.request_info,\n                            resp.history,\n                            message=exc.args[0],\n                            status=resp.status,\n                            headers=resp.headers,\n                        ) from exc\n                else:\n                    compress = 0\n                    notakeover = False\n\n            conn = resp.connection\n            assert conn is not None\n            conn_proto = conn.protocol\n            assert conn_proto is not None\n\n            # For WS connection the read_timeout must be either receive_timeout or greater\n            # None == no timeout, i.e. infinite timeout, so None is the max timeout possible\n            if ws_timeout.ws_receive is None:\n                # Reset regardless\n                conn_proto.read_timeout = None\n            elif conn_proto.read_timeout is not None:\n                conn_proto.read_timeout = max(\n                    ws_timeout.ws_receive, conn_proto.read_timeout\n                )\n\n            transport = conn.transport\n            assert transport is not None\n            reader: FlowControlDataQueue[WSMessage] = FlowControlDataQueue(\n                conn_proto, 2**16, loop=self._loop\n            )\n            conn_proto.set_parser(WebSocketReader(reader, max_msg_size), reader)\n            writer = WebSocketWriter(\n                conn_proto,\n                transport,\n                use_mask=True,\n                compress=compress,\n                notakeover=notakeover,\n            )\n        except BaseException:\n            resp.close()\n            raise\n        else:\n            return self._ws_response_class(\n                reader,\n                writer,\n                protocol,\n                resp,\n                ws_timeout,\n                autoclose,\n                autoping,\n                self._loop,\n                heartbeat=heartbeat,\n                compress=compress,\n                client_notakeover=notakeover,\n            )\n\n    def _prepare_headers(self, headers: Optional[LooseHeaders]) -> \"CIMultiDict[str]\":\n        \"\"\"Add default headers and transform it to CIMultiDict\"\"\"\n        # Convert headers to MultiDict\n        result = CIMultiDict(self._default_headers)\n        if headers:\n            if not isinstance(headers, (MultiDictProxy, MultiDict)):\n                headers = CIMultiDict(headers)\n            added_names: Set[str] = set()\n            for key, value in headers.items():\n                if key in added_names:\n                    result.add(key, value)\n                else:\n                    result[key] = value\n                    added_names.add(key)\n        return result\n\n    if sys.version_info >= (3, 11) and TYPE_CHECKING:\n\n        def get(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def options(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def head(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def post(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def put(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def patch(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def delete(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n    else:\n\n        def get(\n            self, url: StrOrURL, *, allow_redirects: bool = True, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP GET request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_GET, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def options(\n            self, url: StrOrURL, *, allow_redirects: bool = True, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP OPTIONS request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_OPTIONS, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def head(\n            self, url: StrOrURL, *, allow_redirects: bool = False, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP HEAD request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_HEAD, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def post(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP POST request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_POST, url, data=data, **kwargs)\n            )\n\n        def put(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP PUT request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_PUT, url, data=data, **kwargs)\n            )\n\n        def patch(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP PATCH request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_PATCH, url, data=data, **kwargs)\n            )\n\n        def delete(self, url: StrOrURL, **kwargs: Any) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP DELETE request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_DELETE, url, **kwargs)\n            )\n\n    async def close(self) -> None:\n        \"\"\"Close underlying connector.\n\n        Release all acquired resources.\n        \"\"\"\n        if not self.closed:\n            if self._connector is not None and self._connector_owner:\n                await self._connector.close()\n            self._connector = None\n\n    @property\n    def closed(self) -> bool:\n        \"\"\"Is client session closed.\n\n        A readonly property.\n        \"\"\"\n        return self._connector is None or self._connector.closed\n\n    @property\n    def connector(self) -> Optional[BaseConnector]:\n        \"\"\"Connector instance used for the session.\"\"\"\n        return self._connector\n\n    @property\n    def cookie_jar(self) -> AbstractCookieJar:\n        \"\"\"The session cookies.\"\"\"\n        return self._cookie_jar\n\n    @property\n    def version(self) -> Tuple[int, int]:\n        \"\"\"The session HTTP protocol version.\"\"\"\n        return self._version\n\n    @property\n    def requote_redirect_url(self) -> bool:\n        \"\"\"Do URL requoting on redirection handling.\"\"\"\n        return self._requote_redirect_url\n\n    @requote_redirect_url.setter\n    def requote_redirect_url(self, val: bool) -> None:\n        \"\"\"Do URL requoting on redirection handling.\"\"\"\n        warnings.warn(\n            \"session.requote_redirect_url modification is deprecated #2778\",\n            DeprecationWarning,\n            stacklevel=2,\n        )\n        self._requote_redirect_url = val\n\n    @property\n    def loop(self) -> asyncio.AbstractEventLoop:\n        \"\"\"Session's loop.\"\"\"\n        warnings.warn(\n            \"client.loop property is deprecated\", DeprecationWarning, stacklevel=2\n        )\n        return self._loop\n\n    @property\n    def timeout(self) -> ClientTimeout:\n        \"\"\"Timeout for the session.\"\"\"\n        return self._timeout\n\n    @property\n    def headers(self) -> \"CIMultiDict[str]\":\n        \"\"\"The default headers of the client session.\"\"\"\n        return self._default_headers\n\n    @property\n    def skip_auto_headers(self) -> FrozenSet[istr]:\n        \"\"\"Headers for which autogeneration should be skipped\"\"\"\n        return self._skip_auto_headers\n\n    @property\n    def auth(self) -> Optional[BasicAuth]:\n        \"\"\"An object that represents HTTP Basic Authorization\"\"\"\n        return self._default_auth\n\n    @property\n    def json_serialize(self) -> JSONEncoder:\n        \"\"\"Json serializer callable\"\"\"\n        return self._json_serialize\n\n    @property\n    def connector_owner(self) -> bool:\n        \"\"\"Should connector be closed on session closing\"\"\"\n        return self._connector_owner\n\n    @property\n    def raise_for_status(\n        self,\n    ) -> Union[bool, Callable[[ClientResponse], Awaitable[None]]]:\n        \"\"\"Should `ClientResponse.raise_for_status()` be called for each response.\"\"\"\n        return self._raise_for_status\n\n    @property\n    def auto_decompress(self) -> bool:\n        \"\"\"Should the body response be automatically decompressed.\"\"\"\n        return self._auto_decompress\n\n    @property\n    def trust_env(self) -> bool:\n        \"\"\"\n        Should proxies information from environment or netrc be trusted.\n\n        Information is from HTTP_PROXY / HTTPS_PROXY environment variables\n        or ~/.netrc file if present.\n        \"\"\"\n        return self._trust_env\n\n    @property\n    def trace_configs(self) -> List[TraceConfig]:\n        \"\"\"A list of TraceConfig instances used for client tracing\"\"\"\n        return self._trace_configs\n\n    def detach(self) -> None:\n        \"\"\"Detach connector from session without closing the former.\n\n        Session is switched to closed state anyway.\n        \"\"\"\n        self._connector = None\n\n    def __enter__(self) -> None:\n        raise TypeError(\"Use async with instead\")\n\n    def __exit__(\n        self,\n        exc_type: Optional[Type[BaseException]],\n        exc_val: Optional[BaseException],\n        exc_tb: Optional[TracebackType],\n    ) -> None:\n        # __exit__ should exist in pair with __enter__ but never executed\n        pass  # pragma: no cover\n\n    async def __aenter__(self) -> \"ClientSession\":\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        await self.close()",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 225,
                                "end_lineno": 1373,
                                "parent": null
                            }
                        },
                        {
                            "file_name": "aiohttp/client.py",
                            "type": "class",
                            "name": "ClientSession",
                            "content": "class ClientSession:\n    \"\"\"First-class interface for making HTTP requests.\"\"\"\n\n    ATTRS = frozenset(\n        [\n            \"_base_url\",\n            \"_source_traceback\",\n            \"_connector\",\n            \"requote_redirect_url\",\n            \"_loop\",\n            \"_cookie_jar\",\n            \"_connector_owner\",\n            \"_default_auth\",\n            \"_version\",\n            \"_json_serialize\",\n            \"_requote_redirect_url\",\n            \"_timeout\",\n            \"_raise_for_status\",\n            \"_auto_decompress\",\n            \"_trust_env\",\n            \"_default_headers\",\n            \"_skip_auto_headers\",\n            \"_request_class\",\n            \"_response_class\",\n            \"_ws_response_class\",\n            \"_trace_configs\",\n            \"_read_bufsize\",\n            \"_max_line_size\",\n            \"_max_field_size\",\n            \"_resolve_charset\",\n            \"_default_proxy\",\n            \"_default_proxy_auth\",\n        ]\n    )\n\n    _source_traceback: Optional[traceback.StackSummary] = None\n    _connector: Optional[BaseConnector] = None\n\n    def __init__(\n        self,\n        base_url: Optional[StrOrURL] = None,\n        *,\n        connector: Optional[BaseConnector] = None,\n        loop: Optional[asyncio.AbstractEventLoop] = None,\n        cookies: Optional[LooseCookies] = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        skip_auto_headers: Optional[Iterable[str]] = None,\n        auth: Optional[BasicAuth] = None,\n        json_serialize: JSONEncoder = json.dumps,\n        request_class: Type[ClientRequest] = ClientRequest,\n        response_class: Type[ClientResponse] = ClientResponse,\n        ws_response_class: Type[ClientWebSocketResponse] = ClientWebSocketResponse,\n        version: HttpVersion = http.HttpVersion11,\n        cookie_jar: Optional[AbstractCookieJar] = None,\n        connector_owner: bool = True,\n        raise_for_status: Union[\n            bool, Callable[[ClientResponse], Awaitable[None]]\n        ] = False,\n        read_timeout: Union[float, _SENTINEL] = sentinel,\n        conn_timeout: Optional[float] = None,\n        timeout: Union[object, ClientTimeout] = sentinel,\n        auto_decompress: bool = True,\n        trust_env: bool = False,\n        requote_redirect_url: bool = True,\n        trace_configs: Optional[List[TraceConfig]] = None,\n        read_bufsize: int = 2**16,\n        max_line_size: int = 8190,\n        max_field_size: int = 8190,\n        fallback_charset_resolver: _CharsetResolver = lambda r, b: \"utf-8\",\n    ) -> None:\n        # We initialise _connector to None immediately, as it's referenced in __del__()\n        # and could cause issues if an exception occurs during initialisation.\n        self._connector: Optional[BaseConnector] = None\n\n        if loop is None:\n            if connector is not None:\n                loop = connector._loop\n\n        loop = loop or asyncio.get_running_loop()\n\n        if base_url is None or isinstance(base_url, URL):\n            self._base_url: Optional[URL] = base_url\n        else:\n            self._base_url = URL(base_url)\n            assert (\n                self._base_url.origin() == self._base_url\n            ), \"Only absolute URLs without path part are supported\"\n\n        if timeout is sentinel or timeout is None:\n            self._timeout = DEFAULT_TIMEOUT\n            if read_timeout is not sentinel:\n                warnings.warn(\n                    \"read_timeout is deprecated, use timeout argument instead\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n                self._timeout = attr.evolve(self._timeout, total=read_timeout)\n            if conn_timeout is not None:\n                self._timeout = attr.evolve(self._timeout, connect=conn_timeout)\n                warnings.warn(\n                    \"conn_timeout is deprecated, use timeout argument instead\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n        else:\n            if not isinstance(timeout, ClientTimeout):\n                raise ValueError(\n                    f\"timeout parameter cannot be of {type(timeout)} type, \"\n                    \"please use 'timeout=ClientTimeout(...)'\",\n                )\n            self._timeout = timeout\n            if read_timeout is not sentinel:\n                raise ValueError(\n                    \"read_timeout and timeout parameters \"\n                    \"conflict, please setup \"\n                    \"timeout.read\"\n                )\n            if conn_timeout is not None:\n                raise ValueError(\n                    \"conn_timeout and timeout parameters \"\n                    \"conflict, please setup \"\n                    \"timeout.connect\"\n                )\n\n        if connector is None:\n            connector = TCPConnector(loop=loop)\n\n        if connector._loop is not loop:\n            raise RuntimeError(\"Session and connector has to use same event loop\")\n\n        self._loop = loop\n\n        if loop.get_debug():\n            self._source_traceback = traceback.extract_stack(sys._getframe(1))\n\n        if cookie_jar is None:\n            cookie_jar = CookieJar(loop=loop)\n        self._cookie_jar = cookie_jar\n\n        if cookies is not None:\n            self._cookie_jar.update_cookies(cookies)\n\n        self._connector = connector\n        self._connector_owner = connector_owner\n        self._default_auth = auth\n        self._version = version\n        self._json_serialize = json_serialize\n        self._raise_for_status = raise_for_status\n        self._auto_decompress = auto_decompress\n        self._trust_env = trust_env\n        self._requote_redirect_url = requote_redirect_url\n        self._read_bufsize = read_bufsize\n        self._max_line_size = max_line_size\n        self._max_field_size = max_field_size\n\n        # Convert to list of tuples\n        if headers:\n            real_headers: CIMultiDict[str] = CIMultiDict(headers)\n        else:\n            real_headers = CIMultiDict()\n        self._default_headers: CIMultiDict[str] = real_headers\n        if skip_auto_headers is not None:\n            self._skip_auto_headers = frozenset(istr(i) for i in skip_auto_headers)\n        else:\n            self._skip_auto_headers = frozenset()\n\n        self._request_class = request_class\n        self._response_class = response_class\n        self._ws_response_class = ws_response_class\n\n        self._trace_configs = trace_configs or []\n        for trace_config in self._trace_configs:\n            trace_config.freeze()\n\n        self._resolve_charset = fallback_charset_resolver\n\n        self._default_proxy = proxy\n        self._default_proxy_auth = proxy_auth\n\n    def __init_subclass__(cls: Type[\"ClientSession\"]) -> None:\n        warnings.warn(\n            \"Inheritance class {} from ClientSession \"\n            \"is discouraged\".format(cls.__name__),\n            DeprecationWarning,\n            stacklevel=2,\n        )\n\n    if DEBUG:\n\n        def __setattr__(self, name: str, val: Any) -> None:\n            if name not in self.ATTRS:\n                warnings.warn(\n                    \"Setting custom ClientSession.{} attribute \"\n                    \"is discouraged\".format(name),\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n            super().__setattr__(name, val)\n\n    def __del__(self, _warnings: Any = warnings) -> None:\n        if not self.closed:\n            kwargs = {\"source\": self}\n            _warnings.warn(\n                f\"Unclosed client session {self!r}\", ResourceWarning, **kwargs\n            )\n            context = {\"client_session\": self, \"message\": \"Unclosed client session\"}\n            if self._source_traceback is not None:\n                context[\"source_traceback\"] = self._source_traceback\n            self._loop.call_exception_handler(context)\n\n    if sys.version_info >= (3, 11) and TYPE_CHECKING:\n\n        def request(\n            self,\n            method: str,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n    else:\n\n        def request(\n            self, method: str, url: StrOrURL, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP request.\"\"\"\n            return _RequestContextManager(self._request(method, url, **kwargs))\n\n    def _build_url(self, str_or_url: StrOrURL) -> URL:\n        url = URL(str_or_url)\n        if self._base_url is None:\n            return url\n        else:\n            assert not url.absolute and url.path.startswith(\"/\")\n            return self._base_url.join(url)\n\n    async def _request(\n        self,\n        method: str,\n        str_or_url: StrOrURL,\n        *,\n        params: Query = None,\n        data: Any = None,\n        json: Any = None,\n        cookies: Optional[LooseCookies] = None,\n        headers: Optional[LooseHeaders] = None,\n        skip_auto_headers: Optional[Iterable[str]] = None,\n        auth: Optional[BasicAuth] = None,\n        allow_redirects: bool = True,\n        max_redirects: int = 10,\n        compress: Union[str, bool, None] = None,\n        chunked: Optional[bool] = None,\n        expect100: bool = False,\n        raise_for_status: Union[\n            None, bool, Callable[[ClientResponse], Awaitable[None]]\n        ] = None,\n        read_until_eof: bool = True,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        timeout: Union[ClientTimeout, _SENTINEL] = sentinel,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        server_hostname: Optional[str] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        trace_request_ctx: Optional[Mapping[str, str]] = None,\n        read_bufsize: Optional[int] = None,\n        auto_decompress: Optional[bool] = None,\n        max_line_size: Optional[int] = None,\n        max_field_size: Optional[int] = None,\n    ) -> ClientResponse:\n\n        # NOTE: timeout clamps existing connect and read timeouts.  We cannot\n        # set the default to None because we need to detect if the user wants\n        # to use the existing timeouts by setting timeout to None.\n\n        if self.closed:\n            raise RuntimeError(\"Session is closed\")\n\n        ssl = _merge_ssl_params(ssl, verify_ssl, ssl_context, fingerprint)\n\n        if data is not None and json is not None:\n            raise ValueError(\n                \"data and json parameters can not be used at the same time\"\n            )\n        elif json is not None:\n            data = payload.JsonPayload(json, dumps=self._json_serialize)\n\n        if not isinstance(chunked, bool) and chunked is not None:\n            warnings.warn(\"Chunk size is deprecated #1615\", DeprecationWarning)\n\n        redirects = 0\n        history = []\n        version = self._version\n        params = params or {}\n\n        # Merge with default headers and transform to CIMultiDict\n        headers = self._prepare_headers(headers)\n\n        try:\n            url = self._build_url(str_or_url)\n        except ValueError as e:\n            raise InvalidUrlClientError(str_or_url) from e\n\n        assert self._connector is not None\n        if url.scheme not in self._connector.allowed_protocol_schema_set:\n            raise NonHttpUrlClientError(url)\n\n        skip_headers = set(self._skip_auto_headers)\n        if skip_auto_headers is not None:\n            for i in skip_auto_headers:\n                skip_headers.add(istr(i))\n\n        if proxy is None:\n            proxy = self._default_proxy\n        if proxy_auth is None:\n            proxy_auth = self._default_proxy_auth\n\n        if proxy is None:\n            proxy_headers = None\n        else:\n            proxy_headers = self._prepare_headers(proxy_headers)\n            try:\n                proxy = URL(proxy)\n            except ValueError as e:\n                raise InvalidURL(proxy) from e\n\n        if timeout is sentinel:\n            real_timeout: ClientTimeout = self._timeout\n        else:\n            if not isinstance(timeout, ClientTimeout):\n                real_timeout = ClientTimeout(total=timeout)\n            else:\n                real_timeout = timeout\n        # timeout is cumulative for all request operations\n        # (request, redirects, responses, data consuming)\n        tm = TimeoutHandle(\n            self._loop, real_timeout.total, ceil_threshold=real_timeout.ceil_threshold\n        )\n        handle = tm.start()\n\n        if read_bufsize is None:\n            read_bufsize = self._read_bufsize\n\n        if auto_decompress is None:\n            auto_decompress = self._auto_decompress\n\n        if max_line_size is None:\n            max_line_size = self._max_line_size\n\n        if max_field_size is None:\n            max_field_size = self._max_field_size\n\n        traces = [\n            Trace(\n                self,\n                trace_config,\n                trace_config.trace_config_ctx(trace_request_ctx=trace_request_ctx),\n            )\n            for trace_config in self._trace_configs\n        ]\n\n        for trace in traces:\n            await trace.send_request_start(method, url.update_query(params), headers)\n\n        timer = tm.timer()\n        try:\n            with timer:\n                # https://www.rfc-editor.org/rfc/rfc9112.html#name-retrying-requests\n                retry_persistent_connection = method in IDEMPOTENT_METHODS\n                while True:\n                    url, auth_from_url = strip_auth_from_url(url)\n                    if not url.raw_host:\n                        # NOTE: Bail early, otherwise, causes `InvalidURL` through\n                        # NOTE: `self._request_class()` below.\n                        err_exc_cls = (\n                            InvalidUrlRedirectClientError\n                            if redirects\n                            else InvalidUrlClientError\n                        )\n                        raise err_exc_cls(url)\n                    if auth and auth_from_url:\n                        raise ValueError(\n                            \"Cannot combine AUTH argument with \"\n                            \"credentials encoded in URL\"\n                        )\n\n                    if auth is None:\n                        auth = auth_from_url\n\n                    if auth is None and (\n                        not self._base_url or self._base_url.origin() == url.origin()\n                    ):\n                        auth = self._default_auth\n                    # It would be confusing if we support explicit\n                    # Authorization header with auth argument\n                    if (\n                        headers is not None\n                        and auth is not None\n                        and hdrs.AUTHORIZATION in headers\n                    ):\n                        raise ValueError(\n                            \"Cannot combine AUTHORIZATION header \"\n                            \"with AUTH argument or credentials \"\n                            \"encoded in URL\"\n                        )\n\n                    all_cookies = self._cookie_jar.filter_cookies(url)\n\n                    if cookies is not None:\n                        tmp_cookie_jar = CookieJar()\n                        tmp_cookie_jar.update_cookies(cookies)\n                        req_cookies = tmp_cookie_jar.filter_cookies(url)\n                        if req_cookies:\n                            all_cookies.load(req_cookies)\n\n                    if proxy is not None:\n                        proxy = URL(proxy)\n                    elif self._trust_env:\n                        with suppress(LookupError):\n                            proxy, proxy_auth = get_env_proxy_for_url(url)\n\n                    req = self._request_class(\n                        method,\n                        url,\n                        params=params,\n                        headers=headers,\n                        skip_auto_headers=skip_headers if skip_headers else None,\n                        data=data,\n                        cookies=all_cookies,\n                        auth=auth,\n                        version=version,\n                        compress=compress,\n                        chunked=chunked,\n                        expect100=expect100,\n                        loop=self._loop,\n                        response_class=self._response_class,\n                        proxy=proxy,\n                        proxy_auth=proxy_auth,\n                        timer=timer,\n                        session=self,\n                        ssl=ssl if ssl is not None else True,\n                        server_hostname=server_hostname,\n                        proxy_headers=proxy_headers,\n                        traces=traces,\n                        trust_env=self.trust_env,\n                    )\n\n                    # connection timeout\n                    try:\n                        async with ceil_timeout(\n                            real_timeout.connect,\n                            ceil_threshold=real_timeout.ceil_threshold,\n                        ):\n                            conn = await self._connector.connect(\n                                req, traces=traces, timeout=real_timeout\n                            )\n                    except asyncio.TimeoutError as exc:\n                        raise ConnectionTimeoutError(\n                            f\"Connection timeout to host {url}\"\n                        ) from exc\n\n                    assert conn.transport is not None\n\n                    assert conn.protocol is not None\n                    conn.protocol.set_response_params(\n                        timer=timer,\n                        skip_payload=method_must_be_empty_body(method),\n                        read_until_eof=read_until_eof,\n                        auto_decompress=auto_decompress,\n                        read_timeout=real_timeout.sock_read,\n                        read_bufsize=read_bufsize,\n                        timeout_ceil_threshold=self._connector._timeout_ceil_threshold,\n                        max_line_size=max_line_size,\n                        max_field_size=max_field_size,\n                    )\n\n                    try:\n                        try:\n                            resp = await req.send(conn)\n                            try:\n                                await resp.start(conn)\n                            except BaseException:\n                                resp.close()\n                                raise\n                        except BaseException:\n                            conn.close()\n                            raise\n                    except (ClientOSError, ServerDisconnectedError):\n                        if retry_persistent_connection:\n                            retry_persistent_connection = False\n                            continue\n                        raise\n                    except ClientError:\n                        raise\n                    except OSError as exc:\n                        if exc.errno is None and isinstance(exc, asyncio.TimeoutError):\n                            raise\n                        raise ClientOSError(*exc.args) from exc\n\n                    self._cookie_jar.update_cookies(resp.cookies, resp.url)\n\n                    # redirects\n                    if resp.status in (301, 302, 303, 307, 308) and allow_redirects:\n\n                        for trace in traces:\n                            await trace.send_request_redirect(\n                                method, url.update_query(params), headers, resp\n                            )\n\n                        redirects += 1\n                        history.append(resp)\n                        if max_redirects and redirects >= max_redirects:\n                            resp.close()\n                            raise TooManyRedirects(\n                                history[0].request_info, tuple(history)\n                            )\n\n                        # For 301 and 302, mimic IE, now changed in RFC\n                        # https://github.com/kennethreitz/requests/pull/269\n                        if (resp.status == 303 and resp.method != hdrs.METH_HEAD) or (\n                            resp.status in (301, 302) and resp.method == hdrs.METH_POST\n                        ):\n                            method = hdrs.METH_GET\n                            data = None\n                            if headers.get(hdrs.CONTENT_LENGTH):\n                                headers.pop(hdrs.CONTENT_LENGTH)\n\n                        r_url = resp.headers.get(hdrs.LOCATION) or resp.headers.get(\n                            hdrs.URI\n                        )\n                        if r_url is None:\n                            # see github.com/aio-libs/aiohttp/issues/2022\n                            break\n                        else:\n                            # reading from correct redirection\n                            # response is forbidden\n                            resp.release()\n\n                        try:\n                            parsed_redirect_url = URL(\n                                r_url, encoded=not self._requote_redirect_url\n                            )\n                        except ValueError as e:\n                            raise InvalidUrlRedirectClientError(\n                                r_url,\n                                \"Server attempted redirecting to a location that does not look like a URL\",\n                            ) from e\n\n                        scheme = parsed_redirect_url.scheme\n                        if scheme not in HTTP_AND_EMPTY_SCHEMA_SET:\n                            resp.close()\n                            raise NonHttpUrlRedirectClientError(r_url)\n                        elif not scheme:\n                            parsed_redirect_url = url.join(parsed_redirect_url)\n\n                        try:\n                            redirect_origin = parsed_redirect_url.origin()\n                        except ValueError as origin_val_err:\n                            raise InvalidUrlRedirectClientError(\n                                parsed_redirect_url,\n                                \"Invalid redirect URL origin\",\n                            ) from origin_val_err\n\n                        if url.origin() != redirect_origin:\n                            auth = None\n                            headers.pop(hdrs.AUTHORIZATION, None)\n\n                        url = parsed_redirect_url\n                        params = {}\n                        resp.release()\n                        continue\n\n                    break\n\n            # check response status\n            if raise_for_status is None:\n                raise_for_status = self._raise_for_status\n\n            if raise_for_status is None:\n                pass\n            elif callable(raise_for_status):\n                await raise_for_status(resp)\n            elif raise_for_status:\n                resp.raise_for_status()\n\n            # register connection\n            if handle is not None:\n                if resp.connection is not None:\n                    resp.connection.add_callback(handle.cancel)\n                else:\n                    handle.cancel()\n\n            resp._history = tuple(history)\n\n            for trace in traces:\n                await trace.send_request_end(\n                    method, url.update_query(params), headers, resp\n                )\n            return resp\n\n        except BaseException as e:\n            # cleanup timer\n            tm.close()\n            if handle:\n                handle.cancel()\n                handle = None\n\n            for trace in traces:\n                await trace.send_request_exception(\n                    method, url.update_query(params), headers, e\n                )\n            raise\n\n    def ws_connect(\n        self,\n        url: StrOrURL,\n        *,\n        method: str = hdrs.METH_GET,\n        protocols: Iterable[str] = (),\n        timeout: Union[ClientWSTimeout, _SENTINEL] = sentinel,\n        receive_timeout: Optional[float] = None,\n        autoclose: bool = True,\n        autoping: bool = True,\n        heartbeat: Optional[float] = None,\n        auth: Optional[BasicAuth] = None,\n        origin: Optional[str] = None,\n        params: Query = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        compress: int = 0,\n        max_msg_size: int = 4 * 1024 * 1024,\n    ) -> \"_WSRequestContextManager\":\n        \"\"\"Initiate websocket connection.\"\"\"\n        return _WSRequestContextManager(\n            self._ws_connect(\n                url,\n                method=method,\n                protocols=protocols,\n                timeout=timeout,\n                receive_timeout=receive_timeout,\n                autoclose=autoclose,\n                autoping=autoping,\n                heartbeat=heartbeat,\n                auth=auth,\n                origin=origin,\n                params=params,\n                headers=headers,\n                proxy=proxy,\n                proxy_auth=proxy_auth,\n                ssl=ssl,\n                verify_ssl=verify_ssl,\n                fingerprint=fingerprint,\n                ssl_context=ssl_context,\n                proxy_headers=proxy_headers,\n                compress=compress,\n                max_msg_size=max_msg_size,\n            )\n        )\n\n    async def _ws_connect(\n        self,\n        url: StrOrURL,\n        *,\n        method: str = hdrs.METH_GET,\n        protocols: Iterable[str] = (),\n        timeout: Union[ClientWSTimeout, _SENTINEL] = sentinel,\n        receive_timeout: Optional[float] = None,\n        autoclose: bool = True,\n        autoping: bool = True,\n        heartbeat: Optional[float] = None,\n        auth: Optional[BasicAuth] = None,\n        origin: Optional[str] = None,\n        params: Query = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        compress: int = 0,\n        max_msg_size: int = 4 * 1024 * 1024,\n    ) -> ClientWebSocketResponse:\n        if timeout is not sentinel:\n            if isinstance(timeout, ClientWSTimeout):\n                ws_timeout = timeout\n            else:\n                warnings.warn(\n                    \"parameter 'timeout' of type 'float' \"\n                    \"is deprecated, please use \"\n                    \"'timeout=ClientWSTimeout(ws_close=...)'\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n                ws_timeout = ClientWSTimeout(ws_close=timeout)\n        else:\n            ws_timeout = DEFAULT_WS_CLIENT_TIMEOUT\n        if receive_timeout is not None:\n            warnings.warn(\n                \"float parameter 'receive_timeout' \"\n                \"is deprecated, please use parameter \"\n                \"'timeout=ClientWSTimeout(ws_receive=...)'\",\n                DeprecationWarning,\n                stacklevel=2,\n            )\n            ws_timeout = attr.evolve(ws_timeout, ws_receive=receive_timeout)\n\n        if headers is None:\n            real_headers: CIMultiDict[str] = CIMultiDict()\n        else:\n            real_headers = CIMultiDict(headers)\n\n        default_headers = {\n            hdrs.UPGRADE: \"websocket\",\n            hdrs.CONNECTION: \"Upgrade\",\n            hdrs.SEC_WEBSOCKET_VERSION: \"13\",\n        }\n\n        for key, value in default_headers.items():\n            real_headers.setdefault(key, value)\n\n        sec_key = base64.b64encode(os.urandom(16))\n        real_headers[hdrs.SEC_WEBSOCKET_KEY] = sec_key.decode()\n\n        if protocols:\n            real_headers[hdrs.SEC_WEBSOCKET_PROTOCOL] = \",\".join(protocols)\n        if origin is not None:\n            real_headers[hdrs.ORIGIN] = origin\n        if compress:\n            extstr = ws_ext_gen(compress=compress)\n            real_headers[hdrs.SEC_WEBSOCKET_EXTENSIONS] = extstr\n\n        # For the sake of backward compatibility, if user passes in None, convert it to True\n        if ssl is None:\n            warnings.warn(\n                \"ssl=None is deprecated, please use ssl=True\",\n                DeprecationWarning,\n                stacklevel=2,\n            )\n            ssl = True\n        ssl = _merge_ssl_params(ssl, verify_ssl, ssl_context, fingerprint)\n\n        # send request\n        resp = await self.request(\n            method,\n            url,\n            params=params,\n            headers=real_headers,\n            read_until_eof=False,\n            auth=auth,\n            proxy=proxy,\n            proxy_auth=proxy_auth,\n            ssl=ssl,\n            proxy_headers=proxy_headers,\n        )\n\n        try:\n            # check handshake\n            if resp.status != 101:\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid response status\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            if resp.headers.get(hdrs.UPGRADE, \"\").lower() != \"websocket\":\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid upgrade header\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            if resp.headers.get(hdrs.CONNECTION, \"\").lower() != \"upgrade\":\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid connection header\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            # key calculation\n            r_key = resp.headers.get(hdrs.SEC_WEBSOCKET_ACCEPT, \"\")\n            match = base64.b64encode(hashlib.sha1(sec_key + WS_KEY).digest()).decode()\n            if r_key != match:\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid challenge response\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            # websocket protocol\n            protocol = None\n            if protocols and hdrs.SEC_WEBSOCKET_PROTOCOL in resp.headers:\n                resp_protocols = [\n                    proto.strip()\n                    for proto in resp.headers[hdrs.SEC_WEBSOCKET_PROTOCOL].split(\",\")\n                ]\n\n                for proto in resp_protocols:\n                    if proto in protocols:\n                        protocol = proto\n                        break\n\n            # websocket compress\n            notakeover = False\n            if compress:\n                compress_hdrs = resp.headers.get(hdrs.SEC_WEBSOCKET_EXTENSIONS)\n                if compress_hdrs:\n                    try:\n                        compress, notakeover = ws_ext_parse(compress_hdrs)\n                    except WSHandshakeError as exc:\n                        raise WSServerHandshakeError(\n                            resp.request_info,\n                            resp.history,\n                            message=exc.args[0],\n                            status=resp.status,\n                            headers=resp.headers,\n                        ) from exc\n                else:\n                    compress = 0\n                    notakeover = False\n\n            conn = resp.connection\n            assert conn is not None\n            conn_proto = conn.protocol\n            assert conn_proto is not None\n\n            # For WS connection the read_timeout must be either receive_timeout or greater\n            # None == no timeout, i.e. infinite timeout, so None is the max timeout possible\n            if ws_timeout.ws_receive is None:\n                # Reset regardless\n                conn_proto.read_timeout = None\n            elif conn_proto.read_timeout is not None:\n                conn_proto.read_timeout = max(\n                    ws_timeout.ws_receive, conn_proto.read_timeout\n                )\n\n            transport = conn.transport\n            assert transport is not None\n            reader: FlowControlDataQueue[WSMessage] = FlowControlDataQueue(\n                conn_proto, 2**16, loop=self._loop\n            )\n            conn_proto.set_parser(WebSocketReader(reader, max_msg_size), reader)\n            writer = WebSocketWriter(\n                conn_proto,\n                transport,\n                use_mask=True,\n                compress=compress,\n                notakeover=notakeover,\n            )\n        except BaseException:\n            resp.close()\n            raise\n        else:\n            return self._ws_response_class(\n                reader,\n                writer,\n                protocol,\n                resp,\n                ws_timeout,\n                autoclose,\n                autoping,\n                self._loop,\n                heartbeat=heartbeat,\n                compress=compress,\n                client_notakeover=notakeover,\n            )\n\n    def _prepare_headers(self, headers: Optional[LooseHeaders]) -> \"CIMultiDict[str]\":\n        \"\"\"Add default headers and transform it to CIMultiDict\"\"\"\n        # Convert headers to MultiDict\n        result = CIMultiDict(self._default_headers)\n        if headers:\n            if not isinstance(headers, (MultiDictProxy, MultiDict)):\n                headers = CIMultiDict(headers)\n            added_names: Set[str] = set()\n            for key, value in headers.items():\n                if key in added_names:\n                    result.add(key, value)\n                else:\n                    result[key] = value\n                    added_names.add(key)\n        return result\n\n    if sys.version_info >= (3, 11) and TYPE_CHECKING:\n\n        def get(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def options(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def head(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def post(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def put(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def patch(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def delete(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n    else:\n\n        def get(\n            self, url: StrOrURL, *, allow_redirects: bool = True, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP GET request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_GET, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def options(\n            self, url: StrOrURL, *, allow_redirects: bool = True, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP OPTIONS request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_OPTIONS, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def head(\n            self, url: StrOrURL, *, allow_redirects: bool = False, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP HEAD request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_HEAD, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def post(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP POST request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_POST, url, data=data, **kwargs)\n            )\n\n        def put(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP PUT request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_PUT, url, data=data, **kwargs)\n            )\n\n        def patch(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP PATCH request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_PATCH, url, data=data, **kwargs)\n            )\n\n        def delete(self, url: StrOrURL, **kwargs: Any) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP DELETE request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_DELETE, url, **kwargs)\n            )\n\n    async def close(self) -> None:\n        \"\"\"Close underlying connector.\n\n        Release all acquired resources.\n        \"\"\"\n        if not self.closed:\n            if self._connector is not None and self._connector_owner:\n                await self._connector.close()\n            self._connector = None\n\n    @property\n    def closed(self) -> bool:\n        \"\"\"Is client session closed.\n\n        A readonly property.\n        \"\"\"\n        return self._connector is None or self._connector.closed\n\n    @property\n    def connector(self) -> Optional[BaseConnector]:\n        \"\"\"Connector instance used for the session.\"\"\"\n        return self._connector\n\n    @property\n    def cookie_jar(self) -> AbstractCookieJar:\n        \"\"\"The session cookies.\"\"\"\n        return self._cookie_jar\n\n    @property\n    def version(self) -> Tuple[int, int]:\n        \"\"\"The session HTTP protocol version.\"\"\"\n        return self._version\n\n    @property\n    def requote_redirect_url(self) -> bool:\n        \"\"\"Do URL requoting on redirection handling.\"\"\"\n        return self._requote_redirect_url\n\n    @requote_redirect_url.setter\n    def requote_redirect_url(self, val: bool) -> None:\n        \"\"\"Do URL requoting on redirection handling.\"\"\"\n        warnings.warn(\n            \"session.requote_redirect_url modification is deprecated #2778\",\n            DeprecationWarning,\n            stacklevel=2,\n        )\n        self._requote_redirect_url = val\n\n    @property\n    def loop(self) -> asyncio.AbstractEventLoop:\n        \"\"\"Session's loop.\"\"\"\n        warnings.warn(\n            \"client.loop property is deprecated\", DeprecationWarning, stacklevel=2\n        )\n        return self._loop\n\n    @property\n    def timeout(self) -> ClientTimeout:\n        \"\"\"Timeout for the session.\"\"\"\n        return self._timeout\n\n    @property\n    def headers(self) -> \"CIMultiDict[str]\":\n        \"\"\"The default headers of the client session.\"\"\"\n        return self._default_headers\n\n    @property\n    def skip_auto_headers(self) -> FrozenSet[istr]:\n        \"\"\"Headers for which autogeneration should be skipped\"\"\"\n        return self._skip_auto_headers\n\n    @property\n    def auth(self) -> Optional[BasicAuth]:\n        \"\"\"An object that represents HTTP Basic Authorization\"\"\"\n        return self._default_auth\n\n    @property\n    def json_serialize(self) -> JSONEncoder:\n        \"\"\"Json serializer callable\"\"\"\n        return self._json_serialize\n\n    @property\n    def connector_owner(self) -> bool:\n        \"\"\"Should connector be closed on session closing\"\"\"\n        return self._connector_owner\n\n    @property\n    def raise_for_status(\n        self,\n    ) -> Union[bool, Callable[[ClientResponse], Awaitable[None]]]:\n        \"\"\"Should `ClientResponse.raise_for_status()` be called for each response.\"\"\"\n        return self._raise_for_status\n\n    @property\n    def auto_decompress(self) -> bool:\n        \"\"\"Should the body response be automatically decompressed.\"\"\"\n        return self._auto_decompress\n\n    @property\n    def trust_env(self) -> bool:\n        \"\"\"\n        Should proxies information from environment or netrc be trusted.\n\n        Information is from HTTP_PROXY / HTTPS_PROXY environment variables\n        or ~/.netrc file if present.\n        \"\"\"\n        return self._trust_env\n\n    @property\n    def trace_configs(self) -> List[TraceConfig]:\n        \"\"\"A list of TraceConfig instances used for client tracing\"\"\"\n        return self._trace_configs\n\n    def detach(self) -> None:\n        \"\"\"Detach connector from session without closing the former.\n\n        Session is switched to closed state anyway.\n        \"\"\"\n        self._connector = None\n\n    def __enter__(self) -> None:\n        raise TypeError(\"Use async with instead\")\n\n    def __exit__(\n        self,\n        exc_type: Optional[Type[BaseException]],\n        exc_val: Optional[BaseException],\n        exc_tb: Optional[TracebackType],\n    ) -> None:\n        # __exit__ should exist in pair with __enter__ but never executed\n        pass  # pragma: no cover\n\n    async def __aenter__(self) -> \"ClientSession\":\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        await self.close()",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 225,
                            "end_lineno": 1373,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 396,
                            "length": 6
                        },
                        "new_range": {
                            "start": 400,
                            "length": 9
                        },
                        "section": "class ClientSession:"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        self._resolve_charset = fallback_charset_resolver",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        self._default_proxy = proxy",
                                "type": "added"
                            },
                            {
                                "content": "        self._default_proxy_auth = proxy_auth",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "    def __init_subclass__(cls: Type[\"ClientSession\"]) -> None:",
                                "type": "context"
                            },
                            {
                                "content": "        warnings.warn(",
                                "type": "context"
                            },
                            {
                                "content": "            \"Inheritance class {} from ClientSession \"",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "aiohttp/client.py",
                            "type": "method",
                            "name": "ClientSession.__init__",
                            "content": "class ClientSession:\n    \"\"\"First-class interface for making HTTP requests.\"\"\"\n\n    ATTRS = frozenset(\n        [\n            \"_base_url\",\n            \"_source_traceback\",\n            \"_connector\",\n            \"requote_redirect_url\",\n            \"_loop\",\n            \"_cookie_jar\",\n            \"_connector_owner\",\n            \"_default_auth\",\n            \"_version\",\n            \"_json_serialize\",\n            \"_requote_redirect_url\",\n            \"_timeout\",\n            \"_raise_for_status\",\n            \"_auto_decompress\",\n            \"_trust_env\",\n            \"_default_headers\",\n            \"_skip_auto_headers\",\n            \"_request_class\",\n            \"_response_class\",\n            \"_ws_response_class\",\n            \"_trace_configs\",\n            \"_read_bufsize\",\n            \"_max_line_size\",\n            \"_max_field_size\",\n            \"_resolve_charset\",\n            \"_default_proxy\",\n            \"_default_proxy_auth\",\n        ]\n    )\n\n    _source_traceback: Optional[traceback.StackSummary] = None\n    _connector: Optional[BaseConnector] = None\n\n    def __init__(\n        self,\n        base_url: Optional[StrOrURL] = None,\n        *,\n        connector: Optional[BaseConnector] = None,\n        loop: Optional[asyncio.AbstractEventLoop] = None,\n        cookies: Optional[LooseCookies] = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        skip_auto_headers: Optional[Iterable[str]] = None,\n        auth: Optional[BasicAuth] = None,\n        json_serialize: JSONEncoder = json.dumps,\n        request_class: Type[ClientRequest] = ClientRequest,\n        response_class: Type[ClientResponse] = ClientResponse,\n        ws_response_class: Type[ClientWebSocketResponse] = ClientWebSocketResponse,\n        version: HttpVersion = http.HttpVersion11,\n        cookie_jar: Optional[AbstractCookieJar] = None,\n        connector_owner: bool = True,\n        raise_for_status: Union[\n            bool, Callable[[ClientResponse], Awaitable[None]]\n        ] = False,\n        read_timeout: Union[float, _SENTINEL] = sentinel,\n        conn_timeout: Optional[float] = None,\n        timeout: Union[object, ClientTimeout] = sentinel,\n        auto_decompress: bool = True,\n        trust_env: bool = False,\n        requote_redirect_url: bool = True,\n        trace_configs: Optional[List[TraceConfig]] = None,\n        read_bufsize: int = 2**16,\n        max_line_size: int = 8190,\n        max_field_size: int = 8190,\n        fallback_charset_resolver: _CharsetResolver = lambda r, b: \"utf-8\",\n    ) -> None:\n        # We initialise _connector to None immediately, as it's referenced in __del__()\n        # and could cause issues if an exception occurs during initialisation.\n        self._connector: Optional[BaseConnector] = None\n\n        if loop is None:\n            if connector is not None:\n                loop = connector._loop\n\n        loop = loop or asyncio.get_running_loop()\n\n        if base_url is None or isinstance(base_url, URL):\n            self._base_url: Optional[URL] = base_url\n        else:\n            self._base_url = URL(base_url)\n            assert (\n                self._base_url.origin() == self._base_url\n            ), \"Only absolute URLs without path part are supported\"\n\n        if timeout is sentinel or timeout is None:\n            self._timeout = DEFAULT_TIMEOUT\n            if read_timeout is not sentinel:\n                warnings.warn(\n                    \"read_timeout is deprecated, use timeout argument instead\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n                self._timeout = attr.evolve(self._timeout, total=read_timeout)\n            if conn_timeout is not None:\n                self._timeout = attr.evolve(self._timeout, connect=conn_timeout)\n                warnings.warn(\n                    \"conn_timeout is deprecated, use timeout argument instead\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n        else:\n            if not isinstance(timeout, ClientTimeout):\n                raise ValueError(\n                    f\"timeout parameter cannot be of {type(timeout)} type, \"\n                    \"please use 'timeout=ClientTimeout(...)'\",\n                )\n            self._timeout = timeout\n            if read_timeout is not sentinel:\n                raise ValueError(\n                    \"read_timeout and timeout parameters \"\n                    \"conflict, please setup \"\n                    \"timeout.read\"\n                )\n            if conn_timeout is not None:\n                raise ValueError(\n                    \"conn_timeout and timeout parameters \"\n                    \"conflict, please setup \"\n                    \"timeout.connect\"\n                )\n\n        if connector is None:\n            connector = TCPConnector(loop=loop)\n\n        if connector._loop is not loop:\n            raise RuntimeError(\"Session and connector has to use same event loop\")\n\n        self._loop = loop\n\n        if loop.get_debug():\n            self._source_traceback = traceback.extract_stack(sys._getframe(1))\n\n        if cookie_jar is None:\n            cookie_jar = CookieJar(loop=loop)\n        self._cookie_jar = cookie_jar\n\n        if cookies is not None:\n            self._cookie_jar.update_cookies(cookies)\n\n        self._connector = connector\n        self._connector_owner = connector_owner\n        self._default_auth = auth\n        self._version = version\n        self._json_serialize = json_serialize\n        self._raise_for_status = raise_for_status\n        self._auto_decompress = auto_decompress\n        self._trust_env = trust_env\n        self._requote_redirect_url = requote_redirect_url\n        self._read_bufsize = read_bufsize\n        self._max_line_size = max_line_size\n        self._max_field_size = max_field_size\n\n        # Convert to list of tuples\n        if headers:\n            real_headers: CIMultiDict[str] = CIMultiDict(headers)\n        else:\n            real_headers = CIMultiDict()\n        self._default_headers: CIMultiDict[str] = real_headers\n        if skip_auto_headers is not None:\n            self._skip_auto_headers = frozenset(istr(i) for i in skip_auto_headers)\n        else:\n            self._skip_auto_headers = frozenset()\n\n        self._request_class = request_class\n        self._response_class = response_class\n        self._ws_response_class = ws_response_class\n\n        self._trace_configs = trace_configs or []\n        for trace_config in self._trace_configs:\n            trace_config.freeze()\n\n        self._resolve_charset = fallback_charset_resolver\n\n        self._default_proxy = proxy\n        self._default_proxy_auth = proxy_auth\n\n    def __init_subclass__(cls: Type[\"ClientSession\"]) -> None:\n        warnings.warn(\n            \"Inheritance class {} from ClientSession \"\n            \"is discouraged\".format(cls.__name__),\n            DeprecationWarning,\n            stacklevel=2,\n        )\n\n    if DEBUG:\n\n        def __setattr__(self, name: str, val: Any) -> None:\n            if name not in self.ATTRS:\n                warnings.warn(\n                    \"Setting custom ClientSession.{} attribute \"\n                    \"is discouraged\".format(name),\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n            super().__setattr__(name, val)\n\n    def __del__(self, _warnings: Any = warnings) -> None:\n        if not self.closed:\n            kwargs = {\"source\": self}\n            _warnings.warn(\n                f\"Unclosed client session {self!r}\", ResourceWarning, **kwargs\n            )\n            context = {\"client_session\": self, \"message\": \"Unclosed client session\"}\n            if self._source_traceback is not None:\n                context[\"source_traceback\"] = self._source_traceback\n            self._loop.call_exception_handler(context)\n\n    if sys.version_info >= (3, 11) and TYPE_CHECKING:\n\n        def request(\n            self,\n            method: str,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n    else:\n\n        def request(\n            self, method: str, url: StrOrURL, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP request.\"\"\"\n            return _RequestContextManager(self._request(method, url, **kwargs))\n\n    def _build_url(self, str_or_url: StrOrURL) -> URL:\n        url = URL(str_or_url)\n        if self._base_url is None:\n            return url\n        else:\n            assert not url.absolute and url.path.startswith(\"/\")\n            return self._base_url.join(url)\n\n    async def _request(\n        self,\n        method: str,\n        str_or_url: StrOrURL,\n        *,\n        params: Query = None,\n        data: Any = None,\n        json: Any = None,\n        cookies: Optional[LooseCookies] = None,\n        headers: Optional[LooseHeaders] = None,\n        skip_auto_headers: Optional[Iterable[str]] = None,\n        auth: Optional[BasicAuth] = None,\n        allow_redirects: bool = True,\n        max_redirects: int = 10,\n        compress: Union[str, bool, None] = None,\n        chunked: Optional[bool] = None,\n        expect100: bool = False,\n        raise_for_status: Union[\n            None, bool, Callable[[ClientResponse], Awaitable[None]]\n        ] = None,\n        read_until_eof: bool = True,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        timeout: Union[ClientTimeout, _SENTINEL] = sentinel,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        server_hostname: Optional[str] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        trace_request_ctx: Optional[Mapping[str, str]] = None,\n        read_bufsize: Optional[int] = None,\n        auto_decompress: Optional[bool] = None,\n        max_line_size: Optional[int] = None,\n        max_field_size: Optional[int] = None,\n    ) -> ClientResponse:\n\n        # NOTE: timeout clamps existing connect and read timeouts.  We cannot\n        # set the default to None because we need to detect if the user wants\n        # to use the existing timeouts by setting timeout to None.\n\n        if self.closed:\n            raise RuntimeError(\"Session is closed\")\n\n        ssl = _merge_ssl_params(ssl, verify_ssl, ssl_context, fingerprint)\n\n        if data is not None and json is not None:\n            raise ValueError(\n                \"data and json parameters can not be used at the same time\"\n            )\n        elif json is not None:\n            data = payload.JsonPayload(json, dumps=self._json_serialize)\n\n        if not isinstance(chunked, bool) and chunked is not None:\n            warnings.warn(\"Chunk size is deprecated #1615\", DeprecationWarning)\n\n        redirects = 0\n        history = []\n        version = self._version\n        params = params or {}\n\n        # Merge with default headers and transform to CIMultiDict\n        headers = self._prepare_headers(headers)\n\n        try:\n            url = self._build_url(str_or_url)\n        except ValueError as e:\n            raise InvalidUrlClientError(str_or_url) from e\n\n        assert self._connector is not None\n        if url.scheme not in self._connector.allowed_protocol_schema_set:\n            raise NonHttpUrlClientError(url)\n\n        skip_headers = set(self._skip_auto_headers)\n        if skip_auto_headers is not None:\n            for i in skip_auto_headers:\n                skip_headers.add(istr(i))\n\n        if proxy is None:\n            proxy = self._default_proxy\n        if proxy_auth is None:\n            proxy_auth = self._default_proxy_auth\n\n        if proxy is None:\n            proxy_headers = None\n        else:\n            proxy_headers = self._prepare_headers(proxy_headers)\n            try:\n                proxy = URL(proxy)\n            except ValueError as e:\n                raise InvalidURL(proxy) from e\n\n        if timeout is sentinel:\n            real_timeout: ClientTimeout = self._timeout\n        else:\n            if not isinstance(timeout, ClientTimeout):\n                real_timeout = ClientTimeout(total=timeout)\n            else:\n                real_timeout = timeout\n        # timeout is cumulative for all request operations\n        # (request, redirects, responses, data consuming)\n        tm = TimeoutHandle(\n            self._loop, real_timeout.total, ceil_threshold=real_timeout.ceil_threshold\n        )\n        handle = tm.start()\n\n        if read_bufsize is None:\n            read_bufsize = self._read_bufsize\n\n        if auto_decompress is None:\n            auto_decompress = self._auto_decompress\n\n        if max_line_size is None:\n            max_line_size = self._max_line_size\n\n        if max_field_size is None:\n            max_field_size = self._max_field_size\n\n        traces = [\n            Trace(\n                self,\n                trace_config,\n                trace_config.trace_config_ctx(trace_request_ctx=trace_request_ctx),\n            )\n            for trace_config in self._trace_configs\n        ]\n\n        for trace in traces:\n            await trace.send_request_start(method, url.update_query(params), headers)\n\n        timer = tm.timer()\n        try:\n            with timer:\n                # https://www.rfc-editor.org/rfc/rfc9112.html#name-retrying-requests\n                retry_persistent_connection = method in IDEMPOTENT_METHODS\n                while True:\n                    url, auth_from_url = strip_auth_from_url(url)\n                    if not url.raw_host:\n                        # NOTE: Bail early, otherwise, causes `InvalidURL` through\n                        # NOTE: `self._request_class()` below.\n                        err_exc_cls = (\n                            InvalidUrlRedirectClientError\n                            if redirects\n                            else InvalidUrlClientError\n                        )\n                        raise err_exc_cls(url)\n                    if auth and auth_from_url:\n                        raise ValueError(\n                            \"Cannot combine AUTH argument with \"\n                            \"credentials encoded in URL\"\n                        )\n\n                    if auth is None:\n                        auth = auth_from_url\n\n                    if auth is None and (\n                        not self._base_url or self._base_url.origin() == url.origin()\n                    ):\n                        auth = self._default_auth\n                    # It would be confusing if we support explicit\n                    # Authorization header with auth argument\n                    if (\n                        headers is not None\n                        and auth is not None\n                        and hdrs.AUTHORIZATION in headers\n                    ):\n                        raise ValueError(\n                            \"Cannot combine AUTHORIZATION header \"\n                            \"with AUTH argument or credentials \"\n                            \"encoded in URL\"\n                        )\n\n                    all_cookies = self._cookie_jar.filter_cookies(url)\n\n                    if cookies is not None:\n                        tmp_cookie_jar = CookieJar()\n                        tmp_cookie_jar.update_cookies(cookies)\n                        req_cookies = tmp_cookie_jar.filter_cookies(url)\n                        if req_cookies:\n                            all_cookies.load(req_cookies)\n\n                    if proxy is not None:\n                        proxy = URL(proxy)\n                    elif self._trust_env:\n                        with suppress(LookupError):\n                            proxy, proxy_auth = get_env_proxy_for_url(url)\n\n                    req = self._request_class(\n                        method,\n                        url,\n                        params=params,\n                        headers=headers,\n                        skip_auto_headers=skip_headers if skip_headers else None,\n                        data=data,\n                        cookies=all_cookies,\n                        auth=auth,\n                        version=version,\n                        compress=compress,\n                        chunked=chunked,\n                        expect100=expect100,\n                        loop=self._loop,\n                        response_class=self._response_class,\n                        proxy=proxy,\n                        proxy_auth=proxy_auth,\n                        timer=timer,\n                        session=self,\n                        ssl=ssl if ssl is not None else True,\n                        server_hostname=server_hostname,\n                        proxy_headers=proxy_headers,\n                        traces=traces,\n                        trust_env=self.trust_env,\n                    )\n\n                    # connection timeout\n                    try:\n                        async with ceil_timeout(\n                            real_timeout.connect,\n                            ceil_threshold=real_timeout.ceil_threshold,\n                        ):\n                            conn = await self._connector.connect(\n                                req, traces=traces, timeout=real_timeout\n                            )\n                    except asyncio.TimeoutError as exc:\n                        raise ConnectionTimeoutError(\n                            f\"Connection timeout to host {url}\"\n                        ) from exc\n\n                    assert conn.transport is not None\n\n                    assert conn.protocol is not None\n                    conn.protocol.set_response_params(\n                        timer=timer,\n                        skip_payload=method_must_be_empty_body(method),\n                        read_until_eof=read_until_eof,\n                        auto_decompress=auto_decompress,\n                        read_timeout=real_timeout.sock_read,\n                        read_bufsize=read_bufsize,\n                        timeout_ceil_threshold=self._connector._timeout_ceil_threshold,\n                        max_line_size=max_line_size,\n                        max_field_size=max_field_size,\n                    )\n\n                    try:\n                        try:\n                            resp = await req.send(conn)\n                            try:\n                                await resp.start(conn)\n                            except BaseException:\n                                resp.close()\n                                raise\n                        except BaseException:\n                            conn.close()\n                            raise\n                    except (ClientOSError, ServerDisconnectedError):\n                        if retry_persistent_connection:\n                            retry_persistent_connection = False\n                            continue\n                        raise\n                    except ClientError:\n                        raise\n                    except OSError as exc:\n                        if exc.errno is None and isinstance(exc, asyncio.TimeoutError):\n                            raise\n                        raise ClientOSError(*exc.args) from exc\n\n                    self._cookie_jar.update_cookies(resp.cookies, resp.url)\n\n                    # redirects\n                    if resp.status in (301, 302, 303, 307, 308) and allow_redirects:\n\n                        for trace in traces:\n                            await trace.send_request_redirect(\n                                method, url.update_query(params), headers, resp\n                            )\n\n                        redirects += 1\n                        history.append(resp)\n                        if max_redirects and redirects >= max_redirects:\n                            resp.close()\n                            raise TooManyRedirects(\n                                history[0].request_info, tuple(history)\n                            )\n\n                        # For 301 and 302, mimic IE, now changed in RFC\n                        # https://github.com/kennethreitz/requests/pull/269\n                        if (resp.status == 303 and resp.method != hdrs.METH_HEAD) or (\n                            resp.status in (301, 302) and resp.method == hdrs.METH_POST\n                        ):\n                            method = hdrs.METH_GET\n                            data = None\n                            if headers.get(hdrs.CONTENT_LENGTH):\n                                headers.pop(hdrs.CONTENT_LENGTH)\n\n                        r_url = resp.headers.get(hdrs.LOCATION) or resp.headers.get(\n                            hdrs.URI\n                        )\n                        if r_url is None:\n                            # see github.com/aio-libs/aiohttp/issues/2022\n                            break\n                        else:\n                            # reading from correct redirection\n                            # response is forbidden\n                            resp.release()\n\n                        try:\n                            parsed_redirect_url = URL(\n                                r_url, encoded=not self._requote_redirect_url\n                            )\n                        except ValueError as e:\n                            raise InvalidUrlRedirectClientError(\n                                r_url,\n                                \"Server attempted redirecting to a location that does not look like a URL\",\n                            ) from e\n\n                        scheme = parsed_redirect_url.scheme\n                        if scheme not in HTTP_AND_EMPTY_SCHEMA_SET:\n                            resp.close()\n                            raise NonHttpUrlRedirectClientError(r_url)\n                        elif not scheme:\n                            parsed_redirect_url = url.join(parsed_redirect_url)\n\n                        try:\n                            redirect_origin = parsed_redirect_url.origin()\n                        except ValueError as origin_val_err:\n                            raise InvalidUrlRedirectClientError(\n                                parsed_redirect_url,\n                                \"Invalid redirect URL origin\",\n                            ) from origin_val_err\n\n                        if url.origin() != redirect_origin:\n                            auth = None\n                            headers.pop(hdrs.AUTHORIZATION, None)\n\n                        url = parsed_redirect_url\n                        params = {}\n                        resp.release()\n                        continue\n\n                    break\n\n            # check response status\n            if raise_for_status is None:\n                raise_for_status = self._raise_for_status\n\n            if raise_for_status is None:\n                pass\n            elif callable(raise_for_status):\n                await raise_for_status(resp)\n            elif raise_for_status:\n                resp.raise_for_status()\n\n            # register connection\n            if handle is not None:\n                if resp.connection is not None:\n                    resp.connection.add_callback(handle.cancel)\n                else:\n                    handle.cancel()\n\n            resp._history = tuple(history)\n\n            for trace in traces:\n                await trace.send_request_end(\n                    method, url.update_query(params), headers, resp\n                )\n            return resp\n\n        except BaseException as e:\n            # cleanup timer\n            tm.close()\n            if handle:\n                handle.cancel()\n                handle = None\n\n            for trace in traces:\n                await trace.send_request_exception(\n                    method, url.update_query(params), headers, e\n                )\n            raise\n\n    def ws_connect(\n        self,\n        url: StrOrURL,\n        *,\n        method: str = hdrs.METH_GET,\n        protocols: Iterable[str] = (),\n        timeout: Union[ClientWSTimeout, _SENTINEL] = sentinel,\n        receive_timeout: Optional[float] = None,\n        autoclose: bool = True,\n        autoping: bool = True,\n        heartbeat: Optional[float] = None,\n        auth: Optional[BasicAuth] = None,\n        origin: Optional[str] = None,\n        params: Query = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        compress: int = 0,\n        max_msg_size: int = 4 * 1024 * 1024,\n    ) -> \"_WSRequestContextManager\":\n        \"\"\"Initiate websocket connection.\"\"\"\n        return _WSRequestContextManager(\n            self._ws_connect(\n                url,\n                method=method,\n                protocols=protocols,\n                timeout=timeout,\n                receive_timeout=receive_timeout,\n                autoclose=autoclose,\n                autoping=autoping,\n                heartbeat=heartbeat,\n                auth=auth,\n                origin=origin,\n                params=params,\n                headers=headers,\n                proxy=proxy,\n                proxy_auth=proxy_auth,\n                ssl=ssl,\n                verify_ssl=verify_ssl,\n                fingerprint=fingerprint,\n                ssl_context=ssl_context,\n                proxy_headers=proxy_headers,\n                compress=compress,\n                max_msg_size=max_msg_size,\n            )\n        )\n\n    async def _ws_connect(\n        self,\n        url: StrOrURL,\n        *,\n        method: str = hdrs.METH_GET,\n        protocols: Iterable[str] = (),\n        timeout: Union[ClientWSTimeout, _SENTINEL] = sentinel,\n        receive_timeout: Optional[float] = None,\n        autoclose: bool = True,\n        autoping: bool = True,\n        heartbeat: Optional[float] = None,\n        auth: Optional[BasicAuth] = None,\n        origin: Optional[str] = None,\n        params: Query = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        compress: int = 0,\n        max_msg_size: int = 4 * 1024 * 1024,\n    ) -> ClientWebSocketResponse:\n        if timeout is not sentinel:\n            if isinstance(timeout, ClientWSTimeout):\n                ws_timeout = timeout\n            else:\n                warnings.warn(\n                    \"parameter 'timeout' of type 'float' \"\n                    \"is deprecated, please use \"\n                    \"'timeout=ClientWSTimeout(ws_close=...)'\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n                ws_timeout = ClientWSTimeout(ws_close=timeout)\n        else:\n            ws_timeout = DEFAULT_WS_CLIENT_TIMEOUT\n        if receive_timeout is not None:\n            warnings.warn(\n                \"float parameter 'receive_timeout' \"\n                \"is deprecated, please use parameter \"\n                \"'timeout=ClientWSTimeout(ws_receive=...)'\",\n                DeprecationWarning,\n                stacklevel=2,\n            )\n            ws_timeout = attr.evolve(ws_timeout, ws_receive=receive_timeout)\n\n        if headers is None:\n            real_headers: CIMultiDict[str] = CIMultiDict()\n        else:\n            real_headers = CIMultiDict(headers)\n\n        default_headers = {\n            hdrs.UPGRADE: \"websocket\",\n            hdrs.CONNECTION: \"Upgrade\",\n            hdrs.SEC_WEBSOCKET_VERSION: \"13\",\n        }\n\n        for key, value in default_headers.items():\n            real_headers.setdefault(key, value)\n\n        sec_key = base64.b64encode(os.urandom(16))\n        real_headers[hdrs.SEC_WEBSOCKET_KEY] = sec_key.decode()\n\n        if protocols:\n            real_headers[hdrs.SEC_WEBSOCKET_PROTOCOL] = \",\".join(protocols)\n        if origin is not None:\n            real_headers[hdrs.ORIGIN] = origin\n        if compress:\n            extstr = ws_ext_gen(compress=compress)\n            real_headers[hdrs.SEC_WEBSOCKET_EXTENSIONS] = extstr\n\n        # For the sake of backward compatibility, if user passes in None, convert it to True\n        if ssl is None:\n            warnings.warn(\n                \"ssl=None is deprecated, please use ssl=True\",\n                DeprecationWarning,\n                stacklevel=2,\n            )\n            ssl = True\n        ssl = _merge_ssl_params(ssl, verify_ssl, ssl_context, fingerprint)\n\n        # send request\n        resp = await self.request(\n            method,\n            url,\n            params=params,\n            headers=real_headers,\n            read_until_eof=False,\n            auth=auth,\n            proxy=proxy,\n            proxy_auth=proxy_auth,\n            ssl=ssl,\n            proxy_headers=proxy_headers,\n        )\n\n        try:\n            # check handshake\n            if resp.status != 101:\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid response status\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            if resp.headers.get(hdrs.UPGRADE, \"\").lower() != \"websocket\":\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid upgrade header\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            if resp.headers.get(hdrs.CONNECTION, \"\").lower() != \"upgrade\":\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid connection header\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            # key calculation\n            r_key = resp.headers.get(hdrs.SEC_WEBSOCKET_ACCEPT, \"\")\n            match = base64.b64encode(hashlib.sha1(sec_key + WS_KEY).digest()).decode()\n            if r_key != match:\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid challenge response\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            # websocket protocol\n            protocol = None\n            if protocols and hdrs.SEC_WEBSOCKET_PROTOCOL in resp.headers:\n                resp_protocols = [\n                    proto.strip()\n                    for proto in resp.headers[hdrs.SEC_WEBSOCKET_PROTOCOL].split(\",\")\n                ]\n\n                for proto in resp_protocols:\n                    if proto in protocols:\n                        protocol = proto\n                        break\n\n            # websocket compress\n            notakeover = False\n            if compress:\n                compress_hdrs = resp.headers.get(hdrs.SEC_WEBSOCKET_EXTENSIONS)\n                if compress_hdrs:\n                    try:\n                        compress, notakeover = ws_ext_parse(compress_hdrs)\n                    except WSHandshakeError as exc:\n                        raise WSServerHandshakeError(\n                            resp.request_info,\n                            resp.history,\n                            message=exc.args[0],\n                            status=resp.status,\n                            headers=resp.headers,\n                        ) from exc\n                else:\n                    compress = 0\n                    notakeover = False\n\n            conn = resp.connection\n            assert conn is not None\n            conn_proto = conn.protocol\n            assert conn_proto is not None\n\n            # For WS connection the read_timeout must be either receive_timeout or greater\n            # None == no timeout, i.e. infinite timeout, so None is the max timeout possible\n            if ws_timeout.ws_receive is None:\n                # Reset regardless\n                conn_proto.read_timeout = None\n            elif conn_proto.read_timeout is not None:\n                conn_proto.read_timeout = max(\n                    ws_timeout.ws_receive, conn_proto.read_timeout\n                )\n\n            transport = conn.transport\n            assert transport is not None\n            reader: FlowControlDataQueue[WSMessage] = FlowControlDataQueue(\n                conn_proto, 2**16, loop=self._loop\n            )\n            conn_proto.set_parser(WebSocketReader(reader, max_msg_size), reader)\n            writer = WebSocketWriter(\n                conn_proto,\n                transport,\n                use_mask=True,\n                compress=compress,\n                notakeover=notakeover,\n            )\n        except BaseException:\n            resp.close()\n            raise\n        else:\n            return self._ws_response_class(\n                reader,\n                writer,\n                protocol,\n                resp,\n                ws_timeout,\n                autoclose,\n                autoping,\n                self._loop,\n                heartbeat=heartbeat,\n                compress=compress,\n                client_notakeover=notakeover,\n            )\n\n    def _prepare_headers(self, headers: Optional[LooseHeaders]) -> \"CIMultiDict[str]\":\n        \"\"\"Add default headers and transform it to CIMultiDict\"\"\"\n        # Convert headers to MultiDict\n        result = CIMultiDict(self._default_headers)\n        if headers:\n            if not isinstance(headers, (MultiDictProxy, MultiDict)):\n                headers = CIMultiDict(headers)\n            added_names: Set[str] = set()\n            for key, value in headers.items():\n                if key in added_names:\n                    result.add(key, value)\n                else:\n                    result[key] = value\n                    added_names.add(key)\n        return result\n\n    if sys.version_info >= (3, 11) and TYPE_CHECKING:\n\n        def get(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def options(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def head(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def post(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def put(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def patch(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def delete(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n    else:\n\n        def get(\n            self, url: StrOrURL, *, allow_redirects: bool = True, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP GET request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_GET, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def options(\n            self, url: StrOrURL, *, allow_redirects: bool = True, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP OPTIONS request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_OPTIONS, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def head(\n            self, url: StrOrURL, *, allow_redirects: bool = False, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP HEAD request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_HEAD, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def post(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP POST request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_POST, url, data=data, **kwargs)\n            )\n\n        def put(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP PUT request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_PUT, url, data=data, **kwargs)\n            )\n\n        def patch(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP PATCH request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_PATCH, url, data=data, **kwargs)\n            )\n\n        def delete(self, url: StrOrURL, **kwargs: Any) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP DELETE request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_DELETE, url, **kwargs)\n            )\n\n    async def close(self) -> None:\n        \"\"\"Close underlying connector.\n\n        Release all acquired resources.\n        \"\"\"\n        if not self.closed:\n            if self._connector is not None and self._connector_owner:\n                await self._connector.close()\n            self._connector = None\n\n    @property\n    def closed(self) -> bool:\n        \"\"\"Is client session closed.\n\n        A readonly property.\n        \"\"\"\n        return self._connector is None or self._connector.closed\n\n    @property\n    def connector(self) -> Optional[BaseConnector]:\n        \"\"\"Connector instance used for the session.\"\"\"\n        return self._connector\n\n    @property\n    def cookie_jar(self) -> AbstractCookieJar:\n        \"\"\"The session cookies.\"\"\"\n        return self._cookie_jar\n\n    @property\n    def version(self) -> Tuple[int, int]:\n        \"\"\"The session HTTP protocol version.\"\"\"\n        return self._version\n\n    @property\n    def requote_redirect_url(self) -> bool:\n        \"\"\"Do URL requoting on redirection handling.\"\"\"\n        return self._requote_redirect_url\n\n    @requote_redirect_url.setter\n    def requote_redirect_url(self, val: bool) -> None:\n        \"\"\"Do URL requoting on redirection handling.\"\"\"\n        warnings.warn(\n            \"session.requote_redirect_url modification is deprecated #2778\",\n            DeprecationWarning,\n            stacklevel=2,\n        )\n        self._requote_redirect_url = val\n\n    @property\n    def loop(self) -> asyncio.AbstractEventLoop:\n        \"\"\"Session's loop.\"\"\"\n        warnings.warn(\n            \"client.loop property is deprecated\", DeprecationWarning, stacklevel=2\n        )\n        return self._loop\n\n    @property\n    def timeout(self) -> ClientTimeout:\n        \"\"\"Timeout for the session.\"\"\"\n        return self._timeout\n\n    @property\n    def headers(self) -> \"CIMultiDict[str]\":\n        \"\"\"The default headers of the client session.\"\"\"\n        return self._default_headers\n\n    @property\n    def skip_auto_headers(self) -> FrozenSet[istr]:\n        \"\"\"Headers for which autogeneration should be skipped\"\"\"\n        return self._skip_auto_headers\n\n    @property\n    def auth(self) -> Optional[BasicAuth]:\n        \"\"\"An object that represents HTTP Basic Authorization\"\"\"\n        return self._default_auth\n\n    @property\n    def json_serialize(self) -> JSONEncoder:\n        \"\"\"Json serializer callable\"\"\"\n        return self._json_serialize\n\n    @property\n    def connector_owner(self) -> bool:\n        \"\"\"Should connector be closed on session closing\"\"\"\n        return self._connector_owner\n\n    @property\n    def raise_for_status(\n        self,\n    ) -> Union[bool, Callable[[ClientResponse], Awaitable[None]]]:\n        \"\"\"Should `ClientResponse.raise_for_status()` be called for each response.\"\"\"\n        return self._raise_for_status\n\n    @property\n    def auto_decompress(self) -> bool:\n        \"\"\"Should the body response be automatically decompressed.\"\"\"\n        return self._auto_decompress\n\n    @property\n    def trust_env(self) -> bool:\n        \"\"\"\n        Should proxies information from environment or netrc be trusted.\n\n        Information is from HTTP_PROXY / HTTPS_PROXY environment variables\n        or ~/.netrc file if present.\n        \"\"\"\n        return self._trust_env\n\n    @property\n    def trace_configs(self) -> List[TraceConfig]:\n        \"\"\"A list of TraceConfig instances used for client tracing\"\"\"\n        return self._trace_configs\n\n    def detach(self) -> None:\n        \"\"\"Detach connector from session without closing the former.\n\n        Session is switched to closed state anyway.\n        \"\"\"\n        self._connector = None\n\n    def __enter__(self) -> None:\n        raise TypeError(\"Use async with instead\")\n\n    def __exit__(\n        self,\n        exc_type: Optional[Type[BaseException]],\n        exc_val: Optional[BaseException],\n        exc_tb: Optional[TracebackType],\n    ) -> None:\n        # __exit__ should exist in pair with __enter__ but never executed\n        pass  # pragma: no cover\n\n    async def __aenter__(self) -> \"ClientSession\":\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        await self.close()",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 263,
                            "end_lineno": 404,
                            "parent": {
                                "file_name": "aiohttp/client.py",
                                "type": "class",
                                "name": "ClientSession",
                                "content": "class ClientSession:\n    \"\"\"First-class interface for making HTTP requests.\"\"\"\n\n    ATTRS = frozenset(\n        [\n            \"_base_url\",\n            \"_source_traceback\",\n            \"_connector\",\n            \"requote_redirect_url\",\n            \"_loop\",\n            \"_cookie_jar\",\n            \"_connector_owner\",\n            \"_default_auth\",\n            \"_version\",\n            \"_json_serialize\",\n            \"_requote_redirect_url\",\n            \"_timeout\",\n            \"_raise_for_status\",\n            \"_auto_decompress\",\n            \"_trust_env\",\n            \"_default_headers\",\n            \"_skip_auto_headers\",\n            \"_request_class\",\n            \"_response_class\",\n            \"_ws_response_class\",\n            \"_trace_configs\",\n            \"_read_bufsize\",\n            \"_max_line_size\",\n            \"_max_field_size\",\n            \"_resolve_charset\",\n            \"_default_proxy\",\n            \"_default_proxy_auth\",\n        ]\n    )\n\n    _source_traceback: Optional[traceback.StackSummary] = None\n    _connector: Optional[BaseConnector] = None\n\n    def __init__(\n        self,\n        base_url: Optional[StrOrURL] = None,\n        *,\n        connector: Optional[BaseConnector] = None,\n        loop: Optional[asyncio.AbstractEventLoop] = None,\n        cookies: Optional[LooseCookies] = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        skip_auto_headers: Optional[Iterable[str]] = None,\n        auth: Optional[BasicAuth] = None,\n        json_serialize: JSONEncoder = json.dumps,\n        request_class: Type[ClientRequest] = ClientRequest,\n        response_class: Type[ClientResponse] = ClientResponse,\n        ws_response_class: Type[ClientWebSocketResponse] = ClientWebSocketResponse,\n        version: HttpVersion = http.HttpVersion11,\n        cookie_jar: Optional[AbstractCookieJar] = None,\n        connector_owner: bool = True,\n        raise_for_status: Union[\n            bool, Callable[[ClientResponse], Awaitable[None]]\n        ] = False,\n        read_timeout: Union[float, _SENTINEL] = sentinel,\n        conn_timeout: Optional[float] = None,\n        timeout: Union[object, ClientTimeout] = sentinel,\n        auto_decompress: bool = True,\n        trust_env: bool = False,\n        requote_redirect_url: bool = True,\n        trace_configs: Optional[List[TraceConfig]] = None,\n        read_bufsize: int = 2**16,\n        max_line_size: int = 8190,\n        max_field_size: int = 8190,\n        fallback_charset_resolver: _CharsetResolver = lambda r, b: \"utf-8\",\n    ) -> None:\n        # We initialise _connector to None immediately, as it's referenced in __del__()\n        # and could cause issues if an exception occurs during initialisation.\n        self._connector: Optional[BaseConnector] = None\n\n        if loop is None:\n            if connector is not None:\n                loop = connector._loop\n\n        loop = loop or asyncio.get_running_loop()\n\n        if base_url is None or isinstance(base_url, URL):\n            self._base_url: Optional[URL] = base_url\n        else:\n            self._base_url = URL(base_url)\n            assert (\n                self._base_url.origin() == self._base_url\n            ), \"Only absolute URLs without path part are supported\"\n\n        if timeout is sentinel or timeout is None:\n            self._timeout = DEFAULT_TIMEOUT\n            if read_timeout is not sentinel:\n                warnings.warn(\n                    \"read_timeout is deprecated, use timeout argument instead\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n                self._timeout = attr.evolve(self._timeout, total=read_timeout)\n            if conn_timeout is not None:\n                self._timeout = attr.evolve(self._timeout, connect=conn_timeout)\n                warnings.warn(\n                    \"conn_timeout is deprecated, use timeout argument instead\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n        else:\n            if not isinstance(timeout, ClientTimeout):\n                raise ValueError(\n                    f\"timeout parameter cannot be of {type(timeout)} type, \"\n                    \"please use 'timeout=ClientTimeout(...)'\",\n                )\n            self._timeout = timeout\n            if read_timeout is not sentinel:\n                raise ValueError(\n                    \"read_timeout and timeout parameters \"\n                    \"conflict, please setup \"\n                    \"timeout.read\"\n                )\n            if conn_timeout is not None:\n                raise ValueError(\n                    \"conn_timeout and timeout parameters \"\n                    \"conflict, please setup \"\n                    \"timeout.connect\"\n                )\n\n        if connector is None:\n            connector = TCPConnector(loop=loop)\n\n        if connector._loop is not loop:\n            raise RuntimeError(\"Session and connector has to use same event loop\")\n\n        self._loop = loop\n\n        if loop.get_debug():\n            self._source_traceback = traceback.extract_stack(sys._getframe(1))\n\n        if cookie_jar is None:\n            cookie_jar = CookieJar(loop=loop)\n        self._cookie_jar = cookie_jar\n\n        if cookies is not None:\n            self._cookie_jar.update_cookies(cookies)\n\n        self._connector = connector\n        self._connector_owner = connector_owner\n        self._default_auth = auth\n        self._version = version\n        self._json_serialize = json_serialize\n        self._raise_for_status = raise_for_status\n        self._auto_decompress = auto_decompress\n        self._trust_env = trust_env\n        self._requote_redirect_url = requote_redirect_url\n        self._read_bufsize = read_bufsize\n        self._max_line_size = max_line_size\n        self._max_field_size = max_field_size\n\n        # Convert to list of tuples\n        if headers:\n            real_headers: CIMultiDict[str] = CIMultiDict(headers)\n        else:\n            real_headers = CIMultiDict()\n        self._default_headers: CIMultiDict[str] = real_headers\n        if skip_auto_headers is not None:\n            self._skip_auto_headers = frozenset(istr(i) for i in skip_auto_headers)\n        else:\n            self._skip_auto_headers = frozenset()\n\n        self._request_class = request_class\n        self._response_class = response_class\n        self._ws_response_class = ws_response_class\n\n        self._trace_configs = trace_configs or []\n        for trace_config in self._trace_configs:\n            trace_config.freeze()\n\n        self._resolve_charset = fallback_charset_resolver\n\n        self._default_proxy = proxy\n        self._default_proxy_auth = proxy_auth\n\n    def __init_subclass__(cls: Type[\"ClientSession\"]) -> None:\n        warnings.warn(\n            \"Inheritance class {} from ClientSession \"\n            \"is discouraged\".format(cls.__name__),\n            DeprecationWarning,\n            stacklevel=2,\n        )\n\n    if DEBUG:\n\n        def __setattr__(self, name: str, val: Any) -> None:\n            if name not in self.ATTRS:\n                warnings.warn(\n                    \"Setting custom ClientSession.{} attribute \"\n                    \"is discouraged\".format(name),\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n            super().__setattr__(name, val)\n\n    def __del__(self, _warnings: Any = warnings) -> None:\n        if not self.closed:\n            kwargs = {\"source\": self}\n            _warnings.warn(\n                f\"Unclosed client session {self!r}\", ResourceWarning, **kwargs\n            )\n            context = {\"client_session\": self, \"message\": \"Unclosed client session\"}\n            if self._source_traceback is not None:\n                context[\"source_traceback\"] = self._source_traceback\n            self._loop.call_exception_handler(context)\n\n    if sys.version_info >= (3, 11) and TYPE_CHECKING:\n\n        def request(\n            self,\n            method: str,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n    else:\n\n        def request(\n            self, method: str, url: StrOrURL, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP request.\"\"\"\n            return _RequestContextManager(self._request(method, url, **kwargs))\n\n    def _build_url(self, str_or_url: StrOrURL) -> URL:\n        url = URL(str_or_url)\n        if self._base_url is None:\n            return url\n        else:\n            assert not url.absolute and url.path.startswith(\"/\")\n            return self._base_url.join(url)\n\n    async def _request(\n        self,\n        method: str,\n        str_or_url: StrOrURL,\n        *,\n        params: Query = None,\n        data: Any = None,\n        json: Any = None,\n        cookies: Optional[LooseCookies] = None,\n        headers: Optional[LooseHeaders] = None,\n        skip_auto_headers: Optional[Iterable[str]] = None,\n        auth: Optional[BasicAuth] = None,\n        allow_redirects: bool = True,\n        max_redirects: int = 10,\n        compress: Union[str, bool, None] = None,\n        chunked: Optional[bool] = None,\n        expect100: bool = False,\n        raise_for_status: Union[\n            None, bool, Callable[[ClientResponse], Awaitable[None]]\n        ] = None,\n        read_until_eof: bool = True,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        timeout: Union[ClientTimeout, _SENTINEL] = sentinel,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        server_hostname: Optional[str] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        trace_request_ctx: Optional[Mapping[str, str]] = None,\n        read_bufsize: Optional[int] = None,\n        auto_decompress: Optional[bool] = None,\n        max_line_size: Optional[int] = None,\n        max_field_size: Optional[int] = None,\n    ) -> ClientResponse:\n\n        # NOTE: timeout clamps existing connect and read timeouts.  We cannot\n        # set the default to None because we need to detect if the user wants\n        # to use the existing timeouts by setting timeout to None.\n\n        if self.closed:\n            raise RuntimeError(\"Session is closed\")\n\n        ssl = _merge_ssl_params(ssl, verify_ssl, ssl_context, fingerprint)\n\n        if data is not None and json is not None:\n            raise ValueError(\n                \"data and json parameters can not be used at the same time\"\n            )\n        elif json is not None:\n            data = payload.JsonPayload(json, dumps=self._json_serialize)\n\n        if not isinstance(chunked, bool) and chunked is not None:\n            warnings.warn(\"Chunk size is deprecated #1615\", DeprecationWarning)\n\n        redirects = 0\n        history = []\n        version = self._version\n        params = params or {}\n\n        # Merge with default headers and transform to CIMultiDict\n        headers = self._prepare_headers(headers)\n\n        try:\n            url = self._build_url(str_or_url)\n        except ValueError as e:\n            raise InvalidUrlClientError(str_or_url) from e\n\n        assert self._connector is not None\n        if url.scheme not in self._connector.allowed_protocol_schema_set:\n            raise NonHttpUrlClientError(url)\n\n        skip_headers = set(self._skip_auto_headers)\n        if skip_auto_headers is not None:\n            for i in skip_auto_headers:\n                skip_headers.add(istr(i))\n\n        if proxy is None:\n            proxy = self._default_proxy\n        if proxy_auth is None:\n            proxy_auth = self._default_proxy_auth\n\n        if proxy is None:\n            proxy_headers = None\n        else:\n            proxy_headers = self._prepare_headers(proxy_headers)\n            try:\n                proxy = URL(proxy)\n            except ValueError as e:\n                raise InvalidURL(proxy) from e\n\n        if timeout is sentinel:\n            real_timeout: ClientTimeout = self._timeout\n        else:\n            if not isinstance(timeout, ClientTimeout):\n                real_timeout = ClientTimeout(total=timeout)\n            else:\n                real_timeout = timeout\n        # timeout is cumulative for all request operations\n        # (request, redirects, responses, data consuming)\n        tm = TimeoutHandle(\n            self._loop, real_timeout.total, ceil_threshold=real_timeout.ceil_threshold\n        )\n        handle = tm.start()\n\n        if read_bufsize is None:\n            read_bufsize = self._read_bufsize\n\n        if auto_decompress is None:\n            auto_decompress = self._auto_decompress\n\n        if max_line_size is None:\n            max_line_size = self._max_line_size\n\n        if max_field_size is None:\n            max_field_size = self._max_field_size\n\n        traces = [\n            Trace(\n                self,\n                trace_config,\n                trace_config.trace_config_ctx(trace_request_ctx=trace_request_ctx),\n            )\n            for trace_config in self._trace_configs\n        ]\n\n        for trace in traces:\n            await trace.send_request_start(method, url.update_query(params), headers)\n\n        timer = tm.timer()\n        try:\n            with timer:\n                # https://www.rfc-editor.org/rfc/rfc9112.html#name-retrying-requests\n                retry_persistent_connection = method in IDEMPOTENT_METHODS\n                while True:\n                    url, auth_from_url = strip_auth_from_url(url)\n                    if not url.raw_host:\n                        # NOTE: Bail early, otherwise, causes `InvalidURL` through\n                        # NOTE: `self._request_class()` below.\n                        err_exc_cls = (\n                            InvalidUrlRedirectClientError\n                            if redirects\n                            else InvalidUrlClientError\n                        )\n                        raise err_exc_cls(url)\n                    if auth and auth_from_url:\n                        raise ValueError(\n                            \"Cannot combine AUTH argument with \"\n                            \"credentials encoded in URL\"\n                        )\n\n                    if auth is None:\n                        auth = auth_from_url\n\n                    if auth is None and (\n                        not self._base_url or self._base_url.origin() == url.origin()\n                    ):\n                        auth = self._default_auth\n                    # It would be confusing if we support explicit\n                    # Authorization header with auth argument\n                    if (\n                        headers is not None\n                        and auth is not None\n                        and hdrs.AUTHORIZATION in headers\n                    ):\n                        raise ValueError(\n                            \"Cannot combine AUTHORIZATION header \"\n                            \"with AUTH argument or credentials \"\n                            \"encoded in URL\"\n                        )\n\n                    all_cookies = self._cookie_jar.filter_cookies(url)\n\n                    if cookies is not None:\n                        tmp_cookie_jar = CookieJar()\n                        tmp_cookie_jar.update_cookies(cookies)\n                        req_cookies = tmp_cookie_jar.filter_cookies(url)\n                        if req_cookies:\n                            all_cookies.load(req_cookies)\n\n                    if proxy is not None:\n                        proxy = URL(proxy)\n                    elif self._trust_env:\n                        with suppress(LookupError):\n                            proxy, proxy_auth = get_env_proxy_for_url(url)\n\n                    req = self._request_class(\n                        method,\n                        url,\n                        params=params,\n                        headers=headers,\n                        skip_auto_headers=skip_headers if skip_headers else None,\n                        data=data,\n                        cookies=all_cookies,\n                        auth=auth,\n                        version=version,\n                        compress=compress,\n                        chunked=chunked,\n                        expect100=expect100,\n                        loop=self._loop,\n                        response_class=self._response_class,\n                        proxy=proxy,\n                        proxy_auth=proxy_auth,\n                        timer=timer,\n                        session=self,\n                        ssl=ssl if ssl is not None else True,\n                        server_hostname=server_hostname,\n                        proxy_headers=proxy_headers,\n                        traces=traces,\n                        trust_env=self.trust_env,\n                    )\n\n                    # connection timeout\n                    try:\n                        async with ceil_timeout(\n                            real_timeout.connect,\n                            ceil_threshold=real_timeout.ceil_threshold,\n                        ):\n                            conn = await self._connector.connect(\n                                req, traces=traces, timeout=real_timeout\n                            )\n                    except asyncio.TimeoutError as exc:\n                        raise ConnectionTimeoutError(\n                            f\"Connection timeout to host {url}\"\n                        ) from exc\n\n                    assert conn.transport is not None\n\n                    assert conn.protocol is not None\n                    conn.protocol.set_response_params(\n                        timer=timer,\n                        skip_payload=method_must_be_empty_body(method),\n                        read_until_eof=read_until_eof,\n                        auto_decompress=auto_decompress,\n                        read_timeout=real_timeout.sock_read,\n                        read_bufsize=read_bufsize,\n                        timeout_ceil_threshold=self._connector._timeout_ceil_threshold,\n                        max_line_size=max_line_size,\n                        max_field_size=max_field_size,\n                    )\n\n                    try:\n                        try:\n                            resp = await req.send(conn)\n                            try:\n                                await resp.start(conn)\n                            except BaseException:\n                                resp.close()\n                                raise\n                        except BaseException:\n                            conn.close()\n                            raise\n                    except (ClientOSError, ServerDisconnectedError):\n                        if retry_persistent_connection:\n                            retry_persistent_connection = False\n                            continue\n                        raise\n                    except ClientError:\n                        raise\n                    except OSError as exc:\n                        if exc.errno is None and isinstance(exc, asyncio.TimeoutError):\n                            raise\n                        raise ClientOSError(*exc.args) from exc\n\n                    self._cookie_jar.update_cookies(resp.cookies, resp.url)\n\n                    # redirects\n                    if resp.status in (301, 302, 303, 307, 308) and allow_redirects:\n\n                        for trace in traces:\n                            await trace.send_request_redirect(\n                                method, url.update_query(params), headers, resp\n                            )\n\n                        redirects += 1\n                        history.append(resp)\n                        if max_redirects and redirects >= max_redirects:\n                            resp.close()\n                            raise TooManyRedirects(\n                                history[0].request_info, tuple(history)\n                            )\n\n                        # For 301 and 302, mimic IE, now changed in RFC\n                        # https://github.com/kennethreitz/requests/pull/269\n                        if (resp.status == 303 and resp.method != hdrs.METH_HEAD) or (\n                            resp.status in (301, 302) and resp.method == hdrs.METH_POST\n                        ):\n                            method = hdrs.METH_GET\n                            data = None\n                            if headers.get(hdrs.CONTENT_LENGTH):\n                                headers.pop(hdrs.CONTENT_LENGTH)\n\n                        r_url = resp.headers.get(hdrs.LOCATION) or resp.headers.get(\n                            hdrs.URI\n                        )\n                        if r_url is None:\n                            # see github.com/aio-libs/aiohttp/issues/2022\n                            break\n                        else:\n                            # reading from correct redirection\n                            # response is forbidden\n                            resp.release()\n\n                        try:\n                            parsed_redirect_url = URL(\n                                r_url, encoded=not self._requote_redirect_url\n                            )\n                        except ValueError as e:\n                            raise InvalidUrlRedirectClientError(\n                                r_url,\n                                \"Server attempted redirecting to a location that does not look like a URL\",\n                            ) from e\n\n                        scheme = parsed_redirect_url.scheme\n                        if scheme not in HTTP_AND_EMPTY_SCHEMA_SET:\n                            resp.close()\n                            raise NonHttpUrlRedirectClientError(r_url)\n                        elif not scheme:\n                            parsed_redirect_url = url.join(parsed_redirect_url)\n\n                        try:\n                            redirect_origin = parsed_redirect_url.origin()\n                        except ValueError as origin_val_err:\n                            raise InvalidUrlRedirectClientError(\n                                parsed_redirect_url,\n                                \"Invalid redirect URL origin\",\n                            ) from origin_val_err\n\n                        if url.origin() != redirect_origin:\n                            auth = None\n                            headers.pop(hdrs.AUTHORIZATION, None)\n\n                        url = parsed_redirect_url\n                        params = {}\n                        resp.release()\n                        continue\n\n                    break\n\n            # check response status\n            if raise_for_status is None:\n                raise_for_status = self._raise_for_status\n\n            if raise_for_status is None:\n                pass\n            elif callable(raise_for_status):\n                await raise_for_status(resp)\n            elif raise_for_status:\n                resp.raise_for_status()\n\n            # register connection\n            if handle is not None:\n                if resp.connection is not None:\n                    resp.connection.add_callback(handle.cancel)\n                else:\n                    handle.cancel()\n\n            resp._history = tuple(history)\n\n            for trace in traces:\n                await trace.send_request_end(\n                    method, url.update_query(params), headers, resp\n                )\n            return resp\n\n        except BaseException as e:\n            # cleanup timer\n            tm.close()\n            if handle:\n                handle.cancel()\n                handle = None\n\n            for trace in traces:\n                await trace.send_request_exception(\n                    method, url.update_query(params), headers, e\n                )\n            raise\n\n    def ws_connect(\n        self,\n        url: StrOrURL,\n        *,\n        method: str = hdrs.METH_GET,\n        protocols: Iterable[str] = (),\n        timeout: Union[ClientWSTimeout, _SENTINEL] = sentinel,\n        receive_timeout: Optional[float] = None,\n        autoclose: bool = True,\n        autoping: bool = True,\n        heartbeat: Optional[float] = None,\n        auth: Optional[BasicAuth] = None,\n        origin: Optional[str] = None,\n        params: Query = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        compress: int = 0,\n        max_msg_size: int = 4 * 1024 * 1024,\n    ) -> \"_WSRequestContextManager\":\n        \"\"\"Initiate websocket connection.\"\"\"\n        return _WSRequestContextManager(\n            self._ws_connect(\n                url,\n                method=method,\n                protocols=protocols,\n                timeout=timeout,\n                receive_timeout=receive_timeout,\n                autoclose=autoclose,\n                autoping=autoping,\n                heartbeat=heartbeat,\n                auth=auth,\n                origin=origin,\n                params=params,\n                headers=headers,\n                proxy=proxy,\n                proxy_auth=proxy_auth,\n                ssl=ssl,\n                verify_ssl=verify_ssl,\n                fingerprint=fingerprint,\n                ssl_context=ssl_context,\n                proxy_headers=proxy_headers,\n                compress=compress,\n                max_msg_size=max_msg_size,\n            )\n        )\n\n    async def _ws_connect(\n        self,\n        url: StrOrURL,\n        *,\n        method: str = hdrs.METH_GET,\n        protocols: Iterable[str] = (),\n        timeout: Union[ClientWSTimeout, _SENTINEL] = sentinel,\n        receive_timeout: Optional[float] = None,\n        autoclose: bool = True,\n        autoping: bool = True,\n        heartbeat: Optional[float] = None,\n        auth: Optional[BasicAuth] = None,\n        origin: Optional[str] = None,\n        params: Query = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        compress: int = 0,\n        max_msg_size: int = 4 * 1024 * 1024,\n    ) -> ClientWebSocketResponse:\n        if timeout is not sentinel:\n            if isinstance(timeout, ClientWSTimeout):\n                ws_timeout = timeout\n            else:\n                warnings.warn(\n                    \"parameter 'timeout' of type 'float' \"\n                    \"is deprecated, please use \"\n                    \"'timeout=ClientWSTimeout(ws_close=...)'\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n                ws_timeout = ClientWSTimeout(ws_close=timeout)\n        else:\n            ws_timeout = DEFAULT_WS_CLIENT_TIMEOUT\n        if receive_timeout is not None:\n            warnings.warn(\n                \"float parameter 'receive_timeout' \"\n                \"is deprecated, please use parameter \"\n                \"'timeout=ClientWSTimeout(ws_receive=...)'\",\n                DeprecationWarning,\n                stacklevel=2,\n            )\n            ws_timeout = attr.evolve(ws_timeout, ws_receive=receive_timeout)\n\n        if headers is None:\n            real_headers: CIMultiDict[str] = CIMultiDict()\n        else:\n            real_headers = CIMultiDict(headers)\n\n        default_headers = {\n            hdrs.UPGRADE: \"websocket\",\n            hdrs.CONNECTION: \"Upgrade\",\n            hdrs.SEC_WEBSOCKET_VERSION: \"13\",\n        }\n\n        for key, value in default_headers.items():\n            real_headers.setdefault(key, value)\n\n        sec_key = base64.b64encode(os.urandom(16))\n        real_headers[hdrs.SEC_WEBSOCKET_KEY] = sec_key.decode()\n\n        if protocols:\n            real_headers[hdrs.SEC_WEBSOCKET_PROTOCOL] = \",\".join(protocols)\n        if origin is not None:\n            real_headers[hdrs.ORIGIN] = origin\n        if compress:\n            extstr = ws_ext_gen(compress=compress)\n            real_headers[hdrs.SEC_WEBSOCKET_EXTENSIONS] = extstr\n\n        # For the sake of backward compatibility, if user passes in None, convert it to True\n        if ssl is None:\n            warnings.warn(\n                \"ssl=None is deprecated, please use ssl=True\",\n                DeprecationWarning,\n                stacklevel=2,\n            )\n            ssl = True\n        ssl = _merge_ssl_params(ssl, verify_ssl, ssl_context, fingerprint)\n\n        # send request\n        resp = await self.request(\n            method,\n            url,\n            params=params,\n            headers=real_headers,\n            read_until_eof=False,\n            auth=auth,\n            proxy=proxy,\n            proxy_auth=proxy_auth,\n            ssl=ssl,\n            proxy_headers=proxy_headers,\n        )\n\n        try:\n            # check handshake\n            if resp.status != 101:\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid response status\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            if resp.headers.get(hdrs.UPGRADE, \"\").lower() != \"websocket\":\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid upgrade header\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            if resp.headers.get(hdrs.CONNECTION, \"\").lower() != \"upgrade\":\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid connection header\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            # key calculation\n            r_key = resp.headers.get(hdrs.SEC_WEBSOCKET_ACCEPT, \"\")\n            match = base64.b64encode(hashlib.sha1(sec_key + WS_KEY).digest()).decode()\n            if r_key != match:\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid challenge response\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            # websocket protocol\n            protocol = None\n            if protocols and hdrs.SEC_WEBSOCKET_PROTOCOL in resp.headers:\n                resp_protocols = [\n                    proto.strip()\n                    for proto in resp.headers[hdrs.SEC_WEBSOCKET_PROTOCOL].split(\",\")\n                ]\n\n                for proto in resp_protocols:\n                    if proto in protocols:\n                        protocol = proto\n                        break\n\n            # websocket compress\n            notakeover = False\n            if compress:\n                compress_hdrs = resp.headers.get(hdrs.SEC_WEBSOCKET_EXTENSIONS)\n                if compress_hdrs:\n                    try:\n                        compress, notakeover = ws_ext_parse(compress_hdrs)\n                    except WSHandshakeError as exc:\n                        raise WSServerHandshakeError(\n                            resp.request_info,\n                            resp.history,\n                            message=exc.args[0],\n                            status=resp.status,\n                            headers=resp.headers,\n                        ) from exc\n                else:\n                    compress = 0\n                    notakeover = False\n\n            conn = resp.connection\n            assert conn is not None\n            conn_proto = conn.protocol\n            assert conn_proto is not None\n\n            # For WS connection the read_timeout must be either receive_timeout or greater\n            # None == no timeout, i.e. infinite timeout, so None is the max timeout possible\n            if ws_timeout.ws_receive is None:\n                # Reset regardless\n                conn_proto.read_timeout = None\n            elif conn_proto.read_timeout is not None:\n                conn_proto.read_timeout = max(\n                    ws_timeout.ws_receive, conn_proto.read_timeout\n                )\n\n            transport = conn.transport\n            assert transport is not None\n            reader: FlowControlDataQueue[WSMessage] = FlowControlDataQueue(\n                conn_proto, 2**16, loop=self._loop\n            )\n            conn_proto.set_parser(WebSocketReader(reader, max_msg_size), reader)\n            writer = WebSocketWriter(\n                conn_proto,\n                transport,\n                use_mask=True,\n                compress=compress,\n                notakeover=notakeover,\n            )\n        except BaseException:\n            resp.close()\n            raise\n        else:\n            return self._ws_response_class(\n                reader,\n                writer,\n                protocol,\n                resp,\n                ws_timeout,\n                autoclose,\n                autoping,\n                self._loop,\n                heartbeat=heartbeat,\n                compress=compress,\n                client_notakeover=notakeover,\n            )\n\n    def _prepare_headers(self, headers: Optional[LooseHeaders]) -> \"CIMultiDict[str]\":\n        \"\"\"Add default headers and transform it to CIMultiDict\"\"\"\n        # Convert headers to MultiDict\n        result = CIMultiDict(self._default_headers)\n        if headers:\n            if not isinstance(headers, (MultiDictProxy, MultiDict)):\n                headers = CIMultiDict(headers)\n            added_names: Set[str] = set()\n            for key, value in headers.items():\n                if key in added_names:\n                    result.add(key, value)\n                else:\n                    result[key] = value\n                    added_names.add(key)\n        return result\n\n    if sys.version_info >= (3, 11) and TYPE_CHECKING:\n\n        def get(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def options(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def head(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def post(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def put(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def patch(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def delete(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n    else:\n\n        def get(\n            self, url: StrOrURL, *, allow_redirects: bool = True, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP GET request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_GET, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def options(\n            self, url: StrOrURL, *, allow_redirects: bool = True, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP OPTIONS request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_OPTIONS, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def head(\n            self, url: StrOrURL, *, allow_redirects: bool = False, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP HEAD request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_HEAD, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def post(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP POST request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_POST, url, data=data, **kwargs)\n            )\n\n        def put(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP PUT request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_PUT, url, data=data, **kwargs)\n            )\n\n        def patch(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP PATCH request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_PATCH, url, data=data, **kwargs)\n            )\n\n        def delete(self, url: StrOrURL, **kwargs: Any) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP DELETE request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_DELETE, url, **kwargs)\n            )\n\n    async def close(self) -> None:\n        \"\"\"Close underlying connector.\n\n        Release all acquired resources.\n        \"\"\"\n        if not self.closed:\n            if self._connector is not None and self._connector_owner:\n                await self._connector.close()\n            self._connector = None\n\n    @property\n    def closed(self) -> bool:\n        \"\"\"Is client session closed.\n\n        A readonly property.\n        \"\"\"\n        return self._connector is None or self._connector.closed\n\n    @property\n    def connector(self) -> Optional[BaseConnector]:\n        \"\"\"Connector instance used for the session.\"\"\"\n        return self._connector\n\n    @property\n    def cookie_jar(self) -> AbstractCookieJar:\n        \"\"\"The session cookies.\"\"\"\n        return self._cookie_jar\n\n    @property\n    def version(self) -> Tuple[int, int]:\n        \"\"\"The session HTTP protocol version.\"\"\"\n        return self._version\n\n    @property\n    def requote_redirect_url(self) -> bool:\n        \"\"\"Do URL requoting on redirection handling.\"\"\"\n        return self._requote_redirect_url\n\n    @requote_redirect_url.setter\n    def requote_redirect_url(self, val: bool) -> None:\n        \"\"\"Do URL requoting on redirection handling.\"\"\"\n        warnings.warn(\n            \"session.requote_redirect_url modification is deprecated #2778\",\n            DeprecationWarning,\n            stacklevel=2,\n        )\n        self._requote_redirect_url = val\n\n    @property\n    def loop(self) -> asyncio.AbstractEventLoop:\n        \"\"\"Session's loop.\"\"\"\n        warnings.warn(\n            \"client.loop property is deprecated\", DeprecationWarning, stacklevel=2\n        )\n        return self._loop\n\n    @property\n    def timeout(self) -> ClientTimeout:\n        \"\"\"Timeout for the session.\"\"\"\n        return self._timeout\n\n    @property\n    def headers(self) -> \"CIMultiDict[str]\":\n        \"\"\"The default headers of the client session.\"\"\"\n        return self._default_headers\n\n    @property\n    def skip_auto_headers(self) -> FrozenSet[istr]:\n        \"\"\"Headers for which autogeneration should be skipped\"\"\"\n        return self._skip_auto_headers\n\n    @property\n    def auth(self) -> Optional[BasicAuth]:\n        \"\"\"An object that represents HTTP Basic Authorization\"\"\"\n        return self._default_auth\n\n    @property\n    def json_serialize(self) -> JSONEncoder:\n        \"\"\"Json serializer callable\"\"\"\n        return self._json_serialize\n\n    @property\n    def connector_owner(self) -> bool:\n        \"\"\"Should connector be closed on session closing\"\"\"\n        return self._connector_owner\n\n    @property\n    def raise_for_status(\n        self,\n    ) -> Union[bool, Callable[[ClientResponse], Awaitable[None]]]:\n        \"\"\"Should `ClientResponse.raise_for_status()` be called for each response.\"\"\"\n        return self._raise_for_status\n\n    @property\n    def auto_decompress(self) -> bool:\n        \"\"\"Should the body response be automatically decompressed.\"\"\"\n        return self._auto_decompress\n\n    @property\n    def trust_env(self) -> bool:\n        \"\"\"\n        Should proxies information from environment or netrc be trusted.\n\n        Information is from HTTP_PROXY / HTTPS_PROXY environment variables\n        or ~/.netrc file if present.\n        \"\"\"\n        return self._trust_env\n\n    @property\n    def trace_configs(self) -> List[TraceConfig]:\n        \"\"\"A list of TraceConfig instances used for client tracing\"\"\"\n        return self._trace_configs\n\n    def detach(self) -> None:\n        \"\"\"Detach connector from session without closing the former.\n\n        Session is switched to closed state anyway.\n        \"\"\"\n        self._connector = None\n\n    def __enter__(self) -> None:\n        raise TypeError(\"Use async with instead\")\n\n    def __exit__(\n        self,\n        exc_type: Optional[Type[BaseException]],\n        exc_val: Optional[BaseException],\n        exc_tb: Optional[TracebackType],\n    ) -> None:\n        # __exit__ should exist in pair with __enter__ but never executed\n        pass  # pragma: no cover\n\n    async def __aenter__(self) -> \"ClientSession\":\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        await self.close()",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 225,
                                "end_lineno": 1373,
                                "parent": null
                            }
                        },
                        {
                            "file_name": "aiohttp/client.py",
                            "type": "class",
                            "name": "ClientSession",
                            "content": "class ClientSession:\n    \"\"\"First-class interface for making HTTP requests.\"\"\"\n\n    ATTRS = frozenset(\n        [\n            \"_base_url\",\n            \"_source_traceback\",\n            \"_connector\",\n            \"requote_redirect_url\",\n            \"_loop\",\n            \"_cookie_jar\",\n            \"_connector_owner\",\n            \"_default_auth\",\n            \"_version\",\n            \"_json_serialize\",\n            \"_requote_redirect_url\",\n            \"_timeout\",\n            \"_raise_for_status\",\n            \"_auto_decompress\",\n            \"_trust_env\",\n            \"_default_headers\",\n            \"_skip_auto_headers\",\n            \"_request_class\",\n            \"_response_class\",\n            \"_ws_response_class\",\n            \"_trace_configs\",\n            \"_read_bufsize\",\n            \"_max_line_size\",\n            \"_max_field_size\",\n            \"_resolve_charset\",\n            \"_default_proxy\",\n            \"_default_proxy_auth\",\n        ]\n    )\n\n    _source_traceback: Optional[traceback.StackSummary] = None\n    _connector: Optional[BaseConnector] = None\n\n    def __init__(\n        self,\n        base_url: Optional[StrOrURL] = None,\n        *,\n        connector: Optional[BaseConnector] = None,\n        loop: Optional[asyncio.AbstractEventLoop] = None,\n        cookies: Optional[LooseCookies] = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        skip_auto_headers: Optional[Iterable[str]] = None,\n        auth: Optional[BasicAuth] = None,\n        json_serialize: JSONEncoder = json.dumps,\n        request_class: Type[ClientRequest] = ClientRequest,\n        response_class: Type[ClientResponse] = ClientResponse,\n        ws_response_class: Type[ClientWebSocketResponse] = ClientWebSocketResponse,\n        version: HttpVersion = http.HttpVersion11,\n        cookie_jar: Optional[AbstractCookieJar] = None,\n        connector_owner: bool = True,\n        raise_for_status: Union[\n            bool, Callable[[ClientResponse], Awaitable[None]]\n        ] = False,\n        read_timeout: Union[float, _SENTINEL] = sentinel,\n        conn_timeout: Optional[float] = None,\n        timeout: Union[object, ClientTimeout] = sentinel,\n        auto_decompress: bool = True,\n        trust_env: bool = False,\n        requote_redirect_url: bool = True,\n        trace_configs: Optional[List[TraceConfig]] = None,\n        read_bufsize: int = 2**16,\n        max_line_size: int = 8190,\n        max_field_size: int = 8190,\n        fallback_charset_resolver: _CharsetResolver = lambda r, b: \"utf-8\",\n    ) -> None:\n        # We initialise _connector to None immediately, as it's referenced in __del__()\n        # and could cause issues if an exception occurs during initialisation.\n        self._connector: Optional[BaseConnector] = None\n\n        if loop is None:\n            if connector is not None:\n                loop = connector._loop\n\n        loop = loop or asyncio.get_running_loop()\n\n        if base_url is None or isinstance(base_url, URL):\n            self._base_url: Optional[URL] = base_url\n        else:\n            self._base_url = URL(base_url)\n            assert (\n                self._base_url.origin() == self._base_url\n            ), \"Only absolute URLs without path part are supported\"\n\n        if timeout is sentinel or timeout is None:\n            self._timeout = DEFAULT_TIMEOUT\n            if read_timeout is not sentinel:\n                warnings.warn(\n                    \"read_timeout is deprecated, use timeout argument instead\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n                self._timeout = attr.evolve(self._timeout, total=read_timeout)\n            if conn_timeout is not None:\n                self._timeout = attr.evolve(self._timeout, connect=conn_timeout)\n                warnings.warn(\n                    \"conn_timeout is deprecated, use timeout argument instead\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n        else:\n            if not isinstance(timeout, ClientTimeout):\n                raise ValueError(\n                    f\"timeout parameter cannot be of {type(timeout)} type, \"\n                    \"please use 'timeout=ClientTimeout(...)'\",\n                )\n            self._timeout = timeout\n            if read_timeout is not sentinel:\n                raise ValueError(\n                    \"read_timeout and timeout parameters \"\n                    \"conflict, please setup \"\n                    \"timeout.read\"\n                )\n            if conn_timeout is not None:\n                raise ValueError(\n                    \"conn_timeout and timeout parameters \"\n                    \"conflict, please setup \"\n                    \"timeout.connect\"\n                )\n\n        if connector is None:\n            connector = TCPConnector(loop=loop)\n\n        if connector._loop is not loop:\n            raise RuntimeError(\"Session and connector has to use same event loop\")\n\n        self._loop = loop\n\n        if loop.get_debug():\n            self._source_traceback = traceback.extract_stack(sys._getframe(1))\n\n        if cookie_jar is None:\n            cookie_jar = CookieJar(loop=loop)\n        self._cookie_jar = cookie_jar\n\n        if cookies is not None:\n            self._cookie_jar.update_cookies(cookies)\n\n        self._connector = connector\n        self._connector_owner = connector_owner\n        self._default_auth = auth\n        self._version = version\n        self._json_serialize = json_serialize\n        self._raise_for_status = raise_for_status\n        self._auto_decompress = auto_decompress\n        self._trust_env = trust_env\n        self._requote_redirect_url = requote_redirect_url\n        self._read_bufsize = read_bufsize\n        self._max_line_size = max_line_size\n        self._max_field_size = max_field_size\n\n        # Convert to list of tuples\n        if headers:\n            real_headers: CIMultiDict[str] = CIMultiDict(headers)\n        else:\n            real_headers = CIMultiDict()\n        self._default_headers: CIMultiDict[str] = real_headers\n        if skip_auto_headers is not None:\n            self._skip_auto_headers = frozenset(istr(i) for i in skip_auto_headers)\n        else:\n            self._skip_auto_headers = frozenset()\n\n        self._request_class = request_class\n        self._response_class = response_class\n        self._ws_response_class = ws_response_class\n\n        self._trace_configs = trace_configs or []\n        for trace_config in self._trace_configs:\n            trace_config.freeze()\n\n        self._resolve_charset = fallback_charset_resolver\n\n        self._default_proxy = proxy\n        self._default_proxy_auth = proxy_auth\n\n    def __init_subclass__(cls: Type[\"ClientSession\"]) -> None:\n        warnings.warn(\n            \"Inheritance class {} from ClientSession \"\n            \"is discouraged\".format(cls.__name__),\n            DeprecationWarning,\n            stacklevel=2,\n        )\n\n    if DEBUG:\n\n        def __setattr__(self, name: str, val: Any) -> None:\n            if name not in self.ATTRS:\n                warnings.warn(\n                    \"Setting custom ClientSession.{} attribute \"\n                    \"is discouraged\".format(name),\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n            super().__setattr__(name, val)\n\n    def __del__(self, _warnings: Any = warnings) -> None:\n        if not self.closed:\n            kwargs = {\"source\": self}\n            _warnings.warn(\n                f\"Unclosed client session {self!r}\", ResourceWarning, **kwargs\n            )\n            context = {\"client_session\": self, \"message\": \"Unclosed client session\"}\n            if self._source_traceback is not None:\n                context[\"source_traceback\"] = self._source_traceback\n            self._loop.call_exception_handler(context)\n\n    if sys.version_info >= (3, 11) and TYPE_CHECKING:\n\n        def request(\n            self,\n            method: str,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n    else:\n\n        def request(\n            self, method: str, url: StrOrURL, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP request.\"\"\"\n            return _RequestContextManager(self._request(method, url, **kwargs))\n\n    def _build_url(self, str_or_url: StrOrURL) -> URL:\n        url = URL(str_or_url)\n        if self._base_url is None:\n            return url\n        else:\n            assert not url.absolute and url.path.startswith(\"/\")\n            return self._base_url.join(url)\n\n    async def _request(\n        self,\n        method: str,\n        str_or_url: StrOrURL,\n        *,\n        params: Query = None,\n        data: Any = None,\n        json: Any = None,\n        cookies: Optional[LooseCookies] = None,\n        headers: Optional[LooseHeaders] = None,\n        skip_auto_headers: Optional[Iterable[str]] = None,\n        auth: Optional[BasicAuth] = None,\n        allow_redirects: bool = True,\n        max_redirects: int = 10,\n        compress: Union[str, bool, None] = None,\n        chunked: Optional[bool] = None,\n        expect100: bool = False,\n        raise_for_status: Union[\n            None, bool, Callable[[ClientResponse], Awaitable[None]]\n        ] = None,\n        read_until_eof: bool = True,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        timeout: Union[ClientTimeout, _SENTINEL] = sentinel,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        server_hostname: Optional[str] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        trace_request_ctx: Optional[Mapping[str, str]] = None,\n        read_bufsize: Optional[int] = None,\n        auto_decompress: Optional[bool] = None,\n        max_line_size: Optional[int] = None,\n        max_field_size: Optional[int] = None,\n    ) -> ClientResponse:\n\n        # NOTE: timeout clamps existing connect and read timeouts.  We cannot\n        # set the default to None because we need to detect if the user wants\n        # to use the existing timeouts by setting timeout to None.\n\n        if self.closed:\n            raise RuntimeError(\"Session is closed\")\n\n        ssl = _merge_ssl_params(ssl, verify_ssl, ssl_context, fingerprint)\n\n        if data is not None and json is not None:\n            raise ValueError(\n                \"data and json parameters can not be used at the same time\"\n            )\n        elif json is not None:\n            data = payload.JsonPayload(json, dumps=self._json_serialize)\n\n        if not isinstance(chunked, bool) and chunked is not None:\n            warnings.warn(\"Chunk size is deprecated #1615\", DeprecationWarning)\n\n        redirects = 0\n        history = []\n        version = self._version\n        params = params or {}\n\n        # Merge with default headers and transform to CIMultiDict\n        headers = self._prepare_headers(headers)\n\n        try:\n            url = self._build_url(str_or_url)\n        except ValueError as e:\n            raise InvalidUrlClientError(str_or_url) from e\n\n        assert self._connector is not None\n        if url.scheme not in self._connector.allowed_protocol_schema_set:\n            raise NonHttpUrlClientError(url)\n\n        skip_headers = set(self._skip_auto_headers)\n        if skip_auto_headers is not None:\n            for i in skip_auto_headers:\n                skip_headers.add(istr(i))\n\n        if proxy is None:\n            proxy = self._default_proxy\n        if proxy_auth is None:\n            proxy_auth = self._default_proxy_auth\n\n        if proxy is None:\n            proxy_headers = None\n        else:\n            proxy_headers = self._prepare_headers(proxy_headers)\n            try:\n                proxy = URL(proxy)\n            except ValueError as e:\n                raise InvalidURL(proxy) from e\n\n        if timeout is sentinel:\n            real_timeout: ClientTimeout = self._timeout\n        else:\n            if not isinstance(timeout, ClientTimeout):\n                real_timeout = ClientTimeout(total=timeout)\n            else:\n                real_timeout = timeout\n        # timeout is cumulative for all request operations\n        # (request, redirects, responses, data consuming)\n        tm = TimeoutHandle(\n            self._loop, real_timeout.total, ceil_threshold=real_timeout.ceil_threshold\n        )\n        handle = tm.start()\n\n        if read_bufsize is None:\n            read_bufsize = self._read_bufsize\n\n        if auto_decompress is None:\n            auto_decompress = self._auto_decompress\n\n        if max_line_size is None:\n            max_line_size = self._max_line_size\n\n        if max_field_size is None:\n            max_field_size = self._max_field_size\n\n        traces = [\n            Trace(\n                self,\n                trace_config,\n                trace_config.trace_config_ctx(trace_request_ctx=trace_request_ctx),\n            )\n            for trace_config in self._trace_configs\n        ]\n\n        for trace in traces:\n            await trace.send_request_start(method, url.update_query(params), headers)\n\n        timer = tm.timer()\n        try:\n            with timer:\n                # https://www.rfc-editor.org/rfc/rfc9112.html#name-retrying-requests\n                retry_persistent_connection = method in IDEMPOTENT_METHODS\n                while True:\n                    url, auth_from_url = strip_auth_from_url(url)\n                    if not url.raw_host:\n                        # NOTE: Bail early, otherwise, causes `InvalidURL` through\n                        # NOTE: `self._request_class()` below.\n                        err_exc_cls = (\n                            InvalidUrlRedirectClientError\n                            if redirects\n                            else InvalidUrlClientError\n                        )\n                        raise err_exc_cls(url)\n                    if auth and auth_from_url:\n                        raise ValueError(\n                            \"Cannot combine AUTH argument with \"\n                            \"credentials encoded in URL\"\n                        )\n\n                    if auth is None:\n                        auth = auth_from_url\n\n                    if auth is None and (\n                        not self._base_url or self._base_url.origin() == url.origin()\n                    ):\n                        auth = self._default_auth\n                    # It would be confusing if we support explicit\n                    # Authorization header with auth argument\n                    if (\n                        headers is not None\n                        and auth is not None\n                        and hdrs.AUTHORIZATION in headers\n                    ):\n                        raise ValueError(\n                            \"Cannot combine AUTHORIZATION header \"\n                            \"with AUTH argument or credentials \"\n                            \"encoded in URL\"\n                        )\n\n                    all_cookies = self._cookie_jar.filter_cookies(url)\n\n                    if cookies is not None:\n                        tmp_cookie_jar = CookieJar()\n                        tmp_cookie_jar.update_cookies(cookies)\n                        req_cookies = tmp_cookie_jar.filter_cookies(url)\n                        if req_cookies:\n                            all_cookies.load(req_cookies)\n\n                    if proxy is not None:\n                        proxy = URL(proxy)\n                    elif self._trust_env:\n                        with suppress(LookupError):\n                            proxy, proxy_auth = get_env_proxy_for_url(url)\n\n                    req = self._request_class(\n                        method,\n                        url,\n                        params=params,\n                        headers=headers,\n                        skip_auto_headers=skip_headers if skip_headers else None,\n                        data=data,\n                        cookies=all_cookies,\n                        auth=auth,\n                        version=version,\n                        compress=compress,\n                        chunked=chunked,\n                        expect100=expect100,\n                        loop=self._loop,\n                        response_class=self._response_class,\n                        proxy=proxy,\n                        proxy_auth=proxy_auth,\n                        timer=timer,\n                        session=self,\n                        ssl=ssl if ssl is not None else True,\n                        server_hostname=server_hostname,\n                        proxy_headers=proxy_headers,\n                        traces=traces,\n                        trust_env=self.trust_env,\n                    )\n\n                    # connection timeout\n                    try:\n                        async with ceil_timeout(\n                            real_timeout.connect,\n                            ceil_threshold=real_timeout.ceil_threshold,\n                        ):\n                            conn = await self._connector.connect(\n                                req, traces=traces, timeout=real_timeout\n                            )\n                    except asyncio.TimeoutError as exc:\n                        raise ConnectionTimeoutError(\n                            f\"Connection timeout to host {url}\"\n                        ) from exc\n\n                    assert conn.transport is not None\n\n                    assert conn.protocol is not None\n                    conn.protocol.set_response_params(\n                        timer=timer,\n                        skip_payload=method_must_be_empty_body(method),\n                        read_until_eof=read_until_eof,\n                        auto_decompress=auto_decompress,\n                        read_timeout=real_timeout.sock_read,\n                        read_bufsize=read_bufsize,\n                        timeout_ceil_threshold=self._connector._timeout_ceil_threshold,\n                        max_line_size=max_line_size,\n                        max_field_size=max_field_size,\n                    )\n\n                    try:\n                        try:\n                            resp = await req.send(conn)\n                            try:\n                                await resp.start(conn)\n                            except BaseException:\n                                resp.close()\n                                raise\n                        except BaseException:\n                            conn.close()\n                            raise\n                    except (ClientOSError, ServerDisconnectedError):\n                        if retry_persistent_connection:\n                            retry_persistent_connection = False\n                            continue\n                        raise\n                    except ClientError:\n                        raise\n                    except OSError as exc:\n                        if exc.errno is None and isinstance(exc, asyncio.TimeoutError):\n                            raise\n                        raise ClientOSError(*exc.args) from exc\n\n                    self._cookie_jar.update_cookies(resp.cookies, resp.url)\n\n                    # redirects\n                    if resp.status in (301, 302, 303, 307, 308) and allow_redirects:\n\n                        for trace in traces:\n                            await trace.send_request_redirect(\n                                method, url.update_query(params), headers, resp\n                            )\n\n                        redirects += 1\n                        history.append(resp)\n                        if max_redirects and redirects >= max_redirects:\n                            resp.close()\n                            raise TooManyRedirects(\n                                history[0].request_info, tuple(history)\n                            )\n\n                        # For 301 and 302, mimic IE, now changed in RFC\n                        # https://github.com/kennethreitz/requests/pull/269\n                        if (resp.status == 303 and resp.method != hdrs.METH_HEAD) or (\n                            resp.status in (301, 302) and resp.method == hdrs.METH_POST\n                        ):\n                            method = hdrs.METH_GET\n                            data = None\n                            if headers.get(hdrs.CONTENT_LENGTH):\n                                headers.pop(hdrs.CONTENT_LENGTH)\n\n                        r_url = resp.headers.get(hdrs.LOCATION) or resp.headers.get(\n                            hdrs.URI\n                        )\n                        if r_url is None:\n                            # see github.com/aio-libs/aiohttp/issues/2022\n                            break\n                        else:\n                            # reading from correct redirection\n                            # response is forbidden\n                            resp.release()\n\n                        try:\n                            parsed_redirect_url = URL(\n                                r_url, encoded=not self._requote_redirect_url\n                            )\n                        except ValueError as e:\n                            raise InvalidUrlRedirectClientError(\n                                r_url,\n                                \"Server attempted redirecting to a location that does not look like a URL\",\n                            ) from e\n\n                        scheme = parsed_redirect_url.scheme\n                        if scheme not in HTTP_AND_EMPTY_SCHEMA_SET:\n                            resp.close()\n                            raise NonHttpUrlRedirectClientError(r_url)\n                        elif not scheme:\n                            parsed_redirect_url = url.join(parsed_redirect_url)\n\n                        try:\n                            redirect_origin = parsed_redirect_url.origin()\n                        except ValueError as origin_val_err:\n                            raise InvalidUrlRedirectClientError(\n                                parsed_redirect_url,\n                                \"Invalid redirect URL origin\",\n                            ) from origin_val_err\n\n                        if url.origin() != redirect_origin:\n                            auth = None\n                            headers.pop(hdrs.AUTHORIZATION, None)\n\n                        url = parsed_redirect_url\n                        params = {}\n                        resp.release()\n                        continue\n\n                    break\n\n            # check response status\n            if raise_for_status is None:\n                raise_for_status = self._raise_for_status\n\n            if raise_for_status is None:\n                pass\n            elif callable(raise_for_status):\n                await raise_for_status(resp)\n            elif raise_for_status:\n                resp.raise_for_status()\n\n            # register connection\n            if handle is not None:\n                if resp.connection is not None:\n                    resp.connection.add_callback(handle.cancel)\n                else:\n                    handle.cancel()\n\n            resp._history = tuple(history)\n\n            for trace in traces:\n                await trace.send_request_end(\n                    method, url.update_query(params), headers, resp\n                )\n            return resp\n\n        except BaseException as e:\n            # cleanup timer\n            tm.close()\n            if handle:\n                handle.cancel()\n                handle = None\n\n            for trace in traces:\n                await trace.send_request_exception(\n                    method, url.update_query(params), headers, e\n                )\n            raise\n\n    def ws_connect(\n        self,\n        url: StrOrURL,\n        *,\n        method: str = hdrs.METH_GET,\n        protocols: Iterable[str] = (),\n        timeout: Union[ClientWSTimeout, _SENTINEL] = sentinel,\n        receive_timeout: Optional[float] = None,\n        autoclose: bool = True,\n        autoping: bool = True,\n        heartbeat: Optional[float] = None,\n        auth: Optional[BasicAuth] = None,\n        origin: Optional[str] = None,\n        params: Query = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        compress: int = 0,\n        max_msg_size: int = 4 * 1024 * 1024,\n    ) -> \"_WSRequestContextManager\":\n        \"\"\"Initiate websocket connection.\"\"\"\n        return _WSRequestContextManager(\n            self._ws_connect(\n                url,\n                method=method,\n                protocols=protocols,\n                timeout=timeout,\n                receive_timeout=receive_timeout,\n                autoclose=autoclose,\n                autoping=autoping,\n                heartbeat=heartbeat,\n                auth=auth,\n                origin=origin,\n                params=params,\n                headers=headers,\n                proxy=proxy,\n                proxy_auth=proxy_auth,\n                ssl=ssl,\n                verify_ssl=verify_ssl,\n                fingerprint=fingerprint,\n                ssl_context=ssl_context,\n                proxy_headers=proxy_headers,\n                compress=compress,\n                max_msg_size=max_msg_size,\n            )\n        )\n\n    async def _ws_connect(\n        self,\n        url: StrOrURL,\n        *,\n        method: str = hdrs.METH_GET,\n        protocols: Iterable[str] = (),\n        timeout: Union[ClientWSTimeout, _SENTINEL] = sentinel,\n        receive_timeout: Optional[float] = None,\n        autoclose: bool = True,\n        autoping: bool = True,\n        heartbeat: Optional[float] = None,\n        auth: Optional[BasicAuth] = None,\n        origin: Optional[str] = None,\n        params: Query = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        compress: int = 0,\n        max_msg_size: int = 4 * 1024 * 1024,\n    ) -> ClientWebSocketResponse:\n        if timeout is not sentinel:\n            if isinstance(timeout, ClientWSTimeout):\n                ws_timeout = timeout\n            else:\n                warnings.warn(\n                    \"parameter 'timeout' of type 'float' \"\n                    \"is deprecated, please use \"\n                    \"'timeout=ClientWSTimeout(ws_close=...)'\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n                ws_timeout = ClientWSTimeout(ws_close=timeout)\n        else:\n            ws_timeout = DEFAULT_WS_CLIENT_TIMEOUT\n        if receive_timeout is not None:\n            warnings.warn(\n                \"float parameter 'receive_timeout' \"\n                \"is deprecated, please use parameter \"\n                \"'timeout=ClientWSTimeout(ws_receive=...)'\",\n                DeprecationWarning,\n                stacklevel=2,\n            )\n            ws_timeout = attr.evolve(ws_timeout, ws_receive=receive_timeout)\n\n        if headers is None:\n            real_headers: CIMultiDict[str] = CIMultiDict()\n        else:\n            real_headers = CIMultiDict(headers)\n\n        default_headers = {\n            hdrs.UPGRADE: \"websocket\",\n            hdrs.CONNECTION: \"Upgrade\",\n            hdrs.SEC_WEBSOCKET_VERSION: \"13\",\n        }\n\n        for key, value in default_headers.items():\n            real_headers.setdefault(key, value)\n\n        sec_key = base64.b64encode(os.urandom(16))\n        real_headers[hdrs.SEC_WEBSOCKET_KEY] = sec_key.decode()\n\n        if protocols:\n            real_headers[hdrs.SEC_WEBSOCKET_PROTOCOL] = \",\".join(protocols)\n        if origin is not None:\n            real_headers[hdrs.ORIGIN] = origin\n        if compress:\n            extstr = ws_ext_gen(compress=compress)\n            real_headers[hdrs.SEC_WEBSOCKET_EXTENSIONS] = extstr\n\n        # For the sake of backward compatibility, if user passes in None, convert it to True\n        if ssl is None:\n            warnings.warn(\n                \"ssl=None is deprecated, please use ssl=True\",\n                DeprecationWarning,\n                stacklevel=2,\n            )\n            ssl = True\n        ssl = _merge_ssl_params(ssl, verify_ssl, ssl_context, fingerprint)\n\n        # send request\n        resp = await self.request(\n            method,\n            url,\n            params=params,\n            headers=real_headers,\n            read_until_eof=False,\n            auth=auth,\n            proxy=proxy,\n            proxy_auth=proxy_auth,\n            ssl=ssl,\n            proxy_headers=proxy_headers,\n        )\n\n        try:\n            # check handshake\n            if resp.status != 101:\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid response status\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            if resp.headers.get(hdrs.UPGRADE, \"\").lower() != \"websocket\":\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid upgrade header\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            if resp.headers.get(hdrs.CONNECTION, \"\").lower() != \"upgrade\":\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid connection header\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            # key calculation\n            r_key = resp.headers.get(hdrs.SEC_WEBSOCKET_ACCEPT, \"\")\n            match = base64.b64encode(hashlib.sha1(sec_key + WS_KEY).digest()).decode()\n            if r_key != match:\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid challenge response\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            # websocket protocol\n            protocol = None\n            if protocols and hdrs.SEC_WEBSOCKET_PROTOCOL in resp.headers:\n                resp_protocols = [\n                    proto.strip()\n                    for proto in resp.headers[hdrs.SEC_WEBSOCKET_PROTOCOL].split(\",\")\n                ]\n\n                for proto in resp_protocols:\n                    if proto in protocols:\n                        protocol = proto\n                        break\n\n            # websocket compress\n            notakeover = False\n            if compress:\n                compress_hdrs = resp.headers.get(hdrs.SEC_WEBSOCKET_EXTENSIONS)\n                if compress_hdrs:\n                    try:\n                        compress, notakeover = ws_ext_parse(compress_hdrs)\n                    except WSHandshakeError as exc:\n                        raise WSServerHandshakeError(\n                            resp.request_info,\n                            resp.history,\n                            message=exc.args[0],\n                            status=resp.status,\n                            headers=resp.headers,\n                        ) from exc\n                else:\n                    compress = 0\n                    notakeover = False\n\n            conn = resp.connection\n            assert conn is not None\n            conn_proto = conn.protocol\n            assert conn_proto is not None\n\n            # For WS connection the read_timeout must be either receive_timeout or greater\n            # None == no timeout, i.e. infinite timeout, so None is the max timeout possible\n            if ws_timeout.ws_receive is None:\n                # Reset regardless\n                conn_proto.read_timeout = None\n            elif conn_proto.read_timeout is not None:\n                conn_proto.read_timeout = max(\n                    ws_timeout.ws_receive, conn_proto.read_timeout\n                )\n\n            transport = conn.transport\n            assert transport is not None\n            reader: FlowControlDataQueue[WSMessage] = FlowControlDataQueue(\n                conn_proto, 2**16, loop=self._loop\n            )\n            conn_proto.set_parser(WebSocketReader(reader, max_msg_size), reader)\n            writer = WebSocketWriter(\n                conn_proto,\n                transport,\n                use_mask=True,\n                compress=compress,\n                notakeover=notakeover,\n            )\n        except BaseException:\n            resp.close()\n            raise\n        else:\n            return self._ws_response_class(\n                reader,\n                writer,\n                protocol,\n                resp,\n                ws_timeout,\n                autoclose,\n                autoping,\n                self._loop,\n                heartbeat=heartbeat,\n                compress=compress,\n                client_notakeover=notakeover,\n            )\n\n    def _prepare_headers(self, headers: Optional[LooseHeaders]) -> \"CIMultiDict[str]\":\n        \"\"\"Add default headers and transform it to CIMultiDict\"\"\"\n        # Convert headers to MultiDict\n        result = CIMultiDict(self._default_headers)\n        if headers:\n            if not isinstance(headers, (MultiDictProxy, MultiDict)):\n                headers = CIMultiDict(headers)\n            added_names: Set[str] = set()\n            for key, value in headers.items():\n                if key in added_names:\n                    result.add(key, value)\n                else:\n                    result[key] = value\n                    added_names.add(key)\n        return result\n\n    if sys.version_info >= (3, 11) and TYPE_CHECKING:\n\n        def get(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def options(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def head(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def post(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def put(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def patch(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def delete(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n    else:\n\n        def get(\n            self, url: StrOrURL, *, allow_redirects: bool = True, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP GET request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_GET, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def options(\n            self, url: StrOrURL, *, allow_redirects: bool = True, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP OPTIONS request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_OPTIONS, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def head(\n            self, url: StrOrURL, *, allow_redirects: bool = False, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP HEAD request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_HEAD, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def post(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP POST request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_POST, url, data=data, **kwargs)\n            )\n\n        def put(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP PUT request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_PUT, url, data=data, **kwargs)\n            )\n\n        def patch(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP PATCH request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_PATCH, url, data=data, **kwargs)\n            )\n\n        def delete(self, url: StrOrURL, **kwargs: Any) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP DELETE request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_DELETE, url, **kwargs)\n            )\n\n    async def close(self) -> None:\n        \"\"\"Close underlying connector.\n\n        Release all acquired resources.\n        \"\"\"\n        if not self.closed:\n            if self._connector is not None and self._connector_owner:\n                await self._connector.close()\n            self._connector = None\n\n    @property\n    def closed(self) -> bool:\n        \"\"\"Is client session closed.\n\n        A readonly property.\n        \"\"\"\n        return self._connector is None or self._connector.closed\n\n    @property\n    def connector(self) -> Optional[BaseConnector]:\n        \"\"\"Connector instance used for the session.\"\"\"\n        return self._connector\n\n    @property\n    def cookie_jar(self) -> AbstractCookieJar:\n        \"\"\"The session cookies.\"\"\"\n        return self._cookie_jar\n\n    @property\n    def version(self) -> Tuple[int, int]:\n        \"\"\"The session HTTP protocol version.\"\"\"\n        return self._version\n\n    @property\n    def requote_redirect_url(self) -> bool:\n        \"\"\"Do URL requoting on redirection handling.\"\"\"\n        return self._requote_redirect_url\n\n    @requote_redirect_url.setter\n    def requote_redirect_url(self, val: bool) -> None:\n        \"\"\"Do URL requoting on redirection handling.\"\"\"\n        warnings.warn(\n            \"session.requote_redirect_url modification is deprecated #2778\",\n            DeprecationWarning,\n            stacklevel=2,\n        )\n        self._requote_redirect_url = val\n\n    @property\n    def loop(self) -> asyncio.AbstractEventLoop:\n        \"\"\"Session's loop.\"\"\"\n        warnings.warn(\n            \"client.loop property is deprecated\", DeprecationWarning, stacklevel=2\n        )\n        return self._loop\n\n    @property\n    def timeout(self) -> ClientTimeout:\n        \"\"\"Timeout for the session.\"\"\"\n        return self._timeout\n\n    @property\n    def headers(self) -> \"CIMultiDict[str]\":\n        \"\"\"The default headers of the client session.\"\"\"\n        return self._default_headers\n\n    @property\n    def skip_auto_headers(self) -> FrozenSet[istr]:\n        \"\"\"Headers for which autogeneration should be skipped\"\"\"\n        return self._skip_auto_headers\n\n    @property\n    def auth(self) -> Optional[BasicAuth]:\n        \"\"\"An object that represents HTTP Basic Authorization\"\"\"\n        return self._default_auth\n\n    @property\n    def json_serialize(self) -> JSONEncoder:\n        \"\"\"Json serializer callable\"\"\"\n        return self._json_serialize\n\n    @property\n    def connector_owner(self) -> bool:\n        \"\"\"Should connector be closed on session closing\"\"\"\n        return self._connector_owner\n\n    @property\n    def raise_for_status(\n        self,\n    ) -> Union[bool, Callable[[ClientResponse], Awaitable[None]]]:\n        \"\"\"Should `ClientResponse.raise_for_status()` be called for each response.\"\"\"\n        return self._raise_for_status\n\n    @property\n    def auto_decompress(self) -> bool:\n        \"\"\"Should the body response be automatically decompressed.\"\"\"\n        return self._auto_decompress\n\n    @property\n    def trust_env(self) -> bool:\n        \"\"\"\n        Should proxies information from environment or netrc be trusted.\n\n        Information is from HTTP_PROXY / HTTPS_PROXY environment variables\n        or ~/.netrc file if present.\n        \"\"\"\n        return self._trust_env\n\n    @property\n    def trace_configs(self) -> List[TraceConfig]:\n        \"\"\"A list of TraceConfig instances used for client tracing\"\"\"\n        return self._trace_configs\n\n    def detach(self) -> None:\n        \"\"\"Detach connector from session without closing the former.\n\n        Session is switched to closed state anyway.\n        \"\"\"\n        self._connector = None\n\n    def __enter__(self) -> None:\n        raise TypeError(\"Use async with instead\")\n\n    def __exit__(\n        self,\n        exc_type: Optional[Type[BaseException]],\n        exc_val: Optional[BaseException],\n        exc_tb: Optional[TracebackType],\n    ) -> None:\n        # __exit__ should exist in pair with __enter__ but never executed\n        pass  # pragma: no cover\n\n    async def __aenter__(self) -> \"ClientSession\":\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        await self.close()",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 225,
                            "end_lineno": 1373,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 530,
                            "length": 6
                        },
                        "new_range": {
                            "start": 537,
                            "length": 11
                        },
                        "section": "class ClientSession:"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "            for i in skip_auto_headers:",
                                "type": "context"
                            },
                            {
                                "content": "                skip_headers.add(istr(i))",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        if proxy is None:",
                                "type": "added"
                            },
                            {
                                "content": "            proxy = self._default_proxy",
                                "type": "added"
                            },
                            {
                                "content": "        if proxy_auth is None:",
                                "type": "added"
                            },
                            {
                                "content": "            proxy_auth = self._default_proxy_auth",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "        if proxy is None:",
                                "type": "context"
                            },
                            {
                                "content": "            proxy_headers = None",
                                "type": "context"
                            },
                            {
                                "content": "        else:",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "aiohttp/client.py",
                            "type": "method",
                            "name": "ClientSession._request",
                            "content": "class ClientSession:\n    \"\"\"First-class interface for making HTTP requests.\"\"\"\n\n    ATTRS = frozenset(\n        [\n            \"_base_url\",\n            \"_source_traceback\",\n            \"_connector\",\n            \"requote_redirect_url\",\n            \"_loop\",\n            \"_cookie_jar\",\n            \"_connector_owner\",\n            \"_default_auth\",\n            \"_version\",\n            \"_json_serialize\",\n            \"_requote_redirect_url\",\n            \"_timeout\",\n            \"_raise_for_status\",\n            \"_auto_decompress\",\n            \"_trust_env\",\n            \"_default_headers\",\n            \"_skip_auto_headers\",\n            \"_request_class\",\n            \"_response_class\",\n            \"_ws_response_class\",\n            \"_trace_configs\",\n            \"_read_bufsize\",\n            \"_max_line_size\",\n            \"_max_field_size\",\n            \"_resolve_charset\",\n            \"_default_proxy\",\n            \"_default_proxy_auth\",\n        ]\n    )\n\n    _source_traceback: Optional[traceback.StackSummary] = None\n    _connector: Optional[BaseConnector] = None\n\n    def __init__(\n        self,\n        base_url: Optional[StrOrURL] = None,\n        *,\n        connector: Optional[BaseConnector] = None,\n        loop: Optional[asyncio.AbstractEventLoop] = None,\n        cookies: Optional[LooseCookies] = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        skip_auto_headers: Optional[Iterable[str]] = None,\n        auth: Optional[BasicAuth] = None,\n        json_serialize: JSONEncoder = json.dumps,\n        request_class: Type[ClientRequest] = ClientRequest,\n        response_class: Type[ClientResponse] = ClientResponse,\n        ws_response_class: Type[ClientWebSocketResponse] = ClientWebSocketResponse,\n        version: HttpVersion = http.HttpVersion11,\n        cookie_jar: Optional[AbstractCookieJar] = None,\n        connector_owner: bool = True,\n        raise_for_status: Union[\n            bool, Callable[[ClientResponse], Awaitable[None]]\n        ] = False,\n        read_timeout: Union[float, _SENTINEL] = sentinel,\n        conn_timeout: Optional[float] = None,\n        timeout: Union[object, ClientTimeout] = sentinel,\n        auto_decompress: bool = True,\n        trust_env: bool = False,\n        requote_redirect_url: bool = True,\n        trace_configs: Optional[List[TraceConfig]] = None,\n        read_bufsize: int = 2**16,\n        max_line_size: int = 8190,\n        max_field_size: int = 8190,\n        fallback_charset_resolver: _CharsetResolver = lambda r, b: \"utf-8\",\n    ) -> None:\n        # We initialise _connector to None immediately, as it's referenced in __del__()\n        # and could cause issues if an exception occurs during initialisation.\n        self._connector: Optional[BaseConnector] = None\n\n        if loop is None:\n            if connector is not None:\n                loop = connector._loop\n\n        loop = loop or asyncio.get_running_loop()\n\n        if base_url is None or isinstance(base_url, URL):\n            self._base_url: Optional[URL] = base_url\n        else:\n            self._base_url = URL(base_url)\n            assert (\n                self._base_url.origin() == self._base_url\n            ), \"Only absolute URLs without path part are supported\"\n\n        if timeout is sentinel or timeout is None:\n            self._timeout = DEFAULT_TIMEOUT\n            if read_timeout is not sentinel:\n                warnings.warn(\n                    \"read_timeout is deprecated, use timeout argument instead\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n                self._timeout = attr.evolve(self._timeout, total=read_timeout)\n            if conn_timeout is not None:\n                self._timeout = attr.evolve(self._timeout, connect=conn_timeout)\n                warnings.warn(\n                    \"conn_timeout is deprecated, use timeout argument instead\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n        else:\n            if not isinstance(timeout, ClientTimeout):\n                raise ValueError(\n                    f\"timeout parameter cannot be of {type(timeout)} type, \"\n                    \"please use 'timeout=ClientTimeout(...)'\",\n                )\n            self._timeout = timeout\n            if read_timeout is not sentinel:\n                raise ValueError(\n                    \"read_timeout and timeout parameters \"\n                    \"conflict, please setup \"\n                    \"timeout.read\"\n                )\n            if conn_timeout is not None:\n                raise ValueError(\n                    \"conn_timeout and timeout parameters \"\n                    \"conflict, please setup \"\n                    \"timeout.connect\"\n                )\n\n        if connector is None:\n            connector = TCPConnector(loop=loop)\n\n        if connector._loop is not loop:\n            raise RuntimeError(\"Session and connector has to use same event loop\")\n\n        self._loop = loop\n\n        if loop.get_debug():\n            self._source_traceback = traceback.extract_stack(sys._getframe(1))\n\n        if cookie_jar is None:\n            cookie_jar = CookieJar(loop=loop)\n        self._cookie_jar = cookie_jar\n\n        if cookies is not None:\n            self._cookie_jar.update_cookies(cookies)\n\n        self._connector = connector\n        self._connector_owner = connector_owner\n        self._default_auth = auth\n        self._version = version\n        self._json_serialize = json_serialize\n        self._raise_for_status = raise_for_status\n        self._auto_decompress = auto_decompress\n        self._trust_env = trust_env\n        self._requote_redirect_url = requote_redirect_url\n        self._read_bufsize = read_bufsize\n        self._max_line_size = max_line_size\n        self._max_field_size = max_field_size\n\n        # Convert to list of tuples\n        if headers:\n            real_headers: CIMultiDict[str] = CIMultiDict(headers)\n        else:\n            real_headers = CIMultiDict()\n        self._default_headers: CIMultiDict[str] = real_headers\n        if skip_auto_headers is not None:\n            self._skip_auto_headers = frozenset(istr(i) for i in skip_auto_headers)\n        else:\n            self._skip_auto_headers = frozenset()\n\n        self._request_class = request_class\n        self._response_class = response_class\n        self._ws_response_class = ws_response_class\n\n        self._trace_configs = trace_configs or []\n        for trace_config in self._trace_configs:\n            trace_config.freeze()\n\n        self._resolve_charset = fallback_charset_resolver\n\n        self._default_proxy = proxy\n        self._default_proxy_auth = proxy_auth\n\n    def __init_subclass__(cls: Type[\"ClientSession\"]) -> None:\n        warnings.warn(\n            \"Inheritance class {} from ClientSession \"\n            \"is discouraged\".format(cls.__name__),\n            DeprecationWarning,\n            stacklevel=2,\n        )\n\n    if DEBUG:\n\n        def __setattr__(self, name: str, val: Any) -> None:\n            if name not in self.ATTRS:\n                warnings.warn(\n                    \"Setting custom ClientSession.{} attribute \"\n                    \"is discouraged\".format(name),\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n            super().__setattr__(name, val)\n\n    def __del__(self, _warnings: Any = warnings) -> None:\n        if not self.closed:\n            kwargs = {\"source\": self}\n            _warnings.warn(\n                f\"Unclosed client session {self!r}\", ResourceWarning, **kwargs\n            )\n            context = {\"client_session\": self, \"message\": \"Unclosed client session\"}\n            if self._source_traceback is not None:\n                context[\"source_traceback\"] = self._source_traceback\n            self._loop.call_exception_handler(context)\n\n    if sys.version_info >= (3, 11) and TYPE_CHECKING:\n\n        def request(\n            self,\n            method: str,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n    else:\n\n        def request(\n            self, method: str, url: StrOrURL, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP request.\"\"\"\n            return _RequestContextManager(self._request(method, url, **kwargs))\n\n    def _build_url(self, str_or_url: StrOrURL) -> URL:\n        url = URL(str_or_url)\n        if self._base_url is None:\n            return url\n        else:\n            assert not url.absolute and url.path.startswith(\"/\")\n            return self._base_url.join(url)\n\n    async def _request(\n        self,\n        method: str,\n        str_or_url: StrOrURL,\n        *,\n        params: Query = None,\n        data: Any = None,\n        json: Any = None,\n        cookies: Optional[LooseCookies] = None,\n        headers: Optional[LooseHeaders] = None,\n        skip_auto_headers: Optional[Iterable[str]] = None,\n        auth: Optional[BasicAuth] = None,\n        allow_redirects: bool = True,\n        max_redirects: int = 10,\n        compress: Union[str, bool, None] = None,\n        chunked: Optional[bool] = None,\n        expect100: bool = False,\n        raise_for_status: Union[\n            None, bool, Callable[[ClientResponse], Awaitable[None]]\n        ] = None,\n        read_until_eof: bool = True,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        timeout: Union[ClientTimeout, _SENTINEL] = sentinel,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        server_hostname: Optional[str] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        trace_request_ctx: Optional[Mapping[str, str]] = None,\n        read_bufsize: Optional[int] = None,\n        auto_decompress: Optional[bool] = None,\n        max_line_size: Optional[int] = None,\n        max_field_size: Optional[int] = None,\n    ) -> ClientResponse:\n\n        # NOTE: timeout clamps existing connect and read timeouts.  We cannot\n        # set the default to None because we need to detect if the user wants\n        # to use the existing timeouts by setting timeout to None.\n\n        if self.closed:\n            raise RuntimeError(\"Session is closed\")\n\n        ssl = _merge_ssl_params(ssl, verify_ssl, ssl_context, fingerprint)\n\n        if data is not None and json is not None:\n            raise ValueError(\n                \"data and json parameters can not be used at the same time\"\n            )\n        elif json is not None:\n            data = payload.JsonPayload(json, dumps=self._json_serialize)\n\n        if not isinstance(chunked, bool) and chunked is not None:\n            warnings.warn(\"Chunk size is deprecated #1615\", DeprecationWarning)\n\n        redirects = 0\n        history = []\n        version = self._version\n        params = params or {}\n\n        # Merge with default headers and transform to CIMultiDict\n        headers = self._prepare_headers(headers)\n\n        try:\n            url = self._build_url(str_or_url)\n        except ValueError as e:\n            raise InvalidUrlClientError(str_or_url) from e\n\n        assert self._connector is not None\n        if url.scheme not in self._connector.allowed_protocol_schema_set:\n            raise NonHttpUrlClientError(url)\n\n        skip_headers = set(self._skip_auto_headers)\n        if skip_auto_headers is not None:\n            for i in skip_auto_headers:\n                skip_headers.add(istr(i))\n\n        if proxy is None:\n            proxy = self._default_proxy\n        if proxy_auth is None:\n            proxy_auth = self._default_proxy_auth\n\n        if proxy is None:\n            proxy_headers = None\n        else:\n            proxy_headers = self._prepare_headers(proxy_headers)\n            try:\n                proxy = URL(proxy)\n            except ValueError as e:\n                raise InvalidURL(proxy) from e\n\n        if timeout is sentinel:\n            real_timeout: ClientTimeout = self._timeout\n        else:\n            if not isinstance(timeout, ClientTimeout):\n                real_timeout = ClientTimeout(total=timeout)\n            else:\n                real_timeout = timeout\n        # timeout is cumulative for all request operations\n        # (request, redirects, responses, data consuming)\n        tm = TimeoutHandle(\n            self._loop, real_timeout.total, ceil_threshold=real_timeout.ceil_threshold\n        )\n        handle = tm.start()\n\n        if read_bufsize is None:\n            read_bufsize = self._read_bufsize\n\n        if auto_decompress is None:\n            auto_decompress = self._auto_decompress\n\n        if max_line_size is None:\n            max_line_size = self._max_line_size\n\n        if max_field_size is None:\n            max_field_size = self._max_field_size\n\n        traces = [\n            Trace(\n                self,\n                trace_config,\n                trace_config.trace_config_ctx(trace_request_ctx=trace_request_ctx),\n            )\n            for trace_config in self._trace_configs\n        ]\n\n        for trace in traces:\n            await trace.send_request_start(method, url.update_query(params), headers)\n\n        timer = tm.timer()\n        try:\n            with timer:\n                # https://www.rfc-editor.org/rfc/rfc9112.html#name-retrying-requests\n                retry_persistent_connection = method in IDEMPOTENT_METHODS\n                while True:\n                    url, auth_from_url = strip_auth_from_url(url)\n                    if not url.raw_host:\n                        # NOTE: Bail early, otherwise, causes `InvalidURL` through\n                        # NOTE: `self._request_class()` below.\n                        err_exc_cls = (\n                            InvalidUrlRedirectClientError\n                            if redirects\n                            else InvalidUrlClientError\n                        )\n                        raise err_exc_cls(url)\n                    if auth and auth_from_url:\n                        raise ValueError(\n                            \"Cannot combine AUTH argument with \"\n                            \"credentials encoded in URL\"\n                        )\n\n                    if auth is None:\n                        auth = auth_from_url\n\n                    if auth is None and (\n                        not self._base_url or self._base_url.origin() == url.origin()\n                    ):\n                        auth = self._default_auth\n                    # It would be confusing if we support explicit\n                    # Authorization header with auth argument\n                    if (\n                        headers is not None\n                        and auth is not None\n                        and hdrs.AUTHORIZATION in headers\n                    ):\n                        raise ValueError(\n                            \"Cannot combine AUTHORIZATION header \"\n                            \"with AUTH argument or credentials \"\n                            \"encoded in URL\"\n                        )\n\n                    all_cookies = self._cookie_jar.filter_cookies(url)\n\n                    if cookies is not None:\n                        tmp_cookie_jar = CookieJar()\n                        tmp_cookie_jar.update_cookies(cookies)\n                        req_cookies = tmp_cookie_jar.filter_cookies(url)\n                        if req_cookies:\n                            all_cookies.load(req_cookies)\n\n                    if proxy is not None:\n                        proxy = URL(proxy)\n                    elif self._trust_env:\n                        with suppress(LookupError):\n                            proxy, proxy_auth = get_env_proxy_for_url(url)\n\n                    req = self._request_class(\n                        method,\n                        url,\n                        params=params,\n                        headers=headers,\n                        skip_auto_headers=skip_headers if skip_headers else None,\n                        data=data,\n                        cookies=all_cookies,\n                        auth=auth,\n                        version=version,\n                        compress=compress,\n                        chunked=chunked,\n                        expect100=expect100,\n                        loop=self._loop,\n                        response_class=self._response_class,\n                        proxy=proxy,\n                        proxy_auth=proxy_auth,\n                        timer=timer,\n                        session=self,\n                        ssl=ssl if ssl is not None else True,\n                        server_hostname=server_hostname,\n                        proxy_headers=proxy_headers,\n                        traces=traces,\n                        trust_env=self.trust_env,\n                    )\n\n                    # connection timeout\n                    try:\n                        async with ceil_timeout(\n                            real_timeout.connect,\n                            ceil_threshold=real_timeout.ceil_threshold,\n                        ):\n                            conn = await self._connector.connect(\n                                req, traces=traces, timeout=real_timeout\n                            )\n                    except asyncio.TimeoutError as exc:\n                        raise ConnectionTimeoutError(\n                            f\"Connection timeout to host {url}\"\n                        ) from exc\n\n                    assert conn.transport is not None\n\n                    assert conn.protocol is not None\n                    conn.protocol.set_response_params(\n                        timer=timer,\n                        skip_payload=method_must_be_empty_body(method),\n                        read_until_eof=read_until_eof,\n                        auto_decompress=auto_decompress,\n                        read_timeout=real_timeout.sock_read,\n                        read_bufsize=read_bufsize,\n                        timeout_ceil_threshold=self._connector._timeout_ceil_threshold,\n                        max_line_size=max_line_size,\n                        max_field_size=max_field_size,\n                    )\n\n                    try:\n                        try:\n                            resp = await req.send(conn)\n                            try:\n                                await resp.start(conn)\n                            except BaseException:\n                                resp.close()\n                                raise\n                        except BaseException:\n                            conn.close()\n                            raise\n                    except (ClientOSError, ServerDisconnectedError):\n                        if retry_persistent_connection:\n                            retry_persistent_connection = False\n                            continue\n                        raise\n                    except ClientError:\n                        raise\n                    except OSError as exc:\n                        if exc.errno is None and isinstance(exc, asyncio.TimeoutError):\n                            raise\n                        raise ClientOSError(*exc.args) from exc\n\n                    self._cookie_jar.update_cookies(resp.cookies, resp.url)\n\n                    # redirects\n                    if resp.status in (301, 302, 303, 307, 308) and allow_redirects:\n\n                        for trace in traces:\n                            await trace.send_request_redirect(\n                                method, url.update_query(params), headers, resp\n                            )\n\n                        redirects += 1\n                        history.append(resp)\n                        if max_redirects and redirects >= max_redirects:\n                            resp.close()\n                            raise TooManyRedirects(\n                                history[0].request_info, tuple(history)\n                            )\n\n                        # For 301 and 302, mimic IE, now changed in RFC\n                        # https://github.com/kennethreitz/requests/pull/269\n                        if (resp.status == 303 and resp.method != hdrs.METH_HEAD) or (\n                            resp.status in (301, 302) and resp.method == hdrs.METH_POST\n                        ):\n                            method = hdrs.METH_GET\n                            data = None\n                            if headers.get(hdrs.CONTENT_LENGTH):\n                                headers.pop(hdrs.CONTENT_LENGTH)\n\n                        r_url = resp.headers.get(hdrs.LOCATION) or resp.headers.get(\n                            hdrs.URI\n                        )\n                        if r_url is None:\n                            # see github.com/aio-libs/aiohttp/issues/2022\n                            break\n                        else:\n                            # reading from correct redirection\n                            # response is forbidden\n                            resp.release()\n\n                        try:\n                            parsed_redirect_url = URL(\n                                r_url, encoded=not self._requote_redirect_url\n                            )\n                        except ValueError as e:\n                            raise InvalidUrlRedirectClientError(\n                                r_url,\n                                \"Server attempted redirecting to a location that does not look like a URL\",\n                            ) from e\n\n                        scheme = parsed_redirect_url.scheme\n                        if scheme not in HTTP_AND_EMPTY_SCHEMA_SET:\n                            resp.close()\n                            raise NonHttpUrlRedirectClientError(r_url)\n                        elif not scheme:\n                            parsed_redirect_url = url.join(parsed_redirect_url)\n\n                        try:\n                            redirect_origin = parsed_redirect_url.origin()\n                        except ValueError as origin_val_err:\n                            raise InvalidUrlRedirectClientError(\n                                parsed_redirect_url,\n                                \"Invalid redirect URL origin\",\n                            ) from origin_val_err\n\n                        if url.origin() != redirect_origin:\n                            auth = None\n                            headers.pop(hdrs.AUTHORIZATION, None)\n\n                        url = parsed_redirect_url\n                        params = {}\n                        resp.release()\n                        continue\n\n                    break\n\n            # check response status\n            if raise_for_status is None:\n                raise_for_status = self._raise_for_status\n\n            if raise_for_status is None:\n                pass\n            elif callable(raise_for_status):\n                await raise_for_status(resp)\n            elif raise_for_status:\n                resp.raise_for_status()\n\n            # register connection\n            if handle is not None:\n                if resp.connection is not None:\n                    resp.connection.add_callback(handle.cancel)\n                else:\n                    handle.cancel()\n\n            resp._history = tuple(history)\n\n            for trace in traces:\n                await trace.send_request_end(\n                    method, url.update_query(params), headers, resp\n                )\n            return resp\n\n        except BaseException as e:\n            # cleanup timer\n            tm.close()\n            if handle:\n                handle.cancel()\n                handle = None\n\n            for trace in traces:\n                await trace.send_request_exception(\n                    method, url.update_query(params), headers, e\n                )\n            raise\n\n    def ws_connect(\n        self,\n        url: StrOrURL,\n        *,\n        method: str = hdrs.METH_GET,\n        protocols: Iterable[str] = (),\n        timeout: Union[ClientWSTimeout, _SENTINEL] = sentinel,\n        receive_timeout: Optional[float] = None,\n        autoclose: bool = True,\n        autoping: bool = True,\n        heartbeat: Optional[float] = None,\n        auth: Optional[BasicAuth] = None,\n        origin: Optional[str] = None,\n        params: Query = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        compress: int = 0,\n        max_msg_size: int = 4 * 1024 * 1024,\n    ) -> \"_WSRequestContextManager\":\n        \"\"\"Initiate websocket connection.\"\"\"\n        return _WSRequestContextManager(\n            self._ws_connect(\n                url,\n                method=method,\n                protocols=protocols,\n                timeout=timeout,\n                receive_timeout=receive_timeout,\n                autoclose=autoclose,\n                autoping=autoping,\n                heartbeat=heartbeat,\n                auth=auth,\n                origin=origin,\n                params=params,\n                headers=headers,\n                proxy=proxy,\n                proxy_auth=proxy_auth,\n                ssl=ssl,\n                verify_ssl=verify_ssl,\n                fingerprint=fingerprint,\n                ssl_context=ssl_context,\n                proxy_headers=proxy_headers,\n                compress=compress,\n                max_msg_size=max_msg_size,\n            )\n        )\n\n    async def _ws_connect(\n        self,\n        url: StrOrURL,\n        *,\n        method: str = hdrs.METH_GET,\n        protocols: Iterable[str] = (),\n        timeout: Union[ClientWSTimeout, _SENTINEL] = sentinel,\n        receive_timeout: Optional[float] = None,\n        autoclose: bool = True,\n        autoping: bool = True,\n        heartbeat: Optional[float] = None,\n        auth: Optional[BasicAuth] = None,\n        origin: Optional[str] = None,\n        params: Query = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        compress: int = 0,\n        max_msg_size: int = 4 * 1024 * 1024,\n    ) -> ClientWebSocketResponse:\n        if timeout is not sentinel:\n            if isinstance(timeout, ClientWSTimeout):\n                ws_timeout = timeout\n            else:\n                warnings.warn(\n                    \"parameter 'timeout' of type 'float' \"\n                    \"is deprecated, please use \"\n                    \"'timeout=ClientWSTimeout(ws_close=...)'\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n                ws_timeout = ClientWSTimeout(ws_close=timeout)\n        else:\n            ws_timeout = DEFAULT_WS_CLIENT_TIMEOUT\n        if receive_timeout is not None:\n            warnings.warn(\n                \"float parameter 'receive_timeout' \"\n                \"is deprecated, please use parameter \"\n                \"'timeout=ClientWSTimeout(ws_receive=...)'\",\n                DeprecationWarning,\n                stacklevel=2,\n            )\n            ws_timeout = attr.evolve(ws_timeout, ws_receive=receive_timeout)\n\n        if headers is None:\n            real_headers: CIMultiDict[str] = CIMultiDict()\n        else:\n            real_headers = CIMultiDict(headers)\n\n        default_headers = {\n            hdrs.UPGRADE: \"websocket\",\n            hdrs.CONNECTION: \"Upgrade\",\n            hdrs.SEC_WEBSOCKET_VERSION: \"13\",\n        }\n\n        for key, value in default_headers.items():\n            real_headers.setdefault(key, value)\n\n        sec_key = base64.b64encode(os.urandom(16))\n        real_headers[hdrs.SEC_WEBSOCKET_KEY] = sec_key.decode()\n\n        if protocols:\n            real_headers[hdrs.SEC_WEBSOCKET_PROTOCOL] = \",\".join(protocols)\n        if origin is not None:\n            real_headers[hdrs.ORIGIN] = origin\n        if compress:\n            extstr = ws_ext_gen(compress=compress)\n            real_headers[hdrs.SEC_WEBSOCKET_EXTENSIONS] = extstr\n\n        # For the sake of backward compatibility, if user passes in None, convert it to True\n        if ssl is None:\n            warnings.warn(\n                \"ssl=None is deprecated, please use ssl=True\",\n                DeprecationWarning,\n                stacklevel=2,\n            )\n            ssl = True\n        ssl = _merge_ssl_params(ssl, verify_ssl, ssl_context, fingerprint)\n\n        # send request\n        resp = await self.request(\n            method,\n            url,\n            params=params,\n            headers=real_headers,\n            read_until_eof=False,\n            auth=auth,\n            proxy=proxy,\n            proxy_auth=proxy_auth,\n            ssl=ssl,\n            proxy_headers=proxy_headers,\n        )\n\n        try:\n            # check handshake\n            if resp.status != 101:\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid response status\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            if resp.headers.get(hdrs.UPGRADE, \"\").lower() != \"websocket\":\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid upgrade header\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            if resp.headers.get(hdrs.CONNECTION, \"\").lower() != \"upgrade\":\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid connection header\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            # key calculation\n            r_key = resp.headers.get(hdrs.SEC_WEBSOCKET_ACCEPT, \"\")\n            match = base64.b64encode(hashlib.sha1(sec_key + WS_KEY).digest()).decode()\n            if r_key != match:\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid challenge response\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            # websocket protocol\n            protocol = None\n            if protocols and hdrs.SEC_WEBSOCKET_PROTOCOL in resp.headers:\n                resp_protocols = [\n                    proto.strip()\n                    for proto in resp.headers[hdrs.SEC_WEBSOCKET_PROTOCOL].split(\",\")\n                ]\n\n                for proto in resp_protocols:\n                    if proto in protocols:\n                        protocol = proto\n                        break\n\n            # websocket compress\n            notakeover = False\n            if compress:\n                compress_hdrs = resp.headers.get(hdrs.SEC_WEBSOCKET_EXTENSIONS)\n                if compress_hdrs:\n                    try:\n                        compress, notakeover = ws_ext_parse(compress_hdrs)\n                    except WSHandshakeError as exc:\n                        raise WSServerHandshakeError(\n                            resp.request_info,\n                            resp.history,\n                            message=exc.args[0],\n                            status=resp.status,\n                            headers=resp.headers,\n                        ) from exc\n                else:\n                    compress = 0\n                    notakeover = False\n\n            conn = resp.connection\n            assert conn is not None\n            conn_proto = conn.protocol\n            assert conn_proto is not None\n\n            # For WS connection the read_timeout must be either receive_timeout or greater\n            # None == no timeout, i.e. infinite timeout, so None is the max timeout possible\n            if ws_timeout.ws_receive is None:\n                # Reset regardless\n                conn_proto.read_timeout = None\n            elif conn_proto.read_timeout is not None:\n                conn_proto.read_timeout = max(\n                    ws_timeout.ws_receive, conn_proto.read_timeout\n                )\n\n            transport = conn.transport\n            assert transport is not None\n            reader: FlowControlDataQueue[WSMessage] = FlowControlDataQueue(\n                conn_proto, 2**16, loop=self._loop\n            )\n            conn_proto.set_parser(WebSocketReader(reader, max_msg_size), reader)\n            writer = WebSocketWriter(\n                conn_proto,\n                transport,\n                use_mask=True,\n                compress=compress,\n                notakeover=notakeover,\n            )\n        except BaseException:\n            resp.close()\n            raise\n        else:\n            return self._ws_response_class(\n                reader,\n                writer,\n                protocol,\n                resp,\n                ws_timeout,\n                autoclose,\n                autoping,\n                self._loop,\n                heartbeat=heartbeat,\n                compress=compress,\n                client_notakeover=notakeover,\n            )\n\n    def _prepare_headers(self, headers: Optional[LooseHeaders]) -> \"CIMultiDict[str]\":\n        \"\"\"Add default headers and transform it to CIMultiDict\"\"\"\n        # Convert headers to MultiDict\n        result = CIMultiDict(self._default_headers)\n        if headers:\n            if not isinstance(headers, (MultiDictProxy, MultiDict)):\n                headers = CIMultiDict(headers)\n            added_names: Set[str] = set()\n            for key, value in headers.items():\n                if key in added_names:\n                    result.add(key, value)\n                else:\n                    result[key] = value\n                    added_names.add(key)\n        return result\n\n    if sys.version_info >= (3, 11) and TYPE_CHECKING:\n\n        def get(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def options(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def head(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def post(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def put(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def patch(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def delete(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n    else:\n\n        def get(\n            self, url: StrOrURL, *, allow_redirects: bool = True, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP GET request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_GET, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def options(\n            self, url: StrOrURL, *, allow_redirects: bool = True, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP OPTIONS request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_OPTIONS, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def head(\n            self, url: StrOrURL, *, allow_redirects: bool = False, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP HEAD request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_HEAD, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def post(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP POST request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_POST, url, data=data, **kwargs)\n            )\n\n        def put(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP PUT request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_PUT, url, data=data, **kwargs)\n            )\n\n        def patch(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP PATCH request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_PATCH, url, data=data, **kwargs)\n            )\n\n        def delete(self, url: StrOrURL, **kwargs: Any) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP DELETE request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_DELETE, url, **kwargs)\n            )\n\n    async def close(self) -> None:\n        \"\"\"Close underlying connector.\n\n        Release all acquired resources.\n        \"\"\"\n        if not self.closed:\n            if self._connector is not None and self._connector_owner:\n                await self._connector.close()\n            self._connector = None\n\n    @property\n    def closed(self) -> bool:\n        \"\"\"Is client session closed.\n\n        A readonly property.\n        \"\"\"\n        return self._connector is None or self._connector.closed\n\n    @property\n    def connector(self) -> Optional[BaseConnector]:\n        \"\"\"Connector instance used for the session.\"\"\"\n        return self._connector\n\n    @property\n    def cookie_jar(self) -> AbstractCookieJar:\n        \"\"\"The session cookies.\"\"\"\n        return self._cookie_jar\n\n    @property\n    def version(self) -> Tuple[int, int]:\n        \"\"\"The session HTTP protocol version.\"\"\"\n        return self._version\n\n    @property\n    def requote_redirect_url(self) -> bool:\n        \"\"\"Do URL requoting on redirection handling.\"\"\"\n        return self._requote_redirect_url\n\n    @requote_redirect_url.setter\n    def requote_redirect_url(self, val: bool) -> None:\n        \"\"\"Do URL requoting on redirection handling.\"\"\"\n        warnings.warn(\n            \"session.requote_redirect_url modification is deprecated #2778\",\n            DeprecationWarning,\n            stacklevel=2,\n        )\n        self._requote_redirect_url = val\n\n    @property\n    def loop(self) -> asyncio.AbstractEventLoop:\n        \"\"\"Session's loop.\"\"\"\n        warnings.warn(\n            \"client.loop property is deprecated\", DeprecationWarning, stacklevel=2\n        )\n        return self._loop\n\n    @property\n    def timeout(self) -> ClientTimeout:\n        \"\"\"Timeout for the session.\"\"\"\n        return self._timeout\n\n    @property\n    def headers(self) -> \"CIMultiDict[str]\":\n        \"\"\"The default headers of the client session.\"\"\"\n        return self._default_headers\n\n    @property\n    def skip_auto_headers(self) -> FrozenSet[istr]:\n        \"\"\"Headers for which autogeneration should be skipped\"\"\"\n        return self._skip_auto_headers\n\n    @property\n    def auth(self) -> Optional[BasicAuth]:\n        \"\"\"An object that represents HTTP Basic Authorization\"\"\"\n        return self._default_auth\n\n    @property\n    def json_serialize(self) -> JSONEncoder:\n        \"\"\"Json serializer callable\"\"\"\n        return self._json_serialize\n\n    @property\n    def connector_owner(self) -> bool:\n        \"\"\"Should connector be closed on session closing\"\"\"\n        return self._connector_owner\n\n    @property\n    def raise_for_status(\n        self,\n    ) -> Union[bool, Callable[[ClientResponse], Awaitable[None]]]:\n        \"\"\"Should `ClientResponse.raise_for_status()` be called for each response.\"\"\"\n        return self._raise_for_status\n\n    @property\n    def auto_decompress(self) -> bool:\n        \"\"\"Should the body response be automatically decompressed.\"\"\"\n        return self._auto_decompress\n\n    @property\n    def trust_env(self) -> bool:\n        \"\"\"\n        Should proxies information from environment or netrc be trusted.\n\n        Information is from HTTP_PROXY / HTTPS_PROXY environment variables\n        or ~/.netrc file if present.\n        \"\"\"\n        return self._trust_env\n\n    @property\n    def trace_configs(self) -> List[TraceConfig]:\n        \"\"\"A list of TraceConfig instances used for client tracing\"\"\"\n        return self._trace_configs\n\n    def detach(self) -> None:\n        \"\"\"Detach connector from session without closing the former.\n\n        Session is switched to closed state anyway.\n        \"\"\"\n        self._connector = None\n\n    def __enter__(self) -> None:\n        raise TypeError(\"Use async with instead\")\n\n    def __exit__(\n        self,\n        exc_type: Optional[Type[BaseException]],\n        exc_val: Optional[BaseException],\n        exc_tb: Optional[TracebackType],\n    ) -> None:\n        # __exit__ should exist in pair with __enter__ but never executed\n        pass  # pragma: no cover\n\n    async def __aenter__(self) -> \"ClientSession\":\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        await self.close()",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 462,
                            "end_lineno": 839,
                            "parent": {
                                "file_name": "aiohttp/client.py",
                                "type": "class",
                                "name": "ClientSession",
                                "content": "class ClientSession:\n    \"\"\"First-class interface for making HTTP requests.\"\"\"\n\n    ATTRS = frozenset(\n        [\n            \"_base_url\",\n            \"_source_traceback\",\n            \"_connector\",\n            \"requote_redirect_url\",\n            \"_loop\",\n            \"_cookie_jar\",\n            \"_connector_owner\",\n            \"_default_auth\",\n            \"_version\",\n            \"_json_serialize\",\n            \"_requote_redirect_url\",\n            \"_timeout\",\n            \"_raise_for_status\",\n            \"_auto_decompress\",\n            \"_trust_env\",\n            \"_default_headers\",\n            \"_skip_auto_headers\",\n            \"_request_class\",\n            \"_response_class\",\n            \"_ws_response_class\",\n            \"_trace_configs\",\n            \"_read_bufsize\",\n            \"_max_line_size\",\n            \"_max_field_size\",\n            \"_resolve_charset\",\n            \"_default_proxy\",\n            \"_default_proxy_auth\",\n        ]\n    )\n\n    _source_traceback: Optional[traceback.StackSummary] = None\n    _connector: Optional[BaseConnector] = None\n\n    def __init__(\n        self,\n        base_url: Optional[StrOrURL] = None,\n        *,\n        connector: Optional[BaseConnector] = None,\n        loop: Optional[asyncio.AbstractEventLoop] = None,\n        cookies: Optional[LooseCookies] = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        skip_auto_headers: Optional[Iterable[str]] = None,\n        auth: Optional[BasicAuth] = None,\n        json_serialize: JSONEncoder = json.dumps,\n        request_class: Type[ClientRequest] = ClientRequest,\n        response_class: Type[ClientResponse] = ClientResponse,\n        ws_response_class: Type[ClientWebSocketResponse] = ClientWebSocketResponse,\n        version: HttpVersion = http.HttpVersion11,\n        cookie_jar: Optional[AbstractCookieJar] = None,\n        connector_owner: bool = True,\n        raise_for_status: Union[\n            bool, Callable[[ClientResponse], Awaitable[None]]\n        ] = False,\n        read_timeout: Union[float, _SENTINEL] = sentinel,\n        conn_timeout: Optional[float] = None,\n        timeout: Union[object, ClientTimeout] = sentinel,\n        auto_decompress: bool = True,\n        trust_env: bool = False,\n        requote_redirect_url: bool = True,\n        trace_configs: Optional[List[TraceConfig]] = None,\n        read_bufsize: int = 2**16,\n        max_line_size: int = 8190,\n        max_field_size: int = 8190,\n        fallback_charset_resolver: _CharsetResolver = lambda r, b: \"utf-8\",\n    ) -> None:\n        # We initialise _connector to None immediately, as it's referenced in __del__()\n        # and could cause issues if an exception occurs during initialisation.\n        self._connector: Optional[BaseConnector] = None\n\n        if loop is None:\n            if connector is not None:\n                loop = connector._loop\n\n        loop = loop or asyncio.get_running_loop()\n\n        if base_url is None or isinstance(base_url, URL):\n            self._base_url: Optional[URL] = base_url\n        else:\n            self._base_url = URL(base_url)\n            assert (\n                self._base_url.origin() == self._base_url\n            ), \"Only absolute URLs without path part are supported\"\n\n        if timeout is sentinel or timeout is None:\n            self._timeout = DEFAULT_TIMEOUT\n            if read_timeout is not sentinel:\n                warnings.warn(\n                    \"read_timeout is deprecated, use timeout argument instead\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n                self._timeout = attr.evolve(self._timeout, total=read_timeout)\n            if conn_timeout is not None:\n                self._timeout = attr.evolve(self._timeout, connect=conn_timeout)\n                warnings.warn(\n                    \"conn_timeout is deprecated, use timeout argument instead\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n        else:\n            if not isinstance(timeout, ClientTimeout):\n                raise ValueError(\n                    f\"timeout parameter cannot be of {type(timeout)} type, \"\n                    \"please use 'timeout=ClientTimeout(...)'\",\n                )\n            self._timeout = timeout\n            if read_timeout is not sentinel:\n                raise ValueError(\n                    \"read_timeout and timeout parameters \"\n                    \"conflict, please setup \"\n                    \"timeout.read\"\n                )\n            if conn_timeout is not None:\n                raise ValueError(\n                    \"conn_timeout and timeout parameters \"\n                    \"conflict, please setup \"\n                    \"timeout.connect\"\n                )\n\n        if connector is None:\n            connector = TCPConnector(loop=loop)\n\n        if connector._loop is not loop:\n            raise RuntimeError(\"Session and connector has to use same event loop\")\n\n        self._loop = loop\n\n        if loop.get_debug():\n            self._source_traceback = traceback.extract_stack(sys._getframe(1))\n\n        if cookie_jar is None:\n            cookie_jar = CookieJar(loop=loop)\n        self._cookie_jar = cookie_jar\n\n        if cookies is not None:\n            self._cookie_jar.update_cookies(cookies)\n\n        self._connector = connector\n        self._connector_owner = connector_owner\n        self._default_auth = auth\n        self._version = version\n        self._json_serialize = json_serialize\n        self._raise_for_status = raise_for_status\n        self._auto_decompress = auto_decompress\n        self._trust_env = trust_env\n        self._requote_redirect_url = requote_redirect_url\n        self._read_bufsize = read_bufsize\n        self._max_line_size = max_line_size\n        self._max_field_size = max_field_size\n\n        # Convert to list of tuples\n        if headers:\n            real_headers: CIMultiDict[str] = CIMultiDict(headers)\n        else:\n            real_headers = CIMultiDict()\n        self._default_headers: CIMultiDict[str] = real_headers\n        if skip_auto_headers is not None:\n            self._skip_auto_headers = frozenset(istr(i) for i in skip_auto_headers)\n        else:\n            self._skip_auto_headers = frozenset()\n\n        self._request_class = request_class\n        self._response_class = response_class\n        self._ws_response_class = ws_response_class\n\n        self._trace_configs = trace_configs or []\n        for trace_config in self._trace_configs:\n            trace_config.freeze()\n\n        self._resolve_charset = fallback_charset_resolver\n\n        self._default_proxy = proxy\n        self._default_proxy_auth = proxy_auth\n\n    def __init_subclass__(cls: Type[\"ClientSession\"]) -> None:\n        warnings.warn(\n            \"Inheritance class {} from ClientSession \"\n            \"is discouraged\".format(cls.__name__),\n            DeprecationWarning,\n            stacklevel=2,\n        )\n\n    if DEBUG:\n\n        def __setattr__(self, name: str, val: Any) -> None:\n            if name not in self.ATTRS:\n                warnings.warn(\n                    \"Setting custom ClientSession.{} attribute \"\n                    \"is discouraged\".format(name),\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n            super().__setattr__(name, val)\n\n    def __del__(self, _warnings: Any = warnings) -> None:\n        if not self.closed:\n            kwargs = {\"source\": self}\n            _warnings.warn(\n                f\"Unclosed client session {self!r}\", ResourceWarning, **kwargs\n            )\n            context = {\"client_session\": self, \"message\": \"Unclosed client session\"}\n            if self._source_traceback is not None:\n                context[\"source_traceback\"] = self._source_traceback\n            self._loop.call_exception_handler(context)\n\n    if sys.version_info >= (3, 11) and TYPE_CHECKING:\n\n        def request(\n            self,\n            method: str,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n    else:\n\n        def request(\n            self, method: str, url: StrOrURL, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP request.\"\"\"\n            return _RequestContextManager(self._request(method, url, **kwargs))\n\n    def _build_url(self, str_or_url: StrOrURL) -> URL:\n        url = URL(str_or_url)\n        if self._base_url is None:\n            return url\n        else:\n            assert not url.absolute and url.path.startswith(\"/\")\n            return self._base_url.join(url)\n\n    async def _request(\n        self,\n        method: str,\n        str_or_url: StrOrURL,\n        *,\n        params: Query = None,\n        data: Any = None,\n        json: Any = None,\n        cookies: Optional[LooseCookies] = None,\n        headers: Optional[LooseHeaders] = None,\n        skip_auto_headers: Optional[Iterable[str]] = None,\n        auth: Optional[BasicAuth] = None,\n        allow_redirects: bool = True,\n        max_redirects: int = 10,\n        compress: Union[str, bool, None] = None,\n        chunked: Optional[bool] = None,\n        expect100: bool = False,\n        raise_for_status: Union[\n            None, bool, Callable[[ClientResponse], Awaitable[None]]\n        ] = None,\n        read_until_eof: bool = True,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        timeout: Union[ClientTimeout, _SENTINEL] = sentinel,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        server_hostname: Optional[str] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        trace_request_ctx: Optional[Mapping[str, str]] = None,\n        read_bufsize: Optional[int] = None,\n        auto_decompress: Optional[bool] = None,\n        max_line_size: Optional[int] = None,\n        max_field_size: Optional[int] = None,\n    ) -> ClientResponse:\n\n        # NOTE: timeout clamps existing connect and read timeouts.  We cannot\n        # set the default to None because we need to detect if the user wants\n        # to use the existing timeouts by setting timeout to None.\n\n        if self.closed:\n            raise RuntimeError(\"Session is closed\")\n\n        ssl = _merge_ssl_params(ssl, verify_ssl, ssl_context, fingerprint)\n\n        if data is not None and json is not None:\n            raise ValueError(\n                \"data and json parameters can not be used at the same time\"\n            )\n        elif json is not None:\n            data = payload.JsonPayload(json, dumps=self._json_serialize)\n\n        if not isinstance(chunked, bool) and chunked is not None:\n            warnings.warn(\"Chunk size is deprecated #1615\", DeprecationWarning)\n\n        redirects = 0\n        history = []\n        version = self._version\n        params = params or {}\n\n        # Merge with default headers and transform to CIMultiDict\n        headers = self._prepare_headers(headers)\n\n        try:\n            url = self._build_url(str_or_url)\n        except ValueError as e:\n            raise InvalidUrlClientError(str_or_url) from e\n\n        assert self._connector is not None\n        if url.scheme not in self._connector.allowed_protocol_schema_set:\n            raise NonHttpUrlClientError(url)\n\n        skip_headers = set(self._skip_auto_headers)\n        if skip_auto_headers is not None:\n            for i in skip_auto_headers:\n                skip_headers.add(istr(i))\n\n        if proxy is None:\n            proxy = self._default_proxy\n        if proxy_auth is None:\n            proxy_auth = self._default_proxy_auth\n\n        if proxy is None:\n            proxy_headers = None\n        else:\n            proxy_headers = self._prepare_headers(proxy_headers)\n            try:\n                proxy = URL(proxy)\n            except ValueError as e:\n                raise InvalidURL(proxy) from e\n\n        if timeout is sentinel:\n            real_timeout: ClientTimeout = self._timeout\n        else:\n            if not isinstance(timeout, ClientTimeout):\n                real_timeout = ClientTimeout(total=timeout)\n            else:\n                real_timeout = timeout\n        # timeout is cumulative for all request operations\n        # (request, redirects, responses, data consuming)\n        tm = TimeoutHandle(\n            self._loop, real_timeout.total, ceil_threshold=real_timeout.ceil_threshold\n        )\n        handle = tm.start()\n\n        if read_bufsize is None:\n            read_bufsize = self._read_bufsize\n\n        if auto_decompress is None:\n            auto_decompress = self._auto_decompress\n\n        if max_line_size is None:\n            max_line_size = self._max_line_size\n\n        if max_field_size is None:\n            max_field_size = self._max_field_size\n\n        traces = [\n            Trace(\n                self,\n                trace_config,\n                trace_config.trace_config_ctx(trace_request_ctx=trace_request_ctx),\n            )\n            for trace_config in self._trace_configs\n        ]\n\n        for trace in traces:\n            await trace.send_request_start(method, url.update_query(params), headers)\n\n        timer = tm.timer()\n        try:\n            with timer:\n                # https://www.rfc-editor.org/rfc/rfc9112.html#name-retrying-requests\n                retry_persistent_connection = method in IDEMPOTENT_METHODS\n                while True:\n                    url, auth_from_url = strip_auth_from_url(url)\n                    if not url.raw_host:\n                        # NOTE: Bail early, otherwise, causes `InvalidURL` through\n                        # NOTE: `self._request_class()` below.\n                        err_exc_cls = (\n                            InvalidUrlRedirectClientError\n                            if redirects\n                            else InvalidUrlClientError\n                        )\n                        raise err_exc_cls(url)\n                    if auth and auth_from_url:\n                        raise ValueError(\n                            \"Cannot combine AUTH argument with \"\n                            \"credentials encoded in URL\"\n                        )\n\n                    if auth is None:\n                        auth = auth_from_url\n\n                    if auth is None and (\n                        not self._base_url or self._base_url.origin() == url.origin()\n                    ):\n                        auth = self._default_auth\n                    # It would be confusing if we support explicit\n                    # Authorization header with auth argument\n                    if (\n                        headers is not None\n                        and auth is not None\n                        and hdrs.AUTHORIZATION in headers\n                    ):\n                        raise ValueError(\n                            \"Cannot combine AUTHORIZATION header \"\n                            \"with AUTH argument or credentials \"\n                            \"encoded in URL\"\n                        )\n\n                    all_cookies = self._cookie_jar.filter_cookies(url)\n\n                    if cookies is not None:\n                        tmp_cookie_jar = CookieJar()\n                        tmp_cookie_jar.update_cookies(cookies)\n                        req_cookies = tmp_cookie_jar.filter_cookies(url)\n                        if req_cookies:\n                            all_cookies.load(req_cookies)\n\n                    if proxy is not None:\n                        proxy = URL(proxy)\n                    elif self._trust_env:\n                        with suppress(LookupError):\n                            proxy, proxy_auth = get_env_proxy_for_url(url)\n\n                    req = self._request_class(\n                        method,\n                        url,\n                        params=params,\n                        headers=headers,\n                        skip_auto_headers=skip_headers if skip_headers else None,\n                        data=data,\n                        cookies=all_cookies,\n                        auth=auth,\n                        version=version,\n                        compress=compress,\n                        chunked=chunked,\n                        expect100=expect100,\n                        loop=self._loop,\n                        response_class=self._response_class,\n                        proxy=proxy,\n                        proxy_auth=proxy_auth,\n                        timer=timer,\n                        session=self,\n                        ssl=ssl if ssl is not None else True,\n                        server_hostname=server_hostname,\n                        proxy_headers=proxy_headers,\n                        traces=traces,\n                        trust_env=self.trust_env,\n                    )\n\n                    # connection timeout\n                    try:\n                        async with ceil_timeout(\n                            real_timeout.connect,\n                            ceil_threshold=real_timeout.ceil_threshold,\n                        ):\n                            conn = await self._connector.connect(\n                                req, traces=traces, timeout=real_timeout\n                            )\n                    except asyncio.TimeoutError as exc:\n                        raise ConnectionTimeoutError(\n                            f\"Connection timeout to host {url}\"\n                        ) from exc\n\n                    assert conn.transport is not None\n\n                    assert conn.protocol is not None\n                    conn.protocol.set_response_params(\n                        timer=timer,\n                        skip_payload=method_must_be_empty_body(method),\n                        read_until_eof=read_until_eof,\n                        auto_decompress=auto_decompress,\n                        read_timeout=real_timeout.sock_read,\n                        read_bufsize=read_bufsize,\n                        timeout_ceil_threshold=self._connector._timeout_ceil_threshold,\n                        max_line_size=max_line_size,\n                        max_field_size=max_field_size,\n                    )\n\n                    try:\n                        try:\n                            resp = await req.send(conn)\n                            try:\n                                await resp.start(conn)\n                            except BaseException:\n                                resp.close()\n                                raise\n                        except BaseException:\n                            conn.close()\n                            raise\n                    except (ClientOSError, ServerDisconnectedError):\n                        if retry_persistent_connection:\n                            retry_persistent_connection = False\n                            continue\n                        raise\n                    except ClientError:\n                        raise\n                    except OSError as exc:\n                        if exc.errno is None and isinstance(exc, asyncio.TimeoutError):\n                            raise\n                        raise ClientOSError(*exc.args) from exc\n\n                    self._cookie_jar.update_cookies(resp.cookies, resp.url)\n\n                    # redirects\n                    if resp.status in (301, 302, 303, 307, 308) and allow_redirects:\n\n                        for trace in traces:\n                            await trace.send_request_redirect(\n                                method, url.update_query(params), headers, resp\n                            )\n\n                        redirects += 1\n                        history.append(resp)\n                        if max_redirects and redirects >= max_redirects:\n                            resp.close()\n                            raise TooManyRedirects(\n                                history[0].request_info, tuple(history)\n                            )\n\n                        # For 301 and 302, mimic IE, now changed in RFC\n                        # https://github.com/kennethreitz/requests/pull/269\n                        if (resp.status == 303 and resp.method != hdrs.METH_HEAD) or (\n                            resp.status in (301, 302) and resp.method == hdrs.METH_POST\n                        ):\n                            method = hdrs.METH_GET\n                            data = None\n                            if headers.get(hdrs.CONTENT_LENGTH):\n                                headers.pop(hdrs.CONTENT_LENGTH)\n\n                        r_url = resp.headers.get(hdrs.LOCATION) or resp.headers.get(\n                            hdrs.URI\n                        )\n                        if r_url is None:\n                            # see github.com/aio-libs/aiohttp/issues/2022\n                            break\n                        else:\n                            # reading from correct redirection\n                            # response is forbidden\n                            resp.release()\n\n                        try:\n                            parsed_redirect_url = URL(\n                                r_url, encoded=not self._requote_redirect_url\n                            )\n                        except ValueError as e:\n                            raise InvalidUrlRedirectClientError(\n                                r_url,\n                                \"Server attempted redirecting to a location that does not look like a URL\",\n                            ) from e\n\n                        scheme = parsed_redirect_url.scheme\n                        if scheme not in HTTP_AND_EMPTY_SCHEMA_SET:\n                            resp.close()\n                            raise NonHttpUrlRedirectClientError(r_url)\n                        elif not scheme:\n                            parsed_redirect_url = url.join(parsed_redirect_url)\n\n                        try:\n                            redirect_origin = parsed_redirect_url.origin()\n                        except ValueError as origin_val_err:\n                            raise InvalidUrlRedirectClientError(\n                                parsed_redirect_url,\n                                \"Invalid redirect URL origin\",\n                            ) from origin_val_err\n\n                        if url.origin() != redirect_origin:\n                            auth = None\n                            headers.pop(hdrs.AUTHORIZATION, None)\n\n                        url = parsed_redirect_url\n                        params = {}\n                        resp.release()\n                        continue\n\n                    break\n\n            # check response status\n            if raise_for_status is None:\n                raise_for_status = self._raise_for_status\n\n            if raise_for_status is None:\n                pass\n            elif callable(raise_for_status):\n                await raise_for_status(resp)\n            elif raise_for_status:\n                resp.raise_for_status()\n\n            # register connection\n            if handle is not None:\n                if resp.connection is not None:\n                    resp.connection.add_callback(handle.cancel)\n                else:\n                    handle.cancel()\n\n            resp._history = tuple(history)\n\n            for trace in traces:\n                await trace.send_request_end(\n                    method, url.update_query(params), headers, resp\n                )\n            return resp\n\n        except BaseException as e:\n            # cleanup timer\n            tm.close()\n            if handle:\n                handle.cancel()\n                handle = None\n\n            for trace in traces:\n                await trace.send_request_exception(\n                    method, url.update_query(params), headers, e\n                )\n            raise\n\n    def ws_connect(\n        self,\n        url: StrOrURL,\n        *,\n        method: str = hdrs.METH_GET,\n        protocols: Iterable[str] = (),\n        timeout: Union[ClientWSTimeout, _SENTINEL] = sentinel,\n        receive_timeout: Optional[float] = None,\n        autoclose: bool = True,\n        autoping: bool = True,\n        heartbeat: Optional[float] = None,\n        auth: Optional[BasicAuth] = None,\n        origin: Optional[str] = None,\n        params: Query = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        compress: int = 0,\n        max_msg_size: int = 4 * 1024 * 1024,\n    ) -> \"_WSRequestContextManager\":\n        \"\"\"Initiate websocket connection.\"\"\"\n        return _WSRequestContextManager(\n            self._ws_connect(\n                url,\n                method=method,\n                protocols=protocols,\n                timeout=timeout,\n                receive_timeout=receive_timeout,\n                autoclose=autoclose,\n                autoping=autoping,\n                heartbeat=heartbeat,\n                auth=auth,\n                origin=origin,\n                params=params,\n                headers=headers,\n                proxy=proxy,\n                proxy_auth=proxy_auth,\n                ssl=ssl,\n                verify_ssl=verify_ssl,\n                fingerprint=fingerprint,\n                ssl_context=ssl_context,\n                proxy_headers=proxy_headers,\n                compress=compress,\n                max_msg_size=max_msg_size,\n            )\n        )\n\n    async def _ws_connect(\n        self,\n        url: StrOrURL,\n        *,\n        method: str = hdrs.METH_GET,\n        protocols: Iterable[str] = (),\n        timeout: Union[ClientWSTimeout, _SENTINEL] = sentinel,\n        receive_timeout: Optional[float] = None,\n        autoclose: bool = True,\n        autoping: bool = True,\n        heartbeat: Optional[float] = None,\n        auth: Optional[BasicAuth] = None,\n        origin: Optional[str] = None,\n        params: Query = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        compress: int = 0,\n        max_msg_size: int = 4 * 1024 * 1024,\n    ) -> ClientWebSocketResponse:\n        if timeout is not sentinel:\n            if isinstance(timeout, ClientWSTimeout):\n                ws_timeout = timeout\n            else:\n                warnings.warn(\n                    \"parameter 'timeout' of type 'float' \"\n                    \"is deprecated, please use \"\n                    \"'timeout=ClientWSTimeout(ws_close=...)'\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n                ws_timeout = ClientWSTimeout(ws_close=timeout)\n        else:\n            ws_timeout = DEFAULT_WS_CLIENT_TIMEOUT\n        if receive_timeout is not None:\n            warnings.warn(\n                \"float parameter 'receive_timeout' \"\n                \"is deprecated, please use parameter \"\n                \"'timeout=ClientWSTimeout(ws_receive=...)'\",\n                DeprecationWarning,\n                stacklevel=2,\n            )\n            ws_timeout = attr.evolve(ws_timeout, ws_receive=receive_timeout)\n\n        if headers is None:\n            real_headers: CIMultiDict[str] = CIMultiDict()\n        else:\n            real_headers = CIMultiDict(headers)\n\n        default_headers = {\n            hdrs.UPGRADE: \"websocket\",\n            hdrs.CONNECTION: \"Upgrade\",\n            hdrs.SEC_WEBSOCKET_VERSION: \"13\",\n        }\n\n        for key, value in default_headers.items():\n            real_headers.setdefault(key, value)\n\n        sec_key = base64.b64encode(os.urandom(16))\n        real_headers[hdrs.SEC_WEBSOCKET_KEY] = sec_key.decode()\n\n        if protocols:\n            real_headers[hdrs.SEC_WEBSOCKET_PROTOCOL] = \",\".join(protocols)\n        if origin is not None:\n            real_headers[hdrs.ORIGIN] = origin\n        if compress:\n            extstr = ws_ext_gen(compress=compress)\n            real_headers[hdrs.SEC_WEBSOCKET_EXTENSIONS] = extstr\n\n        # For the sake of backward compatibility, if user passes in None, convert it to True\n        if ssl is None:\n            warnings.warn(\n                \"ssl=None is deprecated, please use ssl=True\",\n                DeprecationWarning,\n                stacklevel=2,\n            )\n            ssl = True\n        ssl = _merge_ssl_params(ssl, verify_ssl, ssl_context, fingerprint)\n\n        # send request\n        resp = await self.request(\n            method,\n            url,\n            params=params,\n            headers=real_headers,\n            read_until_eof=False,\n            auth=auth,\n            proxy=proxy,\n            proxy_auth=proxy_auth,\n            ssl=ssl,\n            proxy_headers=proxy_headers,\n        )\n\n        try:\n            # check handshake\n            if resp.status != 101:\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid response status\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            if resp.headers.get(hdrs.UPGRADE, \"\").lower() != \"websocket\":\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid upgrade header\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            if resp.headers.get(hdrs.CONNECTION, \"\").lower() != \"upgrade\":\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid connection header\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            # key calculation\n            r_key = resp.headers.get(hdrs.SEC_WEBSOCKET_ACCEPT, \"\")\n            match = base64.b64encode(hashlib.sha1(sec_key + WS_KEY).digest()).decode()\n            if r_key != match:\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid challenge response\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            # websocket protocol\n            protocol = None\n            if protocols and hdrs.SEC_WEBSOCKET_PROTOCOL in resp.headers:\n                resp_protocols = [\n                    proto.strip()\n                    for proto in resp.headers[hdrs.SEC_WEBSOCKET_PROTOCOL].split(\",\")\n                ]\n\n                for proto in resp_protocols:\n                    if proto in protocols:\n                        protocol = proto\n                        break\n\n            # websocket compress\n            notakeover = False\n            if compress:\n                compress_hdrs = resp.headers.get(hdrs.SEC_WEBSOCKET_EXTENSIONS)\n                if compress_hdrs:\n                    try:\n                        compress, notakeover = ws_ext_parse(compress_hdrs)\n                    except WSHandshakeError as exc:\n                        raise WSServerHandshakeError(\n                            resp.request_info,\n                            resp.history,\n                            message=exc.args[0],\n                            status=resp.status,\n                            headers=resp.headers,\n                        ) from exc\n                else:\n                    compress = 0\n                    notakeover = False\n\n            conn = resp.connection\n            assert conn is not None\n            conn_proto = conn.protocol\n            assert conn_proto is not None\n\n            # For WS connection the read_timeout must be either receive_timeout or greater\n            # None == no timeout, i.e. infinite timeout, so None is the max timeout possible\n            if ws_timeout.ws_receive is None:\n                # Reset regardless\n                conn_proto.read_timeout = None\n            elif conn_proto.read_timeout is not None:\n                conn_proto.read_timeout = max(\n                    ws_timeout.ws_receive, conn_proto.read_timeout\n                )\n\n            transport = conn.transport\n            assert transport is not None\n            reader: FlowControlDataQueue[WSMessage] = FlowControlDataQueue(\n                conn_proto, 2**16, loop=self._loop\n            )\n            conn_proto.set_parser(WebSocketReader(reader, max_msg_size), reader)\n            writer = WebSocketWriter(\n                conn_proto,\n                transport,\n                use_mask=True,\n                compress=compress,\n                notakeover=notakeover,\n            )\n        except BaseException:\n            resp.close()\n            raise\n        else:\n            return self._ws_response_class(\n                reader,\n                writer,\n                protocol,\n                resp,\n                ws_timeout,\n                autoclose,\n                autoping,\n                self._loop,\n                heartbeat=heartbeat,\n                compress=compress,\n                client_notakeover=notakeover,\n            )\n\n    def _prepare_headers(self, headers: Optional[LooseHeaders]) -> \"CIMultiDict[str]\":\n        \"\"\"Add default headers and transform it to CIMultiDict\"\"\"\n        # Convert headers to MultiDict\n        result = CIMultiDict(self._default_headers)\n        if headers:\n            if not isinstance(headers, (MultiDictProxy, MultiDict)):\n                headers = CIMultiDict(headers)\n            added_names: Set[str] = set()\n            for key, value in headers.items():\n                if key in added_names:\n                    result.add(key, value)\n                else:\n                    result[key] = value\n                    added_names.add(key)\n        return result\n\n    if sys.version_info >= (3, 11) and TYPE_CHECKING:\n\n        def get(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def options(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def head(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def post(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def put(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def patch(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def delete(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n    else:\n\n        def get(\n            self, url: StrOrURL, *, allow_redirects: bool = True, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP GET request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_GET, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def options(\n            self, url: StrOrURL, *, allow_redirects: bool = True, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP OPTIONS request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_OPTIONS, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def head(\n            self, url: StrOrURL, *, allow_redirects: bool = False, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP HEAD request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_HEAD, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def post(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP POST request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_POST, url, data=data, **kwargs)\n            )\n\n        def put(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP PUT request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_PUT, url, data=data, **kwargs)\n            )\n\n        def patch(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP PATCH request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_PATCH, url, data=data, **kwargs)\n            )\n\n        def delete(self, url: StrOrURL, **kwargs: Any) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP DELETE request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_DELETE, url, **kwargs)\n            )\n\n    async def close(self) -> None:\n        \"\"\"Close underlying connector.\n\n        Release all acquired resources.\n        \"\"\"\n        if not self.closed:\n            if self._connector is not None and self._connector_owner:\n                await self._connector.close()\n            self._connector = None\n\n    @property\n    def closed(self) -> bool:\n        \"\"\"Is client session closed.\n\n        A readonly property.\n        \"\"\"\n        return self._connector is None or self._connector.closed\n\n    @property\n    def connector(self) -> Optional[BaseConnector]:\n        \"\"\"Connector instance used for the session.\"\"\"\n        return self._connector\n\n    @property\n    def cookie_jar(self) -> AbstractCookieJar:\n        \"\"\"The session cookies.\"\"\"\n        return self._cookie_jar\n\n    @property\n    def version(self) -> Tuple[int, int]:\n        \"\"\"The session HTTP protocol version.\"\"\"\n        return self._version\n\n    @property\n    def requote_redirect_url(self) -> bool:\n        \"\"\"Do URL requoting on redirection handling.\"\"\"\n        return self._requote_redirect_url\n\n    @requote_redirect_url.setter\n    def requote_redirect_url(self, val: bool) -> None:\n        \"\"\"Do URL requoting on redirection handling.\"\"\"\n        warnings.warn(\n            \"session.requote_redirect_url modification is deprecated #2778\",\n            DeprecationWarning,\n            stacklevel=2,\n        )\n        self._requote_redirect_url = val\n\n    @property\n    def loop(self) -> asyncio.AbstractEventLoop:\n        \"\"\"Session's loop.\"\"\"\n        warnings.warn(\n            \"client.loop property is deprecated\", DeprecationWarning, stacklevel=2\n        )\n        return self._loop\n\n    @property\n    def timeout(self) -> ClientTimeout:\n        \"\"\"Timeout for the session.\"\"\"\n        return self._timeout\n\n    @property\n    def headers(self) -> \"CIMultiDict[str]\":\n        \"\"\"The default headers of the client session.\"\"\"\n        return self._default_headers\n\n    @property\n    def skip_auto_headers(self) -> FrozenSet[istr]:\n        \"\"\"Headers for which autogeneration should be skipped\"\"\"\n        return self._skip_auto_headers\n\n    @property\n    def auth(self) -> Optional[BasicAuth]:\n        \"\"\"An object that represents HTTP Basic Authorization\"\"\"\n        return self._default_auth\n\n    @property\n    def json_serialize(self) -> JSONEncoder:\n        \"\"\"Json serializer callable\"\"\"\n        return self._json_serialize\n\n    @property\n    def connector_owner(self) -> bool:\n        \"\"\"Should connector be closed on session closing\"\"\"\n        return self._connector_owner\n\n    @property\n    def raise_for_status(\n        self,\n    ) -> Union[bool, Callable[[ClientResponse], Awaitable[None]]]:\n        \"\"\"Should `ClientResponse.raise_for_status()` be called for each response.\"\"\"\n        return self._raise_for_status\n\n    @property\n    def auto_decompress(self) -> bool:\n        \"\"\"Should the body response be automatically decompressed.\"\"\"\n        return self._auto_decompress\n\n    @property\n    def trust_env(self) -> bool:\n        \"\"\"\n        Should proxies information from environment or netrc be trusted.\n\n        Information is from HTTP_PROXY / HTTPS_PROXY environment variables\n        or ~/.netrc file if present.\n        \"\"\"\n        return self._trust_env\n\n    @property\n    def trace_configs(self) -> List[TraceConfig]:\n        \"\"\"A list of TraceConfig instances used for client tracing\"\"\"\n        return self._trace_configs\n\n    def detach(self) -> None:\n        \"\"\"Detach connector from session without closing the former.\n\n        Session is switched to closed state anyway.\n        \"\"\"\n        self._connector = None\n\n    def __enter__(self) -> None:\n        raise TypeError(\"Use async with instead\")\n\n    def __exit__(\n        self,\n        exc_type: Optional[Type[BaseException]],\n        exc_val: Optional[BaseException],\n        exc_tb: Optional[TracebackType],\n    ) -> None:\n        # __exit__ should exist in pair with __enter__ but never executed\n        pass  # pragma: no cover\n\n    async def __aenter__(self) -> \"ClientSession\":\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        await self.close()",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 225,
                                "end_lineno": 1373,
                                "parent": null
                            }
                        },
                        {
                            "file_name": "aiohttp/client.py",
                            "type": "class",
                            "name": "ClientSession",
                            "content": "class ClientSession:\n    \"\"\"First-class interface for making HTTP requests.\"\"\"\n\n    ATTRS = frozenset(\n        [\n            \"_base_url\",\n            \"_source_traceback\",\n            \"_connector\",\n            \"requote_redirect_url\",\n            \"_loop\",\n            \"_cookie_jar\",\n            \"_connector_owner\",\n            \"_default_auth\",\n            \"_version\",\n            \"_json_serialize\",\n            \"_requote_redirect_url\",\n            \"_timeout\",\n            \"_raise_for_status\",\n            \"_auto_decompress\",\n            \"_trust_env\",\n            \"_default_headers\",\n            \"_skip_auto_headers\",\n            \"_request_class\",\n            \"_response_class\",\n            \"_ws_response_class\",\n            \"_trace_configs\",\n            \"_read_bufsize\",\n            \"_max_line_size\",\n            \"_max_field_size\",\n            \"_resolve_charset\",\n            \"_default_proxy\",\n            \"_default_proxy_auth\",\n        ]\n    )\n\n    _source_traceback: Optional[traceback.StackSummary] = None\n    _connector: Optional[BaseConnector] = None\n\n    def __init__(\n        self,\n        base_url: Optional[StrOrURL] = None,\n        *,\n        connector: Optional[BaseConnector] = None,\n        loop: Optional[asyncio.AbstractEventLoop] = None,\n        cookies: Optional[LooseCookies] = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        skip_auto_headers: Optional[Iterable[str]] = None,\n        auth: Optional[BasicAuth] = None,\n        json_serialize: JSONEncoder = json.dumps,\n        request_class: Type[ClientRequest] = ClientRequest,\n        response_class: Type[ClientResponse] = ClientResponse,\n        ws_response_class: Type[ClientWebSocketResponse] = ClientWebSocketResponse,\n        version: HttpVersion = http.HttpVersion11,\n        cookie_jar: Optional[AbstractCookieJar] = None,\n        connector_owner: bool = True,\n        raise_for_status: Union[\n            bool, Callable[[ClientResponse], Awaitable[None]]\n        ] = False,\n        read_timeout: Union[float, _SENTINEL] = sentinel,\n        conn_timeout: Optional[float] = None,\n        timeout: Union[object, ClientTimeout] = sentinel,\n        auto_decompress: bool = True,\n        trust_env: bool = False,\n        requote_redirect_url: bool = True,\n        trace_configs: Optional[List[TraceConfig]] = None,\n        read_bufsize: int = 2**16,\n        max_line_size: int = 8190,\n        max_field_size: int = 8190,\n        fallback_charset_resolver: _CharsetResolver = lambda r, b: \"utf-8\",\n    ) -> None:\n        # We initialise _connector to None immediately, as it's referenced in __del__()\n        # and could cause issues if an exception occurs during initialisation.\n        self._connector: Optional[BaseConnector] = None\n\n        if loop is None:\n            if connector is not None:\n                loop = connector._loop\n\n        loop = loop or asyncio.get_running_loop()\n\n        if base_url is None or isinstance(base_url, URL):\n            self._base_url: Optional[URL] = base_url\n        else:\n            self._base_url = URL(base_url)\n            assert (\n                self._base_url.origin() == self._base_url\n            ), \"Only absolute URLs without path part are supported\"\n\n        if timeout is sentinel or timeout is None:\n            self._timeout = DEFAULT_TIMEOUT\n            if read_timeout is not sentinel:\n                warnings.warn(\n                    \"read_timeout is deprecated, use timeout argument instead\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n                self._timeout = attr.evolve(self._timeout, total=read_timeout)\n            if conn_timeout is not None:\n                self._timeout = attr.evolve(self._timeout, connect=conn_timeout)\n                warnings.warn(\n                    \"conn_timeout is deprecated, use timeout argument instead\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n        else:\n            if not isinstance(timeout, ClientTimeout):\n                raise ValueError(\n                    f\"timeout parameter cannot be of {type(timeout)} type, \"\n                    \"please use 'timeout=ClientTimeout(...)'\",\n                )\n            self._timeout = timeout\n            if read_timeout is not sentinel:\n                raise ValueError(\n                    \"read_timeout and timeout parameters \"\n                    \"conflict, please setup \"\n                    \"timeout.read\"\n                )\n            if conn_timeout is not None:\n                raise ValueError(\n                    \"conn_timeout and timeout parameters \"\n                    \"conflict, please setup \"\n                    \"timeout.connect\"\n                )\n\n        if connector is None:\n            connector = TCPConnector(loop=loop)\n\n        if connector._loop is not loop:\n            raise RuntimeError(\"Session and connector has to use same event loop\")\n\n        self._loop = loop\n\n        if loop.get_debug():\n            self._source_traceback = traceback.extract_stack(sys._getframe(1))\n\n        if cookie_jar is None:\n            cookie_jar = CookieJar(loop=loop)\n        self._cookie_jar = cookie_jar\n\n        if cookies is not None:\n            self._cookie_jar.update_cookies(cookies)\n\n        self._connector = connector\n        self._connector_owner = connector_owner\n        self._default_auth = auth\n        self._version = version\n        self._json_serialize = json_serialize\n        self._raise_for_status = raise_for_status\n        self._auto_decompress = auto_decompress\n        self._trust_env = trust_env\n        self._requote_redirect_url = requote_redirect_url\n        self._read_bufsize = read_bufsize\n        self._max_line_size = max_line_size\n        self._max_field_size = max_field_size\n\n        # Convert to list of tuples\n        if headers:\n            real_headers: CIMultiDict[str] = CIMultiDict(headers)\n        else:\n            real_headers = CIMultiDict()\n        self._default_headers: CIMultiDict[str] = real_headers\n        if skip_auto_headers is not None:\n            self._skip_auto_headers = frozenset(istr(i) for i in skip_auto_headers)\n        else:\n            self._skip_auto_headers = frozenset()\n\n        self._request_class = request_class\n        self._response_class = response_class\n        self._ws_response_class = ws_response_class\n\n        self._trace_configs = trace_configs or []\n        for trace_config in self._trace_configs:\n            trace_config.freeze()\n\n        self._resolve_charset = fallback_charset_resolver\n\n        self._default_proxy = proxy\n        self._default_proxy_auth = proxy_auth\n\n    def __init_subclass__(cls: Type[\"ClientSession\"]) -> None:\n        warnings.warn(\n            \"Inheritance class {} from ClientSession \"\n            \"is discouraged\".format(cls.__name__),\n            DeprecationWarning,\n            stacklevel=2,\n        )\n\n    if DEBUG:\n\n        def __setattr__(self, name: str, val: Any) -> None:\n            if name not in self.ATTRS:\n                warnings.warn(\n                    \"Setting custom ClientSession.{} attribute \"\n                    \"is discouraged\".format(name),\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n            super().__setattr__(name, val)\n\n    def __del__(self, _warnings: Any = warnings) -> None:\n        if not self.closed:\n            kwargs = {\"source\": self}\n            _warnings.warn(\n                f\"Unclosed client session {self!r}\", ResourceWarning, **kwargs\n            )\n            context = {\"client_session\": self, \"message\": \"Unclosed client session\"}\n            if self._source_traceback is not None:\n                context[\"source_traceback\"] = self._source_traceback\n            self._loop.call_exception_handler(context)\n\n    if sys.version_info >= (3, 11) and TYPE_CHECKING:\n\n        def request(\n            self,\n            method: str,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n    else:\n\n        def request(\n            self, method: str, url: StrOrURL, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP request.\"\"\"\n            return _RequestContextManager(self._request(method, url, **kwargs))\n\n    def _build_url(self, str_or_url: StrOrURL) -> URL:\n        url = URL(str_or_url)\n        if self._base_url is None:\n            return url\n        else:\n            assert not url.absolute and url.path.startswith(\"/\")\n            return self._base_url.join(url)\n\n    async def _request(\n        self,\n        method: str,\n        str_or_url: StrOrURL,\n        *,\n        params: Query = None,\n        data: Any = None,\n        json: Any = None,\n        cookies: Optional[LooseCookies] = None,\n        headers: Optional[LooseHeaders] = None,\n        skip_auto_headers: Optional[Iterable[str]] = None,\n        auth: Optional[BasicAuth] = None,\n        allow_redirects: bool = True,\n        max_redirects: int = 10,\n        compress: Union[str, bool, None] = None,\n        chunked: Optional[bool] = None,\n        expect100: bool = False,\n        raise_for_status: Union[\n            None, bool, Callable[[ClientResponse], Awaitable[None]]\n        ] = None,\n        read_until_eof: bool = True,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        timeout: Union[ClientTimeout, _SENTINEL] = sentinel,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        server_hostname: Optional[str] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        trace_request_ctx: Optional[Mapping[str, str]] = None,\n        read_bufsize: Optional[int] = None,\n        auto_decompress: Optional[bool] = None,\n        max_line_size: Optional[int] = None,\n        max_field_size: Optional[int] = None,\n    ) -> ClientResponse:\n\n        # NOTE: timeout clamps existing connect and read timeouts.  We cannot\n        # set the default to None because we need to detect if the user wants\n        # to use the existing timeouts by setting timeout to None.\n\n        if self.closed:\n            raise RuntimeError(\"Session is closed\")\n\n        ssl = _merge_ssl_params(ssl, verify_ssl, ssl_context, fingerprint)\n\n        if data is not None and json is not None:\n            raise ValueError(\n                \"data and json parameters can not be used at the same time\"\n            )\n        elif json is not None:\n            data = payload.JsonPayload(json, dumps=self._json_serialize)\n\n        if not isinstance(chunked, bool) and chunked is not None:\n            warnings.warn(\"Chunk size is deprecated #1615\", DeprecationWarning)\n\n        redirects = 0\n        history = []\n        version = self._version\n        params = params or {}\n\n        # Merge with default headers and transform to CIMultiDict\n        headers = self._prepare_headers(headers)\n\n        try:\n            url = self._build_url(str_or_url)\n        except ValueError as e:\n            raise InvalidUrlClientError(str_or_url) from e\n\n        assert self._connector is not None\n        if url.scheme not in self._connector.allowed_protocol_schema_set:\n            raise NonHttpUrlClientError(url)\n\n        skip_headers = set(self._skip_auto_headers)\n        if skip_auto_headers is not None:\n            for i in skip_auto_headers:\n                skip_headers.add(istr(i))\n\n        if proxy is None:\n            proxy = self._default_proxy\n        if proxy_auth is None:\n            proxy_auth = self._default_proxy_auth\n\n        if proxy is None:\n            proxy_headers = None\n        else:\n            proxy_headers = self._prepare_headers(proxy_headers)\n            try:\n                proxy = URL(proxy)\n            except ValueError as e:\n                raise InvalidURL(proxy) from e\n\n        if timeout is sentinel:\n            real_timeout: ClientTimeout = self._timeout\n        else:\n            if not isinstance(timeout, ClientTimeout):\n                real_timeout = ClientTimeout(total=timeout)\n            else:\n                real_timeout = timeout\n        # timeout is cumulative for all request operations\n        # (request, redirects, responses, data consuming)\n        tm = TimeoutHandle(\n            self._loop, real_timeout.total, ceil_threshold=real_timeout.ceil_threshold\n        )\n        handle = tm.start()\n\n        if read_bufsize is None:\n            read_bufsize = self._read_bufsize\n\n        if auto_decompress is None:\n            auto_decompress = self._auto_decompress\n\n        if max_line_size is None:\n            max_line_size = self._max_line_size\n\n        if max_field_size is None:\n            max_field_size = self._max_field_size\n\n        traces = [\n            Trace(\n                self,\n                trace_config,\n                trace_config.trace_config_ctx(trace_request_ctx=trace_request_ctx),\n            )\n            for trace_config in self._trace_configs\n        ]\n\n        for trace in traces:\n            await trace.send_request_start(method, url.update_query(params), headers)\n\n        timer = tm.timer()\n        try:\n            with timer:\n                # https://www.rfc-editor.org/rfc/rfc9112.html#name-retrying-requests\n                retry_persistent_connection = method in IDEMPOTENT_METHODS\n                while True:\n                    url, auth_from_url = strip_auth_from_url(url)\n                    if not url.raw_host:\n                        # NOTE: Bail early, otherwise, causes `InvalidURL` through\n                        # NOTE: `self._request_class()` below.\n                        err_exc_cls = (\n                            InvalidUrlRedirectClientError\n                            if redirects\n                            else InvalidUrlClientError\n                        )\n                        raise err_exc_cls(url)\n                    if auth and auth_from_url:\n                        raise ValueError(\n                            \"Cannot combine AUTH argument with \"\n                            \"credentials encoded in URL\"\n                        )\n\n                    if auth is None:\n                        auth = auth_from_url\n\n                    if auth is None and (\n                        not self._base_url or self._base_url.origin() == url.origin()\n                    ):\n                        auth = self._default_auth\n                    # It would be confusing if we support explicit\n                    # Authorization header with auth argument\n                    if (\n                        headers is not None\n                        and auth is not None\n                        and hdrs.AUTHORIZATION in headers\n                    ):\n                        raise ValueError(\n                            \"Cannot combine AUTHORIZATION header \"\n                            \"with AUTH argument or credentials \"\n                            \"encoded in URL\"\n                        )\n\n                    all_cookies = self._cookie_jar.filter_cookies(url)\n\n                    if cookies is not None:\n                        tmp_cookie_jar = CookieJar()\n                        tmp_cookie_jar.update_cookies(cookies)\n                        req_cookies = tmp_cookie_jar.filter_cookies(url)\n                        if req_cookies:\n                            all_cookies.load(req_cookies)\n\n                    if proxy is not None:\n                        proxy = URL(proxy)\n                    elif self._trust_env:\n                        with suppress(LookupError):\n                            proxy, proxy_auth = get_env_proxy_for_url(url)\n\n                    req = self._request_class(\n                        method,\n                        url,\n                        params=params,\n                        headers=headers,\n                        skip_auto_headers=skip_headers if skip_headers else None,\n                        data=data,\n                        cookies=all_cookies,\n                        auth=auth,\n                        version=version,\n                        compress=compress,\n                        chunked=chunked,\n                        expect100=expect100,\n                        loop=self._loop,\n                        response_class=self._response_class,\n                        proxy=proxy,\n                        proxy_auth=proxy_auth,\n                        timer=timer,\n                        session=self,\n                        ssl=ssl if ssl is not None else True,\n                        server_hostname=server_hostname,\n                        proxy_headers=proxy_headers,\n                        traces=traces,\n                        trust_env=self.trust_env,\n                    )\n\n                    # connection timeout\n                    try:\n                        async with ceil_timeout(\n                            real_timeout.connect,\n                            ceil_threshold=real_timeout.ceil_threshold,\n                        ):\n                            conn = await self._connector.connect(\n                                req, traces=traces, timeout=real_timeout\n                            )\n                    except asyncio.TimeoutError as exc:\n                        raise ConnectionTimeoutError(\n                            f\"Connection timeout to host {url}\"\n                        ) from exc\n\n                    assert conn.transport is not None\n\n                    assert conn.protocol is not None\n                    conn.protocol.set_response_params(\n                        timer=timer,\n                        skip_payload=method_must_be_empty_body(method),\n                        read_until_eof=read_until_eof,\n                        auto_decompress=auto_decompress,\n                        read_timeout=real_timeout.sock_read,\n                        read_bufsize=read_bufsize,\n                        timeout_ceil_threshold=self._connector._timeout_ceil_threshold,\n                        max_line_size=max_line_size,\n                        max_field_size=max_field_size,\n                    )\n\n                    try:\n                        try:\n                            resp = await req.send(conn)\n                            try:\n                                await resp.start(conn)\n                            except BaseException:\n                                resp.close()\n                                raise\n                        except BaseException:\n                            conn.close()\n                            raise\n                    except (ClientOSError, ServerDisconnectedError):\n                        if retry_persistent_connection:\n                            retry_persistent_connection = False\n                            continue\n                        raise\n                    except ClientError:\n                        raise\n                    except OSError as exc:\n                        if exc.errno is None and isinstance(exc, asyncio.TimeoutError):\n                            raise\n                        raise ClientOSError(*exc.args) from exc\n\n                    self._cookie_jar.update_cookies(resp.cookies, resp.url)\n\n                    # redirects\n                    if resp.status in (301, 302, 303, 307, 308) and allow_redirects:\n\n                        for trace in traces:\n                            await trace.send_request_redirect(\n                                method, url.update_query(params), headers, resp\n                            )\n\n                        redirects += 1\n                        history.append(resp)\n                        if max_redirects and redirects >= max_redirects:\n                            resp.close()\n                            raise TooManyRedirects(\n                                history[0].request_info, tuple(history)\n                            )\n\n                        # For 301 and 302, mimic IE, now changed in RFC\n                        # https://github.com/kennethreitz/requests/pull/269\n                        if (resp.status == 303 and resp.method != hdrs.METH_HEAD) or (\n                            resp.status in (301, 302) and resp.method == hdrs.METH_POST\n                        ):\n                            method = hdrs.METH_GET\n                            data = None\n                            if headers.get(hdrs.CONTENT_LENGTH):\n                                headers.pop(hdrs.CONTENT_LENGTH)\n\n                        r_url = resp.headers.get(hdrs.LOCATION) or resp.headers.get(\n                            hdrs.URI\n                        )\n                        if r_url is None:\n                            # see github.com/aio-libs/aiohttp/issues/2022\n                            break\n                        else:\n                            # reading from correct redirection\n                            # response is forbidden\n                            resp.release()\n\n                        try:\n                            parsed_redirect_url = URL(\n                                r_url, encoded=not self._requote_redirect_url\n                            )\n                        except ValueError as e:\n                            raise InvalidUrlRedirectClientError(\n                                r_url,\n                                \"Server attempted redirecting to a location that does not look like a URL\",\n                            ) from e\n\n                        scheme = parsed_redirect_url.scheme\n                        if scheme not in HTTP_AND_EMPTY_SCHEMA_SET:\n                            resp.close()\n                            raise NonHttpUrlRedirectClientError(r_url)\n                        elif not scheme:\n                            parsed_redirect_url = url.join(parsed_redirect_url)\n\n                        try:\n                            redirect_origin = parsed_redirect_url.origin()\n                        except ValueError as origin_val_err:\n                            raise InvalidUrlRedirectClientError(\n                                parsed_redirect_url,\n                                \"Invalid redirect URL origin\",\n                            ) from origin_val_err\n\n                        if url.origin() != redirect_origin:\n                            auth = None\n                            headers.pop(hdrs.AUTHORIZATION, None)\n\n                        url = parsed_redirect_url\n                        params = {}\n                        resp.release()\n                        continue\n\n                    break\n\n            # check response status\n            if raise_for_status is None:\n                raise_for_status = self._raise_for_status\n\n            if raise_for_status is None:\n                pass\n            elif callable(raise_for_status):\n                await raise_for_status(resp)\n            elif raise_for_status:\n                resp.raise_for_status()\n\n            # register connection\n            if handle is not None:\n                if resp.connection is not None:\n                    resp.connection.add_callback(handle.cancel)\n                else:\n                    handle.cancel()\n\n            resp._history = tuple(history)\n\n            for trace in traces:\n                await trace.send_request_end(\n                    method, url.update_query(params), headers, resp\n                )\n            return resp\n\n        except BaseException as e:\n            # cleanup timer\n            tm.close()\n            if handle:\n                handle.cancel()\n                handle = None\n\n            for trace in traces:\n                await trace.send_request_exception(\n                    method, url.update_query(params), headers, e\n                )\n            raise\n\n    def ws_connect(\n        self,\n        url: StrOrURL,\n        *,\n        method: str = hdrs.METH_GET,\n        protocols: Iterable[str] = (),\n        timeout: Union[ClientWSTimeout, _SENTINEL] = sentinel,\n        receive_timeout: Optional[float] = None,\n        autoclose: bool = True,\n        autoping: bool = True,\n        heartbeat: Optional[float] = None,\n        auth: Optional[BasicAuth] = None,\n        origin: Optional[str] = None,\n        params: Query = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        compress: int = 0,\n        max_msg_size: int = 4 * 1024 * 1024,\n    ) -> \"_WSRequestContextManager\":\n        \"\"\"Initiate websocket connection.\"\"\"\n        return _WSRequestContextManager(\n            self._ws_connect(\n                url,\n                method=method,\n                protocols=protocols,\n                timeout=timeout,\n                receive_timeout=receive_timeout,\n                autoclose=autoclose,\n                autoping=autoping,\n                heartbeat=heartbeat,\n                auth=auth,\n                origin=origin,\n                params=params,\n                headers=headers,\n                proxy=proxy,\n                proxy_auth=proxy_auth,\n                ssl=ssl,\n                verify_ssl=verify_ssl,\n                fingerprint=fingerprint,\n                ssl_context=ssl_context,\n                proxy_headers=proxy_headers,\n                compress=compress,\n                max_msg_size=max_msg_size,\n            )\n        )\n\n    async def _ws_connect(\n        self,\n        url: StrOrURL,\n        *,\n        method: str = hdrs.METH_GET,\n        protocols: Iterable[str] = (),\n        timeout: Union[ClientWSTimeout, _SENTINEL] = sentinel,\n        receive_timeout: Optional[float] = None,\n        autoclose: bool = True,\n        autoping: bool = True,\n        heartbeat: Optional[float] = None,\n        auth: Optional[BasicAuth] = None,\n        origin: Optional[str] = None,\n        params: Query = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        compress: int = 0,\n        max_msg_size: int = 4 * 1024 * 1024,\n    ) -> ClientWebSocketResponse:\n        if timeout is not sentinel:\n            if isinstance(timeout, ClientWSTimeout):\n                ws_timeout = timeout\n            else:\n                warnings.warn(\n                    \"parameter 'timeout' of type 'float' \"\n                    \"is deprecated, please use \"\n                    \"'timeout=ClientWSTimeout(ws_close=...)'\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n                ws_timeout = ClientWSTimeout(ws_close=timeout)\n        else:\n            ws_timeout = DEFAULT_WS_CLIENT_TIMEOUT\n        if receive_timeout is not None:\n            warnings.warn(\n                \"float parameter 'receive_timeout' \"\n                \"is deprecated, please use parameter \"\n                \"'timeout=ClientWSTimeout(ws_receive=...)'\",\n                DeprecationWarning,\n                stacklevel=2,\n            )\n            ws_timeout = attr.evolve(ws_timeout, ws_receive=receive_timeout)\n\n        if headers is None:\n            real_headers: CIMultiDict[str] = CIMultiDict()\n        else:\n            real_headers = CIMultiDict(headers)\n\n        default_headers = {\n            hdrs.UPGRADE: \"websocket\",\n            hdrs.CONNECTION: \"Upgrade\",\n            hdrs.SEC_WEBSOCKET_VERSION: \"13\",\n        }\n\n        for key, value in default_headers.items():\n            real_headers.setdefault(key, value)\n\n        sec_key = base64.b64encode(os.urandom(16))\n        real_headers[hdrs.SEC_WEBSOCKET_KEY] = sec_key.decode()\n\n        if protocols:\n            real_headers[hdrs.SEC_WEBSOCKET_PROTOCOL] = \",\".join(protocols)\n        if origin is not None:\n            real_headers[hdrs.ORIGIN] = origin\n        if compress:\n            extstr = ws_ext_gen(compress=compress)\n            real_headers[hdrs.SEC_WEBSOCKET_EXTENSIONS] = extstr\n\n        # For the sake of backward compatibility, if user passes in None, convert it to True\n        if ssl is None:\n            warnings.warn(\n                \"ssl=None is deprecated, please use ssl=True\",\n                DeprecationWarning,\n                stacklevel=2,\n            )\n            ssl = True\n        ssl = _merge_ssl_params(ssl, verify_ssl, ssl_context, fingerprint)\n\n        # send request\n        resp = await self.request(\n            method,\n            url,\n            params=params,\n            headers=real_headers,\n            read_until_eof=False,\n            auth=auth,\n            proxy=proxy,\n            proxy_auth=proxy_auth,\n            ssl=ssl,\n            proxy_headers=proxy_headers,\n        )\n\n        try:\n            # check handshake\n            if resp.status != 101:\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid response status\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            if resp.headers.get(hdrs.UPGRADE, \"\").lower() != \"websocket\":\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid upgrade header\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            if resp.headers.get(hdrs.CONNECTION, \"\").lower() != \"upgrade\":\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid connection header\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            # key calculation\n            r_key = resp.headers.get(hdrs.SEC_WEBSOCKET_ACCEPT, \"\")\n            match = base64.b64encode(hashlib.sha1(sec_key + WS_KEY).digest()).decode()\n            if r_key != match:\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid challenge response\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            # websocket protocol\n            protocol = None\n            if protocols and hdrs.SEC_WEBSOCKET_PROTOCOL in resp.headers:\n                resp_protocols = [\n                    proto.strip()\n                    for proto in resp.headers[hdrs.SEC_WEBSOCKET_PROTOCOL].split(\",\")\n                ]\n\n                for proto in resp_protocols:\n                    if proto in protocols:\n                        protocol = proto\n                        break\n\n            # websocket compress\n            notakeover = False\n            if compress:\n                compress_hdrs = resp.headers.get(hdrs.SEC_WEBSOCKET_EXTENSIONS)\n                if compress_hdrs:\n                    try:\n                        compress, notakeover = ws_ext_parse(compress_hdrs)\n                    except WSHandshakeError as exc:\n                        raise WSServerHandshakeError(\n                            resp.request_info,\n                            resp.history,\n                            message=exc.args[0],\n                            status=resp.status,\n                            headers=resp.headers,\n                        ) from exc\n                else:\n                    compress = 0\n                    notakeover = False\n\n            conn = resp.connection\n            assert conn is not None\n            conn_proto = conn.protocol\n            assert conn_proto is not None\n\n            # For WS connection the read_timeout must be either receive_timeout or greater\n            # None == no timeout, i.e. infinite timeout, so None is the max timeout possible\n            if ws_timeout.ws_receive is None:\n                # Reset regardless\n                conn_proto.read_timeout = None\n            elif conn_proto.read_timeout is not None:\n                conn_proto.read_timeout = max(\n                    ws_timeout.ws_receive, conn_proto.read_timeout\n                )\n\n            transport = conn.transport\n            assert transport is not None\n            reader: FlowControlDataQueue[WSMessage] = FlowControlDataQueue(\n                conn_proto, 2**16, loop=self._loop\n            )\n            conn_proto.set_parser(WebSocketReader(reader, max_msg_size), reader)\n            writer = WebSocketWriter(\n                conn_proto,\n                transport,\n                use_mask=True,\n                compress=compress,\n                notakeover=notakeover,\n            )\n        except BaseException:\n            resp.close()\n            raise\n        else:\n            return self._ws_response_class(\n                reader,\n                writer,\n                protocol,\n                resp,\n                ws_timeout,\n                autoclose,\n                autoping,\n                self._loop,\n                heartbeat=heartbeat,\n                compress=compress,\n                client_notakeover=notakeover,\n            )\n\n    def _prepare_headers(self, headers: Optional[LooseHeaders]) -> \"CIMultiDict[str]\":\n        \"\"\"Add default headers and transform it to CIMultiDict\"\"\"\n        # Convert headers to MultiDict\n        result = CIMultiDict(self._default_headers)\n        if headers:\n            if not isinstance(headers, (MultiDictProxy, MultiDict)):\n                headers = CIMultiDict(headers)\n            added_names: Set[str] = set()\n            for key, value in headers.items():\n                if key in added_names:\n                    result.add(key, value)\n                else:\n                    result[key] = value\n                    added_names.add(key)\n        return result\n\n    if sys.version_info >= (3, 11) and TYPE_CHECKING:\n\n        def get(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def options(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def head(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def post(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def put(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def patch(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def delete(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n    else:\n\n        def get(\n            self, url: StrOrURL, *, allow_redirects: bool = True, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP GET request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_GET, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def options(\n            self, url: StrOrURL, *, allow_redirects: bool = True, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP OPTIONS request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_OPTIONS, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def head(\n            self, url: StrOrURL, *, allow_redirects: bool = False, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP HEAD request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_HEAD, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def post(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP POST request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_POST, url, data=data, **kwargs)\n            )\n\n        def put(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP PUT request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_PUT, url, data=data, **kwargs)\n            )\n\n        def patch(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP PATCH request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_PATCH, url, data=data, **kwargs)\n            )\n\n        def delete(self, url: StrOrURL, **kwargs: Any) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP DELETE request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_DELETE, url, **kwargs)\n            )\n\n    async def close(self) -> None:\n        \"\"\"Close underlying connector.\n\n        Release all acquired resources.\n        \"\"\"\n        if not self.closed:\n            if self._connector is not None and self._connector_owner:\n                await self._connector.close()\n            self._connector = None\n\n    @property\n    def closed(self) -> bool:\n        \"\"\"Is client session closed.\n\n        A readonly property.\n        \"\"\"\n        return self._connector is None or self._connector.closed\n\n    @property\n    def connector(self) -> Optional[BaseConnector]:\n        \"\"\"Connector instance used for the session.\"\"\"\n        return self._connector\n\n    @property\n    def cookie_jar(self) -> AbstractCookieJar:\n        \"\"\"The session cookies.\"\"\"\n        return self._cookie_jar\n\n    @property\n    def version(self) -> Tuple[int, int]:\n        \"\"\"The session HTTP protocol version.\"\"\"\n        return self._version\n\n    @property\n    def requote_redirect_url(self) -> bool:\n        \"\"\"Do URL requoting on redirection handling.\"\"\"\n        return self._requote_redirect_url\n\n    @requote_redirect_url.setter\n    def requote_redirect_url(self, val: bool) -> None:\n        \"\"\"Do URL requoting on redirection handling.\"\"\"\n        warnings.warn(\n            \"session.requote_redirect_url modification is deprecated #2778\",\n            DeprecationWarning,\n            stacklevel=2,\n        )\n        self._requote_redirect_url = val\n\n    @property\n    def loop(self) -> asyncio.AbstractEventLoop:\n        \"\"\"Session's loop.\"\"\"\n        warnings.warn(\n            \"client.loop property is deprecated\", DeprecationWarning, stacklevel=2\n        )\n        return self._loop\n\n    @property\n    def timeout(self) -> ClientTimeout:\n        \"\"\"Timeout for the session.\"\"\"\n        return self._timeout\n\n    @property\n    def headers(self) -> \"CIMultiDict[str]\":\n        \"\"\"The default headers of the client session.\"\"\"\n        return self._default_headers\n\n    @property\n    def skip_auto_headers(self) -> FrozenSet[istr]:\n        \"\"\"Headers for which autogeneration should be skipped\"\"\"\n        return self._skip_auto_headers\n\n    @property\n    def auth(self) -> Optional[BasicAuth]:\n        \"\"\"An object that represents HTTP Basic Authorization\"\"\"\n        return self._default_auth\n\n    @property\n    def json_serialize(self) -> JSONEncoder:\n        \"\"\"Json serializer callable\"\"\"\n        return self._json_serialize\n\n    @property\n    def connector_owner(self) -> bool:\n        \"\"\"Should connector be closed on session closing\"\"\"\n        return self._connector_owner\n\n    @property\n    def raise_for_status(\n        self,\n    ) -> Union[bool, Callable[[ClientResponse], Awaitable[None]]]:\n        \"\"\"Should `ClientResponse.raise_for_status()` be called for each response.\"\"\"\n        return self._raise_for_status\n\n    @property\n    def auto_decompress(self) -> bool:\n        \"\"\"Should the body response be automatically decompressed.\"\"\"\n        return self._auto_decompress\n\n    @property\n    def trust_env(self) -> bool:\n        \"\"\"\n        Should proxies information from environment or netrc be trusted.\n\n        Information is from HTTP_PROXY / HTTPS_PROXY environment variables\n        or ~/.netrc file if present.\n        \"\"\"\n        return self._trust_env\n\n    @property\n    def trace_configs(self) -> List[TraceConfig]:\n        \"\"\"A list of TraceConfig instances used for client tracing\"\"\"\n        return self._trace_configs\n\n    def detach(self) -> None:\n        \"\"\"Detach connector from session without closing the former.\n\n        Session is switched to closed state anyway.\n        \"\"\"\n        self._connector = None\n\n    def __enter__(self) -> None:\n        raise TypeError(\"Use async with instead\")\n\n    def __exit__(\n        self,\n        exc_type: Optional[Type[BaseException]],\n        exc_val: Optional[BaseException],\n        exc_tb: Optional[TracebackType],\n    ) -> None:\n        # __exit__ should exist in pair with __enter__ but never executed\n        pass  # pragma: no cover\n\n    async def __aenter__(self) -> \"ClientSession\":\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        await self.close()",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 225,
                            "end_lineno": 1373,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": ".. _aiohttp-client-advanced:\n\nAdvanced Client Usage\n=====================\n\n.. currentmodule:: aiohttp\n\n.. _aiohttp-client-session:\n\nClient Session\n--------------\n\n:class:`ClientSession` is the heart and the main entry point for all\nclient API operations.\n\nCreate the session first, use the instance for performing HTTP\nrequests and initiating WebSocket connections.\n\nThe session contains a cookie storage and connection pool, thus\ncookies and connections are shared between HTTP requests sent by the\nsame session.\n\nCustom Request Headers\n----------------------\n\nIf you need to add HTTP headers to a request, pass them in a\n:class:`dict` to the *headers* parameter.\n\nFor example, if you want to specify the content-type directly::\n\n    url = 'http://example.com/image'\n    payload = b'GIF89a\\x01\\x00\\x01\\x00\\x00\\xff\\x00,\\x00\\x00'\n              b'\\x00\\x00\\x01\\x00\\x01\\x00\\x00\\x02\\x00;'\n    headers = {'content-type': 'image/gif'}\n\n    await session.post(url,\n                       data=payload,\n                       headers=headers)\n\nYou also can set default headers for all session requests::\n\n    headers={\"Authorization\": \"Basic bG9naW46cGFzcw==\"}\n    async with aiohttp.ClientSession(headers=headers) as session:\n        async with session.get(\"http://httpbin.org/headers\") as r:\n            json_body = await r.json()\n            assert json_body['headers']['Authorization'] == \\\n                'Basic bG9naW46cGFzcw=='\n\nTypical use case is sending JSON body. You can specify content type\ndirectly as shown above, but it is more convenient to use special keyword\n``json``::\n\n    await session.post(url, json={'example': 'text'})\n\nFor *text/plain* ::\n\n    await session.post(url, data='Привет, Мир!')\n\n.. note::\n   ``Authorization`` header will be removed if you get redirected\n   to a different host or protocol.\n\nCustom Cookies\n--------------\n\nTo send your own cookies to the server, you can use the *cookies*\nparameter of :class:`ClientSession` constructor::\n\n    url = 'http://httpbin.org/cookies'\n    cookies = {'cookies_are': 'working'}\n    async with ClientSession(cookies=cookies) as session:\n        async with session.get(url) as resp:\n            assert await resp.json() == {\n               \"cookies\": {\"cookies_are\": \"working\"}}\n\n.. note::\n   ``httpbin.org/cookies`` endpoint returns request cookies\n   in JSON-encoded body.\n   To access session cookies see :attr:`ClientSession.cookie_jar`.\n\n:class:`~aiohttp.ClientSession` may be used for sharing cookies\nbetween multiple requests::\n\n    async with aiohttp.ClientSession() as session:\n        async with session.get(\n            \"http://httpbin.org/cookies/set?my_cookie=my_value\",\n            allow_redirects=False\n        ) as resp:\n            assert resp.cookies[\"my_cookie\"].value == \"my_value\"\n        async with session.get(\"http://httpbin.org/cookies\") as r:\n            json_body = await r.json()\n            assert json_body[\"cookies\"][\"my_cookie\"] == \"my_value\"\n\nResponse Headers and Cookies\n----------------------------\n\nWe can view the server's response :attr:`ClientResponse.headers` using\na :class:`~multidict.CIMultiDictProxy`::\n\n    assert resp.headers == {\n        'ACCESS-CONTROL-ALLOW-ORIGIN': '*',\n        'CONTENT-TYPE': 'application/json',\n        'DATE': 'Tue, 15 Jul 2014 16:49:51 GMT',\n        'SERVER': 'gunicorn/18.0',\n        'CONTENT-LENGTH': '331',\n        'CONNECTION': 'keep-alive'}\n\nThe dictionary is special, though: it's made just for HTTP\nheaders. According to `RFC 7230\n<http://tools.ietf.org/html/rfc7230#section-3.2>`_, HTTP Header names\nare case-insensitive. It also supports multiple values for the same\nkey as HTTP protocol does.\n\nSo, we can access the headers using any capitalization we want::\n\n    assert resp.headers['Content-Type'] == 'application/json'\n\n    assert resp.headers.get('content-type') == 'application/json'\n\nAll headers are converted from binary data using UTF-8 with\n``surrogateescape`` option. That works fine on most cases but\nsometimes unconverted data is needed if a server uses nonstandard\nencoding. While these headers are malformed from :rfc:`7230`\nperspective they may be retrieved by using\n:attr:`ClientResponse.raw_headers` property::\n\n    assert resp.raw_headers == (\n        (b'SERVER', b'nginx'),\n        (b'DATE', b'Sat, 09 Jan 2016 20:28:40 GMT'),\n        (b'CONTENT-TYPE', b'text/html; charset=utf-8'),\n        (b'CONTENT-LENGTH', b'12150'),\n        (b'CONNECTION', b'keep-alive'))\n\n\nIf a response contains some *HTTP Cookies*, you can quickly access them::\n\n    url = 'http://example.com/some/cookie/setting/url'\n    async with session.get(url) as resp:\n        print(resp.cookies['example_cookie_name'])\n\n.. note::\n\n   Response cookies contain only values, that were in ``Set-Cookie`` headers\n   of the **last** request in redirection chain. To gather cookies between all\n   redirection requests please use :ref:`aiohttp.ClientSession\n   <aiohttp-client-session>` object.\n\n\nRedirection History\n-------------------\n\nIf a request was redirected, it is possible to view previous responses using\nthe :attr:`~ClientResponse.history` attribute::\n\n    resp = await session.get('http://example.com/some/redirect/')\n    assert resp.status == 200\n    assert resp.url = URL('http://example.com/some/other/url/')\n    assert len(resp.history) == 1\n    assert resp.history[0].status == 301\n    assert resp.history[0].url = URL(\n        'http://example.com/some/redirect/')\n\nIf no redirects occurred or ``allow_redirects`` is set to ``False``,\nhistory will be an empty sequence.\n\n\nCookie Jar\n----------\n\n.. _aiohttp-client-cookie-safety:\n\nCookie Safety\n^^^^^^^^^^^^^\n\nBy default :class:`~aiohttp.ClientSession` uses strict version of\n:class:`aiohttp.CookieJar`. :rfc:`2109` explicitly forbids cookie\naccepting from URLs with IP address instead of DNS name\n(e.g. ``http://127.0.0.1:80/cookie``).\n\nIt's good but sometimes for testing we need to enable support for such\ncookies. It should be done by passing ``unsafe=True`` to\n:class:`aiohttp.CookieJar` constructor::\n\n\n   jar = aiohttp.CookieJar(unsafe=True)\n   session = aiohttp.ClientSession(cookie_jar=jar)\n\n\n.. _aiohttp-client-cookie-quoting-routine:\n\nCookie Quoting Routine\n^^^^^^^^^^^^^^^^^^^^^^\n\nThe client uses the :class:`~aiohttp.SimpleCookie` quoting routines\nconform to the :rfc:`2109`, which in turn references the character definitions\nfrom :rfc:`2068`. They provide a two-way quoting algorithm where any non-text\ncharacter is translated into a 4 character sequence: a forward-slash\nfollowed by the three-digit octal equivalent of the character.\nAny ``\\`` or ``\"`` is quoted with a preceding ``\\`` slash.\nBecause of the way browsers really handle cookies (as opposed to what the RFC\nsays) we also encode ``,`` and ``;``.\n\nSome backend systems does not support quoted cookies. You can skip this\nquotation routine by passing ``quote_cookie=False`` to the\n:class:`~aiohttp.CookieJar` constructor::\n\n   jar = aiohttp.CookieJar(quote_cookie=False)\n   session = aiohttp.ClientSession(cookie_jar=jar)\n\n\n.. _aiohttp-client-dummy-cookie-jar:\n\nDummy Cookie Jar\n^^^^^^^^^^^^^^^^\n\nSometimes cookie processing is not desirable. For this purpose it's\npossible to pass :class:`aiohttp.DummyCookieJar` instance into client\nsession::\n\n   jar = aiohttp.DummyCookieJar()\n   session = aiohttp.ClientSession(cookie_jar=jar)\n\n\nUploading pre-compressed data\n-----------------------------\n\nTo upload data that is already compressed before passing it to\naiohttp, call the request function with the used compression algorithm\nname (usually ``deflate`` or ``gzip``) as the value of the\n``Content-Encoding`` header::\n\n    async def my_coroutine(session, headers, my_data):\n        data = zlib.compress(my_data)\n        headers = {'Content-Encoding': 'deflate'}\n        async with session.post('http://httpbin.org/post',\n                                data=data,\n                                headers=headers)\n            pass\n\nDisabling content type validation for JSON responses\n----------------------------------------------------\n\nThe standard explicitly restricts JSON ``Content-Type`` HTTP header to\n``application/json`` or any extended form, e.g. ``application/vnd.custom-type+json``.\nUnfortunately, some servers send a wrong type, like ``text/html``.\n\nThis can be worked around in two ways:\n\n1. Pass the expected type explicitly (in this case checking will be strict, without the extended form support,\n   so ``custom/xxx+type`` won't be accepted):\n\n   ``await resp.json(content_type='custom/type')``.\n2. Disable the check entirely:\n\n   ``await resp.json(content_type=None)``.\n\n.. _aiohttp-client-tracing:\n\nClient Tracing\n--------------\n\nThe execution flow of a specific request can be followed attaching\nlisteners coroutines to the signals provided by the\n:class:`TraceConfig` instance, this instance will be used as a\nparameter for the :class:`ClientSession` constructor having as a\nresult a client that triggers the different signals supported by the\n:class:`TraceConfig`. By default any instance of\n:class:`ClientSession` class comes with the signals ability\ndisabled. The following snippet shows how the start and the end\nsignals of a request flow can be followed::\n\n    async def on_request_start(\n            session, trace_config_ctx, params):\n        print(\"Starting request\")\n\n    async def on_request_end(session, trace_config_ctx, params):\n        print(\"Ending request\")\n\n    trace_config = aiohttp.TraceConfig()\n    trace_config.on_request_start.append(on_request_start)\n    trace_config.on_request_end.append(on_request_end)\n    async with aiohttp.ClientSession(\n            trace_configs=[trace_config]) as client:\n        client.get('http://example.com/some/redirect/')\n\nThe ``trace_configs`` is a list that can contain instances of\n:class:`TraceConfig` class that allow run the signals handlers coming\nfrom different :class:`TraceConfig` instances.  The following example\nshows how two different :class:`TraceConfig` that have a different\nnature are installed to perform their job in each signal handle::\n\n    from mylib.traceconfig import AuditRequest\n    from mylib.traceconfig import XRay\n\n    async with aiohttp.ClientSession(\n            trace_configs=[AuditRequest(), XRay()]) as client:\n        client.get('http://example.com/some/redirect/')\n\n\nAll signals take as a parameters first, the :class:`ClientSession`\ninstance used by the specific request related to that signals and\nsecond, a :class:`~types.SimpleNamespace` instance called\n``trace_config_ctx``. The ``trace_config_ctx`` object can be used to\nshare the state through to the different signals that belong to the\nsame request and to the same :class:`TraceConfig` class, perhaps::\n\n    async def on_request_start(\n            session, trace_config_ctx, params):\n        trace_config_ctx.start = asyncio.get_event_loop().time()\n\n    async def on_request_end(session, trace_config_ctx, params):\n        elapsed = asyncio.get_event_loop().time() - trace_config_ctx.start\n        print(\"Request took {}\".format(elapsed))\n\n\nThe ``trace_config_ctx`` param is by default a\n:class:`~types.SimpleNamespace` that is initialized at the beginning of the\nrequest flow. However, the factory used to create this object can be\noverwritten using the ``trace_config_ctx_factory`` constructor param of\nthe :class:`TraceConfig` class.\n\nThe ``trace_request_ctx`` param can given at the beginning of the\nrequest execution, accepted by all of the HTTP verbs,  and will be\npassed as a keyword argument for the ``trace_config_ctx_factory``\nfactory. This param is useful to pass data that is only available at\nrequest time, perhaps::\n\n    async def on_request_start(\n            session, trace_config_ctx, params):\n        print(trace_config_ctx.trace_request_ctx)\n\n\n    session.get('http://example.com/some/redirect/',\n                trace_request_ctx={'foo': 'bar'})\n\n\n.. seealso:: :ref:`aiohttp-client-tracing-reference` section for\n             more information about the different signals supported.\n\nConnectors\n----------\n\nTo tweak or change *transport* layer of requests you can pass a custom\n*connector* to :class:`~aiohttp.ClientSession` and family. For example::\n\n    conn = aiohttp.TCPConnector()\n    session = aiohttp.ClientSession(connector=conn)\n\n.. note::\n\n   By default *session* object takes the ownership of the connector, among\n   other things closing the connections once the *session* is closed. If\n   you are keen on share the same *connector* through different *session*\n   instances you must give the  *connector_owner* parameter as **False**\n   for each *session* instance.\n\n.. seealso:: :ref:`aiohttp-client-reference-connectors` section for\n             more information about different connector types and\n             configuration options.\n\n\nLimiting connection pool size\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nTo limit amount of simultaneously opened connections you can pass *limit*\nparameter to *connector*::\n\n    conn = aiohttp.TCPConnector(limit=30)\n\nThe example limits total amount of parallel connections to `30`.\n\nThe default is `100`.\n\nIf you explicitly want not to have limits, pass `0`. For example::\n\n    conn = aiohttp.TCPConnector(limit=0)\n\nTo limit amount of simultaneously opened connection to the same\nendpoint (``(host, port, is_ssl)`` triple) you can pass *limit_per_host*\nparameter to *connector*::\n\n    conn = aiohttp.TCPConnector(limit_per_host=30)\n\nThe example limits amount of parallel connections to the same to `30`.\n\nThe default is `0` (no limit on per host bases).\n\nTuning the DNS cache\n^^^^^^^^^^^^^^^^^^^^\n\nBy default :class:`~aiohttp.TCPConnector` comes with the DNS cache\ntable enabled, and resolutions will be cached by default for `10` seconds.\nThis behavior can be changed either to change of the TTL for a resolution,\nas can be seen in the following example::\n\n    conn = aiohttp.TCPConnector(ttl_dns_cache=300)\n\nor disabling the use of the DNS cache table, meaning that all requests will\nend up making a DNS resolution, as the following example shows::\n\n    conn = aiohttp.TCPConnector(use_dns_cache=False)\n\n\nResolving using custom nameservers\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nIn order to specify the nameservers to when resolving the hostnames,\n:term:`aiodns` is required::\n\n    from aiohttp.resolver import AsyncResolver\n\n    resolver = AsyncResolver(nameservers=[\"8.8.8.8\", \"8.8.4.4\"])\n    conn = aiohttp.TCPConnector(resolver=resolver)\n\n\nUnix domain sockets\n^^^^^^^^^^^^^^^^^^^\n\nIf your HTTP server uses UNIX domain sockets you can use\n:class:`~aiohttp.UnixConnector`::\n\n  conn = aiohttp.UnixConnector(path='/path/to/socket')\n  session = aiohttp.ClientSession(connector=conn)\n\n\nNamed pipes in Windows\n^^^^^^^^^^^^^^^^^^^^^^\n\nIf your HTTP server uses Named pipes you can use\n:class:`~aiohttp.NamedPipeConnector`::\n\n  conn = aiohttp.NamedPipeConnector(path=r'\\\\.\\pipe\\<name-of-pipe>')\n  session = aiohttp.ClientSession(connector=conn)\n\nIt will only work with the ProactorEventLoop\n\nSSL control for TCP sockets\n---------------------------\n\nBy default *aiohttp* uses strict checks for HTTPS protocol. Certification\nchecks can be relaxed by setting *ssl* to ``False``::\n\n  r = await session.get('https://example.com', ssl=False)\n\nIf you need to setup custom ssl parameters (use own certification\nfiles for example) you can create a :class:`ssl.SSLContext` instance and\npass it into the :meth:`ClientSession.request` methods or set it for the\nentire session with ``ClientSession(connector=TCPConnector(ssl=ssl_context))``.\n\nThere are explicit errors when ssl verification fails\n\n:class:`aiohttp.ClientConnectorSSLError`::\n\n  try:\n      await session.get('https://expired.badssl.com/')\n  except aiohttp.ClientConnectorSSLError as e:\n      assert isinstance(e, ssl.SSLError)\n\n:class:`aiohttp.ClientConnectorCertificateError`::\n\n  try:\n      await session.get('https://wrong.host.badssl.com/')\n  except aiohttp.ClientConnectorCertificateError as e:\n      assert isinstance(e, ssl.CertificateError)\n\nIf you need to skip both ssl related errors\n\n:class:`aiohttp.ClientSSLError`::\n\n  try:\n      await session.get('https://expired.badssl.com/')\n  except aiohttp.ClientSSLError as e:\n      assert isinstance(e, ssl.SSLError)\n\n  try:\n      await session.get('https://wrong.host.badssl.com/')\n  except aiohttp.ClientSSLError as e:\n      assert isinstance(e, ssl.CertificateError)\n\nExample: Use certifi\n^^^^^^^^^^^^^^^^^^^^\n\nBy default, Python uses the system CA certificates. In rare cases, these may not be\ninstalled or Python is unable to find them, resulting in a error like\n`ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate`\n\nOne way to work around this problem is to use the `certifi` package::\n\n  ssl_context = ssl.create_default_context(cafile=certifi.where())\n  async with ClientSession(connector=TCPConnector(ssl=ssl_context)) as sess:\n      ...\n\nExample: Use self-signed certificate\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nIf you need to verify *self-signed* certificates, you need to add a call to\n:meth:`ssl.SSLContext.load_cert_chain` with the key pair::\n\n  ssl_context = ssl.create_default_context()\n  ssl_context.load_cert_chain(\"/path/to/client/public/device.pem\",\n                              \"/path/to/client/private/device.key\")\n  async with sess.get(\"https://example.com\", ssl=ssl_context) as resp:\n      ...\n\nExample: Verify certificate fingerprint\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nYou may also verify certificates via *SHA256* fingerprint::\n\n  # Attempt to connect to https://www.python.org\n  # with a pin to a bogus certificate:\n  bad_fp = b'0'*64\n  exc = None\n  try:\n      r = await session.get('https://www.python.org',\n                            ssl=aiohttp.Fingerprint(bad_fp))\n  except aiohttp.FingerprintMismatch as e:\n      exc = e\n  assert exc is not None\n  assert exc.expected == bad_fp\n\n  # www.python.org cert's actual fingerprint\n  assert exc.got == b'...'\n\nNote that this is the fingerprint of the DER-encoded certificate.\nIf you have the certificate in PEM format, you can convert it to\nDER with e.g::\n\n   openssl x509 -in crt.pem -inform PEM -outform DER > crt.der\n\n.. note::\n\n   Tip: to convert from a hexadecimal digest to a binary byte-string,\n   you can use :func:`binascii.unhexlify`.\n\n   *ssl* parameter could be passed\n   to :class:`TCPConnector` as default, the value from\n   :meth:`ClientSession.get` and others override default.\n\n.. _aiohttp-client-proxy-support:\n\nProxy support\n-------------\n\naiohttp supports plain HTTP proxies and HTTP proxies that can be\nupgraded to HTTPS via the HTTP CONNECT method. aiohttp has a limited\nsupport for proxies that must be connected to via ``https://`` — see\nthe info box below for more details.\nTo connect, use the *proxy* parameter::\n\n   async with aiohttp.ClientSession() as session:\n       async with session.get(\"http://python.org\",\n                              proxy=\"http://proxy.com\") as resp:\n           print(resp.status)\n\nIt also supports proxy authorization::\n\n   async with aiohttp.ClientSession() as session:\n       proxy_auth = aiohttp.BasicAuth('user', 'pass')\n       async with session.get(\"http://python.org\",\n                              proxy=\"http://proxy.com\",\n                              proxy_auth=proxy_auth) as resp:\n           print(resp.status)\n\nAuthentication credentials can be passed in proxy URL::\n\n   session.get(\"http://python.org\",\n               proxy=\"http://user:pass@some.proxy.com\")\n\nContrary to the ``requests`` library, it won't read environment\nvariables by default. But you can do so by passing\n``trust_env=True`` into :class:`aiohttp.ClientSession`\nconstructor.::\n\n   async with aiohttp.ClientSession(trust_env=True) as session:\n       async with session.get(\"http://python.org\") as resp:\n           print(resp.status)\n\n.. note::\n    aiohttp uses :func:`urllib.request.getproxies`\n    for reading the proxy configuration (e.g. from the *HTTP_PROXY* etc. environment variables) and applies them for the *HTTP*, *HTTPS*, *WS* and *WSS* schemes.\n\n    Hosts defined in ``no_proxy`` will bypass the proxy.\n.. versionadded:: 3.8\n\n   *WS_PROXY* and *WSS_PROXY* are supported since aiohttp v3.8.\n\nProxy credentials are given from ``~/.netrc`` file if present (see\n:class:`aiohttp.ClientSession` for more details).\n\n.. attention::\n\n   As of now (Python 3.10), support for TLS in TLS is disabled for the transports that\n   :py:mod:`asyncio` uses. If the further release of Python (say v3.11)\n   toggles one attribute, it'll *just work™*.\n\n   aiohttp v3.8 and higher is ready for this to happen and has code in\n   place supports TLS-in-TLS, hence sending HTTPS requests over HTTPS\n   proxy tunnels.\n\n   ⚠️ For as long as your Python runtime doesn't declare the support for\n   TLS-in-TLS, please don't file bugs with aiohttp but rather try to\n   help the CPython upstream enable this feature. Meanwhile, if you\n   *really* need this to work, there's a patch that may help you make\n   it happen, include it into your app's code base:\n   https://github.com/aio-libs/aiohttp/discussions/6044#discussioncomment-1432443.\n\n.. important::\n\n   When supplying a custom :py:class:`ssl.SSLContext` instance, bear in\n   mind that it will be used not only to establish a TLS session with\n   the HTTPS endpoint you're hitting but also to establish a TLS tunnel\n   to the HTTPS proxy. To avoid surprises, make sure to set up the trust\n   chain that would recognize TLS certificates used by both the endpoint\n   and the proxy.\n\nGraceful Shutdown\n-----------------\n\nWhen :class:`ClientSession` closes at the end of an ``async with``\nblock (or through a direct :meth:`ClientSession.close` call), the\nunderlying connection remains open due to asyncio internal details. In\npractice, the underlying connection will close after a short\nwhile. However, if the event loop is stopped before the underlying\nconnection is closed, a ``ResourceWarning: unclosed transport``\nwarning is emitted (when warnings are enabled).\n\nTo avoid this situation, a small delay must be added before closing\nthe event loop to allow any open underlying connections to close.\n\nFor a :class:`ClientSession` without SSL, a simple zero-sleep (``await\nasyncio.sleep(0)``) will suffice::\n\n    async def read_website():\n        async with aiohttp.ClientSession() as session:\n            async with session.get('http://example.org/') as resp:\n                await resp.read()\n        # Zero-sleep to allow underlying connections to close\n        await asyncio.sleep(0)\n\nFor a :class:`ClientSession` with SSL, the application must wait a\nshort duration before closing::\n\n    ...\n    # Wait 250 ms for the underlying SSL connections to close\n    await asyncio.sleep(0.250)\n\nNote that the appropriate amount of time to wait will vary from\napplication to application.\n\nAll if this will eventually become obsolete when the asyncio internals\nare changed so that aiohttp itself can wait on the underlying\nconnection to close. Please follow issue `#1925\n<https://github.com/aio-libs/aiohttp/issues/1925>`_ for the progress\non this.\n\n\nCharacter Set Detection\n-----------------------\n\nIf you encounter a :exc:`UnicodeDecodeError` when using :meth:`ClientResponse.text`\nthis may be because the response does not include the charset needed\nto decode the body.\n\nIf you know the correct encoding for a request, you can simply specify\nthe encoding as a parameter (e.g. ``resp.text(\"windows-1252\")``).\n\nAlternatively, :class:`ClientSession` accepts a ``fallback_charset_resolver`` parameter which\ncan be used to introduce charset guessing functionality. When a charset is not found\nin the Content-Type header, this function will be called to get the charset encoding. For\nexample, this can be used with the ``chardetng_py`` library.::\n\n    from chardetng_py import detect\n\n    def charset_resolver(resp: ClientResponse, body: bytes) -> str:\n        tld = resp.url.host.rsplit(\".\", maxsplit=1)[-1]\n        return detect(body, allow_utf8=True, tld=tld.encode())\n\n    ClientSession(fallback_charset_resolver=charset_resolver)\n\nOr, if ``chardetng_py`` doesn't work for you, then ``charset-normalizer`` is another option::\n\n    from charset_normalizer import detect\n\n    ClientSession(fallback_charset_resolver=lambda r, b: detect(b)[\"encoding\"] or \"utf-8\")\n",
            "new_file_content": ".. _aiohttp-client-advanced:\n\nAdvanced Client Usage\n=====================\n\n.. currentmodule:: aiohttp\n\n.. _aiohttp-client-session:\n\nClient Session\n--------------\n\n:class:`ClientSession` is the heart and the main entry point for all\nclient API operations.\n\nCreate the session first, use the instance for performing HTTP\nrequests and initiating WebSocket connections.\n\nThe session contains a cookie storage and connection pool, thus\ncookies and connections are shared between HTTP requests sent by the\nsame session.\n\nCustom Request Headers\n----------------------\n\nIf you need to add HTTP headers to a request, pass them in a\n:class:`dict` to the *headers* parameter.\n\nFor example, if you want to specify the content-type directly::\n\n    url = 'http://example.com/image'\n    payload = b'GIF89a\\x01\\x00\\x01\\x00\\x00\\xff\\x00,\\x00\\x00'\n              b'\\x00\\x00\\x01\\x00\\x01\\x00\\x00\\x02\\x00;'\n    headers = {'content-type': 'image/gif'}\n\n    await session.post(url,\n                       data=payload,\n                       headers=headers)\n\nYou also can set default headers for all session requests::\n\n    headers={\"Authorization\": \"Basic bG9naW46cGFzcw==\"}\n    async with aiohttp.ClientSession(headers=headers) as session:\n        async with session.get(\"http://httpbin.org/headers\") as r:\n            json_body = await r.json()\n            assert json_body['headers']['Authorization'] == \\\n                'Basic bG9naW46cGFzcw=='\n\nTypical use case is sending JSON body. You can specify content type\ndirectly as shown above, but it is more convenient to use special keyword\n``json``::\n\n    await session.post(url, json={'example': 'text'})\n\nFor *text/plain* ::\n\n    await session.post(url, data='Привет, Мир!')\n\n.. note::\n   ``Authorization`` header will be removed if you get redirected\n   to a different host or protocol.\n\nCustom Cookies\n--------------\n\nTo send your own cookies to the server, you can use the *cookies*\nparameter of :class:`ClientSession` constructor::\n\n    url = 'http://httpbin.org/cookies'\n    cookies = {'cookies_are': 'working'}\n    async with ClientSession(cookies=cookies) as session:\n        async with session.get(url) as resp:\n            assert await resp.json() == {\n               \"cookies\": {\"cookies_are\": \"working\"}}\n\n.. note::\n   ``httpbin.org/cookies`` endpoint returns request cookies\n   in JSON-encoded body.\n   To access session cookies see :attr:`ClientSession.cookie_jar`.\n\n:class:`~aiohttp.ClientSession` may be used for sharing cookies\nbetween multiple requests::\n\n    async with aiohttp.ClientSession() as session:\n        async with session.get(\n            \"http://httpbin.org/cookies/set?my_cookie=my_value\",\n            allow_redirects=False\n        ) as resp:\n            assert resp.cookies[\"my_cookie\"].value == \"my_value\"\n        async with session.get(\"http://httpbin.org/cookies\") as r:\n            json_body = await r.json()\n            assert json_body[\"cookies\"][\"my_cookie\"] == \"my_value\"\n\nResponse Headers and Cookies\n----------------------------\n\nWe can view the server's response :attr:`ClientResponse.headers` using\na :class:`~multidict.CIMultiDictProxy`::\n\n    assert resp.headers == {\n        'ACCESS-CONTROL-ALLOW-ORIGIN': '*',\n        'CONTENT-TYPE': 'application/json',\n        'DATE': 'Tue, 15 Jul 2014 16:49:51 GMT',\n        'SERVER': 'gunicorn/18.0',\n        'CONTENT-LENGTH': '331',\n        'CONNECTION': 'keep-alive'}\n\nThe dictionary is special, though: it's made just for HTTP\nheaders. According to `RFC 7230\n<http://tools.ietf.org/html/rfc7230#section-3.2>`_, HTTP Header names\nare case-insensitive. It also supports multiple values for the same\nkey as HTTP protocol does.\n\nSo, we can access the headers using any capitalization we want::\n\n    assert resp.headers['Content-Type'] == 'application/json'\n\n    assert resp.headers.get('content-type') == 'application/json'\n\nAll headers are converted from binary data using UTF-8 with\n``surrogateescape`` option. That works fine on most cases but\nsometimes unconverted data is needed if a server uses nonstandard\nencoding. While these headers are malformed from :rfc:`7230`\nperspective they may be retrieved by using\n:attr:`ClientResponse.raw_headers` property::\n\n    assert resp.raw_headers == (\n        (b'SERVER', b'nginx'),\n        (b'DATE', b'Sat, 09 Jan 2016 20:28:40 GMT'),\n        (b'CONTENT-TYPE', b'text/html; charset=utf-8'),\n        (b'CONTENT-LENGTH', b'12150'),\n        (b'CONNECTION', b'keep-alive'))\n\n\nIf a response contains some *HTTP Cookies*, you can quickly access them::\n\n    url = 'http://example.com/some/cookie/setting/url'\n    async with session.get(url) as resp:\n        print(resp.cookies['example_cookie_name'])\n\n.. note::\n\n   Response cookies contain only values, that were in ``Set-Cookie`` headers\n   of the **last** request in redirection chain. To gather cookies between all\n   redirection requests please use :ref:`aiohttp.ClientSession\n   <aiohttp-client-session>` object.\n\n\nRedirection History\n-------------------\n\nIf a request was redirected, it is possible to view previous responses using\nthe :attr:`~ClientResponse.history` attribute::\n\n    resp = await session.get('http://example.com/some/redirect/')\n    assert resp.status == 200\n    assert resp.url = URL('http://example.com/some/other/url/')\n    assert len(resp.history) == 1\n    assert resp.history[0].status == 301\n    assert resp.history[0].url = URL(\n        'http://example.com/some/redirect/')\n\nIf no redirects occurred or ``allow_redirects`` is set to ``False``,\nhistory will be an empty sequence.\n\n\nCookie Jar\n----------\n\n.. _aiohttp-client-cookie-safety:\n\nCookie Safety\n^^^^^^^^^^^^^\n\nBy default :class:`~aiohttp.ClientSession` uses strict version of\n:class:`aiohttp.CookieJar`. :rfc:`2109` explicitly forbids cookie\naccepting from URLs with IP address instead of DNS name\n(e.g. ``http://127.0.0.1:80/cookie``).\n\nIt's good but sometimes for testing we need to enable support for such\ncookies. It should be done by passing ``unsafe=True`` to\n:class:`aiohttp.CookieJar` constructor::\n\n\n   jar = aiohttp.CookieJar(unsafe=True)\n   session = aiohttp.ClientSession(cookie_jar=jar)\n\n\n.. _aiohttp-client-cookie-quoting-routine:\n\nCookie Quoting Routine\n^^^^^^^^^^^^^^^^^^^^^^\n\nThe client uses the :class:`~aiohttp.SimpleCookie` quoting routines\nconform to the :rfc:`2109`, which in turn references the character definitions\nfrom :rfc:`2068`. They provide a two-way quoting algorithm where any non-text\ncharacter is translated into a 4 character sequence: a forward-slash\nfollowed by the three-digit octal equivalent of the character.\nAny ``\\`` or ``\"`` is quoted with a preceding ``\\`` slash.\nBecause of the way browsers really handle cookies (as opposed to what the RFC\nsays) we also encode ``,`` and ``;``.\n\nSome backend systems does not support quoted cookies. You can skip this\nquotation routine by passing ``quote_cookie=False`` to the\n:class:`~aiohttp.CookieJar` constructor::\n\n   jar = aiohttp.CookieJar(quote_cookie=False)\n   session = aiohttp.ClientSession(cookie_jar=jar)\n\n\n.. _aiohttp-client-dummy-cookie-jar:\n\nDummy Cookie Jar\n^^^^^^^^^^^^^^^^\n\nSometimes cookie processing is not desirable. For this purpose it's\npossible to pass :class:`aiohttp.DummyCookieJar` instance into client\nsession::\n\n   jar = aiohttp.DummyCookieJar()\n   session = aiohttp.ClientSession(cookie_jar=jar)\n\n\nUploading pre-compressed data\n-----------------------------\n\nTo upload data that is already compressed before passing it to\naiohttp, call the request function with the used compression algorithm\nname (usually ``deflate`` or ``gzip``) as the value of the\n``Content-Encoding`` header::\n\n    async def my_coroutine(session, headers, my_data):\n        data = zlib.compress(my_data)\n        headers = {'Content-Encoding': 'deflate'}\n        async with session.post('http://httpbin.org/post',\n                                data=data,\n                                headers=headers)\n            pass\n\nDisabling content type validation for JSON responses\n----------------------------------------------------\n\nThe standard explicitly restricts JSON ``Content-Type`` HTTP header to\n``application/json`` or any extended form, e.g. ``application/vnd.custom-type+json``.\nUnfortunately, some servers send a wrong type, like ``text/html``.\n\nThis can be worked around in two ways:\n\n1. Pass the expected type explicitly (in this case checking will be strict, without the extended form support,\n   so ``custom/xxx+type`` won't be accepted):\n\n   ``await resp.json(content_type='custom/type')``.\n2. Disable the check entirely:\n\n   ``await resp.json(content_type=None)``.\n\n.. _aiohttp-client-tracing:\n\nClient Tracing\n--------------\n\nThe execution flow of a specific request can be followed attaching\nlisteners coroutines to the signals provided by the\n:class:`TraceConfig` instance, this instance will be used as a\nparameter for the :class:`ClientSession` constructor having as a\nresult a client that triggers the different signals supported by the\n:class:`TraceConfig`. By default any instance of\n:class:`ClientSession` class comes with the signals ability\ndisabled. The following snippet shows how the start and the end\nsignals of a request flow can be followed::\n\n    async def on_request_start(\n            session, trace_config_ctx, params):\n        print(\"Starting request\")\n\n    async def on_request_end(session, trace_config_ctx, params):\n        print(\"Ending request\")\n\n    trace_config = aiohttp.TraceConfig()\n    trace_config.on_request_start.append(on_request_start)\n    trace_config.on_request_end.append(on_request_end)\n    async with aiohttp.ClientSession(\n            trace_configs=[trace_config]) as client:\n        client.get('http://example.com/some/redirect/')\n\nThe ``trace_configs`` is a list that can contain instances of\n:class:`TraceConfig` class that allow run the signals handlers coming\nfrom different :class:`TraceConfig` instances.  The following example\nshows how two different :class:`TraceConfig` that have a different\nnature are installed to perform their job in each signal handle::\n\n    from mylib.traceconfig import AuditRequest\n    from mylib.traceconfig import XRay\n\n    async with aiohttp.ClientSession(\n            trace_configs=[AuditRequest(), XRay()]) as client:\n        client.get('http://example.com/some/redirect/')\n\n\nAll signals take as a parameters first, the :class:`ClientSession`\ninstance used by the specific request related to that signals and\nsecond, a :class:`~types.SimpleNamespace` instance called\n``trace_config_ctx``. The ``trace_config_ctx`` object can be used to\nshare the state through to the different signals that belong to the\nsame request and to the same :class:`TraceConfig` class, perhaps::\n\n    async def on_request_start(\n            session, trace_config_ctx, params):\n        trace_config_ctx.start = asyncio.get_event_loop().time()\n\n    async def on_request_end(session, trace_config_ctx, params):\n        elapsed = asyncio.get_event_loop().time() - trace_config_ctx.start\n        print(\"Request took {}\".format(elapsed))\n\n\nThe ``trace_config_ctx`` param is by default a\n:class:`~types.SimpleNamespace` that is initialized at the beginning of the\nrequest flow. However, the factory used to create this object can be\noverwritten using the ``trace_config_ctx_factory`` constructor param of\nthe :class:`TraceConfig` class.\n\nThe ``trace_request_ctx`` param can given at the beginning of the\nrequest execution, accepted by all of the HTTP verbs,  and will be\npassed as a keyword argument for the ``trace_config_ctx_factory``\nfactory. This param is useful to pass data that is only available at\nrequest time, perhaps::\n\n    async def on_request_start(\n            session, trace_config_ctx, params):\n        print(trace_config_ctx.trace_request_ctx)\n\n\n    session.get('http://example.com/some/redirect/',\n                trace_request_ctx={'foo': 'bar'})\n\n\n.. seealso:: :ref:`aiohttp-client-tracing-reference` section for\n             more information about the different signals supported.\n\nConnectors\n----------\n\nTo tweak or change *transport* layer of requests you can pass a custom\n*connector* to :class:`~aiohttp.ClientSession` and family. For example::\n\n    conn = aiohttp.TCPConnector()\n    session = aiohttp.ClientSession(connector=conn)\n\n.. note::\n\n   By default *session* object takes the ownership of the connector, among\n   other things closing the connections once the *session* is closed. If\n   you are keen on share the same *connector* through different *session*\n   instances you must give the  *connector_owner* parameter as **False**\n   for each *session* instance.\n\n.. seealso:: :ref:`aiohttp-client-reference-connectors` section for\n             more information about different connector types and\n             configuration options.\n\n\nLimiting connection pool size\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nTo limit amount of simultaneously opened connections you can pass *limit*\nparameter to *connector*::\n\n    conn = aiohttp.TCPConnector(limit=30)\n\nThe example limits total amount of parallel connections to `30`.\n\nThe default is `100`.\n\nIf you explicitly want not to have limits, pass `0`. For example::\n\n    conn = aiohttp.TCPConnector(limit=0)\n\nTo limit amount of simultaneously opened connection to the same\nendpoint (``(host, port, is_ssl)`` triple) you can pass *limit_per_host*\nparameter to *connector*::\n\n    conn = aiohttp.TCPConnector(limit_per_host=30)\n\nThe example limits amount of parallel connections to the same to `30`.\n\nThe default is `0` (no limit on per host bases).\n\nTuning the DNS cache\n^^^^^^^^^^^^^^^^^^^^\n\nBy default :class:`~aiohttp.TCPConnector` comes with the DNS cache\ntable enabled, and resolutions will be cached by default for `10` seconds.\nThis behavior can be changed either to change of the TTL for a resolution,\nas can be seen in the following example::\n\n    conn = aiohttp.TCPConnector(ttl_dns_cache=300)\n\nor disabling the use of the DNS cache table, meaning that all requests will\nend up making a DNS resolution, as the following example shows::\n\n    conn = aiohttp.TCPConnector(use_dns_cache=False)\n\n\nResolving using custom nameservers\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nIn order to specify the nameservers to when resolving the hostnames,\n:term:`aiodns` is required::\n\n    from aiohttp.resolver import AsyncResolver\n\n    resolver = AsyncResolver(nameservers=[\"8.8.8.8\", \"8.8.4.4\"])\n    conn = aiohttp.TCPConnector(resolver=resolver)\n\n\nUnix domain sockets\n^^^^^^^^^^^^^^^^^^^\n\nIf your HTTP server uses UNIX domain sockets you can use\n:class:`~aiohttp.UnixConnector`::\n\n  conn = aiohttp.UnixConnector(path='/path/to/socket')\n  session = aiohttp.ClientSession(connector=conn)\n\n\nNamed pipes in Windows\n^^^^^^^^^^^^^^^^^^^^^^\n\nIf your HTTP server uses Named pipes you can use\n:class:`~aiohttp.NamedPipeConnector`::\n\n  conn = aiohttp.NamedPipeConnector(path=r'\\\\.\\pipe\\<name-of-pipe>')\n  session = aiohttp.ClientSession(connector=conn)\n\nIt will only work with the ProactorEventLoop\n\nSSL control for TCP sockets\n---------------------------\n\nBy default *aiohttp* uses strict checks for HTTPS protocol. Certification\nchecks can be relaxed by setting *ssl* to ``False``::\n\n  r = await session.get('https://example.com', ssl=False)\n\nIf you need to setup custom ssl parameters (use own certification\nfiles for example) you can create a :class:`ssl.SSLContext` instance and\npass it into the :meth:`ClientSession.request` methods or set it for the\nentire session with ``ClientSession(connector=TCPConnector(ssl=ssl_context))``.\n\nThere are explicit errors when ssl verification fails\n\n:class:`aiohttp.ClientConnectorSSLError`::\n\n  try:\n      await session.get('https://expired.badssl.com/')\n  except aiohttp.ClientConnectorSSLError as e:\n      assert isinstance(e, ssl.SSLError)\n\n:class:`aiohttp.ClientConnectorCertificateError`::\n\n  try:\n      await session.get('https://wrong.host.badssl.com/')\n  except aiohttp.ClientConnectorCertificateError as e:\n      assert isinstance(e, ssl.CertificateError)\n\nIf you need to skip both ssl related errors\n\n:class:`aiohttp.ClientSSLError`::\n\n  try:\n      await session.get('https://expired.badssl.com/')\n  except aiohttp.ClientSSLError as e:\n      assert isinstance(e, ssl.SSLError)\n\n  try:\n      await session.get('https://wrong.host.badssl.com/')\n  except aiohttp.ClientSSLError as e:\n      assert isinstance(e, ssl.CertificateError)\n\nExample: Use certifi\n^^^^^^^^^^^^^^^^^^^^\n\nBy default, Python uses the system CA certificates. In rare cases, these may not be\ninstalled or Python is unable to find them, resulting in a error like\n`ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate`\n\nOne way to work around this problem is to use the `certifi` package::\n\n  ssl_context = ssl.create_default_context(cafile=certifi.where())\n  async with ClientSession(connector=TCPConnector(ssl=ssl_context)) as sess:\n      ...\n\nExample: Use self-signed certificate\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nIf you need to verify *self-signed* certificates, you need to add a call to\n:meth:`ssl.SSLContext.load_cert_chain` with the key pair::\n\n  ssl_context = ssl.create_default_context()\n  ssl_context.load_cert_chain(\"/path/to/client/public/device.pem\",\n                              \"/path/to/client/private/device.key\")\n  async with sess.get(\"https://example.com\", ssl=ssl_context) as resp:\n      ...\n\nExample: Verify certificate fingerprint\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nYou may also verify certificates via *SHA256* fingerprint::\n\n  # Attempt to connect to https://www.python.org\n  # with a pin to a bogus certificate:\n  bad_fp = b'0'*64\n  exc = None\n  try:\n      r = await session.get('https://www.python.org',\n                            ssl=aiohttp.Fingerprint(bad_fp))\n  except aiohttp.FingerprintMismatch as e:\n      exc = e\n  assert exc is not None\n  assert exc.expected == bad_fp\n\n  # www.python.org cert's actual fingerprint\n  assert exc.got == b'...'\n\nNote that this is the fingerprint of the DER-encoded certificate.\nIf you have the certificate in PEM format, you can convert it to\nDER with e.g::\n\n   openssl x509 -in crt.pem -inform PEM -outform DER > crt.der\n\n.. note::\n\n   Tip: to convert from a hexadecimal digest to a binary byte-string,\n   you can use :func:`binascii.unhexlify`.\n\n   *ssl* parameter could be passed\n   to :class:`TCPConnector` as default, the value from\n   :meth:`ClientSession.get` and others override default.\n\n.. _aiohttp-client-proxy-support:\n\nProxy support\n-------------\n\naiohttp supports plain HTTP proxies and HTTP proxies that can be\nupgraded to HTTPS via the HTTP CONNECT method. aiohttp has a limited\nsupport for proxies that must be connected to via ``https://`` — see\nthe info box below for more details.\nTo connect, use the *proxy* parameter::\n\n   async with aiohttp.ClientSession() as session:\n       async with session.get(\"http://python.org\",\n                              proxy=\"http://proxy.com\") as resp:\n           print(resp.status)\n\nIt also supports proxy authorization::\n\n   async with aiohttp.ClientSession() as session:\n       proxy_auth = aiohttp.BasicAuth('user', 'pass')\n       async with session.get(\"http://python.org\",\n                              proxy=\"http://proxy.com\",\n                              proxy_auth=proxy_auth) as resp:\n           print(resp.status)\n\nAuthentication credentials can be passed in proxy URL::\n\n   session.get(\"http://python.org\",\n               proxy=\"http://user:pass@some.proxy.com\")\n\nAnd you may set default proxy::\n\n   proxy_auth = aiohttp.BasicAuth('user', 'pass')\n   async with aiohttp.ClientSession(proxy=\"http://proxy.com\", proxy_auth=proxy_auth) as session:\n       async with session.get(\"http://python.org\") as resp:\n           print(resp.status)\n\nContrary to the ``requests`` library, it won't read environment\nvariables by default. But you can do so by passing\n``trust_env=True`` into :class:`aiohttp.ClientSession`\nconstructor.::\n\n   async with aiohttp.ClientSession(trust_env=True) as session:\n       async with session.get(\"http://python.org\") as resp:\n           print(resp.status)\n\n.. note::\n    aiohttp uses :func:`urllib.request.getproxies`\n    for reading the proxy configuration (e.g. from the *HTTP_PROXY* etc. environment variables) and applies them for the *HTTP*, *HTTPS*, *WS* and *WSS* schemes.\n\n    Hosts defined in ``no_proxy`` will bypass the proxy.\n.. versionadded:: 3.8\n\n   *WS_PROXY* and *WSS_PROXY* are supported since aiohttp v3.8.\n\nProxy credentials are given from ``~/.netrc`` file if present (see\n:class:`aiohttp.ClientSession` for more details).\n\n.. attention::\n\n   As of now (Python 3.10), support for TLS in TLS is disabled for the transports that\n   :py:mod:`asyncio` uses. If the further release of Python (say v3.11)\n   toggles one attribute, it'll *just work™*.\n\n   aiohttp v3.8 and higher is ready for this to happen and has code in\n   place supports TLS-in-TLS, hence sending HTTPS requests over HTTPS\n   proxy tunnels.\n\n   ⚠️ For as long as your Python runtime doesn't declare the support for\n   TLS-in-TLS, please don't file bugs with aiohttp but rather try to\n   help the CPython upstream enable this feature. Meanwhile, if you\n   *really* need this to work, there's a patch that may help you make\n   it happen, include it into your app's code base:\n   https://github.com/aio-libs/aiohttp/discussions/6044#discussioncomment-1432443.\n\n.. important::\n\n   When supplying a custom :py:class:`ssl.SSLContext` instance, bear in\n   mind that it will be used not only to establish a TLS session with\n   the HTTPS endpoint you're hitting but also to establish a TLS tunnel\n   to the HTTPS proxy. To avoid surprises, make sure to set up the trust\n   chain that would recognize TLS certificates used by both the endpoint\n   and the proxy.\n\nGraceful Shutdown\n-----------------\n\nWhen :class:`ClientSession` closes at the end of an ``async with``\nblock (or through a direct :meth:`ClientSession.close` call), the\nunderlying connection remains open due to asyncio internal details. In\npractice, the underlying connection will close after a short\nwhile. However, if the event loop is stopped before the underlying\nconnection is closed, a ``ResourceWarning: unclosed transport``\nwarning is emitted (when warnings are enabled).\n\nTo avoid this situation, a small delay must be added before closing\nthe event loop to allow any open underlying connections to close.\n\nFor a :class:`ClientSession` without SSL, a simple zero-sleep (``await\nasyncio.sleep(0)``) will suffice::\n\n    async def read_website():\n        async with aiohttp.ClientSession() as session:\n            async with session.get('http://example.org/') as resp:\n                await resp.read()\n        # Zero-sleep to allow underlying connections to close\n        await asyncio.sleep(0)\n\nFor a :class:`ClientSession` with SSL, the application must wait a\nshort duration before closing::\n\n    ...\n    # Wait 250 ms for the underlying SSL connections to close\n    await asyncio.sleep(0.250)\n\nNote that the appropriate amount of time to wait will vary from\napplication to application.\n\nAll if this will eventually become obsolete when the asyncio internals\nare changed so that aiohttp itself can wait on the underlying\nconnection to close. Please follow issue `#1925\n<https://github.com/aio-libs/aiohttp/issues/1925>`_ for the progress\non this.\n\n\nCharacter Set Detection\n-----------------------\n\nIf you encounter a :exc:`UnicodeDecodeError` when using :meth:`ClientResponse.text`\nthis may be because the response does not include the charset needed\nto decode the body.\n\nIf you know the correct encoding for a request, you can simply specify\nthe encoding as a parameter (e.g. ``resp.text(\"windows-1252\")``).\n\nAlternatively, :class:`ClientSession` accepts a ``fallback_charset_resolver`` parameter which\ncan be used to introduce charset guessing functionality. When a charset is not found\nin the Content-Type header, this function will be called to get the charset encoding. For\nexample, this can be used with the ``chardetng_py`` library.::\n\n    from chardetng_py import detect\n\n    def charset_resolver(resp: ClientResponse, body: bytes) -> str:\n        tld = resp.url.host.rsplit(\".\", maxsplit=1)[-1]\n        return detect(body, allow_utf8=True, tld=tld.encode())\n\n    ClientSession(fallback_charset_resolver=charset_resolver)\n\nOr, if ``chardetng_py`` doesn't work for you, then ``charset-normalizer`` is another option::\n\n    from charset_normalizer import detect\n\n    ClientSession(fallback_charset_resolver=lambda r, b: detect(b)[\"encoding\"] or \"utf-8\")\n",
            "header": {
                "file": {
                    "path": "docs/client_advanced.rst"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "524b0877",
                "new_commit_hash": "8b27351c",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/docs/client_advanced.rst"
            },
            "plus_file": {
                "path": "b/docs/client_advanced.rst"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 567,
                            "length": 6
                        },
                        "new_range": {
                            "start": 567,
                            "length": 13
                        },
                        "section": "Authentication credentials can be passed in proxy URL::"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "   session.get(\"http://python.org\",",
                                "type": "context"
                            },
                            {
                                "content": "               proxy=\"http://user:pass@some.proxy.com\")",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "And you may set default proxy::",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "   proxy_auth = aiohttp.BasicAuth('user', 'pass')",
                                "type": "added"
                            },
                            {
                                "content": "   async with aiohttp.ClientSession(proxy=\"http://proxy.com\", proxy_auth=proxy_auth) as session:",
                                "type": "added"
                            },
                            {
                                "content": "       async with session.get(\"http://python.org\") as resp:",
                                "type": "added"
                            },
                            {
                                "content": "           print(resp.status)",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "Contrary to the ``requests`` library, it won't read environment",
                                "type": "context"
                            },
                            {
                                "content": "variables by default. But you can do so by passing",
                                "type": "context"
                            },
                            {
                                "content": "``trust_env=True`` into :class:`aiohttp.ClientSession`",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "import asyncio\nimport contextlib\nimport gc\nimport io\nimport json\nfrom http.cookies import SimpleCookie\nfrom typing import Any, Awaitable, Callable, List\nfrom unittest import mock\nfrom uuid import uuid4\n\nimport pytest\nfrom multidict import CIMultiDict, MultiDict\nfrom re_assert import Matches\nfrom yarl import URL\n\nimport aiohttp\nfrom aiohttp import client, hdrs, web\nfrom aiohttp.client import ClientSession\nfrom aiohttp.client_proto import ResponseHandler\nfrom aiohttp.client_reqrep import ClientRequest\nfrom aiohttp.connector import BaseConnector, Connection, TCPConnector, UnixConnector\nfrom aiohttp.helpers import DEBUG\nfrom aiohttp.http import RawResponseMessage\nfrom aiohttp.test_utils import make_mocked_coro\nfrom aiohttp.tracing import Trace\n\n\n@pytest.fixture\ndef connector(loop):\n    async def make_conn():\n        return BaseConnector(loop=loop)\n\n    conn = loop.run_until_complete(make_conn())\n    proto = mock.Mock()\n    conn._conns[\"a\"] = [(proto, 123)]\n    yield conn\n    loop.run_until_complete(conn.close())\n\n\n@pytest.fixture\ndef create_session(loop):\n    session = None\n\n    async def maker(*args, **kwargs):\n        nonlocal session\n        session = ClientSession(*args, loop=loop, **kwargs)\n        return session\n\n    yield maker\n    if session is not None:\n        loop.run_until_complete(session.close())\n\n\n@pytest.fixture\ndef session(create_session, loop):\n    return loop.run_until_complete(create_session())\n\n\n@pytest.fixture\ndef params():\n    return dict(\n        headers={\"Authorization\": \"Basic ...\"},\n        max_redirects=2,\n        encoding=\"latin1\",\n        version=aiohttp.HttpVersion10,\n        compress=\"deflate\",\n        chunked=True,\n        expect100=True,\n        read_until_eof=False,\n    )\n\n\nasync def test_close_coro(create_session) -> None:\n    session = await create_session()\n    await session.close()\n\n\nasync def test_init_headers_simple_dict(create_session) -> None:\n    session = await create_session(headers={\"h1\": \"header1\", \"h2\": \"header2\"})\n    assert sorted(session.headers.items()) == ([(\"h1\", \"header1\"), (\"h2\", \"header2\")])\n\n\nasync def test_init_headers_list_of_tuples(create_session) -> None:\n    session = await create_session(\n        headers=[(\"h1\", \"header1\"), (\"h2\", \"header2\"), (\"h3\", \"header3\")]\n    )\n    assert session.headers == CIMultiDict(\n        [(\"h1\", \"header1\"), (\"h2\", \"header2\"), (\"h3\", \"header3\")]\n    )\n\n\nasync def test_init_headers_MultiDict(create_session) -> None:\n    session = await create_session(\n        headers=MultiDict([(\"h1\", \"header1\"), (\"h2\", \"header2\"), (\"h3\", \"header3\")])\n    )\n    assert session.headers == CIMultiDict(\n        [(\"H1\", \"header1\"), (\"H2\", \"header2\"), (\"H3\", \"header3\")]\n    )\n\n\nasync def test_init_headers_list_of_tuples_with_duplicates(create_session) -> None:\n    session = await create_session(\n        headers=[(\"h1\", \"header11\"), (\"h2\", \"header21\"), (\"h1\", \"header12\")]\n    )\n    assert session.headers == CIMultiDict(\n        [(\"H1\", \"header11\"), (\"H2\", \"header21\"), (\"H1\", \"header12\")]\n    )\n\n\nasync def test_init_cookies_with_simple_dict(create_session) -> None:\n    session = await create_session(cookies={\"c1\": \"cookie1\", \"c2\": \"cookie2\"})\n    cookies = session.cookie_jar.filter_cookies()\n    assert set(cookies) == {\"c1\", \"c2\"}\n    assert cookies[\"c1\"].value == \"cookie1\"\n    assert cookies[\"c2\"].value == \"cookie2\"\n\n\nasync def test_init_cookies_with_list_of_tuples(create_session) -> None:\n    session = await create_session(cookies=[(\"c1\", \"cookie1\"), (\"c2\", \"cookie2\")])\n\n    cookies = session.cookie_jar.filter_cookies()\n    assert set(cookies) == {\"c1\", \"c2\"}\n    assert cookies[\"c1\"].value == \"cookie1\"\n    assert cookies[\"c2\"].value == \"cookie2\"\n\n\nasync def test_merge_headers(create_session) -> None:\n    # Check incoming simple dict\n    session = await create_session(headers={\"h1\": \"header1\", \"h2\": \"header2\"})\n    headers = session._prepare_headers({\"h1\": \"h1\"})\n\n    assert isinstance(headers, CIMultiDict)\n    assert headers == {\"h1\": \"h1\", \"h2\": \"header2\"}\n\n\nasync def test_merge_headers_with_multi_dict(create_session) -> None:\n    session = await create_session(headers={\"h1\": \"header1\", \"h2\": \"header2\"})\n    headers = session._prepare_headers(MultiDict([(\"h1\", \"h1\")]))\n    assert isinstance(headers, CIMultiDict)\n    assert headers == {\"h1\": \"h1\", \"h2\": \"header2\"}\n\n\nasync def test_merge_headers_with_list_of_tuples(create_session) -> None:\n    session = await create_session(headers={\"h1\": \"header1\", \"h2\": \"header2\"})\n    headers = session._prepare_headers([(\"h1\", \"h1\")])\n    assert isinstance(headers, CIMultiDict)\n    assert headers == {\"h1\": \"h1\", \"h2\": \"header2\"}\n\n\nasync def test_merge_headers_with_list_of_tuples_duplicated_names(\n    create_session,\n) -> None:\n    session = await create_session(headers={\"h1\": \"header1\", \"h2\": \"header2\"})\n\n    headers = session._prepare_headers([(\"h1\", \"v1\"), (\"h1\", \"v2\")])\n\n    assert isinstance(headers, CIMultiDict)\n    assert list(sorted(headers.items())) == [\n        (\"h1\", \"v1\"),\n        (\"h1\", \"v2\"),\n        (\"h2\", \"header2\"),\n    ]\n\n\ndef test_http_GET(session, params) -> None:\n    with mock.patch(\n        \"aiohttp.client.ClientSession._request\", new_callable=mock.MagicMock\n    ) as patched:\n        session.get(\"http://test.example.com\", params={\"x\": 1}, **params)\n    assert patched.called, \"`ClientSession._request` not called\"\n    assert list(patched.call_args) == [\n        (\n            \"GET\",\n            \"http://test.example.com\",\n        ),\n        dict(params={\"x\": 1}, allow_redirects=True, **params),\n    ]\n\n\ndef test_http_OPTIONS(session, params) -> None:\n    with mock.patch(\n        \"aiohttp.client.ClientSession._request\", new_callable=mock.MagicMock\n    ) as patched:\n        session.options(\"http://opt.example.com\", params={\"x\": 2}, **params)\n    assert patched.called, \"`ClientSession._request` not called\"\n    assert list(patched.call_args) == [\n        (\n            \"OPTIONS\",\n            \"http://opt.example.com\",\n        ),\n        dict(params={\"x\": 2}, allow_redirects=True, **params),\n    ]\n\n\ndef test_http_HEAD(session, params) -> None:\n    with mock.patch(\n        \"aiohttp.client.ClientSession._request\", new_callable=mock.MagicMock\n    ) as patched:\n        session.head(\"http://head.example.com\", params={\"x\": 2}, **params)\n    assert patched.called, \"`ClientSession._request` not called\"\n    assert list(patched.call_args) == [\n        (\n            \"HEAD\",\n            \"http://head.example.com\",\n        ),\n        dict(params={\"x\": 2}, allow_redirects=False, **params),\n    ]\n\n\ndef test_http_POST(session, params) -> None:\n    with mock.patch(\n        \"aiohttp.client.ClientSession._request\", new_callable=mock.MagicMock\n    ) as patched:\n        session.post(\n            \"http://post.example.com\", params={\"x\": 2}, data=\"Some_data\", **params\n        )\n    assert patched.called, \"`ClientSession._request` not called\"\n    assert list(patched.call_args) == [\n        (\n            \"POST\",\n            \"http://post.example.com\",\n        ),\n        dict(params={\"x\": 2}, data=\"Some_data\", **params),\n    ]\n\n\ndef test_http_PUT(session, params) -> None:\n    with mock.patch(\n        \"aiohttp.client.ClientSession._request\", new_callable=mock.MagicMock\n    ) as patched:\n        session.put(\n            \"http://put.example.com\", params={\"x\": 2}, data=\"Some_data\", **params\n        )\n    assert patched.called, \"`ClientSession._request` not called\"\n    assert list(patched.call_args) == [\n        (\n            \"PUT\",\n            \"http://put.example.com\",\n        ),\n        dict(params={\"x\": 2}, data=\"Some_data\", **params),\n    ]\n\n\ndef test_http_PATCH(session, params) -> None:\n    with mock.patch(\n        \"aiohttp.client.ClientSession._request\", new_callable=mock.MagicMock\n    ) as patched:\n        session.patch(\n            \"http://patch.example.com\", params={\"x\": 2}, data=\"Some_data\", **params\n        )\n    assert patched.called, \"`ClientSession._request` not called\"\n    assert list(patched.call_args) == [\n        (\n            \"PATCH\",\n            \"http://patch.example.com\",\n        ),\n        dict(params={\"x\": 2}, data=\"Some_data\", **params),\n    ]\n\n\ndef test_http_DELETE(session, params) -> None:\n    with mock.patch(\n        \"aiohttp.client.ClientSession._request\", new_callable=mock.MagicMock\n    ) as patched:\n        session.delete(\"http://delete.example.com\", params={\"x\": 2}, **params)\n    assert patched.called, \"`ClientSession._request` not called\"\n    assert list(patched.call_args) == [\n        (\n            \"DELETE\",\n            \"http://delete.example.com\",\n        ),\n        dict(params={\"x\": 2}, **params),\n    ]\n\n\nasync def test_close(create_session, connector) -> None:\n    session = await create_session(connector=connector)\n\n    await session.close()\n    assert session.connector is None\n    assert connector.closed\n\n\nasync def test_closed(session) -> None:\n    assert not session.closed\n    await session.close()\n    assert session.closed\n\n\nasync def test_connector(create_session, loop, mocker) -> None:\n    connector = TCPConnector(loop=loop)\n    mocker.spy(connector, \"close\")\n    session = await create_session(connector=connector)\n    assert session.connector is connector\n\n    await session.close()\n    assert connector.close.called\n    await connector.close()\n\n\nasync def test_create_connector(create_session, loop, mocker) -> None:\n    session = await create_session()\n    connector = session.connector\n    mocker.spy(session.connector, \"close\")\n\n    await session.close()\n    assert connector.close.called\n\n\ndef test_connector_loop(loop) -> None:\n    with contextlib.ExitStack() as stack:\n        another_loop = asyncio.new_event_loop()\n        stack.enter_context(contextlib.closing(another_loop))\n\n        async def make_connector():\n            return TCPConnector()\n\n        connector = another_loop.run_until_complete(make_connector())\n\n        with pytest.raises(RuntimeError) as ctx:\n\n            async def make_sess():\n                return ClientSession(connector=connector, loop=loop)\n\n            loop.run_until_complete(make_sess())\n        assert (\n            Matches(\"Session and connector has to use same event loop\")\n            == str(ctx.value).strip()\n        )\n        another_loop.run_until_complete(connector.close())\n\n\ndef test_detach(loop, session) -> None:\n    conn = session.connector\n    try:\n        assert not conn.closed\n        session.detach()\n        assert session.connector is None\n        assert session.closed\n        assert not conn.closed\n    finally:\n        loop.run_until_complete(conn.close())\n\n\nasync def test_request_closed_session(session) -> None:\n    await session.close()\n    with pytest.raises(RuntimeError):\n        await session.request(\"get\", \"/\")\n\n\ndef test_close_flag_for_closed_connector(loop, session) -> None:\n    conn = session.connector\n    assert not session.closed\n    loop.run_until_complete(conn.close())\n    assert session.closed\n\n\nasync def test_double_close(connector, create_session) -> None:\n    session = await create_session(connector=connector)\n\n    await session.close()\n    assert session.connector is None\n    await session.close()\n    assert session.closed\n    assert connector.closed\n\n\nasync def test_del(connector, loop) -> None:\n    loop.set_debug(False)\n    # N.B. don't use session fixture, it stores extra reference internally\n    session = ClientSession(connector=connector, loop=loop)\n    logs = []\n    loop.set_exception_handler(lambda loop, ctx: logs.append(ctx))\n\n    with pytest.warns(ResourceWarning):\n        del session\n        gc.collect()\n\n    assert len(logs) == 1\n    expected = {\"client_session\": mock.ANY, \"message\": \"Unclosed client session\"}\n    assert logs[0] == expected\n\n\nasync def test_del_debug(connector, loop) -> None:\n    loop.set_debug(True)\n    # N.B. don't use session fixture, it stores extra reference internally\n    session = ClientSession(connector=connector, loop=loop)\n    logs = []\n    loop.set_exception_handler(lambda loop, ctx: logs.append(ctx))\n\n    with pytest.warns(ResourceWarning):\n        del session\n        gc.collect()\n\n    assert len(logs) == 1\n    expected = {\n        \"client_session\": mock.ANY,\n        \"message\": \"Unclosed client session\",\n        \"source_traceback\": mock.ANY,\n    }\n    assert logs[0] == expected\n\n\nasync def test_session_context_manager(connector, loop) -> None:\n    with pytest.raises(TypeError):\n        with ClientSession(loop=loop, connector=connector) as session:\n            pass\n\n        assert session.closed\n\n\nasync def test_borrow_connector_loop(connector, create_session, loop) -> None:\n    session = ClientSession(connector=connector, loop=None)\n    try:\n        assert session._loop, loop\n    finally:\n        await session.close()\n\n\nasync def test_reraise_os_error(create_session) -> None:\n    err = OSError(1, \"permission error\")\n    req = mock.Mock()\n    req_factory = mock.Mock(return_value=req)\n    req.send = mock.Mock(side_effect=err)\n    session = await create_session(request_class=req_factory)\n\n    async def create_connection(req, traces, timeout):\n        # return self.transport, self.protocol\n        return mock.Mock()\n\n    session._connector._create_connection = create_connection\n    session._connector._release = mock.Mock()\n\n    with pytest.raises(aiohttp.ClientOSError) as ctx:\n        await session.request(\"get\", \"http://example.com\")\n    e = ctx.value\n    assert e.errno == err.errno\n    assert e.strerror == err.strerror\n\n\nasync def test_close_conn_on_error(create_session) -> None:\n    class UnexpectedException(BaseException):\n        pass\n\n    err = UnexpectedException(\"permission error\")\n    req = mock.Mock()\n    req_factory = mock.Mock(return_value=req)\n    req.send = mock.Mock(side_effect=err)\n    session = await create_session(request_class=req_factory)\n\n    connections = []\n    original_connect = session._connector.connect\n\n    async def connect(req, traces, timeout):\n        conn = await original_connect(req, traces, timeout)\n        connections.append(conn)\n        return conn\n\n    async def create_connection(req, traces, timeout):\n        # return self.transport, self.protocol\n        conn = mock.Mock()\n        return conn\n\n    session._connector.connect = connect\n    session._connector._create_connection = create_connection\n    session._connector._release = mock.Mock()\n\n    with pytest.raises(UnexpectedException):\n        async with session.request(\"get\", \"http://example.com\") as resp:\n            await resp.text()\n\n    # normally called during garbage collection.  triggers an exception\n    # if the connection wasn't already closed\n    for c in connections:\n        c.__del__()\n\n\n@pytest.mark.parametrize(\"protocol\", [\"http\", \"https\", \"ws\", \"wss\"])\nasync def test_ws_connect_allowed_protocols(\n    create_session: Any,\n    create_mocked_conn: Any,\n    protocol: str,\n    ws_key: Any,\n    key_data: Any,\n) -> None:\n    resp = mock.create_autospec(aiohttp.ClientResponse)\n    resp.status = 101\n    resp.headers = {\n        hdrs.UPGRADE: \"websocket\",\n        hdrs.CONNECTION: \"upgrade\",\n        hdrs.SEC_WEBSOCKET_ACCEPT: ws_key,\n    }\n    resp.url = URL(f\"{protocol}://example\")\n    resp.cookies = SimpleCookie()\n    resp.start = mock.AsyncMock()\n\n    req = mock.create_autospec(aiohttp.ClientRequest, spec_set=True)\n    req_factory = mock.Mock(return_value=req)\n    req.send = mock.AsyncMock(return_value=resp)\n    # BaseConnector allows all high level protocols by default\n    connector = BaseConnector()\n\n    session = await create_session(connector=connector, request_class=req_factory)\n\n    connections = []\n    original_connect = session._connector.connect\n\n    async def connect(req, traces, timeout):\n        conn = await original_connect(req, traces, timeout)\n        connections.append(conn)\n        return conn\n\n    async def create_connection(req, traces, timeout):\n        return create_mocked_conn()\n\n    connector = session._connector\n    with mock.patch.object(connector, \"connect\", connect), mock.patch.object(\n        connector, \"_create_connection\", create_connection\n    ), mock.patch.object(connector, \"_release\"), mock.patch(\n        \"aiohttp.client.os\"\n    ) as m_os:\n        m_os.urandom.return_value = key_data\n        await session.ws_connect(f\"{protocol}://example\")\n\n    # normally called during garbage collection.  triggers an exception\n    # if the connection wasn't already closed\n    for c in connections:\n        c.close()\n        c.__del__()\n\n    await session.close()\n\n\n@pytest.mark.parametrize(\"protocol\", [\"http\", \"https\", \"ws\", \"wss\", \"unix\"])\nasync def test_ws_connect_unix_socket_allowed_protocols(\n    create_session: Callable[..., Awaitable[ClientSession]],\n    create_mocked_conn: Callable[[], ResponseHandler],\n    protocol: str,\n    ws_key: bytes,\n    key_data: bytes,\n) -> None:\n    resp = mock.create_autospec(aiohttp.ClientResponse)\n    resp.status = 101\n    resp.headers = {\n        hdrs.UPGRADE: \"websocket\",\n        hdrs.CONNECTION: \"upgrade\",\n        hdrs.SEC_WEBSOCKET_ACCEPT: ws_key,\n    }\n    resp.url = URL(f\"{protocol}://example\")\n    resp.cookies = SimpleCookie()\n    resp.start = mock.AsyncMock()\n\n    req = mock.create_autospec(aiohttp.ClientRequest, spec_set=True)\n    req_factory = mock.Mock(return_value=req)\n    req.send = mock.AsyncMock(return_value=resp)\n    # UnixConnector allows all high level protocols by default and unix sockets\n    session = await create_session(\n        connector=UnixConnector(path=\"\"), request_class=req_factory\n    )\n\n    connections = []\n    assert session._connector is not None\n    original_connect = session._connector.connect\n\n    async def connect(\n        req: ClientRequest, traces: List[Trace], timeout: aiohttp.ClientTimeout\n    ) -> Connection:\n        conn = await original_connect(req, traces, timeout)\n        connections.append(conn)\n        return conn\n\n    async def create_connection(\n        req: object, traces: object, timeout: object\n    ) -> ResponseHandler:\n        return create_mocked_conn()\n\n    connector = session._connector\n    with mock.patch.object(connector, \"connect\", connect), mock.patch.object(\n        connector, \"_create_connection\", create_connection\n    ), mock.patch.object(connector, \"_release\"), mock.patch(\n        \"aiohttp.client.os\"\n    ) as m_os:\n        m_os.urandom.return_value = key_data\n        await session.ws_connect(f\"{protocol}://example\")\n\n    # normally called during garbage collection.  triggers an exception\n    # if the connection wasn't already closed\n    for c in connections:\n        c.close()\n        c.__del__()\n\n    await session.close()\n\n\nasync def test_cookie_jar_usage(loop: Any, aiohttp_client: Any) -> None:\n    req_url = None\n\n    jar = mock.Mock()\n    jar.filter_cookies.return_value = None\n\n    async def handler(request):\n        nonlocal req_url\n        req_url = \"http://%s/\" % request.host\n\n        resp = web.Response()\n        resp.set_cookie(\"response\", \"resp_value\")\n        return resp\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    session = await aiohttp_client(\n        app, cookies={\"request\": \"req_value\"}, cookie_jar=jar\n    )\n\n    # Updating the cookie jar with initial user defined cookies\n    jar.update_cookies.assert_called_with({\"request\": \"req_value\"})\n\n    jar.update_cookies.reset_mock()\n    resp = await session.get(\"/\")\n    await resp.release()\n\n    # Filtering the cookie jar before sending the request,\n    # getting the request URL as only parameter\n    jar.filter_cookies.assert_called_with(URL(req_url))\n\n    # Updating the cookie jar with the response cookies\n    assert jar.update_cookies.called\n    resp_cookies = jar.update_cookies.call_args[0][0]\n    assert isinstance(resp_cookies, SimpleCookie)\n    assert \"response\" in resp_cookies\n    assert resp_cookies[\"response\"].value == \"resp_value\"\n\n\nasync def test_session_default_version(loop) -> None:\n    session = aiohttp.ClientSession(loop=loop)\n    assert session.version == aiohttp.HttpVersion11\n    await session.close()\n\n\nasync def test_session_loop(loop) -> None:\n    session = aiohttp.ClientSession(loop=loop)\n    with pytest.warns(DeprecationWarning):\n        assert session.loop is loop\n    await session.close()\n\n\ndef test_proxy_str(session, params) -> None:\n    with mock.patch(\n        \"aiohttp.client.ClientSession._request\", new_callable=mock.MagicMock\n    ) as patched:\n        session.get(\"http://test.example.com\", proxy=\"http://proxy.com\", **params)\n    assert patched.called, \"`ClientSession._request` not called\"\n    assert list(patched.call_args) == [\n        (\n            \"GET\",\n            \"http://test.example.com\",\n        ),\n        dict(allow_redirects=True, proxy=\"http://proxy.com\", **params),\n    ]\n\n\nasync def test_request_tracing(loop, aiohttp_client) -> None:\n    async def handler(request):\n        return web.json_response({\"ok\": True})\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n\n    trace_config_ctx = mock.Mock()\n    trace_request_ctx = {}\n    body = \"This is request body\"\n    gathered_req_headers = CIMultiDict()\n    on_request_start = mock.Mock(side_effect=make_mocked_coro(mock.Mock()))\n    on_request_redirect = mock.Mock(side_effect=make_mocked_coro(mock.Mock()))\n    on_request_end = mock.Mock(side_effect=make_mocked_coro(mock.Mock()))\n\n    with io.BytesIO() as gathered_req_body, io.BytesIO() as gathered_res_body:\n\n        async def on_request_chunk_sent(session, context, params):\n            gathered_req_body.write(params.chunk)\n\n        async def on_response_chunk_received(session, context, params):\n            gathered_res_body.write(params.chunk)\n\n        async def on_request_headers_sent(session, context, params):\n            gathered_req_headers.extend(**params.headers)\n\n        trace_config = aiohttp.TraceConfig(\n            trace_config_ctx_factory=mock.Mock(return_value=trace_config_ctx)\n        )\n        trace_config.on_request_start.append(on_request_start)\n        trace_config.on_request_end.append(on_request_end)\n        trace_config.on_request_chunk_sent.append(on_request_chunk_sent)\n        trace_config.on_response_chunk_received.append(on_response_chunk_received)\n        trace_config.on_request_redirect.append(on_request_redirect)\n        trace_config.on_request_headers_sent.append(on_request_headers_sent)\n\n        headers = CIMultiDict({\"Custom-Header\": \"Custom value\"})\n        session = await aiohttp_client(\n            app, trace_configs=[trace_config], headers=headers\n        )\n\n        async with session.post(\n            \"/\", data=body, trace_request_ctx=trace_request_ctx\n        ) as resp:\n\n            await resp.json()\n\n            on_request_start.assert_called_once_with(\n                session.session,\n                trace_config_ctx,\n                aiohttp.TraceRequestStartParams(\n                    hdrs.METH_POST, session.make_url(\"/\"), headers\n                ),\n            )\n\n            on_request_end.assert_called_once_with(\n                session.session,\n                trace_config_ctx,\n                aiohttp.TraceRequestEndParams(\n                    hdrs.METH_POST, session.make_url(\"/\"), headers, resp\n                ),\n            )\n            assert not on_request_redirect.called\n            assert gathered_req_body.getvalue() == body.encode(\"utf8\")\n            assert gathered_res_body.getvalue() == json.dumps({\"ok\": True}).encode(\n                \"utf8\"\n            )\n            assert gathered_req_headers[\"Custom-Header\"] == \"Custom value\"\n\n\nasync def test_request_tracing_url_params(loop: Any, aiohttp_client: Any) -> None:\n    async def root_handler(request):\n        return web.Response()\n\n    async def redirect_handler(request):\n        raise web.HTTPFound(\"/\")\n\n    app = web.Application()\n    app.router.add_get(\"/\", root_handler)\n    app.router.add_get(\"/redirect\", redirect_handler)\n\n    mocks = [mock.Mock(side_effect=make_mocked_coro(mock.Mock())) for _ in range(7)]\n    (\n        on_request_start,\n        on_request_redirect,\n        on_request_end,\n        on_request_exception,\n        on_request_chunk_sent,\n        on_response_chunk_received,\n        on_request_headers_sent,\n    ) = mocks\n\n    trace_config = aiohttp.TraceConfig(\n        trace_config_ctx_factory=mock.Mock(return_value=mock.Mock())\n    )\n    trace_config.on_request_start.append(on_request_start)\n    trace_config.on_request_redirect.append(on_request_redirect)\n    trace_config.on_request_end.append(on_request_end)\n    trace_config.on_request_exception.append(on_request_exception)\n    trace_config.on_request_chunk_sent.append(on_request_chunk_sent)\n    trace_config.on_response_chunk_received.append(on_response_chunk_received)\n    trace_config.on_request_headers_sent.append(on_request_headers_sent)\n\n    session = await aiohttp_client(app, trace_configs=[trace_config])\n\n    def reset_mocks() -> None:\n        for m in mocks:\n            m.reset_mock()\n\n    def to_trace_urls(mock_func: mock.Mock) -> List[URL]:\n        return [call_args[0][-1].url for call_args in mock_func.call_args_list]\n\n    def to_url(path: str) -> URL:\n        return session.make_url(path)\n\n    # Standard\n    for req in [\n        lambda: session.get(\"/?x=0\"),\n        lambda: session.get(\"/\", params=dict(x=0)),\n    ]:\n        reset_mocks()\n        async with req() as resp:\n            await resp.text()\n            assert to_trace_urls(on_request_start) == [to_url(\"/?x=0\")]\n            assert to_trace_urls(on_request_redirect) == []\n            assert to_trace_urls(on_request_end) == [to_url(\"/?x=0\")]\n            assert to_trace_urls(on_request_exception) == []\n            assert to_trace_urls(on_request_chunk_sent) == [to_url(\"/?x=0\")]\n            assert to_trace_urls(on_response_chunk_received) == [to_url(\"/?x=0\")]\n            assert to_trace_urls(on_request_headers_sent) == [to_url(\"/?x=0\")]\n\n    # Redirect\n    for req in [\n        lambda: session.get(\"/redirect?x=0\"),\n        lambda: session.get(\"/redirect\", params=dict(x=0)),\n    ]:\n        reset_mocks()\n        async with req() as resp:\n            await resp.text()\n            assert to_trace_urls(on_request_start) == [to_url(\"/redirect?x=0\")]\n            assert to_trace_urls(on_request_redirect) == [to_url(\"/redirect?x=0\")]\n            assert to_trace_urls(on_request_end) == [to_url(\"/\")]\n            assert to_trace_urls(on_request_exception) == []\n            assert to_trace_urls(on_request_chunk_sent) == [\n                to_url(\"/redirect?x=0\"),\n                to_url(\"/\"),\n            ]\n            assert to_trace_urls(on_response_chunk_received) == [to_url(\"/\")]\n            assert to_trace_urls(on_request_headers_sent) == [\n                to_url(\"/redirect?x=0\"),\n                to_url(\"/\"),\n            ]\n\n    # Exception\n    with mock.patch(\"aiohttp.client.TCPConnector.connect\") as connect_patched:\n        connect_patched.side_effect = Exception()\n\n        for req in [\n            lambda: session.get(\"/?x=0\"),\n            lambda: session.get(\"/\", params=dict(x=0)),\n        ]:\n            reset_mocks()\n            with contextlib.suppress(Exception):\n                await req()\n            assert to_trace_urls(on_request_start) == [to_url(\"/?x=0\")]\n            assert to_trace_urls(on_request_redirect) == []\n            assert to_trace_urls(on_request_end) == []\n            assert to_trace_urls(on_request_exception) == [to_url(\"?x=0\")]\n            assert to_trace_urls(on_request_chunk_sent) == []\n            assert to_trace_urls(on_response_chunk_received) == []\n            assert to_trace_urls(on_request_headers_sent) == []\n\n\nasync def test_request_tracing_exception() -> None:\n    loop = asyncio.get_event_loop()\n    on_request_end = mock.Mock(side_effect=make_mocked_coro(mock.Mock()))\n    on_request_exception = mock.Mock(side_effect=make_mocked_coro(mock.Mock()))\n\n    trace_config = aiohttp.TraceConfig()\n    trace_config.on_request_end.append(on_request_end)\n    trace_config.on_request_exception.append(on_request_exception)\n\n    with mock.patch(\"aiohttp.client.TCPConnector.connect\") as connect_patched:\n        error = Exception()\n        connect_patched.side_effect = error\n\n        session = aiohttp.ClientSession(loop=loop, trace_configs=[trace_config])\n\n        try:\n            await session.get(\"http://example.com\")\n        except Exception:\n            pass\n\n        on_request_exception.assert_called_once_with(\n            session,\n            mock.ANY,\n            aiohttp.TraceRequestExceptionParams(\n                hdrs.METH_GET, URL(\"http://example.com\"), CIMultiDict(), error\n            ),\n        )\n        assert not on_request_end.called\n\n    await session.close()\n\n\nasync def test_request_tracing_interpose_headers(loop, aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n\n    class MyClientRequest(ClientRequest):\n        headers = None\n\n        def __init__(self, *args, **kwargs):\n            super().__init__(*args, **kwargs)\n            MyClientRequest.headers = self.headers\n\n    async def new_headers(session, trace_config_ctx, data):\n        data.headers[\"foo\"] = \"bar\"\n\n    trace_config = aiohttp.TraceConfig()\n    trace_config.on_request_start.append(new_headers)\n\n    session = await aiohttp_client(\n        app, request_class=MyClientRequest, trace_configs=[trace_config]\n    )\n\n    await session.get(\"/\")\n    assert MyClientRequest.headers[\"foo\"] == \"bar\"\n\n\ndef test_client_session_inheritance() -> None:\n    with pytest.warns(DeprecationWarning):\n\n        class A(ClientSession):\n            pass\n\n\n@pytest.mark.skipif(not DEBUG, reason=\"The check is applied in DEBUG mode only\")\nasync def test_client_session_custom_attr(loop) -> None:\n    session = ClientSession(loop=loop)\n    with pytest.warns(DeprecationWarning):\n        session.custom = None\n    await session.close()\n\n\nasync def test_client_session_timeout_args(loop) -> None:\n    session1 = ClientSession(loop=loop)\n    assert session1._timeout == client.DEFAULT_TIMEOUT\n\n    with pytest.warns(DeprecationWarning):\n        session2 = ClientSession(loop=loop, read_timeout=20 * 60, conn_timeout=30 * 60)\n    assert session2._timeout == client.ClientTimeout(total=20 * 60, connect=30 * 60)\n\n    with pytest.raises(ValueError):\n        ClientSession(\n            loop=loop, timeout=client.ClientTimeout(total=10 * 60), read_timeout=20 * 60\n        )\n\n    with pytest.raises(ValueError):\n        ClientSession(\n            loop=loop, timeout=client.ClientTimeout(total=10 * 60), conn_timeout=30 * 60\n        )\n\n    await session1.close()\n    await session2.close()\n\n\nasync def test_client_session_timeout_default_args(loop) -> None:\n    session1 = ClientSession()\n    assert session1.timeout == client.DEFAULT_TIMEOUT\n    await session1.close()\n\n\nasync def test_client_session_timeout_zero(\n    create_mocked_conn: Callable[[], ResponseHandler]\n) -> None:\n    async def create_connection(\n        req: object, traces: object, timeout: object\n    ) -> ResponseHandler:\n        await asyncio.sleep(0.01)\n        conn = create_mocked_conn()\n        conn.connected = True  # type: ignore[misc]\n        assert conn.transport is not None\n        conn.transport.is_closing.return_value = False  # type: ignore[attr-defined]\n        msg = mock.create_autospec(RawResponseMessage, spec_set=True, code=200)\n        conn.read.return_value = (msg, mock.Mock())  # type: ignore[attr-defined]\n        return conn\n\n    timeout = client.ClientTimeout(total=10, connect=0, sock_connect=0, sock_read=0)\n    async with ClientSession(timeout=timeout) as session:\n        with mock.patch.object(\n            session._connector, \"_create_connection\", create_connection\n        ):\n            try:\n                resp = await session.get(\"http://example.com\")\n            except asyncio.TimeoutError:  # pragma: no cover\n                pytest.fail(\"0 should disable timeout.\")\n            resp.close()\n\n\nasync def test_client_session_timeout_bad_argument() -> None:\n    with pytest.raises(ValueError):\n        ClientSession(timeout=\"test_bad_argumnet\")\n    with pytest.raises(ValueError):\n        ClientSession(timeout=100)\n\n\nasync def test_requote_redirect_url_default() -> None:\n    session = ClientSession()\n    assert session.requote_redirect_url\n    await session.close()\n\n\nasync def test_requote_redirect_url_default_disable() -> None:\n    session = ClientSession(requote_redirect_url=False)\n    assert not session.requote_redirect_url\n    await session.close()\n\n\nasync def test_requote_redirect_setter() -> None:\n    session = ClientSession()\n    assert session.requote_redirect_url\n    with pytest.warns(DeprecationWarning):\n        session.requote_redirect_url = False\n    assert not session.requote_redirect_url\n    await session.close()\n\n\n@pytest.mark.parametrize(\n    (\"base_url\", \"url\", \"expected_url\"),\n    [\n        pytest.param(\n            None,\n            \"http://example.com/test\",\n            URL(\"http://example.com/test\"),\n            id=\"base_url=None url='http://example.com/test'\",\n        ),\n        pytest.param(\n            None,\n            URL(\"http://example.com/test\"),\n            URL(\"http://example.com/test\"),\n            id=\"base_url=None url=URL('http://example.com/test')\",\n        ),\n        pytest.param(\n            \"http://example.com\",\n            \"/test\",\n            URL(\"http://example.com/test\"),\n            id=\"base_url='http://example.com' url='/test'\",\n        ),\n        pytest.param(\n            URL(\"http://example.com\"),\n            \"/test\",\n            URL(\"http://example.com/test\"),\n            id=\"base_url=URL('http://example.com') url='/test'\",\n        ),\n    ],\n)\nasync def test_build_url_returns_expected_url(\n    create_session, base_url, url, expected_url\n) -> None:\n    session = await create_session(base_url)\n    assert session._build_url(url) == expected_url\n\n\nasync def test_instantiation_with_invalid_timeout_value(loop):\n    loop.set_debug(False)\n    logs = []\n    loop.set_exception_handler(lambda loop, ctx: logs.append(ctx))\n    with pytest.raises(ValueError, match=\"timeout parameter cannot be .*\"):\n        ClientSession(timeout=1)\n    # should not have \"Unclosed client session\" warning\n    assert not logs\n\n\n@pytest.mark.parametrize(\n    (\"outer_name\", \"inner_name\"),\n    [\n        (\"skip_auto_headers\", \"_skip_auto_headers\"),\n        (\"auth\", \"_default_auth\"),\n        (\"json_serialize\", \"_json_serialize\"),\n        (\"connector_owner\", \"_connector_owner\"),\n        (\"raise_for_status\", \"_raise_for_status\"),\n        (\"trust_env\", \"_trust_env\"),\n        (\"trace_configs\", \"_trace_configs\"),\n    ],\n)\nasync def test_properties(\n    session: ClientSession, outer_name: str, inner_name: str\n) -> None:\n    value = uuid4()\n    setattr(session, inner_name, value)\n    assert value == getattr(session, outer_name)\n",
            "new_file_content": "import asyncio\nimport contextlib\nimport gc\nimport io\nimport json\nfrom http.cookies import SimpleCookie\nfrom typing import Any, Awaitable, Callable, List\nfrom unittest import mock\nfrom uuid import uuid4\n\nimport pytest\nfrom multidict import CIMultiDict, MultiDict\nfrom re_assert import Matches\nfrom yarl import URL\n\nimport aiohttp\nfrom aiohttp import client, hdrs, web\nfrom aiohttp.client import ClientSession\nfrom aiohttp.client_proto import ResponseHandler\nfrom aiohttp.client_reqrep import ClientRequest\nfrom aiohttp.connector import BaseConnector, Connection, TCPConnector, UnixConnector\nfrom aiohttp.helpers import DEBUG\nfrom aiohttp.http import RawResponseMessage\nfrom aiohttp.test_utils import make_mocked_coro\nfrom aiohttp.tracing import Trace\n\n\n@pytest.fixture\ndef connector(loop):\n    async def make_conn():\n        return BaseConnector(loop=loop)\n\n    conn = loop.run_until_complete(make_conn())\n    proto = mock.Mock()\n    conn._conns[\"a\"] = [(proto, 123)]\n    yield conn\n    loop.run_until_complete(conn.close())\n\n\n@pytest.fixture\ndef create_session(loop):\n    session = None\n\n    async def maker(*args, **kwargs):\n        nonlocal session\n        session = ClientSession(*args, loop=loop, **kwargs)\n        return session\n\n    yield maker\n    if session is not None:\n        loop.run_until_complete(session.close())\n\n\n@pytest.fixture\ndef session(create_session, loop):\n    return loop.run_until_complete(create_session())\n\n\n@pytest.fixture\ndef params():\n    return dict(\n        headers={\"Authorization\": \"Basic ...\"},\n        max_redirects=2,\n        encoding=\"latin1\",\n        version=aiohttp.HttpVersion10,\n        compress=\"deflate\",\n        chunked=True,\n        expect100=True,\n        read_until_eof=False,\n    )\n\n\nasync def test_close_coro(create_session) -> None:\n    session = await create_session()\n    await session.close()\n\n\nasync def test_init_headers_simple_dict(create_session) -> None:\n    session = await create_session(headers={\"h1\": \"header1\", \"h2\": \"header2\"})\n    assert sorted(session.headers.items()) == ([(\"h1\", \"header1\"), (\"h2\", \"header2\")])\n\n\nasync def test_init_headers_list_of_tuples(create_session) -> None:\n    session = await create_session(\n        headers=[(\"h1\", \"header1\"), (\"h2\", \"header2\"), (\"h3\", \"header3\")]\n    )\n    assert session.headers == CIMultiDict(\n        [(\"h1\", \"header1\"), (\"h2\", \"header2\"), (\"h3\", \"header3\")]\n    )\n\n\nasync def test_init_headers_MultiDict(create_session) -> None:\n    session = await create_session(\n        headers=MultiDict([(\"h1\", \"header1\"), (\"h2\", \"header2\"), (\"h3\", \"header3\")])\n    )\n    assert session.headers == CIMultiDict(\n        [(\"H1\", \"header1\"), (\"H2\", \"header2\"), (\"H3\", \"header3\")]\n    )\n\n\nasync def test_init_headers_list_of_tuples_with_duplicates(create_session) -> None:\n    session = await create_session(\n        headers=[(\"h1\", \"header11\"), (\"h2\", \"header21\"), (\"h1\", \"header12\")]\n    )\n    assert session.headers == CIMultiDict(\n        [(\"H1\", \"header11\"), (\"H2\", \"header21\"), (\"H1\", \"header12\")]\n    )\n\n\nasync def test_init_cookies_with_simple_dict(create_session) -> None:\n    session = await create_session(cookies={\"c1\": \"cookie1\", \"c2\": \"cookie2\"})\n    cookies = session.cookie_jar.filter_cookies()\n    assert set(cookies) == {\"c1\", \"c2\"}\n    assert cookies[\"c1\"].value == \"cookie1\"\n    assert cookies[\"c2\"].value == \"cookie2\"\n\n\nasync def test_init_cookies_with_list_of_tuples(create_session) -> None:\n    session = await create_session(cookies=[(\"c1\", \"cookie1\"), (\"c2\", \"cookie2\")])\n\n    cookies = session.cookie_jar.filter_cookies()\n    assert set(cookies) == {\"c1\", \"c2\"}\n    assert cookies[\"c1\"].value == \"cookie1\"\n    assert cookies[\"c2\"].value == \"cookie2\"\n\n\nasync def test_merge_headers(create_session) -> None:\n    # Check incoming simple dict\n    session = await create_session(headers={\"h1\": \"header1\", \"h2\": \"header2\"})\n    headers = session._prepare_headers({\"h1\": \"h1\"})\n\n    assert isinstance(headers, CIMultiDict)\n    assert headers == {\"h1\": \"h1\", \"h2\": \"header2\"}\n\n\nasync def test_merge_headers_with_multi_dict(create_session) -> None:\n    session = await create_session(headers={\"h1\": \"header1\", \"h2\": \"header2\"})\n    headers = session._prepare_headers(MultiDict([(\"h1\", \"h1\")]))\n    assert isinstance(headers, CIMultiDict)\n    assert headers == {\"h1\": \"h1\", \"h2\": \"header2\"}\n\n\nasync def test_merge_headers_with_list_of_tuples(create_session) -> None:\n    session = await create_session(headers={\"h1\": \"header1\", \"h2\": \"header2\"})\n    headers = session._prepare_headers([(\"h1\", \"h1\")])\n    assert isinstance(headers, CIMultiDict)\n    assert headers == {\"h1\": \"h1\", \"h2\": \"header2\"}\n\n\nasync def test_merge_headers_with_list_of_tuples_duplicated_names(\n    create_session,\n) -> None:\n    session = await create_session(headers={\"h1\": \"header1\", \"h2\": \"header2\"})\n\n    headers = session._prepare_headers([(\"h1\", \"v1\"), (\"h1\", \"v2\")])\n\n    assert isinstance(headers, CIMultiDict)\n    assert list(sorted(headers.items())) == [\n        (\"h1\", \"v1\"),\n        (\"h1\", \"v2\"),\n        (\"h2\", \"header2\"),\n    ]\n\n\ndef test_http_GET(session, params) -> None:\n    with mock.patch(\n        \"aiohttp.client.ClientSession._request\", new_callable=mock.MagicMock\n    ) as patched:\n        session.get(\"http://test.example.com\", params={\"x\": 1}, **params)\n    assert patched.called, \"`ClientSession._request` not called\"\n    assert list(patched.call_args) == [\n        (\n            \"GET\",\n            \"http://test.example.com\",\n        ),\n        dict(params={\"x\": 1}, allow_redirects=True, **params),\n    ]\n\n\ndef test_http_OPTIONS(session, params) -> None:\n    with mock.patch(\n        \"aiohttp.client.ClientSession._request\", new_callable=mock.MagicMock\n    ) as patched:\n        session.options(\"http://opt.example.com\", params={\"x\": 2}, **params)\n    assert patched.called, \"`ClientSession._request` not called\"\n    assert list(patched.call_args) == [\n        (\n            \"OPTIONS\",\n            \"http://opt.example.com\",\n        ),\n        dict(params={\"x\": 2}, allow_redirects=True, **params),\n    ]\n\n\ndef test_http_HEAD(session, params) -> None:\n    with mock.patch(\n        \"aiohttp.client.ClientSession._request\", new_callable=mock.MagicMock\n    ) as patched:\n        session.head(\"http://head.example.com\", params={\"x\": 2}, **params)\n    assert patched.called, \"`ClientSession._request` not called\"\n    assert list(patched.call_args) == [\n        (\n            \"HEAD\",\n            \"http://head.example.com\",\n        ),\n        dict(params={\"x\": 2}, allow_redirects=False, **params),\n    ]\n\n\ndef test_http_POST(session, params) -> None:\n    with mock.patch(\n        \"aiohttp.client.ClientSession._request\", new_callable=mock.MagicMock\n    ) as patched:\n        session.post(\n            \"http://post.example.com\", params={\"x\": 2}, data=\"Some_data\", **params\n        )\n    assert patched.called, \"`ClientSession._request` not called\"\n    assert list(patched.call_args) == [\n        (\n            \"POST\",\n            \"http://post.example.com\",\n        ),\n        dict(params={\"x\": 2}, data=\"Some_data\", **params),\n    ]\n\n\ndef test_http_PUT(session, params) -> None:\n    with mock.patch(\n        \"aiohttp.client.ClientSession._request\", new_callable=mock.MagicMock\n    ) as patched:\n        session.put(\n            \"http://put.example.com\", params={\"x\": 2}, data=\"Some_data\", **params\n        )\n    assert patched.called, \"`ClientSession._request` not called\"\n    assert list(patched.call_args) == [\n        (\n            \"PUT\",\n            \"http://put.example.com\",\n        ),\n        dict(params={\"x\": 2}, data=\"Some_data\", **params),\n    ]\n\n\ndef test_http_PATCH(session, params) -> None:\n    with mock.patch(\n        \"aiohttp.client.ClientSession._request\", new_callable=mock.MagicMock\n    ) as patched:\n        session.patch(\n            \"http://patch.example.com\", params={\"x\": 2}, data=\"Some_data\", **params\n        )\n    assert patched.called, \"`ClientSession._request` not called\"\n    assert list(patched.call_args) == [\n        (\n            \"PATCH\",\n            \"http://patch.example.com\",\n        ),\n        dict(params={\"x\": 2}, data=\"Some_data\", **params),\n    ]\n\n\ndef test_http_DELETE(session, params) -> None:\n    with mock.patch(\n        \"aiohttp.client.ClientSession._request\", new_callable=mock.MagicMock\n    ) as patched:\n        session.delete(\"http://delete.example.com\", params={\"x\": 2}, **params)\n    assert patched.called, \"`ClientSession._request` not called\"\n    assert list(patched.call_args) == [\n        (\n            \"DELETE\",\n            \"http://delete.example.com\",\n        ),\n        dict(params={\"x\": 2}, **params),\n    ]\n\n\nasync def test_close(create_session, connector) -> None:\n    session = await create_session(connector=connector)\n\n    await session.close()\n    assert session.connector is None\n    assert connector.closed\n\n\nasync def test_closed(session) -> None:\n    assert not session.closed\n    await session.close()\n    assert session.closed\n\n\nasync def test_connector(create_session, loop, mocker) -> None:\n    connector = TCPConnector(loop=loop)\n    mocker.spy(connector, \"close\")\n    session = await create_session(connector=connector)\n    assert session.connector is connector\n\n    await session.close()\n    assert connector.close.called\n    await connector.close()\n\n\nasync def test_create_connector(create_session, loop, mocker) -> None:\n    session = await create_session()\n    connector = session.connector\n    mocker.spy(session.connector, \"close\")\n\n    await session.close()\n    assert connector.close.called\n\n\ndef test_connector_loop(loop) -> None:\n    with contextlib.ExitStack() as stack:\n        another_loop = asyncio.new_event_loop()\n        stack.enter_context(contextlib.closing(another_loop))\n\n        async def make_connector():\n            return TCPConnector()\n\n        connector = another_loop.run_until_complete(make_connector())\n\n        with pytest.raises(RuntimeError) as ctx:\n\n            async def make_sess():\n                return ClientSession(connector=connector, loop=loop)\n\n            loop.run_until_complete(make_sess())\n        assert (\n            Matches(\"Session and connector has to use same event loop\")\n            == str(ctx.value).strip()\n        )\n        another_loop.run_until_complete(connector.close())\n\n\ndef test_detach(loop, session) -> None:\n    conn = session.connector\n    try:\n        assert not conn.closed\n        session.detach()\n        assert session.connector is None\n        assert session.closed\n        assert not conn.closed\n    finally:\n        loop.run_until_complete(conn.close())\n\n\nasync def test_request_closed_session(session) -> None:\n    await session.close()\n    with pytest.raises(RuntimeError):\n        await session.request(\"get\", \"/\")\n\n\ndef test_close_flag_for_closed_connector(loop, session) -> None:\n    conn = session.connector\n    assert not session.closed\n    loop.run_until_complete(conn.close())\n    assert session.closed\n\n\nasync def test_double_close(connector, create_session) -> None:\n    session = await create_session(connector=connector)\n\n    await session.close()\n    assert session.connector is None\n    await session.close()\n    assert session.closed\n    assert connector.closed\n\n\nasync def test_del(connector, loop) -> None:\n    loop.set_debug(False)\n    # N.B. don't use session fixture, it stores extra reference internally\n    session = ClientSession(connector=connector, loop=loop)\n    logs = []\n    loop.set_exception_handler(lambda loop, ctx: logs.append(ctx))\n\n    with pytest.warns(ResourceWarning):\n        del session\n        gc.collect()\n\n    assert len(logs) == 1\n    expected = {\"client_session\": mock.ANY, \"message\": \"Unclosed client session\"}\n    assert logs[0] == expected\n\n\nasync def test_del_debug(connector, loop) -> None:\n    loop.set_debug(True)\n    # N.B. don't use session fixture, it stores extra reference internally\n    session = ClientSession(connector=connector, loop=loop)\n    logs = []\n    loop.set_exception_handler(lambda loop, ctx: logs.append(ctx))\n\n    with pytest.warns(ResourceWarning):\n        del session\n        gc.collect()\n\n    assert len(logs) == 1\n    expected = {\n        \"client_session\": mock.ANY,\n        \"message\": \"Unclosed client session\",\n        \"source_traceback\": mock.ANY,\n    }\n    assert logs[0] == expected\n\n\nasync def test_session_context_manager(connector, loop) -> None:\n    with pytest.raises(TypeError):\n        with ClientSession(loop=loop, connector=connector) as session:\n            pass\n\n        assert session.closed\n\n\nasync def test_borrow_connector_loop(connector, create_session, loop) -> None:\n    session = ClientSession(connector=connector, loop=None)\n    try:\n        assert session._loop, loop\n    finally:\n        await session.close()\n\n\nasync def test_reraise_os_error(create_session) -> None:\n    err = OSError(1, \"permission error\")\n    req = mock.Mock()\n    req_factory = mock.Mock(return_value=req)\n    req.send = mock.Mock(side_effect=err)\n    session = await create_session(request_class=req_factory)\n\n    async def create_connection(req, traces, timeout):\n        # return self.transport, self.protocol\n        return mock.Mock()\n\n    session._connector._create_connection = create_connection\n    session._connector._release = mock.Mock()\n\n    with pytest.raises(aiohttp.ClientOSError) as ctx:\n        await session.request(\"get\", \"http://example.com\")\n    e = ctx.value\n    assert e.errno == err.errno\n    assert e.strerror == err.strerror\n\n\nasync def test_close_conn_on_error(create_session) -> None:\n    class UnexpectedException(BaseException):\n        pass\n\n    err = UnexpectedException(\"permission error\")\n    req = mock.Mock()\n    req_factory = mock.Mock(return_value=req)\n    req.send = mock.Mock(side_effect=err)\n    session = await create_session(request_class=req_factory)\n\n    connections = []\n    original_connect = session._connector.connect\n\n    async def connect(req, traces, timeout):\n        conn = await original_connect(req, traces, timeout)\n        connections.append(conn)\n        return conn\n\n    async def create_connection(req, traces, timeout):\n        # return self.transport, self.protocol\n        conn = mock.Mock()\n        return conn\n\n    session._connector.connect = connect\n    session._connector._create_connection = create_connection\n    session._connector._release = mock.Mock()\n\n    with pytest.raises(UnexpectedException):\n        async with session.request(\"get\", \"http://example.com\") as resp:\n            await resp.text()\n\n    # normally called during garbage collection.  triggers an exception\n    # if the connection wasn't already closed\n    for c in connections:\n        c.__del__()\n\n\n@pytest.mark.parametrize(\"protocol\", [\"http\", \"https\", \"ws\", \"wss\"])\nasync def test_ws_connect_allowed_protocols(\n    create_session: Any,\n    create_mocked_conn: Any,\n    protocol: str,\n    ws_key: Any,\n    key_data: Any,\n) -> None:\n    resp = mock.create_autospec(aiohttp.ClientResponse)\n    resp.status = 101\n    resp.headers = {\n        hdrs.UPGRADE: \"websocket\",\n        hdrs.CONNECTION: \"upgrade\",\n        hdrs.SEC_WEBSOCKET_ACCEPT: ws_key,\n    }\n    resp.url = URL(f\"{protocol}://example\")\n    resp.cookies = SimpleCookie()\n    resp.start = mock.AsyncMock()\n\n    req = mock.create_autospec(aiohttp.ClientRequest, spec_set=True)\n    req_factory = mock.Mock(return_value=req)\n    req.send = mock.AsyncMock(return_value=resp)\n    # BaseConnector allows all high level protocols by default\n    connector = BaseConnector()\n\n    session = await create_session(connector=connector, request_class=req_factory)\n\n    connections = []\n    original_connect = session._connector.connect\n\n    async def connect(req, traces, timeout):\n        conn = await original_connect(req, traces, timeout)\n        connections.append(conn)\n        return conn\n\n    async def create_connection(req, traces, timeout):\n        return create_mocked_conn()\n\n    connector = session._connector\n    with mock.patch.object(connector, \"connect\", connect), mock.patch.object(\n        connector, \"_create_connection\", create_connection\n    ), mock.patch.object(connector, \"_release\"), mock.patch(\n        \"aiohttp.client.os\"\n    ) as m_os:\n        m_os.urandom.return_value = key_data\n        await session.ws_connect(f\"{protocol}://example\")\n\n    # normally called during garbage collection.  triggers an exception\n    # if the connection wasn't already closed\n    for c in connections:\n        c.close()\n        c.__del__()\n\n    await session.close()\n\n\n@pytest.mark.parametrize(\"protocol\", [\"http\", \"https\", \"ws\", \"wss\", \"unix\"])\nasync def test_ws_connect_unix_socket_allowed_protocols(\n    create_session: Callable[..., Awaitable[ClientSession]],\n    create_mocked_conn: Callable[[], ResponseHandler],\n    protocol: str,\n    ws_key: bytes,\n    key_data: bytes,\n) -> None:\n    resp = mock.create_autospec(aiohttp.ClientResponse)\n    resp.status = 101\n    resp.headers = {\n        hdrs.UPGRADE: \"websocket\",\n        hdrs.CONNECTION: \"upgrade\",\n        hdrs.SEC_WEBSOCKET_ACCEPT: ws_key,\n    }\n    resp.url = URL(f\"{protocol}://example\")\n    resp.cookies = SimpleCookie()\n    resp.start = mock.AsyncMock()\n\n    req = mock.create_autospec(aiohttp.ClientRequest, spec_set=True)\n    req_factory = mock.Mock(return_value=req)\n    req.send = mock.AsyncMock(return_value=resp)\n    # UnixConnector allows all high level protocols by default and unix sockets\n    session = await create_session(\n        connector=UnixConnector(path=\"\"), request_class=req_factory\n    )\n\n    connections = []\n    assert session._connector is not None\n    original_connect = session._connector.connect\n\n    async def connect(\n        req: ClientRequest, traces: List[Trace], timeout: aiohttp.ClientTimeout\n    ) -> Connection:\n        conn = await original_connect(req, traces, timeout)\n        connections.append(conn)\n        return conn\n\n    async def create_connection(\n        req: object, traces: object, timeout: object\n    ) -> ResponseHandler:\n        return create_mocked_conn()\n\n    connector = session._connector\n    with mock.patch.object(connector, \"connect\", connect), mock.patch.object(\n        connector, \"_create_connection\", create_connection\n    ), mock.patch.object(connector, \"_release\"), mock.patch(\n        \"aiohttp.client.os\"\n    ) as m_os:\n        m_os.urandom.return_value = key_data\n        await session.ws_connect(f\"{protocol}://example\")\n\n    # normally called during garbage collection.  triggers an exception\n    # if the connection wasn't already closed\n    for c in connections:\n        c.close()\n        c.__del__()\n\n    await session.close()\n\n\nasync def test_cookie_jar_usage(loop: Any, aiohttp_client: Any) -> None:\n    req_url = None\n\n    jar = mock.Mock()\n    jar.filter_cookies.return_value = None\n\n    async def handler(request):\n        nonlocal req_url\n        req_url = \"http://%s/\" % request.host\n\n        resp = web.Response()\n        resp.set_cookie(\"response\", \"resp_value\")\n        return resp\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    session = await aiohttp_client(\n        app, cookies={\"request\": \"req_value\"}, cookie_jar=jar\n    )\n\n    # Updating the cookie jar with initial user defined cookies\n    jar.update_cookies.assert_called_with({\"request\": \"req_value\"})\n\n    jar.update_cookies.reset_mock()\n    resp = await session.get(\"/\")\n    await resp.release()\n\n    # Filtering the cookie jar before sending the request,\n    # getting the request URL as only parameter\n    jar.filter_cookies.assert_called_with(URL(req_url))\n\n    # Updating the cookie jar with the response cookies\n    assert jar.update_cookies.called\n    resp_cookies = jar.update_cookies.call_args[0][0]\n    assert isinstance(resp_cookies, SimpleCookie)\n    assert \"response\" in resp_cookies\n    assert resp_cookies[\"response\"].value == \"resp_value\"\n\n\nasync def test_session_default_version(loop) -> None:\n    session = aiohttp.ClientSession(loop=loop)\n    assert session.version == aiohttp.HttpVersion11\n    await session.close()\n\n\nasync def test_session_loop(loop) -> None:\n    session = aiohttp.ClientSession(loop=loop)\n    with pytest.warns(DeprecationWarning):\n        assert session.loop is loop\n    await session.close()\n\n\ndef test_proxy_str(session, params) -> None:\n    with mock.patch(\n        \"aiohttp.client.ClientSession._request\", new_callable=mock.MagicMock\n    ) as patched:\n        session.get(\"http://test.example.com\", proxy=\"http://proxy.com\", **params)\n    assert patched.called, \"`ClientSession._request` not called\"\n    assert list(patched.call_args) == [\n        (\n            \"GET\",\n            \"http://test.example.com\",\n        ),\n        dict(allow_redirects=True, proxy=\"http://proxy.com\", **params),\n    ]\n\n\nasync def test_default_proxy(loop: asyncio.AbstractEventLoop) -> None:\n    proxy_url = URL(\"http://proxy.example.com\")\n    proxy_auth = mock.Mock()\n    proxy_url2 = URL(\"http://proxy.example2.com\")\n    proxy_auth2 = mock.Mock()\n\n    class OnCall(Exception):\n        pass\n\n    request_class_mock = mock.Mock(side_effect=OnCall())\n    session = ClientSession(\n        proxy=proxy_url, proxy_auth=proxy_auth, request_class=request_class_mock\n    )\n\n    assert session._default_proxy == proxy_url, \"`ClientSession._default_proxy` not set\"\n    assert (\n        session._default_proxy_auth == proxy_auth\n    ), \"`ClientSession._default_proxy_auth` not set\"\n\n    with pytest.raises(OnCall):\n        await session.get(\n            \"http://example.com\",\n        )\n\n    assert request_class_mock.called, \"request class not called\"\n    assert (\n        request_class_mock.call_args[1].get(\"proxy\") == proxy_url\n    ), \"`ClientSession._request` uses default proxy not one used in ClientSession.get\"\n    assert (\n        request_class_mock.call_args[1].get(\"proxy_auth\") == proxy_auth\n    ), \"`ClientSession._request` uses default proxy_auth not one used in ClientSession.get\"\n\n    request_class_mock.reset_mock()\n    with pytest.raises(OnCall):\n        await session.get(\n            \"http://example.com\", proxy=proxy_url2, proxy_auth=proxy_auth2\n        )\n\n    assert request_class_mock.called, \"request class not called\"\n    assert (\n        request_class_mock.call_args[1].get(\"proxy\") == proxy_url2\n    ), \"`ClientSession._request` uses default proxy not one used in ClientSession.get\"\n    assert (\n        request_class_mock.call_args[1].get(\"proxy_auth\") == proxy_auth2\n    ), \"`ClientSession._request` uses default proxy_auth not one used in ClientSession.get\"\n\n    await session.close()\n\n\nasync def test_request_tracing(loop: asyncio.AbstractEventLoop, aiohttp_client) -> None:\n    async def handler(request: web.Request) -> web.Response:\n        return web.json_response({\"ok\": True})\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n\n    trace_config_ctx = mock.Mock()\n    trace_request_ctx = {}\n    body = \"This is request body\"\n    gathered_req_headers = CIMultiDict()\n    on_request_start = mock.Mock(side_effect=make_mocked_coro(mock.Mock()))\n    on_request_redirect = mock.Mock(side_effect=make_mocked_coro(mock.Mock()))\n    on_request_end = mock.Mock(side_effect=make_mocked_coro(mock.Mock()))\n\n    with io.BytesIO() as gathered_req_body, io.BytesIO() as gathered_res_body:\n\n        async def on_request_chunk_sent(session, context, params):\n            gathered_req_body.write(params.chunk)\n\n        async def on_response_chunk_received(session, context, params):\n            gathered_res_body.write(params.chunk)\n\n        async def on_request_headers_sent(session, context, params):\n            gathered_req_headers.extend(**params.headers)\n\n        trace_config = aiohttp.TraceConfig(\n            trace_config_ctx_factory=mock.Mock(return_value=trace_config_ctx)\n        )\n        trace_config.on_request_start.append(on_request_start)\n        trace_config.on_request_end.append(on_request_end)\n        trace_config.on_request_chunk_sent.append(on_request_chunk_sent)\n        trace_config.on_response_chunk_received.append(on_response_chunk_received)\n        trace_config.on_request_redirect.append(on_request_redirect)\n        trace_config.on_request_headers_sent.append(on_request_headers_sent)\n\n        headers = CIMultiDict({\"Custom-Header\": \"Custom value\"})\n        session = await aiohttp_client(\n            app, trace_configs=[trace_config], headers=headers\n        )\n\n        async with session.post(\n            \"/\", data=body, trace_request_ctx=trace_request_ctx\n        ) as resp:\n\n            await resp.json()\n\n            on_request_start.assert_called_once_with(\n                session.session,\n                trace_config_ctx,\n                aiohttp.TraceRequestStartParams(\n                    hdrs.METH_POST, session.make_url(\"/\"), headers\n                ),\n            )\n\n            on_request_end.assert_called_once_with(\n                session.session,\n                trace_config_ctx,\n                aiohttp.TraceRequestEndParams(\n                    hdrs.METH_POST, session.make_url(\"/\"), headers, resp\n                ),\n            )\n            assert not on_request_redirect.called\n            assert gathered_req_body.getvalue() == body.encode(\"utf8\")\n            assert gathered_res_body.getvalue() == json.dumps({\"ok\": True}).encode(\n                \"utf8\"\n            )\n            assert gathered_req_headers[\"Custom-Header\"] == \"Custom value\"\n\n\nasync def test_request_tracing_url_params(loop: Any, aiohttp_client: Any) -> None:\n    async def root_handler(request):\n        return web.Response()\n\n    async def redirect_handler(request):\n        raise web.HTTPFound(\"/\")\n\n    app = web.Application()\n    app.router.add_get(\"/\", root_handler)\n    app.router.add_get(\"/redirect\", redirect_handler)\n\n    mocks = [mock.Mock(side_effect=make_mocked_coro(mock.Mock())) for _ in range(7)]\n    (\n        on_request_start,\n        on_request_redirect,\n        on_request_end,\n        on_request_exception,\n        on_request_chunk_sent,\n        on_response_chunk_received,\n        on_request_headers_sent,\n    ) = mocks\n\n    trace_config = aiohttp.TraceConfig(\n        trace_config_ctx_factory=mock.Mock(return_value=mock.Mock())\n    )\n    trace_config.on_request_start.append(on_request_start)\n    trace_config.on_request_redirect.append(on_request_redirect)\n    trace_config.on_request_end.append(on_request_end)\n    trace_config.on_request_exception.append(on_request_exception)\n    trace_config.on_request_chunk_sent.append(on_request_chunk_sent)\n    trace_config.on_response_chunk_received.append(on_response_chunk_received)\n    trace_config.on_request_headers_sent.append(on_request_headers_sent)\n\n    session = await aiohttp_client(app, trace_configs=[trace_config])\n\n    def reset_mocks() -> None:\n        for m in mocks:\n            m.reset_mock()\n\n    def to_trace_urls(mock_func: mock.Mock) -> List[URL]:\n        return [call_args[0][-1].url for call_args in mock_func.call_args_list]\n\n    def to_url(path: str) -> URL:\n        return session.make_url(path)\n\n    # Standard\n    for req in [\n        lambda: session.get(\"/?x=0\"),\n        lambda: session.get(\"/\", params=dict(x=0)),\n    ]:\n        reset_mocks()\n        async with req() as resp:\n            await resp.text()\n            assert to_trace_urls(on_request_start) == [to_url(\"/?x=0\")]\n            assert to_trace_urls(on_request_redirect) == []\n            assert to_trace_urls(on_request_end) == [to_url(\"/?x=0\")]\n            assert to_trace_urls(on_request_exception) == []\n            assert to_trace_urls(on_request_chunk_sent) == [to_url(\"/?x=0\")]\n            assert to_trace_urls(on_response_chunk_received) == [to_url(\"/?x=0\")]\n            assert to_trace_urls(on_request_headers_sent) == [to_url(\"/?x=0\")]\n\n    # Redirect\n    for req in [\n        lambda: session.get(\"/redirect?x=0\"),\n        lambda: session.get(\"/redirect\", params=dict(x=0)),\n    ]:\n        reset_mocks()\n        async with req() as resp:\n            await resp.text()\n            assert to_trace_urls(on_request_start) == [to_url(\"/redirect?x=0\")]\n            assert to_trace_urls(on_request_redirect) == [to_url(\"/redirect?x=0\")]\n            assert to_trace_urls(on_request_end) == [to_url(\"/\")]\n            assert to_trace_urls(on_request_exception) == []\n            assert to_trace_urls(on_request_chunk_sent) == [\n                to_url(\"/redirect?x=0\"),\n                to_url(\"/\"),\n            ]\n            assert to_trace_urls(on_response_chunk_received) == [to_url(\"/\")]\n            assert to_trace_urls(on_request_headers_sent) == [\n                to_url(\"/redirect?x=0\"),\n                to_url(\"/\"),\n            ]\n\n    # Exception\n    with mock.patch(\"aiohttp.client.TCPConnector.connect\") as connect_patched:\n        connect_patched.side_effect = Exception()\n\n        for req in [\n            lambda: session.get(\"/?x=0\"),\n            lambda: session.get(\"/\", params=dict(x=0)),\n        ]:\n            reset_mocks()\n            with contextlib.suppress(Exception):\n                await req()\n            assert to_trace_urls(on_request_start) == [to_url(\"/?x=0\")]\n            assert to_trace_urls(on_request_redirect) == []\n            assert to_trace_urls(on_request_end) == []\n            assert to_trace_urls(on_request_exception) == [to_url(\"?x=0\")]\n            assert to_trace_urls(on_request_chunk_sent) == []\n            assert to_trace_urls(on_response_chunk_received) == []\n            assert to_trace_urls(on_request_headers_sent) == []\n\n\nasync def test_request_tracing_exception() -> None:\n    loop = asyncio.get_event_loop()\n    on_request_end = mock.Mock(side_effect=make_mocked_coro(mock.Mock()))\n    on_request_exception = mock.Mock(side_effect=make_mocked_coro(mock.Mock()))\n\n    trace_config = aiohttp.TraceConfig()\n    trace_config.on_request_end.append(on_request_end)\n    trace_config.on_request_exception.append(on_request_exception)\n\n    with mock.patch(\"aiohttp.client.TCPConnector.connect\") as connect_patched:\n        error = Exception()\n        connect_patched.side_effect = error\n\n        session = aiohttp.ClientSession(loop=loop, trace_configs=[trace_config])\n\n        try:\n            await session.get(\"http://example.com\")\n        except Exception:\n            pass\n\n        on_request_exception.assert_called_once_with(\n            session,\n            mock.ANY,\n            aiohttp.TraceRequestExceptionParams(\n                hdrs.METH_GET, URL(\"http://example.com\"), CIMultiDict(), error\n            ),\n        )\n        assert not on_request_end.called\n\n    await session.close()\n\n\nasync def test_request_tracing_interpose_headers(loop, aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n\n    class MyClientRequest(ClientRequest):\n        headers = None\n\n        def __init__(self, *args, **kwargs):\n            super().__init__(*args, **kwargs)\n            MyClientRequest.headers = self.headers\n\n    async def new_headers(session, trace_config_ctx, data):\n        data.headers[\"foo\"] = \"bar\"\n\n    trace_config = aiohttp.TraceConfig()\n    trace_config.on_request_start.append(new_headers)\n\n    session = await aiohttp_client(\n        app, request_class=MyClientRequest, trace_configs=[trace_config]\n    )\n\n    await session.get(\"/\")\n    assert MyClientRequest.headers[\"foo\"] == \"bar\"\n\n\ndef test_client_session_inheritance() -> None:\n    with pytest.warns(DeprecationWarning):\n\n        class A(ClientSession):\n            pass\n\n\n@pytest.mark.skipif(not DEBUG, reason=\"The check is applied in DEBUG mode only\")\nasync def test_client_session_custom_attr(loop) -> None:\n    session = ClientSession(loop=loop)\n    with pytest.warns(DeprecationWarning):\n        session.custom = None\n    await session.close()\n\n\nasync def test_client_session_timeout_args(loop) -> None:\n    session1 = ClientSession(loop=loop)\n    assert session1._timeout == client.DEFAULT_TIMEOUT\n\n    with pytest.warns(DeprecationWarning):\n        session2 = ClientSession(loop=loop, read_timeout=20 * 60, conn_timeout=30 * 60)\n    assert session2._timeout == client.ClientTimeout(total=20 * 60, connect=30 * 60)\n\n    with pytest.raises(ValueError):\n        ClientSession(\n            loop=loop, timeout=client.ClientTimeout(total=10 * 60), read_timeout=20 * 60\n        )\n\n    with pytest.raises(ValueError):\n        ClientSession(\n            loop=loop, timeout=client.ClientTimeout(total=10 * 60), conn_timeout=30 * 60\n        )\n\n    await session1.close()\n    await session2.close()\n\n\nasync def test_client_session_timeout_default_args(loop) -> None:\n    session1 = ClientSession()\n    assert session1.timeout == client.DEFAULT_TIMEOUT\n    await session1.close()\n\n\nasync def test_client_session_timeout_zero(\n    create_mocked_conn: Callable[[], ResponseHandler]\n) -> None:\n    async def create_connection(\n        req: object, traces: object, timeout: object\n    ) -> ResponseHandler:\n        await asyncio.sleep(0.01)\n        conn = create_mocked_conn()\n        conn.connected = True  # type: ignore[misc]\n        assert conn.transport is not None\n        conn.transport.is_closing.return_value = False  # type: ignore[attr-defined]\n        msg = mock.create_autospec(RawResponseMessage, spec_set=True, code=200)\n        conn.read.return_value = (msg, mock.Mock())  # type: ignore[attr-defined]\n        return conn\n\n    timeout = client.ClientTimeout(total=10, connect=0, sock_connect=0, sock_read=0)\n    async with ClientSession(timeout=timeout) as session:\n        with mock.patch.object(\n            session._connector, \"_create_connection\", create_connection\n        ):\n            try:\n                resp = await session.get(\"http://example.com\")\n            except asyncio.TimeoutError:  # pragma: no cover\n                pytest.fail(\"0 should disable timeout.\")\n            resp.close()\n\n\nasync def test_client_session_timeout_bad_argument() -> None:\n    with pytest.raises(ValueError):\n        ClientSession(timeout=\"test_bad_argumnet\")\n    with pytest.raises(ValueError):\n        ClientSession(timeout=100)\n\n\nasync def test_requote_redirect_url_default() -> None:\n    session = ClientSession()\n    assert session.requote_redirect_url\n    await session.close()\n\n\nasync def test_requote_redirect_url_default_disable() -> None:\n    session = ClientSession(requote_redirect_url=False)\n    assert not session.requote_redirect_url\n    await session.close()\n\n\nasync def test_requote_redirect_setter() -> None:\n    session = ClientSession()\n    assert session.requote_redirect_url\n    with pytest.warns(DeprecationWarning):\n        session.requote_redirect_url = False\n    assert not session.requote_redirect_url\n    await session.close()\n\n\n@pytest.mark.parametrize(\n    (\"base_url\", \"url\", \"expected_url\"),\n    [\n        pytest.param(\n            None,\n            \"http://example.com/test\",\n            URL(\"http://example.com/test\"),\n            id=\"base_url=None url='http://example.com/test'\",\n        ),\n        pytest.param(\n            None,\n            URL(\"http://example.com/test\"),\n            URL(\"http://example.com/test\"),\n            id=\"base_url=None url=URL('http://example.com/test')\",\n        ),\n        pytest.param(\n            \"http://example.com\",\n            \"/test\",\n            URL(\"http://example.com/test\"),\n            id=\"base_url='http://example.com' url='/test'\",\n        ),\n        pytest.param(\n            URL(\"http://example.com\"),\n            \"/test\",\n            URL(\"http://example.com/test\"),\n            id=\"base_url=URL('http://example.com') url='/test'\",\n        ),\n    ],\n)\nasync def test_build_url_returns_expected_url(\n    create_session, base_url, url, expected_url\n) -> None:\n    session = await create_session(base_url)\n    assert session._build_url(url) == expected_url\n\n\nasync def test_instantiation_with_invalid_timeout_value(loop):\n    loop.set_debug(False)\n    logs = []\n    loop.set_exception_handler(lambda loop, ctx: logs.append(ctx))\n    with pytest.raises(ValueError, match=\"timeout parameter cannot be .*\"):\n        ClientSession(timeout=1)\n    # should not have \"Unclosed client session\" warning\n    assert not logs\n\n\n@pytest.mark.parametrize(\n    (\"outer_name\", \"inner_name\"),\n    [\n        (\"skip_auto_headers\", \"_skip_auto_headers\"),\n        (\"auth\", \"_default_auth\"),\n        (\"json_serialize\", \"_json_serialize\"),\n        (\"connector_owner\", \"_connector_owner\"),\n        (\"raise_for_status\", \"_raise_for_status\"),\n        (\"trust_env\", \"_trust_env\"),\n        (\"trace_configs\", \"_trace_configs\"),\n    ],\n)\nasync def test_properties(\n    session: ClientSession, outer_name: str, inner_name: str\n) -> None:\n    value = uuid4()\n    setattr(session, inner_name, value)\n    assert value == getattr(session, outer_name)\n",
            "header": {
                "file": {
                    "path": "tests/test_client_session.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "86f3a1b6",
                "new_commit_hash": "89a06466",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/tests/test_client_session.py"
            },
            "plus_file": {
                "path": "b/tests/test_client_session.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 659,
                            "length": 8
                        },
                        "new_range": {
                            "start": 659,
                            "length": 57
                        },
                        "section": "def test_proxy_str(session, params) -> None:"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "    ]",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "async def test_request_tracing(loop, aiohttp_client) -> None:",
                                "type": "deleted"
                            },
                            {
                                "content": "    async def handler(request):",
                                "type": "deleted"
                            },
                            {
                                "content": "async def test_default_proxy(loop: asyncio.AbstractEventLoop) -> None:",
                                "type": "added"
                            },
                            {
                                "content": "    proxy_url = URL(\"http://proxy.example.com\")",
                                "type": "added"
                            },
                            {
                                "content": "    proxy_auth = mock.Mock()",
                                "type": "added"
                            },
                            {
                                "content": "    proxy_url2 = URL(\"http://proxy.example2.com\")",
                                "type": "added"
                            },
                            {
                                "content": "    proxy_auth2 = mock.Mock()",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "    class OnCall(Exception):",
                                "type": "added"
                            },
                            {
                                "content": "        pass",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "    request_class_mock = mock.Mock(side_effect=OnCall())",
                                "type": "added"
                            },
                            {
                                "content": "    session = ClientSession(",
                                "type": "added"
                            },
                            {
                                "content": "        proxy=proxy_url, proxy_auth=proxy_auth, request_class=request_class_mock",
                                "type": "added"
                            },
                            {
                                "content": "    )",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "    assert session._default_proxy == proxy_url, \"`ClientSession._default_proxy` not set\"",
                                "type": "added"
                            },
                            {
                                "content": "    assert (",
                                "type": "added"
                            },
                            {
                                "content": "        session._default_proxy_auth == proxy_auth",
                                "type": "added"
                            },
                            {
                                "content": "    ), \"`ClientSession._default_proxy_auth` not set\"",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "    with pytest.raises(OnCall):",
                                "type": "added"
                            },
                            {
                                "content": "        await session.get(",
                                "type": "added"
                            },
                            {
                                "content": "            \"http://example.com\",",
                                "type": "added"
                            },
                            {
                                "content": "        )",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "    assert request_class_mock.called, \"request class not called\"",
                                "type": "added"
                            },
                            {
                                "content": "    assert (",
                                "type": "added"
                            },
                            {
                                "content": "        request_class_mock.call_args[1].get(\"proxy\") == proxy_url",
                                "type": "added"
                            },
                            {
                                "content": "    ), \"`ClientSession._request` uses default proxy not one used in ClientSession.get\"",
                                "type": "added"
                            },
                            {
                                "content": "    assert (",
                                "type": "added"
                            },
                            {
                                "content": "        request_class_mock.call_args[1].get(\"proxy_auth\") == proxy_auth",
                                "type": "added"
                            },
                            {
                                "content": "    ), \"`ClientSession._request` uses default proxy_auth not one used in ClientSession.get\"",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "    request_class_mock.reset_mock()",
                                "type": "added"
                            },
                            {
                                "content": "    with pytest.raises(OnCall):",
                                "type": "added"
                            },
                            {
                                "content": "        await session.get(",
                                "type": "added"
                            },
                            {
                                "content": "            \"http://example.com\", proxy=proxy_url2, proxy_auth=proxy_auth2",
                                "type": "added"
                            },
                            {
                                "content": "        )",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "    assert request_class_mock.called, \"request class not called\"",
                                "type": "added"
                            },
                            {
                                "content": "    assert (",
                                "type": "added"
                            },
                            {
                                "content": "        request_class_mock.call_args[1].get(\"proxy\") == proxy_url2",
                                "type": "added"
                            },
                            {
                                "content": "    ), \"`ClientSession._request` uses default proxy not one used in ClientSession.get\"",
                                "type": "added"
                            },
                            {
                                "content": "    assert (",
                                "type": "added"
                            },
                            {
                                "content": "        request_class_mock.call_args[1].get(\"proxy_auth\") == proxy_auth2",
                                "type": "added"
                            },
                            {
                                "content": "    ), \"`ClientSession._request` uses default proxy_auth not one used in ClientSession.get\"",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "    await session.close()",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "async def test_request_tracing(loop: asyncio.AbstractEventLoop, aiohttp_client) -> None:",
                                "type": "added"
                            },
                            {
                                "content": "    async def handler(request: web.Request) -> web.Response:",
                                "type": "added"
                            },
                            {
                                "content": "        return web.json_response({\"ok\": True})",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    app = web.Application()",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "tests/test_client_session.py",
                            "type": "function",
                            "name": "test_request_tracing",
                            "content": "async def test_request_tracing(loop, aiohttp_client) -> None:\n    async def handler(request):\n        return web.json_response({\"ok\": True})\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n\n    trace_config_ctx = mock.Mock()\n    trace_request_ctx = {}\n    body = \"This is request body\"\n    gathered_req_headers = CIMultiDict()\n    on_request_start = mock.Mock(side_effect=make_mocked_coro(mock.Mock()))\n    on_request_redirect = mock.Mock(side_effect=make_mocked_coro(mock.Mock()))\n    on_request_end = mock.Mock(side_effect=make_mocked_coro(mock.Mock()))\n\n    with io.BytesIO() as gathered_req_body, io.BytesIO() as gathered_res_body:\n\n        async def on_request_chunk_sent(session, context, params):\n            gathered_req_body.write(params.chunk)\n\n        async def on_response_chunk_received(session, context, params):\n            gathered_res_body.write(params.chunk)\n\n        async def on_request_headers_sent(session, context, params):\n            gathered_req_headers.extend(**params.headers)\n\n        trace_config = aiohttp.TraceConfig(\n            trace_config_ctx_factory=mock.Mock(return_value=trace_config_ctx)\n        )\n        trace_config.on_request_start.append(on_request_start)\n        trace_config.on_request_end.append(on_request_end)\n        trace_config.on_request_chunk_sent.append(on_request_chunk_sent)\n        trace_config.on_response_chunk_received.append(on_response_chunk_received)\n        trace_config.on_request_redirect.append(on_request_redirect)\n        trace_config.on_request_headers_sent.append(on_request_headers_sent)\n\n        headers = CIMultiDict({\"Custom-Header\": \"Custom value\"})\n        session = await aiohttp_client(\n            app, trace_configs=[trace_config], headers=headers\n        )\n\n        async with session.post(\n            \"/\", data=body, trace_request_ctx=trace_request_ctx\n        ) as resp:\n\n            await resp.json()\n\n            on_request_start.assert_called_once_with(\n                session.session,\n                trace_config_ctx,\n                aiohttp.TraceRequestStartParams(\n                    hdrs.METH_POST, session.make_url(\"/\"), headers\n                ),\n            )\n\n            on_request_end.assert_called_once_with(\n                session.session,\n                trace_config_ctx,\n                aiohttp.TraceRequestEndParams(\n                    hdrs.METH_POST, session.make_url(\"/\"), headers, resp\n                ),\n            )\n            assert not on_request_redirect.called\n            assert gathered_req_body.getvalue() == body.encode(\"utf8\")\n            assert gathered_res_body.getvalue() == json.dumps({\"ok\": True}).encode(\n                \"utf8\"\n            )\n            assert gathered_req_headers[\"Custom-Header\"] == \"Custom value\"",
                            "ast_type_str": "AsyncFunctionDef",
                            "start_lineno": 662,
                            "end_lineno": 729,
                            "parent": null
                        }
                    ],
                    "added_entities": [
                        {
                            "file_name": "tests/test_client_session.py",
                            "type": "function",
                            "name": "test_default_proxy",
                            "content": "async def test_default_proxy(loop: asyncio.AbstractEventLoop) -> None:\n    proxy_url = URL(\"http://proxy.example.com\")\n    proxy_auth = mock.Mock()\n    proxy_url2 = URL(\"http://proxy.example2.com\")\n    proxy_auth2 = mock.Mock()\n\n    class OnCall(Exception):\n        pass\n\n    request_class_mock = mock.Mock(side_effect=OnCall())\n    session = ClientSession(\n        proxy=proxy_url, proxy_auth=proxy_auth, request_class=request_class_mock\n    )\n\n    assert session._default_proxy == proxy_url, \"`ClientSession._default_proxy` not set\"\n    assert (\n        session._default_proxy_auth == proxy_auth\n    ), \"`ClientSession._default_proxy_auth` not set\"\n\n    with pytest.raises(OnCall):\n        await session.get(\n            \"http://example.com\",\n        )\n\n    assert request_class_mock.called, \"request class not called\"\n    assert (\n        request_class_mock.call_args[1].get(\"proxy\") == proxy_url\n    ), \"`ClientSession._request` uses default proxy not one used in ClientSession.get\"\n    assert (\n        request_class_mock.call_args[1].get(\"proxy_auth\") == proxy_auth\n    ), \"`ClientSession._request` uses default proxy_auth not one used in ClientSession.get\"\n\n    request_class_mock.reset_mock()\n    with pytest.raises(OnCall):\n        await session.get(\n            \"http://example.com\", proxy=proxy_url2, proxy_auth=proxy_auth2\n        )\n\n    assert request_class_mock.called, \"request class not called\"\n    assert (\n        request_class_mock.call_args[1].get(\"proxy\") == proxy_url2\n    ), \"`ClientSession._request` uses default proxy not one used in ClientSession.get\"\n    assert (\n        request_class_mock.call_args[1].get(\"proxy_auth\") == proxy_auth2\n    ), \"`ClientSession._request` uses default proxy_auth not one used in ClientSession.get\"\n\n    await session.close()",
                            "ast_type_str": "AsyncFunctionDef",
                            "start_lineno": 662,
                            "end_lineno": 708,
                            "parent": null
                        }
                    ],
                    "deleted_entities": []
                }
            ]
        }
    ],
    "old_commit_hash": "e238777c2a1e99e5de6e57972a31488ee8f03e37^",
    "new_commit_hash": "e238777c2a1e99e5de6e57972a31488ee8f03e37",
    "commit_message": "[PR #9207/970c5d9 backport][3.11] add proxy and proxy_auth variables to ClientSession.__init__ (#9331)\n\nCo-authored-by: J. Nick Koston <nick@koston.org>\r\nCo-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>\r\nFixes #123'). -->",
    "commit_date": "2024-10-01T21:19:00Z",
    "metadata": {}
}
{
    "repo_name": "aiohttp",
    "new_commit_hash": "e238777c2a1e99e5de6e57972a31488ee8f03e37",
    "test_file_codes": [
        "import asyncio\nimport contextlib\nimport gc\nimport io\nimport json\nfrom http.cookies import SimpleCookie\nfrom typing import Any, Awaitable, Callable, List\nfrom unittest import mock\nfrom uuid import uuid4\n\nimport pytest\nfrom multidict import CIMultiDict, MultiDict\nfrom re_assert import Matches\nfrom yarl import URL\n\nimport aiohttp\nfrom aiohttp import client, hdrs, web\nfrom aiohttp.client import ClientSession\nfrom aiohttp.client_proto import ResponseHandler\nfrom aiohttp.client_reqrep import ClientRequest\nfrom aiohttp.connector import BaseConnector, Connection, TCPConnector, UnixConnector\nfrom aiohttp.helpers import DEBUG\nfrom aiohttp.http import RawResponseMessage\nfrom aiohttp.test_utils import make_mocked_coro\nfrom aiohttp.tracing import Trace\n\n\n@pytest.fixture\ndef connector(loop):\n    async def make_conn():\n        return BaseConnector(loop=loop)\n\n    conn = loop.run_until_complete(make_conn())\n    proto = mock.Mock()\n    conn._conns[\"a\"] = [(proto, 123)]\n    yield conn\n    loop.run_until_complete(conn.close())\n\n\n@pytest.fixture\ndef create_session(loop):\n    session = None\n\n    async def maker(*args, **kwargs):\n        nonlocal session\n        session = ClientSession(*args, loop=loop, **kwargs)\n        return session\n\n    yield maker\n    if session is not None:\n        loop.run_until_complete(session.close())\n\n\n@pytest.fixture\ndef session(create_session, loop):\n    return loop.run_until_complete(create_session())\n\n\n@pytest.fixture\ndef params():\n    return dict(\n        headers={\"Authorization\": \"Basic ...\"},\n        max_redirects=2,\n        encoding=\"latin1\",\n        version=aiohttp.HttpVersion10,\n        compress=\"deflate\",\n        chunked=True,\n        expect100=True,\n        read_until_eof=False,\n    )\n\n\nasync def test_close_coro(create_session) -> None:\n    session = await create_session()\n    await session.close()\n\n\nasync def test_init_headers_simple_dict(create_session) -> None:\n    session = await create_session(headers={\"h1\": \"header1\", \"h2\": \"header2\"})\n    assert sorted(session.headers.items()) == ([(\"h1\", \"header1\"), (\"h2\", \"header2\")])\n\n\nasync def test_init_headers_list_of_tuples(create_session) -> None:\n    session = await create_session(\n        headers=[(\"h1\", \"header1\"), (\"h2\", \"header2\"), (\"h3\", \"header3\")]\n    )\n    assert session.headers == CIMultiDict(\n        [(\"h1\", \"header1\"), (\"h2\", \"header2\"), (\"h3\", \"header3\")]\n    )\n\n\nasync def test_init_headers_MultiDict(create_session) -> None:\n    session = await create_session(\n        headers=MultiDict([(\"h1\", \"header1\"), (\"h2\", \"header2\"), (\"h3\", \"header3\")])\n    )\n    assert session.headers == CIMultiDict(\n        [(\"H1\", \"header1\"), (\"H2\", \"header2\"), (\"H3\", \"header3\")]\n    )\n\n\nasync def test_init_headers_list_of_tuples_with_duplicates(create_session) -> None:\n    session = await create_session(\n        headers=[(\"h1\", \"header11\"), (\"h2\", \"header21\"), (\"h1\", \"header12\")]\n    )\n    assert session.headers == CIMultiDict(\n        [(\"H1\", \"header11\"), (\"H2\", \"header21\"), (\"H1\", \"header12\")]\n    )\n\n\nasync def test_init_cookies_with_simple_dict(create_session) -> None:\n    session = await create_session(cookies={\"c1\": \"cookie1\", \"c2\": \"cookie2\"})\n    cookies = session.cookie_jar.filter_cookies()\n    assert set(cookies) == {\"c1\", \"c2\"}\n    assert cookies[\"c1\"].value == \"cookie1\"\n    assert cookies[\"c2\"].value == \"cookie2\"\n\n\nasync def test_init_cookies_with_list_of_tuples(create_session) -> None:\n    session = await create_session(cookies=[(\"c1\", \"cookie1\"), (\"c2\", \"cookie2\")])\n\n    cookies = session.cookie_jar.filter_cookies()\n    assert set(cookies) == {\"c1\", \"c2\"}\n    assert cookies[\"c1\"].value == \"cookie1\"\n    assert cookies[\"c2\"].value == \"cookie2\"\n\n\nasync def test_merge_headers(create_session) -> None:\n    # Check incoming simple dict\n    session = await create_session(headers={\"h1\": \"header1\", \"h2\": \"header2\"})\n    headers = session._prepare_headers({\"h1\": \"h1\"})\n\n    assert isinstance(headers, CIMultiDict)\n    assert headers == {\"h1\": \"h1\", \"h2\": \"header2\"}\n\n\nasync def test_merge_headers_with_multi_dict(create_session) -> None:\n    session = await create_session(headers={\"h1\": \"header1\", \"h2\": \"header2\"})\n    headers = session._prepare_headers(MultiDict([(\"h1\", \"h1\")]))\n    assert isinstance(headers, CIMultiDict)\n    assert headers == {\"h1\": \"h1\", \"h2\": \"header2\"}\n\n\nasync def test_merge_headers_with_list_of_tuples(create_session) -> None:\n    session = await create_session(headers={\"h1\": \"header1\", \"h2\": \"header2\"})\n    headers = session._prepare_headers([(\"h1\", \"h1\")])\n    assert isinstance(headers, CIMultiDict)\n    assert headers == {\"h1\": \"h1\", \"h2\": \"header2\"}\n\n\nasync def test_merge_headers_with_list_of_tuples_duplicated_names(\n    create_session,\n) -> None:\n    session = await create_session(headers={\"h1\": \"header1\", \"h2\": \"header2\"})\n\n    headers = session._prepare_headers([(\"h1\", \"v1\"), (\"h1\", \"v2\")])\n\n    assert isinstance(headers, CIMultiDict)\n    assert list(sorted(headers.items())) == [\n        (\"h1\", \"v1\"),\n        (\"h1\", \"v2\"),\n        (\"h2\", \"header2\"),\n    ]\n\n\ndef test_http_GET(session, params) -> None:\n    with mock.patch(\n        \"aiohttp.client.ClientSession._request\", new_callable=mock.MagicMock\n    ) as patched:\n        session.get(\"http://test.example.com\", params={\"x\": 1}, **params)\n    assert patched.called, \"`ClientSession._request` not called\"\n    assert list(patched.call_args) == [\n        (\n            \"GET\",\n            \"http://test.example.com\",\n        ),\n        dict(params={\"x\": 1}, allow_redirects=True, **params),\n    ]\n\n\ndef test_http_OPTIONS(session, params) -> None:\n    with mock.patch(\n        \"aiohttp.client.ClientSession._request\", new_callable=mock.MagicMock\n    ) as patched:\n        session.options(\"http://opt.example.com\", params={\"x\": 2}, **params)\n    assert patched.called, \"`ClientSession._request` not called\"\n    assert list(patched.call_args) == [\n        (\n            \"OPTIONS\",\n            \"http://opt.example.com\",\n        ),\n        dict(params={\"x\": 2}, allow_redirects=True, **params),\n    ]\n\n\ndef test_http_HEAD(session, params) -> None:\n    with mock.patch(\n        \"aiohttp.client.ClientSession._request\", new_callable=mock.MagicMock\n    ) as patched:\n        session.head(\"http://head.example.com\", params={\"x\": 2}, **params)\n    assert patched.called, \"`ClientSession._request` not called\"\n    assert list(patched.call_args) == [\n        (\n            \"HEAD\",\n            \"http://head.example.com\",\n        ),\n        dict(params={\"x\": 2}, allow_redirects=False, **params),\n    ]\n\n\ndef test_http_POST(session, params) -> None:\n    with mock.patch(\n        \"aiohttp.client.ClientSession._request\", new_callable=mock.MagicMock\n    ) as patched:\n        session.post(\n            \"http://post.example.com\", params={\"x\": 2}, data=\"Some_data\", **params\n        )\n    assert patched.called, \"`ClientSession._request` not called\"\n    assert list(patched.call_args) == [\n        (\n            \"POST\",\n            \"http://post.example.com\",\n        ),\n        dict(params={\"x\": 2}, data=\"Some_data\", **params),\n    ]\n\n\ndef test_http_PUT(session, params) -> None:\n    with mock.patch(\n        \"aiohttp.client.ClientSession._request\", new_callable=mock.MagicMock\n    ) as patched:\n        session.put(\n            \"http://put.example.com\", params={\"x\": 2}, data=\"Some_data\", **params\n        )\n    assert patched.called, \"`ClientSession._request` not called\"\n    assert list(patched.call_args) == [\n        (\n            \"PUT\",\n            \"http://put.example.com\",\n        ),\n        dict(params={\"x\": 2}, data=\"Some_data\", **params),\n    ]\n\n\ndef test_http_PATCH(session, params) -> None:\n    with mock.patch(\n        \"aiohttp.client.ClientSession._request\", new_callable=mock.MagicMock\n    ) as patched:\n        session.patch(\n            \"http://patch.example.com\", params={\"x\": 2}, data=\"Some_data\", **params\n        )\n    assert patched.called, \"`ClientSession._request` not called\"\n    assert list(patched.call_args) == [\n        (\n            \"PATCH\",\n            \"http://patch.example.com\",\n        ),\n        dict(params={\"x\": 2}, data=\"Some_data\", **params),\n    ]\n\n\ndef test_http_DELETE(session, params) -> None:\n    with mock.patch(\n        \"aiohttp.client.ClientSession._request\", new_callable=mock.MagicMock\n    ) as patched:\n        session.delete(\"http://delete.example.com\", params={\"x\": 2}, **params)\n    assert patched.called, \"`ClientSession._request` not called\"\n    assert list(patched.call_args) == [\n        (\n            \"DELETE\",\n            \"http://delete.example.com\",\n        ),\n        dict(params={\"x\": 2}, **params),\n    ]\n\n\nasync def test_close(create_session, connector) -> None:\n    session = await create_session(connector=connector)\n\n    await session.close()\n    assert session.connector is None\n    assert connector.closed\n\n\nasync def test_closed(session) -> None:\n    assert not session.closed\n    await session.close()\n    assert session.closed\n\n\nasync def test_connector(create_session, loop, mocker) -> None:\n    connector = TCPConnector(loop=loop)\n    mocker.spy(connector, \"close\")\n    session = await create_session(connector=connector)\n    assert session.connector is connector\n\n    await session.close()\n    assert connector.close.called\n    await connector.close()\n\n\nasync def test_create_connector(create_session, loop, mocker) -> None:\n    session = await create_session()\n    connector = session.connector\n    mocker.spy(session.connector, \"close\")\n\n    await session.close()\n    assert connector.close.called\n\n\ndef test_connector_loop(loop) -> None:\n    with contextlib.ExitStack() as stack:\n        another_loop = asyncio.new_event_loop()\n        stack.enter_context(contextlib.closing(another_loop))\n\n        async def make_connector():\n            return TCPConnector()\n\n        connector = another_loop.run_until_complete(make_connector())\n\n        with pytest.raises(RuntimeError) as ctx:\n\n            async def make_sess():\n                return ClientSession(connector=connector, loop=loop)\n\n            loop.run_until_complete(make_sess())\n        assert (\n            Matches(\"Session and connector has to use same event loop\")\n            == str(ctx.value).strip()\n        )\n        another_loop.run_until_complete(connector.close())\n\n\ndef test_detach(loop, session) -> None:\n    conn = session.connector\n    try:\n        assert not conn.closed\n        session.detach()\n        assert session.connector is None\n        assert session.closed\n        assert not conn.closed\n    finally:\n        loop.run_until_complete(conn.close())\n\n\nasync def test_request_closed_session(session) -> None:\n    await session.close()\n    with pytest.raises(RuntimeError):\n        await session.request(\"get\", \"/\")\n\n\ndef test_close_flag_for_closed_connector(loop, session) -> None:\n    conn = session.connector\n    assert not session.closed\n    loop.run_until_complete(conn.close())\n    assert session.closed\n\n\nasync def test_double_close(connector, create_session) -> None:\n    session = await create_session(connector=connector)\n\n    await session.close()\n    assert session.connector is None\n    await session.close()\n    assert session.closed\n    assert connector.closed\n\n\nasync def test_del(connector, loop) -> None:\n    loop.set_debug(False)\n    # N.B. don't use session fixture, it stores extra reference internally\n    session = ClientSession(connector=connector, loop=loop)\n    logs = []\n    loop.set_exception_handler(lambda loop, ctx: logs.append(ctx))\n\n    with pytest.warns(ResourceWarning):\n        del session\n        gc.collect()\n\n    assert len(logs) == 1\n    expected = {\"client_session\": mock.ANY, \"message\": \"Unclosed client session\"}\n    assert logs[0] == expected\n\n\nasync def test_del_debug(connector, loop) -> None:\n    loop.set_debug(True)\n    # N.B. don't use session fixture, it stores extra reference internally\n    session = ClientSession(connector=connector, loop=loop)\n    logs = []\n    loop.set_exception_handler(lambda loop, ctx: logs.append(ctx))\n\n    with pytest.warns(ResourceWarning):\n        del session\n        gc.collect()\n\n    assert len(logs) == 1\n    expected = {\n        \"client_session\": mock.ANY,\n        \"message\": \"Unclosed client session\",\n        \"source_traceback\": mock.ANY,\n    }\n    assert logs[0] == expected\n\n\nasync def test_session_context_manager(connector, loop) -> None:\n    with pytest.raises(TypeError):\n        with ClientSession(loop=loop, connector=connector) as session:\n            pass\n\n        assert session.closed\n\n\nasync def test_borrow_connector_loop(connector, create_session, loop) -> None:\n    session = ClientSession(connector=connector, loop=None)\n    try:\n        assert session._loop, loop\n    finally:\n        await session.close()\n\n\nasync def test_reraise_os_error(create_session) -> None:\n    err = OSError(1, \"permission error\")\n    req = mock.Mock()\n    req_factory = mock.Mock(return_value=req)\n    req.send = mock.Mock(side_effect=err)\n    session = await create_session(request_class=req_factory)\n\n    async def create_connection(req, traces, timeout):\n        # return self.transport, self.protocol\n        return mock.Mock()\n\n    session._connector._create_connection = create_connection\n    session._connector._release = mock.Mock()\n\n    with pytest.raises(aiohttp.ClientOSError) as ctx:\n        await session.request(\"get\", \"http://example.com\")\n    e = ctx.value\n    assert e.errno == err.errno\n    assert e.strerror == err.strerror\n\n\nasync def test_close_conn_on_error(create_session) -> None:\n    class UnexpectedException(BaseException):\n        pass\n\n    err = UnexpectedException(\"permission error\")\n    req = mock.Mock()\n    req_factory = mock.Mock(return_value=req)\n    req.send = mock.Mock(side_effect=err)\n    session = await create_session(request_class=req_factory)\n\n    connections = []\n    original_connect = session._connector.connect\n\n    async def connect(req, traces, timeout):\n        conn = await original_connect(req, traces, timeout)\n        connections.append(conn)\n        return conn\n\n    async def create_connection(req, traces, timeout):\n        # return self.transport, self.protocol\n        conn = mock.Mock()\n        return conn\n\n    session._connector.connect = connect\n    session._connector._create_connection = create_connection\n    session._connector._release = mock.Mock()\n\n    with pytest.raises(UnexpectedException):\n        async with session.request(\"get\", \"http://example.com\") as resp:\n            await resp.text()\n\n    # normally called during garbage collection.  triggers an exception\n    # if the connection wasn't already closed\n    for c in connections:\n        c.__del__()\n\n\n@pytest.mark.parametrize(\"protocol\", [\"http\", \"https\", \"ws\", \"wss\"])\nasync def test_ws_connect_allowed_protocols(\n    create_session: Any,\n    create_mocked_conn: Any,\n    protocol: str,\n    ws_key: Any,\n    key_data: Any,\n) -> None:\n    resp = mock.create_autospec(aiohttp.ClientResponse)\n    resp.status = 101\n    resp.headers = {\n        hdrs.UPGRADE: \"websocket\",\n        hdrs.CONNECTION: \"upgrade\",\n        hdrs.SEC_WEBSOCKET_ACCEPT: ws_key,\n    }\n    resp.url = URL(f\"{protocol}://example\")\n    resp.cookies = SimpleCookie()\n    resp.start = mock.AsyncMock()\n\n    req = mock.create_autospec(aiohttp.ClientRequest, spec_set=True)\n    req_factory = mock.Mock(return_value=req)\n    req.send = mock.AsyncMock(return_value=resp)\n    # BaseConnector allows all high level protocols by default\n    connector = BaseConnector()\n\n    session = await create_session(connector=connector, request_class=req_factory)\n\n    connections = []\n    original_connect = session._connector.connect\n\n    async def connect(req, traces, timeout):\n        conn = await original_connect(req, traces, timeout)\n        connections.append(conn)\n        return conn\n\n    async def create_connection(req, traces, timeout):\n        return create_mocked_conn()\n\n    connector = session._connector\n    with mock.patch.object(connector, \"connect\", connect), mock.patch.object(\n        connector, \"_create_connection\", create_connection\n    ), mock.patch.object(connector, \"_release\"), mock.patch(\n        \"aiohttp.client.os\"\n    ) as m_os:\n        m_os.urandom.return_value = key_data\n        await session.ws_connect(f\"{protocol}://example\")\n\n    # normally called during garbage collection.  triggers an exception\n    # if the connection wasn't already closed\n    for c in connections:\n        c.close()\n        c.__del__()\n\n    await session.close()\n\n\n@pytest.mark.parametrize(\"protocol\", [\"http\", \"https\", \"ws\", \"wss\", \"unix\"])\nasync def test_ws_connect_unix_socket_allowed_protocols(\n    create_session: Callable[..., Awaitable[ClientSession]],\n    create_mocked_conn: Callable[[], ResponseHandler],\n    protocol: str,\n    ws_key: bytes,\n    key_data: bytes,\n) -> None:\n    resp = mock.create_autospec(aiohttp.ClientResponse)\n    resp.status = 101\n    resp.headers = {\n        hdrs.UPGRADE: \"websocket\",\n        hdrs.CONNECTION: \"upgrade\",\n        hdrs.SEC_WEBSOCKET_ACCEPT: ws_key,\n    }\n    resp.url = URL(f\"{protocol}://example\")\n    resp.cookies = SimpleCookie()\n    resp.start = mock.AsyncMock()\n\n    req = mock.create_autospec(aiohttp.ClientRequest, spec_set=True)\n    req_factory = mock.Mock(return_value=req)\n    req.send = mock.AsyncMock(return_value=resp)\n    # UnixConnector allows all high level protocols by default and unix sockets\n    session = await create_session(\n        connector=UnixConnector(path=\"\"), request_class=req_factory\n    )\n\n    connections = []\n    assert session._connector is not None\n    original_connect = session._connector.connect\n\n    async def connect(\n        req: ClientRequest, traces: List[Trace], timeout: aiohttp.ClientTimeout\n    ) -> Connection:\n        conn = await original_connect(req, traces, timeout)\n        connections.append(conn)\n        return conn\n\n    async def create_connection(\n        req: object, traces: object, timeout: object\n    ) -> ResponseHandler:\n        return create_mocked_conn()\n\n    connector = session._connector\n    with mock.patch.object(connector, \"connect\", connect), mock.patch.object(\n        connector, \"_create_connection\", create_connection\n    ), mock.patch.object(connector, \"_release\"), mock.patch(\n        \"aiohttp.client.os\"\n    ) as m_os:\n        m_os.urandom.return_value = key_data\n        await session.ws_connect(f\"{protocol}://example\")\n\n    # normally called during garbage collection.  triggers an exception\n    # if the connection wasn't already closed\n    for c in connections:\n        c.close()\n        c.__del__()\n\n    await session.close()\n\n\nasync def test_cookie_jar_usage(loop: Any, aiohttp_client: Any) -> None:\n    req_url = None\n\n    jar = mock.Mock()\n    jar.filter_cookies.return_value = None\n\n    async def handler(request):\n        nonlocal req_url\n        req_url = \"http://%s/\" % request.host\n\n        resp = web.Response()\n        resp.set_cookie(\"response\", \"resp_value\")\n        return resp\n\n    app = web.Application()\n    app.router.add_route(\"GET\", \"/\", handler)\n    session = await aiohttp_client(\n        app, cookies={\"request\": \"req_value\"}, cookie_jar=jar\n    )\n\n    # Updating the cookie jar with initial user defined cookies\n    jar.update_cookies.assert_called_with({\"request\": \"req_value\"})\n\n    jar.update_cookies.reset_mock()\n    resp = await session.get(\"/\")\n    await resp.release()\n\n    # Filtering the cookie jar before sending the request,\n    # getting the request URL as only parameter\n    jar.filter_cookies.assert_called_with(URL(req_url))\n\n    # Updating the cookie jar with the response cookies\n    assert jar.update_cookies.called\n    resp_cookies = jar.update_cookies.call_args[0][0]\n    assert isinstance(resp_cookies, SimpleCookie)\n    assert \"response\" in resp_cookies\n    assert resp_cookies[\"response\"].value == \"resp_value\"\n\n\nasync def test_session_default_version(loop) -> None:\n    session = aiohttp.ClientSession(loop=loop)\n    assert session.version == aiohttp.HttpVersion11\n    await session.close()\n\n\nasync def test_session_loop(loop) -> None:\n    session = aiohttp.ClientSession(loop=loop)\n    with pytest.warns(DeprecationWarning):\n        assert session.loop is loop\n    await session.close()\n\n\ndef test_proxy_str(session, params) -> None:\n    with mock.patch(\n        \"aiohttp.client.ClientSession._request\", new_callable=mock.MagicMock\n    ) as patched:\n        session.get(\"http://test.example.com\", proxy=\"http://proxy.com\", **params)\n    assert patched.called, \"`ClientSession._request` not called\"\n    assert list(patched.call_args) == [\n        (\n            \"GET\",\n            \"http://test.example.com\",\n        ),\n        dict(allow_redirects=True, proxy=\"http://proxy.com\", **params),\n    ]\n\n\nasync def test_default_proxy(loop: asyncio.AbstractEventLoop) -> None:\n    proxy_url = URL(\"http://proxy.example.com\")\n    proxy_auth = mock.Mock()\n    proxy_url2 = URL(\"http://proxy.example2.com\")\n    proxy_auth2 = mock.Mock()\n\n    class OnCall(Exception):\n        pass\n\n    request_class_mock = mock.Mock(side_effect=OnCall())\n    session = ClientSession(\n        proxy=proxy_url, proxy_auth=proxy_auth, request_class=request_class_mock\n    )\n\n    assert session._default_proxy == proxy_url, \"`ClientSession._default_proxy` not set\"\n    assert (\n        session._default_proxy_auth == proxy_auth\n    ), \"`ClientSession._default_proxy_auth` not set\"\n\n    with pytest.raises(OnCall):\n        await session.get(\n            \"http://example.com\",\n        )\n\n    assert request_class_mock.called, \"request class not called\"\n    assert (\n        request_class_mock.call_args[1].get(\"proxy\") == proxy_url\n    ), \"`ClientSession._request` uses default proxy not one used in ClientSession.get\"\n    assert (\n        request_class_mock.call_args[1].get(\"proxy_auth\") == proxy_auth\n    ), \"`ClientSession._request` uses default proxy_auth not one used in ClientSession.get\"\n\n    request_class_mock.reset_mock()\n    with pytest.raises(OnCall):\n        await session.get(\n            \"http://example.com\", proxy=proxy_url2, proxy_auth=proxy_auth2\n        )\n\n    assert request_class_mock.called, \"request class not called\"\n    assert (\n        request_class_mock.call_args[1].get(\"proxy\") == proxy_url2\n    ), \"`ClientSession._request` uses default proxy not one used in ClientSession.get\"\n    assert (\n        request_class_mock.call_args[1].get(\"proxy_auth\") == proxy_auth2\n    ), \"`ClientSession._request` uses default proxy_auth not one used in ClientSession.get\"\n\n    await session.close()\n\n\nasync def test_request_tracing(loop: asyncio.AbstractEventLoop, aiohttp_client) -> None:\n    async def handler(request: web.Request) -> web.Response:\n        return web.json_response({\"ok\": True})\n\n    app = web.Application()\n    app.router.add_post(\"/\", handler)\n\n    trace_config_ctx = mock.Mock()\n    trace_request_ctx = {}\n    body = \"This is request body\"\n    gathered_req_headers = CIMultiDict()\n    on_request_start = mock.Mock(side_effect=make_mocked_coro(mock.Mock()))\n    on_request_redirect = mock.Mock(side_effect=make_mocked_coro(mock.Mock()))\n    on_request_end = mock.Mock(side_effect=make_mocked_coro(mock.Mock()))\n\n    with io.BytesIO() as gathered_req_body, io.BytesIO() as gathered_res_body:\n\n        async def on_request_chunk_sent(session, context, params):\n            gathered_req_body.write(params.chunk)\n\n        async def on_response_chunk_received(session, context, params):\n            gathered_res_body.write(params.chunk)\n\n        async def on_request_headers_sent(session, context, params):\n            gathered_req_headers.extend(**params.headers)\n\n        trace_config = aiohttp.TraceConfig(\n            trace_config_ctx_factory=mock.Mock(return_value=trace_config_ctx)\n        )\n        trace_config.on_request_start.append(on_request_start)\n        trace_config.on_request_end.append(on_request_end)\n        trace_config.on_request_chunk_sent.append(on_request_chunk_sent)\n        trace_config.on_response_chunk_received.append(on_response_chunk_received)\n        trace_config.on_request_redirect.append(on_request_redirect)\n        trace_config.on_request_headers_sent.append(on_request_headers_sent)\n\n        headers = CIMultiDict({\"Custom-Header\": \"Custom value\"})\n        session = await aiohttp_client(\n            app, trace_configs=[trace_config], headers=headers\n        )\n\n        async with session.post(\n            \"/\", data=body, trace_request_ctx=trace_request_ctx\n        ) as resp:\n\n            await resp.json()\n\n            on_request_start.assert_called_once_with(\n                session.session,\n                trace_config_ctx,\n                aiohttp.TraceRequestStartParams(\n                    hdrs.METH_POST, session.make_url(\"/\"), headers\n                ),\n            )\n\n            on_request_end.assert_called_once_with(\n                session.session,\n                trace_config_ctx,\n                aiohttp.TraceRequestEndParams(\n                    hdrs.METH_POST, session.make_url(\"/\"), headers, resp\n                ),\n            )\n            assert not on_request_redirect.called\n            assert gathered_req_body.getvalue() == body.encode(\"utf8\")\n            assert gathered_res_body.getvalue() == json.dumps({\"ok\": True}).encode(\n                \"utf8\"\n            )\n            assert gathered_req_headers[\"Custom-Header\"] == \"Custom value\"\n\n\nasync def test_request_tracing_url_params(loop: Any, aiohttp_client: Any) -> None:\n    async def root_handler(request):\n        return web.Response()\n\n    async def redirect_handler(request):\n        raise web.HTTPFound(\"/\")\n\n    app = web.Application()\n    app.router.add_get(\"/\", root_handler)\n    app.router.add_get(\"/redirect\", redirect_handler)\n\n    mocks = [mock.Mock(side_effect=make_mocked_coro(mock.Mock())) for _ in range(7)]\n    (\n        on_request_start,\n        on_request_redirect,\n        on_request_end,\n        on_request_exception,\n        on_request_chunk_sent,\n        on_response_chunk_received,\n        on_request_headers_sent,\n    ) = mocks\n\n    trace_config = aiohttp.TraceConfig(\n        trace_config_ctx_factory=mock.Mock(return_value=mock.Mock())\n    )\n    trace_config.on_request_start.append(on_request_start)\n    trace_config.on_request_redirect.append(on_request_redirect)\n    trace_config.on_request_end.append(on_request_end)\n    trace_config.on_request_exception.append(on_request_exception)\n    trace_config.on_request_chunk_sent.append(on_request_chunk_sent)\n    trace_config.on_response_chunk_received.append(on_response_chunk_received)\n    trace_config.on_request_headers_sent.append(on_request_headers_sent)\n\n    session = await aiohttp_client(app, trace_configs=[trace_config])\n\n    def reset_mocks() -> None:\n        for m in mocks:\n            m.reset_mock()\n\n    def to_trace_urls(mock_func: mock.Mock) -> List[URL]:\n        return [call_args[0][-1].url for call_args in mock_func.call_args_list]\n\n    def to_url(path: str) -> URL:\n        return session.make_url(path)\n\n    # Standard\n    for req in [\n        lambda: session.get(\"/?x=0\"),\n        lambda: session.get(\"/\", params=dict(x=0)),\n    ]:\n        reset_mocks()\n        async with req() as resp:\n            await resp.text()\n            assert to_trace_urls(on_request_start) == [to_url(\"/?x=0\")]\n            assert to_trace_urls(on_request_redirect) == []\n            assert to_trace_urls(on_request_end) == [to_url(\"/?x=0\")]\n            assert to_trace_urls(on_request_exception) == []\n            assert to_trace_urls(on_request_chunk_sent) == [to_url(\"/?x=0\")]\n            assert to_trace_urls(on_response_chunk_received) == [to_url(\"/?x=0\")]\n            assert to_trace_urls(on_request_headers_sent) == [to_url(\"/?x=0\")]\n\n    # Redirect\n    for req in [\n        lambda: session.get(\"/redirect?x=0\"),\n        lambda: session.get(\"/redirect\", params=dict(x=0)),\n    ]:\n        reset_mocks()\n        async with req() as resp:\n            await resp.text()\n            assert to_trace_urls(on_request_start) == [to_url(\"/redirect?x=0\")]\n            assert to_trace_urls(on_request_redirect) == [to_url(\"/redirect?x=0\")]\n            assert to_trace_urls(on_request_end) == [to_url(\"/\")]\n            assert to_trace_urls(on_request_exception) == []\n            assert to_trace_urls(on_request_chunk_sent) == [\n                to_url(\"/redirect?x=0\"),\n                to_url(\"/\"),\n            ]\n            assert to_trace_urls(on_response_chunk_received) == [to_url(\"/\")]\n            assert to_trace_urls(on_request_headers_sent) == [\n                to_url(\"/redirect?x=0\"),\n                to_url(\"/\"),\n            ]\n\n    # Exception\n    with mock.patch(\"aiohttp.client.TCPConnector.connect\") as connect_patched:\n        connect_patched.side_effect = Exception()\n\n        for req in [\n            lambda: session.get(\"/?x=0\"),\n            lambda: session.get(\"/\", params=dict(x=0)),\n        ]:\n            reset_mocks()\n            with contextlib.suppress(Exception):\n                await req()\n            assert to_trace_urls(on_request_start) == [to_url(\"/?x=0\")]\n            assert to_trace_urls(on_request_redirect) == []\n            assert to_trace_urls(on_request_end) == []\n            assert to_trace_urls(on_request_exception) == [to_url(\"?x=0\")]\n            assert to_trace_urls(on_request_chunk_sent) == []\n            assert to_trace_urls(on_response_chunk_received) == []\n            assert to_trace_urls(on_request_headers_sent) == []\n\n\nasync def test_request_tracing_exception() -> None:\n    loop = asyncio.get_event_loop()\n    on_request_end = mock.Mock(side_effect=make_mocked_coro(mock.Mock()))\n    on_request_exception = mock.Mock(side_effect=make_mocked_coro(mock.Mock()))\n\n    trace_config = aiohttp.TraceConfig()\n    trace_config.on_request_end.append(on_request_end)\n    trace_config.on_request_exception.append(on_request_exception)\n\n    with mock.patch(\"aiohttp.client.TCPConnector.connect\") as connect_patched:\n        error = Exception()\n        connect_patched.side_effect = error\n\n        session = aiohttp.ClientSession(loop=loop, trace_configs=[trace_config])\n\n        try:\n            await session.get(\"http://example.com\")\n        except Exception:\n            pass\n\n        on_request_exception.assert_called_once_with(\n            session,\n            mock.ANY,\n            aiohttp.TraceRequestExceptionParams(\n                hdrs.METH_GET, URL(\"http://example.com\"), CIMultiDict(), error\n            ),\n        )\n        assert not on_request_end.called\n\n    await session.close()\n\n\nasync def test_request_tracing_interpose_headers(loop, aiohttp_client) -> None:\n    async def handler(request):\n        return web.Response()\n\n    app = web.Application()\n    app.router.add_get(\"/\", handler)\n\n    class MyClientRequest(ClientRequest):\n        headers = None\n\n        def __init__(self, *args, **kwargs):\n            super().__init__(*args, **kwargs)\n            MyClientRequest.headers = self.headers\n\n    async def new_headers(session, trace_config_ctx, data):\n        data.headers[\"foo\"] = \"bar\"\n\n    trace_config = aiohttp.TraceConfig()\n    trace_config.on_request_start.append(new_headers)\n\n    session = await aiohttp_client(\n        app, request_class=MyClientRequest, trace_configs=[trace_config]\n    )\n\n    await session.get(\"/\")\n    assert MyClientRequest.headers[\"foo\"] == \"bar\"\n\n\ndef test_client_session_inheritance() -> None:\n    with pytest.warns(DeprecationWarning):\n\n        class A(ClientSession):\n            pass\n\n\n@pytest.mark.skipif(not DEBUG, reason=\"The check is applied in DEBUG mode only\")\nasync def test_client_session_custom_attr(loop) -> None:\n    session = ClientSession(loop=loop)\n    with pytest.warns(DeprecationWarning):\n        session.custom = None\n    await session.close()\n\n\nasync def test_client_session_timeout_args(loop) -> None:\n    session1 = ClientSession(loop=loop)\n    assert session1._timeout == client.DEFAULT_TIMEOUT\n\n    with pytest.warns(DeprecationWarning):\n        session2 = ClientSession(loop=loop, read_timeout=20 * 60, conn_timeout=30 * 60)\n    assert session2._timeout == client.ClientTimeout(total=20 * 60, connect=30 * 60)\n\n    with pytest.raises(ValueError):\n        ClientSession(\n            loop=loop, timeout=client.ClientTimeout(total=10 * 60), read_timeout=20 * 60\n        )\n\n    with pytest.raises(ValueError):\n        ClientSession(\n            loop=loop, timeout=client.ClientTimeout(total=10 * 60), conn_timeout=30 * 60\n        )\n\n    await session1.close()\n    await session2.close()\n\n\nasync def test_client_session_timeout_default_args(loop) -> None:\n    session1 = ClientSession()\n    assert session1.timeout == client.DEFAULT_TIMEOUT\n    await session1.close()\n\n\nasync def test_client_session_timeout_zero(\n    create_mocked_conn: Callable[[], ResponseHandler]\n) -> None:\n    async def create_connection(\n        req: object, traces: object, timeout: object\n    ) -> ResponseHandler:\n        await asyncio.sleep(0.01)\n        conn = create_mocked_conn()\n        conn.connected = True  # type: ignore[misc]\n        assert conn.transport is not None\n        conn.transport.is_closing.return_value = False  # type: ignore[attr-defined]\n        msg = mock.create_autospec(RawResponseMessage, spec_set=True, code=200)\n        conn.read.return_value = (msg, mock.Mock())  # type: ignore[attr-defined]\n        return conn\n\n    timeout = client.ClientTimeout(total=10, connect=0, sock_connect=0, sock_read=0)\n    async with ClientSession(timeout=timeout) as session:\n        with mock.patch.object(\n            session._connector, \"_create_connection\", create_connection\n        ):\n            try:\n                resp = await session.get(\"http://example.com\")\n            except asyncio.TimeoutError:  # pragma: no cover\n                pytest.fail(\"0 should disable timeout.\")\n            resp.close()\n\n\nasync def test_client_session_timeout_bad_argument() -> None:\n    with pytest.raises(ValueError):\n        ClientSession(timeout=\"test_bad_argumnet\")\n    with pytest.raises(ValueError):\n        ClientSession(timeout=100)\n\n\nasync def test_requote_redirect_url_default() -> None:\n    session = ClientSession()\n    assert session.requote_redirect_url\n    await session.close()\n\n\nasync def test_requote_redirect_url_default_disable() -> None:\n    session = ClientSession(requote_redirect_url=False)\n    assert not session.requote_redirect_url\n    await session.close()\n\n\nasync def test_requote_redirect_setter() -> None:\n    session = ClientSession()\n    assert session.requote_redirect_url\n    with pytest.warns(DeprecationWarning):\n        session.requote_redirect_url = False\n    assert not session.requote_redirect_url\n    await session.close()\n\n\n@pytest.mark.parametrize(\n    (\"base_url\", \"url\", \"expected_url\"),\n    [\n        pytest.param(\n            None,\n            \"http://example.com/test\",\n            URL(\"http://example.com/test\"),\n            id=\"base_url=None url='http://example.com/test'\",\n        ),\n        pytest.param(\n            None,\n            URL(\"http://example.com/test\"),\n            URL(\"http://example.com/test\"),\n            id=\"base_url=None url=URL('http://example.com/test')\",\n        ),\n        pytest.param(\n            \"http://example.com\",\n            \"/test\",\n            URL(\"http://example.com/test\"),\n            id=\"base_url='http://example.com' url='/test'\",\n        ),\n        pytest.param(\n            URL(\"http://example.com\"),\n            \"/test\",\n            URL(\"http://example.com/test\"),\n            id=\"base_url=URL('http://example.com') url='/test'\",\n        ),\n    ],\n)\nasync def test_build_url_returns_expected_url(\n    create_session, base_url, url, expected_url\n) -> None:\n    session = await create_session(base_url)\n    assert session._build_url(url) == expected_url\n\n\nasync def test_instantiation_with_invalid_timeout_value(loop):\n    loop.set_debug(False)\n    logs = []\n    loop.set_exception_handler(lambda loop, ctx: logs.append(ctx))\n    with pytest.raises(ValueError, match=\"timeout parameter cannot be .*\"):\n        ClientSession(timeout=1)\n    # should not have \"Unclosed client session\" warning\n    assert not logs\n\n\n@pytest.mark.parametrize(\n    (\"outer_name\", \"inner_name\"),\n    [\n        (\"skip_auto_headers\", \"_skip_auto_headers\"),\n        (\"auth\", \"_default_auth\"),\n        (\"json_serialize\", \"_json_serialize\"),\n        (\"connector_owner\", \"_connector_owner\"),\n        (\"raise_for_status\", \"_raise_for_status\"),\n        (\"trust_env\", \"_trust_env\"),\n        (\"trace_configs\", \"_trace_configs\"),\n    ],\n)\nasync def test_properties(\n    session: ClientSession, outer_name: str, inner_name: str\n) -> None:\n    value = uuid4()\n    setattr(session, inner_name, value)\n    assert value == getattr(session, outer_name)\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_e238777c2a1e99e5de6e57972a31488ee8f03e37/requirements/cython.txt\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/tools/gen.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/hdrs.py\n./tools/gen.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/_helpers.pyx\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/_http_parser.pyx\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/_http_writer.pyx\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/_websocket.pyx\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/_helpers.pyi\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/_cparser.pxd\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/_find_header.pxd\ncython -3 -o aiohttp/_helpers.c aiohttp/_helpers.pyx -I aiohttp -Werror\ncython -3 -o aiohttp/_http_parser.c aiohttp/_http_parser.pyx -I aiohttp -Werror\ncython -3 -o aiohttp/_http_writer.c aiohttp/_http_writer.pyx -I aiohttp -Werror\ncython -3 -o aiohttp/_websocket.c aiohttp/_websocket.pyx -I aiohttp -Werror\ncd vendor/llhttp; npm ci\n\n> llhttp@9.2.1 prepare\n> npm run clean && npm run build-ts\n\n\n> llhttp@9.2.1 clean\n> rm -rf lib && rm -rf test/tmp\n\n\n> llhttp@9.2.1 build-ts\n> tsc\n\n\nadded 213 packages, and audited 214 packages in 5s\n\n41 packages are looking for funding\n  run `npm fund` for details\n\n5 vulnerabilities (3 moderate, 2 high)\n\nTo address issues that do not require attention, run:\n  npm audit fix\n\nSome issues need review, and may require choosing\na different dependency.\n\nRun `npm audit` for details.\nmake -C vendor/llhttp generate\nmake[1]: Entering directory '/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/vendor/llhttp'\nnpx ts-node bin/generate.ts\nmake[1]: Leaving directory '/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/vendor/llhttp'\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/__init__.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/abc.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/base_protocol.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/client.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/client_exceptions.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/client_proto.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/client_reqrep.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/client_ws.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/compression_utils.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/connector.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/cookiejar.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/formdata.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/helpers.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/http.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/http_exceptions.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/http_parser.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/http_websocket.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/http_writer.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/locks.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/log.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/multipart.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/payload.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/payload_streamer.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/pytest_plugin.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/resolver.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/streams.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/tcp_helpers.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/test_utils.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/tracing.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/typedefs.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/web.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/web_app.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/web_exceptions.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/web_fileresponse.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/web_log.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/web_middlewares.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/web_protocol.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/web_request.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/web_response.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/web_routedef.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/web_runner.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/web_server.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/web_urldispatcher.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/aiohttp/web_ws.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/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 3ms\nPrepared 1 package in 0.30ms\nInstalled 1 package in 16ms\n + pip==24.3.1\nResolved 3 packages in 11ms\nInstalled 3 packages in 13ms\n + cython==3.0.11\n + multidict==6.1.0\n + typing-extensions==4.12.2\nResolved 95 packages in 59ms\nUninstalled 1 package in 6ms\nInstalled 93 packages in 197ms\n + aiodns==3.2.0\n + aiohappyeyeballs==2.4.3\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==24.2.0\n + babel==2.16.0\n + brotli==1.1.0\n + build==1.2.2\n + certifi==2024.8.30\n + cffi==1.17.1\n + cfgv==3.4.0\n + charset-normalizer==3.3.2\n + cherry-picker==2.2.0\n + click==8.1.7\n + coverage==7.6.1\n + cryptography==43.0.1\n + distlib==0.3.8\n + docutils==0.20.1\n + exceptiongroup==1.2.2\n + filelock==3.16.1\n + freezegun==1.5.1\n + frozenlist==1.4.1\n + gidgethub==5.3.0\n + gunicorn==23.0.0\n + identify==2.6.1\n + idna==3.4\n + imagesize==1.4.1\n + importlib-metadata==8.5.0\n + importlib-resources==6.4.5\n + incremental==24.7.2\n + iniconfig==2.0.0\n + jinja2==3.1.4\n + markdown-it-py==3.0.0\n + markupsafe==2.1.5\n + mdurl==0.1.2\n + mypy==1.11.2\n + mypy-extensions==1.0.0\n + nodeenv==1.9.1\n + packaging==24.1\n - pip==24.3.1\n + pip==24.2\n + pip-tools==7.4.1\n + platformdirs==4.3.6\n + pluggy==1.5.0\n + pre-commit==3.5.0\n + proxy-py==2.4.8\n + pycares==4.4.0\n + pycparser==2.22\n + pydantic==2.9.2\n + pydantic-core==2.23.4\n + pygments==2.18.0\n + pyjwt==2.8.0\n + pyproject-hooks==1.2.0\n + pytest==8.3.3\n + pytest-cov==5.0.0\n + pytest-mock==3.14.0\n + python-dateutil==2.9.0.post0\n + python-on-whales==0.73.0\n + pyyaml==6.0.2\n + re-assert==1.1.0\n + regex==2024.9.11\n + requests==2.32.3\n + rich==13.8.1\n + setuptools==75.1.0\n + setuptools-git==1.2\n + shellingham==1.5.4\n + six==1.16.0\n + slotscheck==0.19.0\n + snowballstemmer==2.2.0\n + sphinx==7.1.2\n + sphinxcontrib-applehelp==1.0.4\n + sphinxcontrib-devhelp==1.0.2\n + sphinxcontrib-htmlhelp==2.0.1\n + sphinxcontrib-jsmath==1.0.1\n + sphinxcontrib-qthelp==1.0.3\n + sphinxcontrib-serializinghtml==1.1.5\n + sphinxcontrib-towncrier==0.4.0a0\n + tomli==2.0.1\n + towncrier==23.11.0\n + tqdm==4.66.5\n + trustme==1.1.0\n + typer==0.12.5\n + uritemplate==4.1.1\n + urllib3==2.2.3\n + uvloop==0.21.0b1\n + virtualenv==20.26.6\n + wait-for-it==2.2.2\n + wheel==0.44.0\n + yarl==1.13.1\n + zipp==3.20.2\nResolved 10 packages in 1.68s\nPrepared 1 package in 16.92s\nInstalled 1 package in 0.54ms\n + aiohttp==3.11.0.dev0 (from file:///home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37)\nResolved 25 packages in 16ms\nInstalled 5 packages in 5ms\n + async-generator==1.10\n + brotlipy==0.7.0\n + chardet==5.2.0\n + multdict==0.0.5\n + pytest-asyncio==0.25.1\n",
    "new_commit_res_code": 0,
    "new_commit_res_stdout": "============================= test session starts ==============================\nplatform linux -- Python 3.9.21, pytest-8.3.3, pluggy-1.5.0 -- /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/.venv/bin/python\ncachedir: .pytest_cache\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37\nconfigfile: setup.cfg\nplugins: cov-5.0.0, mock-3.14.0, asyncio-0.25.1\nasyncio: mode=strict, asyncio_default_fixture_loop_scope=None\ncollecting ... collected 72 items\n\nr2e_tests/test_1.py::test_close_coro[pyloop] PASSED                      [  1%]\nr2e_tests/test_1.py::test_init_headers_simple_dict[pyloop] PASSED        [  2%]\nr2e_tests/test_1.py::test_init_headers_list_of_tuples[pyloop] PASSED     [  4%]\nr2e_tests/test_1.py::test_init_headers_MultiDict[pyloop] PASSED          [  5%]\nr2e_tests/test_1.py::test_init_headers_list_of_tuples_with_duplicates[pyloop] PASSED [  6%]\nr2e_tests/test_1.py::test_init_cookies_with_simple_dict[pyloop] PASSED   [  8%]\nr2e_tests/test_1.py::test_init_cookies_with_list_of_tuples[pyloop] PASSED [  9%]\nr2e_tests/test_1.py::test_merge_headers[pyloop] PASSED                   [ 11%]\nr2e_tests/test_1.py::test_merge_headers_with_multi_dict[pyloop] PASSED   [ 12%]\nr2e_tests/test_1.py::test_merge_headers_with_list_of_tuples[pyloop] PASSED [ 13%]\nr2e_tests/test_1.py::test_merge_headers_with_list_of_tuples_duplicated_names[pyloop] PASSED [ 15%]\nr2e_tests/test_1.py::test_http_GET[pyloop] PASSED                        [ 16%]\nr2e_tests/test_1.py::test_http_OPTIONS[pyloop] PASSED                    [ 18%]\nr2e_tests/test_1.py::test_http_HEAD[pyloop] PASSED                       [ 19%]\nr2e_tests/test_1.py::test_http_POST[pyloop] PASSED                       [ 20%]\nr2e_tests/test_1.py::test_http_PUT[pyloop] PASSED                        [ 22%]\nr2e_tests/test_1.py::test_http_PATCH[pyloop] PASSED                      [ 23%]\nr2e_tests/test_1.py::test_http_DELETE[pyloop] PASSED                     [ 25%]\nr2e_tests/test_1.py::test_close[pyloop] PASSED                           [ 26%]\nr2e_tests/test_1.py::test_closed[pyloop] PASSED                          [ 27%]\nr2e_tests/test_1.py::test_connector[pyloop] PASSED                       [ 29%]\nr2e_tests/test_1.py::test_create_connector[pyloop] PASSED                [ 30%]\nr2e_tests/test_1.py::test_connector_loop[pyloop] PASSED                  [ 31%]\nr2e_tests/test_1.py::test_detach[pyloop] PASSED                          [ 33%]\nr2e_tests/test_1.py::test_request_closed_session[pyloop] PASSED          [ 34%]\nr2e_tests/test_1.py::test_close_flag_for_closed_connector[pyloop] PASSED [ 36%]\nr2e_tests/test_1.py::test_double_close[pyloop] PASSED                    [ 37%]\nr2e_tests/test_1.py::test_del[pyloop] PASSED                             [ 38%]\nr2e_tests/test_1.py::test_del_debug[pyloop] PASSED                       [ 40%]\nr2e_tests/test_1.py::test_session_context_manager[pyloop] PASSED         [ 41%]\nr2e_tests/test_1.py::test_borrow_connector_loop[pyloop] PASSED           [ 43%]\nr2e_tests/test_1.py::test_reraise_os_error[pyloop] PASSED                [ 44%]\nr2e_tests/test_1.py::test_close_conn_on_error[pyloop] PASSED             [ 45%]\nr2e_tests/test_1.py::test_ws_connect_allowed_protocols[pyloop-http] PASSED [ 47%]\nr2e_tests/test_1.py::test_ws_connect_allowed_protocols[pyloop-https] PASSED [ 48%]\nr2e_tests/test_1.py::test_ws_connect_allowed_protocols[pyloop-ws] PASSED [ 50%]\nr2e_tests/test_1.py::test_ws_connect_allowed_protocols[pyloop-wss] PASSED [ 51%]\nr2e_tests/test_1.py::test_ws_connect_unix_socket_allowed_protocols[pyloop-http] PASSED [ 52%]\nr2e_tests/test_1.py::test_ws_connect_unix_socket_allowed_protocols[pyloop-https] PASSED [ 54%]\nr2e_tests/test_1.py::test_ws_connect_unix_socket_allowed_protocols[pyloop-ws] PASSED [ 55%]\nr2e_tests/test_1.py::test_ws_connect_unix_socket_allowed_protocols[pyloop-wss] PASSED [ 56%]\nr2e_tests/test_1.py::test_ws_connect_unix_socket_allowed_protocols[pyloop-unix] PASSED [ 58%]\nr2e_tests/test_1.py::test_cookie_jar_usage[pyloop] PASSED                [ 59%]\nr2e_tests/test_1.py::test_session_default_version[pyloop] PASSED         [ 61%]\nr2e_tests/test_1.py::test_session_loop[pyloop] PASSED                    [ 62%]\nr2e_tests/test_1.py::test_proxy_str[pyloop] PASSED                       [ 63%]\nr2e_tests/test_1.py::test_default_proxy[pyloop] PASSED                   [ 65%]\nr2e_tests/test_1.py::test_request_tracing[pyloop] PASSED                 [ 66%]\nr2e_tests/test_1.py::test_request_tracing_url_params[pyloop] PASSED      [ 68%]\nr2e_tests/test_1.py::test_request_tracing_exception PASSED               [ 69%]\nr2e_tests/test_1.py::test_request_tracing_interpose_headers[pyloop] PASSED [ 70%]\nr2e_tests/test_1.py::test_client_session_inheritance PASSED              [ 72%]\nr2e_tests/test_1.py::test_client_session_custom_attr[pyloop] SKIPPED     [ 73%]\nr2e_tests/test_1.py::test_client_session_timeout_args[pyloop] PASSED     [ 75%]\nr2e_tests/test_1.py::test_client_session_timeout_default_args[pyloop] PASSED [ 76%]\nr2e_tests/test_1.py::test_client_session_timeout_zero[pyloop] PASSED     [ 77%]\nr2e_tests/test_1.py::test_client_session_timeout_bad_argument PASSED     [ 79%]\nr2e_tests/test_1.py::test_requote_redirect_url_default PASSED            [ 80%]\nr2e_tests/test_1.py::test_requote_redirect_url_default_disable PASSED    [ 81%]\nr2e_tests/test_1.py::test_requote_redirect_setter PASSED                 [ 83%]\nr2e_tests/test_1.py::test_build_url_returns_expected_url[pyloop-base_url=None url='http://example.com/test'] PASSED [ 84%]\nr2e_tests/test_1.py::test_build_url_returns_expected_url[pyloop-base_url=None url=URL('http://example.com/test')] PASSED [ 86%]\nr2e_tests/test_1.py::test_build_url_returns_expected_url[pyloop-base_url='http://example.com' url='/test'] PASSED [ 87%]\nr2e_tests/test_1.py::test_build_url_returns_expected_url[pyloop-base_url=URL('http://example.com') url='/test'] PASSED [ 88%]\nr2e_tests/test_1.py::test_instantiation_with_invalid_timeout_value[pyloop] PASSED [ 90%]\nr2e_tests/test_1.py::test_properties[pyloop-skip_auto_headers-_skip_auto_headers] PASSED [ 91%]\nr2e_tests/test_1.py::test_properties[pyloop-auth-_default_auth] PASSED   [ 93%]\nr2e_tests/test_1.py::test_properties[pyloop-json_serialize-_json_serialize] PASSED [ 94%]\nr2e_tests/test_1.py::test_properties[pyloop-connector_owner-_connector_owner] PASSED [ 95%]\nr2e_tests/test_1.py::test_properties[pyloop-raise_for_status-_raise_for_status] PASSED [ 97%]\nr2e_tests/test_1.py::test_properties[pyloop-trust_env-_trust_env] PASSED [ 98%]\nr2e_tests/test_1.py::test_properties[pyloop-trace_configs-_trace_configs] PASSED [100%]\n\n==================================== PASSES ====================================\n_____________________ test_session_context_manager[pyloop] _____________________\n------------------------------ Captured log call -------------------------------\nERROR    asyncio:base_events.py:1753 Unclosed client session\nclient_session: <aiohttp.client.ClientSession object at 0x75027a29e190>\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                              98      2      0      0    98%\naiohttp/base_protocol.py                    68     36     22      3    39%\naiohttp/client.py                          556    116    206     51    74%\naiohttp/client_exceptions.py               154     65     20      1    52%\naiohttp/client_proto.py                    164     55     56     18    59%\naiohttp/client_reqrep.py                   706    239    302     83    59%\naiohttp/client_ws.py                       271    188     82      3    25%\naiohttp/compression_utils.py                70     36     14      0    40%\naiohttp/connector.py                       773    408    333     48    40%\naiohttp/cookiejar.py                       274    153    130     18    37%\naiohttp/formdata.py                         97     79     46      0    13%\naiohttp/hdrs.py                             90      0      0      0   100%\naiohttp/helpers.py                         497    225    176     23    48%\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                  388    255    148      0    25%\naiohttp/http_writer.py                     119     41     50     12    58%\naiohttp/locks.py                            24     16      4      0    29%\naiohttp/log.py                               7      0      0      0   100%\naiohttp/multipart.py                       623    508    266      1    13%\naiohttp/payload.py                         237     88     58     10    56%\naiohttp/payload_streamer.py                 31     11      4      0    69%\naiohttp/pytest_plugin.py                   163     61     42      6    60%\naiohttp/resolver.py                         79     55     26      2    25%\naiohttp/streams.py                         398    208    146     25    41%\naiohttp/tcp_helpers.py                      19      2      6      3    80%\naiohttp/test_utils.py                      323    115     54     16    60%\naiohttp/tracing.py                         191     12     32      0    95%\naiohttp/typedefs.py                         24      0      0      0   100%\naiohttp/web.py                             126     88     54      0    22%\naiohttp/web_app.py                         292    110     82     18    55%\naiohttp/web_exceptions.py                  157     16      8      3    87%\naiohttp/web_fileresponse.py                160    126     52      0    18%\naiohttp/web_log.py                         102     37     20      1    59%\naiohttp/web_middlewares.py                  59     41     22      0    22%\naiohttp/web_protocol.py                    367    146    158     48    50%\naiohttp/web_request.py                     445    252    140     10    36%\naiohttp/web_response.py                    485    199    226     51    50%\naiohttp/web_routedef.py                    100     44     10      0    55%\naiohttp/web_runner.py                      213     72     36     11    62%\naiohttp/web_server.py                       42      6     12      2    81%\naiohttp/web_urldispatcher.py               740    379    163     21    43%\naiohttp/web_ws.py                          386    313    134      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           2575   2575     86      0     0%\ntests/test_client_proto.py                  99     99      0      0     0%\ntests/test_client_request.py               827    827     18      0     0%\ntests/test_client_response.py              480    480      6      0     0%\ntests/test_client_session.py               589    589     29      0     0%\ntests/test_client_ws.py                    489    489      2      0     0%\ntests/test_client_ws_functional.py         805    805     32      0     0%\ntests/test_connector.py                   1701   1701     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                      86     86      6      0     0%\ntests/test_helpers.py                      491    491     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                        324    324      2      0     0%\ntests/test_proxy_functional.py             459    459     18      0     0%\ntests/test_pytest_plugin.py                 27     27      0      0     0%\ntests/test_resolver.py                     197    197     20      0     0%\ntests/test_route_def.py                    210    210      0      0     0%\ntests/test_run_app.py                      563    563     30      0     0%\ntests/test_streams.py                     1077   1077     38      0     0%\ntests/test_tcp_helpers.py                   52     52      2      0     0%\ntests/test_test_utils.py                   260    260     12      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                       94     94      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                 905    905      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                416    416      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                                    34950  29475   4438    491    16%\n\n============================= slowest 10 durations =============================\n0.09s call     r2e_tests/test_1.py::test_ws_connect_allowed_protocols[pyloop-http]\n0.08s call     r2e_tests/test_1.py::test_ws_connect_allowed_protocols[pyloop-ws]\n0.08s call     r2e_tests/test_1.py::test_ws_connect_allowed_protocols[pyloop-https]\n0.08s call     r2e_tests/test_1.py::test_ws_connect_unix_socket_allowed_protocols[pyloop-wss]\n0.08s call     r2e_tests/test_1.py::test_ws_connect_unix_socket_allowed_protocols[pyloop-unix]\n0.08s call     r2e_tests/test_1.py::test_ws_connect_allowed_protocols[pyloop-wss]\n0.08s call     r2e_tests/test_1.py::test_ws_connect_unix_socket_allowed_protocols[pyloop-ws]\n0.08s call     r2e_tests/test_1.py::test_ws_connect_unix_socket_allowed_protocols[pyloop-https]\n0.08s call     r2e_tests/test_1.py::test_ws_connect_unix_socket_allowed_protocols[pyloop-http]\n0.04s call     r2e_tests/test_1.py::test_client_session_timeout_zero[pyloop]\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::test_close_coro[pyloop]\nPASSED r2e_tests/test_1.py::test_init_headers_simple_dict[pyloop]\nPASSED r2e_tests/test_1.py::test_init_headers_list_of_tuples[pyloop]\nPASSED r2e_tests/test_1.py::test_init_headers_MultiDict[pyloop]\nPASSED r2e_tests/test_1.py::test_init_headers_list_of_tuples_with_duplicates[pyloop]\nPASSED r2e_tests/test_1.py::test_init_cookies_with_simple_dict[pyloop]\nPASSED r2e_tests/test_1.py::test_init_cookies_with_list_of_tuples[pyloop]\nPASSED r2e_tests/test_1.py::test_merge_headers[pyloop]\nPASSED r2e_tests/test_1.py::test_merge_headers_with_multi_dict[pyloop]\nPASSED r2e_tests/test_1.py::test_merge_headers_with_list_of_tuples[pyloop]\nPASSED r2e_tests/test_1.py::test_merge_headers_with_list_of_tuples_duplicated_names[pyloop]\nPASSED r2e_tests/test_1.py::test_http_GET[pyloop]\nPASSED r2e_tests/test_1.py::test_http_OPTIONS[pyloop]\nPASSED r2e_tests/test_1.py::test_http_HEAD[pyloop]\nPASSED r2e_tests/test_1.py::test_http_POST[pyloop]\nPASSED r2e_tests/test_1.py::test_http_PUT[pyloop]\nPASSED r2e_tests/test_1.py::test_http_PATCH[pyloop]\nPASSED r2e_tests/test_1.py::test_http_DELETE[pyloop]\nPASSED r2e_tests/test_1.py::test_close[pyloop]\nPASSED r2e_tests/test_1.py::test_closed[pyloop]\nPASSED r2e_tests/test_1.py::test_connector[pyloop]\nPASSED r2e_tests/test_1.py::test_create_connector[pyloop]\nPASSED r2e_tests/test_1.py::test_connector_loop[pyloop]\nPASSED r2e_tests/test_1.py::test_detach[pyloop]\nPASSED r2e_tests/test_1.py::test_request_closed_session[pyloop]\nPASSED r2e_tests/test_1.py::test_close_flag_for_closed_connector[pyloop]\nPASSED r2e_tests/test_1.py::test_double_close[pyloop]\nPASSED r2e_tests/test_1.py::test_del[pyloop]\nPASSED r2e_tests/test_1.py::test_del_debug[pyloop]\nPASSED r2e_tests/test_1.py::test_session_context_manager[pyloop]\nPASSED r2e_tests/test_1.py::test_borrow_connector_loop[pyloop]\nPASSED r2e_tests/test_1.py::test_reraise_os_error[pyloop]\nPASSED r2e_tests/test_1.py::test_close_conn_on_error[pyloop]\nPASSED r2e_tests/test_1.py::test_ws_connect_allowed_protocols[pyloop-http]\nPASSED r2e_tests/test_1.py::test_ws_connect_allowed_protocols[pyloop-https]\nPASSED r2e_tests/test_1.py::test_ws_connect_allowed_protocols[pyloop-ws]\nPASSED r2e_tests/test_1.py::test_ws_connect_allowed_protocols[pyloop-wss]\nPASSED r2e_tests/test_1.py::test_ws_connect_unix_socket_allowed_protocols[pyloop-http]\nPASSED r2e_tests/test_1.py::test_ws_connect_unix_socket_allowed_protocols[pyloop-https]\nPASSED r2e_tests/test_1.py::test_ws_connect_unix_socket_allowed_protocols[pyloop-ws]\nPASSED r2e_tests/test_1.py::test_ws_connect_unix_socket_allowed_protocols[pyloop-wss]\nPASSED r2e_tests/test_1.py::test_ws_connect_unix_socket_allowed_protocols[pyloop-unix]\nPASSED r2e_tests/test_1.py::test_cookie_jar_usage[pyloop]\nPASSED r2e_tests/test_1.py::test_session_default_version[pyloop]\nPASSED r2e_tests/test_1.py::test_session_loop[pyloop]\nPASSED r2e_tests/test_1.py::test_proxy_str[pyloop]\nPASSED r2e_tests/test_1.py::test_default_proxy[pyloop]\nPASSED r2e_tests/test_1.py::test_request_tracing[pyloop]\nPASSED r2e_tests/test_1.py::test_request_tracing_url_params[pyloop]\nPASSED r2e_tests/test_1.py::test_request_tracing_exception\nPASSED r2e_tests/test_1.py::test_request_tracing_interpose_headers[pyloop]\nPASSED r2e_tests/test_1.py::test_client_session_inheritance\nPASSED r2e_tests/test_1.py::test_client_session_timeout_args[pyloop]\nPASSED r2e_tests/test_1.py::test_client_session_timeout_default_args[pyloop]\nPASSED r2e_tests/test_1.py::test_client_session_timeout_zero[pyloop]\nPASSED r2e_tests/test_1.py::test_client_session_timeout_bad_argument\nPASSED r2e_tests/test_1.py::test_requote_redirect_url_default\nPASSED r2e_tests/test_1.py::test_requote_redirect_url_default_disable\nPASSED r2e_tests/test_1.py::test_requote_redirect_setter\nPASSED r2e_tests/test_1.py::test_build_url_returns_expected_url[pyloop-base_url=None url='http://example.com/test']\nPASSED r2e_tests/test_1.py::test_build_url_returns_expected_url[pyloop-base_url=None url=URL('http://example.com/test')]\nPASSED r2e_tests/test_1.py::test_build_url_returns_expected_url[pyloop-base_url='http://example.com' url='/test']\nPASSED r2e_tests/test_1.py::test_build_url_returns_expected_url[pyloop-base_url=URL('http://example.com') url='/test']\nPASSED r2e_tests/test_1.py::test_instantiation_with_invalid_timeout_value[pyloop]\nPASSED r2e_tests/test_1.py::test_properties[pyloop-skip_auto_headers-_skip_auto_headers]\nPASSED r2e_tests/test_1.py::test_properties[pyloop-auth-_default_auth]\nPASSED r2e_tests/test_1.py::test_properties[pyloop-json_serialize-_json_serialize]\nPASSED r2e_tests/test_1.py::test_properties[pyloop-connector_owner-_connector_owner]\nPASSED r2e_tests/test_1.py::test_properties[pyloop-raise_for_status-_raise_for_status]\nPASSED r2e_tests/test_1.py::test_properties[pyloop-trust_env-_trust_env]\nPASSED r2e_tests/test_1.py::test_properties[pyloop-trace_configs-_trace_configs]\nSKIPPED [1] r2e_tests/test_1.py:951: The check is applied in DEBUG mode only\n======================== 71 passed, 1 skipped in 6.33s =========================\n",
    "new_commit_res_stderr": "/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/.venv/lib/python3.9/site-packages/pytest_asyncio/plugin.py:207: PytestDeprecationWarning: The configuration option \"asyncio_default_fixture_loop_scope\" is unset.\nThe event loop scope for asynchronous fixtures will default to the fixture caching scope. Future versions of pytest-asyncio will default the loop scope for asynchronous fixtures to function scope. Set the default fixture loop scope explicitly in order to avoid unexpected behavior in the future. Valid fixture loop scopes are: \"function\", \"class\", \"module\", \"package\", \"session\"\n\n  warnings.warn(PytestDeprecationWarning(_DEFAULT_FIXTURE_LOOP_SCOPE_UNSET))\n",
    "old_commit_res_code": 1,
    "old_commit_res_stdout": "============================= test session starts ==============================\nplatform linux -- Python 3.9.21, pytest-8.3.3, pluggy-1.5.0 -- /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/.venv/bin/python\ncachedir: .pytest_cache\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37\nconfigfile: setup.cfg\nplugins: cov-5.0.0, mock-3.14.0, asyncio-0.25.1\nasyncio: mode=strict, asyncio_default_fixture_loop_scope=None\ncollecting ... collected 72 items\n\nr2e_tests/test_1.py::test_close_coro[pyloop] PASSED                      [  1%]\nr2e_tests/test_1.py::test_init_headers_simple_dict[pyloop] PASSED        [  2%]\nr2e_tests/test_1.py::test_init_headers_list_of_tuples[pyloop] PASSED     [  4%]\nr2e_tests/test_1.py::test_init_headers_MultiDict[pyloop] PASSED          [  5%]\nr2e_tests/test_1.py::test_init_headers_list_of_tuples_with_duplicates[pyloop] PASSED [  6%]\nr2e_tests/test_1.py::test_init_cookies_with_simple_dict[pyloop] PASSED   [  8%]\nr2e_tests/test_1.py::test_init_cookies_with_list_of_tuples[pyloop] PASSED [  9%]\nr2e_tests/test_1.py::test_merge_headers[pyloop] PASSED                   [ 11%]\nr2e_tests/test_1.py::test_merge_headers_with_multi_dict[pyloop] PASSED   [ 12%]\nr2e_tests/test_1.py::test_merge_headers_with_list_of_tuples[pyloop] PASSED [ 13%]\nr2e_tests/test_1.py::test_merge_headers_with_list_of_tuples_duplicated_names[pyloop] PASSED [ 15%]\nr2e_tests/test_1.py::test_http_GET[pyloop] PASSED                        [ 16%]\nr2e_tests/test_1.py::test_http_OPTIONS[pyloop] PASSED                    [ 18%]\nr2e_tests/test_1.py::test_http_HEAD[pyloop] PASSED                       [ 19%]\nr2e_tests/test_1.py::test_http_POST[pyloop] PASSED                       [ 20%]\nr2e_tests/test_1.py::test_http_PUT[pyloop] PASSED                        [ 22%]\nr2e_tests/test_1.py::test_http_PATCH[pyloop] PASSED                      [ 23%]\nr2e_tests/test_1.py::test_http_DELETE[pyloop] PASSED                     [ 25%]\nr2e_tests/test_1.py::test_close[pyloop] PASSED                           [ 26%]\nr2e_tests/test_1.py::test_closed[pyloop] PASSED                          [ 27%]\nr2e_tests/test_1.py::test_connector[pyloop] PASSED                       [ 29%]\nr2e_tests/test_1.py::test_create_connector[pyloop] PASSED                [ 30%]\nr2e_tests/test_1.py::test_connector_loop[pyloop] PASSED                  [ 31%]\nr2e_tests/test_1.py::test_detach[pyloop] PASSED                          [ 33%]\nr2e_tests/test_1.py::test_request_closed_session[pyloop] PASSED          [ 34%]\nr2e_tests/test_1.py::test_close_flag_for_closed_connector[pyloop] PASSED [ 36%]\nr2e_tests/test_1.py::test_double_close[pyloop] PASSED                    [ 37%]\nr2e_tests/test_1.py::test_del[pyloop] PASSED                             [ 38%]\nr2e_tests/test_1.py::test_del_debug[pyloop] PASSED                       [ 40%]\nr2e_tests/test_1.py::test_session_context_manager[pyloop] PASSED         [ 41%]\nr2e_tests/test_1.py::test_borrow_connector_loop[pyloop] PASSED           [ 43%]\nr2e_tests/test_1.py::test_reraise_os_error[pyloop] PASSED                [ 44%]\nr2e_tests/test_1.py::test_close_conn_on_error[pyloop] PASSED             [ 45%]\nr2e_tests/test_1.py::test_ws_connect_allowed_protocols[pyloop-http] PASSED [ 47%]\nr2e_tests/test_1.py::test_ws_connect_allowed_protocols[pyloop-https] PASSED [ 48%]\nr2e_tests/test_1.py::test_ws_connect_allowed_protocols[pyloop-ws] PASSED [ 50%]\nr2e_tests/test_1.py::test_ws_connect_allowed_protocols[pyloop-wss] PASSED [ 51%]\nr2e_tests/test_1.py::test_ws_connect_unix_socket_allowed_protocols[pyloop-http] PASSED [ 52%]\nr2e_tests/test_1.py::test_ws_connect_unix_socket_allowed_protocols[pyloop-https] PASSED [ 54%]\nr2e_tests/test_1.py::test_ws_connect_unix_socket_allowed_protocols[pyloop-ws] PASSED [ 55%]\nr2e_tests/test_1.py::test_ws_connect_unix_socket_allowed_protocols[pyloop-wss] PASSED [ 56%]\nr2e_tests/test_1.py::test_ws_connect_unix_socket_allowed_protocols[pyloop-unix] PASSED [ 58%]\nr2e_tests/test_1.py::test_cookie_jar_usage[pyloop] PASSED                [ 59%]\nr2e_tests/test_1.py::test_session_default_version[pyloop] PASSED         [ 61%]\nr2e_tests/test_1.py::test_session_loop[pyloop] PASSED                    [ 62%]\nr2e_tests/test_1.py::test_proxy_str[pyloop] PASSED                       [ 63%]\nr2e_tests/test_1.py::test_default_proxy[pyloop] FAILED                   [ 65%]\nr2e_tests/test_1.py::test_request_tracing[pyloop] PASSED                 [ 66%]\nr2e_tests/test_1.py::test_request_tracing_url_params[pyloop] PASSED      [ 68%]\nr2e_tests/test_1.py::test_request_tracing_exception PASSED               [ 69%]\nr2e_tests/test_1.py::test_request_tracing_interpose_headers[pyloop] PASSED [ 70%]\nr2e_tests/test_1.py::test_client_session_inheritance PASSED              [ 72%]\nr2e_tests/test_1.py::test_client_session_custom_attr[pyloop] SKIPPED     [ 73%]\nr2e_tests/test_1.py::test_client_session_timeout_args[pyloop] PASSED     [ 75%]\nr2e_tests/test_1.py::test_client_session_timeout_default_args[pyloop] PASSED [ 76%]\nr2e_tests/test_1.py::test_client_session_timeout_zero[pyloop] PASSED     [ 77%]\nr2e_tests/test_1.py::test_client_session_timeout_bad_argument PASSED     [ 79%]\nr2e_tests/test_1.py::test_requote_redirect_url_default PASSED            [ 80%]\nr2e_tests/test_1.py::test_requote_redirect_url_default_disable PASSED    [ 81%]\nr2e_tests/test_1.py::test_requote_redirect_setter PASSED                 [ 83%]\nr2e_tests/test_1.py::test_build_url_returns_expected_url[pyloop-base_url=None url='http://example.com/test'] PASSED [ 84%]\nr2e_tests/test_1.py::test_build_url_returns_expected_url[pyloop-base_url=None url=URL('http://example.com/test')] PASSED [ 86%]\nr2e_tests/test_1.py::test_build_url_returns_expected_url[pyloop-base_url='http://example.com' url='/test'] PASSED [ 87%]\nr2e_tests/test_1.py::test_build_url_returns_expected_url[pyloop-base_url=URL('http://example.com') url='/test'] PASSED [ 88%]\nr2e_tests/test_1.py::test_instantiation_with_invalid_timeout_value[pyloop] PASSED [ 90%]\nr2e_tests/test_1.py::test_properties[pyloop-skip_auto_headers-_skip_auto_headers] PASSED [ 91%]\nr2e_tests/test_1.py::test_properties[pyloop-auth-_default_auth] PASSED   [ 93%]\nr2e_tests/test_1.py::test_properties[pyloop-json_serialize-_json_serialize] PASSED [ 94%]\nr2e_tests/test_1.py::test_properties[pyloop-connector_owner-_connector_owner] PASSED [ 95%]\nr2e_tests/test_1.py::test_properties[pyloop-raise_for_status-_raise_for_status] PASSED [ 97%]\nr2e_tests/test_1.py::test_properties[pyloop-trust_env-_trust_env] PASSED [ 98%]\nr2e_tests/test_1.py::test_properties[pyloop-trace_configs-_trace_configs] PASSED [100%]\n\n=================================== FAILURES ===================================\n__________________________ test_default_proxy[pyloop] __________________________\n\nloop = <_UnixSelectorEventLoop running=False closed=False debug=False>\n\n    async def test_default_proxy(loop: asyncio.AbstractEventLoop) -> None:\n        proxy_url = URL(\"http://proxy.example.com\")\n        proxy_auth = mock.Mock()\n        proxy_url2 = URL(\"http://proxy.example2.com\")\n        proxy_auth2 = mock.Mock()\n    \n        class OnCall(Exception):\n            pass\n    \n        request_class_mock = mock.Mock(side_effect=OnCall())\n>       session = ClientSession(\n            proxy=proxy_url, proxy_auth=proxy_auth, request_class=request_class_mock\n        )\nE       TypeError: __init__() got an unexpected keyword argument 'proxy'\n\nOnCall     = <class 'r2e_tests.test_1.test_default_proxy.<locals>.OnCall'>\nloop       = <_UnixSelectorEventLoop running=False closed=False debug=False>\nproxy_auth = <Mock id='137018281717472'>\nproxy_auth2 = <Mock id='137018281714304'>\nproxy_url  = URL('http://proxy.example.com')\nproxy_url2 = URL('http://proxy.example2.com')\nrequest_class_mock = <Mock id='137018281717616'>\n\nr2e_tests/test_1.py:672: TypeError\n==================================== PASSES ====================================\n_____________________ test_session_context_manager[pyloop] _____________________\n------------------------------ Captured log call -------------------------------\nERROR    asyncio:base_events.py:1753 Unclosed client session\nclient_session: <aiohttp.client.ClientSession object at 0x7c9e0e42b580>\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                              98      2      0      0    98%\naiohttp/base_protocol.py                    68     36     22      3    39%\naiohttp/client.py                          550    120    202     53    73%\naiohttp/client_exceptions.py               154     65     20      1    52%\naiohttp/client_proto.py                    164     55     56     18    59%\naiohttp/client_reqrep.py                   706    239    302     83    59%\naiohttp/client_ws.py                       271    188     82      3    25%\naiohttp/compression_utils.py                70     36     14      0    40%\naiohttp/connector.py                       773    408    333     48    40%\naiohttp/cookiejar.py                       274    153    130     18    37%\naiohttp/formdata.py                         97     79     46      0    13%\naiohttp/hdrs.py                             90      0      0      0   100%\naiohttp/helpers.py                         497    225    176     23    48%\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                  388    255    148      0    25%\naiohttp/http_writer.py                     119     41     50     12    58%\naiohttp/locks.py                            24     16      4      0    29%\naiohttp/log.py                               7      0      0      0   100%\naiohttp/multipart.py                       623    508    266      1    13%\naiohttp/payload.py                         237     88     58     10    56%\naiohttp/payload_streamer.py                 31     11      4      0    69%\naiohttp/pytest_plugin.py                   163     60     42      6    61%\naiohttp/resolver.py                         79     55     26      2    25%\naiohttp/streams.py                         398    208    146     25    41%\naiohttp/tcp_helpers.py                      19      2      6      3    80%\naiohttp/test_utils.py                      323    115     54     16    60%\naiohttp/tracing.py                         191     12     32      0    95%\naiohttp/typedefs.py                         24      0      0      0   100%\naiohttp/web.py                             126     88     54      0    22%\naiohttp/web_app.py                         292    110     82     18    55%\naiohttp/web_exceptions.py                  157     16      8      3    87%\naiohttp/web_fileresponse.py                160    126     52      0    18%\naiohttp/web_log.py                         102     37     20      1    59%\naiohttp/web_middlewares.py                  59     41     22      0    22%\naiohttp/web_protocol.py                    367    146    158     48    50%\naiohttp/web_request.py                     445    252    140     10    36%\naiohttp/web_response.py                    485    199    226     51    50%\naiohttp/web_routedef.py                    100     44     10      0    55%\naiohttp/web_runner.py                      213     72     36     11    62%\naiohttp/web_server.py                       42      6     12      2    81%\naiohttp/web_urldispatcher.py               740    379    163     21    43%\naiohttp/web_ws.py                          386    313    134      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           2575   2575     86      0     0%\ntests/test_client_proto.py                  99     99      0      0     0%\ntests/test_client_request.py               827    827     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                    489    489      2      0     0%\ntests/test_client_ws_functional.py         805    805     32      0     0%\ntests/test_connector.py                   1701   1701     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                      86     86      6      0     0%\ntests/test_helpers.py                      491    491     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                        324    324      2      0     0%\ntests/test_proxy_functional.py             459    459     18      0     0%\ntests/test_pytest_plugin.py                 27     27      0      0     0%\ntests/test_resolver.py                     197    197     20      0     0%\ntests/test_route_def.py                    210    210      0      0     0%\ntests/test_run_app.py                      563    563     30      0     0%\ntests/test_streams.py                     1077   1077     38      0     0%\ntests/test_tcp_helpers.py                   52     52      2      0     0%\ntests/test_test_utils.py                   260    260     12      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                       94     94      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                 905    905      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                416    416      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                                    34921  29455   4434    493    16%\n\n============================= slowest 10 durations =============================\n0.09s call     r2e_tests/test_1.py::test_ws_connect_allowed_protocols[pyloop-http]\n0.08s call     r2e_tests/test_1.py::test_ws_connect_allowed_protocols[pyloop-https]\n0.08s call     r2e_tests/test_1.py::test_ws_connect_allowed_protocols[pyloop-ws]\n0.08s call     r2e_tests/test_1.py::test_ws_connect_unix_socket_allowed_protocols[pyloop-http]\n0.08s call     r2e_tests/test_1.py::test_ws_connect_allowed_protocols[pyloop-wss]\n0.08s call     r2e_tests/test_1.py::test_ws_connect_unix_socket_allowed_protocols[pyloop-https]\n0.08s call     r2e_tests/test_1.py::test_ws_connect_unix_socket_allowed_protocols[pyloop-ws]\n0.08s call     r2e_tests/test_1.py::test_ws_connect_unix_socket_allowed_protocols[pyloop-wss]\n0.08s call     r2e_tests/test_1.py::test_ws_connect_unix_socket_allowed_protocols[pyloop-unix]\n0.04s call     r2e_tests/test_1.py::test_client_session_timeout_zero[pyloop]\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::test_close_coro[pyloop]\nPASSED r2e_tests/test_1.py::test_init_headers_simple_dict[pyloop]\nPASSED r2e_tests/test_1.py::test_init_headers_list_of_tuples[pyloop]\nPASSED r2e_tests/test_1.py::test_init_headers_MultiDict[pyloop]\nPASSED r2e_tests/test_1.py::test_init_headers_list_of_tuples_with_duplicates[pyloop]\nPASSED r2e_tests/test_1.py::test_init_cookies_with_simple_dict[pyloop]\nPASSED r2e_tests/test_1.py::test_init_cookies_with_list_of_tuples[pyloop]\nPASSED r2e_tests/test_1.py::test_merge_headers[pyloop]\nPASSED r2e_tests/test_1.py::test_merge_headers_with_multi_dict[pyloop]\nPASSED r2e_tests/test_1.py::test_merge_headers_with_list_of_tuples[pyloop]\nPASSED r2e_tests/test_1.py::test_merge_headers_with_list_of_tuples_duplicated_names[pyloop]\nPASSED r2e_tests/test_1.py::test_http_GET[pyloop]\nPASSED r2e_tests/test_1.py::test_http_OPTIONS[pyloop]\nPASSED r2e_tests/test_1.py::test_http_HEAD[pyloop]\nPASSED r2e_tests/test_1.py::test_http_POST[pyloop]\nPASSED r2e_tests/test_1.py::test_http_PUT[pyloop]\nPASSED r2e_tests/test_1.py::test_http_PATCH[pyloop]\nPASSED r2e_tests/test_1.py::test_http_DELETE[pyloop]\nPASSED r2e_tests/test_1.py::test_close[pyloop]\nPASSED r2e_tests/test_1.py::test_closed[pyloop]\nPASSED r2e_tests/test_1.py::test_connector[pyloop]\nPASSED r2e_tests/test_1.py::test_create_connector[pyloop]\nPASSED r2e_tests/test_1.py::test_connector_loop[pyloop]\nPASSED r2e_tests/test_1.py::test_detach[pyloop]\nPASSED r2e_tests/test_1.py::test_request_closed_session[pyloop]\nPASSED r2e_tests/test_1.py::test_close_flag_for_closed_connector[pyloop]\nPASSED r2e_tests/test_1.py::test_double_close[pyloop]\nPASSED r2e_tests/test_1.py::test_del[pyloop]\nPASSED r2e_tests/test_1.py::test_del_debug[pyloop]\nPASSED r2e_tests/test_1.py::test_session_context_manager[pyloop]\nPASSED r2e_tests/test_1.py::test_borrow_connector_loop[pyloop]\nPASSED r2e_tests/test_1.py::test_reraise_os_error[pyloop]\nPASSED r2e_tests/test_1.py::test_close_conn_on_error[pyloop]\nPASSED r2e_tests/test_1.py::test_ws_connect_allowed_protocols[pyloop-http]\nPASSED r2e_tests/test_1.py::test_ws_connect_allowed_protocols[pyloop-https]\nPASSED r2e_tests/test_1.py::test_ws_connect_allowed_protocols[pyloop-ws]\nPASSED r2e_tests/test_1.py::test_ws_connect_allowed_protocols[pyloop-wss]\nPASSED r2e_tests/test_1.py::test_ws_connect_unix_socket_allowed_protocols[pyloop-http]\nPASSED r2e_tests/test_1.py::test_ws_connect_unix_socket_allowed_protocols[pyloop-https]\nPASSED r2e_tests/test_1.py::test_ws_connect_unix_socket_allowed_protocols[pyloop-ws]\nPASSED r2e_tests/test_1.py::test_ws_connect_unix_socket_allowed_protocols[pyloop-wss]\nPASSED r2e_tests/test_1.py::test_ws_connect_unix_socket_allowed_protocols[pyloop-unix]\nPASSED r2e_tests/test_1.py::test_cookie_jar_usage[pyloop]\nPASSED r2e_tests/test_1.py::test_session_default_version[pyloop]\nPASSED r2e_tests/test_1.py::test_session_loop[pyloop]\nPASSED r2e_tests/test_1.py::test_proxy_str[pyloop]\nPASSED r2e_tests/test_1.py::test_request_tracing[pyloop]\nPASSED r2e_tests/test_1.py::test_request_tracing_url_params[pyloop]\nPASSED r2e_tests/test_1.py::test_request_tracing_exception\nPASSED r2e_tests/test_1.py::test_request_tracing_interpose_headers[pyloop]\nPASSED r2e_tests/test_1.py::test_client_session_inheritance\nPASSED r2e_tests/test_1.py::test_client_session_timeout_args[pyloop]\nPASSED r2e_tests/test_1.py::test_client_session_timeout_default_args[pyloop]\nPASSED r2e_tests/test_1.py::test_client_session_timeout_zero[pyloop]\nPASSED r2e_tests/test_1.py::test_client_session_timeout_bad_argument\nPASSED r2e_tests/test_1.py::test_requote_redirect_url_default\nPASSED r2e_tests/test_1.py::test_requote_redirect_url_default_disable\nPASSED r2e_tests/test_1.py::test_requote_redirect_setter\nPASSED r2e_tests/test_1.py::test_build_url_returns_expected_url[pyloop-base_url=None url='http://example.com/test']\nPASSED r2e_tests/test_1.py::test_build_url_returns_expected_url[pyloop-base_url=None url=URL('http://example.com/test')]\nPASSED r2e_tests/test_1.py::test_build_url_returns_expected_url[pyloop-base_url='http://example.com' url='/test']\nPASSED r2e_tests/test_1.py::test_build_url_returns_expected_url[pyloop-base_url=URL('http://example.com') url='/test']\nPASSED r2e_tests/test_1.py::test_instantiation_with_invalid_timeout_value[pyloop]\nPASSED r2e_tests/test_1.py::test_properties[pyloop-skip_auto_headers-_skip_auto_headers]\nPASSED r2e_tests/test_1.py::test_properties[pyloop-auth-_default_auth]\nPASSED r2e_tests/test_1.py::test_properties[pyloop-json_serialize-_json_serialize]\nPASSED r2e_tests/test_1.py::test_properties[pyloop-connector_owner-_connector_owner]\nPASSED r2e_tests/test_1.py::test_properties[pyloop-raise_for_status-_raise_for_status]\nPASSED r2e_tests/test_1.py::test_properties[pyloop-trust_env-_trust_env]\nPASSED r2e_tests/test_1.py::test_properties[pyloop-trace_configs-_trace_configs]\nSKIPPED [1] r2e_tests/test_1.py:951: The check is applied in DEBUG mode only\nFAILED r2e_tests/test_1.py::test_default_proxy[pyloop] - TypeError: __init__(...\n=================== 1 failed, 70 passed, 1 skipped in 6.27s ====================\n",
    "old_commit_res_stderr": "/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e238777c2a1e99e5de6e57972a31488ee8f03e37/.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/9207.feature.rst CONTRIBUTORS.txt aiohttp/client.py docs/client_advanced.rst tests/test_client_session.py
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]

**Title:** ClientSession initialization fails with unexpected 'proxy' and 'proxy_auth' arguments

**Description:**
When attempting to initialize `ClientSession` with `proxy` and `proxy_auth` parameters, a `TypeError` is raised indicating that these arguments are unexpected.

**Example Code:**
```python
from aiohttp import ClientSession
from yarl import URL

proxy_url = URL("http://proxy.example.com")
proxy_auth = None  # Replace with appropriate authentication if needed

session = ClientSession(proxy=proxy_url, proxy_auth=proxy_auth)
```

**Expected Behavior:**
`ClientSession` should accept `proxy` and `proxy_auth` as valid initialization arguments, allowing users to set default proxy settings for all requests made through the session.

**Actual Behavior:**
Initializing `ClientSession` with the `proxy` argument results in the following error:
```
TypeError: __init__() got an unexpected keyword argument 'proxy'
```

[/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.py
"""HTTP Client for asyncio."""

import asyncio
import base64
import hashlib
import json
import os
import sys
import traceback
import warnings
from contextlib import suppress
from types import TracebackType
from typing import (
    TYPE_CHECKING,
    Any,
    Awaitable,
    Callable,
    Coroutine,
    Final,
    FrozenSet,
    Generator,
    Generic,
    Iterable,
    List,
    Mapping,
    Optional,
    Set,
    Tuple,
    Type,
    TypedDict,
    TypeVar,
    Union,
)

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

from . import hdrs, http, payload
from .abc import AbstractCookieJar
from .client_exceptions import (
    ClientConnectionError,
    ClientConnectionResetError,
    ClientConnectorCertificateError,
    ClientConnectorError,
    ClientConnectorSSLError,
    ClientError,
    ClientHttpProxyError,
    ClientOSError,
    ClientPayloadError,
    ClientProxyConnectionError,
    ClientResponseError,
    ClientSSLError,
    ConnectionTimeoutError,
    ContentTypeError,
    InvalidURL,
    InvalidUrlClientError,
    InvalidUrlRedirectClientError,
    NonHttpUrlClientError,
    NonHttpUrlRedirectClientError,
    RedirectClientError,
    ServerConnectionError,
    ServerDisconnectedError,
    ServerFingerprintMismatch,
    ServerTimeoutError,
    SocketTimeoutError,
    TooManyRedirects,
    WSServerHandshakeError,
)
from .client_reqrep import (
    ClientRequest as ClientRequest,
    ClientResponse as ClientResponse,
    Fingerprint as Fingerprint,
    RequestInfo as RequestInfo,
    _merge_ssl_params,
)
from .client_ws import (
    DEFAULT_WS_CLIENT_TIMEOUT,
    ClientWebSocketResponse as ClientWebSocketResponse,
    ClientWSTimeout as ClientWSTimeout,
)
from .connector import (
    HTTP_AND_EMPTY_SCHEMA_SET,
    BaseConnector as BaseConnector,
    NamedPipeConnector as NamedPipeConnector,
    TCPConnector as TCPConnector,
    UnixConnector as UnixConnector,
)
from .cookiejar import CookieJar
from .helpers import (
    _SENTINEL,
    DEBUG,
    BasicAuth,
    TimeoutHandle,
    ceil_timeout,
    get_env_proxy_for_url,
    method_must_be_empty_body,
    sentinel,
    strip_auth_from_url,
)
from .http import WS_KEY, HttpVersion, WebSocketReader, WebSocketWriter
from .http_websocket import WSHandshakeError, WSMessage, ws_ext_gen, ws_ext_parse
from .streams import FlowControlDataQueue
from .tracing import Trace, TraceConfig
from .typedefs import JSONEncoder, LooseCookies, LooseHeaders, Query, StrOrURL

__all__ = (
    # client_exceptions
    "ClientConnectionError",
    "ClientConnectionResetError",
    "ClientConnectorCertificateError",
    "ClientConnectorError",
    "ClientConnectorSSLError",
    "ClientError",
    "ClientHttpProxyError",
    "ClientOSError",
    "ClientPayloadError",
    "ClientProxyConnectionError",
    "ClientResponseError",
    "ClientSSLError",
    "ConnectionTimeoutError",
    "ContentTypeError",
    "InvalidURL",
    "InvalidUrlClientError",
    "RedirectClientError",
    "NonHttpUrlClientError",
    "InvalidUrlRedirectClientError",
    "NonHttpUrlRedirectClientError",
    "ServerConnectionError",
    "ServerDisconnectedError",
    "ServerFingerprintMismatch",
    "ServerTimeoutError",
    "SocketTimeoutError",
    "TooManyRedirects",
    "WSServerHandshakeError",
    # client_reqrep
    "ClientRequest",
    "ClientResponse",
    "Fingerprint",
    "RequestInfo",
    # connector
    "BaseConnector",
    "TCPConnector",
    "UnixConnector",
    "NamedPipeConnector",
    # client_ws
    "ClientWebSocketResponse",
    # client
    "ClientSession",
    "ClientTimeout",
    "ClientWSTimeout",
    "request",
)


if TYPE_CHECKING:
    from ssl import SSLContext
else:
    SSLContext = None

if sys.version_info >= (3, 11) and TYPE_CHECKING:
    from typing import Unpack


class _RequestOptions(TypedDict, total=False):
    params: Query
    data: Any
    json: Any
    cookies: Union[LooseCookies, None]
    headers: Union[LooseHeaders, None]
    skip_auto_headers: Union[Iterable[str], None]
    auth: Union[BasicAuth, None]
    allow_redirects: bool
    max_redirects: int
    compress: Union[str, bool, None]
    chunked: Union[bool, None]
    expect100: bool
    raise_for_status: Union[None, bool, Callable[[ClientResponse], Awaitable[None]]]
    read_until_eof: bool
    proxy: Union[StrOrURL, None]
    proxy_auth: Union[BasicAuth, None]
    timeout: "Union[ClientTimeout, _SENTINEL, None]"
    ssl: Union[SSLContext, bool, Fingerprint]
    server_hostname: Union[str, None]
    proxy_headers: Union[LooseHeaders, None]
    trace_request_ctx: Union[Mapping[str, str], None]
    read_bufsize: Union[int, None]
    auto_decompress: Union[bool, None]
    max_line_size: Union[int, None]
    max_field_size: Union[int, None]


@attr.s(auto_attribs=True, frozen=True, slots=True)
class ClientTimeout:
    total: Optional[float] = None
    connect: Optional[float] = None
    sock_read: Optional[float] = None
    sock_connect: Optional[float] = None
    ceil_threshold: float = 5

    # pool_queue_timeout: Optional[float] = None
    # dns_resolution_timeout: Optional[float] = None
    # socket_connect_timeout: Optional[float] = None
    # connection_acquiring_timeout: Optional[float] = None
    # new_connection_timeout: Optional[float] = None
    # http_header_timeout: Optional[float] = None
    # response_body_timeout: Optional[float] = None

    # to create a timeout specific for a single request, either
    # - create a completely new one to overwrite the default
    # - or use http://www.attrs.org/en/stable/api.html#attr.evolve
    # to overwrite the defaults


# 5 Minute default read timeout
DEFAULT_TIMEOUT: Final[ClientTimeout] = ClientTimeout(total=5 * 60)

# https://www.rfc-editor.org/rfc/rfc9110#section-9.2.2
IDEMPOTENT_METHODS = frozenset({"GET", "HEAD", "OPTIONS", "TRACE", "PUT", "DELETE"})

_RetType = TypeVar("_RetType", ClientResponse, ClientWebSocketResponse)
_CharsetResolver = Callable[[ClientResponse, bytes], str]


class ClientSession:
    """First-class interface for making HTTP requests."""

    ATTRS = frozenset(
        [
            "_base_url",
            "_source_traceback",
            "_connector",
            "requote_redirect_url",
            "_loop",
            "_cookie_jar",
            "_connector_owner",
            "_default_auth",
            "_version",
            "_json_serialize",
            "_requote_redirect_url",
            "_timeout",
            "_raise_for_status",
            "_auto_decompress",
            "_trust_env",
            "_default_headers",
            "_skip_auto_headers",
            "_request_class",
            "_response_class",
            "_ws_response_class",
            "_trace_configs",
            "_read_bufsize",
            "_max_line_size",
            "_max_field_size",
            "_resolve_charset",
        ]
    )

    _source_traceback: Optional[traceback.StackSummary] = None
    _connector: Optional[BaseConnector] = None

    def __init__(
        self,
        base_url: Optional[StrOrURL] = None,
        *,
        connector: Optional[BaseConnector] = None,
        loop: Optional[asyncio.AbstractEventLoop] = None,
        cookies: Optional[LooseCookies] = None,
        headers: Optional[LooseHeaders] = None,
        skip_auto_headers: Optional[Iterable[str]] = None,
        auth: Optional[BasicAuth] = None,
        json_serialize: JSONEncoder = json.dumps,
        request_class: Type[ClientRequest] = ClientRequest,
        response_class: Type[ClientResponse] = ClientResponse,
        ws_response_class: Type[ClientWebSocketResponse] = ClientWebSocketResponse,
        version: HttpVersion = http.HttpVersion11,
        cookie_jar: Optional[AbstractCookieJar] = None,
        connector_owner: bool = True,
        raise_for_status: Union[
            bool, Callable[[ClientResponse], Awaitable[None]]
        ] = False,
        read_timeout: Union[float, _SENTINEL] = sentinel,
        conn_timeout: Optional[float] = None,
        timeout: Union[object, ClientTimeout] = sentinel,
        auto_decompress: bool = True,
        trust_env: bool = False,
        requote_redirect_url: bool = True,
        trace_configs: Optional[List[TraceConfig]] = None,
        read_bufsize: int = 2**16,
        max_line_size: int = 8190,
        max_field_size: int = 8190,
        fallback_charset_resolver: _CharsetResolver = lambda r, b: "utf-8",
    ) -> None:
        # We initialise _connector to None immediately, as it's referenced in __del__()
        # and could cause issues if an exception occurs during initialisation.
        self._connector: Optional[BaseConnector] = None

        if loop is None:
            if connector is not None:
                loop = connector._loop

        loop = loop or asyncio.get_running_loop()

        if base_url is None or isinstance(base_url, URL):
            self._base_url: Optional[URL] = base_url
        else:
            self._base_url = URL(base_url)
            assert (
                self._base_url.origin() == self._base_url
            ), "Only absolute URLs without path part are supported"

        if timeout is sentinel or timeout is None:
            self._timeout = DEFAULT_TIMEOUT
            if read_timeout is not sentinel:
                warnings.warn(
                    "read_timeout is deprecated, use timeout argument instead",
                    DeprecationWarning,
                    stacklevel=2,
                )
                self._timeout = attr.evolve(self._timeout, total=read_timeout)
            if conn_timeout is not None:
                self._timeout = attr.evolve(self._timeout, connect=conn_timeout)
                warnings.warn(
                    "conn_timeout is deprecated, use timeout argument instead",
                    DeprecationWarning,
                    stacklevel=2,
                )
        else:
            if not isinstance(timeout, ClientTimeout):
                raise ValueError(
                    f"timeout parameter cannot be of {type(timeout)} type, "
                    "please use 'timeout=ClientTimeout(...)'",
                )
            self._timeout = timeout
            if read_timeout is not sentinel:
                raise ValueError(
                    "read_timeout and timeout parameters "
                    "conflict, please setup "
                    "timeout.read"
                )
            if conn_timeout is not None:
                raise ValueError(
                    "conn_timeout and timeout parameters "
                    "conflict, please setup "
                    "timeout.connect"
                )

        if connector is None:
            connector = TCPConnector(loop=loop)

        if connector._loop is not loop:
            raise RuntimeError("Session and connector has to use same event loop")

        self._loop = loop

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

        if cookie_jar is None:
            cookie_jar = CookieJar(loop=loop)
        self._cookie_jar = cookie_jar

        if cookies is not None:
            self._cookie_jar.update_cookies(cookies)

        self._connector = connector
        self._connector_owner = connector_owner
        self._default_auth = auth
        self._version = version
        self._json_serialize = json_serialize
        self._raise_for_status = raise_for_status
        self._auto_decompress = auto_decompress
        self._trust_env = trust_env
        self._requote_redirect_url = requote_redirect_url
        self._read_bufsize = read_bufsize
        self._max_line_size = max_line_size
        self._max_field_size = max_field_size

        # Convert to list of tuples
        if headers:
            real_headers: CIMultiDict[str] = CIMultiDict(headers)
        else:
            real_headers = CIMultiDict()
        self._default_headers: CIMultiDict[str] = real_headers
        if skip_auto_headers is not None:
            self._skip_auto_headers = frozenset(istr(i) for i in skip_auto_headers)
        else:
            self._skip_auto_headers = frozenset()

        self._request_class = request_class
        self._response_class = response_class
        self._ws_response_class = ws_response_class

        self._trace_configs = trace_configs or []
        for trace_config in self._trace_configs:
            trace_config.freeze()

        self._resolve_charset = fallback_charset_resolver

    def __init_subclass__(cls: Type["ClientSession"]) -> None:
        warnings.warn(
            "Inheritance class {} from ClientSession "
            "is discouraged".format(cls.__name__),
            DeprecationWarning,
            stacklevel=2,
        )

    if DEBUG:

        def __setattr__(self, name: str, val: Any) -> None:
            if name not in self.ATTRS:
                warnings.warn(
                    "Setting custom ClientSession.{} attribute "
                    "is discouraged".format(name),
                    DeprecationWarning,
                    stacklevel=2,
                )
            super().__setattr__(name, val)

    def __del__(self, _warnings: Any = warnings) -> None:
        if not self.closed:
            kwargs = {"source": self}
            _warnings.warn(
                f"Unclosed client session {self!r}", ResourceWarning, **kwargs
            )
            context = {"client_session": self, "message": "Unclosed client session"}
            if self._source_traceback is not None:
                context["source_traceback"] = self._source_traceback
            self._loop.call_exception_handler(context)

    if sys.version_info >= (3, 11) and TYPE_CHECKING:

        def request(
            self,
            method: str,
            url: StrOrURL,
            **kwargs: Unpack[_RequestOptions],
        ) -> "_RequestContextManager": ...

    else:

        def request(
            self, method: str, url: StrOrURL, **kwargs: Any
        ) -> "_RequestContextManager":
            """Perform HTTP request."""
            return _RequestContextManager(self._request(method, url, **kwargs))

    def _build_url(self, str_or_url: StrOrURL) -> URL:
        url = URL(str_or_url)
        if self._base_url is None:
            return url
        else:
            assert not url.absolute and url.path.startswith("/")
            return self._base_url.join(url)

    async def _request(
        self,
        method: str,
        str_or_url: StrOrURL,
        *,
        params: Query = None,
        data: Any = None,
        json: Any = None,
        cookies: Optional[LooseCookies] = None,
        headers: Optional[LooseHeaders] = None,
        skip_auto_headers: Optional[Iterable[str]] = None,
        auth: Optional[BasicAuth] = None,
        allow_redirects: bool = True,
        max_redirects: int = 10,
        compress: Union[str, bool, None] = None,
        chunked: Optional[bool] = None,
        expect100: bool = False,
        raise_for_status: Union[
            None, bool, Callable[[ClientResponse], Awaitable[None]]
        ] = None,
        read_until_eof: bool = True,
        proxy: Optional[StrOrURL] = None,
        proxy_auth: Optional[BasicAuth] = None,
        timeout: Union[ClientTimeout, _SENTINEL] = sentinel,
        verify_ssl: Optional[bool] = None,
        fingerprint: Optional[bytes] = None,
        ssl_context: Optional[SSLContext] = None,
        ssl: Union[SSLContext, bool, Fingerprint] = True,
        server_hostname: Optional[str] = None,
        proxy_headers: Optional[LooseHeaders] = None,
        trace_request_ctx: Optional[Mapping[str, str]] = None,
        read_bufsize: Optional[int] = None,
        auto_decompress: Optional[bool] = None,
        max_line_size: Optional[int] = None,
        max_field_size: Optional[int] = None,
    ) -> ClientResponse:

        # NOTE: timeout clamps existing connect and read timeouts.  We cannot
        # set the default to None because we need to detect if the user wants
        # to use the existing timeouts by setting timeout to None.

        if self.closed:
            raise RuntimeError("Session is closed")

        ssl = _merge_ssl_params(ssl, verify_ssl, ssl_context, fingerprint)

        if data is not None and json is not None:
            raise ValueError(
                "data and json parameters can not be used at the same time"
            )
        elif json is not None:
            data = payload.JsonPayload(json, dumps=self._json_serialize)

        if not isinstance(chunked, bool) and chunked is not None:
            warnings.warn("Chunk size is deprecated #1615", DeprecationWarning)

        redirects = 0
        history = []
        version = self._version
        params = params or {}

        # Merge with default headers and transform to CIMultiDict
        headers = self._prepare_headers(headers)

        try:
            url = self._build_url(str_or_url)
        except ValueError as e:
            raise InvalidUrlClientError(str_or_url) from e

        assert self._connector is not None
        if url.scheme not in self._connector.allowed_protocol_schema_set:
            raise NonHttpUrlClientError(url)

        skip_headers = set(self._skip_auto_headers)
        if skip_auto_headers is not None:
            for i in skip_auto_headers:
                skip_headers.add(istr(i))

        if proxy is None:
            proxy_headers = None
        else:
            proxy_headers = self._prepare_headers(proxy_headers)
            try:
                proxy = URL(proxy)
            except ValueError as e:
                raise InvalidURL(proxy) from e

        if timeout is sentinel:
            real_timeout: ClientTimeout = self._timeout
        else:
            if not isinstance(timeout, ClientTimeout):
                real_timeout = ClientTimeout(total=timeout)
            else:
                real_timeout = timeout
        # timeout is cumulative for all request operations
        # (request, redirects, responses, data consuming)
        tm = TimeoutHandle(
            self._loop, real_timeout.total, ceil_threshold=real_timeout.ceil_threshold
        )
        handle = tm.start()

        if read_bufsize is None:
            read_bufsize = self._read_bufsize

        if auto_decompress is None:
            auto_decompress = self._auto_decompress

        if max_line_size is None:
            max_line_size = self._max_line_size

        if max_field_size is None:
            max_field_size = self._max_field_size

        traces = [
            Trace(
                self,
                trace_config,
                trace_config.trace_config_ctx(trace_request_ctx=trace_request_ctx),
            )
            for trace_config in self._trace_configs
        ]

        for trace in traces:
            await trace.send_request_start(method, url.update_query(params), headers)

        timer = tm.timer()
        try:
            with timer:
                # https://www.rfc-editor.org/rfc/rfc9112.html#name-retrying-requests
                retry_persistent_connection = method in IDEMPOTENT_METHODS
                while True:
                    url, auth_from_url = strip_auth_from_url(url)
                    if not url.raw_host:
                        # NOTE: Bail early, otherwise, causes `InvalidURL` through
                        # NOTE: `self._request_class()` below.
                        err_exc_cls = (
                            InvalidUrlRedirectClientError
                            if redirects
                            else InvalidUrlClientError
                        )
                        raise err_exc_cls(url)
                    if auth and auth_from_url:
                        raise ValueError(
                            "Cannot combine AUTH argument with "
                            "credentials encoded in URL"
                        )

                    if auth is None:
                        auth = auth_from_url

                    if auth is None and (
                        not self._base_url or self._base_url.origin() == url.origin()
                    ):
                        auth = self._default_auth
                    # It would be confusing if we support explicit
                    # Authorization header with auth argument
                    if (
                        headers is not None
                        and auth is not None
                        and hdrs.AUTHORIZATION in headers
                    ):
                        raise ValueError(
                            "Cannot combine AUTHORIZATION header "
                            "with AUTH argument or credentials "
                            "encoded in URL"
                        )

                    all_cookies = self._cookie_jar.filter_cookies(url)

                    if cookies is not None:
                        tmp_cookie_jar = CookieJar()
                        tmp_cookie_jar.update_cookies(cookies)
                        req_cookies = tmp_cookie_jar.filter_cookies(url)
                        if req_cookies:
                            all_cookies.load(req_cookies)

                    if proxy is not None:
                        proxy = URL(proxy)
                    elif self._trust_env:
                        with suppress(LookupError):
                            proxy, proxy_auth = get_env_proxy_for_url(url)

                    req = self._request_class(
                        method,
                        url,
                        params=params,
                        headers=headers,
                        skip_auto_headers=skip_headers if skip_headers else None,
                        data=data,
                        cookies=all_cookies,
                        auth=auth,
                        version=version,
                        compress=compress,
                        chunked=chunked,
                        expect100=expect100,
                        loop=self._loop,
                        response_class=self._response_class,
                        proxy=proxy,
                        proxy_auth=proxy_auth,
                        timer=timer,
                        session=self,
                        ssl=ssl if ssl is not None else True,
                        server_hostname=server_hostname,
                        proxy_headers=proxy_headers,
                        traces=traces,
                        trust_env=self.trust_env,
                    )

                    # connection timeout
                    try:
                        async with ceil_timeout(
                            real_timeout.connect,
                            ceil_threshold=real_timeout.ceil_threshold,
                        ):
                            conn = await self._connector.connect(
                                req, traces=traces, timeout=real_timeout
                            )
                    except asyncio.TimeoutError as exc:
                        raise ConnectionTimeoutError(
                            f"Connection timeout to host {url}"
                        ) from exc

                    assert conn.transport is not None

                    assert conn.protocol is not None
                    conn.protocol.set_response_params(
                        timer=timer,
                        skip_payload=method_must_be_empty_body(method),
                        read_until_eof=read_until_eof,
                        auto_decompress=auto_decompress,
                        read_timeout=real_timeout.sock_read,
                        read_bufsize=read_bufsize,
                        timeout_ceil_threshold=self._connector._timeout_ceil_threshold,
                        max_line_size=max_line_size,
                        max_field_size=max_field_size,
                    )

                    try:
                        try:
                            resp = await req.send(conn)
                            try:
                                await resp.start(conn)
                            except BaseException:
                                resp.close()
                                raise
                        except BaseException:
                            conn.close()
                            raise
                    except (ClientOSError, ServerDisconnectedError):
                        if retry_persistent_connection:
                            retry_persistent_connection = False
                            continue
                        raise
                    except ClientError:
                        raise
                    except OSError as exc:
                        if exc.errno is None and isinstance(exc, asyncio.TimeoutError):
                            raise
                        raise ClientOSError(*exc.args) from exc

                    self._cookie_jar.update_cookies(resp.cookies, resp.url)

                    # redirects
                    if resp.status in (301, 302, 303, 307, 308) and allow_redirects:

                        for trace in traces:
                            await trace.send_request_redirect(
                                method, url.update_query(params), headers, resp
                            )

                        redirects += 1
                        history.append(resp)
                        if max_redirects and redirects >= max_redirects:
                            resp.close()
                            raise TooManyRedirects(
                                history[0].request_info, tuple(history)
                            )

                        # For 301 and 302, mimic IE, now changed in RFC
                        # https://github.com/kennethreitz/requests/pull/269
                        if (resp.status == 303 and resp.method != hdrs.METH_HEAD) or (
                            resp.status in (301, 302) and resp.method == hdrs.METH_POST
                        ):
                            method = hdrs.METH_GET
                            data = None
                            if headers.get(hdrs.CONTENT_LENGTH):
                                headers.pop(hdrs.CONTENT_LENGTH)

                        r_url = resp.headers.get(hdrs.LOCATION) or resp.headers.get(
                            hdrs.URI
                        )
                        if r_url is None:
                            # see github.com/aio-libs/aiohttp/issues/2022
                            break
                        else:
                            # reading from correct redirection
                            # response is forbidden
                            resp.release()

                        try:
                            parsed_redirect_url = URL(
                                r_url, encoded=not self._requote_redirect_url
                            )
                        except ValueError as e:
                            raise InvalidUrlRedirectClientError(
                                r_url,
                                "Server attempted redirecting to a location that does not look like a URL",
                            ) from e

                        scheme = parsed_redirect_url.scheme
                        if scheme not in HTTP_AND_EMPTY_SCHEMA_SET:
                            resp.close()
                            raise NonHttpUrlRedirectClientError(r_url)
                        elif not scheme:
                            parsed_redirect_url = url.join(parsed_redirect_url)

                        try:
                            redirect_origin = parsed_redirect_url.origin()
                        except ValueError as origin_val_err:
                            raise InvalidUrlRedirectClientError(
                                parsed_redirect_url,
                                "Invalid redirect URL origin",
                            ) from origin_val_err

                        if url.origin() != redirect_origin:
                            auth = None
                            headers.pop(hdrs.AUTHORIZATION, None)

                        url = parsed_redirect_url
                        params = {}
                        resp.release()
                        continue

                    break

            # check response status
            if raise_for_status is None:
                raise_for_status = self._raise_for_status

            if raise_for_status is None:
                pass
            elif callable(raise_for_status):
                await raise_for_status(resp)
            elif raise_for_status:
                resp.raise_for_status()

            # register connection
            if handle is not None:
                if resp.connection is not None:
                    resp.connection.add_callback(handle.cancel)
                else:
                    handle.cancel()

            resp._history = tuple(history)

            for trace in traces:
                await trace.send_request_end(
                    method, url.update_query(params), headers, resp
                )
            return resp

        except BaseException as e:
            # cleanup timer
            tm.close()
            if handle:
                handle.cancel()
                handle = None

            for trace in traces:
                await trace.send_request_exception(
                    method, url.update_query(params), headers, e
                )
            raise

    def ws_connect(
        self,
        url: StrOrURL,
        *,
        method: str = hdrs.METH_GET,
        protocols: Iterable[str] = (),
        timeout: Union[ClientWSTimeout, _SENTINEL] = sentinel,
        receive_timeout: Optional[float] = None,
        autoclose: bool = True,
        autoping: bool = True,
        heartbeat: Optional[float] = None,
        auth: Optional[BasicAuth] = None,
        origin: Optional[str] = None,
        params: Query = None,
        headers: Optional[LooseHeaders] = None,
        proxy: Optional[StrOrURL] = None,
        proxy_auth: Optional[BasicAuth] = None,
        ssl: Union[SSLContext, bool, Fingerprint] = True,
        verify_ssl: Optional[bool] = None,
        fingerprint: Optional[bytes] = None,
        ssl_context: Optional[SSLContext] = None,
        proxy_headers: Optional[LooseHeaders] = None,
        compress: int = 0,
        max_msg_size: int = 4 * 1024 * 1024,
    ) -> "_WSRequestContextManager":
        """Initiate websocket connection."""
        return _WSRequestContextManager(
            self._ws_connect(
                url,
                method=method,
                protocols=protocols,
                timeout=timeout,
                receive_timeout=receive_timeout,
                autoclose=autoclose,
                autoping=autoping,
                heartbeat=heartbeat,
                auth=auth,
                origin=origin,
                params=params,
                headers=headers,
                proxy=proxy,
                proxy_auth=proxy_auth,
                ssl=ssl,
                verify_ssl=verify_ssl,
                fingerprint=fingerprint,
                ssl_context=ssl_context,
                proxy_headers=proxy_headers,
                compress=compress,
                max_msg_size=max_msg_size,
            )
        )

    async def _ws_connect(
        self,
        url: StrOrURL,
        *,
        method: str = hdrs.METH_GET,
        protocols: Iterable[str] = (),
        timeout: Union[ClientWSTimeout, _SENTINEL] = sentinel,
        receive_timeout: Optional[float] = None,
        autoclose: bool = True,
        autoping: bool = True,
        heartbeat: Optional[float] = None,
        auth: Optional[BasicAuth] = None,
        origin: Optional[str] = None,
        params: Query = None,
        headers: Optional[LooseHeaders] = None,
        proxy: Optional[StrOrURL] = None,
        proxy_auth: Optional[BasicAuth] = None,
        ssl: Union[SSLContext, bool, Fingerprint] = True,
        verify_ssl: Optional[bool] = None,
        fingerprint: Optional[bytes] = None,
        ssl_context: Optional[SSLContext] = None,
        proxy_headers: Optional[LooseHeaders] = None,
        compress: int = 0,
        max_msg_size: int = 4 * 1024 * 1024,
    ) -> ClientWebSocketResponse:
        if timeout is not sentinel:
            if isinstance(timeout, ClientWSTimeout):
                ws_timeout = timeout
            else:
                warnings.warn(
                    "parameter 'timeout' of type 'float' "
                    "is deprecated, please use "
                    "'timeout=ClientWSTimeout(ws_close=...)'",
                    DeprecationWarning,
                    stacklevel=2,
                )
                ws_timeout = ClientWSTimeout(ws_close=timeout)
        else:
            ws_timeout = DEFAULT_WS_CLIENT_TIMEOUT
        if receive_timeout is not None:
            warnings.warn(
                "float parameter 'receive_timeout' "
                "is deprecated, please use parameter "
                "'timeout=ClientWSTimeout(ws_receive=...)'",
                DeprecationWarning,
                stacklevel=2,
            )
            ws_timeout = attr.evolve(ws_timeout, ws_receive=receive_timeout)

        if headers is None:
            real_headers: CIMultiDict[str] = CIMultiDict()
        else:
            real_headers = CIMultiDict(headers)

        default_headers = {
            hdrs.UPGRADE: "websocket",
            hdrs.CONNECTION: "Upgrade",
            hdrs.SEC_WEBSOCKET_VERSION: "13",
        }

        for key, value in default_headers.items():
            real_headers.setdefault(key, value)

        sec_key = base64.b64encode(os.urandom(16))
        real_headers[hdrs.SEC_WEBSOCKET_KEY] = sec_key.decode()

        if protocols:
            real_headers[hdrs.SEC_WEBSOCKET_PROTOCOL] = ",".join(protocols)
        if origin is not None:
            real_headers[hdrs.ORIGIN] = origin
        if compress:
            extstr = ws_ext_gen(compress=compress)
            real_headers[hdrs.SEC_WEBSOCKET_EXTENSIONS] = extstr

        # For the sake of backward compatibility, if user passes in None, convert it to True
        if ssl is None:
            warnings.warn(
                "ssl=None is deprecated, please use ssl=True",
                DeprecationWarning,
                stacklevel=2,
            )
            ssl = True
        ssl = _merge_ssl_params(ssl, verify_ssl, ssl_context, fingerprint)

        # send request
        resp = await self.request(
            method,
            url,
            params=params,
            headers=real_headers,
            read_until_eof=False,
            auth=auth,
            proxy=proxy,
            proxy_auth=proxy_auth,
            ssl=ssl,
            proxy_headers=proxy_headers,
        )

        try:
            # check handshake
            if resp.status != 101:
                raise WSServerHandshakeError(
                    resp.request_info,
                    resp.history,
                    message="Invalid response status",
                    status=resp.status,
                    headers=resp.headers,
                )

            if resp.headers.get(hdrs.UPGRADE, "").lower() != "websocket":
                raise WSServerHandshakeError(
                    resp.request_info,
                    resp.history,
                    message="Invalid upgrade header",
                    status=resp.status,
                    headers=resp.headers,
                )

            if resp.headers.get(hdrs.CONNECTION, "").lower() != "upgrade":
                raise WSServerHandshakeError(
                    resp.request_info,
                    resp.history,
                    message="Invalid connection header",
                    status=resp.status,
                    headers=resp.headers,
                )

            # key calculation
            r_key = resp.headers.get(hdrs.SEC_WEBSOCKET_ACCEPT, "")
            match = base64.b64encode(hashlib.sha1(sec_key + WS_KEY).digest()).decode()
            if r_key != match:
                raise WSServerHandshakeError(
                    resp.request_info,
                    resp.history,
                    message="Invalid challenge response",
                    status=resp.status,
                    headers=resp.headers,
                )

            # websocket protocol
            protocol = None
            if protocols and hdrs.SEC_WEBSOCKET_PROTOCOL in resp.headers:
                resp_protocols = [
                    proto.strip()
                    for proto in resp.headers[hdrs.SEC_WEBSOCKET_PROTOCOL].split(",")
                ]

                for proto in resp_protocols:
                    if proto in protocols:
                        protocol = proto
                        break

            # websocket compress
            notakeover = False
            if compress:
                compress_hdrs = resp.headers.get(hdrs.SEC_WEBSOCKET_EXTENSIONS)
                if compress_hdrs:
                    try:
                        compress, notakeover = ws_ext_parse(compress_hdrs)
                    except WSHandshakeError as exc:
                        raise WSServerHandshakeError(
                            resp.request_info,
                            resp.history,
                            message=exc.args[0],
                            status=resp.status,
                            headers=resp.headers,
                        ) from exc
                else:
                    compress = 0
                    notakeover = False

            conn = resp.connection
            assert conn is not None
            conn_proto = conn.protocol
            assert conn_proto is not None

            # For WS connection the read_timeout must be either receive_timeout or greater
            # None == no timeout, i.e. infinite timeout, so None is the max timeout possible
            if ws_timeout.ws_receive is None:
                # Reset regardless
                conn_proto.read_timeout = None
            elif conn_proto.read_timeout is not None:
                conn_proto.read_timeout = max(
                    ws_timeout.ws_receive, conn_proto.read_timeout
                )

            transport = conn.transport
            assert transport is not None
            reader: FlowControlDataQueue[WSMessage] = FlowControlDataQueue(
                conn_proto, 2**16, loop=self._loop
            )
            conn_proto.set_parser(WebSocketReader(reader, max_msg_size), reader)
            writer = WebSocketWriter(
                conn_proto,
                transport,
                use_mask=True,
                compress=compress,
                notakeover=notakeover,
            )
        except BaseException:
            resp.close()
            raise
        else:
            return self._ws_response_class(
                reader,
                writer,
                protocol,
                resp,
                ws_timeout,
                autoclose,
                autoping,
                self._loop,
                heartbeat=heartbeat,
                compress=compress,
                client_notakeover=notakeover,
            )

    def _prepare_headers(self, headers: Optional[LooseHeaders]) -> "CIMultiDict[str]":
        """Add default headers and transform it to CIMultiDict"""
        # Convert headers to MultiDict
        result = CIMultiDict(self._default_headers)
        if headers:
            if not isinstance(headers, (MultiDictProxy, MultiDict)):
                headers = CIMultiDict(headers)
            added_names: Set[str] = set()
            for key, value in headers.items():
                if key in added_names:
                    result.add(key, value)
                else:
                    result[key] = value
                    added_names.add(key)
        return result

    if sys.version_info >= (3, 11) and TYPE_CHECKING:

        def get(
            self,
            url: StrOrURL,
            **kwargs: Unpack[_RequestOptions],
        ) -> "_RequestContextManager": ...

        def options(
            self,
            url: StrOrURL,
            **kwargs: Unpack[_RequestOptions],
        ) -> "_RequestContextManager": ...

        def head(
            self,
            url: StrOrURL,
            **kwargs: Unpack[_RequestOptions],
        ) -> "_RequestContextManager": ...

        def post(
            self,
            url: StrOrURL,
            **kwargs: Unpack[_RequestOptions],
        ) -> "_RequestContextManager": ...

        def put(
            self,
            url: StrOrURL,
            **kwargs: Unpack[_RequestOptions],
        ) -> "_RequestContextManager": ...

        def patch(
            self,
            url: StrOrURL,
            **kwargs: Unpack[_RequestOptions],
        ) -> "_RequestContextManager": ...

        def delete(
            self,
            url: StrOrURL,
            **kwargs: Unpack[_RequestOptions],
        ) -> "_RequestContextManager": ...

    else:

        def get(
            self, url: StrOrURL, *, allow_redirects: bool = True, **kwargs: Any
        ) -> "_RequestContextManager":
            """Perform HTTP GET request."""
            return _RequestContextManager(
                self._request(
                    hdrs.METH_GET, url, allow_redirects=allow_redirects, **kwargs
                )
            )

        def options(
            self, url: StrOrURL, *, allow_redirects: bool = True, **kwargs: Any
        ) -> "_RequestContextManager":
            """Perform HTTP OPTIONS request."""
            return _RequestContextManager(
                self._request(
                    hdrs.METH_OPTIONS, url, allow_redirects=allow_redirects, **kwargs
                )
            )

        def head(
            self, url: StrOrURL, *, allow_redirects: bool = False, **kwargs: Any
        ) -> "_RequestContextManager":
            """Perform HTTP HEAD request."""
            return _RequestContextManager(
                self._request(
                    hdrs.METH_HEAD, url, allow_redirects=allow_redirects, **kwargs
                )
            )

        def post(
            self, url: StrOrURL, *, data: Any = None, **kwargs: Any
        ) -> "_RequestContextManager":
            """Perform HTTP POST request."""
            return _RequestContextManager(
                self._request(hdrs.METH_POST, url, data=data, **kwargs)
            )

        def put(
            self, url: StrOrURL, *, data: Any = None, **kwargs: Any
        ) -> "_RequestContextManager":
            """Perform HTTP PUT request."""
            return _RequestContextManager(
                self._request(hdrs.METH_PUT, url, data=data, **kwargs)
            )

        def patch(
            self, url: StrOrURL, *, data: Any = None, **kwargs: Any
        ) -> "_RequestContextManager":
            """Perform HTTP PATCH request."""
            return _RequestContextManager(
                self._request(hdrs.METH_PATCH, url, data=data, **kwargs)
            )

        def delete(self, url: StrOrURL, **kwargs: Any) -> "_RequestContextManager":
            """Perform HTTP DELETE request."""
            return _RequestContextManager(
                self._request(hdrs.METH_DELETE, url, **kwargs)
            )

    async def close(self) -> None:
        """Close underlying connector.

        Release all acquired resources.
        """
        if not self.closed:
            if self._connector is not None and self._connector_owner:
                await self._connector.close()
            self._connector = None

    @property
    def closed(self) -> bool:
        """Is client session closed.

        A readonly property.
        """
        return self._connector is None or self._connector.closed

    @property
    def connector(self) -> Optional[BaseConnector]:
        """Connector instance used for the session."""
        return self._connector

    @property
    def cookie_jar(self) -> AbstractCookieJar:
        """The session cookies."""
        return self._cookie_jar

    @property
    def version(self) -> Tuple[int, int]:
        """The session HTTP protocol version."""
        return self._version

    @property
    def requote_redirect_url(self) -> bool:
        """Do URL requoting on redirection handling."""
        return self._requote_redirect_url

    @requote_redirect_url.setter
    def requote_redirect_url(self, val: bool) -> None:
        """Do URL requoting on redirection handling."""
        warnings.warn(
            "session.requote_redirect_url modification is deprecated #2778",
            DeprecationWarning,
            stacklevel=2,
        )
        self._requote_redirect_url = val

    @property
    def loop(self) -> asyncio.AbstractEventLoop:
        """Session's loop."""
        warnings.warn(
            "client.loop property is deprecated", DeprecationWarning, stacklevel=2
        )
        return self._loop

    @property
    def timeout(self) -> ClientTimeout:
        """Timeout for the session."""
        return self._timeout

    @property
    def headers(self) -> "CIMultiDict[str]":
        """The default headers of the client session."""
        return self._default_headers

    @property
    def skip_auto_headers(self) -> FrozenSet[istr]:
        """Headers for which autogeneration should be skipped"""
        return self._skip_auto_headers

    @property
    def auth(self) -> Optional[BasicAuth]:
        """An object that represents HTTP Basic Authorization"""
        return self._default_auth

    @property
    def json_serialize(self) -> JSONEncoder:
        """Json serializer callable"""
        return self._json_serialize

    @property
    def connector_owner(self) -> bool:
        """Should connector be closed on session closing"""
        return self._connector_owner

    @property
    def raise_for_status(
        self,
    ) -> Union[bool, Callable[[ClientResponse], Awaitable[None]]]:
        """Should `ClientResponse.raise_for_status()` be called for each response."""
        return self._raise_for_status

    @property
    def auto_decompress(self) -> bool:
        """Should the body response be automatically decompressed."""
        return self._auto_decompress

    @property
    def trust_env(self) -> bool:
        """
        Should proxies information from environment or netrc be trusted.

        Information is from HTTP_PROXY / HTTPS_PROXY environment variables
        or ~/.netrc file if present.
        """
        return self._trust_env

    @property
    def trace_configs(self) -> List[TraceConfig]:
        """A list of TraceConfig instances used for client tracing"""
        return self._trace_configs

    def detach(self) -> None:
        """Detach connector from session without closing the former.

        Session is switched to closed state anyway.
        """
        self._connector = None

    def __enter__(self) -> None:
        raise TypeError("Use async with instead")

    def __exit__(
        self,
        exc_type: Optional[Type[BaseException]],
        exc_val: Optional[BaseException],
        exc_tb: Optional[TracebackType],
    ) -> None:
        # __exit__ should exist in pair with __enter__ but never executed
        pass  # pragma: no cover

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

    async def __aexit__(
        self,
        exc_type: Optional[Type[BaseException]],
        exc_val: Optional[BaseException],
        exc_tb: Optional[TracebackType],
    ) -> None:
        await self.close()


class _BaseRequestContextManager(Coroutine[Any, Any, _RetType], Generic[_RetType]):

    __slots__ = ("_coro", "_resp")

    def __init__(self, coro: Coroutine["asyncio.Future[Any]", None, _RetType]) -> None:
        self._coro: Coroutine["asyncio.Future[Any]", None, _RetType] = coro

    def send(self, arg: None) -> "asyncio.Future[Any]":
        return self._coro.send(arg)

    def throw(self, *args: Any, **kwargs: Any) -> "asyncio.Future[Any]":
        return self._coro.throw(*args, **kwargs)

    def close(self) -> None:
        return self._coro.close()

    def __await__(self) -> Generator[Any, None, _RetType]:
        ret = self._coro.__await__()
        return ret

    def __iter__(self) -> Generator[Any, None, _RetType]:
        return self.__await__()

    async def __aenter__(self) -> _RetType:
        self._resp: _RetType = await self._coro
        return await self._resp.__aenter__()

    async def __aexit__(
        self,
        exc_type: Optional[Type[BaseException]],
        exc: Optional[BaseException],
        tb: Optional[TracebackType],
    ) -> None:
        await self._resp.__aexit__(exc_type, exc, tb)


_RequestContextManager = _BaseRequestContextManager[ClientResponse]
_WSRequestContextManager = _BaseRequestContextManager[ClientWebSocketResponse]


class _SessionRequestContextManager:

    __slots__ = ("_coro", "_resp", "_session")

    def __init__(
        self,
        coro: Coroutine["asyncio.Future[Any]", None, ClientResponse],
        session: ClientSession,
    ) -> None:
        self._coro = coro
        self._resp: Optional[ClientResponse] = None
        self._session = session

    async def __aenter__(self) -> ClientResponse:
        try:
            self._resp = await self._coro
        except BaseException:
            await self._session.close()
            raise
        else:
            return self._resp

    async def __aexit__(
        self,
        exc_type: Optional[Type[BaseException]],
        exc: Optional[BaseException],
        tb: Optional[TracebackType],
    ) -> None:
        assert self._resp is not None
        self._resp.close()
        await self._session.close()


def request(
    method: str,
    url: StrOrURL,
    *,
    params: Query = None,
    data: Any = None,
    json: Any = None,
    headers: Optional[LooseHeaders] = None,
    skip_auto_headers: Optional[Iterable[str]] = None,
    auth: Optional[BasicAuth] = None,
    allow_redirects: bool = True,
    max_redirects: int = 10,
    compress: Optional[str] = None,
    chunked: Optional[bool] = None,
    expect100: bool = False,
    raise_for_status: Optional[bool] = None,
    read_until_eof: bool = True,
    proxy: Optional[StrOrURL] = None,
    proxy_auth: Optional[BasicAuth] = None,
    timeout: Union[ClientTimeout, object] = sentinel,
    cookies: Optional[LooseCookies] = None,
    version: HttpVersion = http.HttpVersion11,
    connector: Optional[BaseConnector] = None,
    read_bufsize: Optional[int] = None,
    loop: Optional[asyncio.AbstractEventLoop] = None,
    max_line_size: int = 8190,
    max_field_size: int = 8190,
) -> _SessionRequestContextManager:
    """Constructs and sends a request.

    Returns response object.
    method - HTTP method
    url - request url
    params - (optional) Dictionary or bytes to be sent in the query
      string of the new request
    data - (optional) Dictionary, bytes, or file-like object to
      send in the body of the request
    json - (optional) Any json compatible python object
    headers - (optional) Dictionary of HTTP Headers to send with
      the request
    cookies - (optional) Dict object to send with the request
    auth - (optional) BasicAuth named tuple represent HTTP Basic Auth
    auth - aiohttp.helpers.BasicAuth
    allow_redirects - (optional) If set to False, do not follow
      redirects
    version - Request HTTP version.
    compress - Set to True if request has to be compressed
       with deflate encoding.
    chunked - Set to chunk size for chunked transfer encoding.
    expect100 - Expect 100-continue response from server.
    connector - BaseConnector sub-class instance to support
       connection pooling.
    read_until_eof - Read response until eof if response
       does not have Content-Length header.
    loop - Optional event loop.
    timeout - Optional ClientTimeout settings structure, 5min
       total timeout by default.
    Usage::
      >>> import aiohttp
      >>> resp = await aiohttp.request('GET', 'http://python.org/')
      >>> resp
      <ClientResponse(python.org/) [200]>
      >>> data = await resp.read()
    """
    connector_owner = False
    if connector is None:
        connector_owner = True
        connector = TCPConnector(loop=loop, force_close=True)

    session = ClientSession(
        loop=loop,
        cookies=cookies,
        version=version,
        timeout=timeout,
        connector=connector,
        connector_owner=connector_owner,
    )

    return _SessionRequestContextManager(
        session._request(
            method,
            url,
            params=params,
            data=data,
            json=json,
            headers=headers,
            skip_auto_headers=skip_auto_headers,
            auth=auth,
            allow_redirects=allow_redirects,
            max_redirects=max_redirects,
            compress=compress,
            chunked=chunked,
            expect100=expect100,
            raise_for_status=raise_for_status,
            read_until_eof=read_until_eof,
            proxy=proxy,
            proxy_auth=proxy_auth,
            read_bufsize=read_bufsize,
            max_line_size=max_line_size,
            max_field_size=max_field_size,
        ),
        session,
    )

```
--- 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:** ClientSession initialization fails with unexpected 'proxy' and 'proxy_auth' arguments

**Description:**
When attempting to initialize `ClientSession` with `proxy` and `proxy_auth` parameters, a `TypeError` is raised indicating that these arguments are unexpected.

**Example Code:**
```python
from aiohttp import ClientSession
from yarl import URL

proxy_url = URL("http://proxy.example.com")
proxy_auth = None  # Replace with appropriate authentication if needed

session = ClientSession(proxy=proxy_url, proxy_auth=proxy_auth)
```

**Expected Behavior:**
`ClientSession` should accept `proxy` and `proxy_auth` as valid initialization arguments, allowing users to set default proxy settings for all requests made through the session.

**Actual Behavior:**
Initializing `ClientSession` with the `proxy` argument results in the following error:
```
TypeError: __init__() got an unexpected keyword argument 'proxy'
```

[/ISSUE]
{
    "test_close_coro[pyloop]": "PASSED",
    "test_init_headers_simple_dict[pyloop]": "PASSED",
    "test_init_headers_list_of_tuples[pyloop]": "PASSED",
    "test_init_headers_MultiDict[pyloop]": "PASSED",
    "test_init_headers_list_of_tuples_with_duplicates[pyloop]": "PASSED",
    "test_init_cookies_with_simple_dict[pyloop]": "PASSED",
    "test_init_cookies_with_list_of_tuples[pyloop]": "PASSED",
    "test_merge_headers[pyloop]": "PASSED",
    "test_merge_headers_with_multi_dict[pyloop]": "PASSED",
    "test_merge_headers_with_list_of_tuples[pyloop]": "PASSED",
    "test_merge_headers_with_list_of_tuples_duplicated_names[pyloop]": "PASSED",
    "test_http_GET[pyloop]": "PASSED",
    "test_http_OPTIONS[pyloop]": "PASSED",
    "test_http_HEAD[pyloop]": "PASSED",
    "test_http_POST[pyloop]": "PASSED",
    "test_http_PUT[pyloop]": "PASSED",
    "test_http_PATCH[pyloop]": "PASSED",
    "test_http_DELETE[pyloop]": "PASSED",
    "test_close[pyloop]": "PASSED",
    "test_closed[pyloop]": "PASSED",
    "test_connector[pyloop]": "PASSED",
    "test_create_connector[pyloop]": "PASSED",
    "test_connector_loop[pyloop]": "PASSED",
    "test_detach[pyloop]": "PASSED",
    "test_request_closed_session[pyloop]": "PASSED",
    "test_close_flag_for_closed_connector[pyloop]": "PASSED",
    "test_double_close[pyloop]": "PASSED",
    "test_del[pyloop]": "PASSED",
    "test_del_debug[pyloop]": "PASSED",
    "test_session_context_manager[pyloop]": "PASSED",
    "test_borrow_connector_loop[pyloop]": "PASSED",
    "test_reraise_os_error[pyloop]": "PASSED",
    "test_close_conn_on_error[pyloop]": "PASSED",
    "test_ws_connect_allowed_protocols[pyloop-http]": "PASSED",
    "test_ws_connect_allowed_protocols[pyloop-https]": "PASSED",
    "test_ws_connect_allowed_protocols[pyloop-ws]": "PASSED",
    "test_ws_connect_allowed_protocols[pyloop-wss]": "PASSED",
    "test_ws_connect_unix_socket_allowed_protocols[pyloop-http]": "PASSED",
    "test_ws_connect_unix_socket_allowed_protocols[pyloop-https]": "PASSED",
    "test_ws_connect_unix_socket_allowed_protocols[pyloop-ws]": "PASSED",
    "test_ws_connect_unix_socket_allowed_protocols[pyloop-wss]": "PASSED",
    "test_ws_connect_unix_socket_allowed_protocols[pyloop-unix]": "PASSED",
    "test_cookie_jar_usage[pyloop]": "PASSED",
    "test_session_default_version[pyloop]": "PASSED",
    "test_session_loop[pyloop]": "PASSED",
    "test_proxy_str[pyloop]": "PASSED",
    "test_default_proxy[pyloop]": "PASSED",
    "test_request_tracing[pyloop]": "PASSED",
    "test_request_tracing_url_params[pyloop]": "PASSED",
    "test_request_tracing_exception": "PASSED",
    "test_request_tracing_interpose_headers[pyloop]": "PASSED",
    "test_client_session_inheritance": "PASSED",
    "test_client_session_timeout_args[pyloop]": "PASSED",
    "test_client_session_timeout_default_args[pyloop]": "PASSED",
    "test_client_session_timeout_zero[pyloop]": "PASSED",
    "test_client_session_timeout_bad_argument": "PASSED",
    "test_requote_redirect_url_default": "PASSED",
    "test_requote_redirect_url_default_disable": "PASSED",
    "test_requote_redirect_setter": "PASSED",
    "test_build_url_returns_expected_url[pyloop-base_url=None url='http://example.com/test']": "PASSED",
    "test_build_url_returns_expected_url[pyloop-base_url=None url=URL('http://example.com/test')]": "PASSED",
    "test_build_url_returns_expected_url[pyloop-base_url='http://example.com' url='/test']": "PASSED",
    "test_build_url_returns_expected_url[pyloop-base_url=URL('http://example.com') url='/test']": "PASSED",
    "test_instantiation_with_invalid_timeout_value[pyloop]": "PASSED",
    "test_properties[pyloop-skip_auto_headers-_skip_auto_headers]": "PASSED",
    "test_properties[pyloop-auth-_default_auth]": "PASSED",
    "test_properties[pyloop-json_serialize-_json_serialize]": "PASSED",
    "test_properties[pyloop-connector_owner-_connector_owner]": "PASSED",
    "test_properties[pyloop-raise_for_status-_raise_for_status]": "PASSED",
    "test_properties[pyloop-trust_env-_trust_env]": "PASSED",
    "test_properties[pyloop-trace_configs-_trace_configs]": "PASSED"
}
diff --git a/aiohttp/client.py b/aiohttp/client.py
index 6c129c3a..a5c57bb2 100644
--- a/aiohttp/client.py
+++ b/aiohttp/client.py
@@ -252,6 +252,8 @@ class ClientSession:
             "_max_line_size",
             "_max_field_size",
             "_resolve_charset",
+            "_default_proxy",
+            "_default_proxy_auth",
         ]
     )
 
@@ -266,6 +268,8 @@ class ClientSession:
         loop: Optional[asyncio.AbstractEventLoop] = None,
         cookies: Optional[LooseCookies] = None,
         headers: Optional[LooseHeaders] = None,
+        proxy: Optional[StrOrURL] = None,
+        proxy_auth: Optional[BasicAuth] = None,
         skip_auto_headers: Optional[Iterable[str]] = None,
         auth: Optional[BasicAuth] = None,
         json_serialize: JSONEncoder = json.dumps,
@@ -396,6 +400,9 @@ class ClientSession:
 
         self._resolve_charset = fallback_charset_resolver
 
+        self._default_proxy = proxy
+        self._default_proxy_auth = proxy_auth
+
     def __init_subclass__(cls: Type["ClientSession"]) -> None:
         warnings.warn(
             "Inheritance class {} from ClientSession "
@@ -530,6 +537,11 @@ class ClientSession:
             for i in skip_auto_headers:
                 skip_headers.add(istr(i))
 
+        if proxy is None:
+            proxy = self._default_proxy
+        if proxy_auth is None:
+            proxy_auth = self._default_proxy_auth
+
         if proxy is None:
             proxy_headers = None
         else:

{"aiohttp/client.py": "\"\"\"HTTP Client for asyncio.\"\"\"\n\nimport asyncio\nimport base64\nimport hashlib\nimport json\nimport os\nimport sys\nimport traceback\nimport warnings\nfrom contextlib import suppress\nfrom types import TracebackType\nfrom typing import (\n    TYPE_CHECKING,\n    Any,\n    Awaitable,\n    Callable,\n    Coroutine,\n    Final,\n    FrozenSet,\n    Generator,\n    Generic,\n    Iterable,\n    List,\n    Mapping,\n    Optional,\n    Set,\n    Tuple,\n    Type,\n    TypedDict,\n    TypeVar,\n    Union,\n)\n\nimport attr\nfrom multidict import CIMultiDict, MultiDict, MultiDictProxy, istr\nfrom yarl import URL\n\nfrom . import hdrs, http, payload\nfrom .abc import AbstractCookieJar\nfrom .client_exceptions import (\n    ClientConnectionError,\n    ClientConnectionResetError,\n    ClientConnectorCertificateError,\n    ClientConnectorError,\n    ClientConnectorSSLError,\n    ClientError,\n    ClientHttpProxyError,\n    ClientOSError,\n    ClientPayloadError,\n    ClientProxyConnectionError,\n    ClientResponseError,\n    ClientSSLError,\n    ConnectionTimeoutError,\n    ContentTypeError,\n    InvalidURL,\n    InvalidUrlClientError,\n    InvalidUrlRedirectClientError,\n    NonHttpUrlClientError,\n    NonHttpUrlRedirectClientError,\n    RedirectClientError,\n    ServerConnectionError,\n    ServerDisconnectedError,\n    ServerFingerprintMismatch,\n    ServerTimeoutError,\n    SocketTimeoutError,\n    TooManyRedirects,\n    WSServerHandshakeError,\n)\nfrom .client_reqrep import (\n    ClientRequest as ClientRequest,\n    ClientResponse as ClientResponse,\n    Fingerprint as Fingerprint,\n    RequestInfo as RequestInfo,\n    _merge_ssl_params,\n)\nfrom .client_ws import (\n    DEFAULT_WS_CLIENT_TIMEOUT,\n    ClientWebSocketResponse as ClientWebSocketResponse,\n    ClientWSTimeout as ClientWSTimeout,\n)\nfrom .connector import (\n    HTTP_AND_EMPTY_SCHEMA_SET,\n    BaseConnector as BaseConnector,\n    NamedPipeConnector as NamedPipeConnector,\n    TCPConnector as TCPConnector,\n    UnixConnector as UnixConnector,\n)\nfrom .cookiejar import CookieJar\nfrom .helpers import (\n    _SENTINEL,\n    DEBUG,\n    BasicAuth,\n    TimeoutHandle,\n    ceil_timeout,\n    get_env_proxy_for_url,\n    method_must_be_empty_body,\n    sentinel,\n    strip_auth_from_url,\n)\nfrom .http import WS_KEY, HttpVersion, WebSocketReader, WebSocketWriter\nfrom .http_websocket import WSHandshakeError, WSMessage, ws_ext_gen, ws_ext_parse\nfrom .streams import FlowControlDataQueue\nfrom .tracing import Trace, TraceConfig\nfrom .typedefs import JSONEncoder, LooseCookies, LooseHeaders, Query, StrOrURL\n\n__all__ = (\n    # client_exceptions\n    \"ClientConnectionError\",\n    \"ClientConnectionResetError\",\n    \"ClientConnectorCertificateError\",\n    \"ClientConnectorError\",\n    \"ClientConnectorSSLError\",\n    \"ClientError\",\n    \"ClientHttpProxyError\",\n    \"ClientOSError\",\n    \"ClientPayloadError\",\n    \"ClientProxyConnectionError\",\n    \"ClientResponseError\",\n    \"ClientSSLError\",\n    \"ConnectionTimeoutError\",\n    \"ContentTypeError\",\n    \"InvalidURL\",\n    \"InvalidUrlClientError\",\n    \"RedirectClientError\",\n    \"NonHttpUrlClientError\",\n    \"InvalidUrlRedirectClientError\",\n    \"NonHttpUrlRedirectClientError\",\n    \"ServerConnectionError\",\n    \"ServerDisconnectedError\",\n    \"ServerFingerprintMismatch\",\n    \"ServerTimeoutError\",\n    \"SocketTimeoutError\",\n    \"TooManyRedirects\",\n    \"WSServerHandshakeError\",\n    # client_reqrep\n    \"ClientRequest\",\n    \"ClientResponse\",\n    \"Fingerprint\",\n    \"RequestInfo\",\n    # connector\n    \"BaseConnector\",\n    \"TCPConnector\",\n    \"UnixConnector\",\n    \"NamedPipeConnector\",\n    # client_ws\n    \"ClientWebSocketResponse\",\n    # client\n    \"ClientSession\",\n    \"ClientTimeout\",\n    \"ClientWSTimeout\",\n    \"request\",\n)\n\n\nif TYPE_CHECKING:\n    from ssl import SSLContext\nelse:\n    SSLContext = None\n\nif sys.version_info >= (3, 11) and TYPE_CHECKING:\n    from typing import Unpack\n\n\nclass _RequestOptions(TypedDict, total=False):\n    params: Query\n    data: Any\n    json: Any\n    cookies: Union[LooseCookies, None]\n    headers: Union[LooseHeaders, None]\n    skip_auto_headers: Union[Iterable[str], None]\n    auth: Union[BasicAuth, None]\n    allow_redirects: bool\n    max_redirects: int\n    compress: Union[str, bool, None]\n    chunked: Union[bool, None]\n    expect100: bool\n    raise_for_status: Union[None, bool, Callable[[ClientResponse], Awaitable[None]]]\n    read_until_eof: bool\n    proxy: Union[StrOrURL, None]\n    proxy_auth: Union[BasicAuth, None]\n    timeout: \"Union[ClientTimeout, _SENTINEL, None]\"\n    ssl: Union[SSLContext, bool, Fingerprint]\n    server_hostname: Union[str, None]\n    proxy_headers: Union[LooseHeaders, None]\n    trace_request_ctx: Union[Mapping[str, str], None]\n    read_bufsize: Union[int, None]\n    auto_decompress: Union[bool, None]\n    max_line_size: Union[int, None]\n    max_field_size: Union[int, None]\n\n\n@attr.s(auto_attribs=True, frozen=True, slots=True)\nclass ClientTimeout:\n    total: Optional[float] = None\n    connect: Optional[float] = None\n    sock_read: Optional[float] = None\n    sock_connect: Optional[float] = None\n    ceil_threshold: float = 5\n\n    # pool_queue_timeout: Optional[float] = None\n    # dns_resolution_timeout: Optional[float] = None\n    # socket_connect_timeout: Optional[float] = None\n    # connection_acquiring_timeout: Optional[float] = None\n    # new_connection_timeout: Optional[float] = None\n    # http_header_timeout: Optional[float] = None\n    # response_body_timeout: Optional[float] = None\n\n    # to create a timeout specific for a single request, either\n    # - create a completely new one to overwrite the default\n    # - or use http://www.attrs.org/en/stable/api.html#attr.evolve\n    # to overwrite the defaults\n\n\n# 5 Minute default read timeout\nDEFAULT_TIMEOUT: Final[ClientTimeout] = ClientTimeout(total=5 * 60)\n\n# https://www.rfc-editor.org/rfc/rfc9110#section-9.2.2\nIDEMPOTENT_METHODS = frozenset({\"GET\", \"HEAD\", \"OPTIONS\", \"TRACE\", \"PUT\", \"DELETE\"})\n\n_RetType = TypeVar(\"_RetType\", ClientResponse, ClientWebSocketResponse)\n_CharsetResolver = Callable[[ClientResponse, bytes], str]\n\n\nclass ClientSession:\n    \"\"\"First-class interface for making HTTP requests.\"\"\"\n\n    ATTRS = frozenset(\n        [\n            \"_base_url\",\n            \"_source_traceback\",\n            \"_connector\",\n            \"requote_redirect_url\",\n            \"_loop\",\n            \"_cookie_jar\",\n            \"_connector_owner\",\n            \"_default_auth\",\n            \"_version\",\n            \"_json_serialize\",\n            \"_requote_redirect_url\",\n            \"_timeout\",\n            \"_raise_for_status\",\n            \"_auto_decompress\",\n            \"_trust_env\",\n            \"_default_headers\",\n            \"_skip_auto_headers\",\n            \"_request_class\",\n            \"_response_class\",\n            \"_ws_response_class\",\n            \"_trace_configs\",\n            \"_read_bufsize\",\n            \"_max_line_size\",\n            \"_max_field_size\",\n            \"_resolve_charset\",\n        ]\n    )\n\n    _source_traceback: Optional[traceback.StackSummary] = None\n    _connector: Optional[BaseConnector] = None\n\n    def __init__(\n        self,\n        base_url: Optional[StrOrURL] = None,\n        *,\n        connector: Optional[BaseConnector] = None,\n        loop: Optional[asyncio.AbstractEventLoop] = None,\n        cookies: Optional[LooseCookies] = None,\n        headers: Optional[LooseHeaders] = None,\n        skip_auto_headers: Optional[Iterable[str]] = None,\n        auth: Optional[BasicAuth] = None,\n        json_serialize: JSONEncoder = json.dumps,\n        request_class: Type[ClientRequest] = ClientRequest,\n        response_class: Type[ClientResponse] = ClientResponse,\n        ws_response_class: Type[ClientWebSocketResponse] = ClientWebSocketResponse,\n        version: HttpVersion = http.HttpVersion11,\n        cookie_jar: Optional[AbstractCookieJar] = None,\n        connector_owner: bool = True,\n        raise_for_status: Union[\n            bool, Callable[[ClientResponse], Awaitable[None]]\n        ] = False,\n        read_timeout: Union[float, _SENTINEL] = sentinel,\n        conn_timeout: Optional[float] = None,\n        timeout: Union[object, ClientTimeout] = sentinel,\n        auto_decompress: bool = True,\n        trust_env: bool = False,\n        requote_redirect_url: bool = True,\n        trace_configs: Optional[List[TraceConfig]] = None,\n        read_bufsize: int = 2**16,\n        max_line_size: int = 8190,\n        max_field_size: int = 8190,\n        fallback_charset_resolver: _CharsetResolver = lambda r, b: \"utf-8\",\n    ) -> None:\n        # We initialise _connector to None immediately, as it's referenced in __del__()\n        # and could cause issues if an exception occurs during initialisation.\n        self._connector: Optional[BaseConnector] = None\n\n        if loop is None:\n            if connector is not None:\n                loop = connector._loop\n\n        loop = loop or asyncio.get_running_loop()\n\n        if base_url is None or isinstance(base_url, URL):\n            self._base_url: Optional[URL] = base_url\n        else:\n            self._base_url = URL(base_url)\n            assert (\n                self._base_url.origin() == self._base_url\n            ), \"Only absolute URLs without path part are supported\"\n\n        if timeout is sentinel or timeout is None:\n            self._timeout = DEFAULT_TIMEOUT\n            if read_timeout is not sentinel:\n                warnings.warn(\n                    \"read_timeout is deprecated, use timeout argument instead\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n                self._timeout = attr.evolve(self._timeout, total=read_timeout)\n            if conn_timeout is not None:\n                self._timeout = attr.evolve(self._timeout, connect=conn_timeout)\n                warnings.warn(\n                    \"conn_timeout is deprecated, use timeout argument instead\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n        else:\n            if not isinstance(timeout, ClientTimeout):\n                raise ValueError(\n                    f\"timeout parameter cannot be of {type(timeout)} type, \"\n                    \"please use 'timeout=ClientTimeout(...)'\",\n                )\n            self._timeout = timeout\n            if read_timeout is not sentinel:\n                raise ValueError(\n                    \"read_timeout and timeout parameters \"\n                    \"conflict, please setup \"\n                    \"timeout.read\"\n                )\n            if conn_timeout is not None:\n                raise ValueError(\n                    \"conn_timeout and timeout parameters \"\n                    \"conflict, please setup \"\n                    \"timeout.connect\"\n                )\n\n        if connector is None:\n            connector = TCPConnector(loop=loop)\n\n        if connector._loop is not loop:\n            raise RuntimeError(\"Session and connector has to use same event loop\")\n\n        self._loop = loop\n\n        if loop.get_debug():\n            self._source_traceback = traceback.extract_stack(sys._getframe(1))\n\n        if cookie_jar is None:\n            cookie_jar = CookieJar(loop=loop)\n        self._cookie_jar = cookie_jar\n\n        if cookies is not None:\n            self._cookie_jar.update_cookies(cookies)\n\n        self._connector = connector\n        self._connector_owner = connector_owner\n        self._default_auth = auth\n        self._version = version\n        self._json_serialize = json_serialize\n        self._raise_for_status = raise_for_status\n        self._auto_decompress = auto_decompress\n        self._trust_env = trust_env\n        self._requote_redirect_url = requote_redirect_url\n        self._read_bufsize = read_bufsize\n        self._max_line_size = max_line_size\n        self._max_field_size = max_field_size\n\n        # Convert to list of tuples\n        if headers:\n            real_headers: CIMultiDict[str] = CIMultiDict(headers)\n        else:\n            real_headers = CIMultiDict()\n        self._default_headers: CIMultiDict[str] = real_headers\n        if skip_auto_headers is not None:\n            self._skip_auto_headers = frozenset(istr(i) for i in skip_auto_headers)\n        else:\n            self._skip_auto_headers = frozenset()\n\n        self._request_class = request_class\n        self._response_class = response_class\n        self._ws_response_class = ws_response_class\n\n        self._trace_configs = trace_configs or []\n        for trace_config in self._trace_configs:\n            trace_config.freeze()\n\n        self._resolve_charset = fallback_charset_resolver\n\n    def __init_subclass__(cls: Type[\"ClientSession\"]) -> None:\n        warnings.warn(\n            \"Inheritance class {} from ClientSession \"\n            \"is discouraged\".format(cls.__name__),\n            DeprecationWarning,\n            stacklevel=2,\n        )\n\n    if DEBUG:\n\n        def __setattr__(self, name: str, val: Any) -> None:\n            if name not in self.ATTRS:\n                warnings.warn(\n                    \"Setting custom ClientSession.{} attribute \"\n                    \"is discouraged\".format(name),\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n            super().__setattr__(name, val)\n\n    def __del__(self, _warnings: Any = warnings) -> None:\n        if not self.closed:\n            kwargs = {\"source\": self}\n            _warnings.warn(\n                f\"Unclosed client session {self!r}\", ResourceWarning, **kwargs\n            )\n            context = {\"client_session\": self, \"message\": \"Unclosed client session\"}\n            if self._source_traceback is not None:\n                context[\"source_traceback\"] = self._source_traceback\n            self._loop.call_exception_handler(context)\n\n    if sys.version_info >= (3, 11) and TYPE_CHECKING:\n\n        def request(\n            self,\n            method: str,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n    else:\n\n        def request(\n            self, method: str, url: StrOrURL, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP request.\"\"\"\n            return _RequestContextManager(self._request(method, url, **kwargs))\n\n    def _build_url(self, str_or_url: StrOrURL) -> URL:\n        url = URL(str_or_url)\n        if self._base_url is None:\n            return url\n        else:\n            assert not url.absolute and url.path.startswith(\"/\")\n            return self._base_url.join(url)\n\n    async def _request(\n        self,\n        method: str,\n        str_or_url: StrOrURL,\n        *,\n        params: Query = None,\n        data: Any = None,\n        json: Any = None,\n        cookies: Optional[LooseCookies] = None,\n        headers: Optional[LooseHeaders] = None,\n        skip_auto_headers: Optional[Iterable[str]] = None,\n        auth: Optional[BasicAuth] = None,\n        allow_redirects: bool = True,\n        max_redirects: int = 10,\n        compress: Union[str, bool, None] = None,\n        chunked: Optional[bool] = None,\n        expect100: bool = False,\n        raise_for_status: Union[\n            None, bool, Callable[[ClientResponse], Awaitable[None]]\n        ] = None,\n        read_until_eof: bool = True,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        timeout: Union[ClientTimeout, _SENTINEL] = sentinel,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        server_hostname: Optional[str] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        trace_request_ctx: Optional[Mapping[str, str]] = None,\n        read_bufsize: Optional[int] = None,\n        auto_decompress: Optional[bool] = None,\n        max_line_size: Optional[int] = None,\n        max_field_size: Optional[int] = None,\n    ) -> ClientResponse:\n\n        # NOTE: timeout clamps existing connect and read timeouts.  We cannot\n        # set the default to None because we need to detect if the user wants\n        # to use the existing timeouts by setting timeout to None.\n\n        if self.closed:\n            raise RuntimeError(\"Session is closed\")\n\n        ssl = _merge_ssl_params(ssl, verify_ssl, ssl_context, fingerprint)\n\n        if data is not None and json is not None:\n            raise ValueError(\n                \"data and json parameters can not be used at the same time\"\n            )\n        elif json is not None:\n            data = payload.JsonPayload(json, dumps=self._json_serialize)\n\n        if not isinstance(chunked, bool) and chunked is not None:\n            warnings.warn(\"Chunk size is deprecated #1615\", DeprecationWarning)\n\n        redirects = 0\n        history = []\n        version = self._version\n        params = params or {}\n\n        # Merge with default headers and transform to CIMultiDict\n        headers = self._prepare_headers(headers)\n\n        try:\n            url = self._build_url(str_or_url)\n        except ValueError as e:\n            raise InvalidUrlClientError(str_or_url) from e\n\n        assert self._connector is not None\n        if url.scheme not in self._connector.allowed_protocol_schema_set:\n            raise NonHttpUrlClientError(url)\n\n        skip_headers = set(self._skip_auto_headers)\n        if skip_auto_headers is not None:\n            for i in skip_auto_headers:\n                skip_headers.add(istr(i))\n\n        if proxy is None:\n            proxy_headers = None\n        else:\n            proxy_headers = self._prepare_headers(proxy_headers)\n            try:\n                proxy = URL(proxy)\n            except ValueError as e:\n                raise InvalidURL(proxy) from e\n\n        if timeout is sentinel:\n            real_timeout: ClientTimeout = self._timeout\n        else:\n            if not isinstance(timeout, ClientTimeout):\n                real_timeout = ClientTimeout(total=timeout)\n            else:\n                real_timeout = timeout\n        # timeout is cumulative for all request operations\n        # (request, redirects, responses, data consuming)\n        tm = TimeoutHandle(\n            self._loop, real_timeout.total, ceil_threshold=real_timeout.ceil_threshold\n        )\n        handle = tm.start()\n\n        if read_bufsize is None:\n            read_bufsize = self._read_bufsize\n\n        if auto_decompress is None:\n            auto_decompress = self._auto_decompress\n\n        if max_line_size is None:\n            max_line_size = self._max_line_size\n\n        if max_field_size is None:\n            max_field_size = self._max_field_size\n\n        traces = [\n            Trace(\n                self,\n                trace_config,\n                trace_config.trace_config_ctx(trace_request_ctx=trace_request_ctx),\n            )\n            for trace_config in self._trace_configs\n        ]\n\n        for trace in traces:\n            await trace.send_request_start(method, url.update_query(params), headers)\n\n        timer = tm.timer()\n        try:\n            with timer:\n                # https://www.rfc-editor.org/rfc/rfc9112.html#name-retrying-requests\n                retry_persistent_connection = method in IDEMPOTENT_METHODS\n                while True:\n                    url, auth_from_url = strip_auth_from_url(url)\n                    if not url.raw_host:\n                        # NOTE: Bail early, otherwise, causes `InvalidURL` through\n                        # NOTE: `self._request_class()` below.\n                        err_exc_cls = (\n                            InvalidUrlRedirectClientError\n                            if redirects\n                            else InvalidUrlClientError\n                        )\n                        raise err_exc_cls(url)\n                    if auth and auth_from_url:\n                        raise ValueError(\n                            \"Cannot combine AUTH argument with \"\n                            \"credentials encoded in URL\"\n                        )\n\n                    if auth is None:\n                        auth = auth_from_url\n\n                    if auth is None and (\n                        not self._base_url or self._base_url.origin() == url.origin()\n                    ):\n                        auth = self._default_auth\n                    # It would be confusing if we support explicit\n                    # Authorization header with auth argument\n                    if (\n                        headers is not None\n                        and auth is not None\n                        and hdrs.AUTHORIZATION in headers\n                    ):\n                        raise ValueError(\n                            \"Cannot combine AUTHORIZATION header \"\n                            \"with AUTH argument or credentials \"\n                            \"encoded in URL\"\n                        )\n\n                    all_cookies = self._cookie_jar.filter_cookies(url)\n\n                    if cookies is not None:\n                        tmp_cookie_jar = CookieJar()\n                        tmp_cookie_jar.update_cookies(cookies)\n                        req_cookies = tmp_cookie_jar.filter_cookies(url)\n                        if req_cookies:\n                            all_cookies.load(req_cookies)\n\n                    if proxy is not None:\n                        proxy = URL(proxy)\n                    elif self._trust_env:\n                        with suppress(LookupError):\n                            proxy, proxy_auth = get_env_proxy_for_url(url)\n\n                    req = self._request_class(\n                        method,\n                        url,\n                        params=params,\n                        headers=headers,\n                        skip_auto_headers=skip_headers if skip_headers else None,\n                        data=data,\n                        cookies=all_cookies,\n                        auth=auth,\n                        version=version,\n                        compress=compress,\n                        chunked=chunked,\n                        expect100=expect100,\n                        loop=self._loop,\n                        response_class=self._response_class,\n                        proxy=proxy,\n                        proxy_auth=proxy_auth,\n                        timer=timer,\n                        session=self,\n                        ssl=ssl if ssl is not None else True,\n                        server_hostname=server_hostname,\n                        proxy_headers=proxy_headers,\n                        traces=traces,\n                        trust_env=self.trust_env,\n                    )\n\n                    # connection timeout\n                    try:\n                        async with ceil_timeout(\n                            real_timeout.connect,\n                            ceil_threshold=real_timeout.ceil_threshold,\n                        ):\n                            conn = await self._connector.connect(\n                                req, traces=traces, timeout=real_timeout\n                            )\n                    except asyncio.TimeoutError as exc:\n                        raise ConnectionTimeoutError(\n                            f\"Connection timeout to host {url}\"\n                        ) from exc\n\n                    assert conn.transport is not None\n\n                    assert conn.protocol is not None\n                    conn.protocol.set_response_params(\n                        timer=timer,\n                        skip_payload=method_must_be_empty_body(method),\n                        read_until_eof=read_until_eof,\n                        auto_decompress=auto_decompress,\n                        read_timeout=real_timeout.sock_read,\n                        read_bufsize=read_bufsize,\n                        timeout_ceil_threshold=self._connector._timeout_ceil_threshold,\n                        max_line_size=max_line_size,\n                        max_field_size=max_field_size,\n                    )\n\n                    try:\n                        try:\n                            resp = await req.send(conn)\n                            try:\n                                await resp.start(conn)\n                            except BaseException:\n                                resp.close()\n                                raise\n                        except BaseException:\n                            conn.close()\n                            raise\n                    except (ClientOSError, ServerDisconnectedError):\n                        if retry_persistent_connection:\n                            retry_persistent_connection = False\n                            continue\n                        raise\n                    except ClientError:\n                        raise\n                    except OSError as exc:\n                        if exc.errno is None and isinstance(exc, asyncio.TimeoutError):\n                            raise\n                        raise ClientOSError(*exc.args) from exc\n\n                    self._cookie_jar.update_cookies(resp.cookies, resp.url)\n\n                    # redirects\n                    if resp.status in (301, 302, 303, 307, 308) and allow_redirects:\n\n                        for trace in traces:\n                            await trace.send_request_redirect(\n                                method, url.update_query(params), headers, resp\n                            )\n\n                        redirects += 1\n                        history.append(resp)\n                        if max_redirects and redirects >= max_redirects:\n                            resp.close()\n                            raise TooManyRedirects(\n                                history[0].request_info, tuple(history)\n                            )\n\n                        # For 301 and 302, mimic IE, now changed in RFC\n                        # https://github.com/kennethreitz/requests/pull/269\n                        if (resp.status == 303 and resp.method != hdrs.METH_HEAD) or (\n                            resp.status in (301, 302) and resp.method == hdrs.METH_POST\n                        ):\n                            method = hdrs.METH_GET\n                            data = None\n                            if headers.get(hdrs.CONTENT_LENGTH):\n                                headers.pop(hdrs.CONTENT_LENGTH)\n\n                        r_url = resp.headers.get(hdrs.LOCATION) or resp.headers.get(\n                            hdrs.URI\n                        )\n                        if r_url is None:\n                            # see github.com/aio-libs/aiohttp/issues/2022\n                            break\n                        else:\n                            # reading from correct redirection\n                            # response is forbidden\n                            resp.release()\n\n                        try:\n                            parsed_redirect_url = URL(\n                                r_url, encoded=not self._requote_redirect_url\n                            )\n                        except ValueError as e:\n                            raise InvalidUrlRedirectClientError(\n                                r_url,\n                                \"Server attempted redirecting to a location that does not look like a URL\",\n                            ) from e\n\n                        scheme = parsed_redirect_url.scheme\n                        if scheme not in HTTP_AND_EMPTY_SCHEMA_SET:\n                            resp.close()\n                            raise NonHttpUrlRedirectClientError(r_url)\n                        elif not scheme:\n                            parsed_redirect_url = url.join(parsed_redirect_url)\n\n                        try:\n                            redirect_origin = parsed_redirect_url.origin()\n                        except ValueError as origin_val_err:\n                            raise InvalidUrlRedirectClientError(\n                                parsed_redirect_url,\n                                \"Invalid redirect URL origin\",\n                            ) from origin_val_err\n\n                        if url.origin() != redirect_origin:\n                            auth = None\n                            headers.pop(hdrs.AUTHORIZATION, None)\n\n                        url = parsed_redirect_url\n                        params = {}\n                        resp.release()\n                        continue\n\n                    break\n\n            # check response status\n            if raise_for_status is None:\n                raise_for_status = self._raise_for_status\n\n            if raise_for_status is None:\n                pass\n            elif callable(raise_for_status):\n                await raise_for_status(resp)\n            elif raise_for_status:\n                resp.raise_for_status()\n\n            # register connection\n            if handle is not None:\n                if resp.connection is not None:\n                    resp.connection.add_callback(handle.cancel)\n                else:\n                    handle.cancel()\n\n            resp._history = tuple(history)\n\n            for trace in traces:\n                await trace.send_request_end(\n                    method, url.update_query(params), headers, resp\n                )\n            return resp\n\n        except BaseException as e:\n            # cleanup timer\n            tm.close()\n            if handle:\n                handle.cancel()\n                handle = None\n\n            for trace in traces:\n                await trace.send_request_exception(\n                    method, url.update_query(params), headers, e\n                )\n            raise\n\n    def ws_connect(\n        self,\n        url: StrOrURL,\n        *,\n        method: str = hdrs.METH_GET,\n        protocols: Iterable[str] = (),\n        timeout: Union[ClientWSTimeout, _SENTINEL] = sentinel,\n        receive_timeout: Optional[float] = None,\n        autoclose: bool = True,\n        autoping: bool = True,\n        heartbeat: Optional[float] = None,\n        auth: Optional[BasicAuth] = None,\n        origin: Optional[str] = None,\n        params: Query = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        compress: int = 0,\n        max_msg_size: int = 4 * 1024 * 1024,\n    ) -> \"_WSRequestContextManager\":\n        \"\"\"Initiate websocket connection.\"\"\"\n        return _WSRequestContextManager(\n            self._ws_connect(\n                url,\n                method=method,\n                protocols=protocols,\n                timeout=timeout,\n                receive_timeout=receive_timeout,\n                autoclose=autoclose,\n                autoping=autoping,\n                heartbeat=heartbeat,\n                auth=auth,\n                origin=origin,\n                params=params,\n                headers=headers,\n                proxy=proxy,\n                proxy_auth=proxy_auth,\n                ssl=ssl,\n                verify_ssl=verify_ssl,\n                fingerprint=fingerprint,\n                ssl_context=ssl_context,\n                proxy_headers=proxy_headers,\n                compress=compress,\n                max_msg_size=max_msg_size,\n            )\n        )\n\n    async def _ws_connect(\n        self,\n        url: StrOrURL,\n        *,\n        method: str = hdrs.METH_GET,\n        protocols: Iterable[str] = (),\n        timeout: Union[ClientWSTimeout, _SENTINEL] = sentinel,\n        receive_timeout: Optional[float] = None,\n        autoclose: bool = True,\n        autoping: bool = True,\n        heartbeat: Optional[float] = None,\n        auth: Optional[BasicAuth] = None,\n        origin: Optional[str] = None,\n        params: Query = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, bool, Fingerprint] = True,\n        verify_ssl: Optional[bool] = None,\n        fingerprint: Optional[bytes] = None,\n        ssl_context: Optional[SSLContext] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        compress: int = 0,\n        max_msg_size: int = 4 * 1024 * 1024,\n    ) -> ClientWebSocketResponse:\n        if timeout is not sentinel:\n            if isinstance(timeout, ClientWSTimeout):\n                ws_timeout = timeout\n            else:\n                warnings.warn(\n                    \"parameter 'timeout' of type 'float' \"\n                    \"is deprecated, please use \"\n                    \"'timeout=ClientWSTimeout(ws_close=...)'\",\n                    DeprecationWarning,\n                    stacklevel=2,\n                )\n                ws_timeout = ClientWSTimeout(ws_close=timeout)\n        else:\n            ws_timeout = DEFAULT_WS_CLIENT_TIMEOUT\n        if receive_timeout is not None:\n            warnings.warn(\n                \"float parameter 'receive_timeout' \"\n                \"is deprecated, please use parameter \"\n                \"'timeout=ClientWSTimeout(ws_receive=...)'\",\n                DeprecationWarning,\n                stacklevel=2,\n            )\n            ws_timeout = attr.evolve(ws_timeout, ws_receive=receive_timeout)\n\n        if headers is None:\n            real_headers: CIMultiDict[str] = CIMultiDict()\n        else:\n            real_headers = CIMultiDict(headers)\n\n        default_headers = {\n            hdrs.UPGRADE: \"websocket\",\n            hdrs.CONNECTION: \"Upgrade\",\n            hdrs.SEC_WEBSOCKET_VERSION: \"13\",\n        }\n\n        for key, value in default_headers.items():\n            real_headers.setdefault(key, value)\n\n        sec_key = base64.b64encode(os.urandom(16))\n        real_headers[hdrs.SEC_WEBSOCKET_KEY] = sec_key.decode()\n\n        if protocols:\n            real_headers[hdrs.SEC_WEBSOCKET_PROTOCOL] = \",\".join(protocols)\n        if origin is not None:\n            real_headers[hdrs.ORIGIN] = origin\n        if compress:\n            extstr = ws_ext_gen(compress=compress)\n            real_headers[hdrs.SEC_WEBSOCKET_EXTENSIONS] = extstr\n\n        # For the sake of backward compatibility, if user passes in None, convert it to True\n        if ssl is None:\n            warnings.warn(\n                \"ssl=None is deprecated, please use ssl=True\",\n                DeprecationWarning,\n                stacklevel=2,\n            )\n            ssl = True\n        ssl = _merge_ssl_params(ssl, verify_ssl, ssl_context, fingerprint)\n\n        # send request\n        resp = await self.request(\n            method,\n            url,\n            params=params,\n            headers=real_headers,\n            read_until_eof=False,\n            auth=auth,\n            proxy=proxy,\n            proxy_auth=proxy_auth,\n            ssl=ssl,\n            proxy_headers=proxy_headers,\n        )\n\n        try:\n            # check handshake\n            if resp.status != 101:\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid response status\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            if resp.headers.get(hdrs.UPGRADE, \"\").lower() != \"websocket\":\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid upgrade header\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            if resp.headers.get(hdrs.CONNECTION, \"\").lower() != \"upgrade\":\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid connection header\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            # key calculation\n            r_key = resp.headers.get(hdrs.SEC_WEBSOCKET_ACCEPT, \"\")\n            match = base64.b64encode(hashlib.sha1(sec_key + WS_KEY).digest()).decode()\n            if r_key != match:\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid challenge response\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            # websocket protocol\n            protocol = None\n            if protocols and hdrs.SEC_WEBSOCKET_PROTOCOL in resp.headers:\n                resp_protocols = [\n                    proto.strip()\n                    for proto in resp.headers[hdrs.SEC_WEBSOCKET_PROTOCOL].split(\",\")\n                ]\n\n                for proto in resp_protocols:\n                    if proto in protocols:\n                        protocol = proto\n                        break\n\n            # websocket compress\n            notakeover = False\n            if compress:\n                compress_hdrs = resp.headers.get(hdrs.SEC_WEBSOCKET_EXTENSIONS)\n                if compress_hdrs:\n                    try:\n                        compress, notakeover = ws_ext_parse(compress_hdrs)\n                    except WSHandshakeError as exc:\n                        raise WSServerHandshakeError(\n                            resp.request_info,\n                            resp.history,\n                            message=exc.args[0],\n                            status=resp.status,\n                            headers=resp.headers,\n                        ) from exc\n                else:\n                    compress = 0\n                    notakeover = False\n\n            conn = resp.connection\n            assert conn is not None\n            conn_proto = conn.protocol\n            assert conn_proto is not None\n\n            # For WS connection the read_timeout must be either receive_timeout or greater\n            # None == no timeout, i.e. infinite timeout, so None is the max timeout possible\n            if ws_timeout.ws_receive is None:\n                # Reset regardless\n                conn_proto.read_timeout = None\n            elif conn_proto.read_timeout is not None:\n                conn_proto.read_timeout = max(\n                    ws_timeout.ws_receive, conn_proto.read_timeout\n                )\n\n            transport = conn.transport\n            assert transport is not None\n            reader: FlowControlDataQueue[WSMessage] = FlowControlDataQueue(\n                conn_proto, 2**16, loop=self._loop\n            )\n            conn_proto.set_parser(WebSocketReader(reader, max_msg_size), reader)\n            writer = WebSocketWriter(\n                conn_proto,\n                transport,\n                use_mask=True,\n                compress=compress,\n                notakeover=notakeover,\n            )\n        except BaseException:\n            resp.close()\n            raise\n        else:\n            return self._ws_response_class(\n                reader,\n                writer,\n                protocol,\n                resp,\n                ws_timeout,\n                autoclose,\n                autoping,\n                self._loop,\n                heartbeat=heartbeat,\n                compress=compress,\n                client_notakeover=notakeover,\n            )\n\n    def _prepare_headers(self, headers: Optional[LooseHeaders]) -> \"CIMultiDict[str]\":\n        \"\"\"Add default headers and transform it to CIMultiDict\"\"\"\n        # Convert headers to MultiDict\n        result = CIMultiDict(self._default_headers)\n        if headers:\n            if not isinstance(headers, (MultiDictProxy, MultiDict)):\n                headers = CIMultiDict(headers)\n            added_names: Set[str] = set()\n            for key, value in headers.items():\n                if key in added_names:\n                    result.add(key, value)\n                else:\n                    result[key] = value\n                    added_names.add(key)\n        return result\n\n    if sys.version_info >= (3, 11) and TYPE_CHECKING:\n\n        def get(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def options(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def head(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def post(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def put(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def patch(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n        def delete(\n            self,\n            url: StrOrURL,\n            **kwargs: Unpack[_RequestOptions],\n        ) -> \"_RequestContextManager\": ...\n\n    else:\n\n        def get(\n            self, url: StrOrURL, *, allow_redirects: bool = True, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP GET request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_GET, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def options(\n            self, url: StrOrURL, *, allow_redirects: bool = True, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP OPTIONS request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_OPTIONS, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def head(\n            self, url: StrOrURL, *, allow_redirects: bool = False, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP HEAD request.\"\"\"\n            return _RequestContextManager(\n                self._request(\n                    hdrs.METH_HEAD, url, allow_redirects=allow_redirects, **kwargs\n                )\n            )\n\n        def post(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP POST request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_POST, url, data=data, **kwargs)\n            )\n\n        def put(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP PUT request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_PUT, url, data=data, **kwargs)\n            )\n\n        def patch(\n            self, url: StrOrURL, *, data: Any = None, **kwargs: Any\n        ) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP PATCH request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_PATCH, url, data=data, **kwargs)\n            )\n\n        def delete(self, url: StrOrURL, **kwargs: Any) -> \"_RequestContextManager\":\n            \"\"\"Perform HTTP DELETE request.\"\"\"\n            return _RequestContextManager(\n                self._request(hdrs.METH_DELETE, url, **kwargs)\n            )\n\n    async def close(self) -> None:\n        \"\"\"Close underlying connector.\n\n        Release all acquired resources.\n        \"\"\"\n        if not self.closed:\n            if self._connector is not None and self._connector_owner:\n                await self._connector.close()\n            self._connector = None\n\n    @property\n    def closed(self) -> bool:\n        \"\"\"Is client session closed.\n\n        A readonly property.\n        \"\"\"\n        return self._connector is None or self._connector.closed\n\n    @property\n    def connector(self) -> Optional[BaseConnector]:\n        \"\"\"Connector instance used for the session.\"\"\"\n        return self._connector\n\n    @property\n    def cookie_jar(self) -> AbstractCookieJar:\n        \"\"\"The session cookies.\"\"\"\n        return self._cookie_jar\n\n    @property\n    def version(self) -> Tuple[int, int]:\n        \"\"\"The session HTTP protocol version.\"\"\"\n        return self._version\n\n    @property\n    def requote_redirect_url(self) -> bool:\n        \"\"\"Do URL requoting on redirection handling.\"\"\"\n        return self._requote_redirect_url\n\n    @requote_redirect_url.setter\n    def requote_redirect_url(self, val: bool) -> None:\n        \"\"\"Do URL requoting on redirection handling.\"\"\"\n        warnings.warn(\n            \"session.requote_redirect_url modification is deprecated #2778\",\n            DeprecationWarning,\n            stacklevel=2,\n        )\n        self._requote_redirect_url = val\n\n    @property\n    def loop(self) -> asyncio.AbstractEventLoop:\n        \"\"\"Session's loop.\"\"\"\n        warnings.warn(\n            \"client.loop property is deprecated\", DeprecationWarning, stacklevel=2\n        )\n        return self._loop\n\n    @property\n    def timeout(self) -> ClientTimeout:\n        \"\"\"Timeout for the session.\"\"\"\n        return self._timeout\n\n    @property\n    def headers(self) -> \"CIMultiDict[str]\":\n        \"\"\"The default headers of the client session.\"\"\"\n        return self._default_headers\n\n    @property\n    def skip_auto_headers(self) -> FrozenSet[istr]:\n        \"\"\"Headers for which autogeneration should be skipped\"\"\"\n        return self._skip_auto_headers\n\n    @property\n    def auth(self) -> Optional[BasicAuth]:\n        \"\"\"An object that represents HTTP Basic Authorization\"\"\"\n        return self._default_auth\n\n    @property\n    def json_serialize(self) -> JSONEncoder:\n        \"\"\"Json serializer callable\"\"\"\n        return self._json_serialize\n\n    @property\n    def connector_owner(self) -> bool:\n        \"\"\"Should connector be closed on session closing\"\"\"\n        return self._connector_owner\n\n    @property\n    def raise_for_status(\n        self,\n    ) -> Union[bool, Callable[[ClientResponse], Awaitable[None]]]:\n        \"\"\"Should `ClientResponse.raise_for_status()` be called for each response.\"\"\"\n        return self._raise_for_status\n\n    @property\n    def auto_decompress(self) -> bool:\n        \"\"\"Should the body response be automatically decompressed.\"\"\"\n        return self._auto_decompress\n\n    @property\n    def trust_env(self) -> bool:\n        \"\"\"\n        Should proxies information from environment or netrc be trusted.\n\n        Information is from HTTP_PROXY / HTTPS_PROXY environment variables\n        or ~/.netrc file if present.\n        \"\"\"\n        return self._trust_env\n\n    @property\n    def trace_configs(self) -> List[TraceConfig]:\n        \"\"\"A list of TraceConfig instances used for client tracing\"\"\"\n        return self._trace_configs\n\n    def detach(self) -> None:\n        \"\"\"Detach connector from session without closing the former.\n\n        Session is switched to closed state anyway.\n        \"\"\"\n        self._connector = None\n\n    def __enter__(self) -> None:\n        raise TypeError(\"Use async with instead\")\n\n    def __exit__(\n        self,\n        exc_type: Optional[Type[BaseException]],\n        exc_val: Optional[BaseException],\n        exc_tb: Optional[TracebackType],\n    ) -> None:\n        # __exit__ should exist in pair with __enter__ but never executed\n        pass  # pragma: no cover\n\n    async def __aenter__(self) -> \"ClientSession\":\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        await self.close()\n\n\nclass _BaseRequestContextManager(Coroutine[Any, Any, _RetType], Generic[_RetType]):\n\n    __slots__ = (\"_coro\", \"_resp\")\n\n    def __init__(self, coro: Coroutine[\"asyncio.Future[Any]\", None, _RetType]) -> None:\n        self._coro: Coroutine[\"asyncio.Future[Any]\", None, _RetType] = coro\n\n    def send(self, arg: None) -> \"asyncio.Future[Any]\":\n        return self._coro.send(arg)\n\n    def throw(self, *args: Any, **kwargs: Any) -> \"asyncio.Future[Any]\":\n        return self._coro.throw(*args, **kwargs)\n\n    def close(self) -> None:\n        return self._coro.close()\n\n    def __await__(self) -> Generator[Any, None, _RetType]:\n        ret = self._coro.__await__()\n        return ret\n\n    def __iter__(self) -> Generator[Any, None, _RetType]:\n        return self.__await__()\n\n    async def __aenter__(self) -> _RetType:\n        self._resp: _RetType = await self._coro\n        return await self._resp.__aenter__()\n\n    async def __aexit__(\n        self,\n        exc_type: Optional[Type[BaseException]],\n        exc: Optional[BaseException],\n        tb: Optional[TracebackType],\n    ) -> None:\n        await self._resp.__aexit__(exc_type, exc, tb)\n\n\n_RequestContextManager = _BaseRequestContextManager[ClientResponse]\n_WSRequestContextManager = _BaseRequestContextManager[ClientWebSocketResponse]\n\n\nclass _SessionRequestContextManager:\n\n    __slots__ = (\"_coro\", \"_resp\", \"_session\")\n\n    def __init__(\n        self,\n        coro: Coroutine[\"asyncio.Future[Any]\", None, ClientResponse],\n        session: ClientSession,\n    ) -> None:\n        self._coro = coro\n        self._resp: Optional[ClientResponse] = None\n        self._session = session\n\n    async def __aenter__(self) -> ClientResponse:\n        try:\n            self._resp = await self._coro\n        except BaseException:\n            await self._session.close()\n            raise\n        else:\n            return self._resp\n\n    async def __aexit__(\n        self,\n        exc_type: Optional[Type[BaseException]],\n        exc: Optional[BaseException],\n        tb: Optional[TracebackType],\n    ) -> None:\n        assert self._resp is not None\n        self._resp.close()\n        await self._session.close()\n\n\ndef request(\n    method: str,\n    url: StrOrURL,\n    *,\n    params: Query = None,\n    data: Any = None,\n    json: Any = None,\n    headers: Optional[LooseHeaders] = None,\n    skip_auto_headers: Optional[Iterable[str]] = None,\n    auth: Optional[BasicAuth] = None,\n    allow_redirects: bool = True,\n    max_redirects: int = 10,\n    compress: Optional[str] = None,\n    chunked: Optional[bool] = None,\n    expect100: bool = False,\n    raise_for_status: Optional[bool] = None,\n    read_until_eof: bool = True,\n    proxy: Optional[StrOrURL] = None,\n    proxy_auth: Optional[BasicAuth] = None,\n    timeout: Union[ClientTimeout, object] = sentinel,\n    cookies: Optional[LooseCookies] = None,\n    version: HttpVersion = http.HttpVersion11,\n    connector: Optional[BaseConnector] = None,\n    read_bufsize: Optional[int] = None,\n    loop: Optional[asyncio.AbstractEventLoop] = None,\n    max_line_size: int = 8190,\n    max_field_size: int = 8190,\n) -> _SessionRequestContextManager:\n    \"\"\"Constructs and sends a request.\n\n    Returns response object.\n    method - HTTP method\n    url - request url\n    params - (optional) Dictionary or bytes to be sent in the query\n      string of the new request\n    data - (optional) Dictionary, bytes, or file-like object to\n      send in the body of the request\n    json - (optional) Any json compatible python object\n    headers - (optional) Dictionary of HTTP Headers to send with\n      the request\n    cookies - (optional) Dict object to send with the request\n    auth - (optional) BasicAuth named tuple represent HTTP Basic Auth\n    auth - aiohttp.helpers.BasicAuth\n    allow_redirects - (optional) If set to False, do not follow\n      redirects\n    version - Request HTTP version.\n    compress - Set to True if request has to be compressed\n       with deflate encoding.\n    chunked - Set to chunk size for chunked transfer encoding.\n    expect100 - Expect 100-continue response from server.\n    connector - BaseConnector sub-class instance to support\n       connection pooling.\n    read_until_eof - Read response until eof if response\n       does not have Content-Length header.\n    loop - Optional event loop.\n    timeout - Optional ClientTimeout settings structure, 5min\n       total timeout by default.\n    Usage::\n      >>> import aiohttp\n      >>> resp = await aiohttp.request('GET', 'http://python.org/')\n      >>> resp\n      <ClientResponse(python.org/) [200]>\n      >>> data = await resp.read()\n    \"\"\"\n    connector_owner = False\n    if connector is None:\n        connector_owner = True\n        connector = TCPConnector(loop=loop, force_close=True)\n\n    session = ClientSession(\n        loop=loop,\n        cookies=cookies,\n        version=version,\n        timeout=timeout,\n        connector=connector,\n        connector_owner=connector_owner,\n    )\n\n    return _SessionRequestContextManager(\n        session._request(\n            method,\n            url,\n            params=params,\n            data=data,\n            json=json,\n            headers=headers,\n            skip_auto_headers=skip_auto_headers,\n            auth=auth,\n            allow_redirects=allow_redirects,\n            max_redirects=max_redirects,\n            compress=compress,\n            chunked=chunked,\n            expect100=expect100,\n            raise_for_status=raise_for_status,\n            read_until_eof=read_until_eof,\n            proxy=proxy,\n            proxy_auth=proxy_auth,\n            read_bufsize=read_bufsize,\n            max_line_size=max_line_size,\n            max_field_size=max_field_size,\n        ),\n        session,\n    )\n"}
A user will ask you to solve a task. You should first draft your thinking process (inner monologue). Then, generate the solution.

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

**Title:** ClientSession initialization fails with unexpected 'proxy' and 'proxy_auth' arguments

**Description:**
When attempting to initialize `ClientSession` with `proxy` and `proxy_auth` parameters, a `TypeError` is raised indicating that these arguments are unexpected.

**Example Code:**
```python
from aiohttp import ClientSession
from yarl import URL

proxy_url = URL("http://proxy.example.com")
proxy_auth = None  # Replace with appropriate authentication if needed

session = ClientSession(proxy=proxy_url, proxy_auth=proxy_auth)
```

**Expected Behavior:**
`ClientSession` should accept `proxy` and `proxy_auth` as valid initialization arguments, allowing users to set default proxy settings for all requests made through the session.

**Actual Behavior:**
Initializing `ClientSession` with the `proxy` argument results in the following error:
```
TypeError: __init__() got an unexpected keyword argument 'proxy'
```

[/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.py
"""HTTP Client for asyncio."""

import asyncio
import base64
import hashlib
import json
import os
import sys
import traceback
import warnings
from contextlib import suppress
from types import TracebackType
from typing import (
    TYPE_CHECKING,
    Any,
    Awaitable,
    Callable,
    Coroutine,
    Final,
    FrozenSet,
    Generator,
    Generic,
    Iterable,
    List,
    Mapping,
    Optional,
    Set,
    Tuple,
    Type,
    TypedDict,
    TypeVar,
    Union,
)

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

from . import hdrs, http, payload
from .abc import AbstractCookieJar
from .client_exceptions import (
    ClientConnectionError,
    ClientConnectionResetError,
    ClientConnectorCertificateError,
    ClientConnectorError,
    ClientConnectorSSLError,
    ClientError,
    ClientHttpProxyError,
    ClientOSError,
    ClientPayloadError,
    ClientProxyConnectionError,
    ClientResponseError,
    ClientSSLError,
    ConnectionTimeoutError,
    ContentTypeError,
    InvalidURL,
    InvalidUrlClientError,
    InvalidUrlRedirectClientError,
    NonHttpUrlClientError,
    NonHttpUrlRedirectClientError,
    RedirectClientError,
    ServerConnectionError,
    ServerDisconnectedError,
    ServerFingerprintMismatch,
    ServerTimeoutError,
    SocketTimeoutError,
    TooManyRedirects,
    WSServerHandshakeError,
)
from .client_reqrep import (
    ClientRequest as ClientRequest,
    ClientResponse as ClientResponse,
    Fingerprint as Fingerprint,
    RequestInfo as RequestInfo,
    _merge_ssl_params,
)
from .client_ws import (
    DEFAULT_WS_CLIENT_TIMEOUT,
    ClientWebSocketResponse as ClientWebSocketResponse,
    ClientWSTimeout as ClientWSTimeout,
)
from .connector import (
    HTTP_AND_EMPTY_SCHEMA_SET,
    BaseConnector as BaseConnector,
    NamedPipeConnector as NamedPipeConnector,
    TCPConnector as TCPConnector,
    UnixConnector as UnixConnector,
)
from .cookiejar import CookieJar
from .helpers import (
    _SENTINEL,
    DEBUG,
    BasicAuth,
    TimeoutHandle,
    ceil_timeout,
    get_env_proxy_for_url,
    method_must_be_empty_body,
    sentinel,
    strip_auth_from_url,
)
from .http import WS_KEY, HttpVersion, WebSocketReader, WebSocketWriter
from .http_websocket import WSHandshakeError, WSMessage, ws_ext_gen, ws_ext_parse
from .streams import FlowControlDataQueue
from .tracing import Trace, TraceConfig
from .typedefs import JSONEncoder, LooseCookies, LooseHeaders, Query, StrOrURL

__all__ = (
    # client_exceptions
    "ClientConnectionError",
    "ClientConnectionResetError",
    "ClientConnectorCertificateError",
    "ClientConnectorError",
    "ClientConnectorSSLError",
    "ClientError",
    "ClientHttpProxyError",
    "ClientOSError",
    "ClientPayloadError",
    "ClientProxyConnectionError",
    "ClientResponseError",
    "ClientSSLError",
    "ConnectionTimeoutError",
    "ContentTypeError",
    "InvalidURL",
    "InvalidUrlClientError",
    "RedirectClientError",
    "NonHttpUrlClientError",
    "InvalidUrlRedirectClientError",
    "NonHttpUrlRedirectClientError",
    "ServerConnectionError",
    "ServerDisconnectedError",
    "ServerFingerprintMismatch",
    "ServerTimeoutError",
    "SocketTimeoutError",
    "TooManyRedirects",
    "WSServerHandshakeError",
    # client_reqrep
    "ClientRequest",
    "ClientResponse",
    "Fingerprint",
    "RequestInfo",
    # connector
    "BaseConnector",
    "TCPConnector",
    "UnixConnector",
    "NamedPipeConnector",
    # client_ws
    "ClientWebSocketResponse",
    # client
    "ClientSession",
    "ClientTimeout",
    "ClientWSTimeout",
    "request",
)


if TYPE_CHECKING:
    from ssl import SSLContext
else:
    SSLContext = None

if sys.version_info >= (3, 11) and TYPE_CHECKING:
    from typing import Unpack


class _RequestOptions(TypedDict, total=False):
    params: Query
    data: Any
    json: Any
    cookies: Union[LooseCookies, None]
    headers: Union[LooseHeaders, None]
    skip_auto_headers: Union[Iterable[str], None]
    auth: Union[BasicAuth, None]
    allow_redirects: bool
    max_redirects: int
    compress: Union[str, bool, None]
    chunked: Union[bool, None]
    expect100: bool
    raise_for_status: Union[None, bool, Callable[[ClientResponse], Awaitable[None]]]
    read_until_eof: bool
    proxy: Union[StrOrURL, None]
    proxy_auth: Union[BasicAuth, None]
    timeout: "Union[ClientTimeout, _SENTINEL, None]"
    ssl: Union[SSLContext, bool, Fingerprint]
    server_hostname: Union[str, None]
    proxy_headers: Union[LooseHeaders, None]
    trace_request_ctx: Union[Mapping[str, str], None]
    read_bufsize: Union[int, None]
    auto_decompress: Union[bool, None]
    max_line_size: Union[int, None]
    max_field_size: Union[int, None]


@attr.s(auto_attribs=True, frozen=True, slots=True)
class ClientTimeout:
    total: Optional[float] = None
    connect: Optional[float] = None
    sock_read: Optional[float] = None
    sock_connect: Optional[float] = None
    ceil_threshold: float = 5

    # pool_queue_timeout: Optional[float] = None
    # dns_resolution_timeout: Optional[float] = None
    # socket_connect_timeout: Optional[float] = None
    # connection_acquiring_timeout: Optional[float] = None
    # new_connection_timeout: Optional[float] = None
    # http_header_timeout: Optional[float] = None
    # response_body_timeout: Optional[float] = None

    # to create a timeout specific for a single request, either
    # - create a completely new one to overwrite the default
    # - or use http://www.attrs.org/en/stable/api.html#attr.evolve
    # to overwrite the defaults


# 5 Minute default read timeout
DEFAULT_TIMEOUT: Final[ClientTimeout] = ClientTimeout(total=5 * 60)

# https://www.rfc-editor.org/rfc/rfc9110#section-9.2.2
IDEMPOTENT_METHODS = frozenset({"GET", "HEAD", "OPTIONS", "TRACE", "PUT", "DELETE"})

_RetType = TypeVar("_RetType", ClientResponse, ClientWebSocketResponse)
_CharsetResolver = Callable[[ClientResponse, bytes], str]


class ClientSession:
    """First-class interface for making HTTP requests."""

    ATTRS = frozenset(
        [
            "_base_url",
            "_source_traceback",
            "_connector",
            "requote_redirect_url",
            "_loop",
            "_cookie_jar",
            "_connector_owner",
            "_default_auth",
            "_version",
            "_json_serialize",
            "_requote_redirect_url",
            "_timeout",
            "_raise_for_status",
            "_auto_decompress",
            "_trust_env",
            "_default_headers",
            "_skip_auto_headers",
            "_request_class",
            "_response_class",
            "_ws_response_class",
            "_trace_configs",
            "_read_bufsize",
            "_max_line_size",
            "_max_field_size",
            "_resolve_charset",
        ]
    )

    _source_traceback: Optional[traceback.StackSummary] = None
    _connector: Optional[BaseConnector] = None

    def __init__(
        self,
        base_url: Optional[StrOrURL] = None,
        *,
        connector: Optional[BaseConnector] = None,
        loop: Optional[asyncio.AbstractEventLoop] = None,
        cookies: Optional[LooseCookies] = None,
        headers: Optional[LooseHeaders] = None,
        skip_auto_headers: Optional[Iterable[str]] = None,
        auth: Optional[BasicAuth] = None,
        json_serialize: JSONEncoder = json.dumps,
        request_class: Type[ClientRequest] = ClientRequest,
        response_class: Type[ClientResponse] = ClientResponse,
        ws_response_class: Type[ClientWebSocketResponse] = ClientWebSocketResponse,
        version: HttpVersion = http.HttpVersion11,
        cookie_jar: Optional[AbstractCookieJar] = None,
        connector_owner: bool = True,
        raise_for_status: Union[
            bool, Callable[[ClientResponse], Awaitable[None]]
        ] = False,
        read_timeout: Union[float, _SENTINEL] = sentinel,
        conn_timeout: Optional[float] = None,
        timeout: Union[object, ClientTimeout] = sentinel,
        auto_decompress: bool = True,
        trust_env: bool = False,
        requote_redirect_url: bool = True,
        trace_configs: Optional[List[TraceConfig]] = None,
        read_bufsize: int = 2**16,
        max_line_size: int = 8190,
        max_field_size: int = 8190,
        fallback_charset_resolver: _CharsetResolver = lambda r, b: "utf-8",
    ) -> None:
        # We initialise _connector to None immediately, as it's referenced in __del__()
        # and could cause issues if an exception occurs during initialisation.
        self._connector: Optional[BaseConnector] = None

        if loop is None:
            if connector is not None:
                loop = connector._loop

        loop = loop or asyncio.get_running_loop()

        if base_url is None or isinstance(base_url, URL):
            self._base_url: Optional[URL] = base_url
        else:
            self._base_url = URL(base_url)
            assert (
                self._base_url.origin() == self._base_url
            ), "Only absolute URLs without path part are supported"

        if timeout is sentinel or timeout is None:
            self._timeout = DEFAULT_TIMEOUT
            if read_timeout is not sentinel:
                warnings.warn(
                    "read_timeout is deprecated, use timeout argument instead",
                    DeprecationWarning,
                    stacklevel=2,
                )
                self._timeout = attr.evolve(self._timeout, total=read_timeout)
            if conn_timeout is not None:
                self._timeout = attr.evolve(self._timeout, connect=conn_timeout)
                warnings.warn(
                    "conn_timeout is deprecated, use timeout argument instead",
                    DeprecationWarning,
                    stacklevel=2,
                )
        else:
            if not isinstance(timeout, ClientTimeout):
                raise ValueError(
                    f"timeout parameter cannot be of {type(timeout)} type, "
                    "please use 'timeout=ClientTimeout(...)'",
                )
            self._timeout = timeout
            if read_timeout is not sentinel:
                raise ValueError(
                    "read_timeout and timeout parameters "
                    "conflict, please setup "
                    "timeout.read"
                )
            if conn_timeout is not None:
                raise ValueError(
                    "conn_timeout and timeout parameters "
                    "conflict, please setup "
                    "timeout.connect"
                )

        if connector is None:
            connector = TCPConnector(loop=loop)

        if connector._loop is not loop:
            raise RuntimeError("Session and connector has to use same event loop")

        self._loop = loop

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

        if cookie_jar is None:
            cookie_jar = CookieJar(loop=loop)
        self._cookie_jar = cookie_jar

        if cookies is not None:
            self._cookie_jar.update_cookies(cookies)

        self._connector = connector
        self._connector_owner = connector_owner
        self._default_auth = auth
        self._version = version
        self._json_serialize = json_serialize
        self._raise_for_status = raise_for_status
        self._auto_decompress = auto_decompress
        self._trust_env = trust_env
        self._requote_redirect_url = requote_redirect_url
        self._read_bufsize = read_bufsize
        self._max_line_size = max_line_size
        self._max_field_size = max_field_size

        # Convert to list of tuples
        if headers:
            real_headers: CIMultiDict[str] = CIMultiDict(headers)
        else:
            real_headers = CIMultiDict()
        self._default_headers: CIMultiDict[str] = real_headers
        if skip_auto_headers is not None:
            self._skip_auto_headers = frozenset(istr(i) for i in skip_auto_headers)
        else:
            self._skip_auto_headers = frozenset()

        self._request_class = request_class
        self._response_class = response_class
        self._ws_response_class = ws_response_class

        self._trace_configs = trace_configs or []
        for trace_config in self._trace_configs:
            trace_config.freeze()

        self._resolve_charset = fallback_charset_resolver

    def __init_subclass__(cls: Type["ClientSession"]) -> None:
        warnings.warn(
            "Inheritance class {} from ClientSession "
            "is discouraged".format(cls.__name__),
            DeprecationWarning,
            stacklevel=2,
        )

    if DEBUG:

        def __setattr__(self, name: str, val: Any) -> None:
            if name not in self.ATTRS:
                warnings.warn(
                    "Setting custom ClientSession.{} attribute "
                    "is discouraged".format(name),
                    DeprecationWarning,
                    stacklevel=2,
                )
            super().__setattr__(name, val)

    def __del__(self, _warnings: Any = warnings) -> None:
        if not self.closed:
            kwargs = {"source": self}
            _warnings.warn(
                f"Unclosed client session {self!r}", ResourceWarning, **kwargs
            )
            context = {"client_session": self, "message": "Unclosed client session"}
            if self._source_traceback is not None:
                context["source_traceback"] = self._source_traceback
            self._loop.call_exception_handler(context)

    if sys.version_info >= (3, 11) and TYPE_CHECKING:

        def request(
            self,
            method: str,
            url: StrOrURL,
            **kwargs: Unpack[_RequestOptions],
        ) -> "_RequestContextManager": ...

    else:

        def request(
            self, method: str, url: StrOrURL, **kwargs: Any
        ) -> "_RequestContextManager":
            """Perform HTTP request."""
            return _RequestContextManager(self._request(method, url, **kwargs))

    def _build_url(self, str_or_url: StrOrURL) -> URL:
        url = URL(str_or_url)
        if self._base_url is None:
            return url
        else:
            assert not url.absolute and url.path.startswith("/")
            return self._base_url.join(url)

    async def _request(
        self,
        method: str,
        str_or_url: StrOrURL,
        *,
        params: Query = None,
        data: Any = None,
        json: Any = None,
        cookies: Optional[LooseCookies] = None,
        headers: Optional[LooseHeaders] = None,
        skip_auto_headers: Optional[Iterable[str]] = None,
        auth: Optional[BasicAuth] = None,
        allow_redirects: bool = True,
        max_redirects: int = 10,
        compress: Union[str, bool, None] = None,
        chunked: Optional[bool] = None,
        expect100: bool = False,
        raise_for_status: Union[
            None, bool, Callable[[ClientResponse], Awaitable[None]]
        ] = None,
        read_until_eof: bool = True,
        proxy: Optional[StrOrURL] = None,
        proxy_auth: Optional[BasicAuth] = None,
        timeout: Union[ClientTimeout, _SENTINEL] = sentinel,
        verify_ssl: Optional[bool] = None,
        fingerprint: Optional[bytes] = None,
        ssl_context: Optional[SSLContext] = None,
        ssl: Union[SSLContext, bool, Fingerprint] = True,
        server_hostname: Optional[str] = None,
        proxy_headers: Optional[LooseHeaders] = None,
        trace_request_ctx: Optional[Mapping[str, str]] = None,
        read_bufsize: Optional[int] = None,
        auto_decompress: Optional[bool] = None,
        max_line_size: Optional[int] = None,
        max_field_size: Optional[int] = None,
    ) -> ClientResponse:

        # NOTE: timeout clamps existing connect and read timeouts.  We cannot
        # set the default to None because we need to detect if the user wants
        # to use the existing timeouts by setting timeout to None.

        if self.closed:
            raise RuntimeError("Session is closed")

        ssl = _merge_ssl_params(ssl, verify_ssl, ssl_context, fingerprint)

        if data is not None and json is not None:
            raise ValueError(
                "data and json parameters can not be used at the same time"
            )
        elif json is not None:
            data = payload.JsonPayload(json, dumps=self._json_serialize)

        if not isinstance(chunked, bool) and chunked is not None:
            warnings.warn("Chunk size is deprecated #1615", DeprecationWarning)

        redirects = 0
        history = []
        version = self._version
        params = params or {}

        # Merge with default headers and transform to CIMultiDict
        headers = self._prepare_headers(headers)

        try:
            url = self._build_url(str_or_url)
        except ValueError as e:
            raise InvalidUrlClientError(str_or_url) from e

        assert self._connector is not None
        if url.scheme not in self._connector.allowed_protocol_schema_set:
            raise NonHttpUrlClientError(url)

        skip_headers = set(self._skip_auto_headers)
        if skip_auto_headers is not None:
            for i in skip_auto_headers:
                skip_headers.add(istr(i))

        if proxy is None:
            proxy_headers = None
        else:
            proxy_headers = self._prepare_headers(proxy_headers)
            try:
                proxy = URL(proxy)
            except ValueError as e:
                raise InvalidURL(proxy) from e

        if timeout is sentinel:
            real_timeout: ClientTimeout = self._timeout
        else:
            if not isinstance(timeout, ClientTimeout):
                real_timeout = ClientTimeout(total=timeout)
            else:
                real_timeout = timeout
        # timeout is cumulative for all request operations
        # (request, redirects, responses, data consuming)
        tm = TimeoutHandle(
            self._loop, real_timeout.total, ceil_threshold=real_timeout.ceil_threshold
        )
        handle = tm.start()

        if read_bufsize is None:
            read_bufsize = self._read_bufsize

        if auto_decompress is None:
            auto_decompress = self._auto_decompress

        if max_line_size is None:
            max_line_size = self._max_line_size

        if max_field_size is None:
            max_field_size = self._max_field_size

        traces = [
            Trace(
                self,
                trace_config,
                trace_config.trace_config_ctx(trace_request_ctx=trace_request_ctx),
            )
            for trace_config in self._trace_configs
        ]

        for trace in traces:
            await trace.send_request_start(method, url.update_query(params), headers)

        timer = tm.timer()
        try:
            with timer:
                # https://www.rfc-editor.org/rfc/rfc9112.html#name-retrying-requests
                retry_persistent_connection = method in IDEMPOTENT_METHODS
                while True:
                    url, auth_from_url = strip_auth_from_url(url)
                    if not url.raw_host:
                        # NOTE: Bail early, otherwise, causes `InvalidURL` through
                        # NOTE: `self._request_class()` below.
                        err_exc_cls = (
                            InvalidUrlRedirectClientError
                            if redirects
                            else InvalidUrlClientError
                        )
                        raise err_exc_cls(url)
                    if auth and auth_from_url:
                        raise ValueError(
                            "Cannot combine AUTH argument with "
                            "credentials encoded in URL"
                        )

                    if auth is None:
                        auth = auth_from_url

                    if auth is None and (
                        not self._base_url or self._base_url.origin() == url.origin()
                    ):
                        auth = self._default_auth
                    # It would be confusing if we support explicit
                    # Authorization header with auth argument
                    if (
                        headers is not None
                        and auth is not None
                        and hdrs.AUTHORIZATION in headers
                    ):
                        raise ValueError(
                            "Cannot combine AUTHORIZATION header "
                            "with AUTH argument or credentials "
                            "encoded in URL"
                        )

                    all_cookies = self._cookie_jar.filter_cookies(url)

                    if cookies is not None:
                        tmp_cookie_jar = CookieJar()
                        tmp_cookie_jar.update_cookies(cookies)
                        req_cookies = tmp_cookie_jar.filter_cookies(url)
                        if req_cookies:
                            all_cookies.load(req_cookies)

                    if proxy is not None:
                        proxy = URL(proxy)
                    elif self._trust_env:
                        with suppress(LookupError):
                            proxy, proxy_auth = get_env_proxy_for_url(url)

                    req = self._request_class(
                        method,
                        url,
                        params=params,
                        headers=headers,
                        skip_auto_headers=skip_headers if skip_headers else None,
                        data=data,
                        cookies=all_cookies,
                        auth=auth,
                        version=version,
                        compress=compress,
                        chunked=chunked,
                        expect100=expect100,
                        loop=self._loop,
                        response_class=self._response_class,
                        proxy=proxy,
                        proxy_auth=proxy_auth,
                        timer=timer,
                        session=self,
                        ssl=ssl if ssl is not None else True,
                        server_hostname=server_hostname,
                        proxy_headers=proxy_headers,
                        traces=traces,
                        trust_env=self.trust_env,
                    )

                    # connection timeout
                    try:
                        async with ceil_timeout(
                            real_timeout.connect,
                            ceil_threshold=real_timeout.ceil_threshold,
                        ):
                            conn = await self._connector.connect(
                                req, traces=traces, timeout=real_timeout
                            )
                    except asyncio.TimeoutError as exc:
                        raise ConnectionTimeoutError(
                            f"Connection timeout to host {url}"
                        ) from exc

                    assert conn.transport is not None

                    assert conn.protocol is not None
                    conn.protocol.set_response_params(
                        timer=timer,
                        skip_payload=method_must_be_empty_body(method),
                        read_until_eof=read_until_eof,
                        auto_decompress=auto_decompress,
                        read_timeout=real_timeout.sock_read,
                        read_bufsize=read_bufsize,
                        timeout_ceil_threshold=self._connector._timeout_ceil_threshold,
                        max_line_size=max_line_size,
                        max_field_size=max_field_size,
                    )

                    try:
                        try:
                            resp = await req.send(conn)
                            try:
                                await resp.start(conn)
                            except BaseException:
                                resp.close()
                                raise
                        except BaseException:
                            conn.close()
                            raise
                    except (ClientOSError, ServerDisconnectedError):
                        if retry_persistent_connection:
                            retry_persistent_connection = False
                            continue
                        raise
                    except ClientError:
                        raise
                    except OSError as exc:
                        if exc.errno is None and isinstance(exc, asyncio.TimeoutError):
                            raise
                        raise ClientOSError(*exc.args) from exc

                    self._cookie_jar.update_cookies(resp.cookies, resp.url)

                    # redirects
                    if resp.status in (301, 302, 303, 307, 308) and allow_redirects:

                        for trace in traces:
                            await trace.send_request_redirect(
                                method, url.update_query(params), headers, resp
                            )

                        redirects += 1
                        history.append(resp)
                        if max_redirects and redirects >= max_redirects:
                            resp.close()
                            raise TooManyRedirects(
                                history[0].request_info, tuple(history)
                            )

                        # For 301 and 302, mimic IE, now changed in RFC
                        # https://github.com/kennethreitz/requests/pull/269
                        if (resp.status == 303 and resp.method != hdrs.METH_HEAD) or (
                            resp.status in (301, 302) and resp.method == hdrs.METH_POST
                        ):
                            method = hdrs.METH_GET
                            data = None
                            if headers.get(hdrs.CONTENT_LENGTH):
                                headers.pop(hdrs.CONTENT_LENGTH)

                        r_url = resp.headers.get(hdrs.LOCATION) or resp.headers.get(
                            hdrs.URI
                        )
                        if r_url is None:
                            # see github.com/aio-libs/aiohttp/issues/2022
                            break
                        else:
                            # reading from correct redirection
                            # response is forbidden
                            resp.release()

                        try:
                            parsed_redirect_url = URL(
                                r_url, encoded=not self._requote_redirect_url
                            )
                        except ValueError as e:
                            raise InvalidUrlRedirectClientError(
                                r_url,
                                "Server attempted redirecting to a location that does not look like a URL",
                            ) from e

                        scheme = parsed_redirect_url.scheme
                        if scheme not in HTTP_AND_EMPTY_SCHEMA_SET:
                            resp.close()
                            raise NonHttpUrlRedirectClientError(r_url)
                        elif not scheme:
                            parsed_redirect_url = url.join(parsed_redirect_url)

                        try:
                            redirect_origin = parsed_redirect_url.origin()
                        except ValueError as origin_val_err:
                            raise InvalidUrlRedirectClientError(
                                parsed_redirect_url,
                                "Invalid redirect URL origin",
                            ) from origin_val_err

                        if url.origin() != redirect_origin:
                            auth = None
                            headers.pop(hdrs.AUTHORIZATION, None)

                        url = parsed_redirect_url
                        params = {}
                        resp.release()
                        continue

                    break

            # check response status
            if raise_for_status is None:
                raise_for_status = self._raise_for_status

            if raise_for_status is None:
                pass
            elif callable(raise_for_status):
                await raise_for_status(resp)
            elif raise_for_status:
                resp.raise_for_status()

            # register connection
            if handle is not None:
                if resp.connection is not None:
                    resp.connection.add_callback(handle.cancel)
                else:
                    handle.cancel()

            resp._history = tuple(history)

            for trace in traces:
                await trace.send_request_end(
                    method, url.update_query(params), headers, resp
                )
            return resp

        except BaseException as e:
            # cleanup timer
            tm.close()
            if handle:
                handle.cancel()
                handle = None

            for trace in traces:
                await trace.send_request_exception(
                    method, url.update_query(params), headers, e
                )
            raise

    def ws_connect(
        self,
        url: StrOrURL,
        *,
        method: str = hdrs.METH_GET,
        protocols: Iterable[str] = (),
        timeout: Union[ClientWSTimeout, _SENTINEL] = sentinel,
        receive_timeout: Optional[float] = None,
        autoclose: bool = True,
        autoping: bool = True,
        heartbeat: Optional[float] = None,
        auth: Optional[BasicAuth] = None,
        origin: Optional[str] = None,
        params: Query = None,
        headers: Optional[LooseHeaders] = None,
        proxy: Optional[StrOrURL] = None,
        proxy_auth: Optional[BasicAuth] = None,
        ssl: Union[SSLContext, bool, Fingerprint] = True,
        verify_ssl: Optional[bool] = None,
        fingerprint: Optional[bytes] = None,
        ssl_context: Optional[SSLContext] = None,
        proxy_headers: Optional[LooseHeaders] = None,
        compress: int = 0,
        max_msg_size: int = 4 * 1024 * 1024,
    ) -> "_WSRequestContextManager":
        """Initiate websocket connection."""
        return _WSRequestContextManager(
            self._ws_connect(
                url,
                method=method,
                protocols=protocols,
                timeout=timeout,
                receive_timeout=receive_timeout,
                autoclose=autoclose,
                autoping=autoping,
                heartbeat=heartbeat,
                auth=auth,
                origin=origin,
                params=params,
                headers=headers,
                proxy=proxy,
                proxy_auth=proxy_auth,
                ssl=ssl,
                verify_ssl=verify_ssl,
                fingerprint=fingerprint,
                ssl_context=ssl_context,
                proxy_headers=proxy_headers,
                compress=compress,
                max_msg_size=max_msg_size,
            )
        )

    async def _ws_connect(
        self,
        url: StrOrURL,
        *,
        method: str = hdrs.METH_GET,
        protocols: Iterable[str] = (),
        timeout: Union[ClientWSTimeout, _SENTINEL] = sentinel,
        receive_timeout: Optional[float] = None,
        autoclose: bool = True,
        autoping: bool = True,
        heartbeat: Optional[float] = None,
        auth: Optional[BasicAuth] = None,
        origin: Optional[str] = None,
        params: Query = None,
        headers: Optional[LooseHeaders] = None,
        proxy: Optional[StrOrURL] = None,
        proxy_auth: Optional[BasicAuth] = None,
        ssl: Union[SSLContext, bool, Fingerprint] = True,
        verify_ssl: Optional[bool] = None,
        fingerprint: Optional[bytes] = None,
        ssl_context: Optional[SSLContext] = None,
        proxy_headers: Optional[LooseHeaders] = None,
        compress: int = 0,
        max_msg_size: int = 4 * 1024 * 1024,
    ) -> ClientWebSocketResponse:
        if timeout is not sentinel:
            if isinstance(timeout, ClientWSTimeout):
                ws_timeout = timeout
            else:
                warnings.warn(
                    "parameter 'timeout' of type 'float' "
                    "is deprecated, please use "
                    "'timeout=ClientWSTimeout(ws_close=...)'",
                    DeprecationWarning,
                    stacklevel=2,
                )
                ws_timeout = ClientWSTimeout(ws_close=timeout)
        else:
            ws_timeout = DEFAULT_WS_CLIENT_TIMEOUT
        if receive_timeout is not None:
            warnings.warn(
                "float parameter 'receive_timeout' "
                "is deprecated, please use parameter "
                "'timeout=ClientWSTimeout(ws_receive=...)'",
                DeprecationWarning,
                stacklevel=2,
            )
            ws_timeout = attr.evolve(ws_timeout, ws_receive=receive_timeout)

        if headers is None:
            real_headers: CIMultiDict[str] = CIMultiDict()
        else:
            real_headers = CIMultiDict(headers)

        default_headers = {
            hdrs.UPGRADE: "websocket",
            hdrs.CONNECTION: "Upgrade",
            hdrs.SEC_WEBSOCKET_VERSION: "13",
        }

        for key, value in default_headers.items():
            real_headers.setdefault(key, value)

        sec_key = base64.b64encode(os.urandom(16))
        real_headers[hdrs.SEC_WEBSOCKET_KEY] = sec_key.decode()

        if protocols:
            real_headers[hdrs.SEC_WEBSOCKET_PROTOCOL] = ",".join(protocols)
        if origin is not None:
            real_headers[hdrs.ORIGIN] = origin
        if compress:
            extstr = ws_ext_gen(compress=compress)
            real_headers[hdrs.SEC_WEBSOCKET_EXTENSIONS] = extstr

        # For the sake of backward compatibility, if user passes in None, convert it to True
        if ssl is None:
            warnings.warn(
                "ssl=None is deprecated, please use ssl=True",
                DeprecationWarning,
                stacklevel=2,
            )
            ssl = True
        ssl = _merge_ssl_params(ssl, verify_ssl, ssl_context, fingerprint)

        # send request
        resp = await self.request(
            method,
            url,
            params=params,
            headers=real_headers,
            read_until_eof=False,
            auth=auth,
            proxy=proxy,
            proxy_auth=proxy_auth,
            ssl=ssl,
            proxy_headers=proxy_headers,
        )

        try:
            # check handshake
            if resp.status != 101:
                raise WSServerHandshakeError(
                    resp.request_info,
                    resp.history,
                    message="Invalid response status",
                    status=resp.status,
                    headers=resp.headers,
                )

            if resp.headers.get(hdrs.UPGRADE, "").lower() != "websocket":
                raise WSServerHandshakeError(
                    resp.request_info,
                    resp.history,
                    message="Invalid upgrade header",
                    status=resp.status,
                    headers=resp.headers,
                )

            if resp.headers.get(hdrs.CONNECTION, "").lower() != "upgrade":
                raise WSServerHandshakeError(
                    resp.request_info,
                    resp.history,
                    message="Invalid connection header",
                    status=resp.status,
                    headers=resp.headers,
                )

            # key calculation
            r_key = resp.headers.get(hdrs.SEC_WEBSOCKET_ACCEPT, "")
            match = base64.b64encode(hashlib.sha1(sec_key + WS_KEY).digest()).decode()
            if r_key != match:
                raise WSServerHandshakeError(
                    resp.request_info,
                    resp.history,
                    message="Invalid challenge response",
                    status=resp.status,
                    headers=resp.headers,
                )

            # websocket protocol
            protocol = None
            if protocols and hdrs.SEC_WEBSOCKET_PROTOCOL in resp.headers:
                resp_protocols = [
                    proto.strip()
                    for proto in resp.headers[hdrs.SEC_WEBSOCKET_PROTOCOL].split(",")
                ]

                for proto in resp_protocols:
                    if proto in protocols:
                        protocol = proto
                        break

            # websocket compress
            notakeover = False
            if compress:
                compress_hdrs = resp.headers.get(hdrs.SEC_WEBSOCKET_EXTENSIONS)
                if compress_hdrs:
                    try:
                        compress, notakeover = ws_ext_parse(compress_hdrs)
                    except WSHandshakeError as exc:
                        raise WSServerHandshakeError(
                            resp.request_info,
                            resp.history,
                            message=exc.args[0],
                            status=resp.status,
                            headers=resp.headers,
                        ) from exc
                else:
                    compress = 0
                    notakeover = False

            conn = resp.connection
            assert conn is not None
            conn_proto = conn.protocol
            assert conn_proto is not None

            # For WS connection the read_timeout must be either receive_timeout or greater
            # None == no timeout, i.e. infinite timeout, so None is the max timeout possible
            if ws_timeout.ws_receive is None:
                # Reset regardless
                conn_proto.read_timeout = None
            elif conn_proto.read_timeout is not None:
                conn_proto.read_timeout = max(
                    ws_timeout.ws_receive, conn_proto.read_timeout
                )

            transport = conn.transport
            assert transport is not None
            reader: FlowControlDataQueue[WSMessage] = FlowControlDataQueue(
                conn_proto, 2**16, loop=self._loop
            )
            conn_proto.set_parser(WebSocketReader(reader, max_msg_size), reader)
            writer = WebSocketWriter(
                conn_proto,
                transport,
                use_mask=True,
                compress=compress,
                notakeover=notakeover,
            )
        except BaseException:
            resp.close()
            raise
        else:
            return self._ws_response_class(
                reader,
                writer,
                protocol,
                resp,
                ws_timeout,
                autoclose,
                autoping,
                self._loop,
                heartbeat=heartbeat,
                compress=compress,
                client_notakeover=notakeover,
            )

    def _prepare_headers(self, headers: Optional[LooseHeaders]) -> "CIMultiDict[str]":
        """Add default headers and transform it to CIMultiDict"""
        # Convert headers to MultiDict
        result = CIMultiDict(self._default_headers)
        if headers:
            if not isinstance(headers, (MultiDictProxy, MultiDict)):
                headers = CIMultiDict(headers)
            added_names: Set[str] = set()
            for key, value in headers.items():
                if key in added_names:
                    result.add(key, value)
                else:
                    result[key] = value
                    added_names.add(key)
        return result

    if sys.version_info >= (3, 11) and TYPE_CHECKING:

        def get(
            self,
            url: StrOrURL,
            **kwargs: Unpack[_RequestOptions],
        ) -> "_RequestContextManager": ...

        def options(
            self,
            url: StrOrURL,
            **kwargs: Unpack[_RequestOptions],
        ) -> "_RequestContextManager": ...

        def head(
            self,
            url: StrOrURL,
            **kwargs: Unpack[_RequestOptions],
        ) -> "_RequestContextManager": ...

        def post(
            self,
            url: StrOrURL,
            **kwargs: Unpack[_RequestOptions],
        ) -> "_RequestContextManager": ...

        def put(
            self,
            url: StrOrURL,
            **kwargs: Unpack[_RequestOptions],
        ) -> "_RequestContextManager": ...

        def patch(
            self,
            url: StrOrURL,
            **kwargs: Unpack[_RequestOptions],
        ) -> "_RequestContextManager": ...

        def delete(
            self,
            url: StrOrURL,
            **kwargs: Unpack[_RequestOptions],
        ) -> "_RequestContextManager": ...

    else:

        def get(
            self, url: StrOrURL, *, allow_redirects: bool = True, **kwargs: Any
        ) -> "_RequestContextManager":
            """Perform HTTP GET request."""
            return _RequestContextManager(
                self._request(
                    hdrs.METH_GET, url, allow_redirects=allow_redirects, **kwargs
                )
            )

        def options(
            self, url: StrOrURL, *, allow_redirects: bool = True, **kwargs: Any
        ) -> "_RequestContextManager":
            """Perform HTTP OPTIONS request."""
            return _RequestContextManager(
                self._request(
                    hdrs.METH_OPTIONS, url, allow_redirects=allow_redirects, **kwargs
                )
            )

        def head(
            self, url: StrOrURL, *, allow_redirects: bool = False, **kwargs: Any
        ) -> "_RequestContextManager":
            """Perform HTTP HEAD request."""
            return _RequestContextManager(
                self._request(
                    hdrs.METH_HEAD, url, allow_redirects=allow_redirects, **kwargs
                )
            )

        def post(
            self, url: StrOrURL, *, data: Any = None, **kwargs: Any
        ) -> "_RequestContextManager":
            """Perform HTTP POST request."""
            return _RequestContextManager(
                self._request(hdrs.METH_POST, url, data=data, **kwargs)
            )

        def put(
            self, url: StrOrURL, *, data: Any = None, **kwargs: Any
        ) -> "_RequestContextManager":
            """Perform HTTP PUT request."""
            return _RequestContextManager(
                self._request(hdrs.METH_PUT, url, data=data, **kwargs)
            )

        def patch(
            self, url: StrOrURL, *, data: Any = None, **kwargs: Any
        ) -> "_RequestContextManager":
            """Perform HTTP PATCH request."""
            return _RequestContextManager(
                self._request(hdrs.METH_PATCH, url, data=data, **kwargs)
            )

        def delete(self, url: StrOrURL, **kwargs: Any) -> "_RequestContextManager":
            """Perform HTTP DELETE request."""
            return _RequestContextManager(
                self._request(hdrs.METH_DELETE, url, **kwargs)
            )

    async def close(self) -> None:
        """Close underlying connector.

        Release all acquired resources.
        """
        if not self.closed:
            if self._connector is not None and self._connector_owner:
                await self._connector.close()
            self._connector = None

    @property
    def closed(self) -> bool:
        """Is client session closed.

        A readonly property.
        """
        return self._connector is None or self._connector.closed

    @property
    def connector(self) -> Optional[BaseConnector]:
        """Connector instance used for the session."""
        return self._connector

    @property
    def cookie_jar(self) -> AbstractCookieJar:
        """The session cookies."""
        return self._cookie_jar

    @property
    def version(self) -> Tuple[int, int]:
        """The session HTTP protocol version."""
        return self._version

    @property
    def requote_redirect_url(self) -> bool:
        """Do URL requoting on redirection handling."""
        return self._requote_redirect_url

    @requote_redirect_url.setter
    def requote_redirect_url(self, val: bool) -> None:
        """Do URL requoting on redirection handling."""
        warnings.warn(
            "session.requote_redirect_url modification is deprecated #2778",
            DeprecationWarning,
            stacklevel=2,
        )
        self._requote_redirect_url = val

    @property
    def loop(self) -> asyncio.AbstractEventLoop:
        """Session's loop."""
        warnings.warn(
            "client.loop property is deprecated", DeprecationWarning, stacklevel=2
        )
        return self._loop

    @property
    def timeout(self) -> ClientTimeout:
        """Timeout for the session."""
        return self._timeout

    @property
    def headers(self) -> "CIMultiDict[str]":
        """The default headers of the client session."""
        return self._default_headers

    @property
    def skip_auto_headers(self) -> FrozenSet[istr]:
        """Headers for which autogeneration should be skipped"""
        return self._skip_auto_headers

    @property
    def auth(self) -> Optional[BasicAuth]:
        """An object that represents HTTP Basic Authorization"""
        return self._default_auth

    @property
    def json_serialize(self) -> JSONEncoder:
        """Json serializer callable"""
        return self._json_serialize

    @property
    def connector_owner(self) -> bool:
        """Should connector be closed on session closing"""
        return self._connector_owner

    @property
    def raise_for_status(
        self,
    ) -> Union[bool, Callable[[ClientResponse], Awaitable[None]]]:
        """Should `ClientResponse.raise_for_status()` be called for each response."""
        return self._raise_for_status

    @property
    def auto_decompress(self) -> bool:
        """Should the body response be automatically decompressed."""
        return self._auto_decompress

    @property
    def trust_env(self) -> bool:
        """
        Should proxies information from environment or netrc be trusted.

        Information is from HTTP_PROXY / HTTPS_PROXY environment variables
        or ~/.netrc file if present.
        """
        return self._trust_env

    @property
    def trace_configs(self) -> List[TraceConfig]:
        """A list of TraceConfig instances used for client tracing"""
        return self._trace_configs

    def detach(self) -> None:
        """Detach connector from session without closing the former.

        Session is switched to closed state anyway.
        """
        self._connector = None

    def __enter__(self) -> None:
        raise TypeError("Use async with instead")

    def __exit__(
        self,
        exc_type: Optional[Type[BaseException]],
        exc_val: Optional[BaseException],
        exc_tb: Optional[TracebackType],
    ) -> None:
        # __exit__ should exist in pair with __enter__ but never executed
        pass  # pragma: no cover

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

    async def __aexit__(
        self,
        exc_type: Optional[Type[BaseException]],
        exc_val: Optional[BaseException],
        exc_tb: Optional[TracebackType],
    ) -> None:
        await self.close()


class _BaseRequestContextManager(Coroutine[Any, Any, _RetType], Generic[_RetType]):

    __slots__ = ("_coro", "_resp")

    def __init__(self, coro: Coroutine["asyncio.Future[Any]", None, _RetType]) -> None:
        self._coro: Coroutine["asyncio.Future[Any]", None, _RetType] = coro

    def send(self, arg: None) -> "asyncio.Future[Any]":
        return self._coro.send(arg)

    def throw(self, *args: Any, **kwargs: Any) -> "asyncio.Future[Any]":
        return self._coro.throw(*args, **kwargs)

    def close(self) -> None:
        return self._coro.close()

    def __await__(self) -> Generator[Any, None, _RetType]:
        ret = self._coro.__await__()
        return ret

    def __iter__(self) -> Generator[Any, None, _RetType]:
        return self.__await__()

    async def __aenter__(self) -> _RetType:
        self._resp: _RetType = await self._coro
        return await self._resp.__aenter__()

    async def __aexit__(
        self,
        exc_type: Optional[Type[BaseException]],
        exc: Optional[BaseException],
        tb: Optional[TracebackType],
    ) -> None:
        await self._resp.__aexit__(exc_type, exc, tb)


_RequestContextManager = _BaseRequestContextManager[ClientResponse]
_WSRequestContextManager = _BaseRequestContextManager[ClientWebSocketResponse]


class _SessionRequestContextManager:

    __slots__ = ("_coro", "_resp", "_session")

    def __init__(
        self,
        coro: Coroutine["asyncio.Future[Any]", None, ClientResponse],
        session: ClientSession,
    ) -> None:
        self._coro = coro
        self._resp: Optional[ClientResponse] = None
        self._session = session

    async def __aenter__(self) -> ClientResponse:
        try:
            self._resp = await self._coro
        except BaseException:
            await self._session.close()
            raise
        else:
            return self._resp

    async def __aexit__(
        self,
        exc_type: Optional[Type[BaseException]],
        exc: Optional[BaseException],
        tb: Optional[TracebackType],
    ) -> None:
        assert self._resp is not None
        self._resp.close()
        await self._session.close()


def request(
    method: str,
    url: StrOrURL,
    *,
    params: Query = None,
    data: Any = None,
    json: Any = None,
    headers: Optional[LooseHeaders] = None,
    skip_auto_headers: Optional[Iterable[str]] = None,
    auth: Optional[BasicAuth] = None,
    allow_redirects: bool = True,
    max_redirects: int = 10,
    compress: Optional[str] = None,
    chunked: Optional[bool] = None,
    expect100: bool = False,
    raise_for_status: Optional[bool] = None,
    read_until_eof: bool = True,
    proxy: Optional[StrOrURL] = None,
    proxy_auth: Optional[BasicAuth] = None,
    timeout: Union[ClientTimeout, object] = sentinel,
    cookies: Optional[LooseCookies] = None,
    version: HttpVersion = http.HttpVersion11,
    connector: Optional[BaseConnector] = None,
    read_bufsize: Optional[int] = None,
    loop: Optional[asyncio.AbstractEventLoop] = None,
    max_line_size: int = 8190,
    max_field_size: int = 8190,
) -> _SessionRequestContextManager:
    """Constructs and sends a request.

    Returns response object.
    method - HTTP method
    url - request url
    params - (optional) Dictionary or bytes to be sent in the query
      string of the new request
    data - (optional) Dictionary, bytes, or file-like object to
      send in the body of the request
    json - (optional) Any json compatible python object
    headers - (optional) Dictionary of HTTP Headers to send with
      the request
    cookies - (optional) Dict object to send with the request
    auth - (optional) BasicAuth named tuple represent HTTP Basic Auth
    auth - aiohttp.helpers.BasicAuth
    allow_redirects - (optional) If set to False, do not follow
      redirects
    version - Request HTTP version.
    compress - Set to True if request has to be compressed
       with deflate encoding.
    chunked - Set to chunk size for chunked transfer encoding.
    expect100 - Expect 100-continue response from server.
    connector - BaseConnector sub-class instance to support
       connection pooling.
    read_until_eof - Read response until eof if response
       does not have Content-Length header.
    loop - Optional event loop.
    timeout - Optional ClientTimeout settings structure, 5min
       total timeout by default.
    Usage::
      >>> import aiohttp
      >>> resp = await aiohttp.request('GET', 'http://python.org/')
      >>> resp
      <ClientResponse(python.org/) [200]>
      >>> data = await resp.read()
    """
    connector_owner = False
    if connector is None:
        connector_owner = True
        connector = TCPConnector(loop=loop, force_close=True)

    session = ClientSession(
        loop=loop,
        cookies=cookies,
        version=version,
        timeout=timeout,
        connector=connector,
        connector_owner=connector_owner,
    )

    return _SessionRequestContextManager(
        session._request(
            method,
            url,
            params=params,
            data=data,
            json=json,
            headers=headers,
            skip_auto_headers=skip_auto_headers,
            auth=auth,
            allow_redirects=allow_redirects,
            max_redirects=max_redirects,
            compress=compress,
            chunked=chunked,
            expect100=expect100,
            raise_for_status=raise_for_status,
            read_until_eof=read_until_eof,
            proxy=proxy,
            proxy_auth=proxy_auth,
            read_bufsize=read_bufsize,
            max_line_size=max_line_size,
            max_field_size=max_field_size,
        ),
        session,
    )

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