{
    "file_diffs": [
        {
            "old_file_content": "",
            "new_file_content": "Add runtime type check for ``ClientSession`` ``timeout`` parameter.\n",
            "header": {
                "file": {
                    "path": "CHANGES/8021.bugfix"
                },
                "misc_line": "new file mode 100644"
            },
            "index_line": {
                "old_commit_hash": "00000000",
                "new_commit_hash": "f43843a5",
                "mode": ""
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "/dev/null"
            },
            "plus_file": {
                "path": "b/CHANGES/8021.bugfix"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 0,
                            "length": 0
                        },
                        "new_range": {
                            "start": 1,
                            "length": null
                        },
                        "section": ""
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "Add runtime type check for ``ClientSession`` ``timeout`` parameter.",
                                "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 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\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\nChristopher Schmitt\nClaudiu Popa\nColin Dunklau\nCong Xu\nDamien Nadé\nDan King\nDan Xu\nDaniel García\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\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 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 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é\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\nPaulius Šileikis\nPaulus Schoutsen\nPavel Kamaev\nPavel Polyakov\nPavel Sapezhko\nPavol Vargovčík\nPawel Kowalski\nPawel Miech\nPepe Osca\nPhilipp A.\nPieter van Beek\nQiao Han\nRafael Viotti\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\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\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Марк Коренберг\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 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\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\nChristopher Schmitt\nClaudiu Popa\nColin Dunklau\nCong Xu\nDamien Nadé\nDan King\nDan Xu\nDaniel García\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\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 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é\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\nPaulius Šileikis\nPaulus Schoutsen\nPavel Kamaev\nPavel Polyakov\nPavel Sapezhko\nPavol Vargovčík\nPawel Kowalski\nPawel Miech\nPepe Osca\nPhilipp A.\nPieter van Beek\nQiao Han\nRafael Viotti\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\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\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Марк Коренберг\nСемён Марьясин\n",
            "header": {
                "file": {
                    "path": "CONTRIBUTORS.txt"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "931d5c5b",
                "new_commit_hash": "e94381dc",
                "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": 143,
                            "length": 6
                        },
                        "new_range": {
                            "start": 143,
                            "length": 7
                        },
                        "section": "Hugo Hromic"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "Hugo van Kemenade",
                                "type": "context"
                            },
                            {
                                "content": "Hynek Schlawack",
                                "type": "context"
                            },
                            {
                                "content": "Igor Alexandrov",
                                "type": "context"
                            },
                            {
                                "content": "Igor Bolshakov",
                                "type": "added"
                            },
                            {
                                "content": "Igor Davydenko",
                                "type": "context"
                            },
                            {
                                "content": "Igor Mozharovsky",
                                "type": "context"
                            },
                            {
                                "content": "Igor Pavlov",
                                "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 SimpleNamespace, 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    Literal,\n    Mapping,\n    Optional,\n    Set,\n    Tuple,\n    Type,\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 as ClientConnectionError,\n    ClientConnectorCertificateError as ClientConnectorCertificateError,\n    ClientConnectorError as ClientConnectorError,\n    ClientConnectorSSLError as ClientConnectorSSLError,\n    ClientError as ClientError,\n    ClientHttpProxyError as ClientHttpProxyError,\n    ClientOSError as ClientOSError,\n    ClientPayloadError as ClientPayloadError,\n    ClientProxyConnectionError as ClientProxyConnectionError,\n    ClientResponseError as ClientResponseError,\n    ClientSSLError as ClientSSLError,\n    ContentTypeError as ContentTypeError,\n    InvalidURL as InvalidURL,\n    ServerConnectionError as ServerConnectionError,\n    ServerDisconnectedError as ServerDisconnectedError,\n    ServerFingerprintMismatch as ServerFingerprintMismatch,\n    ServerTimeoutError as ServerTimeoutError,\n    TooManyRedirects as TooManyRedirects,\n    WSServerHandshakeError as 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 ClientWebSocketResponse as ClientWebSocketResponse\nfrom .connector import (\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    get_running_loop,\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, StrOrURL\n\n__all__ = (\n    # client_exceptions\n    \"ClientConnectionError\",\n    \"ClientConnectorCertificateError\",\n    \"ClientConnectorError\",\n    \"ClientConnectorSSLError\",\n    \"ClientError\",\n    \"ClientHttpProxyError\",\n    \"ClientOSError\",\n    \"ClientPayloadError\",\n    \"ClientProxyConnectionError\",\n    \"ClientResponseError\",\n    \"ClientSSLError\",\n    \"ContentTypeError\",\n    \"InvalidURL\",\n    \"ServerConnectionError\",\n    \"ServerDisconnectedError\",\n    \"ServerFingerprintMismatch\",\n    \"ServerTimeoutError\",\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    \"request\",\n)\n\n\nif TYPE_CHECKING:\n    from ssl import SSLContext\nelse:\n    SSLContext = 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_RetType = TypeVar(\"_RetType\")\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        if loop is None:\n            if connector is not None:\n                loop = connector._loop\n\n        loop = get_running_loop(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 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        if timeout is sentinel:\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            self._timeout = timeout  # type: ignore[assignment]\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        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    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.is_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: Optional[Mapping[str, str]] = 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: Optional[str] = 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: Optional[Union[SSLContext, Literal[False], Fingerprint]] = None,\n        server_hostname: Optional[str] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        trace_request_ctx: Optional[SimpleNamespace] = 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        proxy_headers = self._prepare_headers(proxy_headers)\n\n        try:\n            url = self._build_url(str_or_url)\n        except ValueError as e:\n            raise InvalidURL(str_or_url) from e\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 not None:\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                while True:\n                    url, auth_from_url = strip_auth_from_url(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                    if auth is None:\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,\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,\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                            assert self._connector is not None\n                            conn = await self._connector.connect(\n                                req, traces=traces, timeout=real_timeout\n                            )\n                    except asyncio.TimeoutError as exc:\n                        raise ServerTimeoutError(\n                            \"Connection timeout \" \"to host {}\".format(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 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_url = URL(\n                                r_url, encoded=not self._requote_redirect_url\n                            )\n\n                        except ValueError as e:\n                            raise InvalidURL(r_url) from e\n\n                        scheme = parsed_url.scheme\n                        if scheme not in (\"http\", \"https\", \"\"):\n                            resp.close()\n                            raise ValueError(\"Can redirect only to http or https\")\n                        elif not scheme:\n                            parsed_url = url.join(parsed_url)\n\n                        if url.origin() != parsed_url.origin():\n                            auth = None\n                            headers.pop(hdrs.AUTHORIZATION, None)\n\n                        url = parsed_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: float = 10.0,\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: Optional[Mapping[str, str]] = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, Literal[False], None, Fingerprint] = None,\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: float = 10.0,\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: Optional[Mapping[str, str]] = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, Literal[False], None, Fingerprint] = None,\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\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        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            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                timeout,\n                autoclose,\n                autoping,\n                self._loop,\n                receive_timeout=receive_timeout,\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    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(hdrs.METH_GET, url, allow_redirects=allow_redirects, **kwargs)\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(self._request(hdrs.METH_DELETE, url, **kwargs))\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 = 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 = await self._coro\n        return self._resp\n\n\nclass _RequestContextManager(_BaseRequestContextManager[ClientResponse]):\n    __slots__ = ()\n\n    async def __aexit__(\n        self,\n        exc_type: Optional[Type[BaseException]],\n        exc: Optional[BaseException],\n        tb: Optional[TracebackType],\n    ) -> None:\n        # We're basing behavior on the exception as it can be caused by\n        # user code unrelated to the status of the connection.  If you\n        # would like to close a connection you must do that\n        # explicitly.  Otherwise connection error handling should kick in\n        # and close/recycle the connection as required.\n        self._resp.release()\n        await self._resp.wait_for_close()\n\n\nclass _WSRequestContextManager(_BaseRequestContextManager[ClientWebSocketResponse]):\n    __slots__ = ()\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.close()\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: Optional[Mapping[str, str]] = 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 SimpleNamespace, 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    Literal,\n    Mapping,\n    Optional,\n    Set,\n    Tuple,\n    Type,\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 as ClientConnectionError,\n    ClientConnectorCertificateError as ClientConnectorCertificateError,\n    ClientConnectorError as ClientConnectorError,\n    ClientConnectorSSLError as ClientConnectorSSLError,\n    ClientError as ClientError,\n    ClientHttpProxyError as ClientHttpProxyError,\n    ClientOSError as ClientOSError,\n    ClientPayloadError as ClientPayloadError,\n    ClientProxyConnectionError as ClientProxyConnectionError,\n    ClientResponseError as ClientResponseError,\n    ClientSSLError as ClientSSLError,\n    ContentTypeError as ContentTypeError,\n    InvalidURL as InvalidURL,\n    ServerConnectionError as ServerConnectionError,\n    ServerDisconnectedError as ServerDisconnectedError,\n    ServerFingerprintMismatch as ServerFingerprintMismatch,\n    ServerTimeoutError as ServerTimeoutError,\n    TooManyRedirects as TooManyRedirects,\n    WSServerHandshakeError as 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 ClientWebSocketResponse as ClientWebSocketResponse\nfrom .connector import (\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    get_running_loop,\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, StrOrURL\n\n__all__ = (\n    # client_exceptions\n    \"ClientConnectionError\",\n    \"ClientConnectorCertificateError\",\n    \"ClientConnectorError\",\n    \"ClientConnectorSSLError\",\n    \"ClientError\",\n    \"ClientHttpProxyError\",\n    \"ClientOSError\",\n    \"ClientPayloadError\",\n    \"ClientProxyConnectionError\",\n    \"ClientResponseError\",\n    \"ClientSSLError\",\n    \"ContentTypeError\",\n    \"InvalidURL\",\n    \"ServerConnectionError\",\n    \"ServerDisconnectedError\",\n    \"ServerFingerprintMismatch\",\n    \"ServerTimeoutError\",\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    \"request\",\n)\n\n\nif TYPE_CHECKING:\n    from ssl import SSLContext\nelse:\n    SSLContext = 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_RetType = TypeVar(\"_RetType\")\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        if loop is None:\n            if connector is not None:\n                loop = connector._loop\n\n        loop = get_running_loop(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 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        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        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    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.is_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: Optional[Mapping[str, str]] = 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: Optional[str] = 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: Optional[Union[SSLContext, Literal[False], Fingerprint]] = None,\n        server_hostname: Optional[str] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        trace_request_ctx: Optional[SimpleNamespace] = 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        proxy_headers = self._prepare_headers(proxy_headers)\n\n        try:\n            url = self._build_url(str_or_url)\n        except ValueError as e:\n            raise InvalidURL(str_or_url) from e\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 not None:\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                while True:\n                    url, auth_from_url = strip_auth_from_url(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                    if auth is None:\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,\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,\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                            assert self._connector is not None\n                            conn = await self._connector.connect(\n                                req, traces=traces, timeout=real_timeout\n                            )\n                    except asyncio.TimeoutError as exc:\n                        raise ServerTimeoutError(\n                            \"Connection timeout \" \"to host {}\".format(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 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_url = URL(\n                                r_url, encoded=not self._requote_redirect_url\n                            )\n\n                        except ValueError as e:\n                            raise InvalidURL(r_url) from e\n\n                        scheme = parsed_url.scheme\n                        if scheme not in (\"http\", \"https\", \"\"):\n                            resp.close()\n                            raise ValueError(\"Can redirect only to http or https\")\n                        elif not scheme:\n                            parsed_url = url.join(parsed_url)\n\n                        if url.origin() != parsed_url.origin():\n                            auth = None\n                            headers.pop(hdrs.AUTHORIZATION, None)\n\n                        url = parsed_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: float = 10.0,\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: Optional[Mapping[str, str]] = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, Literal[False], None, Fingerprint] = None,\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: float = 10.0,\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: Optional[Mapping[str, str]] = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, Literal[False], None, Fingerprint] = None,\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\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        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            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                timeout,\n                autoclose,\n                autoping,\n                self._loop,\n                receive_timeout=receive_timeout,\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    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(hdrs.METH_GET, url, allow_redirects=allow_redirects, **kwargs)\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(self._request(hdrs.METH_DELETE, url, **kwargs))\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 = 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 = await self._coro\n        return self._resp\n\n\nclass _RequestContextManager(_BaseRequestContextManager[ClientResponse]):\n    __slots__ = ()\n\n    async def __aexit__(\n        self,\n        exc_type: Optional[Type[BaseException]],\n        exc: Optional[BaseException],\n        tb: Optional[TracebackType],\n    ) -> None:\n        # We're basing behavior on the exception as it can be caused by\n        # user code unrelated to the status of the connection.  If you\n        # would like to close a connection you must do that\n        # explicitly.  Otherwise connection error handling should kick in\n        # and close/recycle the connection as required.\n        self._resp.release()\n        await self._resp.wait_for_close()\n\n\nclass _WSRequestContextManager(_BaseRequestContextManager[ClientWebSocketResponse]):\n    __slots__ = ()\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.close()\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: Optional[Mapping[str, str]] = 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": "83ef1ba5",
                "new_commit_hash": "bcf32fda",
                "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": 272,
                            "length": 7
                        },
                        "new_range": {
                            "start": 272,
                            "length": 7
                        },
                        "section": "class ClientSession:"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        self._default_auth = auth",
                                "type": "context"
                            },
                            {
                                "content": "        self._version = version",
                                "type": "context"
                            },
                            {
                                "content": "        self._json_serialize = json_serialize",
                                "type": "context"
                            },
                            {
                                "content": "        if timeout is sentinel:",
                                "type": "deleted"
                            },
                            {
                                "content": "        if timeout is sentinel or timeout is None:",
                                "type": "added"
                            },
                            {
                                "content": "            self._timeout = DEFAULT_TIMEOUT",
                                "type": "context"
                            },
                            {
                                "content": "            if read_timeout is not sentinel:",
                                "type": "context"
                            },
                            {
                                "content": "                warnings.warn(",
                                "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        ]\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        if loop is None:\n            if connector is not None:\n                loop = connector._loop\n\n        loop = get_running_loop(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 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        if timeout is sentinel:\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            self._timeout = timeout  # type: ignore[assignment]\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        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    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.is_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: Optional[Mapping[str, str]] = 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: Optional[str] = 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: Optional[Union[SSLContext, Literal[False], Fingerprint]] = None,\n        server_hostname: Optional[str] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        trace_request_ctx: Optional[SimpleNamespace] = 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        proxy_headers = self._prepare_headers(proxy_headers)\n\n        try:\n            url = self._build_url(str_or_url)\n        except ValueError as e:\n            raise InvalidURL(str_or_url) from e\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 not None:\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                while True:\n                    url, auth_from_url = strip_auth_from_url(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                    if auth is None:\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,\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,\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                            assert self._connector is not None\n                            conn = await self._connector.connect(\n                                req, traces=traces, timeout=real_timeout\n                            )\n                    except asyncio.TimeoutError as exc:\n                        raise ServerTimeoutError(\n                            \"Connection timeout \" \"to host {}\".format(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 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_url = URL(\n                                r_url, encoded=not self._requote_redirect_url\n                            )\n\n                        except ValueError as e:\n                            raise InvalidURL(r_url) from e\n\n                        scheme = parsed_url.scheme\n                        if scheme not in (\"http\", \"https\", \"\"):\n                            resp.close()\n                            raise ValueError(\"Can redirect only to http or https\")\n                        elif not scheme:\n                            parsed_url = url.join(parsed_url)\n\n                        if url.origin() != parsed_url.origin():\n                            auth = None\n                            headers.pop(hdrs.AUTHORIZATION, None)\n\n                        url = parsed_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: float = 10.0,\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: Optional[Mapping[str, str]] = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, Literal[False], None, Fingerprint] = None,\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: float = 10.0,\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: Optional[Mapping[str, str]] = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, Literal[False], None, Fingerprint] = None,\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\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        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            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                timeout,\n                autoclose,\n                autoping,\n                self._loop,\n                receive_timeout=receive_timeout,\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    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(hdrs.METH_GET, url, allow_redirects=allow_redirects, **kwargs)\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(self._request(hdrs.METH_DELETE, url, **kwargs))\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": 206,
                            "end_lineno": 332,
                            "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        ]\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        if loop is None:\n            if connector is not None:\n                loop = connector._loop\n\n        loop = get_running_loop(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 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        if timeout is sentinel:\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            self._timeout = timeout  # type: ignore[assignment]\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        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    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.is_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: Optional[Mapping[str, str]] = 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: Optional[str] = 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: Optional[Union[SSLContext, Literal[False], Fingerprint]] = None,\n        server_hostname: Optional[str] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        trace_request_ctx: Optional[SimpleNamespace] = 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        proxy_headers = self._prepare_headers(proxy_headers)\n\n        try:\n            url = self._build_url(str_or_url)\n        except ValueError as e:\n            raise InvalidURL(str_or_url) from e\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 not None:\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                while True:\n                    url, auth_from_url = strip_auth_from_url(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                    if auth is None:\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,\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,\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                            assert self._connector is not None\n                            conn = await self._connector.connect(\n                                req, traces=traces, timeout=real_timeout\n                            )\n                    except asyncio.TimeoutError as exc:\n                        raise ServerTimeoutError(\n                            \"Connection timeout \" \"to host {}\".format(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 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_url = URL(\n                                r_url, encoded=not self._requote_redirect_url\n                            )\n\n                        except ValueError as e:\n                            raise InvalidURL(r_url) from e\n\n                        scheme = parsed_url.scheme\n                        if scheme not in (\"http\", \"https\", \"\"):\n                            resp.close()\n                            raise ValueError(\"Can redirect only to http or https\")\n                        elif not scheme:\n                            parsed_url = url.join(parsed_url)\n\n                        if url.origin() != parsed_url.origin():\n                            auth = None\n                            headers.pop(hdrs.AUTHORIZATION, None)\n\n                        url = parsed_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: float = 10.0,\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: Optional[Mapping[str, str]] = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, Literal[False], None, Fingerprint] = None,\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: float = 10.0,\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: Optional[Mapping[str, str]] = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, Literal[False], None, Fingerprint] = None,\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\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        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            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                timeout,\n                autoclose,\n                autoping,\n                self._loop,\n                receive_timeout=receive_timeout,\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    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(hdrs.METH_GET, url, allow_redirects=allow_redirects, **kwargs)\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(self._request(hdrs.METH_DELETE, url, **kwargs))\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": 170,
                                "end_lineno": 1160,
                                "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        ]\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        if loop is None:\n            if connector is not None:\n                loop = connector._loop\n\n        loop = get_running_loop(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 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        if timeout is sentinel:\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            self._timeout = timeout  # type: ignore[assignment]\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        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    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.is_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: Optional[Mapping[str, str]] = 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: Optional[str] = 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: Optional[Union[SSLContext, Literal[False], Fingerprint]] = None,\n        server_hostname: Optional[str] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        trace_request_ctx: Optional[SimpleNamespace] = 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        proxy_headers = self._prepare_headers(proxy_headers)\n\n        try:\n            url = self._build_url(str_or_url)\n        except ValueError as e:\n            raise InvalidURL(str_or_url) from e\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 not None:\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                while True:\n                    url, auth_from_url = strip_auth_from_url(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                    if auth is None:\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,\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,\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                            assert self._connector is not None\n                            conn = await self._connector.connect(\n                                req, traces=traces, timeout=real_timeout\n                            )\n                    except asyncio.TimeoutError as exc:\n                        raise ServerTimeoutError(\n                            \"Connection timeout \" \"to host {}\".format(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 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_url = URL(\n                                r_url, encoded=not self._requote_redirect_url\n                            )\n\n                        except ValueError as e:\n                            raise InvalidURL(r_url) from e\n\n                        scheme = parsed_url.scheme\n                        if scheme not in (\"http\", \"https\", \"\"):\n                            resp.close()\n                            raise ValueError(\"Can redirect only to http or https\")\n                        elif not scheme:\n                            parsed_url = url.join(parsed_url)\n\n                        if url.origin() != parsed_url.origin():\n                            auth = None\n                            headers.pop(hdrs.AUTHORIZATION, None)\n\n                        url = parsed_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: float = 10.0,\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: Optional[Mapping[str, str]] = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, Literal[False], None, Fingerprint] = None,\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: float = 10.0,\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: Optional[Mapping[str, str]] = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, Literal[False], None, Fingerprint] = None,\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\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        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            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                timeout,\n                autoclose,\n                autoping,\n                self._loop,\n                receive_timeout=receive_timeout,\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    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(hdrs.METH_GET, url, allow_redirects=allow_redirects, **kwargs)\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(self._request(hdrs.METH_DELETE, url, **kwargs))\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": 170,
                            "end_lineno": 1160,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 289,
                            "length": 7
                        },
                        "new_range": {
                            "start": 289,
                            "length": 12
                        },
                        "section": "class ClientSession:"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "                    stacklevel=2,",
                                "type": "context"
                            },
                            {
                                "content": "                )",
                                "type": "context"
                            },
                            {
                                "content": "        else:",
                                "type": "context"
                            },
                            {
                                "content": "            self._timeout = timeout  # type: ignore[assignment]",
                                "type": "deleted"
                            },
                            {
                                "content": "            if not isinstance(timeout, ClientTimeout):",
                                "type": "added"
                            },
                            {
                                "content": "                raise ValueError(",
                                "type": "added"
                            },
                            {
                                "content": "                    f\"timeout parameter cannot be of {type(timeout)} type, \"",
                                "type": "added"
                            },
                            {
                                "content": "                    \"please use 'timeout=ClientTimeout(...)'\",",
                                "type": "added"
                            },
                            {
                                "content": "                )",
                                "type": "added"
                            },
                            {
                                "content": "            self._timeout = timeout",
                                "type": "added"
                            },
                            {
                                "content": "            if read_timeout is not sentinel:",
                                "type": "context"
                            },
                            {
                                "content": "                raise ValueError(",
                                "type": "context"
                            },
                            {
                                "content": "                    \"read_timeout and timeout parameters \"",
                                "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        ]\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        if loop is None:\n            if connector is not None:\n                loop = connector._loop\n\n        loop = get_running_loop(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 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        if timeout is sentinel:\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            self._timeout = timeout  # type: ignore[assignment]\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        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    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.is_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: Optional[Mapping[str, str]] = 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: Optional[str] = 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: Optional[Union[SSLContext, Literal[False], Fingerprint]] = None,\n        server_hostname: Optional[str] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        trace_request_ctx: Optional[SimpleNamespace] = 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        proxy_headers = self._prepare_headers(proxy_headers)\n\n        try:\n            url = self._build_url(str_or_url)\n        except ValueError as e:\n            raise InvalidURL(str_or_url) from e\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 not None:\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                while True:\n                    url, auth_from_url = strip_auth_from_url(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                    if auth is None:\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,\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,\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                            assert self._connector is not None\n                            conn = await self._connector.connect(\n                                req, traces=traces, timeout=real_timeout\n                            )\n                    except asyncio.TimeoutError as exc:\n                        raise ServerTimeoutError(\n                            \"Connection timeout \" \"to host {}\".format(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 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_url = URL(\n                                r_url, encoded=not self._requote_redirect_url\n                            )\n\n                        except ValueError as e:\n                            raise InvalidURL(r_url) from e\n\n                        scheme = parsed_url.scheme\n                        if scheme not in (\"http\", \"https\", \"\"):\n                            resp.close()\n                            raise ValueError(\"Can redirect only to http or https\")\n                        elif not scheme:\n                            parsed_url = url.join(parsed_url)\n\n                        if url.origin() != parsed_url.origin():\n                            auth = None\n                            headers.pop(hdrs.AUTHORIZATION, None)\n\n                        url = parsed_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: float = 10.0,\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: Optional[Mapping[str, str]] = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, Literal[False], None, Fingerprint] = None,\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: float = 10.0,\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: Optional[Mapping[str, str]] = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, Literal[False], None, Fingerprint] = None,\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\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        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            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                timeout,\n                autoclose,\n                autoping,\n                self._loop,\n                receive_timeout=receive_timeout,\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    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(hdrs.METH_GET, url, allow_redirects=allow_redirects, **kwargs)\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(self._request(hdrs.METH_DELETE, url, **kwargs))\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": 206,
                            "end_lineno": 332,
                            "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        ]\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        if loop is None:\n            if connector is not None:\n                loop = connector._loop\n\n        loop = get_running_loop(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 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        if timeout is sentinel:\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            self._timeout = timeout  # type: ignore[assignment]\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        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    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.is_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: Optional[Mapping[str, str]] = 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: Optional[str] = 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: Optional[Union[SSLContext, Literal[False], Fingerprint]] = None,\n        server_hostname: Optional[str] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        trace_request_ctx: Optional[SimpleNamespace] = 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        proxy_headers = self._prepare_headers(proxy_headers)\n\n        try:\n            url = self._build_url(str_or_url)\n        except ValueError as e:\n            raise InvalidURL(str_or_url) from e\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 not None:\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                while True:\n                    url, auth_from_url = strip_auth_from_url(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                    if auth is None:\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,\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,\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                            assert self._connector is not None\n                            conn = await self._connector.connect(\n                                req, traces=traces, timeout=real_timeout\n                            )\n                    except asyncio.TimeoutError as exc:\n                        raise ServerTimeoutError(\n                            \"Connection timeout \" \"to host {}\".format(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 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_url = URL(\n                                r_url, encoded=not self._requote_redirect_url\n                            )\n\n                        except ValueError as e:\n                            raise InvalidURL(r_url) from e\n\n                        scheme = parsed_url.scheme\n                        if scheme not in (\"http\", \"https\", \"\"):\n                            resp.close()\n                            raise ValueError(\"Can redirect only to http or https\")\n                        elif not scheme:\n                            parsed_url = url.join(parsed_url)\n\n                        if url.origin() != parsed_url.origin():\n                            auth = None\n                            headers.pop(hdrs.AUTHORIZATION, None)\n\n                        url = parsed_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: float = 10.0,\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: Optional[Mapping[str, str]] = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, Literal[False], None, Fingerprint] = None,\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: float = 10.0,\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: Optional[Mapping[str, str]] = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, Literal[False], None, Fingerprint] = None,\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\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        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            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                timeout,\n                autoclose,\n                autoping,\n                self._loop,\n                receive_timeout=receive_timeout,\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    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(hdrs.METH_GET, url, allow_redirects=allow_redirects, **kwargs)\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(self._request(hdrs.METH_DELETE, url, **kwargs))\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": 170,
                                "end_lineno": 1160,
                                "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        ]\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        if loop is None:\n            if connector is not None:\n                loop = connector._loop\n\n        loop = get_running_loop(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 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        if timeout is sentinel:\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            self._timeout = timeout  # type: ignore[assignment]\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        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    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.is_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: Optional[Mapping[str, str]] = 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: Optional[str] = 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: Optional[Union[SSLContext, Literal[False], Fingerprint]] = None,\n        server_hostname: Optional[str] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        trace_request_ctx: Optional[SimpleNamespace] = 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        proxy_headers = self._prepare_headers(proxy_headers)\n\n        try:\n            url = self._build_url(str_or_url)\n        except ValueError as e:\n            raise InvalidURL(str_or_url) from e\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 not None:\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                while True:\n                    url, auth_from_url = strip_auth_from_url(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                    if auth is None:\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,\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,\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                            assert self._connector is not None\n                            conn = await self._connector.connect(\n                                req, traces=traces, timeout=real_timeout\n                            )\n                    except asyncio.TimeoutError as exc:\n                        raise ServerTimeoutError(\n                            \"Connection timeout \" \"to host {}\".format(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 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_url = URL(\n                                r_url, encoded=not self._requote_redirect_url\n                            )\n\n                        except ValueError as e:\n                            raise InvalidURL(r_url) from e\n\n                        scheme = parsed_url.scheme\n                        if scheme not in (\"http\", \"https\", \"\"):\n                            resp.close()\n                            raise ValueError(\"Can redirect only to http or https\")\n                        elif not scheme:\n                            parsed_url = url.join(parsed_url)\n\n                        if url.origin() != parsed_url.origin():\n                            auth = None\n                            headers.pop(hdrs.AUTHORIZATION, None)\n\n                        url = parsed_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: float = 10.0,\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: Optional[Mapping[str, str]] = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, Literal[False], None, Fingerprint] = None,\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: float = 10.0,\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: Optional[Mapping[str, str]] = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, Literal[False], None, Fingerprint] = None,\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\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        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            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                timeout,\n                autoclose,\n                autoping,\n                self._loop,\n                receive_timeout=receive_timeout,\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    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(hdrs.METH_GET, url, allow_redirects=allow_redirects, **kwargs)\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(self._request(hdrs.METH_DELETE, url, **kwargs))\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": 170,
                            "end_lineno": 1160,
                            "parent": null
                        }
                    ],
                    "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, List\nfrom unittest import mock\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_reqrep import ClientRequest\nfrom aiohttp.connector import BaseConnector, TCPConnector\nfrom aiohttp.helpers import DEBUG\nfrom aiohttp.test_utils import make_mocked_coro\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\nasync def test_cookie_jar_usage(loop, aiohttp_client) -> 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_argument() -> None:\n    session = ClientSession(timeout=500)\n    assert session.timeout == 500\n    await session.close()\n\n\nasync def test_client_session_timeout_zero() -> None:\n    timeout = client.ClientTimeout(total=10, connect=0, sock_connect=0, sock_read=0)\n    try:\n        async with ClientSession(timeout=timeout) as session:\n            await session.get(\"http://example.com\")\n    except asyncio.TimeoutError:\n        pytest.fail(\"0 should disable timeout.\")\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",
            "new_file_content": "import asyncio\nimport contextlib\nimport gc\nimport io\nimport json\nfrom http.cookies import SimpleCookie\nfrom typing import Any, List\nfrom unittest import mock\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_reqrep import ClientRequest\nfrom aiohttp.connector import BaseConnector, TCPConnector\nfrom aiohttp.helpers import DEBUG\nfrom aiohttp.test_utils import make_mocked_coro\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\nasync def test_cookie_jar_usage(loop, aiohttp_client) -> 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() -> None:\n    timeout = client.ClientTimeout(total=10, connect=0, sock_connect=0, sock_read=0)\n    try:\n        async with ClientSession(timeout=timeout) as session:\n            await session.get(\"http://example.com\")\n    except asyncio.TimeoutError:\n        pytest.fail(\"0 should disable timeout.\")\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",
            "header": {
                "file": {
                    "path": "tests/test_client_session.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "2823fc46",
                "new_commit_hash": "a0654ed8",
                "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": 814,
                            "length": 12
                        },
                        "new_range": {
                            "start": 814,
                            "length": 6
                        },
                        "section": "async def test_client_session_timeout_default_args(loop) -> None:"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "    await session1.close()",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "async def test_client_session_timeout_argument() -> None:",
                                "type": "deleted"
                            },
                            {
                                "content": "    session = ClientSession(timeout=500)",
                                "type": "deleted"
                            },
                            {
                                "content": "    assert session.timeout == 500",
                                "type": "deleted"
                            },
                            {
                                "content": "    await session.close()",
                                "type": "deleted"
                            },
                            {
                                "content": "",
                                "type": "deleted"
                            },
                            {
                                "content": "",
                                "type": "deleted"
                            },
                            {
                                "content": "async def test_client_session_timeout_zero() -> None:",
                                "type": "context"
                            },
                            {
                                "content": "    timeout = client.ClientTimeout(total=10, connect=0, sock_connect=0, sock_read=0)",
                                "type": "context"
                            },
                            {
                                "content": "    try:",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [],
                    "deleted_entities": [
                        {
                            "file_name": "tests/test_client_session.py",
                            "type": "function",
                            "name": "test_client_session_timeout_argument",
                            "content": "async def test_client_session_timeout_argument() -> None:\n    session = ClientSession(timeout=500)\n    assert session.timeout == 500\n    await session.close()",
                            "ast_type_str": "AsyncFunctionDef",
                            "start_lineno": 817,
                            "end_lineno": 820,
                            "parent": null
                        }
                    ]
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 829,
                            "length": 6
                        },
                        "new_range": {
                            "start": 823,
                            "length": 13
                        },
                        "section": "async def test_client_session_timeout_zero() -> None:"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        pytest.fail(\"0 should disable timeout.\")",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "async def test_client_session_timeout_bad_argument() -> None:",
                                "type": "added"
                            },
                            {
                                "content": "    with pytest.raises(ValueError):",
                                "type": "added"
                            },
                            {
                                "content": "        ClientSession(timeout=\"test_bad_argumnet\")",
                                "type": "added"
                            },
                            {
                                "content": "    with pytest.raises(ValueError):",
                                "type": "added"
                            },
                            {
                                "content": "        ClientSession(timeout=100)",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "async def test_requote_redirect_url_default() -> None:",
                                "type": "context"
                            },
                            {
                                "content": "    session = ClientSession()",
                                "type": "context"
                            },
                            {
                                "content": "    assert session.requote_redirect_url",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [
                        {
                            "file_name": "tests/test_client_session.py",
                            "type": "function",
                            "name": "test_client_session_timeout_bad_argument",
                            "content": "async 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)",
                            "ast_type_str": "AsyncFunctionDef",
                            "start_lineno": 826,
                            "end_lineno": 830,
                            "parent": null
                        }
                    ],
                    "deleted_entities": []
                }
            ]
        }
    ],
    "old_commit_hash": "41968f892dfdd098d28d2f55561f5009461e661f^",
    "new_commit_hash": "41968f892dfdd098d28d2f55561f5009461e661f",
    "commit_message": "Backport to 3.9: Add runtime type check for `ClientSession` `timeout` param (#8022) (#8027)",
    "commit_date": "2024-01-12T19:15:51Z",
    "metadata": {}
}
{
    "repo_name": "aiohttp",
    "new_commit_hash": "41968f892dfdd098d28d2f55561f5009461e661f",
    "test_file_codes": [
        "import asyncio\nimport contextlib\nimport gc\nimport io\nimport json\nfrom http.cookies import SimpleCookie\nfrom typing import Any, List\nfrom unittest import mock\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_reqrep import ClientRequest\nfrom aiohttp.connector import BaseConnector, TCPConnector\nfrom aiohttp.helpers import DEBUG\nfrom aiohttp.test_utils import make_mocked_coro\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\nasync def test_cookie_jar_usage(loop, aiohttp_client) -> 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() -> None:\n    timeout = client.ClientTimeout(total=10, connect=0, sock_connect=0, sock_read=0)\n    try:\n        async with ClientSession(timeout=timeout) as session:\n            await session.get(\"http://example.com\")\n    except asyncio.TimeoutError:\n        pytest.fail(\"0 should disable timeout.\")\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",
        "import asyncio\nimport os\nimport socket\nimport ssl\nimport sys\nfrom hashlib import md5, sha256\nfrom pathlib import Path\nfrom tempfile import TemporaryDirectory\nfrom uuid import uuid4\n\nimport pytest\n\nfrom aiohttp.test_utils import loop_context\n\ntry:\n    import trustme\n\n    # Check if the CA is available in runtime, MacOS on Py3.10 fails somehow\n    trustme.CA()\n\n    TRUSTME: bool = True\nexcept ImportError:\n    TRUSTME = False\n\npytest_plugins = [\"aiohttp.pytest_plugin\", \"pytester\"]\n\nIS_HPUX = sys.platform.startswith(\"hp-ux\")\nIS_LINUX = sys.platform.startswith(\"linux\")\n\n\n@pytest.fixture\ndef tls_certificate_authority():\n    if not TRUSTME:\n        pytest.xfail(\"trustme is not supported\")\n    return trustme.CA()\n\n\n@pytest.fixture\ndef tls_certificate(tls_certificate_authority):\n    return tls_certificate_authority.issue_cert(\n        \"localhost\",\n        \"xn--prklad-4va.localhost\",\n        \"127.0.0.1\",\n        \"::1\",\n    )\n\n\n@pytest.fixture\ndef ssl_ctx(tls_certificate):\n    ssl_ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)\n    tls_certificate.configure_cert(ssl_ctx)\n    return ssl_ctx\n\n\n@pytest.fixture\ndef client_ssl_ctx(tls_certificate_authority):\n    ssl_ctx = ssl.create_default_context(purpose=ssl.Purpose.SERVER_AUTH)\n    tls_certificate_authority.configure_trust(ssl_ctx)\n    return ssl_ctx\n\n\n@pytest.fixture\ndef tls_ca_certificate_pem_path(tls_certificate_authority):\n    with tls_certificate_authority.cert_pem.tempfile() as ca_cert_pem:\n        yield ca_cert_pem\n\n\n@pytest.fixture\ndef tls_certificate_pem_path(tls_certificate):\n    with tls_certificate.private_key_and_cert_chain_pem.tempfile() as cert_pem:\n        yield cert_pem\n\n\n@pytest.fixture\ndef tls_certificate_pem_bytes(tls_certificate):\n    return tls_certificate.cert_chain_pems[0].bytes()\n\n\n@pytest.fixture\ndef tls_certificate_fingerprint_sha256(tls_certificate_pem_bytes):\n    tls_cert_der = ssl.PEM_cert_to_DER_cert(tls_certificate_pem_bytes.decode())\n    return sha256(tls_cert_der).digest()\n\n\n@pytest.fixture\ndef unix_sockname(tmp_path, tmp_path_factory):\n    \"\"\"Generate an fs path to the UNIX domain socket for testing.\n\n    N.B. Different OS kernels have different fs path length limitations\n    for it. For Linux, it's 108, for HP-UX it's 92 (or higher) depending\n    on its version. For for most of the BSDs (Open, Free, macOS) it's\n    mostly 104 but sometimes it can be down to 100.\n\n    Ref: https://github.com/aio-libs/aiohttp/issues/3572\n    \"\"\"\n    if not hasattr(socket, \"AF_UNIX\"):\n        pytest.skip(\"requires UNIX sockets\")\n\n    max_sock_len = 92 if IS_HPUX else 108 if IS_LINUX else 100\n    \"\"\"Amount of bytes allocated for the UNIX socket path by OS kernel.\n\n    Ref: https://unix.stackexchange.com/a/367012/27133\n    \"\"\"\n\n    sock_file_name = \"unix.sock\"\n    unique_prefix = f\"{uuid4()!s}-\"\n    unique_prefix_len = len(unique_prefix.encode())\n\n    root_tmp_dir = Path(\"/tmp\").resolve()\n    os_tmp_dir = Path(os.getenv(\"TMPDIR\", \"/tmp\")).resolve()\n    original_base_tmp_path = Path(\n        str(tmp_path_factory.getbasetemp()),\n    ).resolve()\n\n    original_base_tmp_path_hash = md5(\n        str(original_base_tmp_path).encode(),\n    ).hexdigest()\n\n    def make_tmp_dir(base_tmp_dir):\n        return TemporaryDirectory(\n            dir=str(base_tmp_dir),\n            prefix=\"pt-\",\n            suffix=f\"-{original_base_tmp_path_hash!s}\",\n        )\n\n    def assert_sock_fits(sock_path):\n        sock_path_len = len(sock_path.encode())\n        # exit-check to verify that it's correct and simplify debugging\n        # in the future\n        assert sock_path_len <= max_sock_len, (\n            \"Suggested UNIX socket ({sock_path}) is {sock_path_len} bytes \"\n            \"long but the current kernel only has {max_sock_len} bytes \"\n            \"allocated to hold it so it must be shorter. \"\n            \"See https://github.com/aio-libs/aiohttp/issues/3572 \"\n            \"for more info.\"\n        ).format_map(locals())\n\n    paths = original_base_tmp_path, os_tmp_dir, root_tmp_dir\n    unique_paths = [p for n, p in enumerate(paths) if p not in paths[:n]]\n    paths_num = len(unique_paths)\n\n    for num, tmp_dir_path in enumerate(paths, 1):\n        with make_tmp_dir(tmp_dir_path) as tmpd:\n            tmpd = Path(tmpd).resolve()\n            sock_path = str(tmpd / sock_file_name)\n            sock_path_len = len(sock_path.encode())\n\n            if num >= paths_num:\n                # exit-check to verify that it's correct and simplify\n                # debugging in the future\n                assert_sock_fits(sock_path)\n\n            if sock_path_len <= max_sock_len:\n                if max_sock_len - sock_path_len >= unique_prefix_len:\n                    # If we're lucky to have extra space in the path,\n                    # let's also make it more unique\n                    sock_path = str(tmpd / \"\".join((unique_prefix, sock_file_name)))\n                    # Double-checking it:\n                    assert_sock_fits(sock_path)\n                yield sock_path\n                return\n\n\n@pytest.fixture\ndef pipe_name():\n    name = rf\"\\\\.\\pipe\\{uuid4().hex}\"\n    return name\n\n\n@pytest.fixture\ndef selector_loop():\n    policy = asyncio.WindowsSelectorEventLoopPolicy()\n    asyncio.set_event_loop_policy(policy)\n\n    with loop_context(policy.new_event_loop) as _loop:\n        asyncio.set_event_loop(_loop)\n        yield _loop\n\n\n@pytest.fixture\ndef netrc_contents(\n    tmp_path: Path,\n    monkeypatch: pytest.MonkeyPatch,\n    request: pytest.FixtureRequest,\n):\n    \"\"\"\n    Prepare :file:`.netrc` with given contents.\n\n    Monkey-patches :envvar:`NETRC` to point to created file.\n    \"\"\"\n    netrc_contents = getattr(request, \"param\", None)\n\n    netrc_file_path = tmp_path / \".netrc\"\n    if netrc_contents is not None:\n        netrc_file_path.write_text(netrc_contents)\n\n    monkeypatch.setenv(\"NETRC\", str(netrc_file_path))\n\n    return netrc_file_path\n"
    ],
    "test_file_names": [
        "test_1.py",
        "conftest.py"
    ],
    "setup_res_code": 0,
    "setup_res_stdout": "re-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/requirements/cython.txt\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/tools/gen.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/hdrs.py\n./tools/gen.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/_helpers.pyx\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/_http_parser.pyx\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/_http_writer.pyx\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/_websocket.pyx\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/_helpers.pyi\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/_cparser.pxd\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/_find_header.pxd\ncython -3 -o aiohttp/_helpers.c aiohttp/_helpers.pyx -I aiohttp -Werror\ncython -3 -o aiohttp/_http_parser.c aiohttp/_http_parser.pyx -I aiohttp -Werror\ncython -3 -o aiohttp/_http_writer.c aiohttp/_http_writer.pyx -I aiohttp -Werror\ncython -3 -o aiohttp/_websocket.c aiohttp/_websocket.pyx -I aiohttp -Werror\ncd vendor/llhttp; npm install\n\n> llhttp@9.1.3 prepare\n> npm run clean && npm run build-ts\n\n\n> llhttp@9.1.3 clean\n> rm -rf lib && rm -rf test/tmp\n\n\n> llhttp@9.1.3 build-ts\n> tsc\n\n\nadded 157 packages, and audited 158 packages in 4s\n\n23 packages are looking for funding\n  run `npm fund` for details\n\n5 vulnerabilities (4 moderate, 1 high)\n\nTo address issues that do not require attention, run:\n  npm audit fix\n\nSome issues need review, and may require choosing\na different dependency.\n\nRun `npm audit` for details.\nmake -C vendor/llhttp generate\nmake[1]: Entering directory '/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/vendor/llhttp'\nnpx ts-node bin/generate.ts\nmake[1]: Leaving directory '/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/vendor/llhttp'\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/__init__.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/abc.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/base_protocol.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/client.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/client_exceptions.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/client_proto.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/client_reqrep.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/client_ws.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/compression_utils.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/connector.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/cookiejar.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/formdata.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/helpers.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/http.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/http_exceptions.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/http_parser.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/http_websocket.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/http_writer.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/locks.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/log.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/multipart.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/payload.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/payload_streamer.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/pytest_plugin.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/resolver.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/streams.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/tcp_helpers.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/test_utils.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/tracing.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/typedefs.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/web.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/web_app.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/web_exceptions.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/web_fileresponse.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/web_log.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/web_middlewares.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/web_protocol.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/web_request.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/web_response.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/web_routedef.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/web_runner.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/web_server.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/web_urldispatcher.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/web_ws.py\nre-hash /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/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 43ms\nPrepared 1 package in 0.31ms\nInstalled 1 package in 24ms\n + pip==24.3.1\nResolved 3 packages in 15ms\nInstalled 3 packages in 36ms\n + cython==3.0.5\n + multidict==6.0.4\n + typing-extensions==4.7.1\nResolved 95 packages in 45ms\nUninstalled 1 package in 6ms\nInstalled 93 packages in 150ms\n + aiodns==3.1.1\n + aiohttp-theme==0.1.6\n + aioredis==2.0.1\n + aiosignal==1.3.1\n + alabaster==0.7.13\n + annotated-types==0.5.0\n + async-timeout==4.0.3\n + attrs==23.1.0\n + babel==2.12.1\n + blockdiag==3.0.0\n + brotli==1.1.0\n + build==0.10.0\n + certifi==2023.7.22\n + cffi==1.15.1\n + cfgv==3.3.1\n + charset-normalizer==3.2.0\n + cherry-picker==2.2.0\n + click==8.1.6\n + coverage==7.3.2\n + cryptography==41.0.3\n + distlib==0.3.7\n + docutils==0.20.1\n + exceptiongroup==1.1.2\n + filelock==3.12.2\n + freezegun==1.3.0\n + frozenlist==1.4.0\n + funcparserlib==1.0.1\n + gidgethub==5.3.0\n + gunicorn==21.2.0\n + identify==2.5.26\n + idna==3.4\n + imagesize==1.4.1\n + importlib-metadata==8.5.0\n + importlib-resources==6.4.5\n + incremental==22.10.0\n + iniconfig==2.0.0\n + jinja2==3.1.2\n + markupsafe==2.1.3\n + mypy==1.7.1\n + mypy-extensions==1.0.0\n + nodeenv==1.8.0\n + packaging==23.1\n + pillow==9.5.0\n - pip==24.3.1\n + pip==23.2.1\n + pip-tools==7.3.0\n + platformdirs==3.10.0\n + pluggy==1.2.0\n + pre-commit==3.5.0\n + proxy-py==2.4.4rc4\n + pycares==4.3.0\n + pycparser==2.21\n + pydantic==2.2.0\n + pydantic-core==2.6.0\n + pygments==2.15.1\n + pyjwt==2.8.0\n + pyproject-hooks==1.0.0\n + pytest==7.4.3\n + pytest-cov==4.1.0\n + pytest-mock==3.12.0\n + python-dateutil==2.8.2\n + python-on-whales==0.67.0\n + pyyaml==6.0.1\n + re-assert==1.1.0\n + regex==2023.6.3\n + requests==2.31.0\n + setuptools==68.0.0\n + setuptools-git==1.2\n + six==1.16.0\n + slotscheck==0.17.1\n + snowballstemmer==2.2.0\n + sphinx==7.1.2\n + sphinxcontrib-applehelp==1.0.4\n + sphinxcontrib-blockdiag==3.0.0\n + sphinxcontrib-devhelp==1.0.2\n + sphinxcontrib-htmlhelp==2.0.1\n + sphinxcontrib-jsmath==1.0.1\n + sphinxcontrib-qthelp==1.0.3\n + sphinxcontrib-serializinghtml==1.1.5\n + sphinxcontrib-towncrier==0.4.0a0\n + tomli==2.0.1\n + towncrier==23.11.0\n + tqdm==4.65.0\n + trustme==1.1.0\n + typer==0.9.0\n + uritemplate==4.1.1\n + urllib3==2.0.4\n + uvloop==0.19.0\n + virtualenv==20.24.2\n + wait-for-it==2.2.2\n + webcolors==1.13\n + wheel==0.41.0\n + yarl==1.9.3\n + zipp==3.21.0\nResolved 8 packages in 1.33s\nPrepared 1 package in 16.55s\nInstalled 1 package in 1ms\n + aiohttp==3.9.1.dev0 (from file:///home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f)\nResolved 24 packages in 15ms\nInstalled 5 packages in 7ms\n + async-generator==1.10\n + brotlipy==0.7.0\n + chardet==5.2.0\n + multdict==0.0.5\n + pytest-asyncio==0.23.8\n",
    "new_commit_res_code": 0,
    "new_commit_res_stdout": "============================= test session starts ==============================\nplatform linux -- Python 3.9.21, pytest-7.4.3, pluggy-1.2.0 -- /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/.venv/bin/python\ncachedir: .pytest_cache\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f\nconfigfile: setup.cfg\nplugins: mock-3.12.0, asyncio-0.23.8, cov-4.1.0\nasyncio: mode=strict\ncollecting ... collected 54 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        [  3%]\nr2e_tests/test_1.py::test_init_headers_list_of_tuples[pyloop] PASSED     [  5%]\nr2e_tests/test_1.py::test_init_headers_MultiDict[pyloop] PASSED          [  7%]\nr2e_tests/test_1.py::test_init_headers_list_of_tuples_with_duplicates[pyloop] PASSED [  9%]\nr2e_tests/test_1.py::test_init_cookies_with_simple_dict[pyloop] PASSED   [ 11%]\nr2e_tests/test_1.py::test_init_cookies_with_list_of_tuples[pyloop] PASSED [ 12%]\nr2e_tests/test_1.py::test_merge_headers[pyloop] PASSED                   [ 14%]\nr2e_tests/test_1.py::test_merge_headers_with_multi_dict[pyloop] PASSED   [ 16%]\nr2e_tests/test_1.py::test_merge_headers_with_list_of_tuples[pyloop] PASSED [ 18%]\nr2e_tests/test_1.py::test_merge_headers_with_list_of_tuples_duplicated_names[pyloop] PASSED [ 20%]\nr2e_tests/test_1.py::test_http_GET[pyloop] PASSED                        [ 22%]\nr2e_tests/test_1.py::test_http_OPTIONS[pyloop] PASSED                    [ 24%]\nr2e_tests/test_1.py::test_http_HEAD[pyloop] PASSED                       [ 25%]\nr2e_tests/test_1.py::test_http_POST[pyloop] PASSED                       [ 27%]\nr2e_tests/test_1.py::test_http_PUT[pyloop] PASSED                        [ 29%]\nr2e_tests/test_1.py::test_http_PATCH[pyloop] PASSED                      [ 31%]\nr2e_tests/test_1.py::test_http_DELETE[pyloop] PASSED                     [ 33%]\nr2e_tests/test_1.py::test_close[pyloop] PASSED                           [ 35%]\nr2e_tests/test_1.py::test_closed[pyloop] PASSED                          [ 37%]\nr2e_tests/test_1.py::test_connector[pyloop] PASSED                       [ 38%]\nr2e_tests/test_1.py::test_create_connector[pyloop] PASSED                [ 40%]\nr2e_tests/test_1.py::test_connector_loop[pyloop] PASSED                  [ 42%]\nr2e_tests/test_1.py::test_detach[pyloop] PASSED                          [ 44%]\nr2e_tests/test_1.py::test_request_closed_session[pyloop] PASSED          [ 46%]\nr2e_tests/test_1.py::test_close_flag_for_closed_connector[pyloop] PASSED [ 48%]\nr2e_tests/test_1.py::test_double_close[pyloop] PASSED                    [ 50%]\nr2e_tests/test_1.py::test_del[pyloop] PASSED                             [ 51%]\nr2e_tests/test_1.py::test_del_debug[pyloop] PASSED                       [ 53%]\nr2e_tests/test_1.py::test_session_context_manager[pyloop] PASSED         [ 55%]\nr2e_tests/test_1.py::test_borrow_connector_loop[pyloop] PASSED           [ 57%]\nr2e_tests/test_1.py::test_reraise_os_error[pyloop] PASSED                [ 59%]\nr2e_tests/test_1.py::test_close_conn_on_error[pyloop] PASSED             [ 61%]\nr2e_tests/test_1.py::test_cookie_jar_usage[pyloop] PASSED                [ 62%]\nr2e_tests/test_1.py::test_session_default_version[pyloop] PASSED         [ 64%]\nr2e_tests/test_1.py::test_session_loop[pyloop] PASSED                    [ 66%]\nr2e_tests/test_1.py::test_proxy_str[pyloop] PASSED                       [ 68%]\nr2e_tests/test_1.py::test_request_tracing[pyloop] PASSED                 [ 70%]\nr2e_tests/test_1.py::test_request_tracing_url_params[pyloop] PASSED      [ 72%]\nr2e_tests/test_1.py::test_request_tracing_exception PASSED               [ 74%]\nr2e_tests/test_1.py::test_request_tracing_interpose_headers[pyloop] PASSED [ 75%]\nr2e_tests/test_1.py::test_client_session_inheritance PASSED              [ 77%]\nr2e_tests/test_1.py::test_client_session_custom_attr[pyloop] SKIPPED     [ 79%]\nr2e_tests/test_1.py::test_client_session_timeout_args[pyloop] PASSED     [ 81%]\nr2e_tests/test_1.py::test_client_session_timeout_default_args[pyloop] PASSED [ 83%]\nr2e_tests/test_1.py::test_client_session_timeout_zero PASSED             [ 85%]\nr2e_tests/test_1.py::test_client_session_timeout_bad_argument PASSED     [ 87%]\nr2e_tests/test_1.py::test_requote_redirect_url_default PASSED            [ 88%]\nr2e_tests/test_1.py::test_requote_redirect_url_default_disable PASSED    [ 90%]\nr2e_tests/test_1.py::test_requote_redirect_setter PASSED                 [ 92%]\nr2e_tests/test_1.py::test_build_url_returns_expected_url[pyloop-base_url=None url='http://example.com/test'] PASSED [ 94%]\nr2e_tests/test_1.py::test_build_url_returns_expected_url[pyloop-base_url=None url=URL('http://example.com/test')] PASSED [ 96%]\nr2e_tests/test_1.py::test_build_url_returns_expected_url[pyloop-base_url='http://example.com' url='/test'] PASSED [ 98%]\nr2e_tests/test_1.py::test_build_url_returns_expected_url[pyloop-base_url=URL('http://example.com') url='/test'] 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 0x7db74db33a90>\n___________________ test_client_session_timeout_args[pyloop] ___________________\n------------------------------ Captured log call -------------------------------\nERROR    asyncio:base_events.py:1753 Unclosed client session\nclient_session: <aiohttp.client.ClientSession object at 0x7db74e33b5e0>\nERROR    asyncio:base_events.py:1753 Unclosed client session\nclient_session: <aiohttp.client.ClientSession object at 0x7db74e33b100>\n___________________ test_client_session_timeout_bad_argument ___________________\n------------------------------ Captured log call -------------------------------\nERROR    asyncio:base_events.py:1753 Unclosed client session\nclient_session: <aiohttp.client.ClientSession object at 0x7db74e33b5b0>\nERROR    asyncio:base_events.py:1753 Unclosed client session\nclient_session: <aiohttp.client.ClientSession object at 0x7db74e33b070>\n\n---------- coverage: platform linux, python 3.9.21-final-0 -----------\nName                                     Stmts   Miss Branch BrPart  Cover\n--------------------------------------------------------------------------\naiohttp/__init__.py                         27      8      2      1    69%\naiohttp/abc.py                              90      2      0      0    98%\naiohttp/base_protocol.py                    66     36     22      3    38%\naiohttp/client.py                          491    141    180     36    67%\naiohttp/client_exceptions.py               135     57     16      1    52%\naiohttp/client_proto.py                    149     49     54     19    60%\naiohttp/client_reqrep.py                   680    219    290     81    61%\naiohttp/client_ws.py                       210    168     66      1    16%\naiohttp/compression_utils.py                70     27     14      1    52%\naiohttp/connector.py                       715    370    311     52    41%\naiohttp/cookiejar.py                       259    139    125     17    41%\naiohttp/formdata.py                         93     76     46      0    12%\naiohttp/hdrs.py                             90      0      0      0   100%\naiohttp/helpers.py                         519    225    178     25    50%\naiohttp/http.py                             11      0      2      0   100%\naiohttp/http_exceptions.py                  50     20      4      0    56%\naiohttp/http_parser.py                     497    378    200      6    18%\naiohttp/http_websocket.py                  388    286    152      0    19%\naiohttp/http_writer.py                     118     40     50     13    58%\naiohttp/locks.py                            24     10      4      0    50%\naiohttp/log.py                               7      0      0      0   100%\naiohttp/multipart.py                       562    455    232      0    14%\naiohttp/payload.py                         219     82     56     10    56%\naiohttp/payload_streamer.py                 29     10      4      0    70%\naiohttp/pytest_plugin.py                   167     63     42      6    60%\naiohttp/resolver.py                         68     36     22      2    42%\naiohttp/streams.py                         396    206    144     24    41%\naiohttp/tcp_helpers.py                      19      2      6      3    80%\naiohttp/test_utils.py                      313    112     52     14    60%\naiohttp/tracing.py                         191     12     32      0    95%\naiohttp/typedefs.py                         23      0      0      0   100%\naiohttp/web.py                             135     95     54      0    22%\naiohttp/web_app.py                         302    108     74     19    58%\naiohttp/web_exceptions.py                  157     16      8      3    87%\naiohttp/web_fileresponse.py                145    121     48      0    12%\naiohttp/web_log.py                         102     37     20      1    59%\naiohttp/web_middlewares.py                  55     37     20      0    24%\naiohttp/web_protocol.py                    343    133    157     47    51%\naiohttp/web_request.py                     435    245    128      8    36%\naiohttp/web_response.py                    483    198    218     51    50%\naiohttp/web_routedef.py                    106     46     10      0    55%\naiohttp/web_runner.py                      215     73     38     12    62%\naiohttp/web_server.py                       41      5      8      1    84%\naiohttp/web_urldispatcher.py               708    359    161     17    44%\naiohttp/web_ws.py                          331    265    116      1    15%\naiohttp/worker.py                          126    126     30      0     0%\ntests/conftest.py                          105    105     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            183    183     14      0     0%\ntests/test_client_fingerprint.py            59     59      0      0     0%\ntests/test_client_functional.py           2340   2340     76      0     0%\ntests/test_client_proto.py                  99     99      0      0     0%\ntests/test_client_request.py               787    787     18      0     0%\ntests/test_client_response.py              464    464      4      0     0%\ntests/test_client_session.py               483    483     23      0     0%\ntests/test_client_ws.py                    415    415      2      0     0%\ntests/test_client_ws_functional.py         606    606     16      0     0%\ntests/test_connector.py                   1520   1520     76      0     0%\ntests/test_cookiejar.py                    349    349     22      0     0%\ntests/test_flowcontrol_streams.py          100    100      0      0     0%\ntests/test_formdata.py                      72     72      6      0     0%\ntests/test_helpers.py                      464    464     24      0     0%\ntests/test_http_exceptions.py              109    109     10      0     0%\ntests/test_http_parser.py                  963    963     50      0     0%\ntests/test_http_writer.py                  182    182     10      0     0%\ntests/test_imports.py                       31     31      6      0     0%\ntests/test_locks.py                         39     39      0      0     0%\ntests/test_loop.py                          36     36      0      0     0%\ntests/test_multipart.py                    747    747     22      0     0%\ntests/test_multipart_helpers.py            446    446      0      0     0%\ntests/test_payload.py                       94     94      0      0     0%\ntests/test_proxy.py                        285    285      0      0     0%\ntests/test_proxy_functional.py             468    468     20      0     0%\ntests/test_pytest_plugin.py                 27     27      0      0     0%\ntests/test_resolver.py                     176    176     12      0     0%\ntests/test_route_def.py                    210    210      0      0     0%\ntests/test_run_app.py                      522    522     30      0     0%\ntests/test_streams.py                     1077   1077     40      0     0%\ntests/test_tcp_helpers.py                   52     52      2      0     0%\ntests/test_test_utils.py                   242    242      6      0     0%\ntests/test_tracing.py                       48     48      0      0     0%\ntests/test_urldispatch.py                  844    844     24      0     0%\ntests/test_web_app.py                      454    454      6      0     0%\ntests/test_web_cli.py                       75     75      0      0     0%\ntests/test_web_exceptions.py               176    176     22      0     0%\ntests/test_web_functional.py              1547   1547     36      0     0%\ntests/test_web_log.py                      116    116      2      0     0%\ntests/test_web_middleware.py               266    266     12      0     0%\ntests/test_web_request.py                  490    490      8      0     0%\ntests/test_web_request_handler.py           40     40      0      0     0%\ntests/test_web_response.py                 863    863      4      0     0%\ntests/test_web_runner.py                   146    146      4      0     0%\ntests/test_web_sendfile.py                  76     76      0      0     0%\ntests/test_web_sendfile_functional.py      652    652     18      0     0%\ntests/test_web_server.py                   163    163      0      0     0%\ntests/test_web_urldispatcher.py            306    306     14      0     0%\ntests/test_web_websocket.py                334    334      8      0     0%\ntests/test_web_websocket_functional.py     542    542     16      0     0%\ntests/test_websocket_handshake.py          152    152     12      0     0%\ntests/test_websocket_parser.py             300    300     12      0     0%\ntests/test_websocket_writer.py              95     95      6      0     0%\ntests/test_worker.py                       191    191      2      0     0%\n--------------------------------------------------------------------------\nTOTAL                                    32348  27081   4124    475    17%\n\n============================= slowest 10 durations =============================\n0.05s call     r2e_tests/test_1.py::test_client_session_timeout_zero\n0.03s teardown r2e_tests/test_1.py::test_client_session_timeout_default_args[pyloop]\n0.03s call     r2e_tests/test_1.py::test_requote_redirect_url_default\n0.03s call     r2e_tests/test_1.py::test_requote_redirect_url_default_disable\n0.03s teardown r2e_tests/test_1.py::test_build_url_returns_expected_url[pyloop-base_url=URL('http://example.com') url='/test']\n0.03s teardown r2e_tests/test_1.py::test_request_tracing_interpose_headers[pyloop]\n0.03s call     r2e_tests/test_1.py::test_request_tracing_exception\n0.03s call     r2e_tests/test_1.py::test_client_session_timeout_bad_argument\n0.03s teardown r2e_tests/test_1.py::test_del[pyloop]\n0.03s teardown r2e_tests/test_1.py::test_request_tracing_url_params[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_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\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']\nSKIPPED [1] r2e_tests/test_1.py:781: The check is applied in DEBUG mode only\n======================== 53 passed, 1 skipped in 5.12s =========================\n",
    "new_commit_res_stderr": "",
    "old_commit_res_code": 1,
    "old_commit_res_stdout": "============================= test session starts ==============================\nplatform linux -- Python 3.9.21, pytest-7.4.3, pluggy-1.2.0 -- /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/.venv/bin/python\ncachedir: .pytest_cache\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f\nconfigfile: setup.cfg\nplugins: mock-3.12.0, asyncio-0.23.8, cov-4.1.0\nasyncio: mode=strict\ncollecting ... collected 54 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        [  3%]\nr2e_tests/test_1.py::test_init_headers_list_of_tuples[pyloop] PASSED     [  5%]\nr2e_tests/test_1.py::test_init_headers_MultiDict[pyloop] PASSED          [  7%]\nr2e_tests/test_1.py::test_init_headers_list_of_tuples_with_duplicates[pyloop] PASSED [  9%]\nr2e_tests/test_1.py::test_init_cookies_with_simple_dict[pyloop] PASSED   [ 11%]\nr2e_tests/test_1.py::test_init_cookies_with_list_of_tuples[pyloop] PASSED [ 12%]\nr2e_tests/test_1.py::test_merge_headers[pyloop] PASSED                   [ 14%]\nr2e_tests/test_1.py::test_merge_headers_with_multi_dict[pyloop] PASSED   [ 16%]\nr2e_tests/test_1.py::test_merge_headers_with_list_of_tuples[pyloop] PASSED [ 18%]\nr2e_tests/test_1.py::test_merge_headers_with_list_of_tuples_duplicated_names[pyloop] PASSED [ 20%]\nr2e_tests/test_1.py::test_http_GET[pyloop] PASSED                        [ 22%]\nr2e_tests/test_1.py::test_http_OPTIONS[pyloop] PASSED                    [ 24%]\nr2e_tests/test_1.py::test_http_HEAD[pyloop] PASSED                       [ 25%]\nr2e_tests/test_1.py::test_http_POST[pyloop] PASSED                       [ 27%]\nr2e_tests/test_1.py::test_http_PUT[pyloop] PASSED                        [ 29%]\nr2e_tests/test_1.py::test_http_PATCH[pyloop] PASSED                      [ 31%]\nr2e_tests/test_1.py::test_http_DELETE[pyloop] PASSED                     [ 33%]\nr2e_tests/test_1.py::test_close[pyloop] PASSED                           [ 35%]\nr2e_tests/test_1.py::test_closed[pyloop] PASSED                          [ 37%]\nr2e_tests/test_1.py::test_connector[pyloop] PASSED                       [ 38%]\nr2e_tests/test_1.py::test_create_connector[pyloop] PASSED                [ 40%]\nr2e_tests/test_1.py::test_connector_loop[pyloop] PASSED                  [ 42%]\nr2e_tests/test_1.py::test_detach[pyloop] PASSED                          [ 44%]\nr2e_tests/test_1.py::test_request_closed_session[pyloop] PASSED          [ 46%]\nr2e_tests/test_1.py::test_close_flag_for_closed_connector[pyloop] PASSED [ 48%]\nr2e_tests/test_1.py::test_double_close[pyloop] PASSED                    [ 50%]\nr2e_tests/test_1.py::test_del[pyloop] PASSED                             [ 51%]\nr2e_tests/test_1.py::test_del_debug[pyloop] PASSED                       [ 53%]\nr2e_tests/test_1.py::test_session_context_manager[pyloop] PASSED         [ 55%]\nr2e_tests/test_1.py::test_borrow_connector_loop[pyloop] PASSED           [ 57%]\nr2e_tests/test_1.py::test_reraise_os_error[pyloop] PASSED                [ 59%]\nr2e_tests/test_1.py::test_close_conn_on_error[pyloop] PASSED             [ 61%]\nr2e_tests/test_1.py::test_cookie_jar_usage[pyloop] PASSED                [ 62%]\nr2e_tests/test_1.py::test_session_default_version[pyloop] PASSED         [ 64%]\nr2e_tests/test_1.py::test_session_loop[pyloop] PASSED                    [ 66%]\nr2e_tests/test_1.py::test_proxy_str[pyloop] PASSED                       [ 68%]\nr2e_tests/test_1.py::test_request_tracing[pyloop] PASSED                 [ 70%]\nr2e_tests/test_1.py::test_request_tracing_url_params[pyloop] PASSED      [ 72%]\nr2e_tests/test_1.py::test_request_tracing_exception PASSED               [ 74%]\nr2e_tests/test_1.py::test_request_tracing_interpose_headers[pyloop] PASSED [ 75%]\nr2e_tests/test_1.py::test_client_session_inheritance PASSED              [ 77%]\nr2e_tests/test_1.py::test_client_session_custom_attr[pyloop] SKIPPED     [ 79%]\nr2e_tests/test_1.py::test_client_session_timeout_args[pyloop] PASSED     [ 81%]\nr2e_tests/test_1.py::test_client_session_timeout_default_args[pyloop] PASSED [ 83%]\nr2e_tests/test_1.py::test_client_session_timeout_zero PASSED             [ 85%]\nr2e_tests/test_1.py::test_client_session_timeout_bad_argument FAILED     [ 87%]\nr2e_tests/test_1.py::test_requote_redirect_url_default FAILED            [ 88%]\nr2e_tests/test_1.py::test_requote_redirect_url_default_disable PASSED    [ 90%]\nr2e_tests/test_1.py::test_requote_redirect_setter PASSED                 [ 92%]\nr2e_tests/test_1.py::test_build_url_returns_expected_url[pyloop-base_url=None url='http://example.com/test'] PASSED [ 94%]\nr2e_tests/test_1.py::test_build_url_returns_expected_url[pyloop-base_url=None url=URL('http://example.com/test')] PASSED [ 96%]\nr2e_tests/test_1.py::test_build_url_returns_expected_url[pyloop-base_url='http://example.com' url='/test'] PASSED [ 98%]\nr2e_tests/test_1.py::test_build_url_returns_expected_url[pyloop-base_url=URL('http://example.com') url='/test'] PASSED [100%]\n\n=================================== FAILURES ===================================\n___________________ test_client_session_timeout_bad_argument ___________________\n\n    async def test_client_session_timeout_bad_argument() -> None:\n        with pytest.raises(ValueError):\n>           ClientSession(timeout=\"test_bad_argumnet\")\nE           Failed: DID NOT RAISE <class 'ValueError'>\n\n\nr2e_tests/test_1.py:828: Failed\n------------------------------ Captured log call -------------------------------\nERROR    asyncio:base_events.py:1753 Unclosed client session\nclient_session: <aiohttp.client.ClientSession object at 0x77e02ce9ddf0>\n______________________ test_requote_redirect_url_default _______________________\n\ncls = <class '_pytest.runner.CallInfo'>\nfunc = <function call_runtest_hook.<locals>.<lambda> at 0x77e02ce83a60>\nwhen = 'call'\nreraise = (<class '_pytest.outcomes.Exit'>, <class 'KeyboardInterrupt'>)\n\n    @classmethod\n    def from_call(\n        cls,\n        func: \"Callable[[], TResult]\",\n        when: \"Literal['collect', 'setup', 'call', 'teardown']\",\n        reraise: Optional[\n            Union[Type[BaseException], Tuple[Type[BaseException], ...]]\n        ] = None,\n    ) -> \"CallInfo[TResult]\":\n        \"\"\"Call func, wrapping the result in a CallInfo.\n    \n        :param func:\n            The function to call. Called without arguments.\n        :param when:\n            The phase in which the function is called.\n        :param reraise:\n            Exception or exceptions that shall propagate if raised by the\n            function, instead of being wrapped in the CallInfo.\n        \"\"\"\n        excinfo = None\n        start = timing.time()\n        precise_start = timing.perf_counter()\n        try:\n>           result: Optional[TResult] = func()\n\ncls        = <class '_pytest.runner.CallInfo'>\nduration   = 0.018428832991048694\nexcinfo    = <ExceptionInfo PytestUnraisableExceptionWarning('Exception ignored in: <socket.socket fd=-1, family=AddressFamily.AF_U...arning: unclosed <socket.socket fd=14, family=AddressFamily.AF_UNIX, type=SocketKind.SOCK_STREAM, proto=0>\\n') tblen=7>\nfunc       = <function call_runtest_hook.<locals>.<lambda> at 0x77e02ce83a60>\nprecise_start = 86908.973549482\nprecise_stop = 86908.991978315\nreraise    = (<class '_pytest.outcomes.Exit'>, <class 'KeyboardInterrupt'>)\nresult     = None\nstart      = 1735788552.592362\nstop       = 1735788552.6107922\nwhen       = 'call'\n\n.venv/lib/python3.9/site-packages/_pytest/runner.py:341: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.venv/lib/python3.9/site-packages/_pytest/runner.py:262: in <lambda>\n    lambda: ihook(item=item, **kwds), when=when, reraise=reraise\n        ihook      = <_HookCaller 'pytest_runtest_call'>\n        item       = <Function test_requote_redirect_url_default>\n        kwds       = {}\n.venv/lib/python3.9/site-packages/pluggy/_hooks.py:433: in __call__\n    return self._hookexec(self.name, self._hookimpls, kwargs, firstresult)\n        firstresult = False\n        kwargs     = {'item': <Function test_requote_redirect_url_default>}\n        self       = <_HookCaller 'pytest_runtest_call'>\n.venv/lib/python3.9/site-packages/pluggy/_manager.py:112: in _hookexec\n    return self._inner_hookexec(hook_name, methods, kwargs, firstresult)\n        firstresult = False\n        hook_name  = 'pytest_runtest_call'\n        kwargs     = {'item': <Function test_requote_redirect_url_default>}\n        methods    = [<HookImpl plugin_name='runner', plugin=<module '_pytest.runner' from '/home/gcpuser/buckets/local_repoeval_bucket/rep...http_41968f892dfdd098d28d2f55561f5009461e661f/.venv/lib/python3.9/site-packages/_pytest/unraisableexception.py'>>, ...]\n        self       = <_pytest.config.PytestPluginManager object at 0x77e02fe6fb80>\n.venv/lib/python3.9/site-packages/_pytest/unraisableexception.py:88: in pytest_runtest_call\n    yield from unraisable_exception_runtest_hook()\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\n    def unraisable_exception_runtest_hook() -> Generator[None, None, None]:\n        with catch_unraisable_exception() as cm:\n            yield\n            if cm.unraisable:\n                if cm.unraisable.err_msg is not None:\n                    err_msg = cm.unraisable.err_msg\n                else:\n                    err_msg = \"Exception ignored in\"\n                msg = f\"{err_msg}: {cm.unraisable.object!r}\\n\\n\"\n                msg += \"\".join(\n                    traceback.format_exception(\n                        cm.unraisable.exc_type,\n                        cm.unraisable.exc_value,\n                        cm.unraisable.exc_traceback,\n                    )\n                )\n>               warnings.warn(pytest.PytestUnraisableExceptionWarning(msg))\nE               pytest.PytestUnraisableExceptionWarning: Exception ignored in: <socket.socket fd=-1, family=AddressFamily.AF_UNIX, type=SocketKind.SOCK_STREAM, proto=0>\nE               \nE               Traceback (most recent call last):\nE                 File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_41968f892dfdd098d28d2f55561f5009461e661f/aiohttp/test_utils.py\", line 537, in teardown_test_loop\nE                   gc.collect()\nE               ResourceWarning: unclosed <socket.socket fd=14, family=AddressFamily.AF_UNIX, type=SocketKind.SOCK_STREAM, proto=0>\n\ncm         = <_pytest.unraisableexception.catch_unraisable_exception object at 0x77e02cf94e50>\nerr_msg    = 'Exception ignored in'\nmsg        = 'Exception ignored in: <socket.socket fd=-1, family=AddressFamily.AF_UNIX, type=SocketKind.SOCK_STREAM, proto=0>\\n\\nTr...nResourceWarning: unclosed <socket.socket fd=14, family=AddressFamily.AF_UNIX, type=SocketKind.SOCK_STREAM, proto=0>\\n'\n\n.venv/lib/python3.9/site-packages/_pytest/unraisableexception.py:78: PytestUnraisableExceptionWarning\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 0x77e02cf9c040>\n___________________ test_client_session_timeout_args[pyloop] ___________________\n------------------------------ Captured log call -------------------------------\nERROR    asyncio:base_events.py:1753 Unclosed client session\nclient_session: <aiohttp.client.ClientSession object at 0x77e02ce9d160>\nERROR    asyncio:base_events.py:1753 Unclosed client session\nclient_session: <aiohttp.client.ClientSession object at 0x77e02ce9d3d0>\n\n---------- coverage: platform linux, python 3.9.21-final-0 -----------\nName                                     Stmts   Miss Branch BrPart  Cover\n--------------------------------------------------------------------------\naiohttp/__init__.py                         27      8      2      1    69%\naiohttp/abc.py                              90      2      0      0    98%\naiohttp/base_protocol.py                    66     36     22      3    38%\naiohttp/client.py                          489    141    178     36    67%\naiohttp/client_exceptions.py               135     57     16      1    52%\naiohttp/client_proto.py                    149     49     54     19    60%\naiohttp/client_reqrep.py                   680    219    290     81    61%\naiohttp/client_ws.py                       210    168     66      1    16%\naiohttp/compression_utils.py                70     27     14      1    52%\naiohttp/connector.py                       715    370    311     52    41%\naiohttp/cookiejar.py                       259    139    125     17    41%\naiohttp/formdata.py                         93     76     46      0    12%\naiohttp/hdrs.py                             90      0      0      0   100%\naiohttp/helpers.py                         519    225    178     25    50%\naiohttp/http.py                             11      0      2      0   100%\naiohttp/http_exceptions.py                  50     20      4      0    56%\naiohttp/http_parser.py                     497    378    200      6    18%\naiohttp/http_websocket.py                  388    286    152      0    19%\naiohttp/http_writer.py                     118     40     50     13    58%\naiohttp/locks.py                            24     10      4      0    50%\naiohttp/log.py                               7      0      0      0   100%\naiohttp/multipart.py                       562    455    232      0    14%\naiohttp/payload.py                         219     82     56     10    56%\naiohttp/payload_streamer.py                 29     10      4      0    70%\naiohttp/pytest_plugin.py                   167     62     42      6    61%\naiohttp/resolver.py                         68     36     22      2    42%\naiohttp/streams.py                         396    206    144     24    41%\naiohttp/tcp_helpers.py                      19      2      6      3    80%\naiohttp/test_utils.py                      313    112     52     14    60%\naiohttp/tracing.py                         191     12     32      0    95%\naiohttp/typedefs.py                         23      0      0      0   100%\naiohttp/web.py                             135     95     54      0    22%\naiohttp/web_app.py                         302    108     74     19    58%\naiohttp/web_exceptions.py                  157     16      8      3    87%\naiohttp/web_fileresponse.py                145    121     48      0    12%\naiohttp/web_log.py                         102     37     20      1    59%\naiohttp/web_middlewares.py                  55     37     20      0    24%\naiohttp/web_protocol.py                    343    133    157     47    51%\naiohttp/web_request.py                     435    245    128      8    36%\naiohttp/web_response.py                    483    198    218     51    50%\naiohttp/web_routedef.py                    106     46     10      0    55%\naiohttp/web_runner.py                      215     73     38     12    62%\naiohttp/web_server.py                       41      5      8      1    84%\naiohttp/web_urldispatcher.py               708    359    161     17    44%\naiohttp/web_ws.py                          331    265    116      1    15%\naiohttp/worker.py                          126    126     30      0     0%\ntests/conftest.py                          105    105     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            183    183     14      0     0%\ntests/test_client_fingerprint.py            59     59      0      0     0%\ntests/test_client_functional.py           2340   2340     76      0     0%\ntests/test_client_proto.py                  99     99      0      0     0%\ntests/test_client_request.py               787    787     18      0     0%\ntests/test_client_response.py              464    464      4      0     0%\ntests/test_client_session.py               482    482     23      0     0%\ntests/test_client_ws.py                    415    415      2      0     0%\ntests/test_client_ws_functional.py         606    606     16      0     0%\ntests/test_connector.py                   1520   1520     76      0     0%\ntests/test_cookiejar.py                    349    349     22      0     0%\ntests/test_flowcontrol_streams.py          100    100      0      0     0%\ntests/test_formdata.py                      72     72      6      0     0%\ntests/test_helpers.py                      464    464     24      0     0%\ntests/test_http_exceptions.py              109    109     10      0     0%\ntests/test_http_parser.py                  963    963     50      0     0%\ntests/test_http_writer.py                  182    182     10      0     0%\ntests/test_imports.py                       31     31      6      0     0%\ntests/test_locks.py                         39     39      0      0     0%\ntests/test_loop.py                          36     36      0      0     0%\ntests/test_multipart.py                    747    747     22      0     0%\ntests/test_multipart_helpers.py            446    446      0      0     0%\ntests/test_payload.py                       94     94      0      0     0%\ntests/test_proxy.py                        285    285      0      0     0%\ntests/test_proxy_functional.py             468    468     20      0     0%\ntests/test_pytest_plugin.py                 27     27      0      0     0%\ntests/test_resolver.py                     176    176     12      0     0%\ntests/test_route_def.py                    210    210      0      0     0%\ntests/test_run_app.py                      522    522     30      0     0%\ntests/test_streams.py                     1077   1077     40      0     0%\ntests/test_tcp_helpers.py                   52     52      2      0     0%\ntests/test_test_utils.py                   242    242      6      0     0%\ntests/test_tracing.py                       48     48      0      0     0%\ntests/test_urldispatch.py                  844    844     24      0     0%\ntests/test_web_app.py                      454    454      6      0     0%\ntests/test_web_cli.py                       75     75      0      0     0%\ntests/test_web_exceptions.py               176    176     22      0     0%\ntests/test_web_functional.py              1547   1547     36      0     0%\ntests/test_web_log.py                      116    116      2      0     0%\ntests/test_web_middleware.py               266    266     12      0     0%\ntests/test_web_request.py                  490    490      8      0     0%\ntests/test_web_request_handler.py           40     40      0      0     0%\ntests/test_web_response.py                 863    863      4      0     0%\ntests/test_web_runner.py                   146    146      4      0     0%\ntests/test_web_sendfile.py                  76     76      0      0     0%\ntests/test_web_sendfile_functional.py      652    652     18      0     0%\ntests/test_web_server.py                   163    163      0      0     0%\ntests/test_web_urldispatcher.py            306    306     14      0     0%\ntests/test_web_websocket.py                334    334      8      0     0%\ntests/test_web_websocket_functional.py     542    542     16      0     0%\ntests/test_websocket_handshake.py          152    152     12      0     0%\ntests/test_websocket_parser.py             300    300     12      0     0%\ntests/test_websocket_writer.py              95     95      6      0     0%\ntests/test_worker.py                       191    191      2      0     0%\n--------------------------------------------------------------------------\nTOTAL                                    32345  27079   4122    475    17%\n\n============================= slowest 10 durations =============================\n0.05s call     r2e_tests/test_1.py::test_client_session_timeout_zero\n0.05s teardown r2e_tests/test_1.py::test_connector[pyloop]\n0.04s teardown r2e_tests/test_1.py::test_request_tracing_interpose_headers[pyloop]\n0.03s call     r2e_tests/test_1.py::test_request_tracing_exception\n0.02s call     r2e_tests/test_1.py::test_del_debug[pyloop]\n0.02s call     r2e_tests/test_1.py::test_request_tracing_url_params[pyloop]\n0.02s teardown r2e_tests/test_1.py::test_build_url_returns_expected_url[pyloop-base_url=URL('http://example.com') url='/test']\n0.02s call     r2e_tests/test_1.py::test_requote_redirect_url_default_disable\n0.02s teardown r2e_tests/test_1.py::test_client_session_timeout_args[pyloop]\n0.02s teardown r2e_tests/test_1.py::test_client_session_timeout_default_args[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_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\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']\nSKIPPED [1] r2e_tests/test_1.py:781: The check is applied in DEBUG mode only\nFAILED r2e_tests/test_1.py::test_client_session_timeout_bad_argument - Failed...\nFAILED r2e_tests/test_1.py::test_requote_redirect_url_default - pytest.Pytest...\n=================== 2 failed, 51 passed, 1 skipped in 5.57s ====================\n",
    "old_commit_res_stderr": ""
}
CHANGES/8021.bugfix CONTRIBUTORS.txt aiohttp/client.py 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` Allows Invalid Types for `timeout` Parameter Without Raising Errors

**Description:**
When creating a `ClientSession`, providing an incorrect type for the `timeout` parameter does not trigger an error. For instance, passing a string or integer instead of a `ClientTimeout` instance allows the session to be initialized improperly, which can lead to unexpected behavior or failures during request processing.

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

# Incorrect timeout type provided as a string
session = ClientSession(timeout="invalid_timeout")

# Incorrect timeout type provided as an integer
session = ClientSession(timeout=100)
```

