{
    "file_diffs": [
        {
            "old_file_content": "__all__ = ('ContentCoding', 'Request', 'StreamResponse', 'Response')\n\nimport asyncio\nimport binascii\nimport cgi\nimport collections\nimport datetime\nimport http.cookies\nimport io\nimport json\nimport math\nimport time\nimport warnings\n\nimport enum\n\nfrom email.utils import parsedate\nfrom types import MappingProxyType\nfrom urllib.parse import urlsplit, parse_qsl, unquote\n\nfrom . import hdrs\nfrom .helpers import reify\nfrom .multidict import (CIMultiDictProxy,\n                        CIMultiDict,\n                        MultiDictProxy,\n                        MultiDict)\nfrom .protocol import Response as ResponseImpl, HttpVersion10\nfrom .streams import EOF_MARKER\n\n\nsentinel = object()\n\n\nclass HeadersMixin:\n\n    _content_type = None\n    _content_dict = None\n    _stored_content_type = sentinel\n\n    def _parse_content_type(self, raw):\n        self._stored_content_type = raw\n        if raw is None:\n            # default value according to RFC 2616\n            self._content_type = 'application/octet-stream'\n            self._content_dict = {}\n        else:\n            self._content_type, self._content_dict = cgi.parse_header(raw)\n\n    @property\n    def content_type(self, _CONTENT_TYPE=hdrs.CONTENT_TYPE):\n        \"\"\"The value of content part for Content-Type HTTP header.\"\"\"\n        raw = self.headers.get(_CONTENT_TYPE)\n        if self._stored_content_type != raw:\n            self._parse_content_type(raw)\n        return self._content_type\n\n    @property\n    def charset(self, _CONTENT_TYPE=hdrs.CONTENT_TYPE):\n        \"\"\"The value of charset part for Content-Type HTTP header.\"\"\"\n        raw = self.headers.get(_CONTENT_TYPE)\n        if self._stored_content_type != raw:\n            self._parse_content_type(raw)\n        return self._content_dict.get('charset')\n\n    @property\n    def content_length(self, _CONTENT_LENGTH=hdrs.CONTENT_LENGTH):\n        \"\"\"The value of Content-Length HTTP header.\"\"\"\n        l = self.headers.get(_CONTENT_LENGTH)\n        if l is None:\n            return None\n        else:\n            return int(l)\n\nFileField = collections.namedtuple('Field', 'name filename file content_type')\n\n\nclass ContentCoding(enum.Enum):\n    # The content codings that we have support for.\n    #\n    # Additional registered codings are listed at:\n    # https://www.iana.org/assignments/http-parameters/http-parameters.xhtml#content-coding\n    deflate = 'deflate'\n    gzip = 'gzip'\n    identity = 'identity'\n\n\n############################################################\n# HTTP Request\n############################################################\n\n\nclass Request(dict, HeadersMixin):\n\n    POST_METHODS = {hdrs.METH_PATCH, hdrs.METH_POST, hdrs.METH_PUT,\n                    hdrs.METH_TRACE, hdrs.METH_DELETE}\n\n    def __init__(self, app, message, payload, transport, reader, writer, *,\n                 _HOST=hdrs.HOST, secure_proxy_ssl_header=None):\n        self._app = app\n        self._version = message.version\n        self._transport = transport\n        self._reader = reader\n        self._writer = writer\n        self._method = message.method\n        self._host = message.headers.get(_HOST)\n        self._path_qs = message.path\n        self._post = None\n        self._post_files_cache = None\n        self._headers = CIMultiDictProxy(message.headers)\n        if self._version < HttpVersion10:\n            self._keep_alive = False\n        else:\n            self._keep_alive = not message.should_close\n\n        # matchdict, route_name, handler\n        # or information about traversal lookup\n        self._match_info = None  # initialized after route resolving\n\n        self._payload = payload\n        self._cookies = None\n\n        self._read_bytes = None\n        self._has_body = not payload.at_eof()\n\n        self._secure_proxy_ssl_header = secure_proxy_ssl_header\n\n    @property\n    def scheme(self):\n        \"\"\"A string representing the scheme of the request.\n\n        'http' or 'https'.\n        \"\"\"\n        if self._transport.get_extra_info('sslcontext'):\n            return 'https'\n        secure_proxy_ssl_header = self._secure_proxy_ssl_header\n        if secure_proxy_ssl_header is not None:\n            header, value = secure_proxy_ssl_header\n            if self._headers.get(header) == value:\n                return 'https'\n        return 'http'\n\n    @property\n    def method(self):\n        \"\"\"Read only property for getting HTTP method.\n\n        The value is upper-cased str like 'GET', 'POST', 'PUT' etc.\n        \"\"\"\n        return self._method\n\n    @property\n    def version(self):\n        \"\"\"Read only property for getting HTTP version of request.\n\n        Returns aiohttp.protocol.HttpVersion instance.\n        \"\"\"\n        return self._version\n\n    @property\n    def host(self):\n        \"\"\"Read only property for getting *HOST* header of request.\n\n        Returns str or None if HTTP request has no HOST header.\n        \"\"\"\n        return self._host\n\n    @property\n    def path_qs(self):\n        \"\"\"The URL including PATH_INFO and the query string.\n\n        E.g, /app/blog?id=10\n        \"\"\"\n        return self._path_qs\n\n    @reify\n    def _splitted_path(self):\n        return urlsplit(self._path_qs)\n\n    @property\n    def raw_path(self):\n        \"\"\" The URL including raw *PATH INFO* without the host or scheme.\n        Warning, the path is unquoted and may contains non valid URL characters\n\n        E.g., ``/my%2Fpath%7Cwith%21some%25strange%24characters``\n        \"\"\"\n        return self._splitted_path.path\n\n    @reify\n    def path(self):\n        \"\"\"The URL including *PATH INFO* without the host or scheme.\n\n        E.g., ``/app/blog``\n        \"\"\"\n        return unquote(self.raw_path)\n\n    @reify\n    def query_string(self):\n        \"\"\"The query string in the URL.\n\n        E.g., id=10\n        \"\"\"\n        return self._splitted_path.query\n\n    @reify\n    def GET(self):\n        \"\"\"A multidict with all the variables in the query string.\n\n        Lazy property.\n        \"\"\"\n        return MultiDictProxy(MultiDict(parse_qsl(self.query_string)))\n\n    @reify\n    def POST(self):\n        \"\"\"A multidict with all the variables in the POST parameters.\n\n        post() methods has to be called before using this attribute.\n        \"\"\"\n        if self._post is None:\n            raise RuntimeError(\"POST is not available before post()\")\n        return self._post\n\n    @property\n    def headers(self):\n        \"\"\"A case-insensitive multidict proxy with all headers.\"\"\"\n        return self._headers\n\n    @property\n    def if_modified_since(self, _IF_MODIFIED_SINCE=hdrs.IF_MODIFIED_SINCE):\n        \"\"\"The value of If-Modified-Since HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        httpdate = self.headers.get(_IF_MODIFIED_SINCE)\n        if httpdate is not None:\n            timetuple = parsedate(httpdate)\n            if timetuple is not None:\n                return datetime.datetime(*timetuple[:6],\n                                         tzinfo=datetime.timezone.utc)\n        return None\n\n    @property\n    def keep_alive(self):\n        \"\"\"Is keepalive enabled by client?\"\"\"\n        return self._keep_alive\n\n    @property\n    def match_info(self):\n        \"\"\"Result of route resolving.\"\"\"\n        return self._match_info\n\n    @property\n    def app(self):\n        \"\"\"Application instance.\"\"\"\n        return self._app\n\n    @property\n    def transport(self):\n        \"\"\"Transport used for request processing.\"\"\"\n        return self._transport\n\n    @property\n    def cookies(self):\n        \"\"\"Return request cookies.\n\n        A read-only dictionary-like object.\n        \"\"\"\n        if self._cookies is None:\n            raw = self.headers.get(hdrs.COOKIE, '')\n            parsed = http.cookies.SimpleCookie(raw)\n            self._cookies = MappingProxyType(\n                {key: val.value for key, val in parsed.items()})\n        return self._cookies\n\n    @property\n    def payload(self):\n        \"\"\"Return raw payload stream.\"\"\"\n        warnings.warn('use Request.content instead', DeprecationWarning)\n        return self._payload\n\n    @property\n    def content(self):\n        \"\"\"Return raw payload stream.\"\"\"\n        return self._payload\n\n    @property\n    def has_body(self):\n        \"\"\"Return True if request has HTTP BODY, False otherwise.\"\"\"\n        return self._has_body\n\n    @asyncio.coroutine\n    def release(self):\n        \"\"\"Release request.\n\n        Eat unread part of HTTP BODY if present.\n        \"\"\"\n        chunk = yield from self._payload.readany()\n        while chunk is not EOF_MARKER or chunk:\n            chunk = yield from self._payload.readany()\n\n    @asyncio.coroutine\n    def read(self):\n        \"\"\"Read request body if present.\n\n        Returns bytes object with full request content.\n        \"\"\"\n        if self._read_bytes is None:\n            body = bytearray()\n            while True:\n                chunk = yield from self._payload.readany()\n                body.extend(chunk)\n                if chunk is EOF_MARKER:\n                    break\n            self._read_bytes = bytes(body)\n        return self._read_bytes\n\n    @asyncio.coroutine\n    def text(self):\n        \"\"\"Return BODY as text using encoding from .charset.\"\"\"\n        bytes_body = yield from self.read()\n        encoding = self.charset or 'utf-8'\n        return bytes_body.decode(encoding)\n\n    @asyncio.coroutine\n    def json(self, *, loader=json.loads):\n        \"\"\"Return BODY as JSON.\"\"\"\n        body = yield from self.text()\n        return loader(body)\n\n    @asyncio.coroutine\n    def post(self):\n        \"\"\"Return POST parameters.\"\"\"\n        if self._post is not None:\n            return self._post\n        if self.method not in self.POST_METHODS:\n            self._post = MultiDictProxy(MultiDict())\n            return self._post\n\n        content_type = self.content_type\n        if (content_type not in ('',\n                                 'application/x-www-form-urlencoded',\n                                 'multipart/form-data')):\n            self._post = MultiDictProxy(MultiDict())\n            return self._post\n\n        body = yield from self.read()\n        content_charset = self.charset or 'utf-8'\n\n        environ = {'REQUEST_METHOD': self.method,\n                   'CONTENT_LENGTH': str(len(body)),\n                   'QUERY_STRING': '',\n                   'CONTENT_TYPE': self.headers.get(hdrs.CONTENT_TYPE)}\n\n        fs = cgi.FieldStorage(fp=io.BytesIO(body),\n                              environ=environ,\n                              keep_blank_values=True,\n                              encoding=content_charset)\n\n        supported_transfer_encoding = {\n            'base64': binascii.a2b_base64,\n            'quoted-printable': binascii.a2b_qp\n        }\n\n        out = MultiDict()\n        for field in fs.list or ():\n            transfer_encoding = field.headers.get(\n                hdrs.CONTENT_TRANSFER_ENCODING, None)\n            if field.filename:\n                ff = FileField(field.name,\n                               field.filename,\n                               field.file,  # N.B. file closed error\n                               field.type)\n                if self._post_files_cache is None:\n                    self._post_files_cache = {}\n                self._post_files_cache[field.name] = field\n                out.add(field.name, ff)\n            else:\n                value = field.value\n                if transfer_encoding in supported_transfer_encoding:\n                    # binascii accepts bytes\n                    value = value.encode('utf-8')\n                    value = supported_transfer_encoding[\n                        transfer_encoding](value)\n                out.add(field.name, value)\n\n        self._post = MultiDictProxy(out)\n        return self._post\n\n    def __repr__(self):\n        return \"<{} {} {} >\".format(self.__class__.__name__,\n                                    self.method, self.path)\n\n\n############################################################\n# HTTP Response classes\n############################################################\n\n\nclass StreamResponse(HeadersMixin):\n\n    def __init__(self, *, status=200, reason=None, headers=None):\n        self._body = None\n        self._keep_alive = None\n        self._chunked = False\n        self._chunk_size = None\n        self._compression = False\n        self._compression_force = False\n        self._headers = CIMultiDict()\n        self._cookies = http.cookies.SimpleCookie()\n        self.set_status(status, reason)\n\n        self._req = None\n        self._resp_impl = None\n        self._eof_sent = False\n\n        if headers is not None:\n            self._headers.extend(headers)\n\n    def _copy_cookies(self):\n        for cookie in self._cookies.values():\n            value = cookie.output(header='')[1:]\n            self.headers.add(hdrs.SET_COOKIE, value)\n\n    @property\n    def started(self):\n        return self._resp_impl is not None\n\n    @property\n    def status(self):\n        return self._status\n\n    @property\n    def chunked(self):\n        return self._chunked\n\n    @property\n    def compression(self):\n        return self._compression\n\n    @property\n    def reason(self):\n        return self._reason\n\n    def set_status(self, status, reason=None):\n        self._status = int(status)\n        if reason is None:\n            reason = ResponseImpl.calc_reason(status)\n        self._reason = reason\n\n    @property\n    def keep_alive(self):\n        return self._keep_alive\n\n    def force_close(self):\n        self._keep_alive = False\n\n    def enable_chunked_encoding(self, chunk_size=None):\n        \"\"\"Enables automatic chunked transfer encoding.\"\"\"\n        self._chunked = True\n        self._chunk_size = chunk_size\n\n    def enable_compression(self, force=None):\n        \"\"\"Enables response compression encoding.\"\"\"\n        # Backwards compatibility for when force was a bool <0.17.\n        if type(force) == bool:\n            force = ContentCoding.deflate if force else ContentCoding.identity\n\n        self._compression = True\n        self._compression_force = force\n\n    @property\n    def headers(self):\n        return self._headers\n\n    @property\n    def cookies(self):\n        return self._cookies\n\n    def set_cookie(self, name, value, *, expires=None,\n                   domain=None, max_age=None, path='/',\n                   secure=None, httponly=None, version=None):\n        \"\"\"Set or update response cookie.\n\n        Sets new cookie or updates existent with new value.\n        Also updates only those params which are not None.\n        \"\"\"\n\n        old = self._cookies.get(name)\n        if old is not None and old.coded_value == '':\n            # deleted cookie\n            self._cookies.pop(name, None)\n\n        self._cookies[name] = value\n        c = self._cookies[name]\n        if expires is not None:\n            c['expires'] = expires\n        if domain is not None:\n            c['domain'] = domain\n        if max_age is not None:\n            c['max-age'] = max_age\n        if path is not None:\n            c['path'] = path\n        if secure is not None:\n            c['secure'] = secure\n        if httponly is not None:\n            c['httponly'] = httponly\n        if version is not None:\n            c['version'] = version\n\n    def del_cookie(self, name, *, domain=None, path='/'):\n        \"\"\"Delete cookie.\n\n        Creates new empty expired cookie.\n        \"\"\"\n        # TODO: do we need domain/path here?\n        self._cookies.pop(name, None)\n        self.set_cookie(name, '', max_age=0, domain=domain, path=path)\n\n    @property\n    def content_length(self):\n        # Just a placeholder for adding setter\n        return super().content_length\n\n    @content_length.setter\n    def content_length(self, value):\n        if value is not None:\n            value = int(value)\n            # TODO: raise error if chunked enabled\n            self.headers[hdrs.CONTENT_LENGTH] = str(value)\n        elif hdrs.CONTENT_LENGTH in self.headers:\n            del self.headers[hdrs.CONTENT_LENGTH]\n\n    @property\n    def content_type(self):\n        # Just a placeholder for adding setter\n        return super().content_type\n\n    @content_type.setter\n    def content_type(self, value):\n        self.content_type  # read header values if needed\n        self._content_type = str(value)\n        self._generate_content_type_header()\n\n    @property\n    def charset(self):\n        # Just a placeholder for adding setter\n        return super().charset\n\n    @charset.setter\n    def charset(self, value):\n        ctype = self.content_type  # read header values if needed\n        if ctype == 'application/octet-stream':\n            raise RuntimeError(\"Setting charset for application/octet-stream \"\n                               \"doesn't make sense, setup content_type first\")\n        if value is None:\n            self._content_dict.pop('charset', None)\n        else:\n            self._content_dict['charset'] = str(value).lower()\n        self._generate_content_type_header()\n\n    @property\n    def last_modified(self, _LAST_MODIFIED=hdrs.LAST_MODIFIED):\n        \"\"\"The value of Last-Modified HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        httpdate = self.headers.get(_LAST_MODIFIED)\n        if httpdate is not None:\n            timetuple = parsedate(httpdate)\n            if timetuple is not None:\n                return datetime.datetime(*timetuple[:6],\n                                         tzinfo=datetime.timezone.utc)\n        return None\n\n    @last_modified.setter\n    def last_modified(self, value):\n        if value is None:\n            if hdrs.LAST_MODIFIED in self.headers:\n                del self.headers[hdrs.LAST_MODIFIED]\n        elif isinstance(value, (int, float)):\n            self.headers[hdrs.LAST_MODIFIED] = time.strftime(\n                \"%a, %d %b %Y %H:%M:%S GMT\", time.gmtime(math.ceil(value)))\n        elif isinstance(value, datetime.datetime):\n            self.headers[hdrs.LAST_MODIFIED] = time.strftime(\n                \"%a, %d %b %Y %H:%M:%S GMT\", value.utctimetuple())\n        elif isinstance(value, str):\n            self.headers[hdrs.LAST_MODIFIED] = value\n\n    def _generate_content_type_header(self, CONTENT_TYPE=hdrs.CONTENT_TYPE):\n        params = '; '.join(\"%s=%s\" % i for i in self._content_dict.items())\n        if params:\n            ctype = self._content_type + '; ' + params\n        else:\n            ctype = self._content_type\n        self.headers[CONTENT_TYPE] = ctype\n\n    def _start_pre_check(self, request):\n        if self._resp_impl is not None:\n            if self._req is not request:\n                raise RuntimeError(\n                    'Response has been started with different request.')\n            else:\n                return self._resp_impl\n        else:\n            return None\n\n    def _start_compression(self, request):\n        def start(coding):\n            if coding != ContentCoding.identity:\n                self.headers[hdrs.CONTENT_ENCODING] = coding.value\n                self._resp_impl.add_compression_filter(coding.value)\n\n        if self._compression_force:\n            start(self._compression_force)\n        else:\n            accept_encoding = request.headers.get(\n                hdrs.ACCEPT_ENCODING, '').lower()\n            for coding in ContentCoding:\n                if coding.value in accept_encoding:\n                    start(coding)\n                    return\n\n    def start(self, request):\n        resp_impl = self._start_pre_check(request)\n        if resp_impl is not None:\n            return resp_impl\n\n        self._req = request\n        keep_alive = self._keep_alive\n        if keep_alive is None:\n            keep_alive = request.keep_alive\n        self._keep_alive = keep_alive\n\n        resp_impl = self._resp_impl = ResponseImpl(\n            request._writer,\n            self._status,\n            request.version,\n            not keep_alive,\n            self._reason)\n\n        self._copy_cookies()\n\n        if self._compression:\n            self._start_compression(request)\n\n        if self._chunked:\n            resp_impl.enable_chunked_encoding()\n            if self._chunk_size:\n                resp_impl.add_chunking_filter(self._chunk_size)\n\n        headers = self.headers.items()\n        for key, val in headers:\n            resp_impl.add_header(key, val)\n\n        resp_impl.send_headers()\n        return resp_impl\n\n    def write(self, data):\n        assert isinstance(data, (bytes, bytearray, memoryview)), \\\n            'data argument must be byte-ish (%r)' % type(data)\n\n        if self._eof_sent:\n            raise RuntimeError(\"Cannot call write() after write_eof()\")\n        if self._resp_impl is None:\n            raise RuntimeError(\"Cannot call write() before start()\")\n\n        if data:\n            return self._resp_impl.write(data)\n        else:\n            return ()\n\n    @asyncio.coroutine\n    def drain(self):\n        if self._resp_impl is None:\n            raise RuntimeError(\"Response has not been started\")\n        yield from self._resp_impl.transport.drain()\n\n    @asyncio.coroutine\n    def write_eof(self):\n        if self._eof_sent:\n            return\n        if self._resp_impl is None:\n            raise RuntimeError(\"Response has not been started\")\n\n        yield from self._resp_impl.write_eof()\n        self._eof_sent = True\n\n    def __repr__(self):\n        if self.started:\n            info = \"{} {} \".format(self._req.method, self._req.path)\n        else:\n            info = \"not started\"\n        return \"<{} {} {}>\".format(self.__class__.__name__,\n                                   self.reason, info)\n\n\nclass Response(StreamResponse):\n\n    def __init__(self, *, body=None, status=200,\n                 reason=None, text=None, headers=None, content_type=None):\n        super().__init__(status=status, reason=reason, headers=headers)\n\n        if body is not None and text is not None:\n            raise ValueError(\"body and text are not allowed together.\")\n\n        if text is not None:\n            if hdrs.CONTENT_TYPE not in self.headers:\n                # fast path for filling headers\n                if not isinstance(text, str):\n                    raise TypeError('text argument must be str (%r)' %\n                                    type(text))\n                if content_type is None:\n                    content_type = 'text/plain'\n                self.headers[hdrs.CONTENT_TYPE] = (\n                    content_type + '; charset=utf-8')\n                self._content_type = content_type\n                self._content_dict = {'charset': 'utf-8'}\n                self.body = text.encode('utf-8')\n            else:\n                self.text = text\n        else:\n            if content_type:\n                self.content_type = content_type\n            if body is not None:\n                self.body = body\n            else:\n                self.body = None\n\n    @property\n    def body(self):\n        return self._body\n\n    @body.setter\n    def body(self, body):\n        if body is not None and not isinstance(body, bytes):\n            raise TypeError('body argument must be bytes (%r)' % type(body))\n        self._body = body\n        if body is not None:\n            self.content_length = len(body)\n        else:\n            self.content_length = 0\n\n    @property\n    def text(self):\n        return self._body.decode(self.charset or 'utf-8')\n\n    @text.setter\n    def text(self, text):\n        if text is not None and not isinstance(text, str):\n            raise TypeError('text argument must be str (%r)' % type(text))\n\n        if self.content_type == 'application/octet-stream':\n            self.content_type = 'text/plain'\n        if self.charset is None:\n            self.charset = 'utf-8'\n\n        self.body = text.encode(self.charset)\n\n    @asyncio.coroutine\n    def write_eof(self):\n        body = self._body\n        if body is not None:\n            self.write(body)\n        yield from super().write_eof()\n",
            "new_file_content": "__all__ = ('ContentCoding', 'Request', 'StreamResponse', 'Response')\n\nimport asyncio\nimport binascii\nimport cgi\nimport collections\nimport datetime\nimport http.cookies\nimport io\nimport json\nimport math\nimport time\nimport warnings\n\nimport enum\n\nfrom email.utils import parsedate\nfrom types import MappingProxyType\nfrom urllib.parse import urlsplit, parse_qsl, unquote\n\nfrom . import hdrs\nfrom .helpers import reify\nfrom .multidict import (CIMultiDictProxy,\n                        CIMultiDict,\n                        MultiDictProxy,\n                        MultiDict)\nfrom .protocol import Response as ResponseImpl, HttpVersion10\nfrom .streams import EOF_MARKER\n\n\nsentinel = object()\n\n\nclass HeadersMixin:\n\n    _content_type = None\n    _content_dict = None\n    _stored_content_type = sentinel\n\n    def _parse_content_type(self, raw):\n        self._stored_content_type = raw\n        if raw is None:\n            # default value according to RFC 2616\n            self._content_type = 'application/octet-stream'\n            self._content_dict = {}\n        else:\n            self._content_type, self._content_dict = cgi.parse_header(raw)\n\n    @property\n    def content_type(self, _CONTENT_TYPE=hdrs.CONTENT_TYPE):\n        \"\"\"The value of content part for Content-Type HTTP header.\"\"\"\n        raw = self.headers.get(_CONTENT_TYPE)\n        if self._stored_content_type != raw:\n            self._parse_content_type(raw)\n        return self._content_type\n\n    @property\n    def charset(self, _CONTENT_TYPE=hdrs.CONTENT_TYPE):\n        \"\"\"The value of charset part for Content-Type HTTP header.\"\"\"\n        raw = self.headers.get(_CONTENT_TYPE)\n        if self._stored_content_type != raw:\n            self._parse_content_type(raw)\n        return self._content_dict.get('charset')\n\n    @property\n    def content_length(self, _CONTENT_LENGTH=hdrs.CONTENT_LENGTH):\n        \"\"\"The value of Content-Length HTTP header.\"\"\"\n        l = self.headers.get(_CONTENT_LENGTH)\n        if l is None:\n            return None\n        else:\n            return int(l)\n\nFileField = collections.namedtuple('Field', 'name filename file content_type')\n\n\nclass ContentCoding(enum.Enum):\n    # The content codings that we have support for.\n    #\n    # Additional registered codings are listed at:\n    # https://www.iana.org/assignments/http-parameters/http-parameters.xhtml#content-coding\n    deflate = 'deflate'\n    gzip = 'gzip'\n    identity = 'identity'\n\n\n############################################################\n# HTTP Request\n############################################################\n\n\nclass Request(dict, HeadersMixin):\n\n    POST_METHODS = {hdrs.METH_PATCH, hdrs.METH_POST, hdrs.METH_PUT,\n                    hdrs.METH_TRACE, hdrs.METH_DELETE}\n\n    def __init__(self, app, message, payload, transport, reader, writer, *,\n                 _HOST=hdrs.HOST, secure_proxy_ssl_header=None):\n        self._app = app\n        self._version = message.version\n        self._transport = transport\n        self._reader = reader\n        self._writer = writer\n        self._method = message.method\n        self._host = message.headers.get(_HOST)\n        self._path_qs = message.path\n        self._post = None\n        self._post_files_cache = None\n        self._headers = CIMultiDictProxy(message.headers)\n        if self._version < HttpVersion10:\n            self._keep_alive = False\n        else:\n            self._keep_alive = not message.should_close\n\n        # matchdict, route_name, handler\n        # or information about traversal lookup\n        self._match_info = None  # initialized after route resolving\n\n        self._payload = payload\n        self._cookies = None\n\n        self._read_bytes = None\n        self._has_body = not payload.at_eof()\n\n        self._secure_proxy_ssl_header = secure_proxy_ssl_header\n\n    @property\n    def scheme(self):\n        \"\"\"A string representing the scheme of the request.\n\n        'http' or 'https'.\n        \"\"\"\n        if self._transport.get_extra_info('sslcontext'):\n            return 'https'\n        secure_proxy_ssl_header = self._secure_proxy_ssl_header\n        if secure_proxy_ssl_header is not None:\n            header, value = secure_proxy_ssl_header\n            if self._headers.get(header) == value:\n                return 'https'\n        return 'http'\n\n    @property\n    def method(self):\n        \"\"\"Read only property for getting HTTP method.\n\n        The value is upper-cased str like 'GET', 'POST', 'PUT' etc.\n        \"\"\"\n        return self._method\n\n    @property\n    def version(self):\n        \"\"\"Read only property for getting HTTP version of request.\n\n        Returns aiohttp.protocol.HttpVersion instance.\n        \"\"\"\n        return self._version\n\n    @property\n    def host(self):\n        \"\"\"Read only property for getting *HOST* header of request.\n\n        Returns str or None if HTTP request has no HOST header.\n        \"\"\"\n        return self._host\n\n    @property\n    def path_qs(self):\n        \"\"\"The URL including PATH_INFO and the query string.\n\n        E.g, /app/blog?id=10\n        \"\"\"\n        return self._path_qs\n\n    @reify\n    def _splitted_path(self):\n        return urlsplit(self._path_qs)\n\n    @property\n    def raw_path(self):\n        \"\"\" The URL including raw *PATH INFO* without the host or scheme.\n        Warning, the path is unquoted and may contains non valid URL characters\n\n        E.g., ``/my%2Fpath%7Cwith%21some%25strange%24characters``\n        \"\"\"\n        return self._splitted_path.path\n\n    @reify\n    def path(self):\n        \"\"\"The URL including *PATH INFO* without the host or scheme.\n\n        E.g., ``/app/blog``\n        \"\"\"\n        return unquote(self.raw_path)\n\n    @reify\n    def query_string(self):\n        \"\"\"The query string in the URL.\n\n        E.g., id=10\n        \"\"\"\n        return self._splitted_path.query\n\n    @reify\n    def GET(self):\n        \"\"\"A multidict with all the variables in the query string.\n\n        Lazy property.\n        \"\"\"\n        return MultiDictProxy(MultiDict(parse_qsl(self.query_string)))\n\n    @reify\n    def POST(self):\n        \"\"\"A multidict with all the variables in the POST parameters.\n\n        post() methods has to be called before using this attribute.\n        \"\"\"\n        if self._post is None:\n            raise RuntimeError(\"POST is not available before post()\")\n        return self._post\n\n    @property\n    def headers(self):\n        \"\"\"A case-insensitive multidict proxy with all headers.\"\"\"\n        return self._headers\n\n    @property\n    def if_modified_since(self, _IF_MODIFIED_SINCE=hdrs.IF_MODIFIED_SINCE):\n        \"\"\"The value of If-Modified-Since HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        httpdate = self.headers.get(_IF_MODIFIED_SINCE)\n        if httpdate is not None:\n            timetuple = parsedate(httpdate)\n            if timetuple is not None:\n                return datetime.datetime(*timetuple[:6],\n                                         tzinfo=datetime.timezone.utc)\n        return None\n\n    @property\n    def keep_alive(self):\n        \"\"\"Is keepalive enabled by client?\"\"\"\n        return self._keep_alive\n\n    @property\n    def match_info(self):\n        \"\"\"Result of route resolving.\"\"\"\n        return self._match_info\n\n    @property\n    def app(self):\n        \"\"\"Application instance.\"\"\"\n        return self._app\n\n    @property\n    def transport(self):\n        \"\"\"Transport used for request processing.\"\"\"\n        return self._transport\n\n    @property\n    def cookies(self):\n        \"\"\"Return request cookies.\n\n        A read-only dictionary-like object.\n        \"\"\"\n        if self._cookies is None:\n            raw = self.headers.get(hdrs.COOKIE, '')\n            parsed = http.cookies.SimpleCookie(raw)\n            self._cookies = MappingProxyType(\n                {key: val.value for key, val in parsed.items()})\n        return self._cookies\n\n    @property\n    def payload(self):\n        \"\"\"Return raw payload stream.\"\"\"\n        warnings.warn('use Request.content instead', DeprecationWarning)\n        return self._payload\n\n    @property\n    def content(self):\n        \"\"\"Return raw payload stream.\"\"\"\n        return self._payload\n\n    @property\n    def has_body(self):\n        \"\"\"Return True if request has HTTP BODY, False otherwise.\"\"\"\n        return self._has_body\n\n    @asyncio.coroutine\n    def release(self):\n        \"\"\"Release request.\n\n        Eat unread part of HTTP BODY if present.\n        \"\"\"\n        chunk = yield from self._payload.readany()\n        while chunk is not EOF_MARKER or chunk:\n            chunk = yield from self._payload.readany()\n\n    @asyncio.coroutine\n    def read(self):\n        \"\"\"Read request body if present.\n\n        Returns bytes object with full request content.\n        \"\"\"\n        if self._read_bytes is None:\n            body = bytearray()\n            while True:\n                chunk = yield from self._payload.readany()\n                body.extend(chunk)\n                if chunk is EOF_MARKER:\n                    break\n            self._read_bytes = bytes(body)\n        return self._read_bytes\n\n    @asyncio.coroutine\n    def text(self):\n        \"\"\"Return BODY as text using encoding from .charset.\"\"\"\n        bytes_body = yield from self.read()\n        encoding = self.charset or 'utf-8'\n        return bytes_body.decode(encoding)\n\n    @asyncio.coroutine\n    def json(self, *, loader=json.loads):\n        \"\"\"Return BODY as JSON.\"\"\"\n        body = yield from self.text()\n        return loader(body)\n\n    @asyncio.coroutine\n    def post(self):\n        \"\"\"Return POST parameters.\"\"\"\n        if self._post is not None:\n            return self._post\n        if self.method not in self.POST_METHODS:\n            self._post = MultiDictProxy(MultiDict())\n            return self._post\n\n        content_type = self.content_type\n        if (content_type not in ('',\n                                 'application/x-www-form-urlencoded',\n                                 'multipart/form-data')):\n            self._post = MultiDictProxy(MultiDict())\n            return self._post\n\n        body = yield from self.read()\n        content_charset = self.charset or 'utf-8'\n\n        environ = {'REQUEST_METHOD': self.method,\n                   'CONTENT_LENGTH': str(len(body)),\n                   'QUERY_STRING': '',\n                   'CONTENT_TYPE': self.headers.get(hdrs.CONTENT_TYPE)}\n\n        fs = cgi.FieldStorage(fp=io.BytesIO(body),\n                              environ=environ,\n                              keep_blank_values=True,\n                              encoding=content_charset)\n\n        supported_transfer_encoding = {\n            'base64': binascii.a2b_base64,\n            'quoted-printable': binascii.a2b_qp\n        }\n\n        out = MultiDict()\n        for field in fs.list or ():\n            transfer_encoding = field.headers.get(\n                hdrs.CONTENT_TRANSFER_ENCODING, None)\n            if field.filename:\n                ff = FileField(field.name,\n                               field.filename,\n                               field.file,  # N.B. file closed error\n                               field.type)\n                if self._post_files_cache is None:\n                    self._post_files_cache = {}\n                self._post_files_cache[field.name] = field\n                out.add(field.name, ff)\n            else:\n                value = field.value\n                if transfer_encoding in supported_transfer_encoding:\n                    # binascii accepts bytes\n                    value = value.encode('utf-8')\n                    value = supported_transfer_encoding[\n                        transfer_encoding](value)\n                out.add(field.name, value)\n\n        self._post = MultiDictProxy(out)\n        return self._post\n\n    def __repr__(self):\n        return \"<{} {} {} >\".format(self.__class__.__name__,\n                                    self.method, self.path)\n\n\n############################################################\n# HTTP Response classes\n############################################################\n\n\nclass StreamResponse(HeadersMixin):\n\n    def __init__(self, *, status=200, reason=None, headers=None):\n        self._body = None\n        self._keep_alive = None\n        self._chunked = False\n        self._chunk_size = None\n        self._compression = False\n        self._compression_force = False\n        self._headers = CIMultiDict()\n        self._cookies = http.cookies.SimpleCookie()\n        self.set_status(status, reason)\n\n        self._req = None\n        self._resp_impl = None\n        self._eof_sent = False\n\n        if headers is not None:\n            self._headers.extend(headers)\n\n    def _copy_cookies(self):\n        for cookie in self._cookies.values():\n            value = cookie.output(header='')[1:]\n            self.headers.add(hdrs.SET_COOKIE, value)\n\n    @property\n    def started(self):\n        return self._resp_impl is not None\n\n    @property\n    def status(self):\n        return self._status\n\n    @property\n    def chunked(self):\n        return self._chunked\n\n    @property\n    def compression(self):\n        return self._compression\n\n    @property\n    def reason(self):\n        return self._reason\n\n    def set_status(self, status, reason=None):\n        self._status = int(status)\n        if reason is None:\n            reason = ResponseImpl.calc_reason(status)\n        self._reason = reason\n\n    @property\n    def keep_alive(self):\n        return self._keep_alive\n\n    def force_close(self):\n        self._keep_alive = False\n\n    def enable_chunked_encoding(self, chunk_size=None):\n        \"\"\"Enables automatic chunked transfer encoding.\"\"\"\n        self._chunked = True\n        self._chunk_size = chunk_size\n\n    def enable_compression(self, force=None):\n        \"\"\"Enables response compression encoding.\"\"\"\n        # Backwards compatibility for when force was a bool <0.17.\n        if type(force) == bool:\n            force = ContentCoding.deflate if force else ContentCoding.identity\n\n        self._compression = True\n        self._compression_force = force\n\n    @property\n    def headers(self):\n        return self._headers\n\n    @property\n    def cookies(self):\n        return self._cookies\n\n    def set_cookie(self, name, value, *, expires=None,\n                   domain=None, max_age=None, path='/',\n                   secure=None, httponly=None, version=None):\n        \"\"\"Set or update response cookie.\n\n        Sets new cookie or updates existent with new value.\n        Also updates only those params which are not None.\n        \"\"\"\n\n        old = self._cookies.get(name)\n        if old is not None and old.coded_value == '':\n            # deleted cookie\n            self._cookies.pop(name, None)\n\n        self._cookies[name] = value\n        c = self._cookies[name]\n        if expires is not None:\n            c['expires'] = expires\n        if domain is not None:\n            c['domain'] = domain\n        if max_age is not None:\n            c['max-age'] = max_age\n        if path is not None:\n            c['path'] = path\n        if secure is not None:\n            c['secure'] = secure\n        if httponly is not None:\n            c['httponly'] = httponly\n        if version is not None:\n            c['version'] = version\n\n    def del_cookie(self, name, *, domain=None, path='/'):\n        \"\"\"Delete cookie.\n\n        Creates new empty expired cookie.\n        \"\"\"\n        # TODO: do we need domain/path here?\n        self._cookies.pop(name, None)\n        self.set_cookie(name, '', max_age=0, domain=domain, path=path)\n\n    @property\n    def content_length(self):\n        # Just a placeholder for adding setter\n        return super().content_length\n\n    @content_length.setter\n    def content_length(self, value):\n        if value is not None:\n            value = int(value)\n            # TODO: raise error if chunked enabled\n            self.headers[hdrs.CONTENT_LENGTH] = str(value)\n        elif hdrs.CONTENT_LENGTH in self.headers:\n            del self.headers[hdrs.CONTENT_LENGTH]\n\n    @property\n    def content_type(self):\n        # Just a placeholder for adding setter\n        return super().content_type\n\n    @content_type.setter\n    def content_type(self, value):\n        self.content_type  # read header values if needed\n        self._content_type = str(value)\n        self._generate_content_type_header()\n\n    @property\n    def charset(self):\n        # Just a placeholder for adding setter\n        return super().charset\n\n    @charset.setter\n    def charset(self, value):\n        ctype = self.content_type  # read header values if needed\n        if ctype == 'application/octet-stream':\n            raise RuntimeError(\"Setting charset for application/octet-stream \"\n                               \"doesn't make sense, setup content_type first\")\n        if value is None:\n            self._content_dict.pop('charset', None)\n        else:\n            self._content_dict['charset'] = str(value).lower()\n        self._generate_content_type_header()\n\n    @property\n    def last_modified(self, _LAST_MODIFIED=hdrs.LAST_MODIFIED):\n        \"\"\"The value of Last-Modified HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        httpdate = self.headers.get(_LAST_MODIFIED)\n        if httpdate is not None:\n            timetuple = parsedate(httpdate)\n            if timetuple is not None:\n                return datetime.datetime(*timetuple[:6],\n                                         tzinfo=datetime.timezone.utc)\n        return None\n\n    @last_modified.setter\n    def last_modified(self, value):\n        if value is None:\n            if hdrs.LAST_MODIFIED in self.headers:\n                del self.headers[hdrs.LAST_MODIFIED]\n        elif isinstance(value, (int, float)):\n            self.headers[hdrs.LAST_MODIFIED] = time.strftime(\n                \"%a, %d %b %Y %H:%M:%S GMT\", time.gmtime(math.ceil(value)))\n        elif isinstance(value, datetime.datetime):\n            self.headers[hdrs.LAST_MODIFIED] = time.strftime(\n                \"%a, %d %b %Y %H:%M:%S GMT\", value.utctimetuple())\n        elif isinstance(value, str):\n            self.headers[hdrs.LAST_MODIFIED] = value\n\n    def _generate_content_type_header(self, CONTENT_TYPE=hdrs.CONTENT_TYPE):\n        params = '; '.join(\"%s=%s\" % i for i in self._content_dict.items())\n        if params:\n            ctype = self._content_type + '; ' + params\n        else:\n            ctype = self._content_type\n        self.headers[CONTENT_TYPE] = ctype\n\n    def _start_pre_check(self, request):\n        if self._resp_impl is not None:\n            if self._req is not request:\n                raise RuntimeError(\n                    'Response has been started with different request.')\n            else:\n                return self._resp_impl\n        else:\n            return None\n\n    def _start_compression(self, request):\n        def start(coding):\n            if coding != ContentCoding.identity:\n                self.headers[hdrs.CONTENT_ENCODING] = coding.value\n                self._resp_impl.add_compression_filter(coding.value)\n\n        if self._compression_force:\n            start(self._compression_force)\n        else:\n            accept_encoding = request.headers.get(\n                hdrs.ACCEPT_ENCODING, '').lower()\n            for coding in ContentCoding:\n                if coding.value in accept_encoding:\n                    start(coding)\n                    return\n\n    def start(self, request):\n        resp_impl = self._start_pre_check(request)\n        if resp_impl is not None:\n            return resp_impl\n\n        self._req = request\n        keep_alive = self._keep_alive\n        if keep_alive is None:\n            keep_alive = request.keep_alive\n        self._keep_alive = keep_alive\n\n        resp_impl = self._resp_impl = ResponseImpl(\n            request._writer,\n            self._status,\n            request.version,\n            not keep_alive,\n            self._reason)\n\n        self._copy_cookies()\n\n        if self._compression:\n            self._start_compression(request)\n\n        if self._chunked:\n            resp_impl.enable_chunked_encoding()\n            if self._chunk_size:\n                resp_impl.add_chunking_filter(self._chunk_size)\n\n        headers = self.headers.items()\n        for key, val in headers:\n            resp_impl.add_header(key, val)\n\n        resp_impl.send_headers()\n        return resp_impl\n\n    def write(self, data):\n        assert isinstance(data, (bytes, bytearray, memoryview)), \\\n            'data argument must be byte-ish (%r)' % type(data)\n\n        if self._eof_sent:\n            raise RuntimeError(\"Cannot call write() after write_eof()\")\n        if self._resp_impl is None:\n            raise RuntimeError(\"Cannot call write() before start()\")\n\n        if data:\n            return self._resp_impl.write(data)\n        else:\n            return ()\n\n    @asyncio.coroutine\n    def drain(self):\n        if self._resp_impl is None:\n            raise RuntimeError(\"Response has not been started\")\n        yield from self._resp_impl.transport.drain()\n\n    @asyncio.coroutine\n    def write_eof(self):\n        if self._eof_sent:\n            return\n        if self._resp_impl is None:\n            raise RuntimeError(\"Response has not been started\")\n\n        yield from self._resp_impl.write_eof()\n        self._eof_sent = True\n\n    def __repr__(self):\n        if self.started:\n            info = \"{} {} \".format(self._req.method, self._req.path)\n        else:\n            info = \"not started\"\n        return \"<{} {} {}>\".format(self.__class__.__name__,\n                                   self.reason, info)\n\n\nclass Response(StreamResponse):\n\n    def __init__(self, *, body=None, status=200,\n                 reason=None, text=None, headers=None, content_type=None):\n        super().__init__(status=status, reason=reason, headers=headers)\n\n        if body is not None and text is not None:\n            raise ValueError(\"body and text are not allowed together.\")\n\n        if text is not None:\n            if hdrs.CONTENT_TYPE not in self.headers:\n                # fast path for filling headers\n                if not isinstance(text, str):\n                    raise TypeError('text argument must be str (%r)' %\n                                    type(text))\n                if content_type is None:\n                    content_type = 'text/plain'\n                self.headers[hdrs.CONTENT_TYPE] = (\n                    content_type + '; charset=utf-8')\n                self._content_type = content_type\n                self._content_dict = {'charset': 'utf-8'}\n                self.body = text.encode('utf-8')\n            else:\n                self.text = text\n        else:\n            if content_type:\n                self.content_type = content_type\n            if body is not None:\n                self.body = body\n            else:\n                self.body = None\n\n    @property\n    def body(self):\n        return self._body\n\n    @body.setter\n    def body(self, body):\n        if body is not None and not isinstance(body, bytes):\n            raise TypeError('body argument must be bytes (%r)' % type(body))\n        self._body = body\n        if body is not None:\n            self.content_length = len(body)\n        else:\n            self.content_length = 0\n\n    @property\n    def text(self):\n        if self._body is None:\n            return None\n        return self._body.decode(self.charset or 'utf-8')\n\n    @text.setter\n    def text(self, text):\n        if text is not None and not isinstance(text, str):\n            raise TypeError('text argument must be str (%r)' % type(text))\n\n        if self.content_type == 'application/octet-stream':\n            self.content_type = 'text/plain'\n        if self.charset is None:\n            self.charset = 'utf-8'\n\n        self.body = text.encode(self.charset)\n\n    @asyncio.coroutine\n    def write_eof(self):\n        body = self._body\n        if body is not None:\n            self.write(body)\n        yield from super().write_eof()\n",
            "header": {
                "file": {
                    "path": "aiohttp/web_reqrep.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "83cd59b4",
                "new_commit_hash": "b00c8c41",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/aiohttp/web_reqrep.py"
            },
            "plus_file": {
                "path": "b/aiohttp/web_reqrep.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 740,
                            "length": 6
                        },
                        "new_range": {
                            "start": 740,
                            "length": 8
                        },
                        "section": "class Response(StreamResponse):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    @property",
                                "type": "context"
                            },
                            {
                                "content": "    def text(self):",
                                "type": "context"
                            },
                            {
                                "content": "        if self._body is None:",
                                "type": "added"
                            },
                            {
                                "content": "            return None",
                                "type": "added"
                            },
                            {
                                "content": "        return self._body.decode(self.charset or 'utf-8')",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    @text.setter",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "aiohttp/web_reqrep.py",
                            "type": "class",
                            "name": "Response",
                            "content": "class Response(StreamResponse):\n\n    def __init__(self, *, body=None, status=200,\n                 reason=None, text=None, headers=None, content_type=None):\n        super().__init__(status=status, reason=reason, headers=headers)\n\n        if body is not None and text is not None:\n            raise ValueError(\"body and text are not allowed together.\")\n\n        if text is not None:\n            if hdrs.CONTENT_TYPE not in self.headers:\n                # fast path for filling headers\n                if not isinstance(text, str):\n                    raise TypeError('text argument must be str (%r)' %\n                                    type(text))\n                if content_type is None:\n                    content_type = 'text/plain'\n                self.headers[hdrs.CONTENT_TYPE] = (\n                    content_type + '; charset=utf-8')\n                self._content_type = content_type\n                self._content_dict = {'charset': 'utf-8'}\n                self.body = text.encode('utf-8')\n            else:\n                self.text = text\n        else:\n            if content_type:\n                self.content_type = content_type\n            if body is not None:\n                self.body = body\n            else:\n                self.body = None\n\n    @property\n    def body(self):\n        return self._body\n\n    @body.setter\n    def body(self, body):\n        if body is not None and not isinstance(body, bytes):\n            raise TypeError('body argument must be bytes (%r)' % type(body))\n        self._body = body\n        if body is not None:\n            self.content_length = len(body)\n        else:\n            self.content_length = 0\n\n    @property\n    def text(self):\n        if self._body is None:\n            return None\n        return self._body.decode(self.charset or 'utf-8')\n\n    @text.setter\n    def text(self, text):\n        if text is not None and not isinstance(text, str):\n            raise TypeError('text argument must be str (%r)' % type(text))\n\n        if self.content_type == 'application/octet-stream':\n            self.content_type = 'text/plain'\n        if self.charset is None:\n            self.charset = 'utf-8'\n\n        self.body = text.encode(self.charset)\n\n    @asyncio.coroutine\n    def write_eof(self):\n        body = self._body\n        if body is not None:\n            self.write(body)\n        yield from super().write_eof()",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 695,
                            "end_lineno": 764,
                            "parent": null
                        },
                        {
                            "file_name": "aiohttp/web_reqrep.py",
                            "type": "method",
                            "name": "Response.text",
                            "content": "class Response(StreamResponse):\n\n    def __init__(self, *, body=None, status=200,\n                 reason=None, text=None, headers=None, content_type=None):\n        super().__init__(status=status, reason=reason, headers=headers)\n\n        if body is not None and text is not None:\n            raise ValueError(\"body and text are not allowed together.\")\n\n        if text is not None:\n            if hdrs.CONTENT_TYPE not in self.headers:\n                # fast path for filling headers\n                if not isinstance(text, str):\n                    raise TypeError('text argument must be str (%r)' %\n                                    type(text))\n                if content_type is None:\n                    content_type = 'text/plain'\n                self.headers[hdrs.CONTENT_TYPE] = (\n                    content_type + '; charset=utf-8')\n                self._content_type = content_type\n                self._content_dict = {'charset': 'utf-8'}\n                self.body = text.encode('utf-8')\n            else:\n                self.text = text\n        else:\n            if content_type:\n                self.content_type = content_type\n            if body is not None:\n                self.body = body\n            else:\n                self.body = None\n\n    @property\n    def body(self):\n        return self._body\n\n    @body.setter\n    def body(self, body):\n        if body is not None and not isinstance(body, bytes):\n            raise TypeError('body argument must be bytes (%r)' % type(body))\n        self._body = body\n        if body is not None:\n            self.content_length = len(body)\n        else:\n            self.content_length = 0\n\n    @property\n    def text(self):\n        if self._body is None:\n            return None\n        return self._body.decode(self.charset or 'utf-8')\n\n    @text.setter\n    def text(self, text):\n        if text is not None and not isinstance(text, str):\n            raise TypeError('text argument must be str (%r)' % type(text))\n\n        if self.content_type == 'application/octet-stream':\n            self.content_type = 'text/plain'\n        if self.charset is None:\n            self.charset = 'utf-8'\n\n        self.body = text.encode(self.charset)\n\n    @asyncio.coroutine\n    def write_eof(self):\n        body = self._body\n        if body is not None:\n            self.write(body)\n        yield from super().write_eof()",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 742,
                            "end_lineno": 745,
                            "parent": {
                                "file_name": "aiohttp/web_reqrep.py",
                                "type": "class",
                                "name": "Response",
                                "content": "class Response(StreamResponse):\n\n    def __init__(self, *, body=None, status=200,\n                 reason=None, text=None, headers=None, content_type=None):\n        super().__init__(status=status, reason=reason, headers=headers)\n\n        if body is not None and text is not None:\n            raise ValueError(\"body and text are not allowed together.\")\n\n        if text is not None:\n            if hdrs.CONTENT_TYPE not in self.headers:\n                # fast path for filling headers\n                if not isinstance(text, str):\n                    raise TypeError('text argument must be str (%r)' %\n                                    type(text))\n                if content_type is None:\n                    content_type = 'text/plain'\n                self.headers[hdrs.CONTENT_TYPE] = (\n                    content_type + '; charset=utf-8')\n                self._content_type = content_type\n                self._content_dict = {'charset': 'utf-8'}\n                self.body = text.encode('utf-8')\n            else:\n                self.text = text\n        else:\n            if content_type:\n                self.content_type = content_type\n            if body is not None:\n                self.body = body\n            else:\n                self.body = None\n\n    @property\n    def body(self):\n        return self._body\n\n    @body.setter\n    def body(self, body):\n        if body is not None and not isinstance(body, bytes):\n            raise TypeError('body argument must be bytes (%r)' % type(body))\n        self._body = body\n        if body is not None:\n            self.content_length = len(body)\n        else:\n            self.content_length = 0\n\n    @property\n    def text(self):\n        if self._body is None:\n            return None\n        return self._body.decode(self.charset or 'utf-8')\n\n    @text.setter\n    def text(self, text):\n        if text is not None and not isinstance(text, str):\n            raise TypeError('text argument must be str (%r)' % type(text))\n\n        if self.content_type == 'application/octet-stream':\n            self.content_type = 'text/plain'\n        if self.charset is None:\n            self.charset = 'utf-8'\n\n        self.body = text.encode(self.charset)\n\n    @asyncio.coroutine\n    def write_eof(self):\n        body = self._body\n        if body is not None:\n            self.write(body)\n        yield from super().write_eof()",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 695,
                                "end_lineno": 764,
                                "parent": null
                            }
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "import asyncio\nimport datetime\nimport unittest\nfrom unittest import mock\nfrom aiohttp import hdrs\nfrom aiohttp.multidict import CIMultiDict\nfrom aiohttp.web import ContentCoding, Request, StreamResponse, Response\nfrom aiohttp.protocol import HttpVersion, HttpVersion11, HttpVersion10\nfrom aiohttp.protocol import RawRequestMessage\n\n\nclass TestStreamResponse(unittest.TestCase):\n\n    def setUp(self):\n        self.loop = asyncio.new_event_loop()\n        asyncio.set_event_loop(None)\n\n    def tearDown(self):\n        self.loop.close()\n\n    def make_request(self, method, path, headers=CIMultiDict()):\n        message = RawRequestMessage(method, path, HttpVersion11, headers,\n                                    False, False)\n        return self.request_from_message(message)\n\n    def request_from_message(self, message):\n        self.app = mock.Mock()\n        self.payload = mock.Mock()\n        self.transport = mock.Mock()\n        self.reader = mock.Mock()\n        self.writer = mock.Mock()\n        req = Request(self.app, message, self.payload,\n                      self.transport, self.reader, self.writer)\n        return req\n\n    def test_ctor(self):\n        resp = StreamResponse()\n        self.assertEqual(200, resp.status)\n        self.assertIsNone(resp.keep_alive)\n\n    def test_content_length(self):\n        resp = StreamResponse()\n        self.assertIsNone(resp.content_length)\n\n    def test_content_length_setter(self):\n        resp = StreamResponse()\n\n        resp.content_length = 234\n        self.assertEqual(234, resp.content_length)\n\n    def test_drop_content_length_header_on_setting_len_to_None(self):\n        resp = StreamResponse()\n\n        resp.content_length = 1\n        self.assertEqual(\"1\", resp.headers['Content-Length'])\n        resp.content_length = None\n        self.assertNotIn('Content-Length', resp.headers)\n\n    def test_set_content_length_to_None_on_non_set(self):\n        resp = StreamResponse()\n\n        resp.content_length = None\n        self.assertNotIn('Content-Length', resp.headers)\n        resp.content_length = None\n        self.assertNotIn('Content-Length', resp.headers)\n\n    def test_setting_content_type(self):\n        resp = StreamResponse()\n\n        resp.content_type = 'text/html'\n        self.assertEqual('text/html', resp.headers['content-type'])\n\n    def test_setting_charset(self):\n        resp = StreamResponse()\n\n        resp.content_type = 'text/html'\n        resp.charset = 'koi8-r'\n        self.assertEqual('text/html; charset=koi8-r',\n                         resp.headers['content-type'])\n\n    def test_default_charset(self):\n        resp = StreamResponse()\n\n        self.assertIsNone(resp.charset)\n\n    def test_reset_charset(self):\n        resp = StreamResponse()\n\n        resp.content_type = 'text/html'\n        resp.charset = None\n        self.assertIsNone(resp.charset)\n\n    def test_reset_charset_after_setting(self):\n        resp = StreamResponse()\n\n        resp.content_type = 'text/html'\n        resp.charset = 'koi8-r'\n        resp.charset = None\n        self.assertIsNone(resp.charset)\n\n    def test_charset_without_content_type(self):\n        resp = StreamResponse()\n\n        with self.assertRaises(RuntimeError):\n            resp.charset = 'koi8-r'\n\n    def test_last_modified_initial(self):\n        resp = StreamResponse()\n        self.assertIsNone(resp.last_modified)\n\n    def test_last_modified_string(self):\n        resp = StreamResponse()\n\n        dt = datetime.datetime(1990, 1, 2, 3, 4, 5, 0, datetime.timezone.utc)\n        resp.last_modified = 'Mon, 2 Jan 1990 03:04:05 GMT'\n        self.assertEqual(resp.last_modified, dt)\n\n    def test_last_modified_timestamp(self):\n        resp = StreamResponse()\n\n        dt = datetime.datetime(1970, 1, 1, 0, 0, 0, 0, datetime.timezone.utc)\n\n        resp.last_modified = 0\n        self.assertEqual(resp.last_modified, dt)\n\n        resp.last_modified = 0.0\n        self.assertEqual(resp.last_modified, dt)\n\n    def test_last_modified_datetime(self):\n        resp = StreamResponse()\n\n        dt = datetime.datetime(2001, 2, 3, 4, 5, 6, 0, datetime.timezone.utc)\n        resp.last_modified = dt\n        self.assertEqual(resp.last_modified, dt)\n\n    def test_last_modified_reset(self):\n        resp = StreamResponse()\n\n        resp.last_modified = 0\n        resp.last_modified = None\n        self.assertEqual(resp.last_modified, None)\n\n    @mock.patch('aiohttp.web_reqrep.ResponseImpl')\n    def test_start(self, ResponseImpl):\n        req = self.make_request('GET', '/')\n        resp = StreamResponse()\n        self.assertIsNone(resp.keep_alive)\n\n        msg = resp.start(req)\n\n        self.assertTrue(msg.send_headers.called)\n        self.assertIs(msg, resp.start(req))\n\n        self.assertTrue(resp.keep_alive)\n\n        req2 = self.make_request('GET', '/')\n        with self.assertRaises(RuntimeError):\n            resp.start(req2)\n\n    @mock.patch('aiohttp.web_reqrep.ResponseImpl')\n    def test_chunked_encoding(self, ResponseImpl):\n        req = self.make_request('GET', '/')\n        resp = StreamResponse()\n        self.assertFalse(resp.chunked)\n\n        resp.enable_chunked_encoding()\n        self.assertTrue(resp.chunked)\n\n        msg = resp.start(req)\n        self.assertTrue(msg.chunked)\n\n    @mock.patch('aiohttp.web_reqrep.ResponseImpl')\n    def test_chunk_size(self, ResponseImpl):\n        req = self.make_request('GET', '/')\n        resp = StreamResponse()\n        self.assertFalse(resp.chunked)\n\n        resp.enable_chunked_encoding(chunk_size=8192)\n        self.assertTrue(resp.chunked)\n\n        msg = resp.start(req)\n        self.assertTrue(msg.chunked)\n        msg.add_chunking_filter.assert_called_with(8192)\n        self.assertIsNotNone(msg.filter)\n\n    @mock.patch('aiohttp.web_reqrep.ResponseImpl')\n    def test_compression_no_accept(self, ResponseImpl):\n        req = self.make_request('GET', '/')\n        resp = StreamResponse()\n        self.assertFalse(resp.chunked)\n\n        self.assertFalse(resp.compression)\n        resp.enable_compression()\n        self.assertTrue(resp.compression)\n\n        msg = resp.start(req)\n        self.assertFalse(msg.add_compression_filter.called)\n\n    @mock.patch('aiohttp.web_reqrep.ResponseImpl')\n    def test_force_compression_no_accept_backwards_compat(self, ResponseImpl):\n        req = self.make_request('GET', '/')\n        resp = StreamResponse()\n        self.assertFalse(resp.chunked)\n\n        self.assertFalse(resp.compression)\n        resp.enable_compression(force=True)\n        self.assertTrue(resp.compression)\n\n        msg = resp.start(req)\n        self.assertTrue(msg.add_compression_filter.called)\n        self.assertIsNotNone(msg.filter)\n\n    @mock.patch('aiohttp.web_reqrep.ResponseImpl')\n    def test_force_compression_false_backwards_compat(self, ResponseImpl):\n        req = self.make_request('GET', '/')\n        resp = StreamResponse()\n\n        self.assertFalse(resp.compression)\n        resp.enable_compression(force=False)\n        self.assertTrue(resp.compression)\n\n        msg = resp.start(req)\n        self.assertFalse(msg.add_compression_filter.called)\n\n    @mock.patch('aiohttp.web_reqrep.ResponseImpl')\n    def test_compression_default_coding(self, ResponseImpl):\n        req = self.make_request(\n            'GET', '/',\n            headers=CIMultiDict({hdrs.ACCEPT_ENCODING: 'gzip, deflate'}))\n        resp = StreamResponse()\n        self.assertFalse(resp.chunked)\n\n        self.assertFalse(resp.compression)\n        resp.enable_compression()\n        self.assertTrue(resp.compression)\n\n        msg = resp.start(req)\n        msg.add_compression_filter.assert_called_with('deflate')\n        self.assertEqual('deflate', resp.headers.get(hdrs.CONTENT_ENCODING))\n        self.assertIsNotNone(msg.filter)\n\n    @mock.patch('aiohttp.web_reqrep.ResponseImpl')\n    def test_force_compression_deflate(self, ResponseImpl):\n        req = self.make_request(\n            'GET', '/',\n            headers=CIMultiDict({hdrs.ACCEPT_ENCODING: 'gzip, deflate'}))\n        resp = StreamResponse()\n\n        resp.enable_compression(ContentCoding.deflate)\n        self.assertTrue(resp.compression)\n\n        msg = resp.start(req)\n        msg.add_compression_filter.assert_called_with('deflate')\n        self.assertEqual('deflate', resp.headers.get(hdrs.CONTENT_ENCODING))\n\n    @mock.patch('aiohttp.web_reqrep.ResponseImpl')\n    def test_force_compression_no_accept_deflate(self, ResponseImpl):\n        req = self.make_request('GET', '/')\n        resp = StreamResponse()\n\n        resp.enable_compression(ContentCoding.deflate)\n        self.assertTrue(resp.compression)\n\n        msg = resp.start(req)\n        msg.add_compression_filter.assert_called_with('deflate')\n        self.assertEqual('deflate', resp.headers.get(hdrs.CONTENT_ENCODING))\n\n    @mock.patch('aiohttp.web_reqrep.ResponseImpl')\n    def test_force_compression_gzip(self, ResponseImpl):\n        req = self.make_request(\n            'GET', '/',\n            headers=CIMultiDict({hdrs.ACCEPT_ENCODING: 'gzip, deflate'}))\n        resp = StreamResponse()\n\n        resp.enable_compression(ContentCoding.gzip)\n        self.assertTrue(resp.compression)\n\n        msg = resp.start(req)\n        msg.add_compression_filter.assert_called_with('gzip')\n        self.assertEqual('gzip', resp.headers.get(hdrs.CONTENT_ENCODING))\n\n    @mock.patch('aiohttp.web_reqrep.ResponseImpl')\n    def test_force_compression_no_accept_gzip(self, ResponseImpl):\n        req = self.make_request('GET', '/')\n        resp = StreamResponse()\n\n        resp.enable_compression(ContentCoding.gzip)\n        self.assertTrue(resp.compression)\n\n        msg = resp.start(req)\n        msg.add_compression_filter.assert_called_with('gzip')\n        self.assertEqual('gzip', resp.headers.get(hdrs.CONTENT_ENCODING))\n\n    def test_write_non_byteish(self):\n        resp = StreamResponse()\n        resp.start(self.make_request('GET', '/'))\n\n        with self.assertRaises(AssertionError):\n            resp.write(123)\n\n    def test_write_before_start(self):\n        resp = StreamResponse()\n\n        with self.assertRaises(RuntimeError):\n            resp.write(b'data')\n\n    def test_cannot_write_after_eof(self):\n        resp = StreamResponse()\n        resp.start(self.make_request('GET', '/'))\n\n        resp.write(b'data')\n        self.writer.drain.return_value = ()\n        self.loop.run_until_complete(resp.write_eof())\n        self.writer.write.reset_mock()\n\n        with self.assertRaises(RuntimeError):\n            resp.write(b'next data')\n        self.assertFalse(self.writer.write.called)\n\n    def test_cannot_write_eof_before_headers(self):\n        resp = StreamResponse()\n\n        with self.assertRaises(RuntimeError):\n            self.loop.run_until_complete(resp.write_eof())\n\n    def test_cannot_write_eof_twice(self):\n        resp = StreamResponse()\n        resp.start(self.make_request('GET', '/'))\n\n        resp.write(b'data')\n        self.writer.drain.return_value = ()\n        self.loop.run_until_complete(resp.write_eof())\n        self.assertTrue(self.writer.write.called)\n\n        self.writer.write.reset_mock()\n        self.loop.run_until_complete(resp.write_eof())\n        self.assertFalse(self.writer.write.called)\n\n    def test_write_returns_drain(self):\n        resp = StreamResponse()\n        resp.start(self.make_request('GET', '/'))\n\n        self.assertEqual((), resp.write(b'data'))\n\n    def test_write_returns_empty_tuple_on_empty_data(self):\n        resp = StreamResponse()\n        resp.start(self.make_request('GET', '/'))\n\n        self.assertEqual((), resp.write(b''))\n\n    def test_force_close(self):\n        resp = StreamResponse()\n\n        self.assertIsNone(resp.keep_alive)\n        resp.force_close()\n        self.assertFalse(resp.keep_alive)\n\n    def test_response_cookies(self):\n        resp = StreamResponse()\n\n        self.assertEqual(resp.cookies, {})\n        self.assertEqual(str(resp.cookies), '')\n\n        resp.set_cookie('name', 'value')\n        self.assertEqual(str(resp.cookies), 'Set-Cookie: name=value; Path=/')\n        resp.set_cookie('name', 'other_value')\n        self.assertEqual(str(resp.cookies),\n                         'Set-Cookie: name=other_value; Path=/')\n\n        resp.cookies['name'] = 'another_other_value'\n        resp.cookies['name']['max-age'] = 10\n        self.assertEqual(\n            str(resp.cookies),\n            'Set-Cookie: name=another_other_value; Max-Age=10; Path=/')\n\n        resp.del_cookie('name')\n        self.assertEqual(\n            str(resp.cookies),\n            'Set-Cookie: name=; Max-Age=0; Path=/')\n\n        resp.set_cookie('name', 'value', domain='local.host', path=None)\n        self.assertEqual(str(resp.cookies),\n                         'Set-Cookie: name=value; Domain=local.host')\n\n    def test_response_cookie_path(self):\n        resp = StreamResponse()\n\n        self.assertEqual(resp.cookies, {})\n\n        resp.set_cookie('name', 'value', path='/some/path')\n        self.assertEqual(str(resp.cookies),\n                         'Set-Cookie: name=value; Path=/some/path')\n        resp.set_cookie('name', 'value', expires='123')\n        self.assertEqual(str(resp.cookies),\n                         'Set-Cookie: name=value; expires=123;'\n                         ' Path=/')\n        resp.set_cookie('name', 'value', domain='example.com',\n                        path='/home', expires='123', max_age='10',\n                        secure=True, httponly=True, version='2.0')\n        self.assertEqual(str(resp.cookies).lower(),\n                         'set-cookie: name=value; '\n                         'domain=example.com; '\n                         'expires=123; '\n                         'httponly; '\n                         'max-age=10; '\n                         'path=/home; '\n                         'secure; '\n                         'version=2.0')\n\n    def test_response_cookie__issue_del_cookie(self):\n        resp = StreamResponse()\n\n        self.assertEqual(resp.cookies, {})\n        self.assertEqual(str(resp.cookies), '')\n\n        resp.del_cookie('name')\n        self.assertEqual(str(resp.cookies),\n                         'Set-Cookie: name=; Max-Age=0; Path=/')\n\n    def test_cookie_set_after_del(self):\n        resp = StreamResponse()\n\n        resp.del_cookie('name')\n        resp.set_cookie('name', 'val')\n        # check for Max-Age dropped\n        self.assertEqual(str(resp.cookies),\n                         'Set-Cookie: name=val; Path=/')\n\n    def test_set_status_with_reason(self):\n        resp = StreamResponse()\n\n        resp.set_status(200, \"Everithing is fine!\")\n        self.assertEqual(200, resp.status)\n        self.assertEqual(\"Everithing is fine!\", resp.reason)\n\n    def test_start_force_close(self):\n        req = self.make_request('GET', '/')\n        resp = StreamResponse()\n        resp.force_close()\n        self.assertFalse(resp.keep_alive)\n\n        msg = resp.start(req)\n        self.assertFalse(resp.keep_alive)\n        self.assertTrue(msg.closing)\n\n    def test___repr__(self):\n        req = self.make_request('GET', '/path/to')\n        resp = StreamResponse(reason=301)\n        resp.start(req)\n        self.assertEqual(\"<StreamResponse 301 GET /path/to >\", repr(resp))\n\n    def test___repr__not_started(self):\n        resp = StreamResponse(reason=301)\n        self.assertEqual(\"<StreamResponse 301 not started>\", repr(resp))\n\n    def test_keep_alive_http10(self):\n        message = RawRequestMessage('GET', '/', HttpVersion10, CIMultiDict(),\n                                    True, False)\n        req = self.request_from_message(message)\n        resp = StreamResponse()\n        resp.start(req)\n        self.assertFalse(resp.keep_alive)\n\n        headers = CIMultiDict(Connection='keep-alive')\n        message = RawRequestMessage('GET', '/', HttpVersion10, headers,\n                                    False, False)\n        req = self.request_from_message(message)\n        resp = StreamResponse()\n        resp.start(req)\n        self.assertEqual(resp.keep_alive, True)\n\n    def test_keep_alive_http09(self):\n        headers = CIMultiDict(Connection='keep-alive')\n        message = RawRequestMessage('GET', '/', HttpVersion(0, 9), headers,\n                                    False, False)\n        req = self.request_from_message(message)\n        resp = StreamResponse()\n        resp.start(req)\n        self.assertFalse(resp.keep_alive)\n\n\nclass TestResponse(unittest.TestCase):\n\n    def setUp(self):\n        self.loop = asyncio.new_event_loop()\n        asyncio.set_event_loop(None)\n\n    def tearDown(self):\n        self.loop.close()\n\n    def make_request(self, method, path, headers=CIMultiDict()):\n        self.app = mock.Mock()\n        message = RawRequestMessage(method, path, HttpVersion11, headers,\n                                    False, False)\n        self.payload = mock.Mock()\n        self.transport = mock.Mock()\n        self.reader = mock.Mock()\n        self.writer = mock.Mock()\n        req = Request(self.app, message, self.payload,\n                      self.transport, self.reader, self.writer)\n        return req\n\n    def test_ctor(self):\n        resp = Response()\n\n        self.assertEqual(200, resp.status)\n        self.assertEqual('OK', resp.reason)\n        self.assertIsNone(resp.body)\n        self.assertEqual(0, resp.content_length)\n        self.assertEqual(CIMultiDict([('CONTENT-LENGTH', '0')]),\n                         resp.headers)\n\n    def test_ctor_with_headers_and_status(self):\n        resp = Response(body=b'body', status=201, headers={'Age': '12'})\n\n        self.assertEqual(201, resp.status)\n        self.assertEqual(b'body', resp.body)\n        self.assertEqual(4, resp.content_length)\n        self.assertEqual(CIMultiDict(\n            [('AGE', '12'),\n             ('CONTENT-LENGTH', '4')]), resp.headers)\n\n    def test_ctor_content_type(self):\n        resp = Response(content_type='application/json')\n\n        self.assertEqual(200, resp.status)\n        self.assertEqual('OK', resp.reason)\n        self.assertEqual(\n            CIMultiDict(\n                [('CONTENT-TYPE', 'application/json'),\n                 ('CONTENT-LENGTH', '0')]),\n            resp.headers)\n\n    def test_ctor_text_body_combined(self):\n        with self.assertRaises(ValueError):\n            Response(body=b'123', text='test text')\n\n    def test_ctor_text(self):\n        resp = Response(text='test text')\n\n        self.assertEqual(200, resp.status)\n        self.assertEqual('OK', resp.reason)\n        self.assertEqual(\n            CIMultiDict(\n                [('CONTENT-TYPE', 'text/plain; charset=utf-8'),\n                 ('CONTENT-LENGTH', '9')]),\n            resp.headers)\n\n        self.assertEqual(resp.body, b'test text')\n        self.assertEqual(resp.text, 'test text')\n\n    def test_assign_nonbyteish_body(self):\n        resp = Response(body=b'data')\n\n        with self.assertRaises(TypeError):\n            resp.body = 123\n        self.assertEqual(b'data', resp.body)\n        self.assertEqual(4, resp.content_length)\n\n    def test_assign_nonstr_text(self):\n        resp = Response(text='test')\n\n        with self.assertRaises(TypeError):\n            resp.text = b'123'\n        self.assertEqual(b'test', resp.body)\n        self.assertEqual(4, resp.content_length)\n\n    def test_send_headers_for_empty_body(self):\n        req = self.make_request('GET', '/')\n        resp = Response()\n\n        self.writer.drain.return_value = ()\n        buf = b''\n\n        def append(data):\n            nonlocal buf\n            buf += data\n\n        self.writer.write.side_effect = append\n\n        resp.start(req)\n        self.loop.run_until_complete(resp.write_eof())\n        txt = buf.decode('utf8')\n        self.assertRegex(txt, 'HTTP/1.1 200 OK\\r\\nCONTENT-LENGTH: 0\\r\\n'\n                         'CONNECTION: keep-alive\\r\\n'\n                         'DATE: .+\\r\\nSERVER: .+\\r\\n\\r\\n')\n\n    def test_render_with_body(self):\n        req = self.make_request('GET', '/')\n        resp = Response(body=b'data')\n\n        self.writer.drain.return_value = ()\n        buf = b''\n\n        def append(data):\n            nonlocal buf\n            buf += data\n\n        self.writer.write.side_effect = append\n\n        resp.start(req)\n        self.loop.run_until_complete(resp.write_eof())\n        txt = buf.decode('utf8')\n        self.assertRegex(txt, 'HTTP/1.1 200 OK\\r\\nCONTENT-LENGTH: 4\\r\\n'\n                         'CONNECTION: keep-alive\\r\\n'\n                         'DATE: .+\\r\\nSERVER: .+\\r\\n\\r\\ndata')\n\n    def test_send_set_cookie_header(self):\n        resp = Response()\n        resp.cookies['name'] = 'value'\n\n        req = self.make_request('GET', '/')\n        self.writer.drain.return_value = ()\n        buf = b''\n\n        def append(data):\n            nonlocal buf\n            buf += data\n\n        self.writer.write.side_effect = append\n\n        resp.start(req)\n        self.loop.run_until_complete(resp.write_eof())\n        txt = buf.decode('utf8')\n        self.assertRegex(txt, 'HTTP/1.1 200 OK\\r\\nCONTENT-LENGTH: 0\\r\\n'\n                         'SET-COOKIE: name=value\\r\\n'\n                         'CONNECTION: keep-alive\\r\\n'\n                         'DATE: .+\\r\\nSERVER: .+\\r\\n\\r\\n')\n\n    def test_set_text_with_content_type(self):\n        resp = Response()\n        resp.content_type = \"text/html\"\n        resp.text = \"text\"\n\n        self.assertEqual(\"text\", resp.text)\n        self.assertEqual(b\"text\", resp.body)\n        self.assertEqual(\"text/html\", resp.content_type)\n\n    def test_set_text_with_charset(self):\n        resp = Response()\n        resp.content_type = 'text/plain'\n        resp.charset = \"KOI8-R\"\n        resp.text = \"текст\"\n\n        self.assertEqual(\"текст\", resp.text)\n        self.assertEqual(\"текст\".encode('koi8-r'), resp.body)\n        self.assertEqual(\"koi8-r\", resp.charset)\n\n    def test_started_when_not_started(self):\n        resp = StreamResponse()\n        self.assertFalse(resp.started)\n\n    def test_started_when_started(self):\n        resp = StreamResponse()\n        resp.start(self.make_request('GET', '/'))\n        self.assertTrue(resp.started)\n\n    def test_drain_before_start(self):\n\n        @asyncio.coroutine\n        def go():\n            resp = StreamResponse()\n            with self.assertRaises(RuntimeError):\n                yield from resp.drain()\n\n        self.loop.run_until_complete(go())\n\n    def test_nonstr_text_in_ctor(self):\n        with self.assertRaises(TypeError):\n            Response(text=b'data')\n\n    def test_text_in_ctor_with_content_type(self):\n        resp = Response(text='data', content_type='text/html')\n        self.assertEqual('data', resp.text)\n        self.assertEqual('text/html', resp.content_type)\n\n    def test_text_in_ctor_with_content_type_header(self):\n        resp = Response(text='текст',\n                        headers={'Content-Type': 'text/html; charset=koi8-r'})\n        self.assertEqual('текст'.encode('koi8-r'), resp.body)\n        self.assertEqual('text/html', resp.content_type)\n        self.assertEqual('koi8-r', resp.charset)\n",
            "new_file_content": "import asyncio\nimport datetime\nimport unittest\nfrom unittest import mock\nfrom aiohttp import hdrs\nfrom aiohttp.multidict import CIMultiDict\nfrom aiohttp.web import ContentCoding, Request, StreamResponse, Response\nfrom aiohttp.protocol import HttpVersion, HttpVersion11, HttpVersion10\nfrom aiohttp.protocol import RawRequestMessage\n\n\nclass TestStreamResponse(unittest.TestCase):\n\n    def setUp(self):\n        self.loop = asyncio.new_event_loop()\n        asyncio.set_event_loop(None)\n\n    def tearDown(self):\n        self.loop.close()\n\n    def make_request(self, method, path, headers=CIMultiDict()):\n        message = RawRequestMessage(method, path, HttpVersion11, headers,\n                                    False, False)\n        return self.request_from_message(message)\n\n    def request_from_message(self, message):\n        self.app = mock.Mock()\n        self.payload = mock.Mock()\n        self.transport = mock.Mock()\n        self.reader = mock.Mock()\n        self.writer = mock.Mock()\n        req = Request(self.app, message, self.payload,\n                      self.transport, self.reader, self.writer)\n        return req\n\n    def test_ctor(self):\n        resp = StreamResponse()\n        self.assertEqual(200, resp.status)\n        self.assertIsNone(resp.keep_alive)\n\n    def test_content_length(self):\n        resp = StreamResponse()\n        self.assertIsNone(resp.content_length)\n\n    def test_content_length_setter(self):\n        resp = StreamResponse()\n\n        resp.content_length = 234\n        self.assertEqual(234, resp.content_length)\n\n    def test_drop_content_length_header_on_setting_len_to_None(self):\n        resp = StreamResponse()\n\n        resp.content_length = 1\n        self.assertEqual(\"1\", resp.headers['Content-Length'])\n        resp.content_length = None\n        self.assertNotIn('Content-Length', resp.headers)\n\n    def test_set_content_length_to_None_on_non_set(self):\n        resp = StreamResponse()\n\n        resp.content_length = None\n        self.assertNotIn('Content-Length', resp.headers)\n        resp.content_length = None\n        self.assertNotIn('Content-Length', resp.headers)\n\n    def test_setting_content_type(self):\n        resp = StreamResponse()\n\n        resp.content_type = 'text/html'\n        self.assertEqual('text/html', resp.headers['content-type'])\n\n    def test_setting_charset(self):\n        resp = StreamResponse()\n\n        resp.content_type = 'text/html'\n        resp.charset = 'koi8-r'\n        self.assertEqual('text/html; charset=koi8-r',\n                         resp.headers['content-type'])\n\n    def test_default_charset(self):\n        resp = StreamResponse()\n\n        self.assertIsNone(resp.charset)\n\n    def test_reset_charset(self):\n        resp = StreamResponse()\n\n        resp.content_type = 'text/html'\n        resp.charset = None\n        self.assertIsNone(resp.charset)\n\n    def test_reset_charset_after_setting(self):\n        resp = StreamResponse()\n\n        resp.content_type = 'text/html'\n        resp.charset = 'koi8-r'\n        resp.charset = None\n        self.assertIsNone(resp.charset)\n\n    def test_charset_without_content_type(self):\n        resp = StreamResponse()\n\n        with self.assertRaises(RuntimeError):\n            resp.charset = 'koi8-r'\n\n    def test_last_modified_initial(self):\n        resp = StreamResponse()\n        self.assertIsNone(resp.last_modified)\n\n    def test_last_modified_string(self):\n        resp = StreamResponse()\n\n        dt = datetime.datetime(1990, 1, 2, 3, 4, 5, 0, datetime.timezone.utc)\n        resp.last_modified = 'Mon, 2 Jan 1990 03:04:05 GMT'\n        self.assertEqual(resp.last_modified, dt)\n\n    def test_last_modified_timestamp(self):\n        resp = StreamResponse()\n\n        dt = datetime.datetime(1970, 1, 1, 0, 0, 0, 0, datetime.timezone.utc)\n\n        resp.last_modified = 0\n        self.assertEqual(resp.last_modified, dt)\n\n        resp.last_modified = 0.0\n        self.assertEqual(resp.last_modified, dt)\n\n    def test_last_modified_datetime(self):\n        resp = StreamResponse()\n\n        dt = datetime.datetime(2001, 2, 3, 4, 5, 6, 0, datetime.timezone.utc)\n        resp.last_modified = dt\n        self.assertEqual(resp.last_modified, dt)\n\n    def test_last_modified_reset(self):\n        resp = StreamResponse()\n\n        resp.last_modified = 0\n        resp.last_modified = None\n        self.assertEqual(resp.last_modified, None)\n\n    @mock.patch('aiohttp.web_reqrep.ResponseImpl')\n    def test_start(self, ResponseImpl):\n        req = self.make_request('GET', '/')\n        resp = StreamResponse()\n        self.assertIsNone(resp.keep_alive)\n\n        msg = resp.start(req)\n\n        self.assertTrue(msg.send_headers.called)\n        self.assertIs(msg, resp.start(req))\n\n        self.assertTrue(resp.keep_alive)\n\n        req2 = self.make_request('GET', '/')\n        with self.assertRaises(RuntimeError):\n            resp.start(req2)\n\n    @mock.patch('aiohttp.web_reqrep.ResponseImpl')\n    def test_chunked_encoding(self, ResponseImpl):\n        req = self.make_request('GET', '/')\n        resp = StreamResponse()\n        self.assertFalse(resp.chunked)\n\n        resp.enable_chunked_encoding()\n        self.assertTrue(resp.chunked)\n\n        msg = resp.start(req)\n        self.assertTrue(msg.chunked)\n\n    @mock.patch('aiohttp.web_reqrep.ResponseImpl')\n    def test_chunk_size(self, ResponseImpl):\n        req = self.make_request('GET', '/')\n        resp = StreamResponse()\n        self.assertFalse(resp.chunked)\n\n        resp.enable_chunked_encoding(chunk_size=8192)\n        self.assertTrue(resp.chunked)\n\n        msg = resp.start(req)\n        self.assertTrue(msg.chunked)\n        msg.add_chunking_filter.assert_called_with(8192)\n        self.assertIsNotNone(msg.filter)\n\n    @mock.patch('aiohttp.web_reqrep.ResponseImpl')\n    def test_compression_no_accept(self, ResponseImpl):\n        req = self.make_request('GET', '/')\n        resp = StreamResponse()\n        self.assertFalse(resp.chunked)\n\n        self.assertFalse(resp.compression)\n        resp.enable_compression()\n        self.assertTrue(resp.compression)\n\n        msg = resp.start(req)\n        self.assertFalse(msg.add_compression_filter.called)\n\n    @mock.patch('aiohttp.web_reqrep.ResponseImpl')\n    def test_force_compression_no_accept_backwards_compat(self, ResponseImpl):\n        req = self.make_request('GET', '/')\n        resp = StreamResponse()\n        self.assertFalse(resp.chunked)\n\n        self.assertFalse(resp.compression)\n        resp.enable_compression(force=True)\n        self.assertTrue(resp.compression)\n\n        msg = resp.start(req)\n        self.assertTrue(msg.add_compression_filter.called)\n        self.assertIsNotNone(msg.filter)\n\n    @mock.patch('aiohttp.web_reqrep.ResponseImpl')\n    def test_force_compression_false_backwards_compat(self, ResponseImpl):\n        req = self.make_request('GET', '/')\n        resp = StreamResponse()\n\n        self.assertFalse(resp.compression)\n        resp.enable_compression(force=False)\n        self.assertTrue(resp.compression)\n\n        msg = resp.start(req)\n        self.assertFalse(msg.add_compression_filter.called)\n\n    @mock.patch('aiohttp.web_reqrep.ResponseImpl')\n    def test_compression_default_coding(self, ResponseImpl):\n        req = self.make_request(\n            'GET', '/',\n            headers=CIMultiDict({hdrs.ACCEPT_ENCODING: 'gzip, deflate'}))\n        resp = StreamResponse()\n        self.assertFalse(resp.chunked)\n\n        self.assertFalse(resp.compression)\n        resp.enable_compression()\n        self.assertTrue(resp.compression)\n\n        msg = resp.start(req)\n        msg.add_compression_filter.assert_called_with('deflate')\n        self.assertEqual('deflate', resp.headers.get(hdrs.CONTENT_ENCODING))\n        self.assertIsNotNone(msg.filter)\n\n    @mock.patch('aiohttp.web_reqrep.ResponseImpl')\n    def test_force_compression_deflate(self, ResponseImpl):\n        req = self.make_request(\n            'GET', '/',\n            headers=CIMultiDict({hdrs.ACCEPT_ENCODING: 'gzip, deflate'}))\n        resp = StreamResponse()\n\n        resp.enable_compression(ContentCoding.deflate)\n        self.assertTrue(resp.compression)\n\n        msg = resp.start(req)\n        msg.add_compression_filter.assert_called_with('deflate')\n        self.assertEqual('deflate', resp.headers.get(hdrs.CONTENT_ENCODING))\n\n    @mock.patch('aiohttp.web_reqrep.ResponseImpl')\n    def test_force_compression_no_accept_deflate(self, ResponseImpl):\n        req = self.make_request('GET', '/')\n        resp = StreamResponse()\n\n        resp.enable_compression(ContentCoding.deflate)\n        self.assertTrue(resp.compression)\n\n        msg = resp.start(req)\n        msg.add_compression_filter.assert_called_with('deflate')\n        self.assertEqual('deflate', resp.headers.get(hdrs.CONTENT_ENCODING))\n\n    @mock.patch('aiohttp.web_reqrep.ResponseImpl')\n    def test_force_compression_gzip(self, ResponseImpl):\n        req = self.make_request(\n            'GET', '/',\n            headers=CIMultiDict({hdrs.ACCEPT_ENCODING: 'gzip, deflate'}))\n        resp = StreamResponse()\n\n        resp.enable_compression(ContentCoding.gzip)\n        self.assertTrue(resp.compression)\n\n        msg = resp.start(req)\n        msg.add_compression_filter.assert_called_with('gzip')\n        self.assertEqual('gzip', resp.headers.get(hdrs.CONTENT_ENCODING))\n\n    @mock.patch('aiohttp.web_reqrep.ResponseImpl')\n    def test_force_compression_no_accept_gzip(self, ResponseImpl):\n        req = self.make_request('GET', '/')\n        resp = StreamResponse()\n\n        resp.enable_compression(ContentCoding.gzip)\n        self.assertTrue(resp.compression)\n\n        msg = resp.start(req)\n        msg.add_compression_filter.assert_called_with('gzip')\n        self.assertEqual('gzip', resp.headers.get(hdrs.CONTENT_ENCODING))\n\n    def test_write_non_byteish(self):\n        resp = StreamResponse()\n        resp.start(self.make_request('GET', '/'))\n\n        with self.assertRaises(AssertionError):\n            resp.write(123)\n\n    def test_write_before_start(self):\n        resp = StreamResponse()\n\n        with self.assertRaises(RuntimeError):\n            resp.write(b'data')\n\n    def test_cannot_write_after_eof(self):\n        resp = StreamResponse()\n        resp.start(self.make_request('GET', '/'))\n\n        resp.write(b'data')\n        self.writer.drain.return_value = ()\n        self.loop.run_until_complete(resp.write_eof())\n        self.writer.write.reset_mock()\n\n        with self.assertRaises(RuntimeError):\n            resp.write(b'next data')\n        self.assertFalse(self.writer.write.called)\n\n    def test_cannot_write_eof_before_headers(self):\n        resp = StreamResponse()\n\n        with self.assertRaises(RuntimeError):\n            self.loop.run_until_complete(resp.write_eof())\n\n    def test_cannot_write_eof_twice(self):\n        resp = StreamResponse()\n        resp.start(self.make_request('GET', '/'))\n\n        resp.write(b'data')\n        self.writer.drain.return_value = ()\n        self.loop.run_until_complete(resp.write_eof())\n        self.assertTrue(self.writer.write.called)\n\n        self.writer.write.reset_mock()\n        self.loop.run_until_complete(resp.write_eof())\n        self.assertFalse(self.writer.write.called)\n\n    def test_write_returns_drain(self):\n        resp = StreamResponse()\n        resp.start(self.make_request('GET', '/'))\n\n        self.assertEqual((), resp.write(b'data'))\n\n    def test_write_returns_empty_tuple_on_empty_data(self):\n        resp = StreamResponse()\n        resp.start(self.make_request('GET', '/'))\n\n        self.assertEqual((), resp.write(b''))\n\n    def test_force_close(self):\n        resp = StreamResponse()\n\n        self.assertIsNone(resp.keep_alive)\n        resp.force_close()\n        self.assertFalse(resp.keep_alive)\n\n    def test_response_cookies(self):\n        resp = StreamResponse()\n\n        self.assertEqual(resp.cookies, {})\n        self.assertEqual(str(resp.cookies), '')\n\n        resp.set_cookie('name', 'value')\n        self.assertEqual(str(resp.cookies), 'Set-Cookie: name=value; Path=/')\n        resp.set_cookie('name', 'other_value')\n        self.assertEqual(str(resp.cookies),\n                         'Set-Cookie: name=other_value; Path=/')\n\n        resp.cookies['name'] = 'another_other_value'\n        resp.cookies['name']['max-age'] = 10\n        self.assertEqual(\n            str(resp.cookies),\n            'Set-Cookie: name=another_other_value; Max-Age=10; Path=/')\n\n        resp.del_cookie('name')\n        self.assertEqual(\n            str(resp.cookies),\n            'Set-Cookie: name=; Max-Age=0; Path=/')\n\n        resp.set_cookie('name', 'value', domain='local.host', path=None)\n        self.assertEqual(str(resp.cookies),\n                         'Set-Cookie: name=value; Domain=local.host')\n\n    def test_response_cookie_path(self):\n        resp = StreamResponse()\n\n        self.assertEqual(resp.cookies, {})\n\n        resp.set_cookie('name', 'value', path='/some/path')\n        self.assertEqual(str(resp.cookies),\n                         'Set-Cookie: name=value; Path=/some/path')\n        resp.set_cookie('name', 'value', expires='123')\n        self.assertEqual(str(resp.cookies),\n                         'Set-Cookie: name=value; expires=123;'\n                         ' Path=/')\n        resp.set_cookie('name', 'value', domain='example.com',\n                        path='/home', expires='123', max_age='10',\n                        secure=True, httponly=True, version='2.0')\n        self.assertEqual(str(resp.cookies).lower(),\n                         'set-cookie: name=value; '\n                         'domain=example.com; '\n                         'expires=123; '\n                         'httponly; '\n                         'max-age=10; '\n                         'path=/home; '\n                         'secure; '\n                         'version=2.0')\n\n    def test_response_cookie__issue_del_cookie(self):\n        resp = StreamResponse()\n\n        self.assertEqual(resp.cookies, {})\n        self.assertEqual(str(resp.cookies), '')\n\n        resp.del_cookie('name')\n        self.assertEqual(str(resp.cookies),\n                         'Set-Cookie: name=; Max-Age=0; Path=/')\n\n    def test_cookie_set_after_del(self):\n        resp = StreamResponse()\n\n        resp.del_cookie('name')\n        resp.set_cookie('name', 'val')\n        # check for Max-Age dropped\n        self.assertEqual(str(resp.cookies),\n                         'Set-Cookie: name=val; Path=/')\n\n    def test_set_status_with_reason(self):\n        resp = StreamResponse()\n\n        resp.set_status(200, \"Everithing is fine!\")\n        self.assertEqual(200, resp.status)\n        self.assertEqual(\"Everithing is fine!\", resp.reason)\n\n    def test_start_force_close(self):\n        req = self.make_request('GET', '/')\n        resp = StreamResponse()\n        resp.force_close()\n        self.assertFalse(resp.keep_alive)\n\n        msg = resp.start(req)\n        self.assertFalse(resp.keep_alive)\n        self.assertTrue(msg.closing)\n\n    def test___repr__(self):\n        req = self.make_request('GET', '/path/to')\n        resp = StreamResponse(reason=301)\n        resp.start(req)\n        self.assertEqual(\"<StreamResponse 301 GET /path/to >\", repr(resp))\n\n    def test___repr__not_started(self):\n        resp = StreamResponse(reason=301)\n        self.assertEqual(\"<StreamResponse 301 not started>\", repr(resp))\n\n    def test_keep_alive_http10(self):\n        message = RawRequestMessage('GET', '/', HttpVersion10, CIMultiDict(),\n                                    True, False)\n        req = self.request_from_message(message)\n        resp = StreamResponse()\n        resp.start(req)\n        self.assertFalse(resp.keep_alive)\n\n        headers = CIMultiDict(Connection='keep-alive')\n        message = RawRequestMessage('GET', '/', HttpVersion10, headers,\n                                    False, False)\n        req = self.request_from_message(message)\n        resp = StreamResponse()\n        resp.start(req)\n        self.assertEqual(resp.keep_alive, True)\n\n    def test_keep_alive_http09(self):\n        headers = CIMultiDict(Connection='keep-alive')\n        message = RawRequestMessage('GET', '/', HttpVersion(0, 9), headers,\n                                    False, False)\n        req = self.request_from_message(message)\n        resp = StreamResponse()\n        resp.start(req)\n        self.assertFalse(resp.keep_alive)\n\n\nclass TestResponse(unittest.TestCase):\n\n    def setUp(self):\n        self.loop = asyncio.new_event_loop()\n        asyncio.set_event_loop(None)\n\n    def tearDown(self):\n        self.loop.close()\n\n    def make_request(self, method, path, headers=CIMultiDict()):\n        self.app = mock.Mock()\n        message = RawRequestMessage(method, path, HttpVersion11, headers,\n                                    False, False)\n        self.payload = mock.Mock()\n        self.transport = mock.Mock()\n        self.reader = mock.Mock()\n        self.writer = mock.Mock()\n        req = Request(self.app, message, self.payload,\n                      self.transport, self.reader, self.writer)\n        return req\n\n    def test_ctor(self):\n        resp = Response()\n\n        self.assertEqual(200, resp.status)\n        self.assertEqual('OK', resp.reason)\n        self.assertIsNone(resp.body)\n        self.assertEqual(0, resp.content_length)\n        self.assertEqual(CIMultiDict([('CONTENT-LENGTH', '0')]),\n                         resp.headers)\n\n    def test_ctor_with_headers_and_status(self):\n        resp = Response(body=b'body', status=201, headers={'Age': '12'})\n\n        self.assertEqual(201, resp.status)\n        self.assertEqual(b'body', resp.body)\n        self.assertEqual(4, resp.content_length)\n        self.assertEqual(CIMultiDict(\n            [('AGE', '12'),\n             ('CONTENT-LENGTH', '4')]), resp.headers)\n\n    def test_ctor_content_type(self):\n        resp = Response(content_type='application/json')\n\n        self.assertEqual(200, resp.status)\n        self.assertEqual('OK', resp.reason)\n        self.assertEqual(\n            CIMultiDict(\n                [('CONTENT-TYPE', 'application/json'),\n                 ('CONTENT-LENGTH', '0')]),\n            resp.headers)\n\n    def test_ctor_text_body_combined(self):\n        with self.assertRaises(ValueError):\n            Response(body=b'123', text='test text')\n\n    def test_ctor_text(self):\n        resp = Response(text='test text')\n\n        self.assertEqual(200, resp.status)\n        self.assertEqual('OK', resp.reason)\n        self.assertEqual(\n            CIMultiDict(\n                [('CONTENT-TYPE', 'text/plain; charset=utf-8'),\n                 ('CONTENT-LENGTH', '9')]),\n            resp.headers)\n\n        self.assertEqual(resp.body, b'test text')\n        self.assertEqual(resp.text, 'test text')\n\n    def test_assign_nonbyteish_body(self):\n        resp = Response(body=b'data')\n\n        with self.assertRaises(TypeError):\n            resp.body = 123\n        self.assertEqual(b'data', resp.body)\n        self.assertEqual(4, resp.content_length)\n\n    def test_assign_nonstr_text(self):\n        resp = Response(text='test')\n\n        with self.assertRaises(TypeError):\n            resp.text = b'123'\n        self.assertEqual(b'test', resp.body)\n        self.assertEqual(4, resp.content_length)\n\n    def test_send_headers_for_empty_body(self):\n        req = self.make_request('GET', '/')\n        resp = Response()\n\n        self.writer.drain.return_value = ()\n        buf = b''\n\n        def append(data):\n            nonlocal buf\n            buf += data\n\n        self.writer.write.side_effect = append\n\n        resp.start(req)\n        self.loop.run_until_complete(resp.write_eof())\n        txt = buf.decode('utf8')\n        self.assertRegex(txt, 'HTTP/1.1 200 OK\\r\\nCONTENT-LENGTH: 0\\r\\n'\n                         'CONNECTION: keep-alive\\r\\n'\n                         'DATE: .+\\r\\nSERVER: .+\\r\\n\\r\\n')\n\n    def test_render_with_body(self):\n        req = self.make_request('GET', '/')\n        resp = Response(body=b'data')\n\n        self.writer.drain.return_value = ()\n        buf = b''\n\n        def append(data):\n            nonlocal buf\n            buf += data\n\n        self.writer.write.side_effect = append\n\n        resp.start(req)\n        self.loop.run_until_complete(resp.write_eof())\n        txt = buf.decode('utf8')\n        self.assertRegex(txt, 'HTTP/1.1 200 OK\\r\\nCONTENT-LENGTH: 4\\r\\n'\n                         'CONNECTION: keep-alive\\r\\n'\n                         'DATE: .+\\r\\nSERVER: .+\\r\\n\\r\\ndata')\n\n    def test_send_set_cookie_header(self):\n        resp = Response()\n        resp.cookies['name'] = 'value'\n\n        req = self.make_request('GET', '/')\n        self.writer.drain.return_value = ()\n        buf = b''\n\n        def append(data):\n            nonlocal buf\n            buf += data\n\n        self.writer.write.side_effect = append\n\n        resp.start(req)\n        self.loop.run_until_complete(resp.write_eof())\n        txt = buf.decode('utf8')\n        self.assertRegex(txt, 'HTTP/1.1 200 OK\\r\\nCONTENT-LENGTH: 0\\r\\n'\n                         'SET-COOKIE: name=value\\r\\n'\n                         'CONNECTION: keep-alive\\r\\n'\n                         'DATE: .+\\r\\nSERVER: .+\\r\\n\\r\\n')\n\n    def test_set_text_with_content_type(self):\n        resp = Response()\n        resp.content_type = \"text/html\"\n        resp.text = \"text\"\n\n        self.assertEqual(\"text\", resp.text)\n        self.assertEqual(b\"text\", resp.body)\n        self.assertEqual(\"text/html\", resp.content_type)\n\n    def test_set_text_with_charset(self):\n        resp = Response()\n        resp.content_type = 'text/plain'\n        resp.charset = \"KOI8-R\"\n        resp.text = \"текст\"\n\n        self.assertEqual(\"текст\", resp.text)\n        self.assertEqual(\"текст\".encode('koi8-r'), resp.body)\n        self.assertEqual(\"koi8-r\", resp.charset)\n\n    def test_started_when_not_started(self):\n        resp = StreamResponse()\n        self.assertFalse(resp.started)\n\n    def test_started_when_started(self):\n        resp = StreamResponse()\n        resp.start(self.make_request('GET', '/'))\n        self.assertTrue(resp.started)\n\n    def test_drain_before_start(self):\n\n        @asyncio.coroutine\n        def go():\n            resp = StreamResponse()\n            with self.assertRaises(RuntimeError):\n                yield from resp.drain()\n\n        self.loop.run_until_complete(go())\n\n    def test_nonstr_text_in_ctor(self):\n        with self.assertRaises(TypeError):\n            Response(text=b'data')\n\n    def test_text_in_ctor_with_content_type(self):\n        resp = Response(text='data', content_type='text/html')\n        self.assertEqual('data', resp.text)\n        self.assertEqual('text/html', resp.content_type)\n\n    def test_text_in_ctor_with_content_type_header(self):\n        resp = Response(text='текст',\n                        headers={'Content-Type': 'text/html; charset=koi8-r'})\n        self.assertEqual('текст'.encode('koi8-r'), resp.body)\n        self.assertEqual('text/html', resp.content_type)\n        self.assertEqual('koi8-r', resp.charset)\n\n    def test_text_with_empty_payload(self):\n        resp = Response(status=200)\n        self.assertEqual(resp.body, None)\n        self.assertEqual(resp.text, None)\n",
            "header": {
                "file": {
                    "path": "tests/test_web_response.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "585448d4",
                "new_commit_hash": "3e30a5f2",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/tests/test_web_response.py"
            },
            "plus_file": {
                "path": "b/tests/test_web_response.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 680,
                            "length": 3
                        },
                        "new_range": {
                            "start": 680,
                            "length": 8
                        },
                        "section": "class TestResponse(unittest.TestCase):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        self.assertEqual('текст'.encode('koi8-r'), resp.body)",
                                "type": "context"
                            },
                            {
                                "content": "        self.assertEqual('text/html', resp.content_type)",
                                "type": "context"
                            },
                            {
                                "content": "        self.assertEqual('koi8-r', resp.charset)",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "    def test_text_with_empty_payload(self):",
                                "type": "added"
                            },
                            {
                                "content": "        resp = Response(status=200)",
                                "type": "added"
                            },
                            {
                                "content": "        self.assertEqual(resp.body, None)",
                                "type": "added"
                            },
                            {
                                "content": "        self.assertEqual(resp.text, None)",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "tests/test_web_response.py",
                            "type": "class",
                            "name": "TestResponse",
                            "content": "class TestResponse(unittest.TestCase):\n\n    def setUp(self):\n        self.loop = asyncio.new_event_loop()\n        asyncio.set_event_loop(None)\n\n    def tearDown(self):\n        self.loop.close()\n\n    def make_request(self, method, path, headers=CIMultiDict()):\n        self.app = mock.Mock()\n        message = RawRequestMessage(method, path, HttpVersion11, headers,\n                                    False, False)\n        self.payload = mock.Mock()\n        self.transport = mock.Mock()\n        self.reader = mock.Mock()\n        self.writer = mock.Mock()\n        req = Request(self.app, message, self.payload,\n                      self.transport, self.reader, self.writer)\n        return req\n\n    def test_ctor(self):\n        resp = Response()\n\n        self.assertEqual(200, resp.status)\n        self.assertEqual('OK', resp.reason)\n        self.assertIsNone(resp.body)\n        self.assertEqual(0, resp.content_length)\n        self.assertEqual(CIMultiDict([('CONTENT-LENGTH', '0')]),\n                         resp.headers)\n\n    def test_ctor_with_headers_and_status(self):\n        resp = Response(body=b'body', status=201, headers={'Age': '12'})\n\n        self.assertEqual(201, resp.status)\n        self.assertEqual(b'body', resp.body)\n        self.assertEqual(4, resp.content_length)\n        self.assertEqual(CIMultiDict(\n            [('AGE', '12'),\n             ('CONTENT-LENGTH', '4')]), resp.headers)\n\n    def test_ctor_content_type(self):\n        resp = Response(content_type='application/json')\n\n        self.assertEqual(200, resp.status)\n        self.assertEqual('OK', resp.reason)\n        self.assertEqual(\n            CIMultiDict(\n                [('CONTENT-TYPE', 'application/json'),\n                 ('CONTENT-LENGTH', '0')]),\n            resp.headers)\n\n    def test_ctor_text_body_combined(self):\n        with self.assertRaises(ValueError):\n            Response(body=b'123', text='test text')\n\n    def test_ctor_text(self):\n        resp = Response(text='test text')\n\n        self.assertEqual(200, resp.status)\n        self.assertEqual('OK', resp.reason)\n        self.assertEqual(\n            CIMultiDict(\n                [('CONTENT-TYPE', 'text/plain; charset=utf-8'),\n                 ('CONTENT-LENGTH', '9')]),\n            resp.headers)\n\n        self.assertEqual(resp.body, b'test text')\n        self.assertEqual(resp.text, 'test text')\n\n    def test_assign_nonbyteish_body(self):\n        resp = Response(body=b'data')\n\n        with self.assertRaises(TypeError):\n            resp.body = 123\n        self.assertEqual(b'data', resp.body)\n        self.assertEqual(4, resp.content_length)\n\n    def test_assign_nonstr_text(self):\n        resp = Response(text='test')\n\n        with self.assertRaises(TypeError):\n            resp.text = b'123'\n        self.assertEqual(b'test', resp.body)\n        self.assertEqual(4, resp.content_length)\n\n    def test_send_headers_for_empty_body(self):\n        req = self.make_request('GET', '/')\n        resp = Response()\n\n        self.writer.drain.return_value = ()\n        buf = b''\n\n        def append(data):\n            nonlocal buf\n            buf += data\n\n        self.writer.write.side_effect = append\n\n        resp.start(req)\n        self.loop.run_until_complete(resp.write_eof())\n        txt = buf.decode('utf8')\n        self.assertRegex(txt, 'HTTP/1.1 200 OK\\r\\nCONTENT-LENGTH: 0\\r\\n'\n                         'CONNECTION: keep-alive\\r\\n'\n                         'DATE: .+\\r\\nSERVER: .+\\r\\n\\r\\n')\n\n    def test_render_with_body(self):\n        req = self.make_request('GET', '/')\n        resp = Response(body=b'data')\n\n        self.writer.drain.return_value = ()\n        buf = b''\n\n        def append(data):\n            nonlocal buf\n            buf += data\n\n        self.writer.write.side_effect = append\n\n        resp.start(req)\n        self.loop.run_until_complete(resp.write_eof())\n        txt = buf.decode('utf8')\n        self.assertRegex(txt, 'HTTP/1.1 200 OK\\r\\nCONTENT-LENGTH: 4\\r\\n'\n                         'CONNECTION: keep-alive\\r\\n'\n                         'DATE: .+\\r\\nSERVER: .+\\r\\n\\r\\ndata')\n\n    def test_send_set_cookie_header(self):\n        resp = Response()\n        resp.cookies['name'] = 'value'\n\n        req = self.make_request('GET', '/')\n        self.writer.drain.return_value = ()\n        buf = b''\n\n        def append(data):\n            nonlocal buf\n            buf += data\n\n        self.writer.write.side_effect = append\n\n        resp.start(req)\n        self.loop.run_until_complete(resp.write_eof())\n        txt = buf.decode('utf8')\n        self.assertRegex(txt, 'HTTP/1.1 200 OK\\r\\nCONTENT-LENGTH: 0\\r\\n'\n                         'SET-COOKIE: name=value\\r\\n'\n                         'CONNECTION: keep-alive\\r\\n'\n                         'DATE: .+\\r\\nSERVER: .+\\r\\n\\r\\n')\n\n    def test_set_text_with_content_type(self):\n        resp = Response()\n        resp.content_type = \"text/html\"\n        resp.text = \"text\"\n\n        self.assertEqual(\"text\", resp.text)\n        self.assertEqual(b\"text\", resp.body)\n        self.assertEqual(\"text/html\", resp.content_type)\n\n    def test_set_text_with_charset(self):\n        resp = Response()\n        resp.content_type = 'text/plain'\n        resp.charset = \"KOI8-R\"\n        resp.text = \"текст\"\n\n        self.assertEqual(\"текст\", resp.text)\n        self.assertEqual(\"текст\".encode('koi8-r'), resp.body)\n        self.assertEqual(\"koi8-r\", resp.charset)\n\n    def test_started_when_not_started(self):\n        resp = StreamResponse()\n        self.assertFalse(resp.started)\n\n    def test_started_when_started(self):\n        resp = StreamResponse()\n        resp.start(self.make_request('GET', '/'))\n        self.assertTrue(resp.started)\n\n    def test_drain_before_start(self):\n\n        @asyncio.coroutine\n        def go():\n            resp = StreamResponse()\n            with self.assertRaises(RuntimeError):\n                yield from resp.drain()\n\n        self.loop.run_until_complete(go())\n\n    def test_nonstr_text_in_ctor(self):\n        with self.assertRaises(TypeError):\n            Response(text=b'data')\n\n    def test_text_in_ctor_with_content_type(self):\n        resp = Response(text='data', content_type='text/html')\n        self.assertEqual('data', resp.text)\n        self.assertEqual('text/html', resp.content_type)\n\n    def test_text_in_ctor_with_content_type_header(self):\n        resp = Response(text='текст',\n                        headers={'Content-Type': 'text/html; charset=koi8-r'})\n        self.assertEqual('текст'.encode('koi8-r'), resp.body)\n        self.assertEqual('text/html', resp.content_type)\n        self.assertEqual('koi8-r', resp.charset)\n\n    def test_text_with_empty_payload(self):\n        resp = Response(status=200)\n        self.assertEqual(resp.body, None)\n        self.assertEqual(resp.text, None)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 482,
                            "end_lineno": 687,
                            "parent": null
                        }
                    ],
                    "added_entities": [
                        {
                            "file_name": "tests/test_web_response.py",
                            "type": "method",
                            "name": "TestResponse.test_text_with_empty_payload",
                            "content": "class TestResponse(unittest.TestCase):\n\n    def setUp(self):\n        self.loop = asyncio.new_event_loop()\n        asyncio.set_event_loop(None)\n\n    def tearDown(self):\n        self.loop.close()\n\n    def make_request(self, method, path, headers=CIMultiDict()):\n        self.app = mock.Mock()\n        message = RawRequestMessage(method, path, HttpVersion11, headers,\n                                    False, False)\n        self.payload = mock.Mock()\n        self.transport = mock.Mock()\n        self.reader = mock.Mock()\n        self.writer = mock.Mock()\n        req = Request(self.app, message, self.payload,\n                      self.transport, self.reader, self.writer)\n        return req\n\n    def test_ctor(self):\n        resp = Response()\n\n        self.assertEqual(200, resp.status)\n        self.assertEqual('OK', resp.reason)\n        self.assertIsNone(resp.body)\n        self.assertEqual(0, resp.content_length)\n        self.assertEqual(CIMultiDict([('CONTENT-LENGTH', '0')]),\n                         resp.headers)\n\n    def test_ctor_with_headers_and_status(self):\n        resp = Response(body=b'body', status=201, headers={'Age': '12'})\n\n        self.assertEqual(201, resp.status)\n        self.assertEqual(b'body', resp.body)\n        self.assertEqual(4, resp.content_length)\n        self.assertEqual(CIMultiDict(\n            [('AGE', '12'),\n             ('CONTENT-LENGTH', '4')]), resp.headers)\n\n    def test_ctor_content_type(self):\n        resp = Response(content_type='application/json')\n\n        self.assertEqual(200, resp.status)\n        self.assertEqual('OK', resp.reason)\n        self.assertEqual(\n            CIMultiDict(\n                [('CONTENT-TYPE', 'application/json'),\n                 ('CONTENT-LENGTH', '0')]),\n            resp.headers)\n\n    def test_ctor_text_body_combined(self):\n        with self.assertRaises(ValueError):\n            Response(body=b'123', text='test text')\n\n    def test_ctor_text(self):\n        resp = Response(text='test text')\n\n        self.assertEqual(200, resp.status)\n        self.assertEqual('OK', resp.reason)\n        self.assertEqual(\n            CIMultiDict(\n                [('CONTENT-TYPE', 'text/plain; charset=utf-8'),\n                 ('CONTENT-LENGTH', '9')]),\n            resp.headers)\n\n        self.assertEqual(resp.body, b'test text')\n        self.assertEqual(resp.text, 'test text')\n\n    def test_assign_nonbyteish_body(self):\n        resp = Response(body=b'data')\n\n        with self.assertRaises(TypeError):\n            resp.body = 123\n        self.assertEqual(b'data', resp.body)\n        self.assertEqual(4, resp.content_length)\n\n    def test_assign_nonstr_text(self):\n        resp = Response(text='test')\n\n        with self.assertRaises(TypeError):\n            resp.text = b'123'\n        self.assertEqual(b'test', resp.body)\n        self.assertEqual(4, resp.content_length)\n\n    def test_send_headers_for_empty_body(self):\n        req = self.make_request('GET', '/')\n        resp = Response()\n\n        self.writer.drain.return_value = ()\n        buf = b''\n\n        def append(data):\n            nonlocal buf\n            buf += data\n\n        self.writer.write.side_effect = append\n\n        resp.start(req)\n        self.loop.run_until_complete(resp.write_eof())\n        txt = buf.decode('utf8')\n        self.assertRegex(txt, 'HTTP/1.1 200 OK\\r\\nCONTENT-LENGTH: 0\\r\\n'\n                         'CONNECTION: keep-alive\\r\\n'\n                         'DATE: .+\\r\\nSERVER: .+\\r\\n\\r\\n')\n\n    def test_render_with_body(self):\n        req = self.make_request('GET', '/')\n        resp = Response(body=b'data')\n\n        self.writer.drain.return_value = ()\n        buf = b''\n\n        def append(data):\n            nonlocal buf\n            buf += data\n\n        self.writer.write.side_effect = append\n\n        resp.start(req)\n        self.loop.run_until_complete(resp.write_eof())\n        txt = buf.decode('utf8')\n        self.assertRegex(txt, 'HTTP/1.1 200 OK\\r\\nCONTENT-LENGTH: 4\\r\\n'\n                         'CONNECTION: keep-alive\\r\\n'\n                         'DATE: .+\\r\\nSERVER: .+\\r\\n\\r\\ndata')\n\n    def test_send_set_cookie_header(self):\n        resp = Response()\n        resp.cookies['name'] = 'value'\n\n        req = self.make_request('GET', '/')\n        self.writer.drain.return_value = ()\n        buf = b''\n\n        def append(data):\n            nonlocal buf\n            buf += data\n\n        self.writer.write.side_effect = append\n\n        resp.start(req)\n        self.loop.run_until_complete(resp.write_eof())\n        txt = buf.decode('utf8')\n        self.assertRegex(txt, 'HTTP/1.1 200 OK\\r\\nCONTENT-LENGTH: 0\\r\\n'\n                         'SET-COOKIE: name=value\\r\\n'\n                         'CONNECTION: keep-alive\\r\\n'\n                         'DATE: .+\\r\\nSERVER: .+\\r\\n\\r\\n')\n\n    def test_set_text_with_content_type(self):\n        resp = Response()\n        resp.content_type = \"text/html\"\n        resp.text = \"text\"\n\n        self.assertEqual(\"text\", resp.text)\n        self.assertEqual(b\"text\", resp.body)\n        self.assertEqual(\"text/html\", resp.content_type)\n\n    def test_set_text_with_charset(self):\n        resp = Response()\n        resp.content_type = 'text/plain'\n        resp.charset = \"KOI8-R\"\n        resp.text = \"текст\"\n\n        self.assertEqual(\"текст\", resp.text)\n        self.assertEqual(\"текст\".encode('koi8-r'), resp.body)\n        self.assertEqual(\"koi8-r\", resp.charset)\n\n    def test_started_when_not_started(self):\n        resp = StreamResponse()\n        self.assertFalse(resp.started)\n\n    def test_started_when_started(self):\n        resp = StreamResponse()\n        resp.start(self.make_request('GET', '/'))\n        self.assertTrue(resp.started)\n\n    def test_drain_before_start(self):\n\n        @asyncio.coroutine\n        def go():\n            resp = StreamResponse()\n            with self.assertRaises(RuntimeError):\n                yield from resp.drain()\n\n        self.loop.run_until_complete(go())\n\n    def test_nonstr_text_in_ctor(self):\n        with self.assertRaises(TypeError):\n            Response(text=b'data')\n\n    def test_text_in_ctor_with_content_type(self):\n        resp = Response(text='data', content_type='text/html')\n        self.assertEqual('data', resp.text)\n        self.assertEqual('text/html', resp.content_type)\n\n    def test_text_in_ctor_with_content_type_header(self):\n        resp = Response(text='текст',\n                        headers={'Content-Type': 'text/html; charset=koi8-r'})\n        self.assertEqual('текст'.encode('koi8-r'), resp.body)\n        self.assertEqual('text/html', resp.content_type)\n        self.assertEqual('koi8-r', resp.charset)\n\n    def test_text_with_empty_payload(self):\n        resp = Response(status=200)\n        self.assertEqual(resp.body, None)\n        self.assertEqual(resp.text, None)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 684,
                            "end_lineno": 687,
                            "parent": {
                                "file_name": "tests/test_web_response.py",
                                "type": "class",
                                "name": "TestResponse",
                                "content": "class TestResponse(unittest.TestCase):\n\n    def setUp(self):\n        self.loop = asyncio.new_event_loop()\n        asyncio.set_event_loop(None)\n\n    def tearDown(self):\n        self.loop.close()\n\n    def make_request(self, method, path, headers=CIMultiDict()):\n        self.app = mock.Mock()\n        message = RawRequestMessage(method, path, HttpVersion11, headers,\n                                    False, False)\n        self.payload = mock.Mock()\n        self.transport = mock.Mock()\n        self.reader = mock.Mock()\n        self.writer = mock.Mock()\n        req = Request(self.app, message, self.payload,\n                      self.transport, self.reader, self.writer)\n        return req\n\n    def test_ctor(self):\n        resp = Response()\n\n        self.assertEqual(200, resp.status)\n        self.assertEqual('OK', resp.reason)\n        self.assertIsNone(resp.body)\n        self.assertEqual(0, resp.content_length)\n        self.assertEqual(CIMultiDict([('CONTENT-LENGTH', '0')]),\n                         resp.headers)\n\n    def test_ctor_with_headers_and_status(self):\n        resp = Response(body=b'body', status=201, headers={'Age': '12'})\n\n        self.assertEqual(201, resp.status)\n        self.assertEqual(b'body', resp.body)\n        self.assertEqual(4, resp.content_length)\n        self.assertEqual(CIMultiDict(\n            [('AGE', '12'),\n             ('CONTENT-LENGTH', '4')]), resp.headers)\n\n    def test_ctor_content_type(self):\n        resp = Response(content_type='application/json')\n\n        self.assertEqual(200, resp.status)\n        self.assertEqual('OK', resp.reason)\n        self.assertEqual(\n            CIMultiDict(\n                [('CONTENT-TYPE', 'application/json'),\n                 ('CONTENT-LENGTH', '0')]),\n            resp.headers)\n\n    def test_ctor_text_body_combined(self):\n        with self.assertRaises(ValueError):\n            Response(body=b'123', text='test text')\n\n    def test_ctor_text(self):\n        resp = Response(text='test text')\n\n        self.assertEqual(200, resp.status)\n        self.assertEqual('OK', resp.reason)\n        self.assertEqual(\n            CIMultiDict(\n                [('CONTENT-TYPE', 'text/plain; charset=utf-8'),\n                 ('CONTENT-LENGTH', '9')]),\n            resp.headers)\n\n        self.assertEqual(resp.body, b'test text')\n        self.assertEqual(resp.text, 'test text')\n\n    def test_assign_nonbyteish_body(self):\n        resp = Response(body=b'data')\n\n        with self.assertRaises(TypeError):\n            resp.body = 123\n        self.assertEqual(b'data', resp.body)\n        self.assertEqual(4, resp.content_length)\n\n    def test_assign_nonstr_text(self):\n        resp = Response(text='test')\n\n        with self.assertRaises(TypeError):\n            resp.text = b'123'\n        self.assertEqual(b'test', resp.body)\n        self.assertEqual(4, resp.content_length)\n\n    def test_send_headers_for_empty_body(self):\n        req = self.make_request('GET', '/')\n        resp = Response()\n\n        self.writer.drain.return_value = ()\n        buf = b''\n\n        def append(data):\n            nonlocal buf\n            buf += data\n\n        self.writer.write.side_effect = append\n\n        resp.start(req)\n        self.loop.run_until_complete(resp.write_eof())\n        txt = buf.decode('utf8')\n        self.assertRegex(txt, 'HTTP/1.1 200 OK\\r\\nCONTENT-LENGTH: 0\\r\\n'\n                         'CONNECTION: keep-alive\\r\\n'\n                         'DATE: .+\\r\\nSERVER: .+\\r\\n\\r\\n')\n\n    def test_render_with_body(self):\n        req = self.make_request('GET', '/')\n        resp = Response(body=b'data')\n\n        self.writer.drain.return_value = ()\n        buf = b''\n\n        def append(data):\n            nonlocal buf\n            buf += data\n\n        self.writer.write.side_effect = append\n\n        resp.start(req)\n        self.loop.run_until_complete(resp.write_eof())\n        txt = buf.decode('utf8')\n        self.assertRegex(txt, 'HTTP/1.1 200 OK\\r\\nCONTENT-LENGTH: 4\\r\\n'\n                         'CONNECTION: keep-alive\\r\\n'\n                         'DATE: .+\\r\\nSERVER: .+\\r\\n\\r\\ndata')\n\n    def test_send_set_cookie_header(self):\n        resp = Response()\n        resp.cookies['name'] = 'value'\n\n        req = self.make_request('GET', '/')\n        self.writer.drain.return_value = ()\n        buf = b''\n\n        def append(data):\n            nonlocal buf\n            buf += data\n\n        self.writer.write.side_effect = append\n\n        resp.start(req)\n        self.loop.run_until_complete(resp.write_eof())\n        txt = buf.decode('utf8')\n        self.assertRegex(txt, 'HTTP/1.1 200 OK\\r\\nCONTENT-LENGTH: 0\\r\\n'\n                         'SET-COOKIE: name=value\\r\\n'\n                         'CONNECTION: keep-alive\\r\\n'\n                         'DATE: .+\\r\\nSERVER: .+\\r\\n\\r\\n')\n\n    def test_set_text_with_content_type(self):\n        resp = Response()\n        resp.content_type = \"text/html\"\n        resp.text = \"text\"\n\n        self.assertEqual(\"text\", resp.text)\n        self.assertEqual(b\"text\", resp.body)\n        self.assertEqual(\"text/html\", resp.content_type)\n\n    def test_set_text_with_charset(self):\n        resp = Response()\n        resp.content_type = 'text/plain'\n        resp.charset = \"KOI8-R\"\n        resp.text = \"текст\"\n\n        self.assertEqual(\"текст\", resp.text)\n        self.assertEqual(\"текст\".encode('koi8-r'), resp.body)\n        self.assertEqual(\"koi8-r\", resp.charset)\n\n    def test_started_when_not_started(self):\n        resp = StreamResponse()\n        self.assertFalse(resp.started)\n\n    def test_started_when_started(self):\n        resp = StreamResponse()\n        resp.start(self.make_request('GET', '/'))\n        self.assertTrue(resp.started)\n\n    def test_drain_before_start(self):\n\n        @asyncio.coroutine\n        def go():\n            resp = StreamResponse()\n            with self.assertRaises(RuntimeError):\n                yield from resp.drain()\n\n        self.loop.run_until_complete(go())\n\n    def test_nonstr_text_in_ctor(self):\n        with self.assertRaises(TypeError):\n            Response(text=b'data')\n\n    def test_text_in_ctor_with_content_type(self):\n        resp = Response(text='data', content_type='text/html')\n        self.assertEqual('data', resp.text)\n        self.assertEqual('text/html', resp.content_type)\n\n    def test_text_in_ctor_with_content_type_header(self):\n        resp = Response(text='текст',\n                        headers={'Content-Type': 'text/html; charset=koi8-r'})\n        self.assertEqual('текст'.encode('koi8-r'), resp.body)\n        self.assertEqual('text/html', resp.content_type)\n        self.assertEqual('koi8-r', resp.charset)\n\n    def test_text_with_empty_payload(self):\n        resp = Response(status=200)\n        self.assertEqual(resp.body, None)\n        self.assertEqual(resp.text, None)",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 482,
                                "end_lineno": 687,
                                "parent": null
                            }
                        }
                    ],
                    "deleted_entities": []
                }
            ]
        }
    ],
    "old_commit_hash": "4284bed28ae27d5d2bf51cabf2bd3dd2e78a5ea4^",
    "new_commit_hash": "4284bed28ae27d5d2bf51cabf2bd3dd2e78a5ea4",
    "commit_message": "response.text returns None if response.body is None",
    "commit_date": "2015-06-25T21:42:41+03:00",
    "metadata": {}
}
{
    "repo_name": "aiohttp",
    "new_commit_hash": "4284bed28ae27d5d2bf51cabf2bd3dd2e78a5ea4",
    "test_file_codes": [
        "import asyncio\nimport datetime\nimport unittest\nfrom unittest import mock\nfrom aiohttp import hdrs\nfrom aiohttp.multidict import CIMultiDict\nfrom aiohttp.web import ContentCoding, Request, StreamResponse, Response\nfrom aiohttp.protocol import HttpVersion, HttpVersion11, HttpVersion10\nfrom aiohttp.protocol import RawRequestMessage\n\n\nclass TestStreamResponse(unittest.TestCase):\n\n    def setUp(self):\n        self.loop = asyncio.new_event_loop()\n        asyncio.set_event_loop(None)\n\n    def tearDown(self):\n        self.loop.close()\n\n    def make_request(self, method, path, headers=CIMultiDict()):\n        message = RawRequestMessage(method, path, HttpVersion11, headers,\n                                    False, False)\n        return self.request_from_message(message)\n\n    def request_from_message(self, message):\n        self.app = mock.Mock()\n        self.payload = mock.Mock()\n        self.transport = mock.Mock()\n        self.reader = mock.Mock()\n        self.writer = mock.Mock()\n        req = Request(self.app, message, self.payload,\n                      self.transport, self.reader, self.writer)\n        return req\n\n    def test_ctor(self):\n        resp = StreamResponse()\n        self.assertEqual(200, resp.status)\n        self.assertIsNone(resp.keep_alive)\n\n    def test_content_length(self):\n        resp = StreamResponse()\n        self.assertIsNone(resp.content_length)\n\n    def test_content_length_setter(self):\n        resp = StreamResponse()\n\n        resp.content_length = 234\n        self.assertEqual(234, resp.content_length)\n\n    def test_drop_content_length_header_on_setting_len_to_None(self):\n        resp = StreamResponse()\n\n        resp.content_length = 1\n        self.assertEqual(\"1\", resp.headers['Content-Length'])\n        resp.content_length = None\n        self.assertNotIn('Content-Length', resp.headers)\n\n    def test_set_content_length_to_None_on_non_set(self):\n        resp = StreamResponse()\n\n        resp.content_length = None\n        self.assertNotIn('Content-Length', resp.headers)\n        resp.content_length = None\n        self.assertNotIn('Content-Length', resp.headers)\n\n    def test_setting_content_type(self):\n        resp = StreamResponse()\n\n        resp.content_type = 'text/html'\n        self.assertEqual('text/html', resp.headers['content-type'])\n\n    def test_setting_charset(self):\n        resp = StreamResponse()\n\n        resp.content_type = 'text/html'\n        resp.charset = 'koi8-r'\n        self.assertEqual('text/html; charset=koi8-r',\n                         resp.headers['content-type'])\n\n    def test_default_charset(self):\n        resp = StreamResponse()\n\n        self.assertIsNone(resp.charset)\n\n    def test_reset_charset(self):\n        resp = StreamResponse()\n\n        resp.content_type = 'text/html'\n        resp.charset = None\n        self.assertIsNone(resp.charset)\n\n    def test_reset_charset_after_setting(self):\n        resp = StreamResponse()\n\n        resp.content_type = 'text/html'\n        resp.charset = 'koi8-r'\n        resp.charset = None\n        self.assertIsNone(resp.charset)\n\n    def test_charset_without_content_type(self):\n        resp = StreamResponse()\n\n        with self.assertRaises(RuntimeError):\n            resp.charset = 'koi8-r'\n\n    def test_last_modified_initial(self):\n        resp = StreamResponse()\n        self.assertIsNone(resp.last_modified)\n\n    def test_last_modified_string(self):\n        resp = StreamResponse()\n\n        dt = datetime.datetime(1990, 1, 2, 3, 4, 5, 0, datetime.timezone.utc)\n        resp.last_modified = 'Mon, 2 Jan 1990 03:04:05 GMT'\n        self.assertEqual(resp.last_modified, dt)\n\n    def test_last_modified_timestamp(self):\n        resp = StreamResponse()\n\n        dt = datetime.datetime(1970, 1, 1, 0, 0, 0, 0, datetime.timezone.utc)\n\n        resp.last_modified = 0\n        self.assertEqual(resp.last_modified, dt)\n\n        resp.last_modified = 0.0\n        self.assertEqual(resp.last_modified, dt)\n\n    def test_last_modified_datetime(self):\n        resp = StreamResponse()\n\n        dt = datetime.datetime(2001, 2, 3, 4, 5, 6, 0, datetime.timezone.utc)\n        resp.last_modified = dt\n        self.assertEqual(resp.last_modified, dt)\n\n    def test_last_modified_reset(self):\n        resp = StreamResponse()\n\n        resp.last_modified = 0\n        resp.last_modified = None\n        self.assertEqual(resp.last_modified, None)\n\n    @mock.patch('aiohttp.web_reqrep.ResponseImpl')\n    def test_start(self, ResponseImpl):\n        req = self.make_request('GET', '/')\n        resp = StreamResponse()\n        self.assertIsNone(resp.keep_alive)\n\n        msg = resp.start(req)\n\n        self.assertTrue(msg.send_headers.called)\n        self.assertIs(msg, resp.start(req))\n\n        self.assertTrue(resp.keep_alive)\n\n        req2 = self.make_request('GET', '/')\n        with self.assertRaises(RuntimeError):\n            resp.start(req2)\n\n    @mock.patch('aiohttp.web_reqrep.ResponseImpl')\n    def test_chunked_encoding(self, ResponseImpl):\n        req = self.make_request('GET', '/')\n        resp = StreamResponse()\n        self.assertFalse(resp.chunked)\n\n        resp.enable_chunked_encoding()\n        self.assertTrue(resp.chunked)\n\n        msg = resp.start(req)\n        self.assertTrue(msg.chunked)\n\n    @mock.patch('aiohttp.web_reqrep.ResponseImpl')\n    def test_chunk_size(self, ResponseImpl):\n        req = self.make_request('GET', '/')\n        resp = StreamResponse()\n        self.assertFalse(resp.chunked)\n\n        resp.enable_chunked_encoding(chunk_size=8192)\n        self.assertTrue(resp.chunked)\n\n        msg = resp.start(req)\n        self.assertTrue(msg.chunked)\n        msg.add_chunking_filter.assert_called_with(8192)\n        self.assertIsNotNone(msg.filter)\n\n    @mock.patch('aiohttp.web_reqrep.ResponseImpl')\n    def test_compression_no_accept(self, ResponseImpl):\n        req = self.make_request('GET', '/')\n        resp = StreamResponse()\n        self.assertFalse(resp.chunked)\n\n        self.assertFalse(resp.compression)\n        resp.enable_compression()\n        self.assertTrue(resp.compression)\n\n        msg = resp.start(req)\n        self.assertFalse(msg.add_compression_filter.called)\n\n    @mock.patch('aiohttp.web_reqrep.ResponseImpl')\n    def test_force_compression_no_accept_backwards_compat(self, ResponseImpl):\n        req = self.make_request('GET', '/')\n        resp = StreamResponse()\n        self.assertFalse(resp.chunked)\n\n        self.assertFalse(resp.compression)\n        resp.enable_compression(force=True)\n        self.assertTrue(resp.compression)\n\n        msg = resp.start(req)\n        self.assertTrue(msg.add_compression_filter.called)\n        self.assertIsNotNone(msg.filter)\n\n    @mock.patch('aiohttp.web_reqrep.ResponseImpl')\n    def test_force_compression_false_backwards_compat(self, ResponseImpl):\n        req = self.make_request('GET', '/')\n        resp = StreamResponse()\n\n        self.assertFalse(resp.compression)\n        resp.enable_compression(force=False)\n        self.assertTrue(resp.compression)\n\n        msg = resp.start(req)\n        self.assertFalse(msg.add_compression_filter.called)\n\n    @mock.patch('aiohttp.web_reqrep.ResponseImpl')\n    def test_compression_default_coding(self, ResponseImpl):\n        req = self.make_request(\n            'GET', '/',\n            headers=CIMultiDict({hdrs.ACCEPT_ENCODING: 'gzip, deflate'}))\n        resp = StreamResponse()\n        self.assertFalse(resp.chunked)\n\n        self.assertFalse(resp.compression)\n        resp.enable_compression()\n        self.assertTrue(resp.compression)\n\n        msg = resp.start(req)\n        msg.add_compression_filter.assert_called_with('deflate')\n        self.assertEqual('deflate', resp.headers.get(hdrs.CONTENT_ENCODING))\n        self.assertIsNotNone(msg.filter)\n\n    @mock.patch('aiohttp.web_reqrep.ResponseImpl')\n    def test_force_compression_deflate(self, ResponseImpl):\n        req = self.make_request(\n            'GET', '/',\n            headers=CIMultiDict({hdrs.ACCEPT_ENCODING: 'gzip, deflate'}))\n        resp = StreamResponse()\n\n        resp.enable_compression(ContentCoding.deflate)\n        self.assertTrue(resp.compression)\n\n        msg = resp.start(req)\n        msg.add_compression_filter.assert_called_with('deflate')\n        self.assertEqual('deflate', resp.headers.get(hdrs.CONTENT_ENCODING))\n\n    @mock.patch('aiohttp.web_reqrep.ResponseImpl')\n    def test_force_compression_no_accept_deflate(self, ResponseImpl):\n        req = self.make_request('GET', '/')\n        resp = StreamResponse()\n\n        resp.enable_compression(ContentCoding.deflate)\n        self.assertTrue(resp.compression)\n\n        msg = resp.start(req)\n        msg.add_compression_filter.assert_called_with('deflate')\n        self.assertEqual('deflate', resp.headers.get(hdrs.CONTENT_ENCODING))\n\n    @mock.patch('aiohttp.web_reqrep.ResponseImpl')\n    def test_force_compression_gzip(self, ResponseImpl):\n        req = self.make_request(\n            'GET', '/',\n            headers=CIMultiDict({hdrs.ACCEPT_ENCODING: 'gzip, deflate'}))\n        resp = StreamResponse()\n\n        resp.enable_compression(ContentCoding.gzip)\n        self.assertTrue(resp.compression)\n\n        msg = resp.start(req)\n        msg.add_compression_filter.assert_called_with('gzip')\n        self.assertEqual('gzip', resp.headers.get(hdrs.CONTENT_ENCODING))\n\n    @mock.patch('aiohttp.web_reqrep.ResponseImpl')\n    def test_force_compression_no_accept_gzip(self, ResponseImpl):\n        req = self.make_request('GET', '/')\n        resp = StreamResponse()\n\n        resp.enable_compression(ContentCoding.gzip)\n        self.assertTrue(resp.compression)\n\n        msg = resp.start(req)\n        msg.add_compression_filter.assert_called_with('gzip')\n        self.assertEqual('gzip', resp.headers.get(hdrs.CONTENT_ENCODING))\n\n    def test_write_non_byteish(self):\n        resp = StreamResponse()\n        resp.start(self.make_request('GET', '/'))\n\n        with self.assertRaises(AssertionError):\n            resp.write(123)\n\n    def test_write_before_start(self):\n        resp = StreamResponse()\n\n        with self.assertRaises(RuntimeError):\n            resp.write(b'data')\n\n    def test_cannot_write_after_eof(self):\n        resp = StreamResponse()\n        resp.start(self.make_request('GET', '/'))\n\n        resp.write(b'data')\n        self.writer.drain.return_value = ()\n        self.loop.run_until_complete(resp.write_eof())\n        self.writer.write.reset_mock()\n\n        with self.assertRaises(RuntimeError):\n            resp.write(b'next data')\n        self.assertFalse(self.writer.write.called)\n\n    def test_cannot_write_eof_before_headers(self):\n        resp = StreamResponse()\n\n        with self.assertRaises(RuntimeError):\n            self.loop.run_until_complete(resp.write_eof())\n\n    def test_cannot_write_eof_twice(self):\n        resp = StreamResponse()\n        resp.start(self.make_request('GET', '/'))\n\n        resp.write(b'data')\n        self.writer.drain.return_value = ()\n        self.loop.run_until_complete(resp.write_eof())\n        self.assertTrue(self.writer.write.called)\n\n        self.writer.write.reset_mock()\n        self.loop.run_until_complete(resp.write_eof())\n        self.assertFalse(self.writer.write.called)\n\n    def test_write_returns_drain(self):\n        resp = StreamResponse()\n        resp.start(self.make_request('GET', '/'))\n\n        self.assertEqual((), resp.write(b'data'))\n\n    def test_write_returns_empty_tuple_on_empty_data(self):\n        resp = StreamResponse()\n        resp.start(self.make_request('GET', '/'))\n\n        self.assertEqual((), resp.write(b''))\n\n    def test_force_close(self):\n        resp = StreamResponse()\n\n        self.assertIsNone(resp.keep_alive)\n        resp.force_close()\n        self.assertFalse(resp.keep_alive)\n\n    def test_response_cookies(self):\n        resp = StreamResponse()\n\n        self.assertEqual(resp.cookies, {})\n        self.assertEqual(str(resp.cookies), '')\n\n        resp.set_cookie('name', 'value')\n        self.assertEqual(str(resp.cookies), 'Set-Cookie: name=value; Path=/')\n        resp.set_cookie('name', 'other_value')\n        self.assertEqual(str(resp.cookies),\n                         'Set-Cookie: name=other_value; Path=/')\n\n        resp.cookies['name'] = 'another_other_value'\n        resp.cookies['name']['max-age'] = 10\n        self.assertEqual(\n            str(resp.cookies),\n            'Set-Cookie: name=another_other_value; Max-Age=10; Path=/')\n\n        resp.del_cookie('name')\n        self.assertEqual(\n            str(resp.cookies),\n            'Set-Cookie: name=; Max-Age=0; Path=/')\n\n        resp.set_cookie('name', 'value', domain='local.host', path=None)\n        self.assertEqual(str(resp.cookies),\n                         'Set-Cookie: name=value; Domain=local.host')\n\n    def test_response_cookie_path(self):\n        resp = StreamResponse()\n\n        self.assertEqual(resp.cookies, {})\n\n        resp.set_cookie('name', 'value', path='/some/path')\n        self.assertEqual(str(resp.cookies),\n                         'Set-Cookie: name=value; Path=/some/path')\n        resp.set_cookie('name', 'value', expires='123')\n        self.assertEqual(str(resp.cookies),\n                         'Set-Cookie: name=value; expires=123;'\n                         ' Path=/')\n        resp.set_cookie('name', 'value', domain='example.com',\n                        path='/home', expires='123', max_age='10',\n                        secure=True, httponly=True, version='2.0')\n        self.assertEqual(str(resp.cookies).lower(),\n                         'set-cookie: name=value; '\n                         'domain=example.com; '\n                         'expires=123; '\n                         'httponly; '\n                         'max-age=10; '\n                         'path=/home; '\n                         'secure; '\n                         'version=2.0')\n\n    def test_response_cookie__issue_del_cookie(self):\n        resp = StreamResponse()\n\n        self.assertEqual(resp.cookies, {})\n        self.assertEqual(str(resp.cookies), '')\n\n        resp.del_cookie('name')\n        self.assertEqual(str(resp.cookies),\n                         'Set-Cookie: name=; Max-Age=0; Path=/')\n\n    def test_cookie_set_after_del(self):\n        resp = StreamResponse()\n\n        resp.del_cookie('name')\n        resp.set_cookie('name', 'val')\n        # check for Max-Age dropped\n        self.assertEqual(str(resp.cookies),\n                         'Set-Cookie: name=val; Path=/')\n\n    def test_set_status_with_reason(self):\n        resp = StreamResponse()\n\n        resp.set_status(200, \"Everithing is fine!\")\n        self.assertEqual(200, resp.status)\n        self.assertEqual(\"Everithing is fine!\", resp.reason)\n\n    def test_start_force_close(self):\n        req = self.make_request('GET', '/')\n        resp = StreamResponse()\n        resp.force_close()\n        self.assertFalse(resp.keep_alive)\n\n        msg = resp.start(req)\n        self.assertFalse(resp.keep_alive)\n        self.assertTrue(msg.closing)\n\n    def test___repr__(self):\n        req = self.make_request('GET', '/path/to')\n        resp = StreamResponse(reason=301)\n        resp.start(req)\n        self.assertEqual(\"<StreamResponse 301 GET /path/to >\", repr(resp))\n\n    def test___repr__not_started(self):\n        resp = StreamResponse(reason=301)\n        self.assertEqual(\"<StreamResponse 301 not started>\", repr(resp))\n\n    def test_keep_alive_http10(self):\n        message = RawRequestMessage('GET', '/', HttpVersion10, CIMultiDict(),\n                                    True, False)\n        req = self.request_from_message(message)\n        resp = StreamResponse()\n        resp.start(req)\n        self.assertFalse(resp.keep_alive)\n\n        headers = CIMultiDict(Connection='keep-alive')\n        message = RawRequestMessage('GET', '/', HttpVersion10, headers,\n                                    False, False)\n        req = self.request_from_message(message)\n        resp = StreamResponse()\n        resp.start(req)\n        self.assertEqual(resp.keep_alive, True)\n\n    def test_keep_alive_http09(self):\n        headers = CIMultiDict(Connection='keep-alive')\n        message = RawRequestMessage('GET', '/', HttpVersion(0, 9), headers,\n                                    False, False)\n        req = self.request_from_message(message)\n        resp = StreamResponse()\n        resp.start(req)\n        self.assertFalse(resp.keep_alive)\n\n\nclass TestResponse(unittest.TestCase):\n\n    def setUp(self):\n        self.loop = asyncio.new_event_loop()\n        asyncio.set_event_loop(None)\n\n    def tearDown(self):\n        self.loop.close()\n\n    def make_request(self, method, path, headers=CIMultiDict()):\n        self.app = mock.Mock()\n        message = RawRequestMessage(method, path, HttpVersion11, headers,\n                                    False, False)\n        self.payload = mock.Mock()\n        self.transport = mock.Mock()\n        self.reader = mock.Mock()\n        self.writer = mock.Mock()\n        req = Request(self.app, message, self.payload,\n                      self.transport, self.reader, self.writer)\n        return req\n\n    def test_ctor(self):\n        resp = Response()\n\n        self.assertEqual(200, resp.status)\n        self.assertEqual('OK', resp.reason)\n        self.assertIsNone(resp.body)\n        self.assertEqual(0, resp.content_length)\n        self.assertEqual(CIMultiDict([('CONTENT-LENGTH', '0')]),\n                         resp.headers)\n\n    def test_ctor_with_headers_and_status(self):\n        resp = Response(body=b'body', status=201, headers={'Age': '12'})\n\n        self.assertEqual(201, resp.status)\n        self.assertEqual(b'body', resp.body)\n        self.assertEqual(4, resp.content_length)\n        self.assertEqual(CIMultiDict(\n            [('AGE', '12'),\n             ('CONTENT-LENGTH', '4')]), resp.headers)\n\n    def test_ctor_content_type(self):\n        resp = Response(content_type='application/json')\n\n        self.assertEqual(200, resp.status)\n        self.assertEqual('OK', resp.reason)\n        self.assertEqual(\n            CIMultiDict(\n                [('CONTENT-TYPE', 'application/json'),\n                 ('CONTENT-LENGTH', '0')]),\n            resp.headers)\n\n    def test_ctor_text_body_combined(self):\n        with self.assertRaises(ValueError):\n            Response(body=b'123', text='test text')\n\n    def test_ctor_text(self):\n        resp = Response(text='test text')\n\n        self.assertEqual(200, resp.status)\n        self.assertEqual('OK', resp.reason)\n        self.assertEqual(\n            CIMultiDict(\n                [('CONTENT-TYPE', 'text/plain; charset=utf-8'),\n                 ('CONTENT-LENGTH', '9')]),\n            resp.headers)\n\n        self.assertEqual(resp.body, b'test text')\n        self.assertEqual(resp.text, 'test text')\n\n    def test_assign_nonbyteish_body(self):\n        resp = Response(body=b'data')\n\n        with self.assertRaises(TypeError):\n            resp.body = 123\n        self.assertEqual(b'data', resp.body)\n        self.assertEqual(4, resp.content_length)\n\n    def test_assign_nonstr_text(self):\n        resp = Response(text='test')\n\n        with self.assertRaises(TypeError):\n            resp.text = b'123'\n        self.assertEqual(b'test', resp.body)\n        self.assertEqual(4, resp.content_length)\n\n    def test_send_headers_for_empty_body(self):\n        req = self.make_request('GET', '/')\n        resp = Response()\n\n        self.writer.drain.return_value = ()\n        buf = b''\n\n        def append(data):\n            nonlocal buf\n            buf += data\n\n        self.writer.write.side_effect = append\n\n        resp.start(req)\n        self.loop.run_until_complete(resp.write_eof())\n        txt = buf.decode('utf8')\n        self.assertRegex(txt, 'HTTP/1.1 200 OK\\r\\nCONTENT-LENGTH: 0\\r\\n'\n                         'CONNECTION: keep-alive\\r\\n'\n                         'DATE: .+\\r\\nSERVER: .+\\r\\n\\r\\n')\n\n    def test_render_with_body(self):\n        req = self.make_request('GET', '/')\n        resp = Response(body=b'data')\n\n        self.writer.drain.return_value = ()\n        buf = b''\n\n        def append(data):\n            nonlocal buf\n            buf += data\n\n        self.writer.write.side_effect = append\n\n        resp.start(req)\n        self.loop.run_until_complete(resp.write_eof())\n        txt = buf.decode('utf8')\n        self.assertRegex(txt, 'HTTP/1.1 200 OK\\r\\nCONTENT-LENGTH: 4\\r\\n'\n                         'CONNECTION: keep-alive\\r\\n'\n                         'DATE: .+\\r\\nSERVER: .+\\r\\n\\r\\ndata')\n\n    def test_send_set_cookie_header(self):\n        resp = Response()\n        resp.cookies['name'] = 'value'\n\n        req = self.make_request('GET', '/')\n        self.writer.drain.return_value = ()\n        buf = b''\n\n        def append(data):\n            nonlocal buf\n            buf += data\n\n        self.writer.write.side_effect = append\n\n        resp.start(req)\n        self.loop.run_until_complete(resp.write_eof())\n        txt = buf.decode('utf8')\n        self.assertRegex(txt, 'HTTP/1.1 200 OK\\r\\nCONTENT-LENGTH: 0\\r\\n'\n                         'SET-COOKIE: name=value\\r\\n'\n                         'CONNECTION: keep-alive\\r\\n'\n                         'DATE: .+\\r\\nSERVER: .+\\r\\n\\r\\n')\n\n    def test_set_text_with_content_type(self):\n        resp = Response()\n        resp.content_type = \"text/html\"\n        resp.text = \"text\"\n\n        self.assertEqual(\"text\", resp.text)\n        self.assertEqual(b\"text\", resp.body)\n        self.assertEqual(\"text/html\", resp.content_type)\n\n    def test_set_text_with_charset(self):\n        resp = Response()\n        resp.content_type = 'text/plain'\n        resp.charset = \"KOI8-R\"\n        resp.text = \"текст\"\n\n        self.assertEqual(\"текст\", resp.text)\n        self.assertEqual(\"текст\".encode('koi8-r'), resp.body)\n        self.assertEqual(\"koi8-r\", resp.charset)\n\n    def test_started_when_not_started(self):\n        resp = StreamResponse()\n        self.assertFalse(resp.started)\n\n    def test_started_when_started(self):\n        resp = StreamResponse()\n        resp.start(self.make_request('GET', '/'))\n        self.assertTrue(resp.started)\n\n    def test_drain_before_start(self):\n\n        @asyncio.coroutine\n        def go():\n            resp = StreamResponse()\n            with self.assertRaises(RuntimeError):\n                yield from resp.drain()\n\n        self.loop.run_until_complete(go())\n\n    def test_nonstr_text_in_ctor(self):\n        with self.assertRaises(TypeError):\n            Response(text=b'data')\n\n    def test_text_in_ctor_with_content_type(self):\n        resp = Response(text='data', content_type='text/html')\n        self.assertEqual('data', resp.text)\n        self.assertEqual('text/html', resp.content_type)\n\n    def test_text_in_ctor_with_content_type_header(self):\n        resp = Response(text='текст',\n                        headers={'Content-Type': 'text/html; charset=koi8-r'})\n        self.assertEqual('текст'.encode('koi8-r'), resp.body)\n        self.assertEqual('text/html', resp.content_type)\n        self.assertEqual('koi8-r', resp.charset)\n\n    def test_text_with_empty_payload(self):\n        resp = Response(status=200)\n        self.assertEqual(resp.body, None)\n        self.assertEqual(resp.text, None)\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\nTransforming aiohttp/client.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 20ms\nInstalled 26 packages in 54ms\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": 1,
    "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_4284bed28ae27d5d2bf51cabf2bd3dd2e78a5ea4\nplugins: asyncio-0.25.0, mock-3.14.0, cov-6.0.0\nasyncio: mode=strict, asyncio_default_fixture_loop_scope=None\ncollected 64 items\n\nr2e_tests/test_1.py ............F...................F.F................. [ 81%]\n............                                                             [100%]\n\n=================================== FAILURES ===================================\n_________________ TestStreamResponse.test_cookie_set_after_del _________________\n\nself = <r2e_tests.test_1.TestStreamResponse testMethod=test_cookie_set_after_del>\n\n    def test_cookie_set_after_del(self):\n        resp = StreamResponse()\n    \n        resp.del_cookie('name')\n        resp.set_cookie('name', 'val')\n        # check for Max-Age dropped\n>       self.assertEqual(str(resp.cookies),\n                         'Set-Cookie: name=val; Path=/')\nE       AssertionError: 'Set-Cookie: name=val; Max-Age=0; Path=/' != 'Set-Cookie: name=val; Path=/'\nE       - Set-Cookie: name=val; Max-Age=0; Path=/\nE       ?                       -----------\nE       + Set-Cookie: name=val; Path=/\n\nr2e_tests/test_1.py:426: AssertionError\n__________ TestStreamResponse.test_response_cookie__issue_del_cookie ___________\n\nself = <r2e_tests.test_1.TestStreamResponse testMethod=test_response_cookie__issue_del_cookie>\n\n    def test_response_cookie__issue_del_cookie(self):\n        resp = StreamResponse()\n    \n        self.assertEqual(resp.cookies, {})\n        self.assertEqual(str(resp.cookies), '')\n    \n        resp.del_cookie('name')\n>       self.assertEqual(str(resp.cookies),\n                         'Set-Cookie: name=; Max-Age=0; Path=/')\nE       AssertionError: 'Set-Cookie: name=\"\"; Max-Age=0; Path=/' != 'Set-Cookie: name=; Max-Age=0; Path=/'\nE       - Set-Cookie: name=\"\"; Max-Age=0; Path=/\nE       ?                  --\nE       + Set-Cookie: name=; Max-Age=0; Path=/\n\nr2e_tests/test_1.py:417: AssertionError\n___________________ TestStreamResponse.test_response_cookies ___________________\n\nself = <r2e_tests.test_1.TestStreamResponse testMethod=test_response_cookies>\n\n    def test_response_cookies(self):\n        resp = StreamResponse()\n    \n        self.assertEqual(resp.cookies, {})\n        self.assertEqual(str(resp.cookies), '')\n    \n        resp.set_cookie('name', 'value')\n        self.assertEqual(str(resp.cookies), 'Set-Cookie: name=value; Path=/')\n        resp.set_cookie('name', 'other_value')\n        self.assertEqual(str(resp.cookies),\n                         'Set-Cookie: name=other_value; Path=/')\n    \n        resp.cookies['name'] = 'another_other_value'\n        resp.cookies['name']['max-age'] = 10\n        self.assertEqual(\n            str(resp.cookies),\n            'Set-Cookie: name=another_other_value; Max-Age=10; Path=/')\n    \n        resp.del_cookie('name')\n>       self.assertEqual(\n            str(resp.cookies),\n            'Set-Cookie: name=; Max-Age=0; Path=/')\nE       AssertionError: 'Set-Cookie: name=\"\"; Max-Age=0; Path=/' != 'Set-Cookie: name=; Max-Age=0; Path=/'\nE       - Set-Cookie: name=\"\"; Max-Age=0; Path=/\nE       ?                  --\nE       + Set-Cookie: name=; Max-Age=0; Path=/\n\nr2e_tests/test_1.py:377: AssertionError\n==================================== PASSES ====================================\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::TestStreamResponse::test___repr__\nPASSED r2e_tests/test_1.py::TestStreamResponse::test___repr__not_started\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_cannot_write_after_eof\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_cannot_write_eof_before_headers\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_cannot_write_eof_twice\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_charset_without_content_type\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_chunk_size\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_chunked_encoding\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_compression_default_coding\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_compression_no_accept\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_content_length\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_content_length_setter\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_ctor\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_default_charset\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_drop_content_length_header_on_setting_len_to_None\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_force_close\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_force_compression_deflate\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_force_compression_false_backwards_compat\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_force_compression_gzip\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_force_compression_no_accept_backwards_compat\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_force_compression_no_accept_deflate\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_force_compression_no_accept_gzip\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_keep_alive_http09\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_keep_alive_http10\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_last_modified_datetime\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_last_modified_initial\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_last_modified_reset\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_last_modified_string\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_last_modified_timestamp\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_reset_charset\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_reset_charset_after_setting\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_response_cookie_path\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_set_content_length_to_None_on_non_set\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_set_status_with_reason\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_setting_charset\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_setting_content_type\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_start\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_start_force_close\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_write_before_start\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_write_non_byteish\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_write_returns_drain\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_write_returns_empty_tuple_on_empty_data\nPASSED r2e_tests/test_1.py::TestResponse::test_assign_nonbyteish_body\nPASSED r2e_tests/test_1.py::TestResponse::test_assign_nonstr_text\nPASSED r2e_tests/test_1.py::TestResponse::test_ctor\nPASSED r2e_tests/test_1.py::TestResponse::test_ctor_content_type\nPASSED r2e_tests/test_1.py::TestResponse::test_ctor_text\nPASSED r2e_tests/test_1.py::TestResponse::test_ctor_text_body_combined\nPASSED r2e_tests/test_1.py::TestResponse::test_ctor_with_headers_and_status\nPASSED r2e_tests/test_1.py::TestResponse::test_drain_before_start\nPASSED r2e_tests/test_1.py::TestResponse::test_nonstr_text_in_ctor\nPASSED r2e_tests/test_1.py::TestResponse::test_render_with_body\nPASSED r2e_tests/test_1.py::TestResponse::test_send_headers_for_empty_body\nPASSED r2e_tests/test_1.py::TestResponse::test_send_set_cookie_header\nPASSED r2e_tests/test_1.py::TestResponse::test_set_text_with_charset\nPASSED r2e_tests/test_1.py::TestResponse::test_set_text_with_content_type\nPASSED r2e_tests/test_1.py::TestResponse::test_started_when_not_started\nPASSED r2e_tests/test_1.py::TestResponse::test_started_when_started\nPASSED r2e_tests/test_1.py::TestResponse::test_text_in_ctor_with_content_type\nPASSED r2e_tests/test_1.py::TestResponse::test_text_in_ctor_with_content_type_header\nPASSED r2e_tests/test_1.py::TestResponse::test_text_with_empty_payload\nFAILED r2e_tests/test_1.py::TestStreamResponse::test_cookie_set_after_del - A...\nFAILED r2e_tests/test_1.py::TestStreamResponse::test_response_cookie__issue_del_cookie\nFAILED r2e_tests/test_1.py::TestStreamResponse::test_response_cookies - Asser...\n========================= 3 failed, 61 passed in 0.77s =========================\n",
    "new_commit_res_stderr": "/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_4284bed28ae27d5d2bf51cabf2bd3dd2e78a5ea4/.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_4284bed28ae27d5d2bf51cabf2bd3dd2e78a5ea4\nplugins: asyncio-0.25.0, mock-3.14.0, cov-6.0.0\nasyncio: mode=strict, asyncio_default_fixture_loop_scope=None\ncollected 64 items\n\nr2e_tests/test_1.py ............F...................F.F................. [ 81%]\n...........F                                                             [100%]\n\n=================================== FAILURES ===================================\n_________________ TestStreamResponse.test_cookie_set_after_del _________________\n\nself = <r2e_tests.test_1.TestStreamResponse testMethod=test_cookie_set_after_del>\n\n    def test_cookie_set_after_del(self):\n        resp = StreamResponse()\n    \n        resp.del_cookie('name')\n        resp.set_cookie('name', 'val')\n        # check for Max-Age dropped\n>       self.assertEqual(str(resp.cookies),\n                         'Set-Cookie: name=val; Path=/')\nE       AssertionError: 'Set-Cookie: name=val; Max-Age=0; Path=/' != 'Set-Cookie: name=val; Path=/'\nE       - Set-Cookie: name=val; Max-Age=0; Path=/\nE       ?                       -----------\nE       + Set-Cookie: name=val; Path=/\n\nr2e_tests/test_1.py:426: AssertionError\n__________ TestStreamResponse.test_response_cookie__issue_del_cookie ___________\n\nself = <r2e_tests.test_1.TestStreamResponse testMethod=test_response_cookie__issue_del_cookie>\n\n    def test_response_cookie__issue_del_cookie(self):\n        resp = StreamResponse()\n    \n        self.assertEqual(resp.cookies, {})\n        self.assertEqual(str(resp.cookies), '')\n    \n        resp.del_cookie('name')\n>       self.assertEqual(str(resp.cookies),\n                         'Set-Cookie: name=; Max-Age=0; Path=/')\nE       AssertionError: 'Set-Cookie: name=\"\"; Max-Age=0; Path=/' != 'Set-Cookie: name=; Max-Age=0; Path=/'\nE       - Set-Cookie: name=\"\"; Max-Age=0; Path=/\nE       ?                  --\nE       + Set-Cookie: name=; Max-Age=0; Path=/\n\nr2e_tests/test_1.py:417: AssertionError\n___________________ TestStreamResponse.test_response_cookies ___________________\n\nself = <r2e_tests.test_1.TestStreamResponse testMethod=test_response_cookies>\n\n    def test_response_cookies(self):\n        resp = StreamResponse()\n    \n        self.assertEqual(resp.cookies, {})\n        self.assertEqual(str(resp.cookies), '')\n    \n        resp.set_cookie('name', 'value')\n        self.assertEqual(str(resp.cookies), 'Set-Cookie: name=value; Path=/')\n        resp.set_cookie('name', 'other_value')\n        self.assertEqual(str(resp.cookies),\n                         'Set-Cookie: name=other_value; Path=/')\n    \n        resp.cookies['name'] = 'another_other_value'\n        resp.cookies['name']['max-age'] = 10\n        self.assertEqual(\n            str(resp.cookies),\n            'Set-Cookie: name=another_other_value; Max-Age=10; Path=/')\n    \n        resp.del_cookie('name')\n>       self.assertEqual(\n            str(resp.cookies),\n            'Set-Cookie: name=; Max-Age=0; Path=/')\nE       AssertionError: 'Set-Cookie: name=\"\"; Max-Age=0; Path=/' != 'Set-Cookie: name=; Max-Age=0; Path=/'\nE       - Set-Cookie: name=\"\"; Max-Age=0; Path=/\nE       ?                  --\nE       + Set-Cookie: name=; Max-Age=0; Path=/\n\nr2e_tests/test_1.py:377: AssertionError\n__________________ TestResponse.test_text_with_empty_payload ___________________\n\nself = <r2e_tests.test_1.TestResponse testMethod=test_text_with_empty_payload>\n\n    def test_text_with_empty_payload(self):\n        resp = Response(status=200)\n        self.assertEqual(resp.body, None)\n>       self.assertEqual(resp.text, None)\n\nr2e_tests/test_1.py:687: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = <Response OK not started>\n\n    @property\n    def text(self):\n>       return self._body.decode(self.charset or 'utf-8')\nE       AttributeError: 'NoneType' object has no attribute 'decode'\n\naiohttp/web_reqrep.py:743: AttributeError\n==================================== PASSES ====================================\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::TestStreamResponse::test___repr__\nPASSED r2e_tests/test_1.py::TestStreamResponse::test___repr__not_started\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_cannot_write_after_eof\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_cannot_write_eof_before_headers\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_cannot_write_eof_twice\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_charset_without_content_type\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_chunk_size\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_chunked_encoding\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_compression_default_coding\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_compression_no_accept\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_content_length\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_content_length_setter\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_ctor\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_default_charset\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_drop_content_length_header_on_setting_len_to_None\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_force_close\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_force_compression_deflate\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_force_compression_false_backwards_compat\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_force_compression_gzip\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_force_compression_no_accept_backwards_compat\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_force_compression_no_accept_deflate\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_force_compression_no_accept_gzip\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_keep_alive_http09\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_keep_alive_http10\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_last_modified_datetime\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_last_modified_initial\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_last_modified_reset\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_last_modified_string\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_last_modified_timestamp\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_reset_charset\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_reset_charset_after_setting\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_response_cookie_path\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_set_content_length_to_None_on_non_set\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_set_status_with_reason\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_setting_charset\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_setting_content_type\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_start\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_start_force_close\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_write_before_start\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_write_non_byteish\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_write_returns_drain\nPASSED r2e_tests/test_1.py::TestStreamResponse::test_write_returns_empty_tuple_on_empty_data\nPASSED r2e_tests/test_1.py::TestResponse::test_assign_nonbyteish_body\nPASSED r2e_tests/test_1.py::TestResponse::test_assign_nonstr_text\nPASSED r2e_tests/test_1.py::TestResponse::test_ctor\nPASSED r2e_tests/test_1.py::TestResponse::test_ctor_content_type\nPASSED r2e_tests/test_1.py::TestResponse::test_ctor_text\nPASSED r2e_tests/test_1.py::TestResponse::test_ctor_text_body_combined\nPASSED r2e_tests/test_1.py::TestResponse::test_ctor_with_headers_and_status\nPASSED r2e_tests/test_1.py::TestResponse::test_drain_before_start\nPASSED r2e_tests/test_1.py::TestResponse::test_nonstr_text_in_ctor\nPASSED r2e_tests/test_1.py::TestResponse::test_render_with_body\nPASSED r2e_tests/test_1.py::TestResponse::test_send_headers_for_empty_body\nPASSED r2e_tests/test_1.py::TestResponse::test_send_set_cookie_header\nPASSED r2e_tests/test_1.py::TestResponse::test_set_text_with_charset\nPASSED r2e_tests/test_1.py::TestResponse::test_set_text_with_content_type\nPASSED r2e_tests/test_1.py::TestResponse::test_started_when_not_started\nPASSED r2e_tests/test_1.py::TestResponse::test_started_when_started\nPASSED r2e_tests/test_1.py::TestResponse::test_text_in_ctor_with_content_type\nPASSED r2e_tests/test_1.py::TestResponse::test_text_in_ctor_with_content_type_header\nFAILED r2e_tests/test_1.py::TestStreamResponse::test_cookie_set_after_del - A...\nFAILED r2e_tests/test_1.py::TestStreamResponse::test_response_cookie__issue_del_cookie\nFAILED r2e_tests/test_1.py::TestStreamResponse::test_response_cookies - Asser...\nFAILED r2e_tests/test_1.py::TestResponse::test_text_with_empty_payload - Attr...\n========================= 4 failed, 60 passed in 0.31s =========================\n",
    "old_commit_res_stderr": "/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_4284bed28ae27d5d2bf51cabf2bd3dd2e78a5ea4/.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"
}
aiohttp/web_reqrep.py tests/test_web_response.py
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]
**Title:** Accessing `response.text` raises AttributeError when `response.body` is None

