{
    "file_diffs": [
        {
            "old_file_content": "\"\"\"HTTP Client for asyncio.\"\"\"\n\nimport asyncio\nimport base64\nimport hashlib\nimport os\nimport sys\nimport traceback\nimport warnings\nimport http.cookies\nimport urllib.parse\n\nimport aiohttp\nfrom .client_reqrep import ClientRequest, ClientResponse\nfrom .errors import WSServerHandshakeError\nfrom .multidict import MultiDictProxy, MultiDict, CIMultiDict, upstr\nfrom .websocket import WS_KEY, WebSocketParser, WebSocketWriter\nfrom .websocket_client import ClientWebSocketResponse\nfrom . import hdrs\n\n\n__all__ = ('ClientSession', 'request', 'get', 'options', 'head',\n           'delete', 'post', 'put', 'patch')\n\nPY_341 = sys.version_info >= (3, 4, 1)\n\n\nclass ClientSession:\n    \"\"\"First-class interface for making HTTP requests.\"\"\"\n\n    _source_traceback = None\n    _connector = None\n\n    def __init__(self, *, connector=None, loop=None, cookies=None,\n                 headers=None, auth=None, request_class=ClientRequest,\n                 response_class=ClientResponse,\n                 ws_response_class=ClientWebSocketResponse):\n\n        if connector is None:\n            connector = aiohttp.TCPConnector(loop=loop)\n            loop = connector._loop  # never None\n        else:\n            if loop is None:\n                loop = connector._loop  # never None\n            elif connector._loop is not loop:\n                raise ValueError(\"loop argument must agree with connector\")\n\n        self._loop = loop\n        if loop.get_debug():\n            self._source_traceback = traceback.extract_stack(sys._getframe(1))\n\n        self._cookies = http.cookies.SimpleCookie()\n\n        # For Backward compatability with `share_cookies` connectors\n        if connector._share_cookies:\n            self._update_cookies(connector.cookies)\n        if cookies is not None:\n            self._update_cookies(cookies)\n        self._connector = connector\n        self._default_auth = auth\n\n        # Convert to list of tuples\n        if headers:\n            headers = CIMultiDict(headers)\n        else:\n            headers = CIMultiDict()\n        self._default_headers = headers\n\n        self._request_class = request_class\n        self._response_class = response_class\n        self._ws_response_class = ws_response_class\n\n    if PY_341:\n        def __del__(self):\n            if not self.closed:\n                self.close()\n\n                warnings.warn(\"Unclosed client session {!r}\".format(self),\n                              ResourceWarning)\n                context = {'client_session': self,\n                           '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    @asyncio.coroutine\n    def request(self, method, url, *,\n                params=None,\n                data=None,\n                headers=None,\n                files=None,\n                auth=None,\n                allow_redirects=True,\n                max_redirects=10,\n                encoding='utf-8',\n                version=aiohttp.HttpVersion11,\n                compress=None,\n                chunked=None,\n                expect100=False,\n                read_until_eof=True):\n        \"\"\"Perform HTTP request.\"\"\"\n\n        if self.closed:\n            raise RuntimeError('Session is closed')\n\n        redirects = 0\n        if not isinstance(method, upstr):\n            method = upstr(method)\n\n        # Merge with default headers and transform to CIMultiDict\n        headers = self._prepare_headers(headers)\n        if auth is None:\n            auth = self._default_auth\n        # It would be confusing if we support explicit Authorization header\n        # with `auth` argument\n        if (headers is not None and\n                auth is not None and\n                hdrs.AUTHORIZATION in headers):\n            raise ValueError(\"Can't combine `Authorization` header with \"\n                             \"`auth` argument\")\n\n        while True:\n            req = self._request_class(\n                method, url, params=params, headers=headers, data=data,\n                cookies=self.cookies, files=files, encoding=encoding,\n                auth=auth, version=version, compress=compress, chunked=chunked,\n                expect100=expect100,\n                loop=self._loop, response_class=self._response_class)\n\n            conn = yield from self._connector.connect(req)\n            try:\n                resp = req.send(conn.writer, conn.reader)\n                try:\n                    yield from resp.start(conn, read_until_eof)\n                except:\n                    resp.close(force=True)\n                    conn.close()\n                    raise\n            except (aiohttp.HttpProcessingError,\n                    aiohttp.ServerDisconnectedError) as exc:\n                raise aiohttp.ClientResponseError() from exc\n            except OSError as exc:\n                raise aiohttp.ClientOSError() from exc\n\n            self._update_cookies(resp.cookies)\n            # For Backward compatability with `share_cookie` connectors\n            if self._connector._share_cookies:\n                self._connector.update_cookies(resp.cookies)\n\n            # redirects\n            if resp.status in (301, 302, 303, 307) and allow_redirects:\n                redirects += 1\n                if max_redirects and redirects >= max_redirects:\n                    resp.close(force=True)\n                    break\n\n                # For 301 and 302, mimic IE behaviour, now changed in RFC.\n                # Details: https://github.com/kennethreitz/requests/pull/269\n                if resp.status != 307:\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\n                         resp.headers.get(hdrs.URI))\n\n                scheme = urllib.parse.urlsplit(r_url)[0]\n                if scheme not in ('http', 'https', ''):\n                    resp.close(force=True)\n                    raise ValueError('Can redirect only to http or https')\n                elif not scheme:\n                    r_url = urllib.parse.urljoin(url, r_url)\n\n                url = urllib.parse.urldefrag(r_url)[0]\n                if url:\n                    yield from resp.release()\n                    continue\n\n            break\n\n        return resp\n\n    @asyncio.coroutine\n    def ws_connect(self, url, *,\n                   protocols=(),\n                   timeout=10.0,\n                   autoclose=True,\n                   autoping=True):\n        \"\"\"Initiate websocket connection.\"\"\"\n\n        sec_key = base64.b64encode(os.urandom(16))\n\n        headers = {\n            hdrs.UPGRADE: hdrs.WEBSOCKET,\n            hdrs.CONNECTION: hdrs.UPGRADE,\n            hdrs.SEC_WEBSOCKET_VERSION: '13',\n            hdrs.SEC_WEBSOCKET_KEY: sec_key.decode(),\n        }\n        if protocols:\n            headers[hdrs.SEC_WEBSOCKET_PROTOCOL] = ','.join(protocols)\n\n        # send request\n        resp = yield from self.request('get', url, headers=headers,\n                                       read_until_eof=False)\n\n        # check handshake\n        if resp.status != 101:\n            raise WSServerHandshakeError('Invalid response status')\n\n        if resp.headers.get(hdrs.UPGRADE, '').lower() != 'websocket':\n            raise WSServerHandshakeError('Invalid upgrade header')\n\n        if resp.headers.get(hdrs.CONNECTION, '').lower() != 'upgrade':\n            raise WSServerHandshakeError('Invalid connection header')\n\n        # key calculation\n        key = resp.headers.get(hdrs.SEC_WEBSOCKET_ACCEPT, '')\n        match = base64.b64encode(\n            hashlib.sha1(sec_key + WS_KEY).digest()).decode()\n        if key != match:\n            raise WSServerHandshakeError('Invalid challenge response')\n\n        # websocket protocol\n        protocol = None\n        if protocols and hdrs.SEC_WEBSOCKET_PROTOCOL in resp.headers:\n            resp_protocols = [\n                proto.strip() for proto in\n                resp.headers[hdrs.SEC_WEBSOCKET_PROTOCOL].split(',')]\n\n            for proto in resp_protocols:\n                if proto in protocols:\n                    protocol = proto\n                    break\n\n        reader = resp.connection.reader.set_parser(WebSocketParser)\n        writer = WebSocketWriter(resp.connection.writer, use_mask=True)\n\n        return self._ws_response_class(reader,\n                                       writer,\n                                       protocol,\n                                       resp,\n                                       timeout,\n                                       autoclose,\n                                       autoping,\n                                       self._loop)\n\n    def _update_cookies(self, cookies):\n        \"\"\"Update shared cookies.\"\"\"\n        if isinstance(cookies, dict):\n            cookies = cookies.items()\n\n        for name, value in cookies:\n            if isinstance(value, http.cookies.Morsel):\n                # use dict method because SimpleCookie class modifies value\n                # before Python3.4\n                dict.__setitem__(self.cookies, name, value)\n            else:\n                self.cookies[name] = value\n\n    def _prepare_headers(self, headers):\n        \"\"\" Add default headers and transform it to CIMultiDict\n        \"\"\"\n        # Convert headers to MultiDict\n        result = CIMultiDict()\n        if headers:\n            if isinstance(headers, dict):\n                headers = headers.items()\n            elif isinstance(headers, (MultiDictProxy, MultiDict)):\n                headers = headers.items()\n            for key, value in headers:\n                result.add(key, value)\n        # Add defaults only if those are not overridden\n        if self._default_headers:\n            for key, value in self._default_headers.items():\n                if key not in result:\n                    result.add(key, value)\n        return result\n\n    @asyncio.coroutine\n    def get(self, url, *, allow_redirects=True, **kwargs):\n        \"\"\"Perform HTTP GET request.\"\"\"\n        resp = yield from self.request(hdrs.METH_GET, url,\n                                       allow_redirects=allow_redirects,\n                                       **kwargs)\n        return resp\n\n    @asyncio.coroutine\n    def options(self, url, *, allow_redirects=True, **kwargs):\n        \"\"\"Perform HTTP OPTIONS request.\"\"\"\n        resp = yield from self.request(hdrs.METH_OPTIONS, url,\n                                       allow_redirects=allow_redirects,\n                                       **kwargs)\n        return resp\n\n    @asyncio.coroutine\n    def head(self, url, *, allow_redirects=False, **kwargs):\n        \"\"\"Perform HTTP HEAD request.\"\"\"\n        resp = yield from self.request(hdrs.METH_HEAD, url,\n                                       allow_redirects=allow_redirects,\n                                       **kwargs)\n        return resp\n\n    @asyncio.coroutine\n    def post(self, url, *, data=None, **kwargs):\n        \"\"\"Perform HTTP POST request.\"\"\"\n        resp = yield from self.request(hdrs.METH_POST, url,\n                                       data=data,\n                                       **kwargs)\n        return resp\n\n    @asyncio.coroutine\n    def put(self, url, *, data=None, **kwargs):\n        \"\"\"Perform HTTP PUT request.\"\"\"\n        resp = yield from self.request(hdrs.METH_PUT, url,\n                                       data=data,\n                                       **kwargs)\n        return resp\n\n    @asyncio.coroutine\n    def patch(self, url, *, data=None, **kwargs):\n        \"\"\"Perform HTTP PATCH request.\"\"\"\n        resp = yield from self.request(hdrs.METH_PATCH, url,\n                                       data=data,\n                                       **kwargs)\n        return resp\n\n    @asyncio.coroutine\n    def delete(self, url, **kwargs):\n        \"\"\"Perform HTTP DELETE request.\"\"\"\n        resp = yield from self.request(hdrs.METH_DELETE, url,\n                                       **kwargs)\n        return resp\n\n    def close(self):\n        \"\"\"Close underlying connector.\n\n        Release all acquired resources.\n        \"\"\"\n        if not self.closed:\n            self._connector.close()\n            self._connector = None\n\n    @property\n    def closed(self):\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):\n        \"\"\"Connector instance used for the session.\"\"\"\n        return self._connector\n\n    @property\n    def cookies(self):\n        \"\"\"The session cookies.\"\"\"\n        return self._cookies\n\n    def detach(self):\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):\n        return self\n\n    def __exit__(self, exc_type, exc_val, exc_tb):\n        self.close()\n\n\n@asyncio.coroutine\ndef request(method, url, *,\n            params=None,\n            data=None,\n            headers=None,\n            cookies=None,\n            files=None,\n            auth=None,\n            allow_redirects=True,\n            max_redirects=10,\n            encoding='utf-8',\n            version=aiohttp.HttpVersion11,\n            compress=None,\n            chunked=None,\n            expect100=False,\n            connector=None,\n            loop=None,\n            read_until_eof=True,\n            request_class=None,\n            response_class=None):\n    \"\"\"Constructs and sends a request. Returns response object.\n\n    :param str method: http method\n    :param str url: request url\n    :param params: (optional) Dictionary or bytes to be sent in the query\n      string of the new request\n    :param data: (optional) Dictionary, bytes, or file-like object to\n      send in the body of the request\n    :param dict headers: (optional) Dictionary of HTTP Headers to send with\n      the request\n    :param dict cookies: (optional) Dict object to send with the request\n    :param auth: (optional) BasicAuth named tuple represent HTTP Basic Auth\n    :type auth: aiohttp.helpers.BasicAuth\n    :param bool allow_redirects: (optional) If set to False, do not follow\n      redirects\n    :param version: Request http version.\n    :type version: aiohttp.protocol.HttpVersion\n    :param bool compress: Set to True if request has to be compressed\n       with deflate encoding.\n    :param chunked: Set to chunk size for chunked transfer encoding.\n    :type chunked: bool or int\n    :param bool expect100: Expect 100-continue response from server.\n    :param connector: BaseConnector sub-class instance to support\n       connection pooling.\n    :type connector: aiohttp.connector.BaseConnector\n    :param bool read_until_eof: Read response until eof if response\n       does not have Content-Length header.\n    :param request_class: (optional) Custom Request class implementation.\n    :param response_class: (optional) Custom Response class implementation.\n    :param loop: Optional event loop.\n\n    Usage::\n\n      >>> import aiohttp\n      >>> resp = yield from aiohttp.request('GET', 'http://python.org/')\n      >>> resp\n      <ClientResponse(python.org/) [200]>\n      >>> data = yield from resp.read()\n\n    \"\"\"\n    if connector is None:\n        connector = aiohttp.TCPConnector(loop=loop, force_close=True)\n\n    kwargs = {}\n\n    if request_class is not None:\n        kwargs['request_class'] = request_class\n\n    if response_class is not None:\n        kwargs['response_class'] = response_class\n\n    session = ClientSession(loop=loop,\n                            cookies=cookies,\n                            connector=connector,\n                            **kwargs)\n    try:\n        resp = yield from session.request(method, url,\n                                          params=params,\n                                          data=data,\n                                          headers=headers,\n                                          files=files,\n                                          auth=auth,\n                                          allow_redirects=allow_redirects,\n                                          max_redirects=max_redirects,\n                                          encoding=encoding,\n                                          version=version,\n                                          compress=compress,\n                                          chunked=chunked,\n                                          expect100=expect100,\n                                          read_until_eof=read_until_eof)\n        return resp\n    finally:\n        session.detach()\n\n\n@asyncio.coroutine\ndef get(url, **kwargs):\n    ret = yield from request(hdrs.METH_GET, url, **kwargs)\n    return ret\n\n\n@asyncio.coroutine\ndef options(url, **kwargs):\n    ret = yield from request(hdrs.METH_OPTIONS, url, **kwargs)\n    return ret\n\n\n@asyncio.coroutine\ndef head(url, **kwargs):\n    ret = yield from request(hdrs.METH_HEAD, url, **kwargs)\n    return ret\n\n\n@asyncio.coroutine\ndef post(url, **kwargs):\n    ret = yield from request(hdrs.METH_POST, url, **kwargs)\n    return ret\n\n\n@asyncio.coroutine\ndef put(url, **kwargs):\n    ret = yield from request(hdrs.METH_PUT, url, **kwargs)\n    return ret\n\n\n@asyncio.coroutine\ndef patch(url, **kwargs):\n    ret = yield from request(hdrs.METH_PATCH, url, **kwargs)\n    return ret\n\n\n@asyncio.coroutine\ndef delete(url, **kwargs):\n    ret = yield from request(hdrs.METH_DELETE, url, **kwargs)\n    return ret\n",
            "new_file_content": "\"\"\"HTTP Client for asyncio.\"\"\"\n\nimport asyncio\nimport base64\nimport hashlib\nimport os\nimport sys\nimport traceback\nimport warnings\nimport http.cookies\nimport urllib.parse\n\nimport aiohttp\nfrom .client_reqrep import ClientRequest, ClientResponse\nfrom .errors import WSServerHandshakeError\nfrom .multidict import MultiDictProxy, MultiDict, CIMultiDict, upstr\nfrom .websocket import WS_KEY, WebSocketParser, WebSocketWriter\nfrom .websocket_client import ClientWebSocketResponse\nfrom . import hdrs\n\n\n__all__ = ('ClientSession', 'request', 'get', 'options', 'head',\n           'delete', 'post', 'put', 'patch')\n\nPY_341 = sys.version_info >= (3, 4, 1)\n\n\nclass ClientSession:\n    \"\"\"First-class interface for making HTTP requests.\"\"\"\n\n    _source_traceback = None\n    _connector = None\n\n    def __init__(self, *, connector=None, loop=None, cookies=None,\n                 headers=None, auth=None, request_class=ClientRequest,\n                 response_class=ClientResponse,\n                 ws_response_class=ClientWebSocketResponse):\n\n        if connector is None:\n            connector = aiohttp.TCPConnector(loop=loop)\n            loop = connector._loop  # never None\n        else:\n            if loop is None:\n                loop = connector._loop  # never None\n            elif connector._loop is not loop:\n                raise ValueError(\"loop argument must agree with connector\")\n\n        self._loop = loop\n        if loop.get_debug():\n            self._source_traceback = traceback.extract_stack(sys._getframe(1))\n\n        self._cookies = http.cookies.SimpleCookie()\n\n        # For Backward compatability with `share_cookies` connectors\n        if connector._share_cookies:\n            self._update_cookies(connector.cookies)\n        if cookies is not None:\n            self._update_cookies(cookies)\n        self._connector = connector\n        self._default_auth = auth\n\n        # Convert to list of tuples\n        if headers:\n            headers = CIMultiDict(headers)\n        else:\n            headers = CIMultiDict()\n        self._default_headers = headers\n\n        self._request_class = request_class\n        self._response_class = response_class\n        self._ws_response_class = ws_response_class\n\n    if PY_341:\n        def __del__(self):\n            if not self.closed:\n                self.close()\n\n                warnings.warn(\"Unclosed client session {!r}\".format(self),\n                              ResourceWarning)\n                context = {'client_session': self,\n                           '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    @asyncio.coroutine\n    def request(self, method, url, *,\n                params=None,\n                data=None,\n                headers=None,\n                files=None,\n                auth=None,\n                allow_redirects=True,\n                max_redirects=10,\n                encoding='utf-8',\n                version=aiohttp.HttpVersion11,\n                compress=None,\n                chunked=None,\n                expect100=False,\n                read_until_eof=True):\n        \"\"\"Perform HTTP request.\"\"\"\n\n        if self.closed:\n            raise RuntimeError('Session is closed')\n\n        redirects = 0\n        if not isinstance(method, upstr):\n            method = upstr(method)\n\n        # Merge with default headers and transform to CIMultiDict\n        headers = self._prepare_headers(headers)\n        if auth is None:\n            auth = self._default_auth\n        # It would be confusing if we support explicit Authorization header\n        # with `auth` argument\n        if (headers is not None and\n                auth is not None and\n                hdrs.AUTHORIZATION in headers):\n            raise ValueError(\"Can't combine `Authorization` header with \"\n                             \"`auth` argument\")\n\n        while True:\n            req = self._request_class(\n                method, url, params=params, headers=headers, data=data,\n                cookies=self.cookies, files=files, encoding=encoding,\n                auth=auth, version=version, compress=compress, chunked=chunked,\n                expect100=expect100,\n                loop=self._loop, response_class=self._response_class)\n\n            conn = yield from self._connector.connect(req)\n            try:\n                resp = req.send(conn.writer, conn.reader)\n                try:\n                    yield from resp.start(conn, read_until_eof)\n                except:\n                    resp.close(force=True)\n                    conn.close()\n                    raise\n            except (aiohttp.HttpProcessingError,\n                    aiohttp.ServerDisconnectedError) as exc:\n                raise aiohttp.ClientResponseError() from exc\n            except OSError as exc:\n                raise aiohttp.ClientOSError() from exc\n\n            self._update_cookies(resp.cookies)\n            # For Backward compatability with `share_cookie` connectors\n            if self._connector._share_cookies:\n                self._connector.update_cookies(resp.cookies)\n\n            # redirects\n            if resp.status in (301, 302, 303, 307) and allow_redirects:\n                redirects += 1\n                if max_redirects and redirects >= max_redirects:\n                    resp.close(force=True)\n                    break\n\n                # For 301 and 302, mimic IE behaviour, now changed in RFC.\n                # Details: https://github.com/kennethreitz/requests/pull/269\n                if resp.status != 307:\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\n                         resp.headers.get(hdrs.URI))\n\n                scheme = urllib.parse.urlsplit(r_url)[0]\n                if scheme not in ('http', 'https', ''):\n                    resp.close(force=True)\n                    raise ValueError('Can redirect only to http or https')\n                elif not scheme:\n                    r_url = urllib.parse.urljoin(url, r_url)\n\n                url = urllib.parse.urldefrag(r_url)[0]\n                if url:\n                    yield from resp.release()\n                    continue\n\n            break\n\n        return resp\n\n    @asyncio.coroutine\n    def ws_connect(self, url, *,\n                   protocols=(),\n                   timeout=10.0,\n                   autoclose=True,\n                   autoping=True):\n        \"\"\"Initiate websocket connection.\"\"\"\n\n        sec_key = base64.b64encode(os.urandom(16))\n\n        headers = {\n            hdrs.UPGRADE: hdrs.WEBSOCKET,\n            hdrs.CONNECTION: hdrs.UPGRADE,\n            hdrs.SEC_WEBSOCKET_VERSION: '13',\n            hdrs.SEC_WEBSOCKET_KEY: sec_key.decode(),\n        }\n        if protocols:\n            headers[hdrs.SEC_WEBSOCKET_PROTOCOL] = ','.join(protocols)\n\n        # send request\n        resp = yield from self.request('get', url, headers=headers,\n                                       read_until_eof=False)\n\n        # check handshake\n        if resp.status != 101:\n            raise WSServerHandshakeError('Invalid response status')\n\n        if resp.headers.get(hdrs.UPGRADE, '').lower() != 'websocket':\n            raise WSServerHandshakeError('Invalid upgrade header')\n\n        if resp.headers.get(hdrs.CONNECTION, '').lower() != 'upgrade':\n            raise WSServerHandshakeError('Invalid connection header')\n\n        # key calculation\n        key = resp.headers.get(hdrs.SEC_WEBSOCKET_ACCEPT, '')\n        match = base64.b64encode(\n            hashlib.sha1(sec_key + WS_KEY).digest()).decode()\n        if key != match:\n            raise WSServerHandshakeError('Invalid challenge response')\n\n        # websocket protocol\n        protocol = None\n        if protocols and hdrs.SEC_WEBSOCKET_PROTOCOL in resp.headers:\n            resp_protocols = [\n                proto.strip() for proto in\n                resp.headers[hdrs.SEC_WEBSOCKET_PROTOCOL].split(',')]\n\n            for proto in resp_protocols:\n                if proto in protocols:\n                    protocol = proto\n                    break\n\n        reader = resp.connection.reader.set_parser(WebSocketParser)\n        writer = WebSocketWriter(resp.connection.writer, use_mask=True)\n\n        return self._ws_response_class(reader,\n                                       writer,\n                                       protocol,\n                                       resp,\n                                       timeout,\n                                       autoclose,\n                                       autoping,\n                                       self._loop)\n\n    def _update_cookies(self, cookies):\n        \"\"\"Update shared cookies.\"\"\"\n        if isinstance(cookies, dict):\n            cookies = cookies.items()\n\n        for name, value in cookies:\n            if isinstance(value, http.cookies.Morsel):\n                # use dict method because SimpleCookie class modifies value\n                # before Python3.4\n                dict.__setitem__(self.cookies, name, value)\n            else:\n                self.cookies[name] = value\n\n    def _prepare_headers(self, headers):\n        \"\"\" Add default headers and transform it to CIMultiDict\n        \"\"\"\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()\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    @asyncio.coroutine\n    def get(self, url, *, allow_redirects=True, **kwargs):\n        \"\"\"Perform HTTP GET request.\"\"\"\n        resp = yield from self.request(hdrs.METH_GET, url,\n                                       allow_redirects=allow_redirects,\n                                       **kwargs)\n        return resp\n\n    @asyncio.coroutine\n    def options(self, url, *, allow_redirects=True, **kwargs):\n        \"\"\"Perform HTTP OPTIONS request.\"\"\"\n        resp = yield from self.request(hdrs.METH_OPTIONS, url,\n                                       allow_redirects=allow_redirects,\n                                       **kwargs)\n        return resp\n\n    @asyncio.coroutine\n    def head(self, url, *, allow_redirects=False, **kwargs):\n        \"\"\"Perform HTTP HEAD request.\"\"\"\n        resp = yield from self.request(hdrs.METH_HEAD, url,\n                                       allow_redirects=allow_redirects,\n                                       **kwargs)\n        return resp\n\n    @asyncio.coroutine\n    def post(self, url, *, data=None, **kwargs):\n        \"\"\"Perform HTTP POST request.\"\"\"\n        resp = yield from self.request(hdrs.METH_POST, url,\n                                       data=data,\n                                       **kwargs)\n        return resp\n\n    @asyncio.coroutine\n    def put(self, url, *, data=None, **kwargs):\n        \"\"\"Perform HTTP PUT request.\"\"\"\n        resp = yield from self.request(hdrs.METH_PUT, url,\n                                       data=data,\n                                       **kwargs)\n        return resp\n\n    @asyncio.coroutine\n    def patch(self, url, *, data=None, **kwargs):\n        \"\"\"Perform HTTP PATCH request.\"\"\"\n        resp = yield from self.request(hdrs.METH_PATCH, url,\n                                       data=data,\n                                       **kwargs)\n        return resp\n\n    @asyncio.coroutine\n    def delete(self, url, **kwargs):\n        \"\"\"Perform HTTP DELETE request.\"\"\"\n        resp = yield from self.request(hdrs.METH_DELETE, url,\n                                       **kwargs)\n        return resp\n\n    def close(self):\n        \"\"\"Close underlying connector.\n\n        Release all acquired resources.\n        \"\"\"\n        if not self.closed:\n            self._connector.close()\n            self._connector = None\n\n    @property\n    def closed(self):\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):\n        \"\"\"Connector instance used for the session.\"\"\"\n        return self._connector\n\n    @property\n    def cookies(self):\n        \"\"\"The session cookies.\"\"\"\n        return self._cookies\n\n    def detach(self):\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):\n        return self\n\n    def __exit__(self, exc_type, exc_val, exc_tb):\n        self.close()\n\n\n@asyncio.coroutine\ndef request(method, url, *,\n            params=None,\n            data=None,\n            headers=None,\n            cookies=None,\n            files=None,\n            auth=None,\n            allow_redirects=True,\n            max_redirects=10,\n            encoding='utf-8',\n            version=aiohttp.HttpVersion11,\n            compress=None,\n            chunked=None,\n            expect100=False,\n            connector=None,\n            loop=None,\n            read_until_eof=True,\n            request_class=None,\n            response_class=None):\n    \"\"\"Constructs and sends a request. Returns response object.\n\n    :param str method: http method\n    :param str url: request url\n    :param params: (optional) Dictionary or bytes to be sent in the query\n      string of the new request\n    :param data: (optional) Dictionary, bytes, or file-like object to\n      send in the body of the request\n    :param dict headers: (optional) Dictionary of HTTP Headers to send with\n      the request\n    :param dict cookies: (optional) Dict object to send with the request\n    :param auth: (optional) BasicAuth named tuple represent HTTP Basic Auth\n    :type auth: aiohttp.helpers.BasicAuth\n    :param bool allow_redirects: (optional) If set to False, do not follow\n      redirects\n    :param version: Request http version.\n    :type version: aiohttp.protocol.HttpVersion\n    :param bool compress: Set to True if request has to be compressed\n       with deflate encoding.\n    :param chunked: Set to chunk size for chunked transfer encoding.\n    :type chunked: bool or int\n    :param bool expect100: Expect 100-continue response from server.\n    :param connector: BaseConnector sub-class instance to support\n       connection pooling.\n    :type connector: aiohttp.connector.BaseConnector\n    :param bool read_until_eof: Read response until eof if response\n       does not have Content-Length header.\n    :param request_class: (optional) Custom Request class implementation.\n    :param response_class: (optional) Custom Response class implementation.\n    :param loop: Optional event loop.\n\n    Usage::\n\n      >>> import aiohttp\n      >>> resp = yield from aiohttp.request('GET', 'http://python.org/')\n      >>> resp\n      <ClientResponse(python.org/) [200]>\n      >>> data = yield from resp.read()\n\n    \"\"\"\n    if connector is None:\n        connector = aiohttp.TCPConnector(loop=loop, force_close=True)\n\n    kwargs = {}\n\n    if request_class is not None:\n        kwargs['request_class'] = request_class\n\n    if response_class is not None:\n        kwargs['response_class'] = response_class\n\n    session = ClientSession(loop=loop,\n                            cookies=cookies,\n                            connector=connector,\n                            **kwargs)\n    try:\n        resp = yield from session.request(method, url,\n                                          params=params,\n                                          data=data,\n                                          headers=headers,\n                                          files=files,\n                                          auth=auth,\n                                          allow_redirects=allow_redirects,\n                                          max_redirects=max_redirects,\n                                          encoding=encoding,\n                                          version=version,\n                                          compress=compress,\n                                          chunked=chunked,\n                                          expect100=expect100,\n                                          read_until_eof=read_until_eof)\n        return resp\n    finally:\n        session.detach()\n\n\n@asyncio.coroutine\ndef get(url, **kwargs):\n    ret = yield from request(hdrs.METH_GET, url, **kwargs)\n    return ret\n\n\n@asyncio.coroutine\ndef options(url, **kwargs):\n    ret = yield from request(hdrs.METH_OPTIONS, url, **kwargs)\n    return ret\n\n\n@asyncio.coroutine\ndef head(url, **kwargs):\n    ret = yield from request(hdrs.METH_HEAD, url, **kwargs)\n    return ret\n\n\n@asyncio.coroutine\ndef post(url, **kwargs):\n    ret = yield from request(hdrs.METH_POST, url, **kwargs)\n    return ret\n\n\n@asyncio.coroutine\ndef put(url, **kwargs):\n    ret = yield from request(hdrs.METH_PUT, url, **kwargs)\n    return ret\n\n\n@asyncio.coroutine\ndef patch(url, **kwargs):\n    ret = yield from request(hdrs.METH_PATCH, url, **kwargs)\n    return ret\n\n\n@asyncio.coroutine\ndef delete(url, **kwargs):\n    ret = yield from request(hdrs.METH_DELETE, url, **kwargs)\n    return ret\n",
            "header": {
                "file": {
                    "path": "aiohttp/client.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "9b0b68a1",
                "new_commit_hash": "1f91da54",
                "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": 262,
                            "length": 19
                        },
                        "new_range": {
                            "start": 262,
                            "length": 17
                        },
                        "section": "class ClientSession:"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        \"\"\" Add default headers and transform it to CIMultiDict",
                                "type": "context"
                            },
                            {
                                "content": "        \"\"\"",
                                "type": "context"
                            },
                            {
                                "content": "        # Convert headers to MultiDict",
                                "type": "context"
                            },
                            {
                                "content": "        result = CIMultiDict()",
                                "type": "deleted"
                            },
                            {
                                "content": "        result = CIMultiDict(self._default_headers)",
                                "type": "added"
                            },
                            {
                                "content": "        if headers:",
                                "type": "context"
                            },
                            {
                                "content": "            if isinstance(headers, dict):",
                                "type": "deleted"
                            },
                            {
                                "content": "                headers = headers.items()",
                                "type": "deleted"
                            },
                            {
                                "content": "            elif isinstance(headers, (MultiDictProxy, MultiDict)):",
                                "type": "deleted"
                            },
                            {
                                "content": "                headers = headers.items()",
                                "type": "deleted"
                            },
                            {
                                "content": "            for key, value in headers:",
                                "type": "deleted"
                            },
                            {
                                "content": "                result.add(key, value)",
                                "type": "deleted"
                            },
                            {
                                "content": "        # Add defaults only if those are not overridden",
                                "type": "deleted"
                            },
                            {
                                "content": "        if self._default_headers:",
                                "type": "deleted"
                            },
                            {
                                "content": "            for key, value in self._default_headers.items():",
                                "type": "deleted"
                            },
                            {
                                "content": "                if key not in result:",
                                "type": "deleted"
                            },
                            {
                                "content": "            if not isinstance(headers, (MultiDictProxy, MultiDict)):",
                                "type": "added"
                            },
                            {
                                "content": "                headers = CIMultiDict(headers)",
                                "type": "added"
                            },
                            {
                                "content": "            added_names = set()",
                                "type": "added"
                            },
                            {
                                "content": "            for key, value in headers.items():",
                                "type": "added"
                            },
                            {
                                "content": "                if key in added_names:",
                                "type": "added"
                            },
                            {
                                "content": "                    result.add(key, value)",
                                "type": "context"
                            },
                            {
                                "content": "                else:",
                                "type": "added"
                            },
                            {
                                "content": "                    result[key] = value",
                                "type": "added"
                            },
                            {
                                "content": "                    added_names.add(key)",
                                "type": "added"
                            },
                            {
                                "content": "        return result",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    @asyncio.coroutine",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "aiohttp/client.py",
                            "type": "class",
                            "name": "ClientSession",
                            "content": "class ClientSession:\n    \"\"\"First-class interface for making HTTP requests.\"\"\"\n\n    _source_traceback = None\n    _connector = None\n\n    def __init__(self, *, connector=None, loop=None, cookies=None,\n                 headers=None, auth=None, request_class=ClientRequest,\n                 response_class=ClientResponse,\n                 ws_response_class=ClientWebSocketResponse):\n\n        if connector is None:\n            connector = aiohttp.TCPConnector(loop=loop)\n            loop = connector._loop  # never None\n        else:\n            if loop is None:\n                loop = connector._loop  # never None\n            elif connector._loop is not loop:\n                raise ValueError(\"loop argument must agree with connector\")\n\n        self._loop = loop\n        if loop.get_debug():\n            self._source_traceback = traceback.extract_stack(sys._getframe(1))\n\n        self._cookies = http.cookies.SimpleCookie()\n\n        # For Backward compatability with `share_cookies` connectors\n        if connector._share_cookies:\n            self._update_cookies(connector.cookies)\n        if cookies is not None:\n            self._update_cookies(cookies)\n        self._connector = connector\n        self._default_auth = auth\n\n        # Convert to list of tuples\n        if headers:\n            headers = CIMultiDict(headers)\n        else:\n            headers = CIMultiDict()\n        self._default_headers = headers\n\n        self._request_class = request_class\n        self._response_class = response_class\n        self._ws_response_class = ws_response_class\n\n    if PY_341:\n        def __del__(self):\n            if not self.closed:\n                self.close()\n\n                warnings.warn(\"Unclosed client session {!r}\".format(self),\n                              ResourceWarning)\n                context = {'client_session': self,\n                           '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    @asyncio.coroutine\n    def request(self, method, url, *,\n                params=None,\n                data=None,\n                headers=None,\n                files=None,\n                auth=None,\n                allow_redirects=True,\n                max_redirects=10,\n                encoding='utf-8',\n                version=aiohttp.HttpVersion11,\n                compress=None,\n                chunked=None,\n                expect100=False,\n                read_until_eof=True):\n        \"\"\"Perform HTTP request.\"\"\"\n\n        if self.closed:\n            raise RuntimeError('Session is closed')\n\n        redirects = 0\n        if not isinstance(method, upstr):\n            method = upstr(method)\n\n        # Merge with default headers and transform to CIMultiDict\n        headers = self._prepare_headers(headers)\n        if auth is None:\n            auth = self._default_auth\n        # It would be confusing if we support explicit Authorization header\n        # with `auth` argument\n        if (headers is not None and\n                auth is not None and\n                hdrs.AUTHORIZATION in headers):\n            raise ValueError(\"Can't combine `Authorization` header with \"\n                             \"`auth` argument\")\n\n        while True:\n            req = self._request_class(\n                method, url, params=params, headers=headers, data=data,\n                cookies=self.cookies, files=files, encoding=encoding,\n                auth=auth, version=version, compress=compress, chunked=chunked,\n                expect100=expect100,\n                loop=self._loop, response_class=self._response_class)\n\n            conn = yield from self._connector.connect(req)\n            try:\n                resp = req.send(conn.writer, conn.reader)\n                try:\n                    yield from resp.start(conn, read_until_eof)\n                except:\n                    resp.close(force=True)\n                    conn.close()\n                    raise\n            except (aiohttp.HttpProcessingError,\n                    aiohttp.ServerDisconnectedError) as exc:\n                raise aiohttp.ClientResponseError() from exc\n            except OSError as exc:\n                raise aiohttp.ClientOSError() from exc\n\n            self._update_cookies(resp.cookies)\n            # For Backward compatability with `share_cookie` connectors\n            if self._connector._share_cookies:\n                self._connector.update_cookies(resp.cookies)\n\n            # redirects\n            if resp.status in (301, 302, 303, 307) and allow_redirects:\n                redirects += 1\n                if max_redirects and redirects >= max_redirects:\n                    resp.close(force=True)\n                    break\n\n                # For 301 and 302, mimic IE behaviour, now changed in RFC.\n                # Details: https://github.com/kennethreitz/requests/pull/269\n                if resp.status != 307:\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\n                         resp.headers.get(hdrs.URI))\n\n                scheme = urllib.parse.urlsplit(r_url)[0]\n                if scheme not in ('http', 'https', ''):\n                    resp.close(force=True)\n                    raise ValueError('Can redirect only to http or https')\n                elif not scheme:\n                    r_url = urllib.parse.urljoin(url, r_url)\n\n                url = urllib.parse.urldefrag(r_url)[0]\n                if url:\n                    yield from resp.release()\n                    continue\n\n            break\n\n        return resp\n\n    @asyncio.coroutine\n    def ws_connect(self, url, *,\n                   protocols=(),\n                   timeout=10.0,\n                   autoclose=True,\n                   autoping=True):\n        \"\"\"Initiate websocket connection.\"\"\"\n\n        sec_key = base64.b64encode(os.urandom(16))\n\n        headers = {\n            hdrs.UPGRADE: hdrs.WEBSOCKET,\n            hdrs.CONNECTION: hdrs.UPGRADE,\n            hdrs.SEC_WEBSOCKET_VERSION: '13',\n            hdrs.SEC_WEBSOCKET_KEY: sec_key.decode(),\n        }\n        if protocols:\n            headers[hdrs.SEC_WEBSOCKET_PROTOCOL] = ','.join(protocols)\n\n        # send request\n        resp = yield from self.request('get', url, headers=headers,\n                                       read_until_eof=False)\n\n        # check handshake\n        if resp.status != 101:\n            raise WSServerHandshakeError('Invalid response status')\n\n        if resp.headers.get(hdrs.UPGRADE, '').lower() != 'websocket':\n            raise WSServerHandshakeError('Invalid upgrade header')\n\n        if resp.headers.get(hdrs.CONNECTION, '').lower() != 'upgrade':\n            raise WSServerHandshakeError('Invalid connection header')\n\n        # key calculation\n        key = resp.headers.get(hdrs.SEC_WEBSOCKET_ACCEPT, '')\n        match = base64.b64encode(\n            hashlib.sha1(sec_key + WS_KEY).digest()).decode()\n        if key != match:\n            raise WSServerHandshakeError('Invalid challenge response')\n\n        # websocket protocol\n        protocol = None\n        if protocols and hdrs.SEC_WEBSOCKET_PROTOCOL in resp.headers:\n            resp_protocols = [\n                proto.strip() for proto in\n                resp.headers[hdrs.SEC_WEBSOCKET_PROTOCOL].split(',')]\n\n            for proto in resp_protocols:\n                if proto in protocols:\n                    protocol = proto\n                    break\n\n        reader = resp.connection.reader.set_parser(WebSocketParser)\n        writer = WebSocketWriter(resp.connection.writer, use_mask=True)\n\n        return self._ws_response_class(reader,\n                                       writer,\n                                       protocol,\n                                       resp,\n                                       timeout,\n                                       autoclose,\n                                       autoping,\n                                       self._loop)\n\n    def _update_cookies(self, cookies):\n        \"\"\"Update shared cookies.\"\"\"\n        if isinstance(cookies, dict):\n            cookies = cookies.items()\n\n        for name, value in cookies:\n            if isinstance(value, http.cookies.Morsel):\n                # use dict method because SimpleCookie class modifies value\n                # before Python3.4\n                dict.__setitem__(self.cookies, name, value)\n            else:\n                self.cookies[name] = value\n\n    def _prepare_headers(self, headers):\n        \"\"\" Add default headers and transform it to CIMultiDict\n        \"\"\"\n        # Convert headers to MultiDict\n        result = CIMultiDict()\n        if headers:\n            if isinstance(headers, dict):\n                headers = headers.items()\n            elif isinstance(headers, (MultiDictProxy, MultiDict)):\n                headers = headers.items()\n            for key, value in headers:\n                result.add(key, value)\n        # Add defaults only if those are not overridden\n        if self._default_headers:\n            for key, value in self._default_headers.items():\n                if key not in result:\n                    result.add(key, value)\n        return result\n\n    @asyncio.coroutine\n    def get(self, url, *, allow_redirects=True, **kwargs):\n        \"\"\"Perform HTTP GET request.\"\"\"\n        resp = yield from self.request(hdrs.METH_GET, url,\n                                       allow_redirects=allow_redirects,\n                                       **kwargs)\n        return resp\n\n    @asyncio.coroutine\n    def options(self, url, *, allow_redirects=True, **kwargs):\n        \"\"\"Perform HTTP OPTIONS request.\"\"\"\n        resp = yield from self.request(hdrs.METH_OPTIONS, url,\n                                       allow_redirects=allow_redirects,\n                                       **kwargs)\n        return resp\n\n    @asyncio.coroutine\n    def head(self, url, *, allow_redirects=False, **kwargs):\n        \"\"\"Perform HTTP HEAD request.\"\"\"\n        resp = yield from self.request(hdrs.METH_HEAD, url,\n                                       allow_redirects=allow_redirects,\n                                       **kwargs)\n        return resp\n\n    @asyncio.coroutine\n    def post(self, url, *, data=None, **kwargs):\n        \"\"\"Perform HTTP POST request.\"\"\"\n        resp = yield from self.request(hdrs.METH_POST, url,\n                                       data=data,\n                                       **kwargs)\n        return resp\n\n    @asyncio.coroutine\n    def put(self, url, *, data=None, **kwargs):\n        \"\"\"Perform HTTP PUT request.\"\"\"\n        resp = yield from self.request(hdrs.METH_PUT, url,\n                                       data=data,\n                                       **kwargs)\n        return resp\n\n    @asyncio.coroutine\n    def patch(self, url, *, data=None, **kwargs):\n        \"\"\"Perform HTTP PATCH request.\"\"\"\n        resp = yield from self.request(hdrs.METH_PATCH, url,\n                                       data=data,\n                                       **kwargs)\n        return resp\n\n    @asyncio.coroutine\n    def delete(self, url, **kwargs):\n        \"\"\"Perform HTTP DELETE request.\"\"\"\n        resp = yield from self.request(hdrs.METH_DELETE, url,\n                                       **kwargs)\n        return resp\n\n    def close(self):\n        \"\"\"Close underlying connector.\n\n        Release all acquired resources.\n        \"\"\"\n        if not self.closed:\n            self._connector.close()\n            self._connector = None\n\n    @property\n    def closed(self):\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):\n        \"\"\"Connector instance used for the session.\"\"\"\n        return self._connector\n\n    @property\n    def cookies(self):\n        \"\"\"The session cookies.\"\"\"\n        return self._cookies\n\n    def detach(self):\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):\n        return self\n\n    def __exit__(self, exc_type, exc_val, exc_tb):\n        self.close()",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 28,
                            "end_lineno": 373,
                            "parent": null
                        },
                        {
                            "file_name": "aiohttp/client.py",
                            "type": "method",
                            "name": "ClientSession._prepare_headers",
                            "content": "class ClientSession:\n    \"\"\"First-class interface for making HTTP requests.\"\"\"\n\n    _source_traceback = None\n    _connector = None\n\n    def __init__(self, *, connector=None, loop=None, cookies=None,\n                 headers=None, auth=None, request_class=ClientRequest,\n                 response_class=ClientResponse,\n                 ws_response_class=ClientWebSocketResponse):\n\n        if connector is None:\n            connector = aiohttp.TCPConnector(loop=loop)\n            loop = connector._loop  # never None\n        else:\n            if loop is None:\n                loop = connector._loop  # never None\n            elif connector._loop is not loop:\n                raise ValueError(\"loop argument must agree with connector\")\n\n        self._loop = loop\n        if loop.get_debug():\n            self._source_traceback = traceback.extract_stack(sys._getframe(1))\n\n        self._cookies = http.cookies.SimpleCookie()\n\n        # For Backward compatability with `share_cookies` connectors\n        if connector._share_cookies:\n            self._update_cookies(connector.cookies)\n        if cookies is not None:\n            self._update_cookies(cookies)\n        self._connector = connector\n        self._default_auth = auth\n\n        # Convert to list of tuples\n        if headers:\n            headers = CIMultiDict(headers)\n        else:\n            headers = CIMultiDict()\n        self._default_headers = headers\n\n        self._request_class = request_class\n        self._response_class = response_class\n        self._ws_response_class = ws_response_class\n\n    if PY_341:\n        def __del__(self):\n            if not self.closed:\n                self.close()\n\n                warnings.warn(\"Unclosed client session {!r}\".format(self),\n                              ResourceWarning)\n                context = {'client_session': self,\n                           '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    @asyncio.coroutine\n    def request(self, method, url, *,\n                params=None,\n                data=None,\n                headers=None,\n                files=None,\n                auth=None,\n                allow_redirects=True,\n                max_redirects=10,\n                encoding='utf-8',\n                version=aiohttp.HttpVersion11,\n                compress=None,\n                chunked=None,\n                expect100=False,\n                read_until_eof=True):\n        \"\"\"Perform HTTP request.\"\"\"\n\n        if self.closed:\n            raise RuntimeError('Session is closed')\n\n        redirects = 0\n        if not isinstance(method, upstr):\n            method = upstr(method)\n\n        # Merge with default headers and transform to CIMultiDict\n        headers = self._prepare_headers(headers)\n        if auth is None:\n            auth = self._default_auth\n        # It would be confusing if we support explicit Authorization header\n        # with `auth` argument\n        if (headers is not None and\n                auth is not None and\n                hdrs.AUTHORIZATION in headers):\n            raise ValueError(\"Can't combine `Authorization` header with \"\n                             \"`auth` argument\")\n\n        while True:\n            req = self._request_class(\n                method, url, params=params, headers=headers, data=data,\n                cookies=self.cookies, files=files, encoding=encoding,\n                auth=auth, version=version, compress=compress, chunked=chunked,\n                expect100=expect100,\n                loop=self._loop, response_class=self._response_class)\n\n            conn = yield from self._connector.connect(req)\n            try:\n                resp = req.send(conn.writer, conn.reader)\n                try:\n                    yield from resp.start(conn, read_until_eof)\n                except:\n                    resp.close(force=True)\n                    conn.close()\n                    raise\n            except (aiohttp.HttpProcessingError,\n                    aiohttp.ServerDisconnectedError) as exc:\n                raise aiohttp.ClientResponseError() from exc\n            except OSError as exc:\n                raise aiohttp.ClientOSError() from exc\n\n            self._update_cookies(resp.cookies)\n            # For Backward compatability with `share_cookie` connectors\n            if self._connector._share_cookies:\n                self._connector.update_cookies(resp.cookies)\n\n            # redirects\n            if resp.status in (301, 302, 303, 307) and allow_redirects:\n                redirects += 1\n                if max_redirects and redirects >= max_redirects:\n                    resp.close(force=True)\n                    break\n\n                # For 301 and 302, mimic IE behaviour, now changed in RFC.\n                # Details: https://github.com/kennethreitz/requests/pull/269\n                if resp.status != 307:\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\n                         resp.headers.get(hdrs.URI))\n\n                scheme = urllib.parse.urlsplit(r_url)[0]\n                if scheme not in ('http', 'https', ''):\n                    resp.close(force=True)\n                    raise ValueError('Can redirect only to http or https')\n                elif not scheme:\n                    r_url = urllib.parse.urljoin(url, r_url)\n\n                url = urllib.parse.urldefrag(r_url)[0]\n                if url:\n                    yield from resp.release()\n                    continue\n\n            break\n\n        return resp\n\n    @asyncio.coroutine\n    def ws_connect(self, url, *,\n                   protocols=(),\n                   timeout=10.0,\n                   autoclose=True,\n                   autoping=True):\n        \"\"\"Initiate websocket connection.\"\"\"\n\n        sec_key = base64.b64encode(os.urandom(16))\n\n        headers = {\n            hdrs.UPGRADE: hdrs.WEBSOCKET,\n            hdrs.CONNECTION: hdrs.UPGRADE,\n            hdrs.SEC_WEBSOCKET_VERSION: '13',\n            hdrs.SEC_WEBSOCKET_KEY: sec_key.decode(),\n        }\n        if protocols:\n            headers[hdrs.SEC_WEBSOCKET_PROTOCOL] = ','.join(protocols)\n\n        # send request\n        resp = yield from self.request('get', url, headers=headers,\n                                       read_until_eof=False)\n\n        # check handshake\n        if resp.status != 101:\n            raise WSServerHandshakeError('Invalid response status')\n\n        if resp.headers.get(hdrs.UPGRADE, '').lower() != 'websocket':\n            raise WSServerHandshakeError('Invalid upgrade header')\n\n        if resp.headers.get(hdrs.CONNECTION, '').lower() != 'upgrade':\n            raise WSServerHandshakeError('Invalid connection header')\n\n        # key calculation\n        key = resp.headers.get(hdrs.SEC_WEBSOCKET_ACCEPT, '')\n        match = base64.b64encode(\n            hashlib.sha1(sec_key + WS_KEY).digest()).decode()\n        if key != match:\n            raise WSServerHandshakeError('Invalid challenge response')\n\n        # websocket protocol\n        protocol = None\n        if protocols and hdrs.SEC_WEBSOCKET_PROTOCOL in resp.headers:\n            resp_protocols = [\n                proto.strip() for proto in\n                resp.headers[hdrs.SEC_WEBSOCKET_PROTOCOL].split(',')]\n\n            for proto in resp_protocols:\n                if proto in protocols:\n                    protocol = proto\n                    break\n\n        reader = resp.connection.reader.set_parser(WebSocketParser)\n        writer = WebSocketWriter(resp.connection.writer, use_mask=True)\n\n        return self._ws_response_class(reader,\n                                       writer,\n                                       protocol,\n                                       resp,\n                                       timeout,\n                                       autoclose,\n                                       autoping,\n                                       self._loop)\n\n    def _update_cookies(self, cookies):\n        \"\"\"Update shared cookies.\"\"\"\n        if isinstance(cookies, dict):\n            cookies = cookies.items()\n\n        for name, value in cookies:\n            if isinstance(value, http.cookies.Morsel):\n                # use dict method because SimpleCookie class modifies value\n                # before Python3.4\n                dict.__setitem__(self.cookies, name, value)\n            else:\n                self.cookies[name] = value\n\n    def _prepare_headers(self, headers):\n        \"\"\" Add default headers and transform it to CIMultiDict\n        \"\"\"\n        # Convert headers to MultiDict\n        result = CIMultiDict()\n        if headers:\n            if isinstance(headers, dict):\n                headers = headers.items()\n            elif isinstance(headers, (MultiDictProxy, MultiDict)):\n                headers = headers.items()\n            for key, value in headers:\n                result.add(key, value)\n        # Add defaults only if those are not overridden\n        if self._default_headers:\n            for key, value in self._default_headers.items():\n                if key not in result:\n                    result.add(key, value)\n        return result\n\n    @asyncio.coroutine\n    def get(self, url, *, allow_redirects=True, **kwargs):\n        \"\"\"Perform HTTP GET request.\"\"\"\n        resp = yield from self.request(hdrs.METH_GET, url,\n                                       allow_redirects=allow_redirects,\n                                       **kwargs)\n        return resp\n\n    @asyncio.coroutine\n    def options(self, url, *, allow_redirects=True, **kwargs):\n        \"\"\"Perform HTTP OPTIONS request.\"\"\"\n        resp = yield from self.request(hdrs.METH_OPTIONS, url,\n                                       allow_redirects=allow_redirects,\n                                       **kwargs)\n        return resp\n\n    @asyncio.coroutine\n    def head(self, url, *, allow_redirects=False, **kwargs):\n        \"\"\"Perform HTTP HEAD request.\"\"\"\n        resp = yield from self.request(hdrs.METH_HEAD, url,\n                                       allow_redirects=allow_redirects,\n                                       **kwargs)\n        return resp\n\n    @asyncio.coroutine\n    def post(self, url, *, data=None, **kwargs):\n        \"\"\"Perform HTTP POST request.\"\"\"\n        resp = yield from self.request(hdrs.METH_POST, url,\n                                       data=data,\n                                       **kwargs)\n        return resp\n\n    @asyncio.coroutine\n    def put(self, url, *, data=None, **kwargs):\n        \"\"\"Perform HTTP PUT request.\"\"\"\n        resp = yield from self.request(hdrs.METH_PUT, url,\n                                       data=data,\n                                       **kwargs)\n        return resp\n\n    @asyncio.coroutine\n    def patch(self, url, *, data=None, **kwargs):\n        \"\"\"Perform HTTP PATCH request.\"\"\"\n        resp = yield from self.request(hdrs.METH_PATCH, url,\n                                       data=data,\n                                       **kwargs)\n        return resp\n\n    @asyncio.coroutine\n    def delete(self, url, **kwargs):\n        \"\"\"Perform HTTP DELETE request.\"\"\"\n        resp = yield from self.request(hdrs.METH_DELETE, url,\n                                       **kwargs)\n        return resp\n\n    def close(self):\n        \"\"\"Close underlying connector.\n\n        Release all acquired resources.\n        \"\"\"\n        if not self.closed:\n            self._connector.close()\n            self._connector = None\n\n    @property\n    def closed(self):\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):\n        \"\"\"Connector instance used for the session.\"\"\"\n        return self._connector\n\n    @property\n    def cookies(self):\n        \"\"\"The session cookies.\"\"\"\n        return self._cookies\n\n    def detach(self):\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):\n        return self\n\n    def __exit__(self, exc_type, exc_val, exc_tb):\n        self.close()",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 261,
                            "end_lineno": 278,
                            "parent": {
                                "file_name": "aiohttp/client.py",
                                "type": "class",
                                "name": "ClientSession",
                                "content": "class ClientSession:\n    \"\"\"First-class interface for making HTTP requests.\"\"\"\n\n    _source_traceback = None\n    _connector = None\n\n    def __init__(self, *, connector=None, loop=None, cookies=None,\n                 headers=None, auth=None, request_class=ClientRequest,\n                 response_class=ClientResponse,\n                 ws_response_class=ClientWebSocketResponse):\n\n        if connector is None:\n            connector = aiohttp.TCPConnector(loop=loop)\n            loop = connector._loop  # never None\n        else:\n            if loop is None:\n                loop = connector._loop  # never None\n            elif connector._loop is not loop:\n                raise ValueError(\"loop argument must agree with connector\")\n\n        self._loop = loop\n        if loop.get_debug():\n            self._source_traceback = traceback.extract_stack(sys._getframe(1))\n\n        self._cookies = http.cookies.SimpleCookie()\n\n        # For Backward compatability with `share_cookies` connectors\n        if connector._share_cookies:\n            self._update_cookies(connector.cookies)\n        if cookies is not None:\n            self._update_cookies(cookies)\n        self._connector = connector\n        self._default_auth = auth\n\n        # Convert to list of tuples\n        if headers:\n            headers = CIMultiDict(headers)\n        else:\n            headers = CIMultiDict()\n        self._default_headers = headers\n\n        self._request_class = request_class\n        self._response_class = response_class\n        self._ws_response_class = ws_response_class\n\n    if PY_341:\n        def __del__(self):\n            if not self.closed:\n                self.close()\n\n                warnings.warn(\"Unclosed client session {!r}\".format(self),\n                              ResourceWarning)\n                context = {'client_session': self,\n                           '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    @asyncio.coroutine\n    def request(self, method, url, *,\n                params=None,\n                data=None,\n                headers=None,\n                files=None,\n                auth=None,\n                allow_redirects=True,\n                max_redirects=10,\n                encoding='utf-8',\n                version=aiohttp.HttpVersion11,\n                compress=None,\n                chunked=None,\n                expect100=False,\n                read_until_eof=True):\n        \"\"\"Perform HTTP request.\"\"\"\n\n        if self.closed:\n            raise RuntimeError('Session is closed')\n\n        redirects = 0\n        if not isinstance(method, upstr):\n            method = upstr(method)\n\n        # Merge with default headers and transform to CIMultiDict\n        headers = self._prepare_headers(headers)\n        if auth is None:\n            auth = self._default_auth\n        # It would be confusing if we support explicit Authorization header\n        # with `auth` argument\n        if (headers is not None and\n                auth is not None and\n                hdrs.AUTHORIZATION in headers):\n            raise ValueError(\"Can't combine `Authorization` header with \"\n                             \"`auth` argument\")\n\n        while True:\n            req = self._request_class(\n                method, url, params=params, headers=headers, data=data,\n                cookies=self.cookies, files=files, encoding=encoding,\n                auth=auth, version=version, compress=compress, chunked=chunked,\n                expect100=expect100,\n                loop=self._loop, response_class=self._response_class)\n\n            conn = yield from self._connector.connect(req)\n            try:\n                resp = req.send(conn.writer, conn.reader)\n                try:\n                    yield from resp.start(conn, read_until_eof)\n                except:\n                    resp.close(force=True)\n                    conn.close()\n                    raise\n            except (aiohttp.HttpProcessingError,\n                    aiohttp.ServerDisconnectedError) as exc:\n                raise aiohttp.ClientResponseError() from exc\n            except OSError as exc:\n                raise aiohttp.ClientOSError() from exc\n\n            self._update_cookies(resp.cookies)\n            # For Backward compatability with `share_cookie` connectors\n            if self._connector._share_cookies:\n                self._connector.update_cookies(resp.cookies)\n\n            # redirects\n            if resp.status in (301, 302, 303, 307) and allow_redirects:\n                redirects += 1\n                if max_redirects and redirects >= max_redirects:\n                    resp.close(force=True)\n                    break\n\n                # For 301 and 302, mimic IE behaviour, now changed in RFC.\n                # Details: https://github.com/kennethreitz/requests/pull/269\n                if resp.status != 307:\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\n                         resp.headers.get(hdrs.URI))\n\n                scheme = urllib.parse.urlsplit(r_url)[0]\n                if scheme not in ('http', 'https', ''):\n                    resp.close(force=True)\n                    raise ValueError('Can redirect only to http or https')\n                elif not scheme:\n                    r_url = urllib.parse.urljoin(url, r_url)\n\n                url = urllib.parse.urldefrag(r_url)[0]\n                if url:\n                    yield from resp.release()\n                    continue\n\n            break\n\n        return resp\n\n    @asyncio.coroutine\n    def ws_connect(self, url, *,\n                   protocols=(),\n                   timeout=10.0,\n                   autoclose=True,\n                   autoping=True):\n        \"\"\"Initiate websocket connection.\"\"\"\n\n        sec_key = base64.b64encode(os.urandom(16))\n\n        headers = {\n            hdrs.UPGRADE: hdrs.WEBSOCKET,\n            hdrs.CONNECTION: hdrs.UPGRADE,\n            hdrs.SEC_WEBSOCKET_VERSION: '13',\n            hdrs.SEC_WEBSOCKET_KEY: sec_key.decode(),\n        }\n        if protocols:\n            headers[hdrs.SEC_WEBSOCKET_PROTOCOL] = ','.join(protocols)\n\n        # send request\n        resp = yield from self.request('get', url, headers=headers,\n                                       read_until_eof=False)\n\n        # check handshake\n        if resp.status != 101:\n            raise WSServerHandshakeError('Invalid response status')\n\n        if resp.headers.get(hdrs.UPGRADE, '').lower() != 'websocket':\n            raise WSServerHandshakeError('Invalid upgrade header')\n\n        if resp.headers.get(hdrs.CONNECTION, '').lower() != 'upgrade':\n            raise WSServerHandshakeError('Invalid connection header')\n\n        # key calculation\n        key = resp.headers.get(hdrs.SEC_WEBSOCKET_ACCEPT, '')\n        match = base64.b64encode(\n            hashlib.sha1(sec_key + WS_KEY).digest()).decode()\n        if key != match:\n            raise WSServerHandshakeError('Invalid challenge response')\n\n        # websocket protocol\n        protocol = None\n        if protocols and hdrs.SEC_WEBSOCKET_PROTOCOL in resp.headers:\n            resp_protocols = [\n                proto.strip() for proto in\n                resp.headers[hdrs.SEC_WEBSOCKET_PROTOCOL].split(',')]\n\n            for proto in resp_protocols:\n                if proto in protocols:\n                    protocol = proto\n                    break\n\n        reader = resp.connection.reader.set_parser(WebSocketParser)\n        writer = WebSocketWriter(resp.connection.writer, use_mask=True)\n\n        return self._ws_response_class(reader,\n                                       writer,\n                                       protocol,\n                                       resp,\n                                       timeout,\n                                       autoclose,\n                                       autoping,\n                                       self._loop)\n\n    def _update_cookies(self, cookies):\n        \"\"\"Update shared cookies.\"\"\"\n        if isinstance(cookies, dict):\n            cookies = cookies.items()\n\n        for name, value in cookies:\n            if isinstance(value, http.cookies.Morsel):\n                # use dict method because SimpleCookie class modifies value\n                # before Python3.4\n                dict.__setitem__(self.cookies, name, value)\n            else:\n                self.cookies[name] = value\n\n    def _prepare_headers(self, headers):\n        \"\"\" Add default headers and transform it to CIMultiDict\n        \"\"\"\n        # Convert headers to MultiDict\n        result = CIMultiDict()\n        if headers:\n            if isinstance(headers, dict):\n                headers = headers.items()\n            elif isinstance(headers, (MultiDictProxy, MultiDict)):\n                headers = headers.items()\n            for key, value in headers:\n                result.add(key, value)\n        # Add defaults only if those are not overridden\n        if self._default_headers:\n            for key, value in self._default_headers.items():\n                if key not in result:\n                    result.add(key, value)\n        return result\n\n    @asyncio.coroutine\n    def get(self, url, *, allow_redirects=True, **kwargs):\n        \"\"\"Perform HTTP GET request.\"\"\"\n        resp = yield from self.request(hdrs.METH_GET, url,\n                                       allow_redirects=allow_redirects,\n                                       **kwargs)\n        return resp\n\n    @asyncio.coroutine\n    def options(self, url, *, allow_redirects=True, **kwargs):\n        \"\"\"Perform HTTP OPTIONS request.\"\"\"\n        resp = yield from self.request(hdrs.METH_OPTIONS, url,\n                                       allow_redirects=allow_redirects,\n                                       **kwargs)\n        return resp\n\n    @asyncio.coroutine\n    def head(self, url, *, allow_redirects=False, **kwargs):\n        \"\"\"Perform HTTP HEAD request.\"\"\"\n        resp = yield from self.request(hdrs.METH_HEAD, url,\n                                       allow_redirects=allow_redirects,\n                                       **kwargs)\n        return resp\n\n    @asyncio.coroutine\n    def post(self, url, *, data=None, **kwargs):\n        \"\"\"Perform HTTP POST request.\"\"\"\n        resp = yield from self.request(hdrs.METH_POST, url,\n                                       data=data,\n                                       **kwargs)\n        return resp\n\n    @asyncio.coroutine\n    def put(self, url, *, data=None, **kwargs):\n        \"\"\"Perform HTTP PUT request.\"\"\"\n        resp = yield from self.request(hdrs.METH_PUT, url,\n                                       data=data,\n                                       **kwargs)\n        return resp\n\n    @asyncio.coroutine\n    def patch(self, url, *, data=None, **kwargs):\n        \"\"\"Perform HTTP PATCH request.\"\"\"\n        resp = yield from self.request(hdrs.METH_PATCH, url,\n                                       data=data,\n                                       **kwargs)\n        return resp\n\n    @asyncio.coroutine\n    def delete(self, url, **kwargs):\n        \"\"\"Perform HTTP DELETE request.\"\"\"\n        resp = yield from self.request(hdrs.METH_DELETE, url,\n                                       **kwargs)\n        return resp\n\n    def close(self):\n        \"\"\"Close underlying connector.\n\n        Release all acquired resources.\n        \"\"\"\n        if not self.closed:\n            self._connector.close()\n            self._connector = None\n\n    @property\n    def closed(self):\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):\n        \"\"\"Connector instance used for the session.\"\"\"\n        return self._connector\n\n    @property\n    def cookies(self):\n        \"\"\"The session cookies.\"\"\"\n        return self._cookies\n\n    def detach(self):\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):\n        return self\n\n    def __exit__(self, exc_type, exc_val, exc_tb):\n        self.close()",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 28,
                                "end_lineno": 373,
                                "parent": null
                            }
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "# -*- coding: utf-8 -*-\n\"\"\"Tests for aiohttp/client.py\"\"\"\n\nimport asyncio\nimport gc\nimport unittest\nfrom unittest import mock\nimport sys\n\nimport aiohttp\nfrom aiohttp.client import ClientSession\nfrom aiohttp.multidict import MultiDict, CIMultiDict, CIMultiDictProxy\nfrom aiohttp.connector import BaseConnector, TCPConnector\nfrom aiohttp.client_reqrep import ClientRequest, ClientResponse\nfrom http.cookies import SimpleCookie\n\n\nPY_341 = sys.version_info >= (3, 4, 1)\n\n\nclass TestClientSession(unittest.TestCase):\n\n    maxDiff = None\n\n    def setUp(self):\n        self.loop = asyncio.new_event_loop()\n        asyncio.set_event_loop(None)\n        self.run = self.loop.run_until_complete\n\n    def tearDown(self):\n        self.loop.close()\n\n    def make_open_connector(self):\n        conn = BaseConnector(loop=self.loop)\n        transp = unittest.mock.Mock()\n        conn._conns['a'] = [(transp, 'proto', 123)]\n        return conn\n\n    def test_init_headers_simple_dict(self):\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        self.assertEqual(\n            sorted(session._default_headers.items()),\n            ([(\"H1\", \"header1\"),\n              (\"H2\", \"header2\")]))\n        session.close()\n\n    def test_init_headers_list_of_tuples(self):\n        session = ClientSession(\n            headers=[(\"h1\", \"header1\"),\n                     (\"h2\", \"header2\"),\n                     (\"h3\", \"header3\")],\n            loop=self.loop)\n        self.assertEqual(\n            session._default_headers,\n            CIMultiDict([(\"h1\", \"header1\"),\n                         (\"h2\", \"header2\"),\n                         (\"h3\", \"header3\")]))\n        session.close()\n\n    def test_init_headers_MultiDict(self):\n        session = ClientSession(\n            headers=MultiDict(\n                [(\"h1\", \"header1\"),\n                 (\"h2\", \"header2\"),\n                 (\"h3\", \"header3\")]),\n            loop=self.loop)\n        self.assertEqual(\n            session._default_headers,\n            CIMultiDict([(\"H1\", \"header1\"),\n                         (\"H2\", \"header2\"),\n                         (\"H3\", \"header3\")]))\n        session.close()\n\n    def test_init_cookies_with_simple_dict(self):\n        session = ClientSession(\n            cookies={\n                \"c1\": \"cookie1\",\n                \"c2\": \"cookie2\"\n            }, loop=self.loop)\n        self.assertEqual(set(session.cookies), {'c1', 'c2'})\n        self.assertEqual(session.cookies['c1'].value, 'cookie1')\n        self.assertEqual(session.cookies['c2'].value, 'cookie2')\n        session.close()\n\n    def test_init_cookies_with_list_of_tuples(self):\n        session = ClientSession(\n            cookies=[(\"c1\", \"cookie1\"),\n                     (\"c2\", \"cookie2\")],\n            loop=self.loop)\n        self.assertEqual(set(session.cookies), {'c1', 'c2'})\n        self.assertEqual(session.cookies['c1'].value, 'cookie1')\n        self.assertEqual(session.cookies['c2'].value, 'cookie2')\n        session.close()\n\n    def test_merge_headers(self):\n        # Check incoming simple dict\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers({\n            \"h1\": \"h1\"\n        })\n        self.assertIsInstance(headers, CIMultiDict)\n        self.assertEqual(headers, CIMultiDict([\n            (\"h1\", \"h1\"),\n            (\"h2\", \"header2\")\n        ]))\n        session.close()\n\n    def test_merge_headers_with_multi_dict(self):\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers(MultiDict([(\"h1\", \"h1\")]))\n        self.assertIsInstance(headers, CIMultiDict)\n        self.assertEqual(headers, CIMultiDict([\n            (\"h1\", \"h1\"),\n            (\"h2\", \"header2\")\n        ]))\n        session.close()\n\n    def test_merge_headers_with_list_of_tuples(self):\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers([(\"h1\", \"h1\")])\n        self.assertIsInstance(headers, CIMultiDict)\n        self.assertEqual(headers, CIMultiDict([\n            (\"h1\", \"h1\"),\n            (\"h2\", \"header2\")\n        ]))\n        session.close()\n\n    def _make_one(self):\n        session = ClientSession(loop=self.loop)\n        params = 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        return session, params\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_GET(self, patched):\n        session, params = self._make_one()\n        self.run(session.get(\n            \"http://test.example.com\",\n            params={\"x\": 1},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"GET\", \"http://test.example.com\",),\n             dict(\n                 params={\"x\": 1},\n                 allow_redirects=True,\n                 **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_OPTIONS(self, patched):\n        session, params = self._make_one()\n        self.run(session.options(\n            \"http://opt.example.com\",\n            params={\"x\": 2},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"OPTIONS\", \"http://opt.example.com\",),\n             dict(\n                params={\"x\": 2},\n                allow_redirects=True,\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_HEAD(self, patched):\n        session, params = self._make_one()\n        self.run(session.head(\n            \"http://head.example.com\",\n            params={\"x\": 2},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"HEAD\", \"http://head.example.com\",),\n             dict(\n                params={\"x\": 2},\n                allow_redirects=False,\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_POST(self, patched):\n        session, params = self._make_one()\n        self.run(session.post(\n            \"http://post.example.com\",\n            params={\"x\": 2},\n            data=\"Some_data\",\n            files={\"x\": '1'},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"POST\", \"http://post.example.com\",),\n             dict(\n                params={\"x\": 2},\n                data=\"Some_data\",\n                files={\"x\": '1'},\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_PUT(self, patched):\n        session, params = self._make_one()\n        self.run(session.put(\n            \"http://put.example.com\",\n            params={\"x\": 2},\n            data=\"Some_data\",\n            files={\"x\": '1'},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"PUT\", \"http://put.example.com\",),\n             dict(\n                 params={\"x\": 2},\n                 data=\"Some_data\",\n                 files={\"x\": '1'},\n                 **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_PATCH(self, patched):\n        session, params = self._make_one()\n        self.run(session.patch(\n            \"http://patch.example.com\",\n            params={\"x\": 2},\n            data=\"Some_data\",\n            files={\"x\": '1'},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"PATCH\", \"http://patch.example.com\",),\n             dict(\n                params={\"x\": 2},\n                data=\"Some_data\",\n                files={\"x\": '1'},\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_DELETE(self, patched):\n        session, params = self._make_one()\n        self.run(session.delete(\n            \"http://delete.example.com\",\n            params={\"x\": 2},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"DELETE\", \"http://delete.example.com\",),\n             dict(\n                params={\"x\": 2},\n                **params)])\n        session.close()\n\n    def test_close(self):\n        conn = self.make_open_connector()\n        session = ClientSession(loop=self.loop, connector=conn)\n\n        session.close()\n        self.assertIsNone(session.connector)\n        self.assertTrue(conn.closed)\n\n    def test_closed(self):\n        session = ClientSession(loop=self.loop)\n        self.assertFalse(session.closed)\n        session.close()\n        self.assertTrue(session.closed)\n\n    def test_connector(self):\n        connector = TCPConnector(loop=self.loop)\n        session = ClientSession(connector=connector, loop=self.loop)\n        self.assertIs(session.connector, connector)\n        session.close()\n\n    def test_connector_loop(self):\n        loop = asyncio.new_event_loop()\n        connector = TCPConnector(loop=loop)\n        with self.assertRaisesRegex(\n                ValueError,\n                \"loop argument must agree with connector\"):\n            ClientSession(connector=connector, loop=self.loop)\n        connector.close()\n        loop.close()\n\n    def test_cookies_are_readonly(self):\n        session = ClientSession(loop=self.loop)\n        with self.assertRaises(AttributeError):\n            session.cookies = 123\n        session.close()\n\n    def test_detach(self):\n        session = ClientSession(loop=self.loop)\n        conn = session.connector\n        self.assertFalse(conn.closed)\n        session.detach()\n        self.assertIsNone(session.connector)\n        self.assertTrue(session.closed)\n        self.assertFalse(conn.closed)\n        conn.close()\n\n    def test_request_closed_session(self):\n        @asyncio.coroutine\n        def go():\n            session = ClientSession(loop=self.loop)\n            session.close()\n            with self.assertRaises(RuntimeError):\n                yield from session.request('get', '/')\n\n        self.loop.run_until_complete(go())\n\n    def test_close_flag_for_closed_connector(self):\n        session = ClientSession(loop=self.loop)\n        conn = session.connector\n        self.assertFalse(session.closed)\n        conn.close()\n        self.assertTrue(session.closed)\n\n    def test_double_close(self):\n        conn = self.make_open_connector()\n        session = ClientSession(loop=self.loop, connector=conn)\n\n        session.close()\n        self.assertIsNone(session.connector)\n        session.close()\n        self.assertTrue(session.closed)\n        self.assertTrue(conn.closed)\n\n    @unittest.skipUnless(PY_341, \"Requires Python 3.4.1+\")\n    def test_del(self):\n        conn = self.make_open_connector()\n        session = ClientSession(loop=self.loop, connector=conn)\n\n        with self.assertWarns(ResourceWarning):\n            del session\n            gc.collect()\n\n    def test_context_manager(self):\n        conn = self.make_open_connector()\n        with ClientSession(loop=self.loop, connector=conn) as session:\n            pass\n\n        self.assertTrue(session.closed)\n\n    def test_borrow_connector_loop(self):\n        conn = self.make_open_connector()\n        session = ClientSession(connector=conn)\n        self.assertIs(session._loop, self.loop)\n\n\nclass TestCLientRequest(unittest.TestCase):\n\n    def setUp(self):\n        self.loop = asyncio.new_event_loop()\n        asyncio.set_event_loop(None)\n        self.connector = BaseConnector(loop=self.loop)\n        self.transport = mock.Mock()\n        self.protocol = mock.Mock()\n\n    def tearDown(self):\n        self.loop.close()\n\n    def test_custom_req_rep(self):\n        @asyncio.coroutine\n        def go():\n            class CustomResponse(ClientResponse):\n                @asyncio.coroutine\n                def start(self, connection, read_until_eof=False):\n                    self.status = 123\n                    self.reason = 'Test OK'\n                    self.headers = CIMultiDictProxy(CIMultiDict())\n                    self.cookies = SimpleCookie()\n                    return\n\n            called = False\n\n            class CustomRequest(ClientRequest):\n\n                def send(self, writer, reader):\n                    resp = self.response_class(self.method,\n                                               self.url,\n                                               self.host,\n                                               writer=self._writer,\n                                               continue100=self._continue)\n                    resp._post_init(self.loop)\n                    self.response = resp\n                    nonlocal called\n                    called = True\n                    return resp\n\n            @asyncio.coroutine\n            def create_connection(req):\n                self.assertIsInstance(req, CustomRequest)\n                return self.transport, self.protocol\n            self.connector._create_connection = create_connection\n\n            resp = yield from aiohttp.request('get',\n                                              'http://example.com/path/to',\n                                              request_class=CustomRequest,\n                                              response_class=CustomResponse,\n                                              connector=self.connector,\n                                              loop=self.loop)\n            self.assertIsInstance(resp, CustomResponse)\n            self.assertTrue(called)\n        self.loop.run_until_complete(go())\n",
            "new_file_content": "# -*- coding: utf-8 -*-\n\"\"\"Tests for aiohttp/client.py\"\"\"\n\nimport asyncio\nimport gc\nimport unittest\nfrom unittest import mock\nimport sys\n\nimport aiohttp\nfrom aiohttp.client import ClientSession\nfrom aiohttp.multidict import MultiDict, CIMultiDict, CIMultiDictProxy\nfrom aiohttp.connector import BaseConnector, TCPConnector\nfrom aiohttp.client_reqrep import ClientRequest, ClientResponse\nfrom http.cookies import SimpleCookie\n\n\nPY_341 = sys.version_info >= (3, 4, 1)\n\n\nclass TestClientSession(unittest.TestCase):\n\n    maxDiff = None\n\n    def setUp(self):\n        self.loop = asyncio.new_event_loop()\n        asyncio.set_event_loop(None)\n        self.run = self.loop.run_until_complete\n\n    def tearDown(self):\n        self.loop.close()\n\n    def make_open_connector(self):\n        conn = BaseConnector(loop=self.loop)\n        transp = unittest.mock.Mock()\n        conn._conns['a'] = [(transp, 'proto', 123)]\n        return conn\n\n    def test_init_headers_simple_dict(self):\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        self.assertEqual(\n            sorted(session._default_headers.items()),\n            ([(\"H1\", \"header1\"),\n              (\"H2\", \"header2\")]))\n        session.close()\n\n    def test_init_headers_list_of_tuples(self):\n        session = ClientSession(\n            headers=[(\"h1\", \"header1\"),\n                     (\"h2\", \"header2\"),\n                     (\"h3\", \"header3\")],\n            loop=self.loop)\n        self.assertEqual(\n            session._default_headers,\n            CIMultiDict([(\"h1\", \"header1\"),\n                         (\"h2\", \"header2\"),\n                         (\"h3\", \"header3\")]))\n        session.close()\n\n    def test_init_headers_MultiDict(self):\n        session = ClientSession(\n            headers=MultiDict(\n                [(\"h1\", \"header1\"),\n                 (\"h2\", \"header2\"),\n                 (\"h3\", \"header3\")]),\n            loop=self.loop)\n        self.assertEqual(\n            session._default_headers,\n            CIMultiDict([(\"H1\", \"header1\"),\n                         (\"H2\", \"header2\"),\n                         (\"H3\", \"header3\")]))\n        session.close()\n\n    def test_init_cookies_with_simple_dict(self):\n        session = ClientSession(\n            cookies={\n                \"c1\": \"cookie1\",\n                \"c2\": \"cookie2\"\n            }, loop=self.loop)\n        self.assertEqual(set(session.cookies), {'c1', 'c2'})\n        self.assertEqual(session.cookies['c1'].value, 'cookie1')\n        self.assertEqual(session.cookies['c2'].value, 'cookie2')\n        session.close()\n\n    def test_init_cookies_with_list_of_tuples(self):\n        session = ClientSession(\n            cookies=[(\"c1\", \"cookie1\"),\n                     (\"c2\", \"cookie2\")],\n            loop=self.loop)\n        self.assertEqual(set(session.cookies), {'c1', 'c2'})\n        self.assertEqual(session.cookies['c1'].value, 'cookie1')\n        self.assertEqual(session.cookies['c2'].value, 'cookie2')\n        session.close()\n\n    def test_merge_headers(self):\n        # Check incoming simple dict\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers({\n            \"h1\": \"h1\"\n        })\n        self.assertIsInstance(headers, CIMultiDict)\n        self.assertEqual(headers, CIMultiDict([\n            (\"h2\", \"header2\"),\n            (\"h1\", \"h1\")\n        ]))\n        session.close()\n\n    def test_merge_headers_with_multi_dict(self):\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers(MultiDict([(\"h1\", \"h1\")]))\n        self.assertIsInstance(headers, CIMultiDict)\n        self.assertEqual(headers, CIMultiDict([\n            (\"h2\", \"header2\"),\n            (\"h1\", \"h1\")\n        ]))\n        session.close()\n\n    def test_merge_headers_with_list_of_tuples(self):\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers([(\"h1\", \"h1\")])\n        self.assertIsInstance(headers, CIMultiDict)\n        self.assertEqual(headers, CIMultiDict([\n            (\"h2\", \"header2\"),\n            (\"h1\", \"h1\")\n        ]))\n        session.close()\n\n    def _make_one(self):\n        session = ClientSession(loop=self.loop)\n        params = 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        return session, params\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_GET(self, patched):\n        session, params = self._make_one()\n        self.run(session.get(\n            \"http://test.example.com\",\n            params={\"x\": 1},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"GET\", \"http://test.example.com\",),\n             dict(\n                 params={\"x\": 1},\n                 allow_redirects=True,\n                 **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_OPTIONS(self, patched):\n        session, params = self._make_one()\n        self.run(session.options(\n            \"http://opt.example.com\",\n            params={\"x\": 2},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"OPTIONS\", \"http://opt.example.com\",),\n             dict(\n                params={\"x\": 2},\n                allow_redirects=True,\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_HEAD(self, patched):\n        session, params = self._make_one()\n        self.run(session.head(\n            \"http://head.example.com\",\n            params={\"x\": 2},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"HEAD\", \"http://head.example.com\",),\n             dict(\n                params={\"x\": 2},\n                allow_redirects=False,\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_POST(self, patched):\n        session, params = self._make_one()\n        self.run(session.post(\n            \"http://post.example.com\",\n            params={\"x\": 2},\n            data=\"Some_data\",\n            files={\"x\": '1'},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"POST\", \"http://post.example.com\",),\n             dict(\n                params={\"x\": 2},\n                data=\"Some_data\",\n                files={\"x\": '1'},\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_PUT(self, patched):\n        session, params = self._make_one()\n        self.run(session.put(\n            \"http://put.example.com\",\n            params={\"x\": 2},\n            data=\"Some_data\",\n            files={\"x\": '1'},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"PUT\", \"http://put.example.com\",),\n             dict(\n                 params={\"x\": 2},\n                 data=\"Some_data\",\n                 files={\"x\": '1'},\n                 **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_PATCH(self, patched):\n        session, params = self._make_one()\n        self.run(session.patch(\n            \"http://patch.example.com\",\n            params={\"x\": 2},\n            data=\"Some_data\",\n            files={\"x\": '1'},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"PATCH\", \"http://patch.example.com\",),\n             dict(\n                params={\"x\": 2},\n                data=\"Some_data\",\n                files={\"x\": '1'},\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_DELETE(self, patched):\n        session, params = self._make_one()\n        self.run(session.delete(\n            \"http://delete.example.com\",\n            params={\"x\": 2},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"DELETE\", \"http://delete.example.com\",),\n             dict(\n                params={\"x\": 2},\n                **params)])\n        session.close()\n\n    def test_close(self):\n        conn = self.make_open_connector()\n        session = ClientSession(loop=self.loop, connector=conn)\n\n        session.close()\n        self.assertIsNone(session.connector)\n        self.assertTrue(conn.closed)\n\n    def test_closed(self):\n        session = ClientSession(loop=self.loop)\n        self.assertFalse(session.closed)\n        session.close()\n        self.assertTrue(session.closed)\n\n    def test_connector(self):\n        connector = TCPConnector(loop=self.loop)\n        session = ClientSession(connector=connector, loop=self.loop)\n        self.assertIs(session.connector, connector)\n        session.close()\n\n    def test_connector_loop(self):\n        loop = asyncio.new_event_loop()\n        connector = TCPConnector(loop=loop)\n        with self.assertRaisesRegex(\n                ValueError,\n                \"loop argument must agree with connector\"):\n            ClientSession(connector=connector, loop=self.loop)\n        connector.close()\n        loop.close()\n\n    def test_cookies_are_readonly(self):\n        session = ClientSession(loop=self.loop)\n        with self.assertRaises(AttributeError):\n            session.cookies = 123\n        session.close()\n\n    def test_detach(self):\n        session = ClientSession(loop=self.loop)\n        conn = session.connector\n        self.assertFalse(conn.closed)\n        session.detach()\n        self.assertIsNone(session.connector)\n        self.assertTrue(session.closed)\n        self.assertFalse(conn.closed)\n        conn.close()\n\n    def test_request_closed_session(self):\n        @asyncio.coroutine\n        def go():\n            session = ClientSession(loop=self.loop)\n            session.close()\n            with self.assertRaises(RuntimeError):\n                yield from session.request('get', '/')\n\n        self.loop.run_until_complete(go())\n\n    def test_close_flag_for_closed_connector(self):\n        session = ClientSession(loop=self.loop)\n        conn = session.connector\n        self.assertFalse(session.closed)\n        conn.close()\n        self.assertTrue(session.closed)\n\n    def test_double_close(self):\n        conn = self.make_open_connector()\n        session = ClientSession(loop=self.loop, connector=conn)\n\n        session.close()\n        self.assertIsNone(session.connector)\n        session.close()\n        self.assertTrue(session.closed)\n        self.assertTrue(conn.closed)\n\n    @unittest.skipUnless(PY_341, \"Requires Python 3.4.1+\")\n    def test_del(self):\n        conn = self.make_open_connector()\n        session = ClientSession(loop=self.loop, connector=conn)\n\n        with self.assertWarns(ResourceWarning):\n            del session\n            gc.collect()\n\n    def test_context_manager(self):\n        conn = self.make_open_connector()\n        with ClientSession(loop=self.loop, connector=conn) as session:\n            pass\n\n        self.assertTrue(session.closed)\n\n    def test_borrow_connector_loop(self):\n        conn = self.make_open_connector()\n        session = ClientSession(connector=conn)\n        self.assertIs(session._loop, self.loop)\n\n\nclass TestCLientRequest(unittest.TestCase):\n\n    def setUp(self):\n        self.loop = asyncio.new_event_loop()\n        asyncio.set_event_loop(None)\n        self.connector = BaseConnector(loop=self.loop)\n        self.transport = mock.Mock()\n        self.protocol = mock.Mock()\n\n    def tearDown(self):\n        self.loop.close()\n\n    def test_custom_req_rep(self):\n        @asyncio.coroutine\n        def go():\n            class CustomResponse(ClientResponse):\n                @asyncio.coroutine\n                def start(self, connection, read_until_eof=False):\n                    self.status = 123\n                    self.reason = 'Test OK'\n                    self.headers = CIMultiDictProxy(CIMultiDict())\n                    self.cookies = SimpleCookie()\n                    return\n\n            called = False\n\n            class CustomRequest(ClientRequest):\n\n                def send(self, writer, reader):\n                    resp = self.response_class(self.method,\n                                               self.url,\n                                               self.host,\n                                               writer=self._writer,\n                                               continue100=self._continue)\n                    resp._post_init(self.loop)\n                    self.response = resp\n                    nonlocal called\n                    called = True\n                    return resp\n\n            @asyncio.coroutine\n            def create_connection(req):\n                self.assertIsInstance(req, CustomRequest)\n                return self.transport, self.protocol\n            self.connector._create_connection = create_connection\n\n            resp = yield from aiohttp.request('get',\n                                              'http://example.com/path/to',\n                                              request_class=CustomRequest,\n                                              response_class=CustomResponse,\n                                              connector=self.connector,\n                                              loop=self.loop)\n            self.assertIsInstance(resp, CustomResponse)\n            self.assertTrue(called)\n        self.loop.run_until_complete(go())\n",
            "header": {
                "file": {
                    "path": "tests/test_client_session.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "123cbdb9",
                "new_commit_hash": "0ef2cfb8",
                "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": 108,
                            "length": 8
                        },
                        "new_range": {
                            "start": 108,
                            "length": 8
                        },
                        "section": "class TestClientSession(unittest.TestCase):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        })",
                                "type": "context"
                            },
                            {
                                "content": "        self.assertIsInstance(headers, CIMultiDict)",
                                "type": "context"
                            },
                            {
                                "content": "        self.assertEqual(headers, CIMultiDict([",
                                "type": "context"
                            },
                            {
                                "content": "            (\"h1\", \"h1\"),",
                                "type": "deleted"
                            },
                            {
                                "content": "            (\"h2\", \"header2\")",
                                "type": "deleted"
                            },
                            {
                                "content": "            (\"h2\", \"header2\"),",
                                "type": "added"
                            },
                            {
                                "content": "            (\"h1\", \"h1\")",
                                "type": "added"
                            },
                            {
                                "content": "        ]))",
                                "type": "context"
                            },
                            {
                                "content": "        session.close()",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "tests/test_client_session.py",
                            "type": "method",
                            "name": "TestClientSession.test_merge_headers",
                            "content": "class TestClientSession(unittest.TestCase):\n\n    maxDiff = None\n\n    def setUp(self):\n        self.loop = asyncio.new_event_loop()\n        asyncio.set_event_loop(None)\n        self.run = self.loop.run_until_complete\n\n    def tearDown(self):\n        self.loop.close()\n\n    def make_open_connector(self):\n        conn = BaseConnector(loop=self.loop)\n        transp = unittest.mock.Mock()\n        conn._conns['a'] = [(transp, 'proto', 123)]\n        return conn\n\n    def test_init_headers_simple_dict(self):\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        self.assertEqual(\n            sorted(session._default_headers.items()),\n            ([(\"H1\", \"header1\"),\n              (\"H2\", \"header2\")]))\n        session.close()\n\n    def test_init_headers_list_of_tuples(self):\n        session = ClientSession(\n            headers=[(\"h1\", \"header1\"),\n                     (\"h2\", \"header2\"),\n                     (\"h3\", \"header3\")],\n            loop=self.loop)\n        self.assertEqual(\n            session._default_headers,\n            CIMultiDict([(\"h1\", \"header1\"),\n                         (\"h2\", \"header2\"),\n                         (\"h3\", \"header3\")]))\n        session.close()\n\n    def test_init_headers_MultiDict(self):\n        session = ClientSession(\n            headers=MultiDict(\n                [(\"h1\", \"header1\"),\n                 (\"h2\", \"header2\"),\n                 (\"h3\", \"header3\")]),\n            loop=self.loop)\n        self.assertEqual(\n            session._default_headers,\n            CIMultiDict([(\"H1\", \"header1\"),\n                         (\"H2\", \"header2\"),\n                         (\"H3\", \"header3\")]))\n        session.close()\n\n    def test_init_cookies_with_simple_dict(self):\n        session = ClientSession(\n            cookies={\n                \"c1\": \"cookie1\",\n                \"c2\": \"cookie2\"\n            }, loop=self.loop)\n        self.assertEqual(set(session.cookies), {'c1', 'c2'})\n        self.assertEqual(session.cookies['c1'].value, 'cookie1')\n        self.assertEqual(session.cookies['c2'].value, 'cookie2')\n        session.close()\n\n    def test_init_cookies_with_list_of_tuples(self):\n        session = ClientSession(\n            cookies=[(\"c1\", \"cookie1\"),\n                     (\"c2\", \"cookie2\")],\n            loop=self.loop)\n        self.assertEqual(set(session.cookies), {'c1', 'c2'})\n        self.assertEqual(session.cookies['c1'].value, 'cookie1')\n        self.assertEqual(session.cookies['c2'].value, 'cookie2')\n        session.close()\n\n    def test_merge_headers(self):\n        # Check incoming simple dict\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers({\n            \"h1\": \"h1\"\n        })\n        self.assertIsInstance(headers, CIMultiDict)\n        self.assertEqual(headers, CIMultiDict([\n            (\"h1\", \"h1\"),\n            (\"h2\", \"header2\")\n        ]))\n        session.close()\n\n    def test_merge_headers_with_multi_dict(self):\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers(MultiDict([(\"h1\", \"h1\")]))\n        self.assertIsInstance(headers, CIMultiDict)\n        self.assertEqual(headers, CIMultiDict([\n            (\"h1\", \"h1\"),\n            (\"h2\", \"header2\")\n        ]))\n        session.close()\n\n    def test_merge_headers_with_list_of_tuples(self):\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers([(\"h1\", \"h1\")])\n        self.assertIsInstance(headers, CIMultiDict)\n        self.assertEqual(headers, CIMultiDict([\n            (\"h1\", \"h1\"),\n            (\"h2\", \"header2\")\n        ]))\n        session.close()\n\n    def _make_one(self):\n        session = ClientSession(loop=self.loop)\n        params = 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        return session, params\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_GET(self, patched):\n        session, params = self._make_one()\n        self.run(session.get(\n            \"http://test.example.com\",\n            params={\"x\": 1},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"GET\", \"http://test.example.com\",),\n             dict(\n                 params={\"x\": 1},\n                 allow_redirects=True,\n                 **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_OPTIONS(self, patched):\n        session, params = self._make_one()\n        self.run(session.options(\n            \"http://opt.example.com\",\n            params={\"x\": 2},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"OPTIONS\", \"http://opt.example.com\",),\n             dict(\n                params={\"x\": 2},\n                allow_redirects=True,\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_HEAD(self, patched):\n        session, params = self._make_one()\n        self.run(session.head(\n            \"http://head.example.com\",\n            params={\"x\": 2},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"HEAD\", \"http://head.example.com\",),\n             dict(\n                params={\"x\": 2},\n                allow_redirects=False,\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_POST(self, patched):\n        session, params = self._make_one()\n        self.run(session.post(\n            \"http://post.example.com\",\n            params={\"x\": 2},\n            data=\"Some_data\",\n            files={\"x\": '1'},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"POST\", \"http://post.example.com\",),\n             dict(\n                params={\"x\": 2},\n                data=\"Some_data\",\n                files={\"x\": '1'},\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_PUT(self, patched):\n        session, params = self._make_one()\n        self.run(session.put(\n            \"http://put.example.com\",\n            params={\"x\": 2},\n            data=\"Some_data\",\n            files={\"x\": '1'},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"PUT\", \"http://put.example.com\",),\n             dict(\n                 params={\"x\": 2},\n                 data=\"Some_data\",\n                 files={\"x\": '1'},\n                 **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_PATCH(self, patched):\n        session, params = self._make_one()\n        self.run(session.patch(\n            \"http://patch.example.com\",\n            params={\"x\": 2},\n            data=\"Some_data\",\n            files={\"x\": '1'},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"PATCH\", \"http://patch.example.com\",),\n             dict(\n                params={\"x\": 2},\n                data=\"Some_data\",\n                files={\"x\": '1'},\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_DELETE(self, patched):\n        session, params = self._make_one()\n        self.run(session.delete(\n            \"http://delete.example.com\",\n            params={\"x\": 2},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"DELETE\", \"http://delete.example.com\",),\n             dict(\n                params={\"x\": 2},\n                **params)])\n        session.close()\n\n    def test_close(self):\n        conn = self.make_open_connector()\n        session = ClientSession(loop=self.loop, connector=conn)\n\n        session.close()\n        self.assertIsNone(session.connector)\n        self.assertTrue(conn.closed)\n\n    def test_closed(self):\n        session = ClientSession(loop=self.loop)\n        self.assertFalse(session.closed)\n        session.close()\n        self.assertTrue(session.closed)\n\n    def test_connector(self):\n        connector = TCPConnector(loop=self.loop)\n        session = ClientSession(connector=connector, loop=self.loop)\n        self.assertIs(session.connector, connector)\n        session.close()\n\n    def test_connector_loop(self):\n        loop = asyncio.new_event_loop()\n        connector = TCPConnector(loop=loop)\n        with self.assertRaisesRegex(\n                ValueError,\n                \"loop argument must agree with connector\"):\n            ClientSession(connector=connector, loop=self.loop)\n        connector.close()\n        loop.close()\n\n    def test_cookies_are_readonly(self):\n        session = ClientSession(loop=self.loop)\n        with self.assertRaises(AttributeError):\n            session.cookies = 123\n        session.close()\n\n    def test_detach(self):\n        session = ClientSession(loop=self.loop)\n        conn = session.connector\n        self.assertFalse(conn.closed)\n        session.detach()\n        self.assertIsNone(session.connector)\n        self.assertTrue(session.closed)\n        self.assertFalse(conn.closed)\n        conn.close()\n\n    def test_request_closed_session(self):\n        @asyncio.coroutine\n        def go():\n            session = ClientSession(loop=self.loop)\n            session.close()\n            with self.assertRaises(RuntimeError):\n                yield from session.request('get', '/')\n\n        self.loop.run_until_complete(go())\n\n    def test_close_flag_for_closed_connector(self):\n        session = ClientSession(loop=self.loop)\n        conn = session.connector\n        self.assertFalse(session.closed)\n        conn.close()\n        self.assertTrue(session.closed)\n\n    def test_double_close(self):\n        conn = self.make_open_connector()\n        session = ClientSession(loop=self.loop, connector=conn)\n\n        session.close()\n        self.assertIsNone(session.connector)\n        session.close()\n        self.assertTrue(session.closed)\n        self.assertTrue(conn.closed)\n\n    @unittest.skipUnless(PY_341, \"Requires Python 3.4.1+\")\n    def test_del(self):\n        conn = self.make_open_connector()\n        session = ClientSession(loop=self.loop, connector=conn)\n\n        with self.assertWarns(ResourceWarning):\n            del session\n            gc.collect()\n\n    def test_context_manager(self):\n        conn = self.make_open_connector()\n        with ClientSession(loop=self.loop, connector=conn) as session:\n            pass\n\n        self.assertTrue(session.closed)\n\n    def test_borrow_connector_loop(self):\n        conn = self.make_open_connector()\n        session = ClientSession(connector=conn)\n        self.assertIs(session._loop, self.loop)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 99,
                            "end_lineno": 114,
                            "parent": {
                                "file_name": "tests/test_client_session.py",
                                "type": "class",
                                "name": "TestClientSession",
                                "content": "class TestClientSession(unittest.TestCase):\n\n    maxDiff = None\n\n    def setUp(self):\n        self.loop = asyncio.new_event_loop()\n        asyncio.set_event_loop(None)\n        self.run = self.loop.run_until_complete\n\n    def tearDown(self):\n        self.loop.close()\n\n    def make_open_connector(self):\n        conn = BaseConnector(loop=self.loop)\n        transp = unittest.mock.Mock()\n        conn._conns['a'] = [(transp, 'proto', 123)]\n        return conn\n\n    def test_init_headers_simple_dict(self):\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        self.assertEqual(\n            sorted(session._default_headers.items()),\n            ([(\"H1\", \"header1\"),\n              (\"H2\", \"header2\")]))\n        session.close()\n\n    def test_init_headers_list_of_tuples(self):\n        session = ClientSession(\n            headers=[(\"h1\", \"header1\"),\n                     (\"h2\", \"header2\"),\n                     (\"h3\", \"header3\")],\n            loop=self.loop)\n        self.assertEqual(\n            session._default_headers,\n            CIMultiDict([(\"h1\", \"header1\"),\n                         (\"h2\", \"header2\"),\n                         (\"h3\", \"header3\")]))\n        session.close()\n\n    def test_init_headers_MultiDict(self):\n        session = ClientSession(\n            headers=MultiDict(\n                [(\"h1\", \"header1\"),\n                 (\"h2\", \"header2\"),\n                 (\"h3\", \"header3\")]),\n            loop=self.loop)\n        self.assertEqual(\n            session._default_headers,\n            CIMultiDict([(\"H1\", \"header1\"),\n                         (\"H2\", \"header2\"),\n                         (\"H3\", \"header3\")]))\n        session.close()\n\n    def test_init_cookies_with_simple_dict(self):\n        session = ClientSession(\n            cookies={\n                \"c1\": \"cookie1\",\n                \"c2\": \"cookie2\"\n            }, loop=self.loop)\n        self.assertEqual(set(session.cookies), {'c1', 'c2'})\n        self.assertEqual(session.cookies['c1'].value, 'cookie1')\n        self.assertEqual(session.cookies['c2'].value, 'cookie2')\n        session.close()\n\n    def test_init_cookies_with_list_of_tuples(self):\n        session = ClientSession(\n            cookies=[(\"c1\", \"cookie1\"),\n                     (\"c2\", \"cookie2\")],\n            loop=self.loop)\n        self.assertEqual(set(session.cookies), {'c1', 'c2'})\n        self.assertEqual(session.cookies['c1'].value, 'cookie1')\n        self.assertEqual(session.cookies['c2'].value, 'cookie2')\n        session.close()\n\n    def test_merge_headers(self):\n        # Check incoming simple dict\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers({\n            \"h1\": \"h1\"\n        })\n        self.assertIsInstance(headers, CIMultiDict)\n        self.assertEqual(headers, CIMultiDict([\n            (\"h1\", \"h1\"),\n            (\"h2\", \"header2\")\n        ]))\n        session.close()\n\n    def test_merge_headers_with_multi_dict(self):\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers(MultiDict([(\"h1\", \"h1\")]))\n        self.assertIsInstance(headers, CIMultiDict)\n        self.assertEqual(headers, CIMultiDict([\n            (\"h1\", \"h1\"),\n            (\"h2\", \"header2\")\n        ]))\n        session.close()\n\n    def test_merge_headers_with_list_of_tuples(self):\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers([(\"h1\", \"h1\")])\n        self.assertIsInstance(headers, CIMultiDict)\n        self.assertEqual(headers, CIMultiDict([\n            (\"h1\", \"h1\"),\n            (\"h2\", \"header2\")\n        ]))\n        session.close()\n\n    def _make_one(self):\n        session = ClientSession(loop=self.loop)\n        params = 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        return session, params\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_GET(self, patched):\n        session, params = self._make_one()\n        self.run(session.get(\n            \"http://test.example.com\",\n            params={\"x\": 1},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"GET\", \"http://test.example.com\",),\n             dict(\n                 params={\"x\": 1},\n                 allow_redirects=True,\n                 **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_OPTIONS(self, patched):\n        session, params = self._make_one()\n        self.run(session.options(\n            \"http://opt.example.com\",\n            params={\"x\": 2},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"OPTIONS\", \"http://opt.example.com\",),\n             dict(\n                params={\"x\": 2},\n                allow_redirects=True,\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_HEAD(self, patched):\n        session, params = self._make_one()\n        self.run(session.head(\n            \"http://head.example.com\",\n            params={\"x\": 2},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"HEAD\", \"http://head.example.com\",),\n             dict(\n                params={\"x\": 2},\n                allow_redirects=False,\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_POST(self, patched):\n        session, params = self._make_one()\n        self.run(session.post(\n            \"http://post.example.com\",\n            params={\"x\": 2},\n            data=\"Some_data\",\n            files={\"x\": '1'},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"POST\", \"http://post.example.com\",),\n             dict(\n                params={\"x\": 2},\n                data=\"Some_data\",\n                files={\"x\": '1'},\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_PUT(self, patched):\n        session, params = self._make_one()\n        self.run(session.put(\n            \"http://put.example.com\",\n            params={\"x\": 2},\n            data=\"Some_data\",\n            files={\"x\": '1'},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"PUT\", \"http://put.example.com\",),\n             dict(\n                 params={\"x\": 2},\n                 data=\"Some_data\",\n                 files={\"x\": '1'},\n                 **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_PATCH(self, patched):\n        session, params = self._make_one()\n        self.run(session.patch(\n            \"http://patch.example.com\",\n            params={\"x\": 2},\n            data=\"Some_data\",\n            files={\"x\": '1'},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"PATCH\", \"http://patch.example.com\",),\n             dict(\n                params={\"x\": 2},\n                data=\"Some_data\",\n                files={\"x\": '1'},\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_DELETE(self, patched):\n        session, params = self._make_one()\n        self.run(session.delete(\n            \"http://delete.example.com\",\n            params={\"x\": 2},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"DELETE\", \"http://delete.example.com\",),\n             dict(\n                params={\"x\": 2},\n                **params)])\n        session.close()\n\n    def test_close(self):\n        conn = self.make_open_connector()\n        session = ClientSession(loop=self.loop, connector=conn)\n\n        session.close()\n        self.assertIsNone(session.connector)\n        self.assertTrue(conn.closed)\n\n    def test_closed(self):\n        session = ClientSession(loop=self.loop)\n        self.assertFalse(session.closed)\n        session.close()\n        self.assertTrue(session.closed)\n\n    def test_connector(self):\n        connector = TCPConnector(loop=self.loop)\n        session = ClientSession(connector=connector, loop=self.loop)\n        self.assertIs(session.connector, connector)\n        session.close()\n\n    def test_connector_loop(self):\n        loop = asyncio.new_event_loop()\n        connector = TCPConnector(loop=loop)\n        with self.assertRaisesRegex(\n                ValueError,\n                \"loop argument must agree with connector\"):\n            ClientSession(connector=connector, loop=self.loop)\n        connector.close()\n        loop.close()\n\n    def test_cookies_are_readonly(self):\n        session = ClientSession(loop=self.loop)\n        with self.assertRaises(AttributeError):\n            session.cookies = 123\n        session.close()\n\n    def test_detach(self):\n        session = ClientSession(loop=self.loop)\n        conn = session.connector\n        self.assertFalse(conn.closed)\n        session.detach()\n        self.assertIsNone(session.connector)\n        self.assertTrue(session.closed)\n        self.assertFalse(conn.closed)\n        conn.close()\n\n    def test_request_closed_session(self):\n        @asyncio.coroutine\n        def go():\n            session = ClientSession(loop=self.loop)\n            session.close()\n            with self.assertRaises(RuntimeError):\n                yield from session.request('get', '/')\n\n        self.loop.run_until_complete(go())\n\n    def test_close_flag_for_closed_connector(self):\n        session = ClientSession(loop=self.loop)\n        conn = session.connector\n        self.assertFalse(session.closed)\n        conn.close()\n        self.assertTrue(session.closed)\n\n    def test_double_close(self):\n        conn = self.make_open_connector()\n        session = ClientSession(loop=self.loop, connector=conn)\n\n        session.close()\n        self.assertIsNone(session.connector)\n        session.close()\n        self.assertTrue(session.closed)\n        self.assertTrue(conn.closed)\n\n    @unittest.skipUnless(PY_341, \"Requires Python 3.4.1+\")\n    def test_del(self):\n        conn = self.make_open_connector()\n        session = ClientSession(loop=self.loop, connector=conn)\n\n        with self.assertWarns(ResourceWarning):\n            del session\n            gc.collect()\n\n    def test_context_manager(self):\n        conn = self.make_open_connector()\n        with ClientSession(loop=self.loop, connector=conn) as session:\n            pass\n\n        self.assertTrue(session.closed)\n\n    def test_borrow_connector_loop(self):\n        conn = self.make_open_connector()\n        session = ClientSession(connector=conn)\n        self.assertIs(session._loop, self.loop)",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 21,
                                "end_lineno": 376,
                                "parent": null
                            }
                        },
                        {
                            "file_name": "tests/test_client_session.py",
                            "type": "class",
                            "name": "TestClientSession",
                            "content": "class TestClientSession(unittest.TestCase):\n\n    maxDiff = None\n\n    def setUp(self):\n        self.loop = asyncio.new_event_loop()\n        asyncio.set_event_loop(None)\n        self.run = self.loop.run_until_complete\n\n    def tearDown(self):\n        self.loop.close()\n\n    def make_open_connector(self):\n        conn = BaseConnector(loop=self.loop)\n        transp = unittest.mock.Mock()\n        conn._conns['a'] = [(transp, 'proto', 123)]\n        return conn\n\n    def test_init_headers_simple_dict(self):\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        self.assertEqual(\n            sorted(session._default_headers.items()),\n            ([(\"H1\", \"header1\"),\n              (\"H2\", \"header2\")]))\n        session.close()\n\n    def test_init_headers_list_of_tuples(self):\n        session = ClientSession(\n            headers=[(\"h1\", \"header1\"),\n                     (\"h2\", \"header2\"),\n                     (\"h3\", \"header3\")],\n            loop=self.loop)\n        self.assertEqual(\n            session._default_headers,\n            CIMultiDict([(\"h1\", \"header1\"),\n                         (\"h2\", \"header2\"),\n                         (\"h3\", \"header3\")]))\n        session.close()\n\n    def test_init_headers_MultiDict(self):\n        session = ClientSession(\n            headers=MultiDict(\n                [(\"h1\", \"header1\"),\n                 (\"h2\", \"header2\"),\n                 (\"h3\", \"header3\")]),\n            loop=self.loop)\n        self.assertEqual(\n            session._default_headers,\n            CIMultiDict([(\"H1\", \"header1\"),\n                         (\"H2\", \"header2\"),\n                         (\"H3\", \"header3\")]))\n        session.close()\n\n    def test_init_cookies_with_simple_dict(self):\n        session = ClientSession(\n            cookies={\n                \"c1\": \"cookie1\",\n                \"c2\": \"cookie2\"\n            }, loop=self.loop)\n        self.assertEqual(set(session.cookies), {'c1', 'c2'})\n        self.assertEqual(session.cookies['c1'].value, 'cookie1')\n        self.assertEqual(session.cookies['c2'].value, 'cookie2')\n        session.close()\n\n    def test_init_cookies_with_list_of_tuples(self):\n        session = ClientSession(\n            cookies=[(\"c1\", \"cookie1\"),\n                     (\"c2\", \"cookie2\")],\n            loop=self.loop)\n        self.assertEqual(set(session.cookies), {'c1', 'c2'})\n        self.assertEqual(session.cookies['c1'].value, 'cookie1')\n        self.assertEqual(session.cookies['c2'].value, 'cookie2')\n        session.close()\n\n    def test_merge_headers(self):\n        # Check incoming simple dict\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers({\n            \"h1\": \"h1\"\n        })\n        self.assertIsInstance(headers, CIMultiDict)\n        self.assertEqual(headers, CIMultiDict([\n            (\"h1\", \"h1\"),\n            (\"h2\", \"header2\")\n        ]))\n        session.close()\n\n    def test_merge_headers_with_multi_dict(self):\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers(MultiDict([(\"h1\", \"h1\")]))\n        self.assertIsInstance(headers, CIMultiDict)\n        self.assertEqual(headers, CIMultiDict([\n            (\"h1\", \"h1\"),\n            (\"h2\", \"header2\")\n        ]))\n        session.close()\n\n    def test_merge_headers_with_list_of_tuples(self):\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers([(\"h1\", \"h1\")])\n        self.assertIsInstance(headers, CIMultiDict)\n        self.assertEqual(headers, CIMultiDict([\n            (\"h1\", \"h1\"),\n            (\"h2\", \"header2\")\n        ]))\n        session.close()\n\n    def _make_one(self):\n        session = ClientSession(loop=self.loop)\n        params = 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        return session, params\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_GET(self, patched):\n        session, params = self._make_one()\n        self.run(session.get(\n            \"http://test.example.com\",\n            params={\"x\": 1},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"GET\", \"http://test.example.com\",),\n             dict(\n                 params={\"x\": 1},\n                 allow_redirects=True,\n                 **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_OPTIONS(self, patched):\n        session, params = self._make_one()\n        self.run(session.options(\n            \"http://opt.example.com\",\n            params={\"x\": 2},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"OPTIONS\", \"http://opt.example.com\",),\n             dict(\n                params={\"x\": 2},\n                allow_redirects=True,\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_HEAD(self, patched):\n        session, params = self._make_one()\n        self.run(session.head(\n            \"http://head.example.com\",\n            params={\"x\": 2},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"HEAD\", \"http://head.example.com\",),\n             dict(\n                params={\"x\": 2},\n                allow_redirects=False,\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_POST(self, patched):\n        session, params = self._make_one()\n        self.run(session.post(\n            \"http://post.example.com\",\n            params={\"x\": 2},\n            data=\"Some_data\",\n            files={\"x\": '1'},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"POST\", \"http://post.example.com\",),\n             dict(\n                params={\"x\": 2},\n                data=\"Some_data\",\n                files={\"x\": '1'},\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_PUT(self, patched):\n        session, params = self._make_one()\n        self.run(session.put(\n            \"http://put.example.com\",\n            params={\"x\": 2},\n            data=\"Some_data\",\n            files={\"x\": '1'},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"PUT\", \"http://put.example.com\",),\n             dict(\n                 params={\"x\": 2},\n                 data=\"Some_data\",\n                 files={\"x\": '1'},\n                 **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_PATCH(self, patched):\n        session, params = self._make_one()\n        self.run(session.patch(\n            \"http://patch.example.com\",\n            params={\"x\": 2},\n            data=\"Some_data\",\n            files={\"x\": '1'},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"PATCH\", \"http://patch.example.com\",),\n             dict(\n                params={\"x\": 2},\n                data=\"Some_data\",\n                files={\"x\": '1'},\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_DELETE(self, patched):\n        session, params = self._make_one()\n        self.run(session.delete(\n            \"http://delete.example.com\",\n            params={\"x\": 2},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"DELETE\", \"http://delete.example.com\",),\n             dict(\n                params={\"x\": 2},\n                **params)])\n        session.close()\n\n    def test_close(self):\n        conn = self.make_open_connector()\n        session = ClientSession(loop=self.loop, connector=conn)\n\n        session.close()\n        self.assertIsNone(session.connector)\n        self.assertTrue(conn.closed)\n\n    def test_closed(self):\n        session = ClientSession(loop=self.loop)\n        self.assertFalse(session.closed)\n        session.close()\n        self.assertTrue(session.closed)\n\n    def test_connector(self):\n        connector = TCPConnector(loop=self.loop)\n        session = ClientSession(connector=connector, loop=self.loop)\n        self.assertIs(session.connector, connector)\n        session.close()\n\n    def test_connector_loop(self):\n        loop = asyncio.new_event_loop()\n        connector = TCPConnector(loop=loop)\n        with self.assertRaisesRegex(\n                ValueError,\n                \"loop argument must agree with connector\"):\n            ClientSession(connector=connector, loop=self.loop)\n        connector.close()\n        loop.close()\n\n    def test_cookies_are_readonly(self):\n        session = ClientSession(loop=self.loop)\n        with self.assertRaises(AttributeError):\n            session.cookies = 123\n        session.close()\n\n    def test_detach(self):\n        session = ClientSession(loop=self.loop)\n        conn = session.connector\n        self.assertFalse(conn.closed)\n        session.detach()\n        self.assertIsNone(session.connector)\n        self.assertTrue(session.closed)\n        self.assertFalse(conn.closed)\n        conn.close()\n\n    def test_request_closed_session(self):\n        @asyncio.coroutine\n        def go():\n            session = ClientSession(loop=self.loop)\n            session.close()\n            with self.assertRaises(RuntimeError):\n                yield from session.request('get', '/')\n\n        self.loop.run_until_complete(go())\n\n    def test_close_flag_for_closed_connector(self):\n        session = ClientSession(loop=self.loop)\n        conn = session.connector\n        self.assertFalse(session.closed)\n        conn.close()\n        self.assertTrue(session.closed)\n\n    def test_double_close(self):\n        conn = self.make_open_connector()\n        session = ClientSession(loop=self.loop, connector=conn)\n\n        session.close()\n        self.assertIsNone(session.connector)\n        session.close()\n        self.assertTrue(session.closed)\n        self.assertTrue(conn.closed)\n\n    @unittest.skipUnless(PY_341, \"Requires Python 3.4.1+\")\n    def test_del(self):\n        conn = self.make_open_connector()\n        session = ClientSession(loop=self.loop, connector=conn)\n\n        with self.assertWarns(ResourceWarning):\n            del session\n            gc.collect()\n\n    def test_context_manager(self):\n        conn = self.make_open_connector()\n        with ClientSession(loop=self.loop, connector=conn) as session:\n            pass\n\n        self.assertTrue(session.closed)\n\n    def test_borrow_connector_loop(self):\n        conn = self.make_open_connector()\n        session = ClientSession(connector=conn)\n        self.assertIs(session._loop, self.loop)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 21,
                            "end_lineno": 376,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 122,
                            "length": 8
                        },
                        "new_range": {
                            "start": 122,
                            "length": 8
                        },
                        "section": "class TestClientSession(unittest.TestCase):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        headers = session._prepare_headers(MultiDict([(\"h1\", \"h1\")]))",
                                "type": "context"
                            },
                            {
                                "content": "        self.assertIsInstance(headers, CIMultiDict)",
                                "type": "context"
                            },
                            {
                                "content": "        self.assertEqual(headers, CIMultiDict([",
                                "type": "context"
                            },
                            {
                                "content": "            (\"h1\", \"h1\"),",
                                "type": "deleted"
                            },
                            {
                                "content": "            (\"h2\", \"header2\")",
                                "type": "deleted"
                            },
                            {
                                "content": "            (\"h2\", \"header2\"),",
                                "type": "added"
                            },
                            {
                                "content": "            (\"h1\", \"h1\")",
                                "type": "added"
                            },
                            {
                                "content": "        ]))",
                                "type": "context"
                            },
                            {
                                "content": "        session.close()",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "tests/test_client_session.py",
                            "type": "method",
                            "name": "TestClientSession.test_merge_headers_with_multi_dict",
                            "content": "class TestClientSession(unittest.TestCase):\n\n    maxDiff = None\n\n    def setUp(self):\n        self.loop = asyncio.new_event_loop()\n        asyncio.set_event_loop(None)\n        self.run = self.loop.run_until_complete\n\n    def tearDown(self):\n        self.loop.close()\n\n    def make_open_connector(self):\n        conn = BaseConnector(loop=self.loop)\n        transp = unittest.mock.Mock()\n        conn._conns['a'] = [(transp, 'proto', 123)]\n        return conn\n\n    def test_init_headers_simple_dict(self):\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        self.assertEqual(\n            sorted(session._default_headers.items()),\n            ([(\"H1\", \"header1\"),\n              (\"H2\", \"header2\")]))\n        session.close()\n\n    def test_init_headers_list_of_tuples(self):\n        session = ClientSession(\n            headers=[(\"h1\", \"header1\"),\n                     (\"h2\", \"header2\"),\n                     (\"h3\", \"header3\")],\n            loop=self.loop)\n        self.assertEqual(\n            session._default_headers,\n            CIMultiDict([(\"h1\", \"header1\"),\n                         (\"h2\", \"header2\"),\n                         (\"h3\", \"header3\")]))\n        session.close()\n\n    def test_init_headers_MultiDict(self):\n        session = ClientSession(\n            headers=MultiDict(\n                [(\"h1\", \"header1\"),\n                 (\"h2\", \"header2\"),\n                 (\"h3\", \"header3\")]),\n            loop=self.loop)\n        self.assertEqual(\n            session._default_headers,\n            CIMultiDict([(\"H1\", \"header1\"),\n                         (\"H2\", \"header2\"),\n                         (\"H3\", \"header3\")]))\n        session.close()\n\n    def test_init_cookies_with_simple_dict(self):\n        session = ClientSession(\n            cookies={\n                \"c1\": \"cookie1\",\n                \"c2\": \"cookie2\"\n            }, loop=self.loop)\n        self.assertEqual(set(session.cookies), {'c1', 'c2'})\n        self.assertEqual(session.cookies['c1'].value, 'cookie1')\n        self.assertEqual(session.cookies['c2'].value, 'cookie2')\n        session.close()\n\n    def test_init_cookies_with_list_of_tuples(self):\n        session = ClientSession(\n            cookies=[(\"c1\", \"cookie1\"),\n                     (\"c2\", \"cookie2\")],\n            loop=self.loop)\n        self.assertEqual(set(session.cookies), {'c1', 'c2'})\n        self.assertEqual(session.cookies['c1'].value, 'cookie1')\n        self.assertEqual(session.cookies['c2'].value, 'cookie2')\n        session.close()\n\n    def test_merge_headers(self):\n        # Check incoming simple dict\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers({\n            \"h1\": \"h1\"\n        })\n        self.assertIsInstance(headers, CIMultiDict)\n        self.assertEqual(headers, CIMultiDict([\n            (\"h1\", \"h1\"),\n            (\"h2\", \"header2\")\n        ]))\n        session.close()\n\n    def test_merge_headers_with_multi_dict(self):\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers(MultiDict([(\"h1\", \"h1\")]))\n        self.assertIsInstance(headers, CIMultiDict)\n        self.assertEqual(headers, CIMultiDict([\n            (\"h1\", \"h1\"),\n            (\"h2\", \"header2\")\n        ]))\n        session.close()\n\n    def test_merge_headers_with_list_of_tuples(self):\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers([(\"h1\", \"h1\")])\n        self.assertIsInstance(headers, CIMultiDict)\n        self.assertEqual(headers, CIMultiDict([\n            (\"h1\", \"h1\"),\n            (\"h2\", \"header2\")\n        ]))\n        session.close()\n\n    def _make_one(self):\n        session = ClientSession(loop=self.loop)\n        params = 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        return session, params\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_GET(self, patched):\n        session, params = self._make_one()\n        self.run(session.get(\n            \"http://test.example.com\",\n            params={\"x\": 1},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"GET\", \"http://test.example.com\",),\n             dict(\n                 params={\"x\": 1},\n                 allow_redirects=True,\n                 **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_OPTIONS(self, patched):\n        session, params = self._make_one()\n        self.run(session.options(\n            \"http://opt.example.com\",\n            params={\"x\": 2},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"OPTIONS\", \"http://opt.example.com\",),\n             dict(\n                params={\"x\": 2},\n                allow_redirects=True,\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_HEAD(self, patched):\n        session, params = self._make_one()\n        self.run(session.head(\n            \"http://head.example.com\",\n            params={\"x\": 2},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"HEAD\", \"http://head.example.com\",),\n             dict(\n                params={\"x\": 2},\n                allow_redirects=False,\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_POST(self, patched):\n        session, params = self._make_one()\n        self.run(session.post(\n            \"http://post.example.com\",\n            params={\"x\": 2},\n            data=\"Some_data\",\n            files={\"x\": '1'},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"POST\", \"http://post.example.com\",),\n             dict(\n                params={\"x\": 2},\n                data=\"Some_data\",\n                files={\"x\": '1'},\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_PUT(self, patched):\n        session, params = self._make_one()\n        self.run(session.put(\n            \"http://put.example.com\",\n            params={\"x\": 2},\n            data=\"Some_data\",\n            files={\"x\": '1'},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"PUT\", \"http://put.example.com\",),\n             dict(\n                 params={\"x\": 2},\n                 data=\"Some_data\",\n                 files={\"x\": '1'},\n                 **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_PATCH(self, patched):\n        session, params = self._make_one()\n        self.run(session.patch(\n            \"http://patch.example.com\",\n            params={\"x\": 2},\n            data=\"Some_data\",\n            files={\"x\": '1'},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"PATCH\", \"http://patch.example.com\",),\n             dict(\n                params={\"x\": 2},\n                data=\"Some_data\",\n                files={\"x\": '1'},\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_DELETE(self, patched):\n        session, params = self._make_one()\n        self.run(session.delete(\n            \"http://delete.example.com\",\n            params={\"x\": 2},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"DELETE\", \"http://delete.example.com\",),\n             dict(\n                params={\"x\": 2},\n                **params)])\n        session.close()\n\n    def test_close(self):\n        conn = self.make_open_connector()\n        session = ClientSession(loop=self.loop, connector=conn)\n\n        session.close()\n        self.assertIsNone(session.connector)\n        self.assertTrue(conn.closed)\n\n    def test_closed(self):\n        session = ClientSession(loop=self.loop)\n        self.assertFalse(session.closed)\n        session.close()\n        self.assertTrue(session.closed)\n\n    def test_connector(self):\n        connector = TCPConnector(loop=self.loop)\n        session = ClientSession(connector=connector, loop=self.loop)\n        self.assertIs(session.connector, connector)\n        session.close()\n\n    def test_connector_loop(self):\n        loop = asyncio.new_event_loop()\n        connector = TCPConnector(loop=loop)\n        with self.assertRaisesRegex(\n                ValueError,\n                \"loop argument must agree with connector\"):\n            ClientSession(connector=connector, loop=self.loop)\n        connector.close()\n        loop.close()\n\n    def test_cookies_are_readonly(self):\n        session = ClientSession(loop=self.loop)\n        with self.assertRaises(AttributeError):\n            session.cookies = 123\n        session.close()\n\n    def test_detach(self):\n        session = ClientSession(loop=self.loop)\n        conn = session.connector\n        self.assertFalse(conn.closed)\n        session.detach()\n        self.assertIsNone(session.connector)\n        self.assertTrue(session.closed)\n        self.assertFalse(conn.closed)\n        conn.close()\n\n    def test_request_closed_session(self):\n        @asyncio.coroutine\n        def go():\n            session = ClientSession(loop=self.loop)\n            session.close()\n            with self.assertRaises(RuntimeError):\n                yield from session.request('get', '/')\n\n        self.loop.run_until_complete(go())\n\n    def test_close_flag_for_closed_connector(self):\n        session = ClientSession(loop=self.loop)\n        conn = session.connector\n        self.assertFalse(session.closed)\n        conn.close()\n        self.assertTrue(session.closed)\n\n    def test_double_close(self):\n        conn = self.make_open_connector()\n        session = ClientSession(loop=self.loop, connector=conn)\n\n        session.close()\n        self.assertIsNone(session.connector)\n        session.close()\n        self.assertTrue(session.closed)\n        self.assertTrue(conn.closed)\n\n    @unittest.skipUnless(PY_341, \"Requires Python 3.4.1+\")\n    def test_del(self):\n        conn = self.make_open_connector()\n        session = ClientSession(loop=self.loop, connector=conn)\n\n        with self.assertWarns(ResourceWarning):\n            del session\n            gc.collect()\n\n    def test_context_manager(self):\n        conn = self.make_open_connector()\n        with ClientSession(loop=self.loop, connector=conn) as session:\n            pass\n\n        self.assertTrue(session.closed)\n\n    def test_borrow_connector_loop(self):\n        conn = self.make_open_connector()\n        session = ClientSession(connector=conn)\n        self.assertIs(session._loop, self.loop)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 116,
                            "end_lineno": 128,
                            "parent": {
                                "file_name": "tests/test_client_session.py",
                                "type": "class",
                                "name": "TestClientSession",
                                "content": "class TestClientSession(unittest.TestCase):\n\n    maxDiff = None\n\n    def setUp(self):\n        self.loop = asyncio.new_event_loop()\n        asyncio.set_event_loop(None)\n        self.run = self.loop.run_until_complete\n\n    def tearDown(self):\n        self.loop.close()\n\n    def make_open_connector(self):\n        conn = BaseConnector(loop=self.loop)\n        transp = unittest.mock.Mock()\n        conn._conns['a'] = [(transp, 'proto', 123)]\n        return conn\n\n    def test_init_headers_simple_dict(self):\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        self.assertEqual(\n            sorted(session._default_headers.items()),\n            ([(\"H1\", \"header1\"),\n              (\"H2\", \"header2\")]))\n        session.close()\n\n    def test_init_headers_list_of_tuples(self):\n        session = ClientSession(\n            headers=[(\"h1\", \"header1\"),\n                     (\"h2\", \"header2\"),\n                     (\"h3\", \"header3\")],\n            loop=self.loop)\n        self.assertEqual(\n            session._default_headers,\n            CIMultiDict([(\"h1\", \"header1\"),\n                         (\"h2\", \"header2\"),\n                         (\"h3\", \"header3\")]))\n        session.close()\n\n    def test_init_headers_MultiDict(self):\n        session = ClientSession(\n            headers=MultiDict(\n                [(\"h1\", \"header1\"),\n                 (\"h2\", \"header2\"),\n                 (\"h3\", \"header3\")]),\n            loop=self.loop)\n        self.assertEqual(\n            session._default_headers,\n            CIMultiDict([(\"H1\", \"header1\"),\n                         (\"H2\", \"header2\"),\n                         (\"H3\", \"header3\")]))\n        session.close()\n\n    def test_init_cookies_with_simple_dict(self):\n        session = ClientSession(\n            cookies={\n                \"c1\": \"cookie1\",\n                \"c2\": \"cookie2\"\n            }, loop=self.loop)\n        self.assertEqual(set(session.cookies), {'c1', 'c2'})\n        self.assertEqual(session.cookies['c1'].value, 'cookie1')\n        self.assertEqual(session.cookies['c2'].value, 'cookie2')\n        session.close()\n\n    def test_init_cookies_with_list_of_tuples(self):\n        session = ClientSession(\n            cookies=[(\"c1\", \"cookie1\"),\n                     (\"c2\", \"cookie2\")],\n            loop=self.loop)\n        self.assertEqual(set(session.cookies), {'c1', 'c2'})\n        self.assertEqual(session.cookies['c1'].value, 'cookie1')\n        self.assertEqual(session.cookies['c2'].value, 'cookie2')\n        session.close()\n\n    def test_merge_headers(self):\n        # Check incoming simple dict\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers({\n            \"h1\": \"h1\"\n        })\n        self.assertIsInstance(headers, CIMultiDict)\n        self.assertEqual(headers, CIMultiDict([\n            (\"h1\", \"h1\"),\n            (\"h2\", \"header2\")\n        ]))\n        session.close()\n\n    def test_merge_headers_with_multi_dict(self):\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers(MultiDict([(\"h1\", \"h1\")]))\n        self.assertIsInstance(headers, CIMultiDict)\n        self.assertEqual(headers, CIMultiDict([\n            (\"h1\", \"h1\"),\n            (\"h2\", \"header2\")\n        ]))\n        session.close()\n\n    def test_merge_headers_with_list_of_tuples(self):\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers([(\"h1\", \"h1\")])\n        self.assertIsInstance(headers, CIMultiDict)\n        self.assertEqual(headers, CIMultiDict([\n            (\"h1\", \"h1\"),\n            (\"h2\", \"header2\")\n        ]))\n        session.close()\n\n    def _make_one(self):\n        session = ClientSession(loop=self.loop)\n        params = 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        return session, params\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_GET(self, patched):\n        session, params = self._make_one()\n        self.run(session.get(\n            \"http://test.example.com\",\n            params={\"x\": 1},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"GET\", \"http://test.example.com\",),\n             dict(\n                 params={\"x\": 1},\n                 allow_redirects=True,\n                 **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_OPTIONS(self, patched):\n        session, params = self._make_one()\n        self.run(session.options(\n            \"http://opt.example.com\",\n            params={\"x\": 2},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"OPTIONS\", \"http://opt.example.com\",),\n             dict(\n                params={\"x\": 2},\n                allow_redirects=True,\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_HEAD(self, patched):\n        session, params = self._make_one()\n        self.run(session.head(\n            \"http://head.example.com\",\n            params={\"x\": 2},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"HEAD\", \"http://head.example.com\",),\n             dict(\n                params={\"x\": 2},\n                allow_redirects=False,\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_POST(self, patched):\n        session, params = self._make_one()\n        self.run(session.post(\n            \"http://post.example.com\",\n            params={\"x\": 2},\n            data=\"Some_data\",\n            files={\"x\": '1'},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"POST\", \"http://post.example.com\",),\n             dict(\n                params={\"x\": 2},\n                data=\"Some_data\",\n                files={\"x\": '1'},\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_PUT(self, patched):\n        session, params = self._make_one()\n        self.run(session.put(\n            \"http://put.example.com\",\n            params={\"x\": 2},\n            data=\"Some_data\",\n            files={\"x\": '1'},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"PUT\", \"http://put.example.com\",),\n             dict(\n                 params={\"x\": 2},\n                 data=\"Some_data\",\n                 files={\"x\": '1'},\n                 **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_PATCH(self, patched):\n        session, params = self._make_one()\n        self.run(session.patch(\n            \"http://patch.example.com\",\n            params={\"x\": 2},\n            data=\"Some_data\",\n            files={\"x\": '1'},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"PATCH\", \"http://patch.example.com\",),\n             dict(\n                params={\"x\": 2},\n                data=\"Some_data\",\n                files={\"x\": '1'},\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_DELETE(self, patched):\n        session, params = self._make_one()\n        self.run(session.delete(\n            \"http://delete.example.com\",\n            params={\"x\": 2},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"DELETE\", \"http://delete.example.com\",),\n             dict(\n                params={\"x\": 2},\n                **params)])\n        session.close()\n\n    def test_close(self):\n        conn = self.make_open_connector()\n        session = ClientSession(loop=self.loop, connector=conn)\n\n        session.close()\n        self.assertIsNone(session.connector)\n        self.assertTrue(conn.closed)\n\n    def test_closed(self):\n        session = ClientSession(loop=self.loop)\n        self.assertFalse(session.closed)\n        session.close()\n        self.assertTrue(session.closed)\n\n    def test_connector(self):\n        connector = TCPConnector(loop=self.loop)\n        session = ClientSession(connector=connector, loop=self.loop)\n        self.assertIs(session.connector, connector)\n        session.close()\n\n    def test_connector_loop(self):\n        loop = asyncio.new_event_loop()\n        connector = TCPConnector(loop=loop)\n        with self.assertRaisesRegex(\n                ValueError,\n                \"loop argument must agree with connector\"):\n            ClientSession(connector=connector, loop=self.loop)\n        connector.close()\n        loop.close()\n\n    def test_cookies_are_readonly(self):\n        session = ClientSession(loop=self.loop)\n        with self.assertRaises(AttributeError):\n            session.cookies = 123\n        session.close()\n\n    def test_detach(self):\n        session = ClientSession(loop=self.loop)\n        conn = session.connector\n        self.assertFalse(conn.closed)\n        session.detach()\n        self.assertIsNone(session.connector)\n        self.assertTrue(session.closed)\n        self.assertFalse(conn.closed)\n        conn.close()\n\n    def test_request_closed_session(self):\n        @asyncio.coroutine\n        def go():\n            session = ClientSession(loop=self.loop)\n            session.close()\n            with self.assertRaises(RuntimeError):\n                yield from session.request('get', '/')\n\n        self.loop.run_until_complete(go())\n\n    def test_close_flag_for_closed_connector(self):\n        session = ClientSession(loop=self.loop)\n        conn = session.connector\n        self.assertFalse(session.closed)\n        conn.close()\n        self.assertTrue(session.closed)\n\n    def test_double_close(self):\n        conn = self.make_open_connector()\n        session = ClientSession(loop=self.loop, connector=conn)\n\n        session.close()\n        self.assertIsNone(session.connector)\n        session.close()\n        self.assertTrue(session.closed)\n        self.assertTrue(conn.closed)\n\n    @unittest.skipUnless(PY_341, \"Requires Python 3.4.1+\")\n    def test_del(self):\n        conn = self.make_open_connector()\n        session = ClientSession(loop=self.loop, connector=conn)\n\n        with self.assertWarns(ResourceWarning):\n            del session\n            gc.collect()\n\n    def test_context_manager(self):\n        conn = self.make_open_connector()\n        with ClientSession(loop=self.loop, connector=conn) as session:\n            pass\n\n        self.assertTrue(session.closed)\n\n    def test_borrow_connector_loop(self):\n        conn = self.make_open_connector()\n        session = ClientSession(connector=conn)\n        self.assertIs(session._loop, self.loop)",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 21,
                                "end_lineno": 376,
                                "parent": null
                            }
                        },
                        {
                            "file_name": "tests/test_client_session.py",
                            "type": "class",
                            "name": "TestClientSession",
                            "content": "class TestClientSession(unittest.TestCase):\n\n    maxDiff = None\n\n    def setUp(self):\n        self.loop = asyncio.new_event_loop()\n        asyncio.set_event_loop(None)\n        self.run = self.loop.run_until_complete\n\n    def tearDown(self):\n        self.loop.close()\n\n    def make_open_connector(self):\n        conn = BaseConnector(loop=self.loop)\n        transp = unittest.mock.Mock()\n        conn._conns['a'] = [(transp, 'proto', 123)]\n        return conn\n\n    def test_init_headers_simple_dict(self):\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        self.assertEqual(\n            sorted(session._default_headers.items()),\n            ([(\"H1\", \"header1\"),\n              (\"H2\", \"header2\")]))\n        session.close()\n\n    def test_init_headers_list_of_tuples(self):\n        session = ClientSession(\n            headers=[(\"h1\", \"header1\"),\n                     (\"h2\", \"header2\"),\n                     (\"h3\", \"header3\")],\n            loop=self.loop)\n        self.assertEqual(\n            session._default_headers,\n            CIMultiDict([(\"h1\", \"header1\"),\n                         (\"h2\", \"header2\"),\n                         (\"h3\", \"header3\")]))\n        session.close()\n\n    def test_init_headers_MultiDict(self):\n        session = ClientSession(\n            headers=MultiDict(\n                [(\"h1\", \"header1\"),\n                 (\"h2\", \"header2\"),\n                 (\"h3\", \"header3\")]),\n            loop=self.loop)\n        self.assertEqual(\n            session._default_headers,\n            CIMultiDict([(\"H1\", \"header1\"),\n                         (\"H2\", \"header2\"),\n                         (\"H3\", \"header3\")]))\n        session.close()\n\n    def test_init_cookies_with_simple_dict(self):\n        session = ClientSession(\n            cookies={\n                \"c1\": \"cookie1\",\n                \"c2\": \"cookie2\"\n            }, loop=self.loop)\n        self.assertEqual(set(session.cookies), {'c1', 'c2'})\n        self.assertEqual(session.cookies['c1'].value, 'cookie1')\n        self.assertEqual(session.cookies['c2'].value, 'cookie2')\n        session.close()\n\n    def test_init_cookies_with_list_of_tuples(self):\n        session = ClientSession(\n            cookies=[(\"c1\", \"cookie1\"),\n                     (\"c2\", \"cookie2\")],\n            loop=self.loop)\n        self.assertEqual(set(session.cookies), {'c1', 'c2'})\n        self.assertEqual(session.cookies['c1'].value, 'cookie1')\n        self.assertEqual(session.cookies['c2'].value, 'cookie2')\n        session.close()\n\n    def test_merge_headers(self):\n        # Check incoming simple dict\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers({\n            \"h1\": \"h1\"\n        })\n        self.assertIsInstance(headers, CIMultiDict)\n        self.assertEqual(headers, CIMultiDict([\n            (\"h1\", \"h1\"),\n            (\"h2\", \"header2\")\n        ]))\n        session.close()\n\n    def test_merge_headers_with_multi_dict(self):\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers(MultiDict([(\"h1\", \"h1\")]))\n        self.assertIsInstance(headers, CIMultiDict)\n        self.assertEqual(headers, CIMultiDict([\n            (\"h1\", \"h1\"),\n            (\"h2\", \"header2\")\n        ]))\n        session.close()\n\n    def test_merge_headers_with_list_of_tuples(self):\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers([(\"h1\", \"h1\")])\n        self.assertIsInstance(headers, CIMultiDict)\n        self.assertEqual(headers, CIMultiDict([\n            (\"h1\", \"h1\"),\n            (\"h2\", \"header2\")\n        ]))\n        session.close()\n\n    def _make_one(self):\n        session = ClientSession(loop=self.loop)\n        params = 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        return session, params\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_GET(self, patched):\n        session, params = self._make_one()\n        self.run(session.get(\n            \"http://test.example.com\",\n            params={\"x\": 1},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"GET\", \"http://test.example.com\",),\n             dict(\n                 params={\"x\": 1},\n                 allow_redirects=True,\n                 **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_OPTIONS(self, patched):\n        session, params = self._make_one()\n        self.run(session.options(\n            \"http://opt.example.com\",\n            params={\"x\": 2},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"OPTIONS\", \"http://opt.example.com\",),\n             dict(\n                params={\"x\": 2},\n                allow_redirects=True,\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_HEAD(self, patched):\n        session, params = self._make_one()\n        self.run(session.head(\n            \"http://head.example.com\",\n            params={\"x\": 2},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"HEAD\", \"http://head.example.com\",),\n             dict(\n                params={\"x\": 2},\n                allow_redirects=False,\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_POST(self, patched):\n        session, params = self._make_one()\n        self.run(session.post(\n            \"http://post.example.com\",\n            params={\"x\": 2},\n            data=\"Some_data\",\n            files={\"x\": '1'},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"POST\", \"http://post.example.com\",),\n             dict(\n                params={\"x\": 2},\n                data=\"Some_data\",\n                files={\"x\": '1'},\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_PUT(self, patched):\n        session, params = self._make_one()\n        self.run(session.put(\n            \"http://put.example.com\",\n            params={\"x\": 2},\n            data=\"Some_data\",\n            files={\"x\": '1'},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"PUT\", \"http://put.example.com\",),\n             dict(\n                 params={\"x\": 2},\n                 data=\"Some_data\",\n                 files={\"x\": '1'},\n                 **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_PATCH(self, patched):\n        session, params = self._make_one()\n        self.run(session.patch(\n            \"http://patch.example.com\",\n            params={\"x\": 2},\n            data=\"Some_data\",\n            files={\"x\": '1'},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"PATCH\", \"http://patch.example.com\",),\n             dict(\n                params={\"x\": 2},\n                data=\"Some_data\",\n                files={\"x\": '1'},\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_DELETE(self, patched):\n        session, params = self._make_one()\n        self.run(session.delete(\n            \"http://delete.example.com\",\n            params={\"x\": 2},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"DELETE\", \"http://delete.example.com\",),\n             dict(\n                params={\"x\": 2},\n                **params)])\n        session.close()\n\n    def test_close(self):\n        conn = self.make_open_connector()\n        session = ClientSession(loop=self.loop, connector=conn)\n\n        session.close()\n        self.assertIsNone(session.connector)\n        self.assertTrue(conn.closed)\n\n    def test_closed(self):\n        session = ClientSession(loop=self.loop)\n        self.assertFalse(session.closed)\n        session.close()\n        self.assertTrue(session.closed)\n\n    def test_connector(self):\n        connector = TCPConnector(loop=self.loop)\n        session = ClientSession(connector=connector, loop=self.loop)\n        self.assertIs(session.connector, connector)\n        session.close()\n\n    def test_connector_loop(self):\n        loop = asyncio.new_event_loop()\n        connector = TCPConnector(loop=loop)\n        with self.assertRaisesRegex(\n                ValueError,\n                \"loop argument must agree with connector\"):\n            ClientSession(connector=connector, loop=self.loop)\n        connector.close()\n        loop.close()\n\n    def test_cookies_are_readonly(self):\n        session = ClientSession(loop=self.loop)\n        with self.assertRaises(AttributeError):\n            session.cookies = 123\n        session.close()\n\n    def test_detach(self):\n        session = ClientSession(loop=self.loop)\n        conn = session.connector\n        self.assertFalse(conn.closed)\n        session.detach()\n        self.assertIsNone(session.connector)\n        self.assertTrue(session.closed)\n        self.assertFalse(conn.closed)\n        conn.close()\n\n    def test_request_closed_session(self):\n        @asyncio.coroutine\n        def go():\n            session = ClientSession(loop=self.loop)\n            session.close()\n            with self.assertRaises(RuntimeError):\n                yield from session.request('get', '/')\n\n        self.loop.run_until_complete(go())\n\n    def test_close_flag_for_closed_connector(self):\n        session = ClientSession(loop=self.loop)\n        conn = session.connector\n        self.assertFalse(session.closed)\n        conn.close()\n        self.assertTrue(session.closed)\n\n    def test_double_close(self):\n        conn = self.make_open_connector()\n        session = ClientSession(loop=self.loop, connector=conn)\n\n        session.close()\n        self.assertIsNone(session.connector)\n        session.close()\n        self.assertTrue(session.closed)\n        self.assertTrue(conn.closed)\n\n    @unittest.skipUnless(PY_341, \"Requires Python 3.4.1+\")\n    def test_del(self):\n        conn = self.make_open_connector()\n        session = ClientSession(loop=self.loop, connector=conn)\n\n        with self.assertWarns(ResourceWarning):\n            del session\n            gc.collect()\n\n    def test_context_manager(self):\n        conn = self.make_open_connector()\n        with ClientSession(loop=self.loop, connector=conn) as session:\n            pass\n\n        self.assertTrue(session.closed)\n\n    def test_borrow_connector_loop(self):\n        conn = self.make_open_connector()\n        session = ClientSession(connector=conn)\n        self.assertIs(session._loop, self.loop)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 21,
                            "end_lineno": 376,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 136,
                            "length": 8
                        },
                        "new_range": {
                            "start": 136,
                            "length": 8
                        },
                        "section": "class TestClientSession(unittest.TestCase):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        headers = session._prepare_headers([(\"h1\", \"h1\")])",
                                "type": "context"
                            },
                            {
                                "content": "        self.assertIsInstance(headers, CIMultiDict)",
                                "type": "context"
                            },
                            {
                                "content": "        self.assertEqual(headers, CIMultiDict([",
                                "type": "context"
                            },
                            {
                                "content": "            (\"h1\", \"h1\"),",
                                "type": "deleted"
                            },
                            {
                                "content": "            (\"h2\", \"header2\")",
                                "type": "deleted"
                            },
                            {
                                "content": "            (\"h2\", \"header2\"),",
                                "type": "added"
                            },
                            {
                                "content": "            (\"h1\", \"h1\")",
                                "type": "added"
                            },
                            {
                                "content": "        ]))",
                                "type": "context"
                            },
                            {
                                "content": "        session.close()",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "tests/test_client_session.py",
                            "type": "method",
                            "name": "TestClientSession.test_merge_headers_with_list_of_tuples",
                            "content": "class TestClientSession(unittest.TestCase):\n\n    maxDiff = None\n\n    def setUp(self):\n        self.loop = asyncio.new_event_loop()\n        asyncio.set_event_loop(None)\n        self.run = self.loop.run_until_complete\n\n    def tearDown(self):\n        self.loop.close()\n\n    def make_open_connector(self):\n        conn = BaseConnector(loop=self.loop)\n        transp = unittest.mock.Mock()\n        conn._conns['a'] = [(transp, 'proto', 123)]\n        return conn\n\n    def test_init_headers_simple_dict(self):\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        self.assertEqual(\n            sorted(session._default_headers.items()),\n            ([(\"H1\", \"header1\"),\n              (\"H2\", \"header2\")]))\n        session.close()\n\n    def test_init_headers_list_of_tuples(self):\n        session = ClientSession(\n            headers=[(\"h1\", \"header1\"),\n                     (\"h2\", \"header2\"),\n                     (\"h3\", \"header3\")],\n            loop=self.loop)\n        self.assertEqual(\n            session._default_headers,\n            CIMultiDict([(\"h1\", \"header1\"),\n                         (\"h2\", \"header2\"),\n                         (\"h3\", \"header3\")]))\n        session.close()\n\n    def test_init_headers_MultiDict(self):\n        session = ClientSession(\n            headers=MultiDict(\n                [(\"h1\", \"header1\"),\n                 (\"h2\", \"header2\"),\n                 (\"h3\", \"header3\")]),\n            loop=self.loop)\n        self.assertEqual(\n            session._default_headers,\n            CIMultiDict([(\"H1\", \"header1\"),\n                         (\"H2\", \"header2\"),\n                         (\"H3\", \"header3\")]))\n        session.close()\n\n    def test_init_cookies_with_simple_dict(self):\n        session = ClientSession(\n            cookies={\n                \"c1\": \"cookie1\",\n                \"c2\": \"cookie2\"\n            }, loop=self.loop)\n        self.assertEqual(set(session.cookies), {'c1', 'c2'})\n        self.assertEqual(session.cookies['c1'].value, 'cookie1')\n        self.assertEqual(session.cookies['c2'].value, 'cookie2')\n        session.close()\n\n    def test_init_cookies_with_list_of_tuples(self):\n        session = ClientSession(\n            cookies=[(\"c1\", \"cookie1\"),\n                     (\"c2\", \"cookie2\")],\n            loop=self.loop)\n        self.assertEqual(set(session.cookies), {'c1', 'c2'})\n        self.assertEqual(session.cookies['c1'].value, 'cookie1')\n        self.assertEqual(session.cookies['c2'].value, 'cookie2')\n        session.close()\n\n    def test_merge_headers(self):\n        # Check incoming simple dict\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers({\n            \"h1\": \"h1\"\n        })\n        self.assertIsInstance(headers, CIMultiDict)\n        self.assertEqual(headers, CIMultiDict([\n            (\"h1\", \"h1\"),\n            (\"h2\", \"header2\")\n        ]))\n        session.close()\n\n    def test_merge_headers_with_multi_dict(self):\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers(MultiDict([(\"h1\", \"h1\")]))\n        self.assertIsInstance(headers, CIMultiDict)\n        self.assertEqual(headers, CIMultiDict([\n            (\"h1\", \"h1\"),\n            (\"h2\", \"header2\")\n        ]))\n        session.close()\n\n    def test_merge_headers_with_list_of_tuples(self):\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers([(\"h1\", \"h1\")])\n        self.assertIsInstance(headers, CIMultiDict)\n        self.assertEqual(headers, CIMultiDict([\n            (\"h1\", \"h1\"),\n            (\"h2\", \"header2\")\n        ]))\n        session.close()\n\n    def _make_one(self):\n        session = ClientSession(loop=self.loop)\n        params = 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        return session, params\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_GET(self, patched):\n        session, params = self._make_one()\n        self.run(session.get(\n            \"http://test.example.com\",\n            params={\"x\": 1},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"GET\", \"http://test.example.com\",),\n             dict(\n                 params={\"x\": 1},\n                 allow_redirects=True,\n                 **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_OPTIONS(self, patched):\n        session, params = self._make_one()\n        self.run(session.options(\n            \"http://opt.example.com\",\n            params={\"x\": 2},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"OPTIONS\", \"http://opt.example.com\",),\n             dict(\n                params={\"x\": 2},\n                allow_redirects=True,\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_HEAD(self, patched):\n        session, params = self._make_one()\n        self.run(session.head(\n            \"http://head.example.com\",\n            params={\"x\": 2},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"HEAD\", \"http://head.example.com\",),\n             dict(\n                params={\"x\": 2},\n                allow_redirects=False,\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_POST(self, patched):\n        session, params = self._make_one()\n        self.run(session.post(\n            \"http://post.example.com\",\n            params={\"x\": 2},\n            data=\"Some_data\",\n            files={\"x\": '1'},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"POST\", \"http://post.example.com\",),\n             dict(\n                params={\"x\": 2},\n                data=\"Some_data\",\n                files={\"x\": '1'},\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_PUT(self, patched):\n        session, params = self._make_one()\n        self.run(session.put(\n            \"http://put.example.com\",\n            params={\"x\": 2},\n            data=\"Some_data\",\n            files={\"x\": '1'},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"PUT\", \"http://put.example.com\",),\n             dict(\n                 params={\"x\": 2},\n                 data=\"Some_data\",\n                 files={\"x\": '1'},\n                 **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_PATCH(self, patched):\n        session, params = self._make_one()\n        self.run(session.patch(\n            \"http://patch.example.com\",\n            params={\"x\": 2},\n            data=\"Some_data\",\n            files={\"x\": '1'},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"PATCH\", \"http://patch.example.com\",),\n             dict(\n                params={\"x\": 2},\n                data=\"Some_data\",\n                files={\"x\": '1'},\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_DELETE(self, patched):\n        session, params = self._make_one()\n        self.run(session.delete(\n            \"http://delete.example.com\",\n            params={\"x\": 2},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"DELETE\", \"http://delete.example.com\",),\n             dict(\n                params={\"x\": 2},\n                **params)])\n        session.close()\n\n    def test_close(self):\n        conn = self.make_open_connector()\n        session = ClientSession(loop=self.loop, connector=conn)\n\n        session.close()\n        self.assertIsNone(session.connector)\n        self.assertTrue(conn.closed)\n\n    def test_closed(self):\n        session = ClientSession(loop=self.loop)\n        self.assertFalse(session.closed)\n        session.close()\n        self.assertTrue(session.closed)\n\n    def test_connector(self):\n        connector = TCPConnector(loop=self.loop)\n        session = ClientSession(connector=connector, loop=self.loop)\n        self.assertIs(session.connector, connector)\n        session.close()\n\n    def test_connector_loop(self):\n        loop = asyncio.new_event_loop()\n        connector = TCPConnector(loop=loop)\n        with self.assertRaisesRegex(\n                ValueError,\n                \"loop argument must agree with connector\"):\n            ClientSession(connector=connector, loop=self.loop)\n        connector.close()\n        loop.close()\n\n    def test_cookies_are_readonly(self):\n        session = ClientSession(loop=self.loop)\n        with self.assertRaises(AttributeError):\n            session.cookies = 123\n        session.close()\n\n    def test_detach(self):\n        session = ClientSession(loop=self.loop)\n        conn = session.connector\n        self.assertFalse(conn.closed)\n        session.detach()\n        self.assertIsNone(session.connector)\n        self.assertTrue(session.closed)\n        self.assertFalse(conn.closed)\n        conn.close()\n\n    def test_request_closed_session(self):\n        @asyncio.coroutine\n        def go():\n            session = ClientSession(loop=self.loop)\n            session.close()\n            with self.assertRaises(RuntimeError):\n                yield from session.request('get', '/')\n\n        self.loop.run_until_complete(go())\n\n    def test_close_flag_for_closed_connector(self):\n        session = ClientSession(loop=self.loop)\n        conn = session.connector\n        self.assertFalse(session.closed)\n        conn.close()\n        self.assertTrue(session.closed)\n\n    def test_double_close(self):\n        conn = self.make_open_connector()\n        session = ClientSession(loop=self.loop, connector=conn)\n\n        session.close()\n        self.assertIsNone(session.connector)\n        session.close()\n        self.assertTrue(session.closed)\n        self.assertTrue(conn.closed)\n\n    @unittest.skipUnless(PY_341, \"Requires Python 3.4.1+\")\n    def test_del(self):\n        conn = self.make_open_connector()\n        session = ClientSession(loop=self.loop, connector=conn)\n\n        with self.assertWarns(ResourceWarning):\n            del session\n            gc.collect()\n\n    def test_context_manager(self):\n        conn = self.make_open_connector()\n        with ClientSession(loop=self.loop, connector=conn) as session:\n            pass\n\n        self.assertTrue(session.closed)\n\n    def test_borrow_connector_loop(self):\n        conn = self.make_open_connector()\n        session = ClientSession(connector=conn)\n        self.assertIs(session._loop, self.loop)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 130,
                            "end_lineno": 142,
                            "parent": {
                                "file_name": "tests/test_client_session.py",
                                "type": "class",
                                "name": "TestClientSession",
                                "content": "class TestClientSession(unittest.TestCase):\n\n    maxDiff = None\n\n    def setUp(self):\n        self.loop = asyncio.new_event_loop()\n        asyncio.set_event_loop(None)\n        self.run = self.loop.run_until_complete\n\n    def tearDown(self):\n        self.loop.close()\n\n    def make_open_connector(self):\n        conn = BaseConnector(loop=self.loop)\n        transp = unittest.mock.Mock()\n        conn._conns['a'] = [(transp, 'proto', 123)]\n        return conn\n\n    def test_init_headers_simple_dict(self):\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        self.assertEqual(\n            sorted(session._default_headers.items()),\n            ([(\"H1\", \"header1\"),\n              (\"H2\", \"header2\")]))\n        session.close()\n\n    def test_init_headers_list_of_tuples(self):\n        session = ClientSession(\n            headers=[(\"h1\", \"header1\"),\n                     (\"h2\", \"header2\"),\n                     (\"h3\", \"header3\")],\n            loop=self.loop)\n        self.assertEqual(\n            session._default_headers,\n            CIMultiDict([(\"h1\", \"header1\"),\n                         (\"h2\", \"header2\"),\n                         (\"h3\", \"header3\")]))\n        session.close()\n\n    def test_init_headers_MultiDict(self):\n        session = ClientSession(\n            headers=MultiDict(\n                [(\"h1\", \"header1\"),\n                 (\"h2\", \"header2\"),\n                 (\"h3\", \"header3\")]),\n            loop=self.loop)\n        self.assertEqual(\n            session._default_headers,\n            CIMultiDict([(\"H1\", \"header1\"),\n                         (\"H2\", \"header2\"),\n                         (\"H3\", \"header3\")]))\n        session.close()\n\n    def test_init_cookies_with_simple_dict(self):\n        session = ClientSession(\n            cookies={\n                \"c1\": \"cookie1\",\n                \"c2\": \"cookie2\"\n            }, loop=self.loop)\n        self.assertEqual(set(session.cookies), {'c1', 'c2'})\n        self.assertEqual(session.cookies['c1'].value, 'cookie1')\n        self.assertEqual(session.cookies['c2'].value, 'cookie2')\n        session.close()\n\n    def test_init_cookies_with_list_of_tuples(self):\n        session = ClientSession(\n            cookies=[(\"c1\", \"cookie1\"),\n                     (\"c2\", \"cookie2\")],\n            loop=self.loop)\n        self.assertEqual(set(session.cookies), {'c1', 'c2'})\n        self.assertEqual(session.cookies['c1'].value, 'cookie1')\n        self.assertEqual(session.cookies['c2'].value, 'cookie2')\n        session.close()\n\n    def test_merge_headers(self):\n        # Check incoming simple dict\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers({\n            \"h1\": \"h1\"\n        })\n        self.assertIsInstance(headers, CIMultiDict)\n        self.assertEqual(headers, CIMultiDict([\n            (\"h1\", \"h1\"),\n            (\"h2\", \"header2\")\n        ]))\n        session.close()\n\n    def test_merge_headers_with_multi_dict(self):\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers(MultiDict([(\"h1\", \"h1\")]))\n        self.assertIsInstance(headers, CIMultiDict)\n        self.assertEqual(headers, CIMultiDict([\n            (\"h1\", \"h1\"),\n            (\"h2\", \"header2\")\n        ]))\n        session.close()\n\n    def test_merge_headers_with_list_of_tuples(self):\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers([(\"h1\", \"h1\")])\n        self.assertIsInstance(headers, CIMultiDict)\n        self.assertEqual(headers, CIMultiDict([\n            (\"h1\", \"h1\"),\n            (\"h2\", \"header2\")\n        ]))\n        session.close()\n\n    def _make_one(self):\n        session = ClientSession(loop=self.loop)\n        params = 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        return session, params\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_GET(self, patched):\n        session, params = self._make_one()\n        self.run(session.get(\n            \"http://test.example.com\",\n            params={\"x\": 1},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"GET\", \"http://test.example.com\",),\n             dict(\n                 params={\"x\": 1},\n                 allow_redirects=True,\n                 **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_OPTIONS(self, patched):\n        session, params = self._make_one()\n        self.run(session.options(\n            \"http://opt.example.com\",\n            params={\"x\": 2},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"OPTIONS\", \"http://opt.example.com\",),\n             dict(\n                params={\"x\": 2},\n                allow_redirects=True,\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_HEAD(self, patched):\n        session, params = self._make_one()\n        self.run(session.head(\n            \"http://head.example.com\",\n            params={\"x\": 2},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"HEAD\", \"http://head.example.com\",),\n             dict(\n                params={\"x\": 2},\n                allow_redirects=False,\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_POST(self, patched):\n        session, params = self._make_one()\n        self.run(session.post(\n            \"http://post.example.com\",\n            params={\"x\": 2},\n            data=\"Some_data\",\n            files={\"x\": '1'},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"POST\", \"http://post.example.com\",),\n             dict(\n                params={\"x\": 2},\n                data=\"Some_data\",\n                files={\"x\": '1'},\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_PUT(self, patched):\n        session, params = self._make_one()\n        self.run(session.put(\n            \"http://put.example.com\",\n            params={\"x\": 2},\n            data=\"Some_data\",\n            files={\"x\": '1'},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"PUT\", \"http://put.example.com\",),\n             dict(\n                 params={\"x\": 2},\n                 data=\"Some_data\",\n                 files={\"x\": '1'},\n                 **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_PATCH(self, patched):\n        session, params = self._make_one()\n        self.run(session.patch(\n            \"http://patch.example.com\",\n            params={\"x\": 2},\n            data=\"Some_data\",\n            files={\"x\": '1'},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"PATCH\", \"http://patch.example.com\",),\n             dict(\n                params={\"x\": 2},\n                data=\"Some_data\",\n                files={\"x\": '1'},\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_DELETE(self, patched):\n        session, params = self._make_one()\n        self.run(session.delete(\n            \"http://delete.example.com\",\n            params={\"x\": 2},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"DELETE\", \"http://delete.example.com\",),\n             dict(\n                params={\"x\": 2},\n                **params)])\n        session.close()\n\n    def test_close(self):\n        conn = self.make_open_connector()\n        session = ClientSession(loop=self.loop, connector=conn)\n\n        session.close()\n        self.assertIsNone(session.connector)\n        self.assertTrue(conn.closed)\n\n    def test_closed(self):\n        session = ClientSession(loop=self.loop)\n        self.assertFalse(session.closed)\n        session.close()\n        self.assertTrue(session.closed)\n\n    def test_connector(self):\n        connector = TCPConnector(loop=self.loop)\n        session = ClientSession(connector=connector, loop=self.loop)\n        self.assertIs(session.connector, connector)\n        session.close()\n\n    def test_connector_loop(self):\n        loop = asyncio.new_event_loop()\n        connector = TCPConnector(loop=loop)\n        with self.assertRaisesRegex(\n                ValueError,\n                \"loop argument must agree with connector\"):\n            ClientSession(connector=connector, loop=self.loop)\n        connector.close()\n        loop.close()\n\n    def test_cookies_are_readonly(self):\n        session = ClientSession(loop=self.loop)\n        with self.assertRaises(AttributeError):\n            session.cookies = 123\n        session.close()\n\n    def test_detach(self):\n        session = ClientSession(loop=self.loop)\n        conn = session.connector\n        self.assertFalse(conn.closed)\n        session.detach()\n        self.assertIsNone(session.connector)\n        self.assertTrue(session.closed)\n        self.assertFalse(conn.closed)\n        conn.close()\n\n    def test_request_closed_session(self):\n        @asyncio.coroutine\n        def go():\n            session = ClientSession(loop=self.loop)\n            session.close()\n            with self.assertRaises(RuntimeError):\n                yield from session.request('get', '/')\n\n        self.loop.run_until_complete(go())\n\n    def test_close_flag_for_closed_connector(self):\n        session = ClientSession(loop=self.loop)\n        conn = session.connector\n        self.assertFalse(session.closed)\n        conn.close()\n        self.assertTrue(session.closed)\n\n    def test_double_close(self):\n        conn = self.make_open_connector()\n        session = ClientSession(loop=self.loop, connector=conn)\n\n        session.close()\n        self.assertIsNone(session.connector)\n        session.close()\n        self.assertTrue(session.closed)\n        self.assertTrue(conn.closed)\n\n    @unittest.skipUnless(PY_341, \"Requires Python 3.4.1+\")\n    def test_del(self):\n        conn = self.make_open_connector()\n        session = ClientSession(loop=self.loop, connector=conn)\n\n        with self.assertWarns(ResourceWarning):\n            del session\n            gc.collect()\n\n    def test_context_manager(self):\n        conn = self.make_open_connector()\n        with ClientSession(loop=self.loop, connector=conn) as session:\n            pass\n\n        self.assertTrue(session.closed)\n\n    def test_borrow_connector_loop(self):\n        conn = self.make_open_connector()\n        session = ClientSession(connector=conn)\n        self.assertIs(session._loop, self.loop)",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 21,
                                "end_lineno": 376,
                                "parent": null
                            }
                        },
                        {
                            "file_name": "tests/test_client_session.py",
                            "type": "class",
                            "name": "TestClientSession",
                            "content": "class TestClientSession(unittest.TestCase):\n\n    maxDiff = None\n\n    def setUp(self):\n        self.loop = asyncio.new_event_loop()\n        asyncio.set_event_loop(None)\n        self.run = self.loop.run_until_complete\n\n    def tearDown(self):\n        self.loop.close()\n\n    def make_open_connector(self):\n        conn = BaseConnector(loop=self.loop)\n        transp = unittest.mock.Mock()\n        conn._conns['a'] = [(transp, 'proto', 123)]\n        return conn\n\n    def test_init_headers_simple_dict(self):\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        self.assertEqual(\n            sorted(session._default_headers.items()),\n            ([(\"H1\", \"header1\"),\n              (\"H2\", \"header2\")]))\n        session.close()\n\n    def test_init_headers_list_of_tuples(self):\n        session = ClientSession(\n            headers=[(\"h1\", \"header1\"),\n                     (\"h2\", \"header2\"),\n                     (\"h3\", \"header3\")],\n            loop=self.loop)\n        self.assertEqual(\n            session._default_headers,\n            CIMultiDict([(\"h1\", \"header1\"),\n                         (\"h2\", \"header2\"),\n                         (\"h3\", \"header3\")]))\n        session.close()\n\n    def test_init_headers_MultiDict(self):\n        session = ClientSession(\n            headers=MultiDict(\n                [(\"h1\", \"header1\"),\n                 (\"h2\", \"header2\"),\n                 (\"h3\", \"header3\")]),\n            loop=self.loop)\n        self.assertEqual(\n            session._default_headers,\n            CIMultiDict([(\"H1\", \"header1\"),\n                         (\"H2\", \"header2\"),\n                         (\"H3\", \"header3\")]))\n        session.close()\n\n    def test_init_cookies_with_simple_dict(self):\n        session = ClientSession(\n            cookies={\n                \"c1\": \"cookie1\",\n                \"c2\": \"cookie2\"\n            }, loop=self.loop)\n        self.assertEqual(set(session.cookies), {'c1', 'c2'})\n        self.assertEqual(session.cookies['c1'].value, 'cookie1')\n        self.assertEqual(session.cookies['c2'].value, 'cookie2')\n        session.close()\n\n    def test_init_cookies_with_list_of_tuples(self):\n        session = ClientSession(\n            cookies=[(\"c1\", \"cookie1\"),\n                     (\"c2\", \"cookie2\")],\n            loop=self.loop)\n        self.assertEqual(set(session.cookies), {'c1', 'c2'})\n        self.assertEqual(session.cookies['c1'].value, 'cookie1')\n        self.assertEqual(session.cookies['c2'].value, 'cookie2')\n        session.close()\n\n    def test_merge_headers(self):\n        # Check incoming simple dict\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers({\n            \"h1\": \"h1\"\n        })\n        self.assertIsInstance(headers, CIMultiDict)\n        self.assertEqual(headers, CIMultiDict([\n            (\"h1\", \"h1\"),\n            (\"h2\", \"header2\")\n        ]))\n        session.close()\n\n    def test_merge_headers_with_multi_dict(self):\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers(MultiDict([(\"h1\", \"h1\")]))\n        self.assertIsInstance(headers, CIMultiDict)\n        self.assertEqual(headers, CIMultiDict([\n            (\"h1\", \"h1\"),\n            (\"h2\", \"header2\")\n        ]))\n        session.close()\n\n    def test_merge_headers_with_list_of_tuples(self):\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers([(\"h1\", \"h1\")])\n        self.assertIsInstance(headers, CIMultiDict)\n        self.assertEqual(headers, CIMultiDict([\n            (\"h1\", \"h1\"),\n            (\"h2\", \"header2\")\n        ]))\n        session.close()\n\n    def _make_one(self):\n        session = ClientSession(loop=self.loop)\n        params = 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        return session, params\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_GET(self, patched):\n        session, params = self._make_one()\n        self.run(session.get(\n            \"http://test.example.com\",\n            params={\"x\": 1},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"GET\", \"http://test.example.com\",),\n             dict(\n                 params={\"x\": 1},\n                 allow_redirects=True,\n                 **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_OPTIONS(self, patched):\n        session, params = self._make_one()\n        self.run(session.options(\n            \"http://opt.example.com\",\n            params={\"x\": 2},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"OPTIONS\", \"http://opt.example.com\",),\n             dict(\n                params={\"x\": 2},\n                allow_redirects=True,\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_HEAD(self, patched):\n        session, params = self._make_one()\n        self.run(session.head(\n            \"http://head.example.com\",\n            params={\"x\": 2},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"HEAD\", \"http://head.example.com\",),\n             dict(\n                params={\"x\": 2},\n                allow_redirects=False,\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_POST(self, patched):\n        session, params = self._make_one()\n        self.run(session.post(\n            \"http://post.example.com\",\n            params={\"x\": 2},\n            data=\"Some_data\",\n            files={\"x\": '1'},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"POST\", \"http://post.example.com\",),\n             dict(\n                params={\"x\": 2},\n                data=\"Some_data\",\n                files={\"x\": '1'},\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_PUT(self, patched):\n        session, params = self._make_one()\n        self.run(session.put(\n            \"http://put.example.com\",\n            params={\"x\": 2},\n            data=\"Some_data\",\n            files={\"x\": '1'},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"PUT\", \"http://put.example.com\",),\n             dict(\n                 params={\"x\": 2},\n                 data=\"Some_data\",\n                 files={\"x\": '1'},\n                 **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_PATCH(self, patched):\n        session, params = self._make_one()\n        self.run(session.patch(\n            \"http://patch.example.com\",\n            params={\"x\": 2},\n            data=\"Some_data\",\n            files={\"x\": '1'},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"PATCH\", \"http://patch.example.com\",),\n             dict(\n                params={\"x\": 2},\n                data=\"Some_data\",\n                files={\"x\": '1'},\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_DELETE(self, patched):\n        session, params = self._make_one()\n        self.run(session.delete(\n            \"http://delete.example.com\",\n            params={\"x\": 2},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"DELETE\", \"http://delete.example.com\",),\n             dict(\n                params={\"x\": 2},\n                **params)])\n        session.close()\n\n    def test_close(self):\n        conn = self.make_open_connector()\n        session = ClientSession(loop=self.loop, connector=conn)\n\n        session.close()\n        self.assertIsNone(session.connector)\n        self.assertTrue(conn.closed)\n\n    def test_closed(self):\n        session = ClientSession(loop=self.loop)\n        self.assertFalse(session.closed)\n        session.close()\n        self.assertTrue(session.closed)\n\n    def test_connector(self):\n        connector = TCPConnector(loop=self.loop)\n        session = ClientSession(connector=connector, loop=self.loop)\n        self.assertIs(session.connector, connector)\n        session.close()\n\n    def test_connector_loop(self):\n        loop = asyncio.new_event_loop()\n        connector = TCPConnector(loop=loop)\n        with self.assertRaisesRegex(\n                ValueError,\n                \"loop argument must agree with connector\"):\n            ClientSession(connector=connector, loop=self.loop)\n        connector.close()\n        loop.close()\n\n    def test_cookies_are_readonly(self):\n        session = ClientSession(loop=self.loop)\n        with self.assertRaises(AttributeError):\n            session.cookies = 123\n        session.close()\n\n    def test_detach(self):\n        session = ClientSession(loop=self.loop)\n        conn = session.connector\n        self.assertFalse(conn.closed)\n        session.detach()\n        self.assertIsNone(session.connector)\n        self.assertTrue(session.closed)\n        self.assertFalse(conn.closed)\n        conn.close()\n\n    def test_request_closed_session(self):\n        @asyncio.coroutine\n        def go():\n            session = ClientSession(loop=self.loop)\n            session.close()\n            with self.assertRaises(RuntimeError):\n                yield from session.request('get', '/')\n\n        self.loop.run_until_complete(go())\n\n    def test_close_flag_for_closed_connector(self):\n        session = ClientSession(loop=self.loop)\n        conn = session.connector\n        self.assertFalse(session.closed)\n        conn.close()\n        self.assertTrue(session.closed)\n\n    def test_double_close(self):\n        conn = self.make_open_connector()\n        session = ClientSession(loop=self.loop, connector=conn)\n\n        session.close()\n        self.assertIsNone(session.connector)\n        session.close()\n        self.assertTrue(session.closed)\n        self.assertTrue(conn.closed)\n\n    @unittest.skipUnless(PY_341, \"Requires Python 3.4.1+\")\n    def test_del(self):\n        conn = self.make_open_connector()\n        session = ClientSession(loop=self.loop, connector=conn)\n\n        with self.assertWarns(ResourceWarning):\n            del session\n            gc.collect()\n\n    def test_context_manager(self):\n        conn = self.make_open_connector()\n        with ClientSession(loop=self.loop, connector=conn) as session:\n            pass\n\n        self.assertTrue(session.closed)\n\n    def test_borrow_connector_loop(self):\n        conn = self.make_open_connector()\n        session = ClientSession(connector=conn)\n        self.assertIs(session._loop, self.loop)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 21,
                            "end_lineno": 376,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        }
    ],
    "old_commit_hash": "7fa8d945a452fb4ad912589f4ba5bcea13338bcf^",
    "new_commit_hash": "7fa8d945a452fb4ad912589f4ba5bcea13338bcf",
    "commit_message": "Optimize ClientSession headers merging",
    "commit_date": "2015-08-29T09:23:49-04:00",
    "metadata": {}
}
{
    "repo_name": "aiohttp",
    "new_commit_hash": "7fa8d945a452fb4ad912589f4ba5bcea13338bcf",
    "test_file_codes": [
        "# -*- coding: utf-8 -*-\n\"\"\"Tests for aiohttp/client.py\"\"\"\n\nimport asyncio\nimport gc\nimport unittest\nfrom unittest import mock\nimport sys\n\nimport aiohttp\nfrom aiohttp.client import ClientSession\nfrom aiohttp.multidict import MultiDict, CIMultiDict, CIMultiDictProxy\nfrom aiohttp.connector import BaseConnector, TCPConnector\nfrom aiohttp.client_reqrep import ClientRequest, ClientResponse\nfrom http.cookies import SimpleCookie\n\n\nPY_341 = sys.version_info >= (3, 4, 1)\n\n\nclass TestClientSession(unittest.TestCase):\n\n    maxDiff = None\n\n    def setUp(self):\n        self.loop = asyncio.new_event_loop()\n        asyncio.set_event_loop(None)\n        self.run = self.loop.run_until_complete\n\n    def tearDown(self):\n        self.loop.close()\n\n    def make_open_connector(self):\n        conn = BaseConnector(loop=self.loop)\n        transp = unittest.mock.Mock()\n        conn._conns['a'] = [(transp, 'proto', 123)]\n        return conn\n\n    def test_init_headers_simple_dict(self):\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        self.assertEqual(\n            sorted(session._default_headers.items()),\n            ([(\"H1\", \"header1\"),\n              (\"H2\", \"header2\")]))\n        session.close()\n\n    def test_init_headers_list_of_tuples(self):\n        session = ClientSession(\n            headers=[(\"h1\", \"header1\"),\n                     (\"h2\", \"header2\"),\n                     (\"h3\", \"header3\")],\n            loop=self.loop)\n        self.assertEqual(\n            session._default_headers,\n            CIMultiDict([(\"h1\", \"header1\"),\n                         (\"h2\", \"header2\"),\n                         (\"h3\", \"header3\")]))\n        session.close()\n\n    def test_init_headers_MultiDict(self):\n        session = ClientSession(\n            headers=MultiDict(\n                [(\"h1\", \"header1\"),\n                 (\"h2\", \"header2\"),\n                 (\"h3\", \"header3\")]),\n            loop=self.loop)\n        self.assertEqual(\n            session._default_headers,\n            CIMultiDict([(\"H1\", \"header1\"),\n                         (\"H2\", \"header2\"),\n                         (\"H3\", \"header3\")]))\n        session.close()\n\n    def test_init_cookies_with_simple_dict(self):\n        session = ClientSession(\n            cookies={\n                \"c1\": \"cookie1\",\n                \"c2\": \"cookie2\"\n            }, loop=self.loop)\n        self.assertEqual(set(session.cookies), {'c1', 'c2'})\n        self.assertEqual(session.cookies['c1'].value, 'cookie1')\n        self.assertEqual(session.cookies['c2'].value, 'cookie2')\n        session.close()\n\n    def test_init_cookies_with_list_of_tuples(self):\n        session = ClientSession(\n            cookies=[(\"c1\", \"cookie1\"),\n                     (\"c2\", \"cookie2\")],\n            loop=self.loop)\n        self.assertEqual(set(session.cookies), {'c1', 'c2'})\n        self.assertEqual(session.cookies['c1'].value, 'cookie1')\n        self.assertEqual(session.cookies['c2'].value, 'cookie2')\n        session.close()\n\n    def test_merge_headers(self):\n        # Check incoming simple dict\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers({\n            \"h1\": \"h1\"\n        })\n        self.assertIsInstance(headers, CIMultiDict)\n        self.assertEqual(headers, CIMultiDict([\n            (\"h2\", \"header2\"),\n            (\"h1\", \"h1\")\n        ]))\n        session.close()\n\n    def test_merge_headers_with_multi_dict(self):\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers(MultiDict([(\"h1\", \"h1\")]))\n        self.assertIsInstance(headers, CIMultiDict)\n        self.assertEqual(headers, CIMultiDict([\n            (\"h2\", \"header2\"),\n            (\"h1\", \"h1\")\n        ]))\n        session.close()\n\n    def test_merge_headers_with_list_of_tuples(self):\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers([(\"h1\", \"h1\")])\n        self.assertIsInstance(headers, CIMultiDict)\n        self.assertEqual(headers, CIMultiDict([\n            (\"h2\", \"header2\"),\n            (\"h1\", \"h1\")\n        ]))\n        session.close()\n\n    def _make_one(self):\n        session = ClientSession(loop=self.loop)\n        params = 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        return session, params\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_GET(self, patched):\n        session, params = self._make_one()\n        self.run(session.get(\n            \"http://test.example.com\",\n            params={\"x\": 1},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"GET\", \"http://test.example.com\",),\n             dict(\n                 params={\"x\": 1},\n                 allow_redirects=True,\n                 **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_OPTIONS(self, patched):\n        session, params = self._make_one()\n        self.run(session.options(\n            \"http://opt.example.com\",\n            params={\"x\": 2},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"OPTIONS\", \"http://opt.example.com\",),\n             dict(\n                params={\"x\": 2},\n                allow_redirects=True,\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_HEAD(self, patched):\n        session, params = self._make_one()\n        self.run(session.head(\n            \"http://head.example.com\",\n            params={\"x\": 2},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"HEAD\", \"http://head.example.com\",),\n             dict(\n                params={\"x\": 2},\n                allow_redirects=False,\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_POST(self, patched):\n        session, params = self._make_one()\n        self.run(session.post(\n            \"http://post.example.com\",\n            params={\"x\": 2},\n            data=\"Some_data\",\n            files={\"x\": '1'},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"POST\", \"http://post.example.com\",),\n             dict(\n                params={\"x\": 2},\n                data=\"Some_data\",\n                files={\"x\": '1'},\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_PUT(self, patched):\n        session, params = self._make_one()\n        self.run(session.put(\n            \"http://put.example.com\",\n            params={\"x\": 2},\n            data=\"Some_data\",\n            files={\"x\": '1'},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"PUT\", \"http://put.example.com\",),\n             dict(\n                 params={\"x\": 2},\n                 data=\"Some_data\",\n                 files={\"x\": '1'},\n                 **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_PATCH(self, patched):\n        session, params = self._make_one()\n        self.run(session.patch(\n            \"http://patch.example.com\",\n            params={\"x\": 2},\n            data=\"Some_data\",\n            files={\"x\": '1'},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"PATCH\", \"http://patch.example.com\",),\n             dict(\n                params={\"x\": 2},\n                data=\"Some_data\",\n                files={\"x\": '1'},\n                **params)])\n        session.close()\n\n    @mock.patch(\"aiohttp.client.ClientSession.request\")\n    def test_http_DELETE(self, patched):\n        session, params = self._make_one()\n        self.run(session.delete(\n            \"http://delete.example.com\",\n            params={\"x\": 2},\n            **params))\n        self.assertTrue(patched.called, \"`ClientSession.request` not called\")\n        self.assertEqual(\n            list(patched.call_args),\n            [(\"DELETE\", \"http://delete.example.com\",),\n             dict(\n                params={\"x\": 2},\n                **params)])\n        session.close()\n\n    def test_close(self):\n        conn = self.make_open_connector()\n        session = ClientSession(loop=self.loop, connector=conn)\n\n        session.close()\n        self.assertIsNone(session.connector)\n        self.assertTrue(conn.closed)\n\n    def test_closed(self):\n        session = ClientSession(loop=self.loop)\n        self.assertFalse(session.closed)\n        session.close()\n        self.assertTrue(session.closed)\n\n    def test_connector(self):\n        connector = TCPConnector(loop=self.loop)\n        session = ClientSession(connector=connector, loop=self.loop)\n        self.assertIs(session.connector, connector)\n        session.close()\n\n    def test_connector_loop(self):\n        loop = asyncio.new_event_loop()\n        connector = TCPConnector(loop=loop)\n        with self.assertRaisesRegex(\n                ValueError,\n                \"loop argument must agree with connector\"):\n            ClientSession(connector=connector, loop=self.loop)\n        connector.close()\n        loop.close()\n\n    def test_cookies_are_readonly(self):\n        session = ClientSession(loop=self.loop)\n        with self.assertRaises(AttributeError):\n            session.cookies = 123\n        session.close()\n\n    def test_detach(self):\n        session = ClientSession(loop=self.loop)\n        conn = session.connector\n        self.assertFalse(conn.closed)\n        session.detach()\n        self.assertIsNone(session.connector)\n        self.assertTrue(session.closed)\n        self.assertFalse(conn.closed)\n        conn.close()\n\n    def test_request_closed_session(self):\n        @asyncio.coroutine\n        def go():\n            session = ClientSession(loop=self.loop)\n            session.close()\n            with self.assertRaises(RuntimeError):\n                yield from session.request('get', '/')\n\n        self.loop.run_until_complete(go())\n\n    def test_close_flag_for_closed_connector(self):\n        session = ClientSession(loop=self.loop)\n        conn = session.connector\n        self.assertFalse(session.closed)\n        conn.close()\n        self.assertTrue(session.closed)\n\n    def test_double_close(self):\n        conn = self.make_open_connector()\n        session = ClientSession(loop=self.loop, connector=conn)\n\n        session.close()\n        self.assertIsNone(session.connector)\n        session.close()\n        self.assertTrue(session.closed)\n        self.assertTrue(conn.closed)\n\n    @unittest.skipUnless(PY_341, \"Requires Python 3.4.1+\")\n    def test_del(self):\n        conn = self.make_open_connector()\n        session = ClientSession(loop=self.loop, connector=conn)\n\n        with self.assertWarns(ResourceWarning):\n            del session\n            gc.collect()\n\n    def test_context_manager(self):\n        conn = self.make_open_connector()\n        with ClientSession(loop=self.loop, connector=conn) as session:\n            pass\n\n        self.assertTrue(session.closed)\n\n    def test_borrow_connector_loop(self):\n        conn = self.make_open_connector()\n        session = ClientSession(connector=conn)\n        self.assertIs(session._loop, self.loop)\n\n\nclass TestCLientRequest(unittest.TestCase):\n\n    def setUp(self):\n        self.loop = asyncio.new_event_loop()\n        asyncio.set_event_loop(None)\n        self.connector = BaseConnector(loop=self.loop)\n        self.transport = mock.Mock()\n        self.protocol = mock.Mock()\n\n    def tearDown(self):\n        self.loop.close()\n\n    def test_custom_req_rep(self):\n        @asyncio.coroutine\n        def go():\n            class CustomResponse(ClientResponse):\n                @asyncio.coroutine\n                def start(self, connection, read_until_eof=False):\n                    self.status = 123\n                    self.reason = 'Test OK'\n                    self.headers = CIMultiDictProxy(CIMultiDict())\n                    self.cookies = SimpleCookie()\n                    return\n\n            called = False\n\n            class CustomRequest(ClientRequest):\n\n                def send(self, writer, reader):\n                    resp = self.response_class(self.method,\n                                               self.url,\n                                               self.host,\n                                               writer=self._writer,\n                                               continue100=self._continue)\n                    resp._post_init(self.loop)\n                    self.response = resp\n                    nonlocal called\n                    called = True\n                    return resp\n\n            @asyncio.coroutine\n            def create_connection(req):\n                self.assertIsInstance(req, CustomRequest)\n                return self.transport, self.protocol\n            self.connector._create_connection = create_connection\n\n            resp = yield from aiohttp.request('get',\n                                              'http://example.com/path/to',\n                                              request_class=CustomRequest,\n                                              response_class=CustomResponse,\n                                              connector=self.connector,\n                                              loop=self.loop)\n            self.assertIsInstance(resp, CustomResponse)\n            self.assertTrue(called)\n        self.loop.run_until_complete(go())\n"
    ],
    "test_file_names": [
        "test_1.py"
    ],
    "setup_res_code": 0,
    "setup_res_stdout": "Transforming aiohttp/worker.py\nTransforming aiohttp/client_reqrep.py\nTransforming aiohttp/server.py\n",
    "setup_res_stderr": "Using CPython 3.9.21\nCreating virtual environment at: .venv\nActivate with: source .venv/bin/activate\nmake: *** No rule to make target '.develop'.  Stop.\nResolved 26 packages in 38ms\nInstalled 26 packages in 35ms\n + async-generator==1.10\n + async-timeout==5.0.1\n + brotlipy==0.7.0\n + cffi==1.17.1\n + chardet==5.2.0\n + coverage==7.6.10\n + cryptography==44.0.0\n + cython==3.0.11\n + exceptiongroup==1.2.2\n + gunicorn==23.0.0\n + idna==3.10\n + iniconfig==2.0.0\n + multdict==0.0.5\n + multidict==6.1.0\n + packaging==24.2\n + pluggy==1.5.0\n + propcache==0.2.1\n + pycparser==2.22\n + pytest==8.3.4\n + pytest-asyncio==0.25.0\n + pytest-cov==6.0.0\n + pytest-mock==3.14.0\n + tomli==2.2.1\n + trustme==1.2.1\n + typing-extensions==4.12.2\n + yarl==1.18.3\n",
    "new_commit_res_code": 0,
    "new_commit_res_stdout": "============================= test session starts ==============================\nplatform linux -- Python 3.9.21, pytest-8.3.4, pluggy-1.5.0\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_7fa8d945a452fb4ad912589f4ba5bcea13338bcf\nplugins: asyncio-0.25.0, mock-3.14.0, cov-6.0.0\nasyncio: mode=strict, asyncio_default_fixture_loop_scope=None\ncollected 28 items\n\nr2e_tests/test_1.py ............................                         [100%]\n\n==================================== PASSES ====================================\n_________________ TestClientSession.test_borrow_connector_loop _________________\n------------------------------ Captured log call -------------------------------\nERROR    asyncio:base_events.py:1753 Unclosed client session\nclient_session: <aiohttp.client.ClientSession object at 0x713f239b7580>\n__________________________ TestClientSession.test_del __________________________\n------------------------------ Captured log call -------------------------------\nERROR    asyncio:base_events.py:1753 Unclosed client session\nclient_session: <aiohttp.client.ClientSession object at 0x713f239b7280>\n____________________ TestCLientRequest.test_custom_req_rep _____________________\n------------------------------ Captured log call -------------------------------\nERROR    asyncio:base_events.py:1753 Unclosed connection\nclient_connection: <aiohttp.connector.Connection object at 0x713f23e47e80>\nERROR    asyncio:base_events.py:1753 Unclosed response\nclient_response: <ClientResponse(http://example.com/path/to) [123 Test OK]>\n<_CIMultiDictProxy()>\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::TestClientSession::test_borrow_connector_loop\nPASSED r2e_tests/test_1.py::TestClientSession::test_close\nPASSED r2e_tests/test_1.py::TestClientSession::test_close_flag_for_closed_connector\nPASSED r2e_tests/test_1.py::TestClientSession::test_closed\nPASSED r2e_tests/test_1.py::TestClientSession::test_connector\nPASSED r2e_tests/test_1.py::TestClientSession::test_connector_loop\nPASSED r2e_tests/test_1.py::TestClientSession::test_context_manager\nPASSED r2e_tests/test_1.py::TestClientSession::test_cookies_are_readonly\nPASSED r2e_tests/test_1.py::TestClientSession::test_del\nPASSED r2e_tests/test_1.py::TestClientSession::test_detach\nPASSED r2e_tests/test_1.py::TestClientSession::test_double_close\nPASSED r2e_tests/test_1.py::TestClientSession::test_http_DELETE\nPASSED r2e_tests/test_1.py::TestClientSession::test_http_GET\nPASSED r2e_tests/test_1.py::TestClientSession::test_http_HEAD\nPASSED r2e_tests/test_1.py::TestClientSession::test_http_OPTIONS\nPASSED r2e_tests/test_1.py::TestClientSession::test_http_PATCH\nPASSED r2e_tests/test_1.py::TestClientSession::test_http_POST\nPASSED r2e_tests/test_1.py::TestClientSession::test_http_PUT\nPASSED r2e_tests/test_1.py::TestClientSession::test_init_cookies_with_list_of_tuples\nPASSED r2e_tests/test_1.py::TestClientSession::test_init_cookies_with_simple_dict\nPASSED r2e_tests/test_1.py::TestClientSession::test_init_headers_MultiDict\nPASSED r2e_tests/test_1.py::TestClientSession::test_init_headers_list_of_tuples\nPASSED r2e_tests/test_1.py::TestClientSession::test_init_headers_simple_dict\nPASSED r2e_tests/test_1.py::TestClientSession::test_merge_headers\nPASSED r2e_tests/test_1.py::TestClientSession::test_merge_headers_with_list_of_tuples\nPASSED r2e_tests/test_1.py::TestClientSession::test_merge_headers_with_multi_dict\nPASSED r2e_tests/test_1.py::TestClientSession::test_request_closed_session\nPASSED r2e_tests/test_1.py::TestCLientRequest::test_custom_req_rep\n============================== 28 passed in 0.45s ==============================\n",
    "new_commit_res_stderr": "/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_7fa8d945a452fb4ad912589f4ba5bcea13338bcf/.venv/lib/python3.9/site-packages/pytest_asyncio/plugin.py:207: PytestDeprecationWarning: The configuration option \"asyncio_default_fixture_loop_scope\" is unset.\nThe event loop scope for asynchronous fixtures will default to the fixture caching scope. Future versions of pytest-asyncio will default the loop scope for asynchronous fixtures to function scope. Set the default fixture loop scope explicitly in order to avoid unexpected behavior in the future. Valid fixture loop scopes are: \"function\", \"class\", \"module\", \"package\", \"session\"\n\n  warnings.warn(PytestDeprecationWarning(_DEFAULT_FIXTURE_LOOP_SCOPE_UNSET))\n",
    "old_commit_res_code": 1,
    "old_commit_res_stdout": "============================= test session starts ==============================\nplatform linux -- Python 3.9.21, pytest-8.3.4, pluggy-1.5.0\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_7fa8d945a452fb4ad912589f4ba5bcea13338bcf\nplugins: asyncio-0.25.0, mock-3.14.0, cov-6.0.0\nasyncio: mode=strict, asyncio_default_fixture_loop_scope=None\ncollected 28 items\n\nr2e_tests/test_1.py .......................FFF..                         [100%]\n\n=================================== FAILURES ===================================\n_____________________ TestClientSession.test_merge_headers _____________________\n\nself = <r2e_tests.test_1.TestClientSession testMethod=test_merge_headers>\n\n    def test_merge_headers(self):\n        # Check incoming simple dict\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers({\n            \"h1\": \"h1\"\n        })\n        self.assertIsInstance(headers, CIMultiDict)\n>       self.assertEqual(headers, CIMultiDict([\n            (\"h2\", \"header2\"),\n            (\"h1\", \"h1\")\n        ]))\nE       AssertionError: <_CIMultiDict('H1': 'h1', 'H2': 'header2')> != <_CIMultiDict('H2': 'header2', 'H1': 'h1')>\n\nr2e_tests/test_1.py:110: AssertionError\n___________ TestClientSession.test_merge_headers_with_list_of_tuples ___________\n\nself = <r2e_tests.test_1.TestClientSession testMethod=test_merge_headers_with_list_of_tuples>\n\n    def test_merge_headers_with_list_of_tuples(self):\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers([(\"h1\", \"h1\")])\n        self.assertIsInstance(headers, CIMultiDict)\n>       self.assertEqual(headers, CIMultiDict([\n            (\"h2\", \"header2\"),\n            (\"h1\", \"h1\")\n        ]))\nE       AssertionError: <_CIMultiDict('H1': 'h1', 'H2': 'header2')> != <_CIMultiDict('H2': 'header2', 'H1': 'h1')>\n\nr2e_tests/test_1.py:138: AssertionError\n_____________ TestClientSession.test_merge_headers_with_multi_dict _____________\n\nself = <r2e_tests.test_1.TestClientSession testMethod=test_merge_headers_with_multi_dict>\n\n    def test_merge_headers_with_multi_dict(self):\n        session = ClientSession(\n            headers={\n                \"h1\": \"header1\",\n                \"h2\": \"header2\"\n            }, loop=self.loop)\n        headers = session._prepare_headers(MultiDict([(\"h1\", \"h1\")]))\n        self.assertIsInstance(headers, CIMultiDict)\n>       self.assertEqual(headers, CIMultiDict([\n            (\"h2\", \"header2\"),\n            (\"h1\", \"h1\")\n        ]))\nE       AssertionError: <_CIMultiDict('H1': 'h1', 'H2': 'header2')> != <_CIMultiDict('H2': 'header2', 'H1': 'h1')>\n\nr2e_tests/test_1.py:124: AssertionError\n==================================== PASSES ====================================\n_________________ TestClientSession.test_borrow_connector_loop _________________\n------------------------------ Captured log call -------------------------------\nERROR    asyncio:base_events.py:1753 Unclosed client session\nclient_session: <aiohttp.client.ClientSession object at 0x7e1032816ac0>\n__________________________ TestClientSession.test_del __________________________\n------------------------------ Captured log call -------------------------------\nERROR    asyncio:base_events.py:1753 Unclosed client session\nclient_session: <aiohttp.client.ClientSession object at 0x7e1032816e80>\n____________________ TestCLientRequest.test_custom_req_rep _____________________\n------------------------------ Captured log call -------------------------------\nERROR    asyncio:base_events.py:1753 Unclosed connection\nclient_connection: <aiohttp.connector.Connection object at 0x7e10327d8a30>\nERROR    asyncio:base_events.py:1753 Unclosed response\nclient_response: <ClientResponse(http://example.com/path/to) [123 Test OK]>\n<_CIMultiDictProxy()>\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::TestClientSession::test_borrow_connector_loop\nPASSED r2e_tests/test_1.py::TestClientSession::test_close\nPASSED r2e_tests/test_1.py::TestClientSession::test_close_flag_for_closed_connector\nPASSED r2e_tests/test_1.py::TestClientSession::test_closed\nPASSED r2e_tests/test_1.py::TestClientSession::test_connector\nPASSED r2e_tests/test_1.py::TestClientSession::test_connector_loop\nPASSED r2e_tests/test_1.py::TestClientSession::test_context_manager\nPASSED r2e_tests/test_1.py::TestClientSession::test_cookies_are_readonly\nPASSED r2e_tests/test_1.py::TestClientSession::test_del\nPASSED r2e_tests/test_1.py::TestClientSession::test_detach\nPASSED r2e_tests/test_1.py::TestClientSession::test_double_close\nPASSED r2e_tests/test_1.py::TestClientSession::test_http_DELETE\nPASSED r2e_tests/test_1.py::TestClientSession::test_http_GET\nPASSED r2e_tests/test_1.py::TestClientSession::test_http_HEAD\nPASSED r2e_tests/test_1.py::TestClientSession::test_http_OPTIONS\nPASSED r2e_tests/test_1.py::TestClientSession::test_http_PATCH\nPASSED r2e_tests/test_1.py::TestClientSession::test_http_POST\nPASSED r2e_tests/test_1.py::TestClientSession::test_http_PUT\nPASSED r2e_tests/test_1.py::TestClientSession::test_init_cookies_with_list_of_tuples\nPASSED r2e_tests/test_1.py::TestClientSession::test_init_cookies_with_simple_dict\nPASSED r2e_tests/test_1.py::TestClientSession::test_init_headers_MultiDict\nPASSED r2e_tests/test_1.py::TestClientSession::test_init_headers_list_of_tuples\nPASSED r2e_tests/test_1.py::TestClientSession::test_init_headers_simple_dict\nPASSED r2e_tests/test_1.py::TestClientSession::test_request_closed_session\nPASSED r2e_tests/test_1.py::TestCLientRequest::test_custom_req_rep\nFAILED r2e_tests/test_1.py::TestClientSession::test_merge_headers - Assertion...\nFAILED r2e_tests/test_1.py::TestClientSession::test_merge_headers_with_list_of_tuples\nFAILED r2e_tests/test_1.py::TestClientSession::test_merge_headers_with_multi_dict\n========================= 3 failed, 25 passed in 0.24s =========================\n",
    "old_commit_res_stderr": "/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_7fa8d945a452fb4ad912589f4ba5bcea13338bcf/.venv/lib/python3.9/site-packages/pytest_asyncio/plugin.py:207: PytestDeprecationWarning: The configuration option \"asyncio_default_fixture_loop_scope\" is unset.\nThe event loop scope for asynchronous fixtures will default to the fixture caching scope. Future versions of pytest-asyncio will default the loop scope for asynchronous fixtures to function scope. Set the default fixture loop scope explicitly in order to avoid unexpected behavior in the future. Valid fixture loop scopes are: \"function\", \"class\", \"module\", \"package\", \"session\"\n\n  warnings.warn(PytestDeprecationWarning(_DEFAULT_FIXTURE_LOOP_SCOPE_UNSET))\nUnclosed client session\nclient_session: <aiohttp.client.ClientSession object at 0x7e1032b2ae50>\nUnclosed client session\nclient_session: <aiohttp.client.ClientSession object at 0x7e103276de80>\nUnclosed client session\nclient_session: <aiohttp.client.ClientSession object at 0x7e1032c498e0>\n"
}
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]