**Expected Behavior:**
Initializing `ClientSession` with an invalid type for the `timeout` parameter should raise a `ValueError`, informing the user to provide a `ClientTimeout` instance.

**Actual Behavior:**
No error is raised when an invalid type is passed to the `timeout` parameter, resulting in a `ClientSession` instance with an improperly configured timeout, which may cause issues during HTTP requests.
[/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 SimpleNamespace, TracebackType
from typing import (
    TYPE_CHECKING,
    Any,
    Awaitable,
    Callable,
    Coroutine,
    Final,
    FrozenSet,
    Generator,
    Generic,
    Iterable,
    List,
    Literal,
    Mapping,
    Optional,
    Set,
    Tuple,
    Type,
    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 as ClientConnectionError,
    ClientConnectorCertificateError as ClientConnectorCertificateError,
    ClientConnectorError as ClientConnectorError,
    ClientConnectorSSLError as ClientConnectorSSLError,
    ClientError as ClientError,
    ClientHttpProxyError as ClientHttpProxyError,
    ClientOSError as ClientOSError,
    ClientPayloadError as ClientPayloadError,
    ClientProxyConnectionError as ClientProxyConnectionError,
    ClientResponseError as ClientResponseError,
    ClientSSLError as ClientSSLError,
    ContentTypeError as ContentTypeError,
    InvalidURL as InvalidURL,
    ServerConnectionError as ServerConnectionError,
    ServerDisconnectedError as ServerDisconnectedError,
    ServerFingerprintMismatch as ServerFingerprintMismatch,
    ServerTimeoutError as ServerTimeoutError,
    TooManyRedirects as TooManyRedirects,
    WSServerHandshakeError as WSServerHandshakeError,
)
from .client_reqrep import (
    ClientRequest as ClientRequest,
    ClientResponse as ClientResponse,
    Fingerprint as Fingerprint,
    RequestInfo as RequestInfo,
    _merge_ssl_params,
)
from .client_ws import ClientWebSocketResponse as ClientWebSocketResponse
from .connector import (
    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,
    get_running_loop,
    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, StrOrURL

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


if TYPE_CHECKING:
    from ssl import SSLContext
else:
    SSLContext = 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)

_RetType = TypeVar("_RetType")
_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:
        if loop is None:
            if connector is not None:
                loop = connector._loop

        loop = get_running_loop(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 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
        if timeout is sentinel:
            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:
            self._timeout = timeout  # type: ignore[assignment]
            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"
                )
        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)

    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.is_absolute() and url.path.startswith("/")
            return self._base_url.join(url)

    async def _request(
        self,
        method: str,
        str_or_url: StrOrURL,
        *,
        params: Optional[Mapping[str, str]] = 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: Optional[str] = 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: Optional[Union[SSLContext, Literal[False], Fingerprint]] = None,
        server_hostname: Optional[str] = None,
        proxy_headers: Optional[LooseHeaders] = None,
        trace_request_ctx: Optional[SimpleNamespace] = 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)
        proxy_headers = self._prepare_headers(proxy_headers)

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

        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 not None:
            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:
                while True:
                    url, auth_from_url = strip_auth_from_url(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:
                        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,
                        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,
                        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,
                        ):
                            assert self._connector is not None
                            conn = await self._connector.connect(
                                req, traces=traces, timeout=real_timeout
                            )
                    except asyncio.TimeoutError as exc:
                        raise ServerTimeoutError(
                            "Connection timeout " "to host {}".format(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 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_url = URL(
                                r_url, encoded=not self._requote_redirect_url
                            )

                        except ValueError as e:
                            raise InvalidURL(r_url) from e

                        scheme = parsed_url.scheme
                        if scheme not in ("http", "https", ""):
                            resp.close()
                            raise ValueError("Can redirect only to http or https")
                        elif not scheme:
                            parsed_url = url.join(parsed_url)

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

                        url = parsed_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: float = 10.0,
        receive_timeout: Optional[float] = None,
        autoclose: bool = True,
        autoping: bool = True,
        heartbeat: Optional[float] = None,
        auth: Optional[BasicAuth] = None,
        origin: Optional[str] = None,
        params: Optional[Mapping[str, str]] = None,
        headers: Optional[LooseHeaders] = None,
        proxy: Optional[StrOrURL] = None,
        proxy_auth: Optional[BasicAuth] = None,
        ssl: Union[SSLContext, Literal[False], None, Fingerprint] = None,
        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: float = 10.0,
        receive_timeout: Optional[float] = None,
        autoclose: bool = True,
        autoping: bool = True,
        heartbeat: Optional[float] = None,
        auth: Optional[BasicAuth] = None,
        origin: Optional[str] = None,
        params: Optional[Mapping[str, str]] = None,
        headers: Optional[LooseHeaders] = None,
        proxy: Optional[StrOrURL] = None,
        proxy_auth: Optional[BasicAuth] = None,
        ssl: Union[SSLContext, Literal[False], None, Fingerprint] = None,
        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 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

        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
            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,
                timeout,
                autoclose,
                autoping,
                self._loop,
                receive_timeout=receive_timeout,
                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

    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 = 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 = await self._coro
        return self._resp


class _RequestContextManager(_BaseRequestContextManager[ClientResponse]):
    __slots__ = ()

    async def __aexit__(
        self,
        exc_type: Optional[Type[BaseException]],
        exc: Optional[BaseException],
        tb: Optional[TracebackType],
    ) -> None:
        # We're basing behavior on the exception as it can be caused by
        # user code unrelated to the status of the connection.  If you
        # would like to close a connection you must do that
        # explicitly.  Otherwise connection error handling should kick in
        # and close/recycle the connection as required.
        self._resp.release()
        await self._resp.wait_for_close()


class _WSRequestContextManager(_BaseRequestContextManager[ClientWebSocketResponse]):
    __slots__ = ()

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


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: Optional[Mapping[str, str]] = 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` Allows Invalid Types for `timeout` Parameter Without Raising Errors

**Description:**
When creating a `ClientSession`, providing an incorrect type for the `timeout` parameter does not trigger an error. For instance, passing a string or integer instead of a `ClientTimeout` instance allows the session to be initialized improperly, which can lead to unexpected behavior or failures during request processing.

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

# Incorrect timeout type provided as a string
session = ClientSession(timeout="invalid_timeout")

# Incorrect timeout type provided as an integer
session = ClientSession(timeout=100)
```

**Expected Behavior:**
Initializing `ClientSession` with an invalid type for the `timeout` parameter should raise a `ValueError`, informing the user to provide a `ClientTimeout` instance.

**Actual Behavior:**
No error is raised when an invalid type is passed to the `timeout` parameter, resulting in a `ClientSession` instance with an improperly configured timeout, which may cause issues during HTTP requests.
[/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_cookie_jar_usage[pyloop]": "PASSED",
    "test_session_default_version[pyloop]": "PASSED",
    "test_session_loop[pyloop]": "PASSED",
    "test_proxy_str[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": "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"
}
diff --git a/aiohttp/client.py b/aiohttp/client.py
index 83ef1ba5..bcf32fda 100644
--- a/aiohttp/client.py
+++ b/aiohttp/client.py
@@ -272,7 +272,7 @@ class ClientSession:
         self._default_auth = auth
         self._version = version
         self._json_serialize = json_serialize
-        if timeout is sentinel:
+        if timeout is sentinel or timeout is None:
             self._timeout = DEFAULT_TIMEOUT
             if read_timeout is not sentinel:
                 warnings.warn(
@@ -289,7 +289,12 @@ class ClientSession:
                     stacklevel=2,
                 )
         else:
-            self._timeout = timeout  # type: ignore[assignment]
+            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 "

{"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 SimpleNamespace, 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    Literal,\n    Mapping,\n    Optional,\n    Set,\n    Tuple,\n    Type,\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 as ClientConnectionError,\n    ClientConnectorCertificateError as ClientConnectorCertificateError,\n    ClientConnectorError as ClientConnectorError,\n    ClientConnectorSSLError as ClientConnectorSSLError,\n    ClientError as ClientError,\n    ClientHttpProxyError as ClientHttpProxyError,\n    ClientOSError as ClientOSError,\n    ClientPayloadError as ClientPayloadError,\n    ClientProxyConnectionError as ClientProxyConnectionError,\n    ClientResponseError as ClientResponseError,\n    ClientSSLError as ClientSSLError,\n    ContentTypeError as ContentTypeError,\n    InvalidURL as InvalidURL,\n    ServerConnectionError as ServerConnectionError,\n    ServerDisconnectedError as ServerDisconnectedError,\n    ServerFingerprintMismatch as ServerFingerprintMismatch,\n    ServerTimeoutError as ServerTimeoutError,\n    TooManyRedirects as TooManyRedirects,\n    WSServerHandshakeError as 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 ClientWebSocketResponse as ClientWebSocketResponse\nfrom .connector import (\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    get_running_loop,\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, StrOrURL\n\n__all__ = (\n    # client_exceptions\n    \"ClientConnectionError\",\n    \"ClientConnectorCertificateError\",\n    \"ClientConnectorError\",\n    \"ClientConnectorSSLError\",\n    \"ClientError\",\n    \"ClientHttpProxyError\",\n    \"ClientOSError\",\n    \"ClientPayloadError\",\n    \"ClientProxyConnectionError\",\n    \"ClientResponseError\",\n    \"ClientSSLError\",\n    \"ContentTypeError\",\n    \"InvalidURL\",\n    \"ServerConnectionError\",\n    \"ServerDisconnectedError\",\n    \"ServerFingerprintMismatch\",\n    \"ServerTimeoutError\",\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    \"request\",\n)\n\n\nif TYPE_CHECKING:\n    from ssl import SSLContext\nelse:\n    SSLContext = 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_RetType = TypeVar(\"_RetType\")\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        if loop is None:\n            if connector is not None:\n                loop = connector._loop\n\n        loop = get_running_loop(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 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        if timeout is sentinel:\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            self._timeout = timeout  # type: ignore[assignment]\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        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    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.is_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: Optional[Mapping[str, str]] = 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: Optional[str] = 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: Optional[Union[SSLContext, Literal[False], Fingerprint]] = None,\n        server_hostname: Optional[str] = None,\n        proxy_headers: Optional[LooseHeaders] = None,\n        trace_request_ctx: Optional[SimpleNamespace] = 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        proxy_headers = self._prepare_headers(proxy_headers)\n\n        try:\n            url = self._build_url(str_or_url)\n        except ValueError as e:\n            raise InvalidURL(str_or_url) from e\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 not None:\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                while True:\n                    url, auth_from_url = strip_auth_from_url(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                    if auth is None:\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,\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,\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                            assert self._connector is not None\n                            conn = await self._connector.connect(\n                                req, traces=traces, timeout=real_timeout\n                            )\n                    except asyncio.TimeoutError as exc:\n                        raise ServerTimeoutError(\n                            \"Connection timeout \" \"to host {}\".format(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 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_url = URL(\n                                r_url, encoded=not self._requote_redirect_url\n                            )\n\n                        except ValueError as e:\n                            raise InvalidURL(r_url) from e\n\n                        scheme = parsed_url.scheme\n                        if scheme not in (\"http\", \"https\", \"\"):\n                            resp.close()\n                            raise ValueError(\"Can redirect only to http or https\")\n                        elif not scheme:\n                            parsed_url = url.join(parsed_url)\n\n                        if url.origin() != parsed_url.origin():\n                            auth = None\n                            headers.pop(hdrs.AUTHORIZATION, None)\n\n                        url = parsed_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: float = 10.0,\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: Optional[Mapping[str, str]] = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, Literal[False], None, Fingerprint] = None,\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: float = 10.0,\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: Optional[Mapping[str, str]] = None,\n        headers: Optional[LooseHeaders] = None,\n        proxy: Optional[StrOrURL] = None,\n        proxy_auth: Optional[BasicAuth] = None,\n        ssl: Union[SSLContext, Literal[False], None, Fingerprint] = None,\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\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        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            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                timeout,\n                autoclose,\n                autoping,\n                self._loop,\n                receive_timeout=receive_timeout,\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    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(hdrs.METH_GET, url, allow_redirects=allow_redirects, **kwargs)\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(self._request(hdrs.METH_DELETE, url, **kwargs))\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 = 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 = await self._coro\n        return self._resp\n\n\nclass _RequestContextManager(_BaseRequestContextManager[ClientResponse]):\n    __slots__ = ()\n\n    async def __aexit__(\n        self,\n        exc_type: Optional[Type[BaseException]],\n        exc: Optional[BaseException],\n        tb: Optional[TracebackType],\n    ) -> None:\n        # We're basing behavior on the exception as it can be caused by\n        # user code unrelated to the status of the connection.  If you\n        # would like to close a connection you must do that\n        # explicitly.  Otherwise connection error handling should kick in\n        # and close/recycle the connection as required.\n        self._resp.release()\n        await self._resp.wait_for_close()\n\n\nclass _WSRequestContextManager(_BaseRequestContextManager[ClientWebSocketResponse]):\n    __slots__ = ()\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.close()\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: Optional[Mapping[str, str]] = 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` Allows Invalid Types for `timeout` Parameter Without Raising Errors

**Description:**
When creating a `ClientSession`, providing an incorrect type for the `timeout` parameter does not trigger an error. For instance, passing a string or integer instead of a `ClientTimeout` instance allows the session to be initialized improperly, which can lead to unexpected behavior or failures during request processing.

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

# Incorrect timeout type provided as a string
session = ClientSession(timeout="invalid_timeout")

# Incorrect timeout type provided as an integer
session = ClientSession(timeout=100)
```

**Expected Behavior:**
Initializing `ClientSession` with an invalid type for the `timeout` parameter should raise a `ValueError`, informing the user to provide a `ClientTimeout` instance.

**Actual Behavior:**
No error is raised when an invalid type is passed to the `timeout` parameter, resulting in a `ClientSession` instance with an improperly configured timeout, which may cause issues during HTTP requests.
[/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 SimpleNamespace, TracebackType
from typing import (
    TYPE_CHECKING,
    Any,
    Awaitable,
    Callable,
    Coroutine,
    Final,
    FrozenSet,
    Generator,
    Generic,
    Iterable,
    List,
    Literal,
    Mapping,
    Optional,
    Set,
    Tuple,
    Type,
    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 as ClientConnectionError,
    ClientConnectorCertificateError as ClientConnectorCertificateError,
    ClientConnectorError as ClientConnectorError,
    ClientConnectorSSLError as ClientConnectorSSLError,
    ClientError as ClientError,
    ClientHttpProxyError as ClientHttpProxyError,
    ClientOSError as ClientOSError,
    ClientPayloadError as ClientPayloadError,
    ClientProxyConnectionError as ClientProxyConnectionError,
    ClientResponseError as ClientResponseError,
    ClientSSLError as ClientSSLError,
    ContentTypeError as ContentTypeError,
    InvalidURL as InvalidURL,
    ServerConnectionError as ServerConnectionError,
    ServerDisconnectedError as ServerDisconnectedError,
    ServerFingerprintMismatch as ServerFingerprintMismatch,
    ServerTimeoutError as ServerTimeoutError,
    TooManyRedirects as TooManyRedirects,
    WSServerHandshakeError as WSServerHandshakeError,
)
from .client_reqrep import (
    ClientRequest as ClientRequest,
    ClientResponse as ClientResponse,
    Fingerprint as Fingerprint,
    RequestInfo as RequestInfo,
    _merge_ssl_params,
)
from .client_ws import ClientWebSocketResponse as ClientWebSocketResponse
from .connector import (
    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,
    get_running_loop,
    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, StrOrURL

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


if TYPE_CHECKING:
    from ssl import SSLContext
else:
    SSLContext = 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)

_RetType = TypeVar("_RetType")
_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:
        if loop is None:
            if connector is not None:
                loop = connector._loop

        loop = get_running_loop(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 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
        if timeout is sentinel:
            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:
            self._timeout = timeout  # type: ignore[assignment]
            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"
                )
        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)

    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.is_absolute() and url.path.startswith("/")
            return self._base_url.join(url)

    async def _request(
        self,
        method: str,
        str_or_url: StrOrURL,
        *,
        params: Optional[Mapping[str, str]] = 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: Optional[str] = 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: Optional[Union[SSLContext, Literal[False], Fingerprint]] = None,
        server_hostname: Optional[str] = None,
        proxy_headers: Optional[LooseHeaders] = None,
        trace_request_ctx: Optional[SimpleNamespace] = 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)
        proxy_headers = self._prepare_headers(proxy_headers)

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

        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 not None:
            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:
                while True:
                    url, auth_from_url = strip_auth_from_url(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:
                        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,
                        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,
                        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,
                        ):
                            assert self._connector is not None
                            conn = await self._connector.connect(
                                req, traces=traces, timeout=real_timeout
                            )
                    except asyncio.TimeoutError as exc:
                        raise ServerTimeoutError(
                            "Connection timeout " "to host {}".format(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 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_url = URL(
                                r_url, encoded=not self._requote_redirect_url
                            )

                        except ValueError as e:
                            raise InvalidURL(r_url) from e

                        scheme = parsed_url.scheme
                        if scheme not in ("http", "https", ""):
                            resp.close()
                            raise ValueError("Can redirect only to http or https")
                        elif not scheme:
                            parsed_url = url.join(parsed_url)

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

                        url = parsed_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: float = 10.0,
        receive_timeout: Optional[float] = None,
        autoclose: bool = True,
        autoping: bool = True,
        heartbeat: Optional[float] = None,
        auth: Optional[BasicAuth] = None,
        origin: Optional[str] = None,
        params: Optional[Mapping[str, str]] = None,
        headers: Optional[LooseHeaders] = None,
        proxy: Optional[StrOrURL] = None,
        proxy_auth: Optional[BasicAuth] = None,
        ssl: Union[SSLContext, Literal[False], None, Fingerprint] = None,
        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: float = 10.0,
        receive_timeout: Optional[float] = None,
        autoclose: bool = True,
        autoping: bool = True,
        heartbeat: Optional[float] = None,
        auth: Optional[BasicAuth] = None,
        origin: Optional[str] = None,
        params: Optional[Mapping[str, str]] = None,
        headers: Optional[LooseHeaders] = None,
        proxy: Optional[StrOrURL] = None,
        proxy_auth: Optional[BasicAuth] = None,
        ssl: Union[SSLContext, Literal[False], None, Fingerprint] = None,
        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 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

        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
            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,
                timeout,
                autoclose,
                autoping,
                self._loop,
                receive_timeout=receive_timeout,
                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

    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 = 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 = await self._coro
        return self._resp


class _RequestContextManager(_BaseRequestContextManager[ClientResponse]):
    __slots__ = ()

    async def __aexit__(
        self,
        exc_type: Optional[Type[BaseException]],
        exc: Optional[BaseException],
        tb: Optional[TracebackType],
    ) -> None:
        # We're basing behavior on the exception as it can be caused by
        # user code unrelated to the status of the connection.  If you
        # would like to close a connection you must do that
        # explicitly.  Otherwise connection error handling should kick in
        # and close/recycle the connection as required.
        self._resp.release()
        await self._resp.wait_for_close()


class _WSRequestContextManager(_BaseRequestContextManager[ClientWebSocketResponse]):
    __slots__ = ()

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


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: Optional[Mapping[str, str]] = 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