**Description:**
When a `Response` object is created without a body (`response.body` is `None`), attempting to access the `response.text` property results in an `AttributeError`. This occurs because the code tries to decode `None` instead of handling the absence of a body gracefully.

**Example Buggy Code:**
```python
from aiohttp.web_reqrep import Response

resp = Response(status=200)
print(resp.text)  # Raises AttributeError: 'NoneType' object has no attribute 'decode'
```

**Expected Behavior:**
If `response.body` is `None`, accessing `response.text` should return `None` instead of raising an error. This allows for safer access to the text property without additional null checks.

[/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/web_reqrep.py
__all__ = ('ContentCoding', 'Request', 'StreamResponse', 'Response')

import asyncio
import binascii
import cgi
import collections
import datetime
import http.cookies
import io
import json
import math
import time
import warnings

import enum

from email.utils import parsedate
from types import MappingProxyType
from urllib.parse import urlsplit, parse_qsl, unquote

from . import hdrs
from .helpers import reify
from .multidict import (CIMultiDictProxy,
                        CIMultiDict,
                        MultiDictProxy,
                        MultiDict)
from .protocol import Response as ResponseImpl, HttpVersion10
from .streams import EOF_MARKER


sentinel = object()


class HeadersMixin:

    _content_type = None
    _content_dict = None
    _stored_content_type = sentinel

    def _parse_content_type(self, raw):
        self._stored_content_type = raw
        if raw is None:
            # default value according to RFC 2616
            self._content_type = 'application/octet-stream'
            self._content_dict = {}
        else:
            self._content_type, self._content_dict = cgi.parse_header(raw)

    @property
    def content_type(self, _CONTENT_TYPE=hdrs.CONTENT_TYPE):
        """The value of content part for Content-Type HTTP header."""
        raw = self.headers.get(_CONTENT_TYPE)
        if self._stored_content_type != raw:
            self._parse_content_type(raw)
        return self._content_type

    @property
    def charset(self, _CONTENT_TYPE=hdrs.CONTENT_TYPE):
        """The value of charset part for Content-Type HTTP header."""
        raw = self.headers.get(_CONTENT_TYPE)
        if self._stored_content_type != raw:
            self._parse_content_type(raw)
        return self._content_dict.get('charset')

    @property
    def content_length(self, _CONTENT_LENGTH=hdrs.CONTENT_LENGTH):
        """The value of Content-Length HTTP header."""
        l = self.headers.get(_CONTENT_LENGTH)
        if l is None:
            return None
        else:
            return int(l)

FileField = collections.namedtuple('Field', 'name filename file content_type')


class ContentCoding(enum.Enum):
    # The content codings that we have support for.
    #
    # Additional registered codings are listed at:
    # https://www.iana.org/assignments/http-parameters/http-parameters.xhtml#content-coding
    deflate = 'deflate'
    gzip = 'gzip'
    identity = 'identity'


############################################################
# HTTP Request
############################################################


class Request(dict, HeadersMixin):

    POST_METHODS = {hdrs.METH_PATCH, hdrs.METH_POST, hdrs.METH_PUT,
                    hdrs.METH_TRACE, hdrs.METH_DELETE}

    def __init__(self, app, message, payload, transport, reader, writer, *,
                 _HOST=hdrs.HOST, secure_proxy_ssl_header=None):
        self._app = app
        self._version = message.version
        self._transport = transport
        self._reader = reader
        self._writer = writer
        self._method = message.method
        self._host = message.headers.get(_HOST)
        self._path_qs = message.path
        self._post = None
        self._post_files_cache = None
        self._headers = CIMultiDictProxy(message.headers)
        if self._version < HttpVersion10:
            self._keep_alive = False
        else:
            self._keep_alive = not message.should_close

        # matchdict, route_name, handler
        # or information about traversal lookup
        self._match_info = None  # initialized after route resolving

        self._payload = payload
        self._cookies = None

        self._read_bytes = None
        self._has_body = not payload.at_eof()

        self._secure_proxy_ssl_header = secure_proxy_ssl_header

    @property
    def scheme(self):
        """A string representing the scheme of the request.

        'http' or 'https'.
        """
        if self._transport.get_extra_info('sslcontext'):
            return 'https'
        secure_proxy_ssl_header = self._secure_proxy_ssl_header
        if secure_proxy_ssl_header is not None:
            header, value = secure_proxy_ssl_header
            if self._headers.get(header) == value:
                return 'https'
        return 'http'

    @property
    def method(self):
        """Read only property for getting HTTP method.

        The value is upper-cased str like 'GET', 'POST', 'PUT' etc.
        """
        return self._method

    @property
    def version(self):
        """Read only property for getting HTTP version of request.

        Returns aiohttp.protocol.HttpVersion instance.
        """
        return self._version

    @property
    def host(self):
        """Read only property for getting *HOST* header of request.

        Returns str or None if HTTP request has no HOST header.
        """
        return self._host

    @property
    def path_qs(self):
        """The URL including PATH_INFO and the query string.

        E.g, /app/blog?id=10
        """
        return self._path_qs

    @reify
    def _splitted_path(self):
        return urlsplit(self._path_qs)

    @property
    def raw_path(self):
        """ The URL including raw *PATH INFO* without the host or scheme.
        Warning, the path is unquoted and may contains non valid URL characters

        E.g., ``/my%2Fpath%7Cwith%21some%25strange%24characters``
        """
        return self._splitted_path.path

    @reify
    def path(self):
        """The URL including *PATH INFO* without the host or scheme.

        E.g., ``/app/blog``
        """
        return unquote(self.raw_path)

    @reify
    def query_string(self):
        """The query string in the URL.

        E.g., id=10
        """
        return self._splitted_path.query

    @reify
    def GET(self):
        """A multidict with all the variables in the query string.

        Lazy property.
        """
        return MultiDictProxy(MultiDict(parse_qsl(self.query_string)))

    @reify
    def POST(self):
        """A multidict with all the variables in the POST parameters.

        post() methods has to be called before using this attribute.
        """
        if self._post is None:
            raise RuntimeError("POST is not available before post()")
        return self._post

    @property
    def headers(self):
        """A case-insensitive multidict proxy with all headers."""
        return self._headers

    @property
    def if_modified_since(self, _IF_MODIFIED_SINCE=hdrs.IF_MODIFIED_SINCE):
        """The value of If-Modified-Since HTTP header, or None.

        This header is represented as a `datetime` object.
        """
        httpdate = self.headers.get(_IF_MODIFIED_SINCE)
        if httpdate is not None:
            timetuple = parsedate(httpdate)
            if timetuple is not None:
                return datetime.datetime(*timetuple[:6],
                                         tzinfo=datetime.timezone.utc)
        return None

    @property
    def keep_alive(self):
        """Is keepalive enabled by client?"""
        return self._keep_alive

    @property
    def match_info(self):
        """Result of route resolving."""
        return self._match_info

    @property
    def app(self):
        """Application instance."""
        return self._app

    @property
    def transport(self):
        """Transport used for request processing."""
        return self._transport

    @property
    def cookies(self):
        """Return request cookies.

        A read-only dictionary-like object.
        """
        if self._cookies is None:
            raw = self.headers.get(hdrs.COOKIE, '')
            parsed = http.cookies.SimpleCookie(raw)
            self._cookies = MappingProxyType(
                {key: val.value for key, val in parsed.items()})
        return self._cookies

    @property
    def payload(self):
        """Return raw payload stream."""
        warnings.warn('use Request.content instead', DeprecationWarning)
        return self._payload

    @property
    def content(self):
        """Return raw payload stream."""
        return self._payload

    @property
    def has_body(self):
        """Return True if request has HTTP BODY, False otherwise."""
        return self._has_body

    @asyncio.coroutine
    def release(self):
        """Release request.

        Eat unread part of HTTP BODY if present.
        """
        chunk = yield from self._payload.readany()
        while chunk is not EOF_MARKER or chunk:
            chunk = yield from self._payload.readany()

    @asyncio.coroutine
    def read(self):
        """Read request body if present.

        Returns bytes object with full request content.
        """
        if self._read_bytes is None:
            body = bytearray()
            while True:
                chunk = yield from self._payload.readany()
                body.extend(chunk)
                if chunk is EOF_MARKER:
                    break
            self._read_bytes = bytes(body)
        return self._read_bytes

    @asyncio.coroutine
    def text(self):
        """Return BODY as text using encoding from .charset."""
        bytes_body = yield from self.read()
        encoding = self.charset or 'utf-8'
        return bytes_body.decode(encoding)

    @asyncio.coroutine
    def json(self, *, loader=json.loads):
        """Return BODY as JSON."""
        body = yield from self.text()
        return loader(body)

    @asyncio.coroutine
    def post(self):
        """Return POST parameters."""
        if self._post is not None:
            return self._post
        if self.method not in self.POST_METHODS:
            self._post = MultiDictProxy(MultiDict())
            return self._post

        content_type = self.content_type
        if (content_type not in ('',
                                 'application/x-www-form-urlencoded',
                                 'multipart/form-data')):
            self._post = MultiDictProxy(MultiDict())
            return self._post

        body = yield from self.read()
        content_charset = self.charset or 'utf-8'

        environ = {'REQUEST_METHOD': self.method,
                   'CONTENT_LENGTH': str(len(body)),
                   'QUERY_STRING': '',
                   'CONTENT_TYPE': self.headers.get(hdrs.CONTENT_TYPE)}

        fs = cgi.FieldStorage(fp=io.BytesIO(body),
                              environ=environ,
                              keep_blank_values=True,
                              encoding=content_charset)

        supported_transfer_encoding = {
            'base64': binascii.a2b_base64,
            'quoted-printable': binascii.a2b_qp
        }

        out = MultiDict()
        for field in fs.list or ():
            transfer_encoding = field.headers.get(
                hdrs.CONTENT_TRANSFER_ENCODING, None)
            if field.filename:
                ff = FileField(field.name,
                               field.filename,
                               field.file,  # N.B. file closed error
                               field.type)
                if self._post_files_cache is None:
                    self._post_files_cache = {}
                self._post_files_cache[field.name] = field
                out.add(field.name, ff)
            else:
                value = field.value
                if transfer_encoding in supported_transfer_encoding:
                    # binascii accepts bytes
                    value = value.encode('utf-8')
                    value = supported_transfer_encoding[
                        transfer_encoding](value)
                out.add(field.name, value)

        self._post = MultiDictProxy(out)
        return self._post

    def __repr__(self):
        return "<{} {} {} >".format(self.__class__.__name__,
                                    self.method, self.path)


############################################################
# HTTP Response classes
############################################################


class StreamResponse(HeadersMixin):

    def __init__(self, *, status=200, reason=None, headers=None):
        self._body = None
        self._keep_alive = None
        self._chunked = False
        self._chunk_size = None
        self._compression = False
        self._compression_force = False
        self._headers = CIMultiDict()
        self._cookies = http.cookies.SimpleCookie()
        self.set_status(status, reason)

        self._req = None
        self._resp_impl = None
        self._eof_sent = False

        if headers is not None:
            self._headers.extend(headers)

    def _copy_cookies(self):
        for cookie in self._cookies.values():
            value = cookie.output(header='')[1:]
            self.headers.add(hdrs.SET_COOKIE, value)

    @property
    def started(self):
        return self._resp_impl is not None

    @property
    def status(self):
        return self._status

    @property
    def chunked(self):
        return self._chunked

    @property
    def compression(self):
        return self._compression

    @property
    def reason(self):
        return self._reason

    def set_status(self, status, reason=None):
        self._status = int(status)
        if reason is None:
            reason = ResponseImpl.calc_reason(status)
        self._reason = reason

    @property
    def keep_alive(self):
        return self._keep_alive

    def force_close(self):
        self._keep_alive = False

    def enable_chunked_encoding(self, chunk_size=None):
        """Enables automatic chunked transfer encoding."""
        self._chunked = True
        self._chunk_size = chunk_size

    def enable_compression(self, force=None):
        """Enables response compression encoding."""
        # Backwards compatibility for when force was a bool <0.17.
        if type(force) == bool:
            force = ContentCoding.deflate if force else ContentCoding.identity

        self._compression = True
        self._compression_force = force

    @property
    def headers(self):
        return self._headers

    @property
    def cookies(self):
        return self._cookies

    def set_cookie(self, name, value, *, expires=None,
                   domain=None, max_age=None, path='/',
                   secure=None, httponly=None, version=None):
        """Set or update response cookie.

        Sets new cookie or updates existent with new value.
        Also updates only those params which are not None.
        """

        old = self._cookies.get(name)
        if old is not None and old.coded_value == '':
            # deleted cookie
            self._cookies.pop(name, None)

        self._cookies[name] = value
        c = self._cookies[name]
        if expires is not None:
            c['expires'] = expires
        if domain is not None:
            c['domain'] = domain
        if max_age is not None:
            c['max-age'] = max_age
        if path is not None:
            c['path'] = path
        if secure is not None:
            c['secure'] = secure
        if httponly is not None:
            c['httponly'] = httponly
        if version is not None:
            c['version'] = version

    def del_cookie(self, name, *, domain=None, path='/'):
        """Delete cookie.

        Creates new empty expired cookie.
        """
        # TODO: do we need domain/path here?
        self._cookies.pop(name, None)
        self.set_cookie(name, '', max_age=0, domain=domain, path=path)

    @property
    def content_length(self):
        # Just a placeholder for adding setter
        return super().content_length

    @content_length.setter
    def content_length(self, value):
        if value is not None:
            value = int(value)
            # TODO: raise error if chunked enabled
            self.headers[hdrs.CONTENT_LENGTH] = str(value)
        elif hdrs.CONTENT_LENGTH in self.headers:
            del self.headers[hdrs.CONTENT_LENGTH]

    @property
    def content_type(self):
        # Just a placeholder for adding setter
        return super().content_type

    @content_type.setter
    def content_type(self, value):
        self.content_type  # read header values if needed
        self._content_type = str(value)
        self._generate_content_type_header()

    @property
    def charset(self):
        # Just a placeholder for adding setter
        return super().charset

    @charset.setter
    def charset(self, value):
        ctype = self.content_type  # read header values if needed
        if ctype == 'application/octet-stream':
            raise RuntimeError("Setting charset for application/octet-stream "
                               "doesn't make sense, setup content_type first")
        if value is None:
            self._content_dict.pop('charset', None)
        else:
            self._content_dict['charset'] = str(value).lower()
        self._generate_content_type_header()

    @property
    def last_modified(self, _LAST_MODIFIED=hdrs.LAST_MODIFIED):
        """The value of Last-Modified HTTP header, or None.

        This header is represented as a `datetime` object.
        """
        httpdate = self.headers.get(_LAST_MODIFIED)
        if httpdate is not None:
            timetuple = parsedate(httpdate)
            if timetuple is not None:
                return datetime.datetime(*timetuple[:6],
                                         tzinfo=datetime.timezone.utc)
        return None

    @last_modified.setter
    def last_modified(self, value):
        if value is None:
            if hdrs.LAST_MODIFIED in self.headers:
                del self.headers[hdrs.LAST_MODIFIED]
        elif isinstance(value, (int, float)):
            self.headers[hdrs.LAST_MODIFIED] = time.strftime(
                "%a, %d %b %Y %H:%M:%S GMT", time.gmtime(math.ceil(value)))
        elif isinstance(value, datetime.datetime):
            self.headers[hdrs.LAST_MODIFIED] = time.strftime(
                "%a, %d %b %Y %H:%M:%S GMT", value.utctimetuple())
        elif isinstance(value, str):
            self.headers[hdrs.LAST_MODIFIED] = value

    def _generate_content_type_header(self, CONTENT_TYPE=hdrs.CONTENT_TYPE):
        params = '; '.join("%s=%s" % i for i in self._content_dict.items())
        if params:
            ctype = self._content_type + '; ' + params
        else:
            ctype = self._content_type
        self.headers[CONTENT_TYPE] = ctype

    def _start_pre_check(self, request):
        if self._resp_impl is not None:
            if self._req is not request:
                raise RuntimeError(
                    'Response has been started with different request.')
            else:
                return self._resp_impl
        else:
            return None

    def _start_compression(self, request):
        def start(coding):
            if coding != ContentCoding.identity:
                self.headers[hdrs.CONTENT_ENCODING] = coding.value
                self._resp_impl.add_compression_filter(coding.value)

        if self._compression_force:
            start(self._compression_force)
        else:
            accept_encoding = request.headers.get(
                hdrs.ACCEPT_ENCODING, '').lower()
            for coding in ContentCoding:
                if coding.value in accept_encoding:
                    start(coding)
                    return

    def start(self, request):
        resp_impl = self._start_pre_check(request)
        if resp_impl is not None:
            return resp_impl

        self._req = request
        keep_alive = self._keep_alive
        if keep_alive is None:
            keep_alive = request.keep_alive
        self._keep_alive = keep_alive

        resp_impl = self._resp_impl = ResponseImpl(
            request._writer,
            self._status,
            request.version,
            not keep_alive,
            self._reason)

        self._copy_cookies()

        if self._compression:
            self._start_compression(request)

        if self._chunked:
            resp_impl.enable_chunked_encoding()
            if self._chunk_size:
                resp_impl.add_chunking_filter(self._chunk_size)

        headers = self.headers.items()
        for key, val in headers:
            resp_impl.add_header(key, val)

        resp_impl.send_headers()
        return resp_impl

    def write(self, data):
        assert isinstance(data, (bytes, bytearray, memoryview)), \
            'data argument must be byte-ish (%r)' % type(data)

        if self._eof_sent:
            raise RuntimeError("Cannot call write() after write_eof()")
        if self._resp_impl is None:
            raise RuntimeError("Cannot call write() before start()")

        if data:
            return self._resp_impl.write(data)
        else:
            return ()

    @asyncio.coroutine
    def drain(self):
        if self._resp_impl is None:
            raise RuntimeError("Response has not been started")
        yield from self._resp_impl.transport.drain()

    @asyncio.coroutine
    def write_eof(self):
        if self._eof_sent:
            return
        if self._resp_impl is None:
            raise RuntimeError("Response has not been started")

        yield from self._resp_impl.write_eof()
        self._eof_sent = True

    def __repr__(self):
        if self.started:
            info = "{} {} ".format(self._req.method, self._req.path)
        else:
            info = "not started"
        return "<{} {} {}>".format(self.__class__.__name__,
                                   self.reason, info)


class Response(StreamResponse):

    def __init__(self, *, body=None, status=200,
                 reason=None, text=None, headers=None, content_type=None):
        super().__init__(status=status, reason=reason, headers=headers)

        if body is not None and text is not None:
            raise ValueError("body and text are not allowed together.")

        if text is not None:
            if hdrs.CONTENT_TYPE not in self.headers:
                # fast path for filling headers
                if not isinstance(text, str):
                    raise TypeError('text argument must be str (%r)' %
                                    type(text))
                if content_type is None:
                    content_type = 'text/plain'
                self.headers[hdrs.CONTENT_TYPE] = (
                    content_type + '; charset=utf-8')
                self._content_type = content_type
                self._content_dict = {'charset': 'utf-8'}
                self.body = text.encode('utf-8')
            else:
                self.text = text
        else:
            if content_type:
                self.content_type = content_type
            if body is not None:
                self.body = body
            else:
                self.body = None

    @property
    def body(self):
        return self._body

    @body.setter
    def body(self, body):
        if body is not None and not isinstance(body, bytes):
            raise TypeError('body argument must be bytes (%r)' % type(body))
        self._body = body
        if body is not None:
            self.content_length = len(body)
        else:
            self.content_length = 0

    @property
    def text(self):
        return self._body.decode(self.charset or 'utf-8')

    @text.setter
    def text(self, text):
        if text is not None and not isinstance(text, str):
            raise TypeError('text argument must be str (%r)' % type(text))

        if self.content_type == 'application/octet-stream':
            self.content_type = 'text/plain'
        if self.charset is None:
            self.charset = 'utf-8'

        self.body = text.encode(self.charset)

    @asyncio.coroutine
    def write_eof(self):
        body = self._body
        if body is not None:
            self.write(body)
        yield from super().write_eof()

```
--- END FILE ---

Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.

Every *SEARCH/REPLACE* edit must use this format:
1. The file path
2. The start of search block: <<<<<<< SEARCH
3. A contiguous chunk of lines to search for in the existing source code
4. The dividing line: =======
5. The lines to replace into the source code
6. The end of the replace block: >>>>>>> REPLACE

Here is an example:

```python
### mathweb/flask/app.py
<<<<<<< SEARCH
from flask import Flask
=======
import math
from flask import Flask
>>>>>>> REPLACE
```
</solution>

Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
Wrap each *SEARCH/REPLACE* edit in a code block as shown in the example above. If you have multiple *SEARCH/REPLACE* edits, use a separate code block for each one.
[ISSUE]
**Title:** Accessing `response.text` raises AttributeError when `response.body` is None

**Description:**
When a `Response` object is created without a body (`response.body` is `None`), attempting to access the `response.text` property results in an `AttributeError`. This occurs because the code tries to decode `None` instead of handling the absence of a body gracefully.

**Example Buggy Code:**
```python
from aiohttp.web_reqrep import Response

resp = Response(status=200)
print(resp.text)  # Raises AttributeError: 'NoneType' object has no attribute 'decode'
```

**Expected Behavior:**
If `response.body` is `None`, accessing `response.text` should return `None` instead of raising an error. This allows for safer access to the text property without additional null checks.

[/ISSUE]
{
    "TestStreamResponse.test___repr__": "PASSED",
    "TestStreamResponse.test___repr__not_started": "PASSED",
    "TestStreamResponse.test_cannot_write_after_eof": "PASSED",
    "TestStreamResponse.test_cannot_write_eof_before_headers": "PASSED",
    "TestStreamResponse.test_cannot_write_eof_twice": "PASSED",
    "TestStreamResponse.test_charset_without_content_type": "PASSED",
    "TestStreamResponse.test_chunk_size": "PASSED",
    "TestStreamResponse.test_chunked_encoding": "PASSED",
    "TestStreamResponse.test_compression_default_coding": "PASSED",
    "TestStreamResponse.test_compression_no_accept": "PASSED",
    "TestStreamResponse.test_content_length": "PASSED",
    "TestStreamResponse.test_content_length_setter": "PASSED",
    "TestStreamResponse.test_ctor": "PASSED",
    "TestStreamResponse.test_default_charset": "PASSED",
    "TestStreamResponse.test_drop_content_length_header_on_setting_len_to_None": "PASSED",
    "TestStreamResponse.test_force_close": "PASSED",
    "TestStreamResponse.test_force_compression_deflate": "PASSED",
    "TestStreamResponse.test_force_compression_false_backwards_compat": "PASSED",
    "TestStreamResponse.test_force_compression_gzip": "PASSED",
    "TestStreamResponse.test_force_compression_no_accept_backwards_compat": "PASSED",
    "TestStreamResponse.test_force_compression_no_accept_deflate": "PASSED",
    "TestStreamResponse.test_force_compression_no_accept_gzip": "PASSED",
    "TestStreamResponse.test_keep_alive_http09": "PASSED",
    "TestStreamResponse.test_keep_alive_http10": "PASSED",
    "TestStreamResponse.test_last_modified_datetime": "PASSED",
    "TestStreamResponse.test_last_modified_initial": "PASSED",
    "TestStreamResponse.test_last_modified_reset": "PASSED",
    "TestStreamResponse.test_last_modified_string": "PASSED",
    "TestStreamResponse.test_last_modified_timestamp": "PASSED",
    "TestStreamResponse.test_reset_charset": "PASSED",
    "TestStreamResponse.test_reset_charset_after_setting": "PASSED",
    "TestStreamResponse.test_response_cookie_path": "PASSED",
    "TestStreamResponse.test_set_content_length_to_None_on_non_set": "PASSED",
    "TestStreamResponse.test_set_status_with_reason": "PASSED",
    "TestStreamResponse.test_setting_charset": "PASSED",
    "TestStreamResponse.test_setting_content_type": "PASSED",
    "TestStreamResponse.test_start": "PASSED",
    "TestStreamResponse.test_start_force_close": "PASSED",
    "TestStreamResponse.test_write_before_start": "PASSED",
    "TestStreamResponse.test_write_non_byteish": "PASSED",
    "TestStreamResponse.test_write_returns_drain": "PASSED",
    "TestStreamResponse.test_write_returns_empty_tuple_on_empty_data": "PASSED",
    "TestResponse.test_assign_nonbyteish_body": "PASSED",
    "TestResponse.test_assign_nonstr_text": "PASSED",
    "TestResponse.test_ctor": "PASSED",
    "TestResponse.test_ctor_content_type": "PASSED",
    "TestResponse.test_ctor_text": "PASSED",
    "TestResponse.test_ctor_text_body_combined": "PASSED",
    "TestResponse.test_ctor_with_headers_and_status": "PASSED",
    "TestResponse.test_drain_before_start": "PASSED",
    "TestResponse.test_nonstr_text_in_ctor": "PASSED",
    "TestResponse.test_render_with_body": "PASSED",
    "TestResponse.test_send_headers_for_empty_body": "PASSED",
    "TestResponse.test_send_set_cookie_header": "PASSED",
    "TestResponse.test_set_text_with_charset": "PASSED",
    "TestResponse.test_set_text_with_content_type": "PASSED",
    "TestResponse.test_started_when_not_started": "PASSED",
    "TestResponse.test_started_when_started": "PASSED",
    "TestResponse.test_text_in_ctor_with_content_type": "PASSED",
    "TestResponse.test_text_in_ctor_with_content_type_header": "PASSED",
    "TestResponse.test_text_with_empty_payload": "PASSED",
    "TestStreamResponse.test_cookie_set_after_del": "FAILED",
    "TestStreamResponse.test_response_cookie__issue_del_cookie": "FAILED",
    "TestStreamResponse.test_response_cookies": "FAILED"
}
diff --git a/aiohttp/web_reqrep.py b/aiohttp/web_reqrep.py
index 83cd59b4..b00c8c41 100644
--- a/aiohttp/web_reqrep.py
+++ b/aiohttp/web_reqrep.py
@@ -740,6 +740,8 @@ class Response(StreamResponse):
 
     @property
     def text(self):
+        if self._body is None:
+            return None
         return self._body.decode(self.charset or 'utf-8')
 
     @text.setter

{"aiohttp/web_reqrep.py": "__all__ = ('ContentCoding', 'Request', 'StreamResponse', 'Response')\n\nimport asyncio\nimport binascii\nimport cgi\nimport collections\nimport datetime\nimport http.cookies\nimport io\nimport json\nimport math\nimport time\nimport warnings\n\nimport enum\n\nfrom email.utils import parsedate\nfrom types import MappingProxyType\nfrom urllib.parse import urlsplit, parse_qsl, unquote\n\nfrom . import hdrs\nfrom .helpers import reify\nfrom .multidict import (CIMultiDictProxy,\n                        CIMultiDict,\n                        MultiDictProxy,\n                        MultiDict)\nfrom .protocol import Response as ResponseImpl, HttpVersion10\nfrom .streams import EOF_MARKER\n\n\nsentinel = object()\n\n\nclass HeadersMixin:\n\n    _content_type = None\n    _content_dict = None\n    _stored_content_type = sentinel\n\n    def _parse_content_type(self, raw):\n        self._stored_content_type = raw\n        if raw is None:\n            # default value according to RFC 2616\n            self._content_type = 'application/octet-stream'\n            self._content_dict = {}\n        else:\n            self._content_type, self._content_dict = cgi.parse_header(raw)\n\n    @property\n    def content_type(self, _CONTENT_TYPE=hdrs.CONTENT_TYPE):\n        \"\"\"The value of content part for Content-Type HTTP header.\"\"\"\n        raw = self.headers.get(_CONTENT_TYPE)\n        if self._stored_content_type != raw:\n            self._parse_content_type(raw)\n        return self._content_type\n\n    @property\n    def charset(self, _CONTENT_TYPE=hdrs.CONTENT_TYPE):\n        \"\"\"The value of charset part for Content-Type HTTP header.\"\"\"\n        raw = self.headers.get(_CONTENT_TYPE)\n        if self._stored_content_type != raw:\n            self._parse_content_type(raw)\n        return self._content_dict.get('charset')\n\n    @property\n    def content_length(self, _CONTENT_LENGTH=hdrs.CONTENT_LENGTH):\n        \"\"\"The value of Content-Length HTTP header.\"\"\"\n        l = self.headers.get(_CONTENT_LENGTH)\n        if l is None:\n            return None\n        else:\n            return int(l)\n\nFileField = collections.namedtuple('Field', 'name filename file content_type')\n\n\nclass ContentCoding(enum.Enum):\n    # The content codings that we have support for.\n    #\n    # Additional registered codings are listed at:\n    # https://www.iana.org/assignments/http-parameters/http-parameters.xhtml#content-coding\n    deflate = 'deflate'\n    gzip = 'gzip'\n    identity = 'identity'\n\n\n############################################################\n# HTTP Request\n############################################################\n\n\nclass Request(dict, HeadersMixin):\n\n    POST_METHODS = {hdrs.METH_PATCH, hdrs.METH_POST, hdrs.METH_PUT,\n                    hdrs.METH_TRACE, hdrs.METH_DELETE}\n\n    def __init__(self, app, message, payload, transport, reader, writer, *,\n                 _HOST=hdrs.HOST, secure_proxy_ssl_header=None):\n        self._app = app\n        self._version = message.version\n        self._transport = transport\n        self._reader = reader\n        self._writer = writer\n        self._method = message.method\n        self._host = message.headers.get(_HOST)\n        self._path_qs = message.path\n        self._post = None\n        self._post_files_cache = None\n        self._headers = CIMultiDictProxy(message.headers)\n        if self._version < HttpVersion10:\n            self._keep_alive = False\n        else:\n            self._keep_alive = not message.should_close\n\n        # matchdict, route_name, handler\n        # or information about traversal lookup\n        self._match_info = None  # initialized after route resolving\n\n        self._payload = payload\n        self._cookies = None\n\n        self._read_bytes = None\n        self._has_body = not payload.at_eof()\n\n        self._secure_proxy_ssl_header = secure_proxy_ssl_header\n\n    @property\n    def scheme(self):\n        \"\"\"A string representing the scheme of the request.\n\n        'http' or 'https'.\n        \"\"\"\n        if self._transport.get_extra_info('sslcontext'):\n            return 'https'\n        secure_proxy_ssl_header = self._secure_proxy_ssl_header\n        if secure_proxy_ssl_header is not None:\n            header, value = secure_proxy_ssl_header\n            if self._headers.get(header) == value:\n                return 'https'\n        return 'http'\n\n    @property\n    def method(self):\n        \"\"\"Read only property for getting HTTP method.\n\n        The value is upper-cased str like 'GET', 'POST', 'PUT' etc.\n        \"\"\"\n        return self._method\n\n    @property\n    def version(self):\n        \"\"\"Read only property for getting HTTP version of request.\n\n        Returns aiohttp.protocol.HttpVersion instance.\n        \"\"\"\n        return self._version\n\n    @property\n    def host(self):\n        \"\"\"Read only property for getting *HOST* header of request.\n\n        Returns str or None if HTTP request has no HOST header.\n        \"\"\"\n        return self._host\n\n    @property\n    def path_qs(self):\n        \"\"\"The URL including PATH_INFO and the query string.\n\n        E.g, /app/blog?id=10\n        \"\"\"\n        return self._path_qs\n\n    @reify\n    def _splitted_path(self):\n        return urlsplit(self._path_qs)\n\n    @property\n    def raw_path(self):\n        \"\"\" The URL including raw *PATH INFO* without the host or scheme.\n        Warning, the path is unquoted and may contains non valid URL characters\n\n        E.g., ``/my%2Fpath%7Cwith%21some%25strange%24characters``\n        \"\"\"\n        return self._splitted_path.path\n\n    @reify\n    def path(self):\n        \"\"\"The URL including *PATH INFO* without the host or scheme.\n\n        E.g., ``/app/blog``\n        \"\"\"\n        return unquote(self.raw_path)\n\n    @reify\n    def query_string(self):\n        \"\"\"The query string in the URL.\n\n        E.g., id=10\n        \"\"\"\n        return self._splitted_path.query\n\n    @reify\n    def GET(self):\n        \"\"\"A multidict with all the variables in the query string.\n\n        Lazy property.\n        \"\"\"\n        return MultiDictProxy(MultiDict(parse_qsl(self.query_string)))\n\n    @reify\n    def POST(self):\n        \"\"\"A multidict with all the variables in the POST parameters.\n\n        post() methods has to be called before using this attribute.\n        \"\"\"\n        if self._post is None:\n            raise RuntimeError(\"POST is not available before post()\")\n        return self._post\n\n    @property\n    def headers(self):\n        \"\"\"A case-insensitive multidict proxy with all headers.\"\"\"\n        return self._headers\n\n    @property\n    def if_modified_since(self, _IF_MODIFIED_SINCE=hdrs.IF_MODIFIED_SINCE):\n        \"\"\"The value of If-Modified-Since HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        httpdate = self.headers.get(_IF_MODIFIED_SINCE)\n        if httpdate is not None:\n            timetuple = parsedate(httpdate)\n            if timetuple is not None:\n                return datetime.datetime(*timetuple[:6],\n                                         tzinfo=datetime.timezone.utc)\n        return None\n\n    @property\n    def keep_alive(self):\n        \"\"\"Is keepalive enabled by client?\"\"\"\n        return self._keep_alive\n\n    @property\n    def match_info(self):\n        \"\"\"Result of route resolving.\"\"\"\n        return self._match_info\n\n    @property\n    def app(self):\n        \"\"\"Application instance.\"\"\"\n        return self._app\n\n    @property\n    def transport(self):\n        \"\"\"Transport used for request processing.\"\"\"\n        return self._transport\n\n    @property\n    def cookies(self):\n        \"\"\"Return request cookies.\n\n        A read-only dictionary-like object.\n        \"\"\"\n        if self._cookies is None:\n            raw = self.headers.get(hdrs.COOKIE, '')\n            parsed = http.cookies.SimpleCookie(raw)\n            self._cookies = MappingProxyType(\n                {key: val.value for key, val in parsed.items()})\n        return self._cookies\n\n    @property\n    def payload(self):\n        \"\"\"Return raw payload stream.\"\"\"\n        warnings.warn('use Request.content instead', DeprecationWarning)\n        return self._payload\n\n    @property\n    def content(self):\n        \"\"\"Return raw payload stream.\"\"\"\n        return self._payload\n\n    @property\n    def has_body(self):\n        \"\"\"Return True if request has HTTP BODY, False otherwise.\"\"\"\n        return self._has_body\n\n    @asyncio.coroutine\n    def release(self):\n        \"\"\"Release request.\n\n        Eat unread part of HTTP BODY if present.\n        \"\"\"\n        chunk = yield from self._payload.readany()\n        while chunk is not EOF_MARKER or chunk:\n            chunk = yield from self._payload.readany()\n\n    @asyncio.coroutine\n    def read(self):\n        \"\"\"Read request body if present.\n\n        Returns bytes object with full request content.\n        \"\"\"\n        if self._read_bytes is None:\n            body = bytearray()\n            while True:\n                chunk = yield from self._payload.readany()\n                body.extend(chunk)\n                if chunk is EOF_MARKER:\n                    break\n            self._read_bytes = bytes(body)\n        return self._read_bytes\n\n    @asyncio.coroutine\n    def text(self):\n        \"\"\"Return BODY as text using encoding from .charset.\"\"\"\n        bytes_body = yield from self.read()\n        encoding = self.charset or 'utf-8'\n        return bytes_body.decode(encoding)\n\n    @asyncio.coroutine\n    def json(self, *, loader=json.loads):\n        \"\"\"Return BODY as JSON.\"\"\"\n        body = yield from self.text()\n        return loader(body)\n\n    @asyncio.coroutine\n    def post(self):\n        \"\"\"Return POST parameters.\"\"\"\n        if self._post is not None:\n            return self._post\n        if self.method not in self.POST_METHODS:\n            self._post = MultiDictProxy(MultiDict())\n            return self._post\n\n        content_type = self.content_type\n        if (content_type not in ('',\n                                 'application/x-www-form-urlencoded',\n                                 'multipart/form-data')):\n            self._post = MultiDictProxy(MultiDict())\n            return self._post\n\n        body = yield from self.read()\n        content_charset = self.charset or 'utf-8'\n\n        environ = {'REQUEST_METHOD': self.method,\n                   'CONTENT_LENGTH': str(len(body)),\n                   'QUERY_STRING': '',\n                   'CONTENT_TYPE': self.headers.get(hdrs.CONTENT_TYPE)}\n\n        fs = cgi.FieldStorage(fp=io.BytesIO(body),\n                              environ=environ,\n                              keep_blank_values=True,\n                              encoding=content_charset)\n\n        supported_transfer_encoding = {\n            'base64': binascii.a2b_base64,\n            'quoted-printable': binascii.a2b_qp\n        }\n\n        out = MultiDict()\n        for field in fs.list or ():\n            transfer_encoding = field.headers.get(\n                hdrs.CONTENT_TRANSFER_ENCODING, None)\n            if field.filename:\n                ff = FileField(field.name,\n                               field.filename,\n                               field.file,  # N.B. file closed error\n                               field.type)\n                if self._post_files_cache is None:\n                    self._post_files_cache = {}\n                self._post_files_cache[field.name] = field\n                out.add(field.name, ff)\n            else:\n                value = field.value\n                if transfer_encoding in supported_transfer_encoding:\n                    # binascii accepts bytes\n                    value = value.encode('utf-8')\n                    value = supported_transfer_encoding[\n                        transfer_encoding](value)\n                out.add(field.name, value)\n\n        self._post = MultiDictProxy(out)\n        return self._post\n\n    def __repr__(self):\n        return \"<{} {} {} >\".format(self.__class__.__name__,\n                                    self.method, self.path)\n\n\n############################################################\n# HTTP Response classes\n############################################################\n\n\nclass StreamResponse(HeadersMixin):\n\n    def __init__(self, *, status=200, reason=None, headers=None):\n        self._body = None\n        self._keep_alive = None\n        self._chunked = False\n        self._chunk_size = None\n        self._compression = False\n        self._compression_force = False\n        self._headers = CIMultiDict()\n        self._cookies = http.cookies.SimpleCookie()\n        self.set_status(status, reason)\n\n        self._req = None\n        self._resp_impl = None\n        self._eof_sent = False\n\n        if headers is not None:\n            self._headers.extend(headers)\n\n    def _copy_cookies(self):\n        for cookie in self._cookies.values():\n            value = cookie.output(header='')[1:]\n            self.headers.add(hdrs.SET_COOKIE, value)\n\n    @property\n    def started(self):\n        return self._resp_impl is not None\n\n    @property\n    def status(self):\n        return self._status\n\n    @property\n    def chunked(self):\n        return self._chunked\n\n    @property\n    def compression(self):\n        return self._compression\n\n    @property\n    def reason(self):\n        return self._reason\n\n    def set_status(self, status, reason=None):\n        self._status = int(status)\n        if reason is None:\n            reason = ResponseImpl.calc_reason(status)\n        self._reason = reason\n\n    @property\n    def keep_alive(self):\n        return self._keep_alive\n\n    def force_close(self):\n        self._keep_alive = False\n\n    def enable_chunked_encoding(self, chunk_size=None):\n        \"\"\"Enables automatic chunked transfer encoding.\"\"\"\n        self._chunked = True\n        self._chunk_size = chunk_size\n\n    def enable_compression(self, force=None):\n        \"\"\"Enables response compression encoding.\"\"\"\n        # Backwards compatibility for when force was a bool <0.17.\n        if type(force) == bool:\n            force = ContentCoding.deflate if force else ContentCoding.identity\n\n        self._compression = True\n        self._compression_force = force\n\n    @property\n    def headers(self):\n        return self._headers\n\n    @property\n    def cookies(self):\n        return self._cookies\n\n    def set_cookie(self, name, value, *, expires=None,\n                   domain=None, max_age=None, path='/',\n                   secure=None, httponly=None, version=None):\n        \"\"\"Set or update response cookie.\n\n        Sets new cookie or updates existent with new value.\n        Also updates only those params which are not None.\n        \"\"\"\n\n        old = self._cookies.get(name)\n        if old is not None and old.coded_value == '':\n            # deleted cookie\n            self._cookies.pop(name, None)\n\n        self._cookies[name] = value\n        c = self._cookies[name]\n        if expires is not None:\n            c['expires'] = expires\n        if domain is not None:\n            c['domain'] = domain\n        if max_age is not None:\n            c['max-age'] = max_age\n        if path is not None:\n            c['path'] = path\n        if secure is not None:\n            c['secure'] = secure\n        if httponly is not None:\n            c['httponly'] = httponly\n        if version is not None:\n            c['version'] = version\n\n    def del_cookie(self, name, *, domain=None, path='/'):\n        \"\"\"Delete cookie.\n\n        Creates new empty expired cookie.\n        \"\"\"\n        # TODO: do we need domain/path here?\n        self._cookies.pop(name, None)\n        self.set_cookie(name, '', max_age=0, domain=domain, path=path)\n\n    @property\n    def content_length(self):\n        # Just a placeholder for adding setter\n        return super().content_length\n\n    @content_length.setter\n    def content_length(self, value):\n        if value is not None:\n            value = int(value)\n            # TODO: raise error if chunked enabled\n            self.headers[hdrs.CONTENT_LENGTH] = str(value)\n        elif hdrs.CONTENT_LENGTH in self.headers:\n            del self.headers[hdrs.CONTENT_LENGTH]\n\n    @property\n    def content_type(self):\n        # Just a placeholder for adding setter\n        return super().content_type\n\n    @content_type.setter\n    def content_type(self, value):\n        self.content_type  # read header values if needed\n        self._content_type = str(value)\n        self._generate_content_type_header()\n\n    @property\n    def charset(self):\n        # Just a placeholder for adding setter\n        return super().charset\n\n    @charset.setter\n    def charset(self, value):\n        ctype = self.content_type  # read header values if needed\n        if ctype == 'application/octet-stream':\n            raise RuntimeError(\"Setting charset for application/octet-stream \"\n                               \"doesn't make sense, setup content_type first\")\n        if value is None:\n            self._content_dict.pop('charset', None)\n        else:\n            self._content_dict['charset'] = str(value).lower()\n        self._generate_content_type_header()\n\n    @property\n    def last_modified(self, _LAST_MODIFIED=hdrs.LAST_MODIFIED):\n        \"\"\"The value of Last-Modified HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        httpdate = self.headers.get(_LAST_MODIFIED)\n        if httpdate is not None:\n            timetuple = parsedate(httpdate)\n            if timetuple is not None:\n                return datetime.datetime(*timetuple[:6],\n                                         tzinfo=datetime.timezone.utc)\n        return None\n\n    @last_modified.setter\n    def last_modified(self, value):\n        if value is None:\n            if hdrs.LAST_MODIFIED in self.headers:\n                del self.headers[hdrs.LAST_MODIFIED]\n        elif isinstance(value, (int, float)):\n            self.headers[hdrs.LAST_MODIFIED] = time.strftime(\n                \"%a, %d %b %Y %H:%M:%S GMT\", time.gmtime(math.ceil(value)))\n        elif isinstance(value, datetime.datetime):\n            self.headers[hdrs.LAST_MODIFIED] = time.strftime(\n                \"%a, %d %b %Y %H:%M:%S GMT\", value.utctimetuple())\n        elif isinstance(value, str):\n            self.headers[hdrs.LAST_MODIFIED] = value\n\n    def _generate_content_type_header(self, CONTENT_TYPE=hdrs.CONTENT_TYPE):\n        params = '; '.join(\"%s=%s\" % i for i in self._content_dict.items())\n        if params:\n            ctype = self._content_type + '; ' + params\n        else:\n            ctype = self._content_type\n        self.headers[CONTENT_TYPE] = ctype\n\n    def _start_pre_check(self, request):\n        if self._resp_impl is not None:\n            if self._req is not request:\n                raise RuntimeError(\n                    'Response has been started with different request.')\n            else:\n                return self._resp_impl\n        else:\n            return None\n\n    def _start_compression(self, request):\n        def start(coding):\n            if coding != ContentCoding.identity:\n                self.headers[hdrs.CONTENT_ENCODING] = coding.value\n                self._resp_impl.add_compression_filter(coding.value)\n\n        if self._compression_force:\n            start(self._compression_force)\n        else:\n            accept_encoding = request.headers.get(\n                hdrs.ACCEPT_ENCODING, '').lower()\n            for coding in ContentCoding:\n                if coding.value in accept_encoding:\n                    start(coding)\n                    return\n\n    def start(self, request):\n        resp_impl = self._start_pre_check(request)\n        if resp_impl is not None:\n            return resp_impl\n\n        self._req = request\n        keep_alive = self._keep_alive\n        if keep_alive is None:\n            keep_alive = request.keep_alive\n        self._keep_alive = keep_alive\n\n        resp_impl = self._resp_impl = ResponseImpl(\n            request._writer,\n            self._status,\n            request.version,\n            not keep_alive,\n            self._reason)\n\n        self._copy_cookies()\n\n        if self._compression:\n            self._start_compression(request)\n\n        if self._chunked:\n            resp_impl.enable_chunked_encoding()\n            if self._chunk_size:\n                resp_impl.add_chunking_filter(self._chunk_size)\n\n        headers = self.headers.items()\n        for key, val in headers:\n            resp_impl.add_header(key, val)\n\n        resp_impl.send_headers()\n        return resp_impl\n\n    def write(self, data):\n        assert isinstance(data, (bytes, bytearray, memoryview)), \\\n            'data argument must be byte-ish (%r)' % type(data)\n\n        if self._eof_sent:\n            raise RuntimeError(\"Cannot call write() after write_eof()\")\n        if self._resp_impl is None:\n            raise RuntimeError(\"Cannot call write() before start()\")\n\n        if data:\n            return self._resp_impl.write(data)\n        else:\n            return ()\n\n    @asyncio.coroutine\n    def drain(self):\n        if self._resp_impl is None:\n            raise RuntimeError(\"Response has not been started\")\n        yield from self._resp_impl.transport.drain()\n\n    @asyncio.coroutine\n    def write_eof(self):\n        if self._eof_sent:\n            return\n        if self._resp_impl is None:\n            raise RuntimeError(\"Response has not been started\")\n\n        yield from self._resp_impl.write_eof()\n        self._eof_sent = True\n\n    def __repr__(self):\n        if self.started:\n            info = \"{} {} \".format(self._req.method, self._req.path)\n        else:\n            info = \"not started\"\n        return \"<{} {} {}>\".format(self.__class__.__name__,\n                                   self.reason, info)\n\n\nclass Response(StreamResponse):\n\n    def __init__(self, *, body=None, status=200,\n                 reason=None, text=None, headers=None, content_type=None):\n        super().__init__(status=status, reason=reason, headers=headers)\n\n        if body is not None and text is not None:\n            raise ValueError(\"body and text are not allowed together.\")\n\n        if text is not None:\n            if hdrs.CONTENT_TYPE not in self.headers:\n                # fast path for filling headers\n                if not isinstance(text, str):\n                    raise TypeError('text argument must be str (%r)' %\n                                    type(text))\n                if content_type is None:\n                    content_type = 'text/plain'\n                self.headers[hdrs.CONTENT_TYPE] = (\n                    content_type + '; charset=utf-8')\n                self._content_type = content_type\n                self._content_dict = {'charset': 'utf-8'}\n                self.body = text.encode('utf-8')\n            else:\n                self.text = text\n        else:\n            if content_type:\n                self.content_type = content_type\n            if body is not None:\n                self.body = body\n            else:\n                self.body = None\n\n    @property\n    def body(self):\n        return self._body\n\n    @body.setter\n    def body(self, body):\n        if body is not None and not isinstance(body, bytes):\n            raise TypeError('body argument must be bytes (%r)' % type(body))\n        self._body = body\n        if body is not None:\n            self.content_length = len(body)\n        else:\n            self.content_length = 0\n\n    @property\n    def text(self):\n        return self._body.decode(self.charset or 'utf-8')\n\n    @text.setter\n    def text(self, text):\n        if text is not None and not isinstance(text, str):\n            raise TypeError('text argument must be str (%r)' % type(text))\n\n        if self.content_type == 'application/octet-stream':\n            self.content_type = 'text/plain'\n        if self.charset is None:\n            self.charset = 'utf-8'\n\n        self.body = text.encode(self.charset)\n\n    @asyncio.coroutine\n    def write_eof(self):\n        body = self._body\n        if body is not None:\n            self.write(body)\n        yield from super().write_eof()\n"}
A user will ask you to solve a task. You should first draft your thinking process (inner monologue). Then, generate the solution.

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

**Description:**
When a `Response` object is created without a body (`response.body` is `None`), attempting to access the `response.text` property results in an `AttributeError`. This occurs because the code tries to decode `None` instead of handling the absence of a body gracefully.

**Example Buggy Code:**
```python
from aiohttp.web_reqrep import Response

resp = Response(status=200)
print(resp.text)  # Raises AttributeError: 'NoneType' object has no attribute 'decode'
```

**Expected Behavior:**
If `response.body` is `None`, accessing `response.text` should return `None` instead of raising an error. This allows for safer access to the text property without additional null checks.

[/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/web_reqrep.py
__all__ = ('ContentCoding', 'Request', 'StreamResponse', 'Response')

import asyncio
import binascii
import cgi
import collections
import datetime
import http.cookies
import io
import json
import math
import time
import warnings

import enum

from email.utils import parsedate
from types import MappingProxyType
from urllib.parse import urlsplit, parse_qsl, unquote

from . import hdrs
from .helpers import reify
from .multidict import (CIMultiDictProxy,
                        CIMultiDict,
                        MultiDictProxy,
                        MultiDict)
from .protocol import Response as ResponseImpl, HttpVersion10
from .streams import EOF_MARKER


sentinel = object()


class HeadersMixin:

    _content_type = None
    _content_dict = None
    _stored_content_type = sentinel

    def _parse_content_type(self, raw):
        self._stored_content_type = raw
        if raw is None:
            # default value according to RFC 2616
            self._content_type = 'application/octet-stream'
            self._content_dict = {}
        else:
            self._content_type, self._content_dict = cgi.parse_header(raw)

    @property
    def content_type(self, _CONTENT_TYPE=hdrs.CONTENT_TYPE):
        """The value of content part for Content-Type HTTP header."""
        raw = self.headers.get(_CONTENT_TYPE)
        if self._stored_content_type != raw:
            self._parse_content_type(raw)
        return self._content_type

    @property
    def charset(self, _CONTENT_TYPE=hdrs.CONTENT_TYPE):
        """The value of charset part for Content-Type HTTP header."""
        raw = self.headers.get(_CONTENT_TYPE)
        if self._stored_content_type != raw:
            self._parse_content_type(raw)
        return self._content_dict.get('charset')

    @property
    def content_length(self, _CONTENT_LENGTH=hdrs.CONTENT_LENGTH):
        """The value of Content-Length HTTP header."""
        l = self.headers.get(_CONTENT_LENGTH)
        if l is None:
            return None
        else:
            return int(l)

FileField = collections.namedtuple('Field', 'name filename file content_type')


class ContentCoding(enum.Enum):
    # The content codings that we have support for.
    #
    # Additional registered codings are listed at:
    # https://www.iana.org/assignments/http-parameters/http-parameters.xhtml#content-coding
    deflate = 'deflate'
    gzip = 'gzip'
    identity = 'identity'


############################################################
# HTTP Request
############################################################


class Request(dict, HeadersMixin):

    POST_METHODS = {hdrs.METH_PATCH, hdrs.METH_POST, hdrs.METH_PUT,
                    hdrs.METH_TRACE, hdrs.METH_DELETE}

    def __init__(self, app, message, payload, transport, reader, writer, *,
                 _HOST=hdrs.HOST, secure_proxy_ssl_header=None):
        self._app = app
        self._version = message.version
        self._transport = transport
        self._reader = reader
        self._writer = writer
        self._method = message.method
        self._host = message.headers.get(_HOST)
        self._path_qs = message.path
        self._post = None
        self._post_files_cache = None
        self._headers = CIMultiDictProxy(message.headers)
        if self._version < HttpVersion10:
            self._keep_alive = False
        else:
            self._keep_alive = not message.should_close

        # matchdict, route_name, handler
        # or information about traversal lookup
        self._match_info = None  # initialized after route resolving

        self._payload = payload
        self._cookies = None

        self._read_bytes = None
        self._has_body = not payload.at_eof()

        self._secure_proxy_ssl_header = secure_proxy_ssl_header

    @property
    def scheme(self):
        """A string representing the scheme of the request.

        'http' or 'https'.
        """
        if self._transport.get_extra_info('sslcontext'):
            return 'https'
        secure_proxy_ssl_header = self._secure_proxy_ssl_header
        if secure_proxy_ssl_header is not None:
            header, value = secure_proxy_ssl_header
            if self._headers.get(header) == value:
                return 'https'
        return 'http'

    @property
    def method(self):
        """Read only property for getting HTTP method.

        The value is upper-cased str like 'GET', 'POST', 'PUT' etc.
        """
        return self._method

    @property
    def version(self):
        """Read only property for getting HTTP version of request.

        Returns aiohttp.protocol.HttpVersion instance.
        """
        return self._version

    @property
    def host(self):
        """Read only property for getting *HOST* header of request.

        Returns str or None if HTTP request has no HOST header.
        """
        return self._host

    @property
    def path_qs(self):
        """The URL including PATH_INFO and the query string.

        E.g, /app/blog?id=10
        """
        return self._path_qs

    @reify
    def _splitted_path(self):
        return urlsplit(self._path_qs)

    @property
    def raw_path(self):
        """ The URL including raw *PATH INFO* without the host or scheme.
        Warning, the path is unquoted and may contains non valid URL characters

        E.g., ``/my%2Fpath%7Cwith%21some%25strange%24characters``
        """
        return self._splitted_path.path

    @reify
    def path(self):
        """The URL including *PATH INFO* without the host or scheme.

        E.g., ``/app/blog``
        """
        return unquote(self.raw_path)

    @reify
    def query_string(self):
        """The query string in the URL.

        E.g., id=10
        """
        return self._splitted_path.query

    @reify
    def GET(self):
        """A multidict with all the variables in the query string.

        Lazy property.
        """
        return MultiDictProxy(MultiDict(parse_qsl(self.query_string)))

    @reify
    def POST(self):
        """A multidict with all the variables in the POST parameters.

        post() methods has to be called before using this attribute.
        """
        if self._post is None:
            raise RuntimeError("POST is not available before post()")
        return self._post

    @property
    def headers(self):
        """A case-insensitive multidict proxy with all headers."""
        return self._headers

    @property
    def if_modified_since(self, _IF_MODIFIED_SINCE=hdrs.IF_MODIFIED_SINCE):
        """The value of If-Modified-Since HTTP header, or None.

        This header is represented as a `datetime` object.
        """
        httpdate = self.headers.get(_IF_MODIFIED_SINCE)
        if httpdate is not None:
            timetuple = parsedate(httpdate)
            if timetuple is not None:
                return datetime.datetime(*timetuple[:6],
                                         tzinfo=datetime.timezone.utc)
        return None

    @property
    def keep_alive(self):
        """Is keepalive enabled by client?"""
        return self._keep_alive

    @property
    def match_info(self):
        """Result of route resolving."""
        return self._match_info

    @property
    def app(self):
        """Application instance."""
        return self._app

    @property
    def transport(self):
        """Transport used for request processing."""
        return self._transport

    @property
    def cookies(self):
        """Return request cookies.

        A read-only dictionary-like object.
        """
        if self._cookies is None:
            raw = self.headers.get(hdrs.COOKIE, '')
            parsed = http.cookies.SimpleCookie(raw)
            self._cookies = MappingProxyType(
                {key: val.value for key, val in parsed.items()})
        return self._cookies

    @property
    def payload(self):
        """Return raw payload stream."""
        warnings.warn('use Request.content instead', DeprecationWarning)
        return self._payload

    @property
    def content(self):
        """Return raw payload stream."""
        return self._payload

    @property
    def has_body(self):
        """Return True if request has HTTP BODY, False otherwise."""
        return self._has_body

    @asyncio.coroutine
    def release(self):
        """Release request.

        Eat unread part of HTTP BODY if present.
        """
        chunk = yield from self._payload.readany()
        while chunk is not EOF_MARKER or chunk:
            chunk = yield from self._payload.readany()

    @asyncio.coroutine
    def read(self):
        """Read request body if present.

        Returns bytes object with full request content.
        """
        if self._read_bytes is None:
            body = bytearray()
            while True:
                chunk = yield from self._payload.readany()
                body.extend(chunk)
                if chunk is EOF_MARKER:
                    break
            self._read_bytes = bytes(body)
        return self._read_bytes

    @asyncio.coroutine
    def text(self):
        """Return BODY as text using encoding from .charset."""
        bytes_body = yield from self.read()
        encoding = self.charset or 'utf-8'
        return bytes_body.decode(encoding)

    @asyncio.coroutine
    def json(self, *, loader=json.loads):
        """Return BODY as JSON."""
        body = yield from self.text()
        return loader(body)

    @asyncio.coroutine
    def post(self):
        """Return POST parameters."""
        if self._post is not None:
            return self._post
        if self.method not in self.POST_METHODS:
            self._post = MultiDictProxy(MultiDict())
            return self._post

        content_type = self.content_type
        if (content_type not in ('',
                                 'application/x-www-form-urlencoded',
                                 'multipart/form-data')):
            self._post = MultiDictProxy(MultiDict())
            return self._post

        body = yield from self.read()
        content_charset = self.charset or 'utf-8'

        environ = {'REQUEST_METHOD': self.method,
                   'CONTENT_LENGTH': str(len(body)),
                   'QUERY_STRING': '',
                   'CONTENT_TYPE': self.headers.get(hdrs.CONTENT_TYPE)}

        fs = cgi.FieldStorage(fp=io.BytesIO(body),
                              environ=environ,
                              keep_blank_values=True,
                              encoding=content_charset)

        supported_transfer_encoding = {
            'base64': binascii.a2b_base64,
            'quoted-printable': binascii.a2b_qp
        }

        out = MultiDict()
        for field in fs.list or ():
            transfer_encoding = field.headers.get(
                hdrs.CONTENT_TRANSFER_ENCODING, None)
            if field.filename:
                ff = FileField(field.name,
                               field.filename,
                               field.file,  # N.B. file closed error
                               field.type)
                if self._post_files_cache is None:
                    self._post_files_cache = {}
                self._post_files_cache[field.name] = field
                out.add(field.name, ff)
            else:
                value = field.value
                if transfer_encoding in supported_transfer_encoding:
                    # binascii accepts bytes
                    value = value.encode('utf-8')
                    value = supported_transfer_encoding[
                        transfer_encoding](value)
                out.add(field.name, value)

        self._post = MultiDictProxy(out)
        return self._post

    def __repr__(self):
        return "<{} {} {} >".format(self.__class__.__name__,
                                    self.method, self.path)


############################################################
# HTTP Response classes
############################################################


class StreamResponse(HeadersMixin):

    def __init__(self, *, status=200, reason=None, headers=None):
        self._body = None
        self._keep_alive = None
        self._chunked = False
        self._chunk_size = None
        self._compression = False
        self._compression_force = False
        self._headers = CIMultiDict()
        self._cookies = http.cookies.SimpleCookie()
        self.set_status(status, reason)

        self._req = None
        self._resp_impl = None
        self._eof_sent = False

        if headers is not None:
            self._headers.extend(headers)

    def _copy_cookies(self):
        for cookie in self._cookies.values():
            value = cookie.output(header='')[1:]
            self.headers.add(hdrs.SET_COOKIE, value)

    @property
    def started(self):
        return self._resp_impl is not None

    @property
    def status(self):
        return self._status

    @property
    def chunked(self):
        return self._chunked

    @property
    def compression(self):
        return self._compression

    @property
    def reason(self):
        return self._reason

    def set_status(self, status, reason=None):
        self._status = int(status)
        if reason is None:
            reason = ResponseImpl.calc_reason(status)
        self._reason = reason

    @property
    def keep_alive(self):
        return self._keep_alive

    def force_close(self):
        self._keep_alive = False

    def enable_chunked_encoding(self, chunk_size=None):
        """Enables automatic chunked transfer encoding."""
        self._chunked = True
        self._chunk_size = chunk_size

    def enable_compression(self, force=None):
        """Enables response compression encoding."""
        # Backwards compatibility for when force was a bool <0.17.
        if type(force) == bool:
            force = ContentCoding.deflate if force else ContentCoding.identity

        self._compression = True
        self._compression_force = force

    @property
    def headers(self):
        return self._headers

    @property
    def cookies(self):
        return self._cookies

    def set_cookie(self, name, value, *, expires=None,
                   domain=None, max_age=None, path='/',
                   secure=None, httponly=None, version=None):
        """Set or update response cookie.

        Sets new cookie or updates existent with new value.
        Also updates only those params which are not None.
        """

        old = self._cookies.get(name)
        if old is not None and old.coded_value == '':
            # deleted cookie
            self._cookies.pop(name, None)

        self._cookies[name] = value
        c = self._cookies[name]
        if expires is not None:
            c['expires'] = expires
        if domain is not None:
            c['domain'] = domain
        if max_age is not None:
            c['max-age'] = max_age
        if path is not None:
            c['path'] = path
        if secure is not None:
            c['secure'] = secure
        if httponly is not None:
            c['httponly'] = httponly
        if version is not None:
            c['version'] = version

    def del_cookie(self, name, *, domain=None, path='/'):
        """Delete cookie.

        Creates new empty expired cookie.
        """
        # TODO: do we need domain/path here?
        self._cookies.pop(name, None)
        self.set_cookie(name, '', max_age=0, domain=domain, path=path)

    @property
    def content_length(self):
        # Just a placeholder for adding setter
        return super().content_length

    @content_length.setter
    def content_length(self, value):
        if value is not None:
            value = int(value)
            # TODO: raise error if chunked enabled
            self.headers[hdrs.CONTENT_LENGTH] = str(value)
        elif hdrs.CONTENT_LENGTH in self.headers:
            del self.headers[hdrs.CONTENT_LENGTH]

    @property
    def content_type(self):
        # Just a placeholder for adding setter
        return super().content_type

    @content_type.setter
    def content_type(self, value):
        self.content_type  # read header values if needed
        self._content_type = str(value)
        self._generate_content_type_header()

    @property
    def charset(self):
        # Just a placeholder for adding setter
        return super().charset

    @charset.setter
    def charset(self, value):
        ctype = self.content_type  # read header values if needed
        if ctype == 'application/octet-stream':
            raise RuntimeError("Setting charset for application/octet-stream "
                               "doesn't make sense, setup content_type first")
        if value is None:
            self._content_dict.pop('charset', None)
        else:
            self._content_dict['charset'] = str(value).lower()
        self._generate_content_type_header()

    @property
    def last_modified(self, _LAST_MODIFIED=hdrs.LAST_MODIFIED):
        """The value of Last-Modified HTTP header, or None.

        This header is represented as a `datetime` object.
        """
        httpdate = self.headers.get(_LAST_MODIFIED)
        if httpdate is not None:
            timetuple = parsedate(httpdate)
            if timetuple is not None:
                return datetime.datetime(*timetuple[:6],
                                         tzinfo=datetime.timezone.utc)
        return None

    @last_modified.setter
    def last_modified(self, value):
        if value is None:
            if hdrs.LAST_MODIFIED in self.headers:
                del self.headers[hdrs.LAST_MODIFIED]
        elif isinstance(value, (int, float)):
            self.headers[hdrs.LAST_MODIFIED] = time.strftime(
                "%a, %d %b %Y %H:%M:%S GMT", time.gmtime(math.ceil(value)))
        elif isinstance(value, datetime.datetime):
            self.headers[hdrs.LAST_MODIFIED] = time.strftime(
                "%a, %d %b %Y %H:%M:%S GMT", value.utctimetuple())
        elif isinstance(value, str):
            self.headers[hdrs.LAST_MODIFIED] = value

    def _generate_content_type_header(self, CONTENT_TYPE=hdrs.CONTENT_TYPE):
        params = '; '.join("%s=%s" % i for i in self._content_dict.items())
        if params:
            ctype = self._content_type + '; ' + params
        else:
            ctype = self._content_type
        self.headers[CONTENT_TYPE] = ctype

    def _start_pre_check(self, request):
        if self._resp_impl is not None:
            if self._req is not request:
                raise RuntimeError(
                    'Response has been started with different request.')
            else:
                return self._resp_impl
        else:
            return None

    def _start_compression(self, request):
        def start(coding):
            if coding != ContentCoding.identity:
                self.headers[hdrs.CONTENT_ENCODING] = coding.value
                self._resp_impl.add_compression_filter(coding.value)

        if self._compression_force:
            start(self._compression_force)
        else:
            accept_encoding = request.headers.get(
                hdrs.ACCEPT_ENCODING, '').lower()
            for coding in ContentCoding:
                if coding.value in accept_encoding:
                    start(coding)
                    return

    def start(self, request):
        resp_impl = self._start_pre_check(request)
        if resp_impl is not None:
            return resp_impl

        self._req = request
        keep_alive = self._keep_alive
        if keep_alive is None:
            keep_alive = request.keep_alive
        self._keep_alive = keep_alive

        resp_impl = self._resp_impl = ResponseImpl(
            request._writer,
            self._status,
            request.version,
            not keep_alive,
            self._reason)

        self._copy_cookies()

        if self._compression:
            self._start_compression(request)

        if self._chunked:
            resp_impl.enable_chunked_encoding()
            if self._chunk_size:
                resp_impl.add_chunking_filter(self._chunk_size)

        headers = self.headers.items()
        for key, val in headers:
            resp_impl.add_header(key, val)

        resp_impl.send_headers()
        return resp_impl

    def write(self, data):
        assert isinstance(data, (bytes, bytearray, memoryview)), \
            'data argument must be byte-ish (%r)' % type(data)

        if self._eof_sent:
            raise RuntimeError("Cannot call write() after write_eof()")
        if self._resp_impl is None:
            raise RuntimeError("Cannot call write() before start()")

        if data:
            return self._resp_impl.write(data)
        else:
            return ()

    @asyncio.coroutine
    def drain(self):
        if self._resp_impl is None:
            raise RuntimeError("Response has not been started")
        yield from self._resp_impl.transport.drain()

    @asyncio.coroutine
    def write_eof(self):
        if self._eof_sent:
            return
        if self._resp_impl is None:
            raise RuntimeError("Response has not been started")

        yield from self._resp_impl.write_eof()
        self._eof_sent = True

    def __repr__(self):
        if self.started:
            info = "{} {} ".format(self._req.method, self._req.path)
        else:
            info = "not started"
        return "<{} {} {}>".format(self.__class__.__name__,
                                   self.reason, info)


class Response(StreamResponse):

    def __init__(self, *, body=None, status=200,
                 reason=None, text=None, headers=None, content_type=None):
        super().__init__(status=status, reason=reason, headers=headers)

        if body is not None and text is not None:
            raise ValueError("body and text are not allowed together.")

        if text is not None:
            if hdrs.CONTENT_TYPE not in self.headers:
                # fast path for filling headers
                if not isinstance(text, str):
                    raise TypeError('text argument must be str (%r)' %
                                    type(text))
                if content_type is None:
                    content_type = 'text/plain'
                self.headers[hdrs.CONTENT_TYPE] = (
                    content_type + '; charset=utf-8')
                self._content_type = content_type
                self._content_dict = {'charset': 'utf-8'}
                self.body = text.encode('utf-8')
            else:
                self.text = text
        else:
            if content_type:
                self.content_type = content_type
            if body is not None:
                self.body = body
            else:
                self.body = None

    @property
    def body(self):
        return self._body

    @body.setter
    def body(self, body):
        if body is not None and not isinstance(body, bytes):
            raise TypeError('body argument must be bytes (%r)' % type(body))
        self._body = body
        if body is not None:
            self.content_length = len(body)
        else:
            self.content_length = 0

    @property
    def text(self):
        return self._body.decode(self.charset or 'utf-8')

    @text.setter
    def text(self, text):
        if text is not None and not isinstance(text, str):
            raise TypeError('text argument must be str (%r)' % type(text))

        if self.content_type == 'application/octet-stream':
            self.content_type = 'text/plain'
        if self.charset is None:
            self.charset = 'utf-8'

        self.body = text.encode(self.charset)

    @asyncio.coroutine
    def write_eof(self):
        body = self._body
        if body is not None:
            self.write(body)
        yield from super().write_eof()

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