**Incorrect Capitalization of Header Keys When Merging in ClientSession**

**Description**

When merging default headers with additional headers in the `ClientSession` class, the header keys are being unexpectedly capitalized. This causes discrepancies between the provided headers and the resulting merged headers, leading to failed tests and unintended behavior.

**Example Code**

```python
session = ClientSession(headers={'h1': 'header1', 'h2': 'header2'}, loop=self.loop)
headers = session._prepare_headers({'h1': 'h1'})
print(headers)
```

**Expected Behavior**

The merged headers should retain the original casing of the header keys:

```python
CIMultiDict([
    ('h2', 'header2'),
    ('h1', 'h1')
])
```

**Actual Behavior**

The header keys are being capitalized during the merging process:

```python
CIMultiDict([
    ('H1', 'h1'),
    ('H2', 'header2')
])
```

This unexpected capitalization leads to assertion errors in tests that expect the original header key casing.

[/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 os
import sys
import traceback
import warnings
import http.cookies
import urllib.parse

import aiohttp
from .client_reqrep import ClientRequest, ClientResponse
from .errors import WSServerHandshakeError
from .multidict import MultiDictProxy, MultiDict, CIMultiDict, upstr
from .websocket import WS_KEY, WebSocketParser, WebSocketWriter
from .websocket_client import ClientWebSocketResponse
from . import hdrs


__all__ = ('ClientSession', 'request', 'get', 'options', 'head',
           'delete', 'post', 'put', 'patch')

PY_341 = sys.version_info >= (3, 4, 1)


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

    _source_traceback = None
    _connector = None

    def __init__(self, *, connector=None, loop=None, cookies=None,
                 headers=None, auth=None, request_class=ClientRequest,
                 response_class=ClientResponse,
                 ws_response_class=ClientWebSocketResponse):

        if connector is None:
            connector = aiohttp.TCPConnector(loop=loop)
            loop = connector._loop  # never None
        else:
            if loop is None:
                loop = connector._loop  # never None
            elif connector._loop is not loop:
                raise ValueError("loop argument must agree with connector")

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

        self._cookies = http.cookies.SimpleCookie()

        # For Backward compatability with `share_cookies` connectors
        if connector._share_cookies:
            self._update_cookies(connector.cookies)
        if cookies is not None:
            self._update_cookies(cookies)
        self._connector = connector
        self._default_auth = auth

        # Convert to list of tuples
        if headers:
            headers = CIMultiDict(headers)
        else:
            headers = CIMultiDict()
        self._default_headers = headers

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

    if PY_341:
        def __del__(self):
            if not self.closed:
                self.close()

                warnings.warn("Unclosed client session {!r}".format(self),
                              ResourceWarning)
                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)

    @asyncio.coroutine
    def request(self, method, url, *,
                params=None,
                data=None,
                headers=None,
                files=None,
                auth=None,
                allow_redirects=True,
                max_redirects=10,
                encoding='utf-8',
                version=aiohttp.HttpVersion11,
                compress=None,
                chunked=None,
                expect100=False,
                read_until_eof=True):
        """Perform HTTP request."""

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

        redirects = 0
        if not isinstance(method, upstr):
            method = upstr(method)

        # Merge with default headers and transform to CIMultiDict
        headers = self._prepare_headers(headers)
        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("Can't combine `Authorization` header with "
                             "`auth` argument")

        while True:
            req = self._request_class(
                method, url, params=params, headers=headers, data=data,
                cookies=self.cookies, files=files, encoding=encoding,
                auth=auth, version=version, compress=compress, chunked=chunked,
                expect100=expect100,
                loop=self._loop, response_class=self._response_class)

            conn = yield from self._connector.connect(req)
            try:
                resp = req.send(conn.writer, conn.reader)
                try:
                    yield from resp.start(conn, read_until_eof)
                except:
                    resp.close(force=True)
                    conn.close()
                    raise
            except (aiohttp.HttpProcessingError,
                    aiohttp.ServerDisconnectedError) as exc:
                raise aiohttp.ClientResponseError() from exc
            except OSError as exc:
                raise aiohttp.ClientOSError() from exc

            self._update_cookies(resp.cookies)
            # For Backward compatability with `share_cookie` connectors
            if self._connector._share_cookies:
                self._connector.update_cookies(resp.cookies)

            # redirects
            if resp.status in (301, 302, 303, 307) and allow_redirects:
                redirects += 1
                if max_redirects and redirects >= max_redirects:
                    resp.close(force=True)
                    break

                # For 301 and 302, mimic IE behaviour, now changed in RFC.
                # Details: https://github.com/kennethreitz/requests/pull/269
                if resp.status != 307:
                    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))

                scheme = urllib.parse.urlsplit(r_url)[0]
                if scheme not in ('http', 'https', ''):
                    resp.close(force=True)
                    raise ValueError('Can redirect only to http or https')
                elif not scheme:
                    r_url = urllib.parse.urljoin(url, r_url)

                url = urllib.parse.urldefrag(r_url)[0]
                if url:
                    yield from resp.release()
                    continue

            break

        return resp

    @asyncio.coroutine
    def ws_connect(self, url, *,
                   protocols=(),
                   timeout=10.0,
                   autoclose=True,
                   autoping=True):
        """Initiate websocket connection."""

        sec_key = base64.b64encode(os.urandom(16))

        headers = {
            hdrs.UPGRADE: hdrs.WEBSOCKET,
            hdrs.CONNECTION: hdrs.UPGRADE,
            hdrs.SEC_WEBSOCKET_VERSION: '13',
            hdrs.SEC_WEBSOCKET_KEY: sec_key.decode(),
        }
        if protocols:
            headers[hdrs.SEC_WEBSOCKET_PROTOCOL] = ','.join(protocols)

        # send request
        resp = yield from self.request('get', url, headers=headers,
                                       read_until_eof=False)

        # check handshake
        if resp.status != 101:
            raise WSServerHandshakeError('Invalid response status')

        if resp.headers.get(hdrs.UPGRADE, '').lower() != 'websocket':
            raise WSServerHandshakeError('Invalid upgrade header')

        if resp.headers.get(hdrs.CONNECTION, '').lower() != 'upgrade':
            raise WSServerHandshakeError('Invalid connection header')

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

        # 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

        reader = resp.connection.reader.set_parser(WebSocketParser)
        writer = WebSocketWriter(resp.connection.writer, use_mask=True)

        return self._ws_response_class(reader,
                                       writer,
                                       protocol,
                                       resp,
                                       timeout,
                                       autoclose,
                                       autoping,
                                       self._loop)

    def _update_cookies(self, cookies):
        """Update shared cookies."""
        if isinstance(cookies, dict):
            cookies = cookies.items()

        for name, value in cookies:
            if isinstance(value, http.cookies.Morsel):
                # use dict method because SimpleCookie class modifies value
                # before Python3.4
                dict.__setitem__(self.cookies, name, value)
            else:
                self.cookies[name] = value

    def _prepare_headers(self, headers):
        """ Add default headers and transform it to CIMultiDict
        """
        # Convert headers to MultiDict
        result = CIMultiDict()
        if headers:
            if isinstance(headers, dict):
                headers = headers.items()
            elif isinstance(headers, (MultiDictProxy, MultiDict)):
                headers = headers.items()
            for key, value in headers:
                result.add(key, value)
        # Add defaults only if those are not overridden
        if self._default_headers:
            for key, value in self._default_headers.items():
                if key not in result:
                    result.add(key, value)
        return result

    @asyncio.coroutine
    def get(self, url, *, allow_redirects=True, **kwargs):
        """Perform HTTP GET request."""
        resp = yield from self.request(hdrs.METH_GET, url,
                                       allow_redirects=allow_redirects,
                                       **kwargs)
        return resp

    @asyncio.coroutine
    def options(self, url, *, allow_redirects=True, **kwargs):
        """Perform HTTP OPTIONS request."""
        resp = yield from self.request(hdrs.METH_OPTIONS, url,
                                       allow_redirects=allow_redirects,
                                       **kwargs)
        return resp

    @asyncio.coroutine
    def head(self, url, *, allow_redirects=False, **kwargs):
        """Perform HTTP HEAD request."""
        resp = yield from self.request(hdrs.METH_HEAD, url,
                                       allow_redirects=allow_redirects,
                                       **kwargs)
        return resp

    @asyncio.coroutine
    def post(self, url, *, data=None, **kwargs):
        """Perform HTTP POST request."""
        resp = yield from self.request(hdrs.METH_POST, url,
                                       data=data,
                                       **kwargs)
        return resp

    @asyncio.coroutine
    def put(self, url, *, data=None, **kwargs):
        """Perform HTTP PUT request."""
        resp = yield from self.request(hdrs.METH_PUT, url,
                                       data=data,
                                       **kwargs)
        return resp

    @asyncio.coroutine
    def patch(self, url, *, data=None, **kwargs):
        """Perform HTTP PATCH request."""
        resp = yield from self.request(hdrs.METH_PATCH, url,
                                       data=data,
                                       **kwargs)
        return resp

    @asyncio.coroutine
    def delete(self, url, **kwargs):
        """Perform HTTP DELETE request."""
        resp = yield from self.request(hdrs.METH_DELETE, url,
                                       **kwargs)
        return resp

    def close(self):
        """Close underlying connector.

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

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

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

    @property
    def connector(self):
        """Connector instance used for the session."""
        return self._connector

    @property
    def cookies(self):
        """The session cookies."""
        return self._cookies

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

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

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.close()


@asyncio.coroutine
def request(method, url, *,
            params=None,
            data=None,
            headers=None,
            cookies=None,
            files=None,
            auth=None,
            allow_redirects=True,
            max_redirects=10,
            encoding='utf-8',
            version=aiohttp.HttpVersion11,
            compress=None,
            chunked=None,
            expect100=False,
            connector=None,
            loop=None,
            read_until_eof=True,
            request_class=None,
            response_class=None):
    """Constructs and sends a request. Returns response object.

    :param str method: http method
    :param str url: request url
    :param params: (optional) Dictionary or bytes to be sent in the query
      string of the new request
    :param data: (optional) Dictionary, bytes, or file-like object to
      send in the body of the request
    :param dict headers: (optional) Dictionary of HTTP Headers to send with
      the request
    :param dict cookies: (optional) Dict object to send with the request
    :param auth: (optional) BasicAuth named tuple represent HTTP Basic Auth
    :type auth: aiohttp.helpers.BasicAuth
    :param bool allow_redirects: (optional) If set to False, do not follow
      redirects
    :param version: Request http version.
    :type version: aiohttp.protocol.HttpVersion
    :param bool compress: Set to True if request has to be compressed
       with deflate encoding.
    :param chunked: Set to chunk size for chunked transfer encoding.
    :type chunked: bool or int
    :param bool expect100: Expect 100-continue response from server.
    :param connector: BaseConnector sub-class instance to support
       connection pooling.
    :type connector: aiohttp.connector.BaseConnector
    :param bool read_until_eof: Read response until eof if response
       does not have Content-Length header.
    :param request_class: (optional) Custom Request class implementation.
    :param response_class: (optional) Custom Response class implementation.
    :param loop: Optional event loop.

    Usage::

      >>> import aiohttp
      >>> resp = yield from aiohttp.request('GET', 'http://python.org/')
      >>> resp
      <ClientResponse(python.org/) [200]>
      >>> data = yield from resp.read()

    """
    if connector is None:
        connector = aiohttp.TCPConnector(loop=loop, force_close=True)

    kwargs = {}

    if request_class is not None:
        kwargs['request_class'] = request_class

    if response_class is not None:
        kwargs['response_class'] = response_class

    session = ClientSession(loop=loop,
                            cookies=cookies,
                            connector=connector,
                            **kwargs)
    try:
        resp = yield from session.request(method, url,
                                          params=params,
                                          data=data,
                                          headers=headers,
                                          files=files,
                                          auth=auth,
                                          allow_redirects=allow_redirects,
                                          max_redirects=max_redirects,
                                          encoding=encoding,
                                          version=version,
                                          compress=compress,
                                          chunked=chunked,
                                          expect100=expect100,
                                          read_until_eof=read_until_eof)
        return resp
    finally:
        session.detach()


@asyncio.coroutine
def get(url, **kwargs):
    ret = yield from request(hdrs.METH_GET, url, **kwargs)
    return ret


@asyncio.coroutine
def options(url, **kwargs):
    ret = yield from request(hdrs.METH_OPTIONS, url, **kwargs)
    return ret


@asyncio.coroutine
def head(url, **kwargs):
    ret = yield from request(hdrs.METH_HEAD, url, **kwargs)
    return ret


@asyncio.coroutine
def post(url, **kwargs):
    ret = yield from request(hdrs.METH_POST, url, **kwargs)
    return ret


@asyncio.coroutine
def put(url, **kwargs):
    ret = yield from request(hdrs.METH_PUT, url, **kwargs)
    return ret


@asyncio.coroutine
def patch(url, **kwargs):
    ret = yield from request(hdrs.METH_PATCH, url, **kwargs)
    return ret


@asyncio.coroutine
def delete(url, **kwargs):
    ret = yield from request(hdrs.METH_DELETE, url, **kwargs)
    return ret

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

**Incorrect Capitalization of Header Keys When Merging in ClientSession**

**Description**

When merging default headers with additional headers in the `ClientSession` class, the header keys are being unexpectedly capitalized. This causes discrepancies between the provided headers and the resulting merged headers, leading to failed tests and unintended behavior.

**Example Code**

```python
session = ClientSession(headers={'h1': 'header1', 'h2': 'header2'}, loop=self.loop)
headers = session._prepare_headers({'h1': 'h1'})
print(headers)
```

**Expected Behavior**

The merged headers should retain the original casing of the header keys:

```python
CIMultiDict([
    ('h2', 'header2'),
    ('h1', 'h1')
])
```

**Actual Behavior**

The header keys are being capitalized during the merging process:

```python
CIMultiDict([
    ('H1', 'h1'),
    ('H2', 'header2')
])
```

This unexpected capitalization leads to assertion errors in tests that expect the original header key casing.

[/ISSUE]
{
    "TestClientSession.test_borrow_connector_loop": "PASSED",
    "TestClientSession.test_close": "PASSED",
    "TestClientSession.test_close_flag_for_closed_connector": "PASSED",
    "TestClientSession.test_closed": "PASSED",
    "TestClientSession.test_connector": "PASSED",
    "TestClientSession.test_connector_loop": "PASSED",
    "TestClientSession.test_context_manager": "PASSED",
    "TestClientSession.test_cookies_are_readonly": "PASSED",
    "TestClientSession.test_del": "PASSED",
    "TestClientSession.test_detach": "PASSED",
    "TestClientSession.test_double_close": "PASSED",
    "TestClientSession.test_http_DELETE": "PASSED",
    "TestClientSession.test_http_GET": "PASSED",
    "TestClientSession.test_http_HEAD": "PASSED",
    "TestClientSession.test_http_OPTIONS": "PASSED",
    "TestClientSession.test_http_PATCH": "PASSED",
    "TestClientSession.test_http_POST": "PASSED",
    "TestClientSession.test_http_PUT": "PASSED",
    "TestClientSession.test_init_cookies_with_list_of_tuples": "PASSED",
    "TestClientSession.test_init_cookies_with_simple_dict": "PASSED",
    "TestClientSession.test_init_headers_MultiDict": "PASSED",
    "TestClientSession.test_init_headers_list_of_tuples": "PASSED",
    "TestClientSession.test_init_headers_simple_dict": "PASSED",
    "TestClientSession.test_merge_headers": "PASSED",
    "TestClientSession.test_merge_headers_with_list_of_tuples": "PASSED",
    "TestClientSession.test_merge_headers_with_multi_dict": "PASSED",
    "TestClientSession.test_request_closed_session": "PASSED",
    "TestCLientRequest.test_custom_req_rep": "PASSED"
}
diff --git a/aiohttp/client.py b/aiohttp/client.py
index 9b0b68a1..1f91da54 100644
--- a/aiohttp/client.py
+++ b/aiohttp/client.py
@@ -262,19 +262,17 @@ class ClientSession:
         """ Add default headers and transform it to CIMultiDict
         """
         # Convert headers to MultiDict
-        result = CIMultiDict()
+        result = CIMultiDict(self._default_headers)
         if headers:
-            if isinstance(headers, dict):
-                headers = headers.items()
-            elif isinstance(headers, (MultiDictProxy, MultiDict)):
-                headers = headers.items()
-            for key, value in headers:
-                result.add(key, value)
-        # Add defaults only if those are not overridden
-        if self._default_headers:
-            for key, value in self._default_headers.items():
-                if key not in result:
+            if not isinstance(headers, (MultiDictProxy, MultiDict)):
+                headers = CIMultiDict(headers)
+            added_names = 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
 
     @asyncio.coroutine

{"aiohttp/client.py": "\"\"\"HTTP Client for asyncio.\"\"\"\n\nimport asyncio\nimport base64\nimport hashlib\nimport os\nimport sys\nimport traceback\nimport warnings\nimport http.cookies\nimport urllib.parse\n\nimport aiohttp\nfrom .client_reqrep import ClientRequest, ClientResponse\nfrom .errors import WSServerHandshakeError\nfrom .multidict import MultiDictProxy, MultiDict, CIMultiDict, upstr\nfrom .websocket import WS_KEY, WebSocketParser, WebSocketWriter\nfrom .websocket_client import ClientWebSocketResponse\nfrom . import hdrs\n\n\n__all__ = ('ClientSession', 'request', 'get', 'options', 'head',\n           'delete', 'post', 'put', 'patch')\n\nPY_341 = sys.version_info >= (3, 4, 1)\n\n\nclass ClientSession:\n    \"\"\"First-class interface for making HTTP requests.\"\"\"\n\n    _source_traceback = None\n    _connector = None\n\n    def __init__(self, *, connector=None, loop=None, cookies=None,\n                 headers=None, auth=None, request_class=ClientRequest,\n                 response_class=ClientResponse,\n                 ws_response_class=ClientWebSocketResponse):\n\n        if connector is None:\n            connector = aiohttp.TCPConnector(loop=loop)\n            loop = connector._loop  # never None\n        else:\n            if loop is None:\n                loop = connector._loop  # never None\n            elif connector._loop is not loop:\n                raise ValueError(\"loop argument must agree with connector\")\n\n        self._loop = loop\n        if loop.get_debug():\n            self._source_traceback = traceback.extract_stack(sys._getframe(1))\n\n        self._cookies = http.cookies.SimpleCookie()\n\n        # For Backward compatability with `share_cookies` connectors\n        if connector._share_cookies:\n            self._update_cookies(connector.cookies)\n        if cookies is not None:\n            self._update_cookies(cookies)\n        self._connector = connector\n        self._default_auth = auth\n\n        # Convert to list of tuples\n        if headers:\n            headers = CIMultiDict(headers)\n        else:\n            headers = CIMultiDict()\n        self._default_headers = headers\n\n        self._request_class = request_class\n        self._response_class = response_class\n        self._ws_response_class = ws_response_class\n\n    if PY_341:\n        def __del__(self):\n            if not self.closed:\n                self.close()\n\n                warnings.warn(\"Unclosed client session {!r}\".format(self),\n                              ResourceWarning)\n                context = {'client_session': self,\n                           '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    @asyncio.coroutine\n    def request(self, method, url, *,\n                params=None,\n                data=None,\n                headers=None,\n                files=None,\n                auth=None,\n                allow_redirects=True,\n                max_redirects=10,\n                encoding='utf-8',\n                version=aiohttp.HttpVersion11,\n                compress=None,\n                chunked=None,\n                expect100=False,\n                read_until_eof=True):\n        \"\"\"Perform HTTP request.\"\"\"\n\n        if self.closed:\n            raise RuntimeError('Session is closed')\n\n        redirects = 0\n        if not isinstance(method, upstr):\n            method = upstr(method)\n\n        # Merge with default headers and transform to CIMultiDict\n        headers = self._prepare_headers(headers)\n        if auth is None:\n            auth = self._default_auth\n        # It would be confusing if we support explicit Authorization header\n        # with `auth` argument\n        if (headers is not None and\n                auth is not None and\n                hdrs.AUTHORIZATION in headers):\n            raise ValueError(\"Can't combine `Authorization` header with \"\n                             \"`auth` argument\")\n\n        while True:\n            req = self._request_class(\n                method, url, params=params, headers=headers, data=data,\n                cookies=self.cookies, files=files, encoding=encoding,\n                auth=auth, version=version, compress=compress, chunked=chunked,\n                expect100=expect100,\n                loop=self._loop, response_class=self._response_class)\n\n            conn = yield from self._connector.connect(req)\n            try:\n                resp = req.send(conn.writer, conn.reader)\n                try:\n                    yield from resp.start(conn, read_until_eof)\n                except:\n                    resp.close(force=True)\n                    conn.close()\n                    raise\n            except (aiohttp.HttpProcessingError,\n                    aiohttp.ServerDisconnectedError) as exc:\n                raise aiohttp.ClientResponseError() from exc\n            except OSError as exc:\n                raise aiohttp.ClientOSError() from exc\n\n            self._update_cookies(resp.cookies)\n            # For Backward compatability with `share_cookie` connectors\n            if self._connector._share_cookies:\n                self._connector.update_cookies(resp.cookies)\n\n            # redirects\n            if resp.status in (301, 302, 303, 307) and allow_redirects:\n                redirects += 1\n                if max_redirects and redirects >= max_redirects:\n                    resp.close(force=True)\n                    break\n\n                # For 301 and 302, mimic IE behaviour, now changed in RFC.\n                # Details: https://github.com/kennethreitz/requests/pull/269\n                if resp.status != 307:\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\n                         resp.headers.get(hdrs.URI))\n\n                scheme = urllib.parse.urlsplit(r_url)[0]\n                if scheme not in ('http', 'https', ''):\n                    resp.close(force=True)\n                    raise ValueError('Can redirect only to http or https')\n                elif not scheme:\n                    r_url = urllib.parse.urljoin(url, r_url)\n\n                url = urllib.parse.urldefrag(r_url)[0]\n                if url:\n                    yield from resp.release()\n                    continue\n\n            break\n\n        return resp\n\n    @asyncio.coroutine\n    def ws_connect(self, url, *,\n                   protocols=(),\n                   timeout=10.0,\n                   autoclose=True,\n                   autoping=True):\n        \"\"\"Initiate websocket connection.\"\"\"\n\n        sec_key = base64.b64encode(os.urandom(16))\n\n        headers = {\n            hdrs.UPGRADE: hdrs.WEBSOCKET,\n            hdrs.CONNECTION: hdrs.UPGRADE,\n            hdrs.SEC_WEBSOCKET_VERSION: '13',\n            hdrs.SEC_WEBSOCKET_KEY: sec_key.decode(),\n        }\n        if protocols:\n            headers[hdrs.SEC_WEBSOCKET_PROTOCOL] = ','.join(protocols)\n\n        # send request\n        resp = yield from self.request('get', url, headers=headers,\n                                       read_until_eof=False)\n\n        # check handshake\n        if resp.status != 101:\n            raise WSServerHandshakeError('Invalid response status')\n\n        if resp.headers.get(hdrs.UPGRADE, '').lower() != 'websocket':\n            raise WSServerHandshakeError('Invalid upgrade header')\n\n        if resp.headers.get(hdrs.CONNECTION, '').lower() != 'upgrade':\n            raise WSServerHandshakeError('Invalid connection header')\n\n        # key calculation\n        key = resp.headers.get(hdrs.SEC_WEBSOCKET_ACCEPT, '')\n        match = base64.b64encode(\n            hashlib.sha1(sec_key + WS_KEY).digest()).decode()\n        if key != match:\n            raise WSServerHandshakeError('Invalid challenge response')\n\n        # websocket protocol\n        protocol = None\n        if protocols and hdrs.SEC_WEBSOCKET_PROTOCOL in resp.headers:\n            resp_protocols = [\n                proto.strip() for proto in\n                resp.headers[hdrs.SEC_WEBSOCKET_PROTOCOL].split(',')]\n\n            for proto in resp_protocols:\n                if proto in protocols:\n                    protocol = proto\n                    break\n\n        reader = resp.connection.reader.set_parser(WebSocketParser)\n        writer = WebSocketWriter(resp.connection.writer, use_mask=True)\n\n        return self._ws_response_class(reader,\n                                       writer,\n                                       protocol,\n                                       resp,\n                                       timeout,\n                                       autoclose,\n                                       autoping,\n                                       self._loop)\n\n    def _update_cookies(self, cookies):\n        \"\"\"Update shared cookies.\"\"\"\n        if isinstance(cookies, dict):\n            cookies = cookies.items()\n\n        for name, value in cookies:\n            if isinstance(value, http.cookies.Morsel):\n                # use dict method because SimpleCookie class modifies value\n                # before Python3.4\n                dict.__setitem__(self.cookies, name, value)\n            else:\n                self.cookies[name] = value\n\n    def _prepare_headers(self, headers):\n        \"\"\" Add default headers and transform it to CIMultiDict\n        \"\"\"\n        # Convert headers to MultiDict\n        result = CIMultiDict()\n        if headers:\n            if isinstance(headers, dict):\n                headers = headers.items()\n            elif isinstance(headers, (MultiDictProxy, MultiDict)):\n                headers = headers.items()\n            for key, value in headers:\n                result.add(key, value)\n        # Add defaults only if those are not overridden\n        if self._default_headers:\n            for key, value in self._default_headers.items():\n                if key not in result:\n                    result.add(key, value)\n        return result\n\n    @asyncio.coroutine\n    def get(self, url, *, allow_redirects=True, **kwargs):\n        \"\"\"Perform HTTP GET request.\"\"\"\n        resp = yield from self.request(hdrs.METH_GET, url,\n                                       allow_redirects=allow_redirects,\n                                       **kwargs)\n        return resp\n\n    @asyncio.coroutine\n    def options(self, url, *, allow_redirects=True, **kwargs):\n        \"\"\"Perform HTTP OPTIONS request.\"\"\"\n        resp = yield from self.request(hdrs.METH_OPTIONS, url,\n                                       allow_redirects=allow_redirects,\n                                       **kwargs)\n        return resp\n\n    @asyncio.coroutine\n    def head(self, url, *, allow_redirects=False, **kwargs):\n        \"\"\"Perform HTTP HEAD request.\"\"\"\n        resp = yield from self.request(hdrs.METH_HEAD, url,\n                                       allow_redirects=allow_redirects,\n                                       **kwargs)\n        return resp\n\n    @asyncio.coroutine\n    def post(self, url, *, data=None, **kwargs):\n        \"\"\"Perform HTTP POST request.\"\"\"\n        resp = yield from self.request(hdrs.METH_POST, url,\n                                       data=data,\n                                       **kwargs)\n        return resp\n\n    @asyncio.coroutine\n    def put(self, url, *, data=None, **kwargs):\n        \"\"\"Perform HTTP PUT request.\"\"\"\n        resp = yield from self.request(hdrs.METH_PUT, url,\n                                       data=data,\n                                       **kwargs)\n        return resp\n\n    @asyncio.coroutine\n    def patch(self, url, *, data=None, **kwargs):\n        \"\"\"Perform HTTP PATCH request.\"\"\"\n        resp = yield from self.request(hdrs.METH_PATCH, url,\n                                       data=data,\n                                       **kwargs)\n        return resp\n\n    @asyncio.coroutine\n    def delete(self, url, **kwargs):\n        \"\"\"Perform HTTP DELETE request.\"\"\"\n        resp = yield from self.request(hdrs.METH_DELETE, url,\n                                       **kwargs)\n        return resp\n\n    def close(self):\n        \"\"\"Close underlying connector.\n\n        Release all acquired resources.\n        \"\"\"\n        if not self.closed:\n            self._connector.close()\n            self._connector = None\n\n    @property\n    def closed(self):\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):\n        \"\"\"Connector instance used for the session.\"\"\"\n        return self._connector\n\n    @property\n    def cookies(self):\n        \"\"\"The session cookies.\"\"\"\n        return self._cookies\n\n    def detach(self):\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):\n        return self\n\n    def __exit__(self, exc_type, exc_val, exc_tb):\n        self.close()\n\n\n@asyncio.coroutine\ndef request(method, url, *,\n            params=None,\n            data=None,\n            headers=None,\n            cookies=None,\n            files=None,\n            auth=None,\n            allow_redirects=True,\n            max_redirects=10,\n            encoding='utf-8',\n            version=aiohttp.HttpVersion11,\n            compress=None,\n            chunked=None,\n            expect100=False,\n            connector=None,\n            loop=None,\n            read_until_eof=True,\n            request_class=None,\n            response_class=None):\n    \"\"\"Constructs and sends a request. Returns response object.\n\n    :param str method: http method\n    :param str url: request url\n    :param params: (optional) Dictionary or bytes to be sent in the query\n      string of the new request\n    :param data: (optional) Dictionary, bytes, or file-like object to\n      send in the body of the request\n    :param dict headers: (optional) Dictionary of HTTP Headers to send with\n      the request\n    :param dict cookies: (optional) Dict object to send with the request\n    :param auth: (optional) BasicAuth named tuple represent HTTP Basic Auth\n    :type auth: aiohttp.helpers.BasicAuth\n    :param bool allow_redirects: (optional) If set to False, do not follow\n      redirects\n    :param version: Request http version.\n    :type version: aiohttp.protocol.HttpVersion\n    :param bool compress: Set to True if request has to be compressed\n       with deflate encoding.\n    :param chunked: Set to chunk size for chunked transfer encoding.\n    :type chunked: bool or int\n    :param bool expect100: Expect 100-continue response from server.\n    :param connector: BaseConnector sub-class instance to support\n       connection pooling.\n    :type connector: aiohttp.connector.BaseConnector\n    :param bool read_until_eof: Read response until eof if response\n       does not have Content-Length header.\n    :param request_class: (optional) Custom Request class implementation.\n    :param response_class: (optional) Custom Response class implementation.\n    :param loop: Optional event loop.\n\n    Usage::\n\n      >>> import aiohttp\n      >>> resp = yield from aiohttp.request('GET', 'http://python.org/')\n      >>> resp\n      <ClientResponse(python.org/) [200]>\n      >>> data = yield from resp.read()\n\n    \"\"\"\n    if connector is None:\n        connector = aiohttp.TCPConnector(loop=loop, force_close=True)\n\n    kwargs = {}\n\n    if request_class is not None:\n        kwargs['request_class'] = request_class\n\n    if response_class is not None:\n        kwargs['response_class'] = response_class\n\n    session = ClientSession(loop=loop,\n                            cookies=cookies,\n                            connector=connector,\n                            **kwargs)\n    try:\n        resp = yield from session.request(method, url,\n                                          params=params,\n                                          data=data,\n                                          headers=headers,\n                                          files=files,\n                                          auth=auth,\n                                          allow_redirects=allow_redirects,\n                                          max_redirects=max_redirects,\n                                          encoding=encoding,\n                                          version=version,\n                                          compress=compress,\n                                          chunked=chunked,\n                                          expect100=expect100,\n                                          read_until_eof=read_until_eof)\n        return resp\n    finally:\n        session.detach()\n\n\n@asyncio.coroutine\ndef get(url, **kwargs):\n    ret = yield from request(hdrs.METH_GET, url, **kwargs)\n    return ret\n\n\n@asyncio.coroutine\ndef options(url, **kwargs):\n    ret = yield from request(hdrs.METH_OPTIONS, url, **kwargs)\n    return ret\n\n\n@asyncio.coroutine\ndef head(url, **kwargs):\n    ret = yield from request(hdrs.METH_HEAD, url, **kwargs)\n    return ret\n\n\n@asyncio.coroutine\ndef post(url, **kwargs):\n    ret = yield from request(hdrs.METH_POST, url, **kwargs)\n    return ret\n\n\n@asyncio.coroutine\ndef put(url, **kwargs):\n    ret = yield from request(hdrs.METH_PUT, url, **kwargs)\n    return ret\n\n\n@asyncio.coroutine\ndef patch(url, **kwargs):\n    ret = yield from request(hdrs.METH_PATCH, url, **kwargs)\n    return ret\n\n\n@asyncio.coroutine\ndef delete(url, **kwargs):\n    ret = yield from request(hdrs.METH_DELETE, url, **kwargs)\n    return ret\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]

**Incorrect Capitalization of Header Keys When Merging in ClientSession**

**Description**

When merging default headers with additional headers in the `ClientSession` class, the header keys are being unexpectedly capitalized. This causes discrepancies between the provided headers and the resulting merged headers, leading to failed tests and unintended behavior.

**Example Code**

```python
session = ClientSession(headers={'h1': 'header1', 'h2': 'header2'}, loop=self.loop)
headers = session._prepare_headers({'h1': 'h1'})
print(headers)
```

**Expected Behavior**

The merged headers should retain the original casing of the header keys:

```python
CIMultiDict([
    ('h2', 'header2'),
    ('h1', 'h1')
])
```

**Actual Behavior**

The header keys are being capitalized during the merging process:

```python
CIMultiDict([
    ('H1', 'h1'),
    ('H2', 'header2')
])
```

This unexpected capitalization leads to assertion errors in tests that expect the original header key casing.

[/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 os
import sys
import traceback
import warnings
import http.cookies
import urllib.parse

import aiohttp
from .client_reqrep import ClientRequest, ClientResponse
from .errors import WSServerHandshakeError
from .multidict import MultiDictProxy, MultiDict, CIMultiDict, upstr
from .websocket import WS_KEY, WebSocketParser, WebSocketWriter
from .websocket_client import ClientWebSocketResponse
from . import hdrs


__all__ = ('ClientSession', 'request', 'get', 'options', 'head',
           'delete', 'post', 'put', 'patch')

PY_341 = sys.version_info >= (3, 4, 1)


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

    _source_traceback = None
    _connector = None

    def __init__(self, *, connector=None, loop=None, cookies=None,
                 headers=None, auth=None, request_class=ClientRequest,
                 response_class=ClientResponse,
                 ws_response_class=ClientWebSocketResponse):

        if connector is None:
            connector = aiohttp.TCPConnector(loop=loop)
            loop = connector._loop  # never None
        else:
            if loop is None:
                loop = connector._loop  # never None
            elif connector._loop is not loop:
                raise ValueError("loop argument must agree with connector")

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

        self._cookies = http.cookies.SimpleCookie()

        # For Backward compatability with `share_cookies` connectors
        if connector._share_cookies:
            self._update_cookies(connector.cookies)
        if cookies is not None:
            self._update_cookies(cookies)
        self._connector = connector
        self._default_auth = auth

        # Convert to list of tuples
        if headers:
            headers = CIMultiDict(headers)
        else:
            headers = CIMultiDict()
        self._default_headers = headers

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

    if PY_341:
        def __del__(self):
            if not self.closed:
                self.close()

                warnings.warn("Unclosed client session {!r}".format(self),
                              ResourceWarning)
                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)

    @asyncio.coroutine
    def request(self, method, url, *,
                params=None,
                data=None,
                headers=None,
                files=None,
                auth=None,
                allow_redirects=True,
                max_redirects=10,
                encoding='utf-8',
                version=aiohttp.HttpVersion11,
                compress=None,
                chunked=None,
                expect100=False,
                read_until_eof=True):
        """Perform HTTP request."""

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

        redirects = 0
        if not isinstance(method, upstr):
            method = upstr(method)

        # Merge with default headers and transform to CIMultiDict
        headers = self._prepare_headers(headers)
        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("Can't combine `Authorization` header with "
                             "`auth` argument")

        while True:
            req = self._request_class(
                method, url, params=params, headers=headers, data=data,
                cookies=self.cookies, files=files, encoding=encoding,
                auth=auth, version=version, compress=compress, chunked=chunked,
                expect100=expect100,
                loop=self._loop, response_class=self._response_class)

            conn = yield from self._connector.connect(req)
            try:
                resp = req.send(conn.writer, conn.reader)
                try:
                    yield from resp.start(conn, read_until_eof)
                except:
                    resp.close(force=True)
                    conn.close()
                    raise
            except (aiohttp.HttpProcessingError,
                    aiohttp.ServerDisconnectedError) as exc:
                raise aiohttp.ClientResponseError() from exc
            except OSError as exc:
                raise aiohttp.ClientOSError() from exc

            self._update_cookies(resp.cookies)
            # For Backward compatability with `share_cookie` connectors
            if self._connector._share_cookies:
                self._connector.update_cookies(resp.cookies)

            # redirects
            if resp.status in (301, 302, 303, 307) and allow_redirects:
                redirects += 1
                if max_redirects and redirects >= max_redirects:
                    resp.close(force=True)
                    break

                # For 301 and 302, mimic IE behaviour, now changed in RFC.
                # Details: https://github.com/kennethreitz/requests/pull/269
                if resp.status != 307:
                    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))

                scheme = urllib.parse.urlsplit(r_url)[0]
                if scheme not in ('http', 'https', ''):
                    resp.close(force=True)
                    raise ValueError('Can redirect only to http or https')
                elif not scheme:
                    r_url = urllib.parse.urljoin(url, r_url)

                url = urllib.parse.urldefrag(r_url)[0]
                if url:
                    yield from resp.release()
                    continue

            break

        return resp

    @asyncio.coroutine
    def ws_connect(self, url, *,
                   protocols=(),
                   timeout=10.0,
                   autoclose=True,
                   autoping=True):
        """Initiate websocket connection."""

        sec_key = base64.b64encode(os.urandom(16))

        headers = {
            hdrs.UPGRADE: hdrs.WEBSOCKET,
            hdrs.CONNECTION: hdrs.UPGRADE,
            hdrs.SEC_WEBSOCKET_VERSION: '13',
            hdrs.SEC_WEBSOCKET_KEY: sec_key.decode(),
        }
        if protocols:
            headers[hdrs.SEC_WEBSOCKET_PROTOCOL] = ','.join(protocols)

        # send request
        resp = yield from self.request('get', url, headers=headers,
                                       read_until_eof=False)

        # check handshake
        if resp.status != 101:
            raise WSServerHandshakeError('Invalid response status')

        if resp.headers.get(hdrs.UPGRADE, '').lower() != 'websocket':
            raise WSServerHandshakeError('Invalid upgrade header')

        if resp.headers.get(hdrs.CONNECTION, '').lower() != 'upgrade':
            raise WSServerHandshakeError('Invalid connection header')

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

        # 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

        reader = resp.connection.reader.set_parser(WebSocketParser)
        writer = WebSocketWriter(resp.connection.writer, use_mask=True)

        return self._ws_response_class(reader,
                                       writer,
                                       protocol,
                                       resp,
                                       timeout,
                                       autoclose,
                                       autoping,
                                       self._loop)

    def _update_cookies(self, cookies):
        """Update shared cookies."""
        if isinstance(cookies, dict):
            cookies = cookies.items()

        for name, value in cookies:
            if isinstance(value, http.cookies.Morsel):
                # use dict method because SimpleCookie class modifies value
                # before Python3.4
                dict.__setitem__(self.cookies, name, value)
            else:
                self.cookies[name] = value

    def _prepare_headers(self, headers):
        """ Add default headers and transform it to CIMultiDict
        """
        # Convert headers to MultiDict
        result = CIMultiDict()
        if headers:
            if isinstance(headers, dict):
                headers = headers.items()
            elif isinstance(headers, (MultiDictProxy, MultiDict)):
                headers = headers.items()
            for key, value in headers:
                result.add(key, value)
        # Add defaults only if those are not overridden
        if self._default_headers:
            for key, value in self._default_headers.items():
                if key not in result:
                    result.add(key, value)
        return result

    @asyncio.coroutine
    def get(self, url, *, allow_redirects=True, **kwargs):
        """Perform HTTP GET request."""
        resp = yield from self.request(hdrs.METH_GET, url,
                                       allow_redirects=allow_redirects,
                                       **kwargs)
        return resp

    @asyncio.coroutine
    def options(self, url, *, allow_redirects=True, **kwargs):
        """Perform HTTP OPTIONS request."""
        resp = yield from self.request(hdrs.METH_OPTIONS, url,
                                       allow_redirects=allow_redirects,
                                       **kwargs)
        return resp

    @asyncio.coroutine
    def head(self, url, *, allow_redirects=False, **kwargs):
        """Perform HTTP HEAD request."""
        resp = yield from self.request(hdrs.METH_HEAD, url,
                                       allow_redirects=allow_redirects,
                                       **kwargs)
        return resp

    @asyncio.coroutine
    def post(self, url, *, data=None, **kwargs):
        """Perform HTTP POST request."""
        resp = yield from self.request(hdrs.METH_POST, url,
                                       data=data,
                                       **kwargs)
        return resp

    @asyncio.coroutine
    def put(self, url, *, data=None, **kwargs):
        """Perform HTTP PUT request."""
        resp = yield from self.request(hdrs.METH_PUT, url,
                                       data=data,
                                       **kwargs)
        return resp

    @asyncio.coroutine
    def patch(self, url, *, data=None, **kwargs):
        """Perform HTTP PATCH request."""
        resp = yield from self.request(hdrs.METH_PATCH, url,
                                       data=data,
                                       **kwargs)
        return resp

    @asyncio.coroutine
    def delete(self, url, **kwargs):
        """Perform HTTP DELETE request."""
        resp = yield from self.request(hdrs.METH_DELETE, url,
                                       **kwargs)
        return resp

    def close(self):
        """Close underlying connector.

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

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

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

    @property
    def connector(self):
        """Connector instance used for the session."""
        return self._connector

    @property
    def cookies(self):
        """The session cookies."""
        return self._cookies

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

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

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.close()


@asyncio.coroutine
def request(method, url, *,
            params=None,
            data=None,
            headers=None,
            cookies=None,
            files=None,
            auth=None,
            allow_redirects=True,
            max_redirects=10,
            encoding='utf-8',
            version=aiohttp.HttpVersion11,
            compress=None,
            chunked=None,
            expect100=False,
            connector=None,
            loop=None,
            read_until_eof=True,
            request_class=None,
            response_class=None):
    """Constructs and sends a request. Returns response object.

    :param str method: http method
    :param str url: request url
    :param params: (optional) Dictionary or bytes to be sent in the query
      string of the new request
    :param data: (optional) Dictionary, bytes, or file-like object to
      send in the body of the request
    :param dict headers: (optional) Dictionary of HTTP Headers to send with
      the request
    :param dict cookies: (optional) Dict object to send with the request
    :param auth: (optional) BasicAuth named tuple represent HTTP Basic Auth
    :type auth: aiohttp.helpers.BasicAuth
    :param bool allow_redirects: (optional) If set to False, do not follow
      redirects
    :param version: Request http version.
    :type version: aiohttp.protocol.HttpVersion
    :param bool compress: Set to True if request has to be compressed
       with deflate encoding.
    :param chunked: Set to chunk size for chunked transfer encoding.
    :type chunked: bool or int
    :param bool expect100: Expect 100-continue response from server.
    :param connector: BaseConnector sub-class instance to support
       connection pooling.
    :type connector: aiohttp.connector.BaseConnector
    :param bool read_until_eof: Read response until eof if response
       does not have Content-Length header.
    :param request_class: (optional) Custom Request class implementation.
    :param response_class: (optional) Custom Response class implementation.
    :param loop: Optional event loop.

    Usage::

      >>> import aiohttp
      >>> resp = yield from aiohttp.request('GET', 'http://python.org/')
      >>> resp
      <ClientResponse(python.org/) [200]>
      >>> data = yield from resp.read()

    """
    if connector is None:
        connector = aiohttp.TCPConnector(loop=loop, force_close=True)

    kwargs = {}

    if request_class is not None:
        kwargs['request_class'] = request_class

    if response_class is not None:
        kwargs['response_class'] = response_class

    session = ClientSession(loop=loop,
                            cookies=cookies,
                            connector=connector,
                            **kwargs)
    try:
        resp = yield from session.request(method, url,
                                          params=params,
                                          data=data,
                                          headers=headers,
                                          files=files,
                                          auth=auth,
                                          allow_redirects=allow_redirects,
                                          max_redirects=max_redirects,
                                          encoding=encoding,
                                          version=version,
                                          compress=compress,
                                          chunked=chunked,
                                          expect100=expect100,
                                          read_until_eof=read_until_eof)
        return resp
    finally:
        session.detach()


@asyncio.coroutine
def get(url, **kwargs):
    ret = yield from request(hdrs.METH_GET, url, **kwargs)
    return ret


@asyncio.coroutine
def options(url, **kwargs):
    ret = yield from request(hdrs.METH_OPTIONS, url, **kwargs)
    return ret


@asyncio.coroutine
def head(url, **kwargs):
    ret = yield from request(hdrs.METH_HEAD, url, **kwargs)
    return ret


@asyncio.coroutine
def post(url, **kwargs):
    ret = yield from request(hdrs.METH_POST, url, **kwargs)
    return ret


@asyncio.coroutine
def put(url, **kwargs):
    ret = yield from request(hdrs.METH_PUT, url, **kwargs)
    return ret


@asyncio.coroutine
def patch(url, **kwargs):
    ret = yield from request(hdrs.METH_PATCH, url, **kwargs)
    return ret


@asyncio.coroutine
def delete(url, **kwargs):
    ret = yield from request(hdrs.METH_DELETE, url, **kwargs)
    return ret

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