{
    "file_diffs": [
        {
            "old_file_content": "\"\"\"Various helper functions\"\"\"\nimport base64\nimport io\nimport os\nimport urllib.parse\nfrom collections import namedtuple\nfrom wsgiref.handlers import format_date_time\n\nfrom . import hdrs, multidict\n\n__all__ = ('BasicAuth', 'FormData', 'parse_mimetype')\n\n\nclass BasicAuth(namedtuple('BasicAuth', ['login', 'password', 'encoding'])):\n    \"\"\"Http basic authentication helper.\n\n    :param str login: Login\n    :param str password: Password\n    :param str encoding: (optional) encoding ('latin1' by default)\n    \"\"\"\n\n    def __new__(cls, login, password='', encoding='latin1'):\n        if login is None:\n            raise ValueError('None is not allowed as login value')\n\n        if password is None:\n            raise ValueError('None is not allowed as password value')\n\n        return super().__new__(cls, login, password, encoding)\n\n    def encode(self):\n        \"\"\"Encode credentials.\"\"\"\n        creds = ('%s:%s' % (self.login, self.password)).encode(self.encoding)\n        return 'Basic %s' % base64.b64encode(creds).decode(self.encoding)\n\n\nclass FormData:\n    \"\"\"Helper class for multipart/form-data and\n    application/x-www-form-urlencoded body generation.\"\"\"\n\n    def __init__(self, fields=()):\n        from . import multipart\n        self._writer = multipart.MultipartWriter('form-data')\n        self._fields = []\n        self._is_multipart = False\n\n        if isinstance(fields, dict):\n            fields = list(fields.items())\n        elif not isinstance(fields, (list, tuple)):\n            fields = (fields,)\n        self.add_fields(*fields)\n\n    @property\n    def is_multipart(self):\n        return self._is_multipart\n\n    @property\n    def content_type(self):\n        if self._is_multipart:\n            return self._writer.headers[hdrs.CONTENT_TYPE]\n        else:\n            return 'application/x-www-form-urlencoded'\n\n    def add_field(self, name, value, *, content_type=None, filename=None,\n                  content_transfer_encoding=None):\n\n        if isinstance(value, io.IOBase):\n            self._is_multipart = True\n\n        type_options = multidict.MultiDict({'name': name})\n        if filename is None and isinstance(value, io.IOBase):\n            filename = guess_filename(value, name)\n        if filename is not None:\n            type_options['filename'] = filename\n            self._is_multipart = True\n\n        headers = {}\n        if content_type is not None:\n            headers[hdrs.CONTENT_TYPE] = content_type\n            self._is_multipart = True\n        if content_transfer_encoding is not None:\n            headers[hdrs.CONTENT_TRANSFER_ENCODING] = content_transfer_encoding\n            self._is_multipart = True\n\n        self._fields.append((type_options, headers, value))\n\n    def add_fields(self, *fields):\n        to_add = list(fields)\n\n        while to_add:\n            rec = to_add.pop(0)\n\n            if isinstance(rec, io.IOBase):\n                k = guess_filename(rec, 'unknown')\n                self.add_field(k, rec)\n\n            elif isinstance(rec,\n                            (multidict.MultiDictProxy,\n                             multidict.MultiDict)):\n                to_add.extend(rec.items())\n\n            elif isinstance(rec, (list, tuple)) and len(rec) == 2:\n                k, fp = rec\n                self.add_field(k, fp)\n\n            else:\n                raise TypeError('Only io.IOBase, multidict and (name, file) '\n                                'pairs allowed, use .add_field() for passing '\n                                'more complex parameters')\n\n    def _gen_form_urlencoded(self, encoding):\n        # form data (x-www-form-urlencoded)\n        data = []\n        for type_options, _, value in self._fields:\n            data.append((type_options['name'], value))\n\n        data = urllib.parse.urlencode(data, doseq=True)\n        return data.encode(encoding)\n\n    def _gen_form_data(self, *args, **kwargs):\n        \"\"\"Encode a list of fields using the multipart/form-data MIME format\"\"\"\n        for dispparams, headers, value in self._fields:\n            part = self._writer.append(value, headers)\n            if dispparams:\n                part.set_content_disposition('form-data', **dispparams)\n                # FIXME cgi.FieldStorage doesn't likes body parts with\n                # Content-Length which were sent via chunked transfer encoding\n                part.headers.pop(hdrs.CONTENT_LENGTH, None)\n        yield from self._writer.serialize()\n\n    def __call__(self, encoding):\n        if self._is_multipart:\n            return self._gen_form_data(encoding)\n        else:\n            return self._gen_form_urlencoded(encoding)\n\n\ndef parse_mimetype(mimetype):\n    \"\"\"Parses a MIME type into its components.\n\n    :param str mimetype: MIME type\n\n    :returns: 4 element tuple for MIME type, subtype, suffix and parameters\n    :rtype: tuple\n\n    Example:\n\n    >>> parse_mimetype('text/html; charset=utf-8')\n    ('text', 'html', '', {'charset': 'utf-8'})\n\n    \"\"\"\n    if not mimetype:\n        return '', '', '', {}\n\n    parts = mimetype.split(';')\n    params = []\n    for item in parts[1:]:\n        if not item:\n            continue\n        key, value = item.split('=', 1) if '=' in item else (item, '')\n        params.append((key.lower().strip(), value.strip(' \"')))\n    params = dict(params)\n\n    fulltype = parts[0].strip().lower()\n    if fulltype == '*':\n        fulltype = '*/*'\n\n    mtype, stype = fulltype.split('/', 1) \\\n        if '/' in fulltype else (fulltype, '')\n    stype, suffix = stype.split('+', 1) if '+' in stype else (stype, '')\n\n    return mtype, stype, suffix, params\n\n\ndef str_to_bytes(s, encoding='utf-8'):\n    if isinstance(s, str):\n        return s.encode(encoding)\n    return s\n\n\ndef guess_filename(obj, default=None):\n    name = getattr(obj, 'name', None)\n    if name and name[0] != '<' and name[-1] != '>':\n        return os.path.split(name)[-1]\n    return default\n\n\ndef parse_remote_addr(forward):\n    if isinstance(forward, str):\n        # we only took the last one\n        # http://en.wikipedia.org/wiki/X-Forwarded-For\n        if ',' in forward:\n            forward = forward.rsplit(',', 1)[-1].strip()\n\n        # find host and port on ipv6 address\n        if '[' in forward and ']' in forward:\n            host = forward.split(']')[0][1:].lower()\n        elif ':' in forward and forward.count(':') == 1:\n            host = forward.split(':')[0].lower()\n        else:\n            host = forward\n\n        forward = forward.split(']')[-1]\n        if ':' in forward and forward.count(':') == 1:\n            port = forward.split(':', 1)[1]\n        else:\n            port = 80\n\n        remote = (host, port)\n    else:\n        remote = forward\n\n    return remote[0], str(remote[1])\n\n\ndef atoms(message, environ, response, transport, request_time):\n    \"\"\"Gets atoms for log formatting.\"\"\"\n    if message:\n        r = '{} {} HTTP/{}.{}'.format(\n            message.method, message.path,\n            message.version[0], message.version[1])\n        headers = message.headers\n    else:\n        r = ''\n        headers = {}\n\n    if transport is not None:\n        remote_addr = parse_remote_addr(\n            transport.get_extra_info('addr', '127.0.0.1'))\n    else:\n        remote_addr = ('',)\n\n    atoms = {\n        'h': remote_addr[0],\n        'l': '-',\n        'u': '-',\n        't': format_date_time(None),\n        'r': r,\n        's': str(getattr(response, 'status', '')),\n        'b': str(getattr(response, 'output_length', '')),\n        'f': headers.get(hdrs.REFERER, '-'),\n        'a': headers.get(hdrs.USER_AGENT, '-'),\n        'T': str(int(request_time)),\n        'D': str(request_time).split('.', 1)[-1][:5],\n        'p': \"<%s>\" % os.getpid()\n    }\n\n    return atoms\n\n\nclass SafeAtoms(dict):\n    \"\"\"Copy from gunicorn\"\"\"\n\n    def __init__(self, atoms, i_headers, o_headers):\n        dict.__init__(self)\n\n        self._i_headers = i_headers\n        self._o_headers = o_headers\n\n        for key, value in atoms.items():\n            self[key] = value.replace('\"', '\\\\\"')\n\n    def __getitem__(self, k):\n        if k.startswith('{'):\n            if k.endswith('}i'):\n                headers = self._i_headers\n            elif k.endswith('}o'):\n                headers = self._o_headers\n            else:\n                headers = None\n\n            if headers is not None:\n                return headers.get(k[1:-2], '-')\n\n        if k in self:\n            return super(SafeAtoms, self).__getitem__(k)\n        else:\n            return '-'\n\n\nclass reify:\n    \"\"\"Use as a class method decorator.  It operates almost exactly like\n    the Python ``@property`` decorator, but it puts the result of the\n    method it decorates into the instance dict after the first call,\n    effectively replacing the function it decorates with an instance\n    variable.  It is, in Python parlance, a non-data descriptor.\n\n    \"\"\"\n\n    def __init__(self, wrapped):\n        self.wrapped = wrapped\n        try:\n            self.__doc__ = wrapped.__doc__\n        except:  # pragma: no cover\n            pass\n\n    def __get__(self, inst, objtype=None):\n        if inst is None:\n            return self\n        val = self.wrapped(inst)\n        setattr(inst, self.wrapped.__name__, val)\n        return val\n",
            "new_file_content": "\"\"\"Various helper functions\"\"\"\nimport base64\nimport io\nimport os\nimport urllib.parse\nfrom collections import namedtuple\nfrom wsgiref.handlers import format_date_time\n\nfrom . import hdrs, multidict\n\n__all__ = ('BasicAuth', 'FormData', 'parse_mimetype')\n\n\nclass BasicAuth(namedtuple('BasicAuth', ['login', 'password', 'encoding'])):\n    \"\"\"Http basic authentication helper.\n\n    :param str login: Login\n    :param str password: Password\n    :param str encoding: (optional) encoding ('latin1' by default)\n    \"\"\"\n\n    def __new__(cls, login, password='', encoding='latin1'):\n        if login is None:\n            raise ValueError('None is not allowed as login value')\n\n        if password is None:\n            raise ValueError('None is not allowed as password value')\n\n        return super().__new__(cls, login, password, encoding)\n\n    def encode(self):\n        \"\"\"Encode credentials.\"\"\"\n        creds = ('%s:%s' % (self.login, self.password)).encode(self.encoding)\n        return 'Basic %s' % base64.b64encode(creds).decode(self.encoding)\n\n\nclass FormData:\n    \"\"\"Helper class for multipart/form-data and\n    application/x-www-form-urlencoded body generation.\"\"\"\n\n    def __init__(self, fields=()):\n        from . import multipart\n        self._writer = multipart.MultipartWriter('form-data')\n        self._fields = []\n        self._is_multipart = False\n\n        if isinstance(fields, dict):\n            fields = list(fields.items())\n        elif not isinstance(fields, (list, tuple)):\n            fields = (fields,)\n        self.add_fields(*fields)\n\n    @property\n    def is_multipart(self):\n        return self._is_multipart\n\n    @property\n    def content_type(self):\n        if self._is_multipart:\n            return self._writer.headers[hdrs.CONTENT_TYPE]\n        else:\n            return 'application/x-www-form-urlencoded'\n\n    def add_field(self, name, value, *, content_type=None, filename=None,\n                  content_transfer_encoding=None):\n\n        if isinstance(value, io.IOBase):\n            self._is_multipart = True\n\n        type_options = multidict.MultiDict({'name': name})\n        if filename is not None and not isinstance(filename, str):\n            raise TypeError('filename must be an instance of str. '\n                            'Got: %s' % filename)\n        if filename is None and isinstance(value, io.IOBase):\n            filename = guess_filename(value, name)\n        if filename is not None:\n            type_options['filename'] = filename\n            self._is_multipart = True\n\n        headers = {}\n        if content_type is not None:\n            if not isinstance(content_type, str):\n                raise TypeError('content_type must be an instance of str. '\n                                'Got: %s' % content_type)\n            headers[hdrs.CONTENT_TYPE] = content_type\n            self._is_multipart = True\n        if content_transfer_encoding is not None:\n            if not isinstance(content_transfer_encoding, str):\n                raise TypeError('content_transfer_encoding must be an instance'\n                                ' of str. Got: %s' % content_transfer_encoding)\n            headers[hdrs.CONTENT_TRANSFER_ENCODING] = content_transfer_encoding\n            self._is_multipart = True\n\n        self._fields.append((type_options, headers, value))\n\n    def add_fields(self, *fields):\n        to_add = list(fields)\n\n        while to_add:\n            rec = to_add.pop(0)\n\n            if isinstance(rec, io.IOBase):\n                k = guess_filename(rec, 'unknown')\n                self.add_field(k, rec)\n\n            elif isinstance(rec,\n                            (multidict.MultiDictProxy,\n                             multidict.MultiDict)):\n                to_add.extend(rec.items())\n\n            elif isinstance(rec, (list, tuple)) and len(rec) == 2:\n                k, fp = rec\n                self.add_field(k, fp)\n\n            else:\n                raise TypeError('Only io.IOBase, multidict and (name, file) '\n                                'pairs allowed, use .add_field() for passing '\n                                'more complex parameters')\n\n    def _gen_form_urlencoded(self, encoding):\n        # form data (x-www-form-urlencoded)\n        data = []\n        for type_options, _, value in self._fields:\n            data.append((type_options['name'], value))\n\n        data = urllib.parse.urlencode(data, doseq=True)\n        return data.encode(encoding)\n\n    def _gen_form_data(self, *args, **kwargs):\n        \"\"\"Encode a list of fields using the multipart/form-data MIME format\"\"\"\n        for dispparams, headers, value in self._fields:\n            part = self._writer.append(value, headers)\n            if dispparams:\n                part.set_content_disposition('form-data', **dispparams)\n                # FIXME cgi.FieldStorage doesn't likes body parts with\n                # Content-Length which were sent via chunked transfer encoding\n                part.headers.pop(hdrs.CONTENT_LENGTH, None)\n        yield from self._writer.serialize()\n\n    def __call__(self, encoding):\n        if self._is_multipart:\n            return self._gen_form_data(encoding)\n        else:\n            return self._gen_form_urlencoded(encoding)\n\n\ndef parse_mimetype(mimetype):\n    \"\"\"Parses a MIME type into its components.\n\n    :param str mimetype: MIME type\n\n    :returns: 4 element tuple for MIME type, subtype, suffix and parameters\n    :rtype: tuple\n\n    Example:\n\n    >>> parse_mimetype('text/html; charset=utf-8')\n    ('text', 'html', '', {'charset': 'utf-8'})\n\n    \"\"\"\n    if not mimetype:\n        return '', '', '', {}\n\n    parts = mimetype.split(';')\n    params = []\n    for item in parts[1:]:\n        if not item:\n            continue\n        key, value = item.split('=', 1) if '=' in item else (item, '')\n        params.append((key.lower().strip(), value.strip(' \"')))\n    params = dict(params)\n\n    fulltype = parts[0].strip().lower()\n    if fulltype == '*':\n        fulltype = '*/*'\n\n    mtype, stype = fulltype.split('/', 1) \\\n        if '/' in fulltype else (fulltype, '')\n    stype, suffix = stype.split('+', 1) if '+' in stype else (stype, '')\n\n    return mtype, stype, suffix, params\n\n\ndef str_to_bytes(s, encoding='utf-8'):\n    if isinstance(s, str):\n        return s.encode(encoding)\n    return s\n\n\ndef guess_filename(obj, default=None):\n    name = getattr(obj, 'name', None)\n    if name and name[0] != '<' and name[-1] != '>':\n        return os.path.split(name)[-1]\n    return default\n\n\ndef parse_remote_addr(forward):\n    if isinstance(forward, str):\n        # we only took the last one\n        # http://en.wikipedia.org/wiki/X-Forwarded-For\n        if ',' in forward:\n            forward = forward.rsplit(',', 1)[-1].strip()\n\n        # find host and port on ipv6 address\n        if '[' in forward and ']' in forward:\n            host = forward.split(']')[0][1:].lower()\n        elif ':' in forward and forward.count(':') == 1:\n            host = forward.split(':')[0].lower()\n        else:\n            host = forward\n\n        forward = forward.split(']')[-1]\n        if ':' in forward and forward.count(':') == 1:\n            port = forward.split(':', 1)[1]\n        else:\n            port = 80\n\n        remote = (host, port)\n    else:\n        remote = forward\n\n    return remote[0], str(remote[1])\n\n\ndef atoms(message, environ, response, transport, request_time):\n    \"\"\"Gets atoms for log formatting.\"\"\"\n    if message:\n        r = '{} {} HTTP/{}.{}'.format(\n            message.method, message.path,\n            message.version[0], message.version[1])\n        headers = message.headers\n    else:\n        r = ''\n        headers = {}\n\n    if transport is not None:\n        remote_addr = parse_remote_addr(\n            transport.get_extra_info('addr', '127.0.0.1'))\n    else:\n        remote_addr = ('',)\n\n    atoms = {\n        'h': remote_addr[0],\n        'l': '-',\n        'u': '-',\n        't': format_date_time(None),\n        'r': r,\n        's': str(getattr(response, 'status', '')),\n        'b': str(getattr(response, 'output_length', '')),\n        'f': headers.get(hdrs.REFERER, '-'),\n        'a': headers.get(hdrs.USER_AGENT, '-'),\n        'T': str(int(request_time)),\n        'D': str(request_time).split('.', 1)[-1][:5],\n        'p': \"<%s>\" % os.getpid()\n    }\n\n    return atoms\n\n\nclass SafeAtoms(dict):\n    \"\"\"Copy from gunicorn\"\"\"\n\n    def __init__(self, atoms, i_headers, o_headers):\n        dict.__init__(self)\n\n        self._i_headers = i_headers\n        self._o_headers = o_headers\n\n        for key, value in atoms.items():\n            self[key] = value.replace('\"', '\\\\\"')\n\n    def __getitem__(self, k):\n        if k.startswith('{'):\n            if k.endswith('}i'):\n                headers = self._i_headers\n            elif k.endswith('}o'):\n                headers = self._o_headers\n            else:\n                headers = None\n\n            if headers is not None:\n                return headers.get(k[1:-2], '-')\n\n        if k in self:\n            return super(SafeAtoms, self).__getitem__(k)\n        else:\n            return '-'\n\n\nclass reify:\n    \"\"\"Use as a class method decorator.  It operates almost exactly like\n    the Python ``@property`` decorator, but it puts the result of the\n    method it decorates into the instance dict after the first call,\n    effectively replacing the function it decorates with an instance\n    variable.  It is, in Python parlance, a non-data descriptor.\n\n    \"\"\"\n\n    def __init__(self, wrapped):\n        self.wrapped = wrapped\n        try:\n            self.__doc__ = wrapped.__doc__\n        except:  # pragma: no cover\n            pass\n\n    def __get__(self, inst, objtype=None):\n        if inst is None:\n            return self\n        val = self.wrapped(inst)\n        setattr(inst, self.wrapped.__name__, val)\n        return val\n",
            "header": {
                "file": {
                    "path": "aiohttp/helpers.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "f2dfae0d",
                "new_commit_hash": "136f49a6",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/aiohttp/helpers.py"
            },
            "plus_file": {
                "path": "b/aiohttp/helpers.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 68,
                            "length": 6
                        },
                        "new_range": {
                            "start": 68,
                            "length": 9
                        },
                        "section": "class FormData:"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "            self._is_multipart = True",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        type_options = multidict.MultiDict({'name': name})",
                                "type": "context"
                            },
                            {
                                "content": "        if filename is not None and not isinstance(filename, str):",
                                "type": "added"
                            },
                            {
                                "content": "            raise TypeError('filename must be an instance of str. '",
                                "type": "added"
                            },
                            {
                                "content": "                            'Got: %s' % filename)",
                                "type": "added"
                            },
                            {
                                "content": "        if filename is None and isinstance(value, io.IOBase):",
                                "type": "context"
                            },
                            {
                                "content": "            filename = guess_filename(value, name)",
                                "type": "context"
                            },
                            {
                                "content": "        if filename is not None:",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "aiohttp/helpers.py",
                            "type": "method",
                            "name": "FormData.add_field",
                            "content": "class FormData:\n    \"\"\"Helper class for multipart/form-data and\n    application/x-www-form-urlencoded body generation.\"\"\"\n\n    def __init__(self, fields=()):\n        from . import multipart\n        self._writer = multipart.MultipartWriter('form-data')\n        self._fields = []\n        self._is_multipart = False\n\n        if isinstance(fields, dict):\n            fields = list(fields.items())\n        elif not isinstance(fields, (list, tuple)):\n            fields = (fields,)\n        self.add_fields(*fields)\n\n    @property\n    def is_multipart(self):\n        return self._is_multipart\n\n    @property\n    def content_type(self):\n        if self._is_multipart:\n            return self._writer.headers[hdrs.CONTENT_TYPE]\n        else:\n            return 'application/x-www-form-urlencoded'\n\n    def add_field(self, name, value, *, content_type=None, filename=None,\n                  content_transfer_encoding=None):\n\n        if isinstance(value, io.IOBase):\n            self._is_multipart = True\n\n        type_options = multidict.MultiDict({'name': name})\n        if filename is not None and not isinstance(filename, str):\n            raise TypeError('filename must be an instance of str. '\n                            'Got: %s' % filename)\n        if filename is None and isinstance(value, io.IOBase):\n            filename = guess_filename(value, name)\n        if filename is not None:\n            type_options['filename'] = filename\n            self._is_multipart = True\n\n        headers = {}\n        if content_type is not None:\n            if not isinstance(content_type, str):\n                raise TypeError('content_type must be an instance of str. '\n                                'Got: %s' % content_type)\n            headers[hdrs.CONTENT_TYPE] = content_type\n            self._is_multipart = True\n        if content_transfer_encoding is not None:\n            if not isinstance(content_transfer_encoding, str):\n                raise TypeError('content_transfer_encoding must be an instance'\n                                ' of str. Got: %s' % content_transfer_encoding)\n            headers[hdrs.CONTENT_TRANSFER_ENCODING] = content_transfer_encoding\n            self._is_multipart = True\n\n        self._fields.append((type_options, headers, value))\n\n    def add_fields(self, *fields):\n        to_add = list(fields)\n\n        while to_add:\n            rec = to_add.pop(0)\n\n            if isinstance(rec, io.IOBase):\n                k = guess_filename(rec, 'unknown')\n                self.add_field(k, rec)\n\n            elif isinstance(rec,\n                            (multidict.MultiDictProxy,\n                             multidict.MultiDict)):\n                to_add.extend(rec.items())\n\n            elif isinstance(rec, (list, tuple)) and len(rec) == 2:\n                k, fp = rec\n                self.add_field(k, fp)\n\n            else:\n                raise TypeError('Only io.IOBase, multidict and (name, file) '\n                                'pairs allowed, use .add_field() for passing '\n                                'more complex parameters')\n\n    def _gen_form_urlencoded(self, encoding):\n        # form data (x-www-form-urlencoded)\n        data = []\n        for type_options, _, value in self._fields:\n            data.append((type_options['name'], value))\n\n        data = urllib.parse.urlencode(data, doseq=True)\n        return data.encode(encoding)\n\n    def _gen_form_data(self, *args, **kwargs):\n        \"\"\"Encode a list of fields using the multipart/form-data MIME format\"\"\"\n        for dispparams, headers, value in self._fields:\n            part = self._writer.append(value, headers)\n            if dispparams:\n                part.set_content_disposition('form-data', **dispparams)\n                # FIXME cgi.FieldStorage doesn't likes body parts with\n                # Content-Length which were sent via chunked transfer encoding\n                part.headers.pop(hdrs.CONTENT_LENGTH, None)\n        yield from self._writer.serialize()\n\n    def __call__(self, encoding):\n        if self._is_multipart:\n            return self._gen_form_data(encoding)\n        else:\n            return self._gen_form_urlencoded(encoding)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 64,
                            "end_lineno": 94,
                            "parent": {
                                "file_name": "aiohttp/helpers.py",
                                "type": "class",
                                "name": "FormData",
                                "content": "class FormData:\n    \"\"\"Helper class for multipart/form-data and\n    application/x-www-form-urlencoded body generation.\"\"\"\n\n    def __init__(self, fields=()):\n        from . import multipart\n        self._writer = multipart.MultipartWriter('form-data')\n        self._fields = []\n        self._is_multipart = False\n\n        if isinstance(fields, dict):\n            fields = list(fields.items())\n        elif not isinstance(fields, (list, tuple)):\n            fields = (fields,)\n        self.add_fields(*fields)\n\n    @property\n    def is_multipart(self):\n        return self._is_multipart\n\n    @property\n    def content_type(self):\n        if self._is_multipart:\n            return self._writer.headers[hdrs.CONTENT_TYPE]\n        else:\n            return 'application/x-www-form-urlencoded'\n\n    def add_field(self, name, value, *, content_type=None, filename=None,\n                  content_transfer_encoding=None):\n\n        if isinstance(value, io.IOBase):\n            self._is_multipart = True\n\n        type_options = multidict.MultiDict({'name': name})\n        if filename is not None and not isinstance(filename, str):\n            raise TypeError('filename must be an instance of str. '\n                            'Got: %s' % filename)\n        if filename is None and isinstance(value, io.IOBase):\n            filename = guess_filename(value, name)\n        if filename is not None:\n            type_options['filename'] = filename\n            self._is_multipart = True\n\n        headers = {}\n        if content_type is not None:\n            if not isinstance(content_type, str):\n                raise TypeError('content_type must be an instance of str. '\n                                'Got: %s' % content_type)\n            headers[hdrs.CONTENT_TYPE] = content_type\n            self._is_multipart = True\n        if content_transfer_encoding is not None:\n            if not isinstance(content_transfer_encoding, str):\n                raise TypeError('content_transfer_encoding must be an instance'\n                                ' of str. Got: %s' % content_transfer_encoding)\n            headers[hdrs.CONTENT_TRANSFER_ENCODING] = content_transfer_encoding\n            self._is_multipart = True\n\n        self._fields.append((type_options, headers, value))\n\n    def add_fields(self, *fields):\n        to_add = list(fields)\n\n        while to_add:\n            rec = to_add.pop(0)\n\n            if isinstance(rec, io.IOBase):\n                k = guess_filename(rec, 'unknown')\n                self.add_field(k, rec)\n\n            elif isinstance(rec,\n                            (multidict.MultiDictProxy,\n                             multidict.MultiDict)):\n                to_add.extend(rec.items())\n\n            elif isinstance(rec, (list, tuple)) and len(rec) == 2:\n                k, fp = rec\n                self.add_field(k, fp)\n\n            else:\n                raise TypeError('Only io.IOBase, multidict and (name, file) '\n                                'pairs allowed, use .add_field() for passing '\n                                'more complex parameters')\n\n    def _gen_form_urlencoded(self, encoding):\n        # form data (x-www-form-urlencoded)\n        data = []\n        for type_options, _, value in self._fields:\n            data.append((type_options['name'], value))\n\n        data = urllib.parse.urlencode(data, doseq=True)\n        return data.encode(encoding)\n\n    def _gen_form_data(self, *args, **kwargs):\n        \"\"\"Encode a list of fields using the multipart/form-data MIME format\"\"\"\n        for dispparams, headers, value in self._fields:\n            part = self._writer.append(value, headers)\n            if dispparams:\n                part.set_content_disposition('form-data', **dispparams)\n                # FIXME cgi.FieldStorage doesn't likes body parts with\n                # Content-Length which were sent via chunked transfer encoding\n                part.headers.pop(hdrs.CONTENT_LENGTH, None)\n        yield from self._writer.serialize()\n\n    def __call__(self, encoding):\n        if self._is_multipart:\n            return self._gen_form_data(encoding)\n        else:\n            return self._gen_form_urlencoded(encoding)",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 37,
                                "end_lineno": 144,
                                "parent": null
                            }
                        },
                        {
                            "file_name": "aiohttp/helpers.py",
                            "type": "class",
                            "name": "FormData",
                            "content": "class FormData:\n    \"\"\"Helper class for multipart/form-data and\n    application/x-www-form-urlencoded body generation.\"\"\"\n\n    def __init__(self, fields=()):\n        from . import multipart\n        self._writer = multipart.MultipartWriter('form-data')\n        self._fields = []\n        self._is_multipart = False\n\n        if isinstance(fields, dict):\n            fields = list(fields.items())\n        elif not isinstance(fields, (list, tuple)):\n            fields = (fields,)\n        self.add_fields(*fields)\n\n    @property\n    def is_multipart(self):\n        return self._is_multipart\n\n    @property\n    def content_type(self):\n        if self._is_multipart:\n            return self._writer.headers[hdrs.CONTENT_TYPE]\n        else:\n            return 'application/x-www-form-urlencoded'\n\n    def add_field(self, name, value, *, content_type=None, filename=None,\n                  content_transfer_encoding=None):\n\n        if isinstance(value, io.IOBase):\n            self._is_multipart = True\n\n        type_options = multidict.MultiDict({'name': name})\n        if filename is not None and not isinstance(filename, str):\n            raise TypeError('filename must be an instance of str. '\n                            'Got: %s' % filename)\n        if filename is None and isinstance(value, io.IOBase):\n            filename = guess_filename(value, name)\n        if filename is not None:\n            type_options['filename'] = filename\n            self._is_multipart = True\n\n        headers = {}\n        if content_type is not None:\n            if not isinstance(content_type, str):\n                raise TypeError('content_type must be an instance of str. '\n                                'Got: %s' % content_type)\n            headers[hdrs.CONTENT_TYPE] = content_type\n            self._is_multipart = True\n        if content_transfer_encoding is not None:\n            if not isinstance(content_transfer_encoding, str):\n                raise TypeError('content_transfer_encoding must be an instance'\n                                ' of str. Got: %s' % content_transfer_encoding)\n            headers[hdrs.CONTENT_TRANSFER_ENCODING] = content_transfer_encoding\n            self._is_multipart = True\n\n        self._fields.append((type_options, headers, value))\n\n    def add_fields(self, *fields):\n        to_add = list(fields)\n\n        while to_add:\n            rec = to_add.pop(0)\n\n            if isinstance(rec, io.IOBase):\n                k = guess_filename(rec, 'unknown')\n                self.add_field(k, rec)\n\n            elif isinstance(rec,\n                            (multidict.MultiDictProxy,\n                             multidict.MultiDict)):\n                to_add.extend(rec.items())\n\n            elif isinstance(rec, (list, tuple)) and len(rec) == 2:\n                k, fp = rec\n                self.add_field(k, fp)\n\n            else:\n                raise TypeError('Only io.IOBase, multidict and (name, file) '\n                                'pairs allowed, use .add_field() for passing '\n                                'more complex parameters')\n\n    def _gen_form_urlencoded(self, encoding):\n        # form data (x-www-form-urlencoded)\n        data = []\n        for type_options, _, value in self._fields:\n            data.append((type_options['name'], value))\n\n        data = urllib.parse.urlencode(data, doseq=True)\n        return data.encode(encoding)\n\n    def _gen_form_data(self, *args, **kwargs):\n        \"\"\"Encode a list of fields using the multipart/form-data MIME format\"\"\"\n        for dispparams, headers, value in self._fields:\n            part = self._writer.append(value, headers)\n            if dispparams:\n                part.set_content_disposition('form-data', **dispparams)\n                # FIXME cgi.FieldStorage doesn't likes body parts with\n                # Content-Length which were sent via chunked transfer encoding\n                part.headers.pop(hdrs.CONTENT_LENGTH, None)\n        yield from self._writer.serialize()\n\n    def __call__(self, encoding):\n        if self._is_multipart:\n            return self._gen_form_data(encoding)\n        else:\n            return self._gen_form_urlencoded(encoding)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 37,
                            "end_lineno": 144,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 76,
                            "length": 9
                        },
                        "new_range": {
                            "start": 79,
                            "length": 15
                        },
                        "section": "class FormData:"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        headers = {}",
                                "type": "context"
                            },
                            {
                                "content": "        if content_type is not None:",
                                "type": "context"
                            },
                            {
                                "content": "            if not isinstance(content_type, str):",
                                "type": "added"
                            },
                            {
                                "content": "                raise TypeError('content_type must be an instance of str. '",
                                "type": "added"
                            },
                            {
                                "content": "                                'Got: %s' % content_type)",
                                "type": "added"
                            },
                            {
                                "content": "            headers[hdrs.CONTENT_TYPE] = content_type",
                                "type": "context"
                            },
                            {
                                "content": "            self._is_multipart = True",
                                "type": "context"
                            },
                            {
                                "content": "        if content_transfer_encoding is not None:",
                                "type": "context"
                            },
                            {
                                "content": "            if not isinstance(content_transfer_encoding, str):",
                                "type": "added"
                            },
                            {
                                "content": "                raise TypeError('content_transfer_encoding must be an instance'",
                                "type": "added"
                            },
                            {
                                "content": "                                ' of str. Got: %s' % content_transfer_encoding)",
                                "type": "added"
                            },
                            {
                                "content": "            headers[hdrs.CONTENT_TRANSFER_ENCODING] = content_transfer_encoding",
                                "type": "context"
                            },
                            {
                                "content": "            self._is_multipart = True",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "aiohttp/helpers.py",
                            "type": "method",
                            "name": "FormData.add_field",
                            "content": "class FormData:\n    \"\"\"Helper class for multipart/form-data and\n    application/x-www-form-urlencoded body generation.\"\"\"\n\n    def __init__(self, fields=()):\n        from . import multipart\n        self._writer = multipart.MultipartWriter('form-data')\n        self._fields = []\n        self._is_multipart = False\n\n        if isinstance(fields, dict):\n            fields = list(fields.items())\n        elif not isinstance(fields, (list, tuple)):\n            fields = (fields,)\n        self.add_fields(*fields)\n\n    @property\n    def is_multipart(self):\n        return self._is_multipart\n\n    @property\n    def content_type(self):\n        if self._is_multipart:\n            return self._writer.headers[hdrs.CONTENT_TYPE]\n        else:\n            return 'application/x-www-form-urlencoded'\n\n    def add_field(self, name, value, *, content_type=None, filename=None,\n                  content_transfer_encoding=None):\n\n        if isinstance(value, io.IOBase):\n            self._is_multipart = True\n\n        type_options = multidict.MultiDict({'name': name})\n        if filename is not None and not isinstance(filename, str):\n            raise TypeError('filename must be an instance of str. '\n                            'Got: %s' % filename)\n        if filename is None and isinstance(value, io.IOBase):\n            filename = guess_filename(value, name)\n        if filename is not None:\n            type_options['filename'] = filename\n            self._is_multipart = True\n\n        headers = {}\n        if content_type is not None:\n            if not isinstance(content_type, str):\n                raise TypeError('content_type must be an instance of str. '\n                                'Got: %s' % content_type)\n            headers[hdrs.CONTENT_TYPE] = content_type\n            self._is_multipart = True\n        if content_transfer_encoding is not None:\n            if not isinstance(content_transfer_encoding, str):\n                raise TypeError('content_transfer_encoding must be an instance'\n                                ' of str. Got: %s' % content_transfer_encoding)\n            headers[hdrs.CONTENT_TRANSFER_ENCODING] = content_transfer_encoding\n            self._is_multipart = True\n\n        self._fields.append((type_options, headers, value))\n\n    def add_fields(self, *fields):\n        to_add = list(fields)\n\n        while to_add:\n            rec = to_add.pop(0)\n\n            if isinstance(rec, io.IOBase):\n                k = guess_filename(rec, 'unknown')\n                self.add_field(k, rec)\n\n            elif isinstance(rec,\n                            (multidict.MultiDictProxy,\n                             multidict.MultiDict)):\n                to_add.extend(rec.items())\n\n            elif isinstance(rec, (list, tuple)) and len(rec) == 2:\n                k, fp = rec\n                self.add_field(k, fp)\n\n            else:\n                raise TypeError('Only io.IOBase, multidict and (name, file) '\n                                'pairs allowed, use .add_field() for passing '\n                                'more complex parameters')\n\n    def _gen_form_urlencoded(self, encoding):\n        # form data (x-www-form-urlencoded)\n        data = []\n        for type_options, _, value in self._fields:\n            data.append((type_options['name'], value))\n\n        data = urllib.parse.urlencode(data, doseq=True)\n        return data.encode(encoding)\n\n    def _gen_form_data(self, *args, **kwargs):\n        \"\"\"Encode a list of fields using the multipart/form-data MIME format\"\"\"\n        for dispparams, headers, value in self._fields:\n            part = self._writer.append(value, headers)\n            if dispparams:\n                part.set_content_disposition('form-data', **dispparams)\n                # FIXME cgi.FieldStorage doesn't likes body parts with\n                # Content-Length which were sent via chunked transfer encoding\n                part.headers.pop(hdrs.CONTENT_LENGTH, None)\n        yield from self._writer.serialize()\n\n    def __call__(self, encoding):\n        if self._is_multipart:\n            return self._gen_form_data(encoding)\n        else:\n            return self._gen_form_urlencoded(encoding)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 64,
                            "end_lineno": 94,
                            "parent": {
                                "file_name": "aiohttp/helpers.py",
                                "type": "class",
                                "name": "FormData",
                                "content": "class FormData:\n    \"\"\"Helper class for multipart/form-data and\n    application/x-www-form-urlencoded body generation.\"\"\"\n\n    def __init__(self, fields=()):\n        from . import multipart\n        self._writer = multipart.MultipartWriter('form-data')\n        self._fields = []\n        self._is_multipart = False\n\n        if isinstance(fields, dict):\n            fields = list(fields.items())\n        elif not isinstance(fields, (list, tuple)):\n            fields = (fields,)\n        self.add_fields(*fields)\n\n    @property\n    def is_multipart(self):\n        return self._is_multipart\n\n    @property\n    def content_type(self):\n        if self._is_multipart:\n            return self._writer.headers[hdrs.CONTENT_TYPE]\n        else:\n            return 'application/x-www-form-urlencoded'\n\n    def add_field(self, name, value, *, content_type=None, filename=None,\n                  content_transfer_encoding=None):\n\n        if isinstance(value, io.IOBase):\n            self._is_multipart = True\n\n        type_options = multidict.MultiDict({'name': name})\n        if filename is not None and not isinstance(filename, str):\n            raise TypeError('filename must be an instance of str. '\n                            'Got: %s' % filename)\n        if filename is None and isinstance(value, io.IOBase):\n            filename = guess_filename(value, name)\n        if filename is not None:\n            type_options['filename'] = filename\n            self._is_multipart = True\n\n        headers = {}\n        if content_type is not None:\n            if not isinstance(content_type, str):\n                raise TypeError('content_type must be an instance of str. '\n                                'Got: %s' % content_type)\n            headers[hdrs.CONTENT_TYPE] = content_type\n            self._is_multipart = True\n        if content_transfer_encoding is not None:\n            if not isinstance(content_transfer_encoding, str):\n                raise TypeError('content_transfer_encoding must be an instance'\n                                ' of str. Got: %s' % content_transfer_encoding)\n            headers[hdrs.CONTENT_TRANSFER_ENCODING] = content_transfer_encoding\n            self._is_multipart = True\n\n        self._fields.append((type_options, headers, value))\n\n    def add_fields(self, *fields):\n        to_add = list(fields)\n\n        while to_add:\n            rec = to_add.pop(0)\n\n            if isinstance(rec, io.IOBase):\n                k = guess_filename(rec, 'unknown')\n                self.add_field(k, rec)\n\n            elif isinstance(rec,\n                            (multidict.MultiDictProxy,\n                             multidict.MultiDict)):\n                to_add.extend(rec.items())\n\n            elif isinstance(rec, (list, tuple)) and len(rec) == 2:\n                k, fp = rec\n                self.add_field(k, fp)\n\n            else:\n                raise TypeError('Only io.IOBase, multidict and (name, file) '\n                                'pairs allowed, use .add_field() for passing '\n                                'more complex parameters')\n\n    def _gen_form_urlencoded(self, encoding):\n        # form data (x-www-form-urlencoded)\n        data = []\n        for type_options, _, value in self._fields:\n            data.append((type_options['name'], value))\n\n        data = urllib.parse.urlencode(data, doseq=True)\n        return data.encode(encoding)\n\n    def _gen_form_data(self, *args, **kwargs):\n        \"\"\"Encode a list of fields using the multipart/form-data MIME format\"\"\"\n        for dispparams, headers, value in self._fields:\n            part = self._writer.append(value, headers)\n            if dispparams:\n                part.set_content_disposition('form-data', **dispparams)\n                # FIXME cgi.FieldStorage doesn't likes body parts with\n                # Content-Length which were sent via chunked transfer encoding\n                part.headers.pop(hdrs.CONTENT_LENGTH, None)\n        yield from self._writer.serialize()\n\n    def __call__(self, encoding):\n        if self._is_multipart:\n            return self._gen_form_data(encoding)\n        else:\n            return self._gen_form_urlencoded(encoding)",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 37,
                                "end_lineno": 144,
                                "parent": null
                            }
                        },
                        {
                            "file_name": "aiohttp/helpers.py",
                            "type": "class",
                            "name": "FormData",
                            "content": "class FormData:\n    \"\"\"Helper class for multipart/form-data and\n    application/x-www-form-urlencoded body generation.\"\"\"\n\n    def __init__(self, fields=()):\n        from . import multipart\n        self._writer = multipart.MultipartWriter('form-data')\n        self._fields = []\n        self._is_multipart = False\n\n        if isinstance(fields, dict):\n            fields = list(fields.items())\n        elif not isinstance(fields, (list, tuple)):\n            fields = (fields,)\n        self.add_fields(*fields)\n\n    @property\n    def is_multipart(self):\n        return self._is_multipart\n\n    @property\n    def content_type(self):\n        if self._is_multipart:\n            return self._writer.headers[hdrs.CONTENT_TYPE]\n        else:\n            return 'application/x-www-form-urlencoded'\n\n    def add_field(self, name, value, *, content_type=None, filename=None,\n                  content_transfer_encoding=None):\n\n        if isinstance(value, io.IOBase):\n            self._is_multipart = True\n\n        type_options = multidict.MultiDict({'name': name})\n        if filename is not None and not isinstance(filename, str):\n            raise TypeError('filename must be an instance of str. '\n                            'Got: %s' % filename)\n        if filename is None and isinstance(value, io.IOBase):\n            filename = guess_filename(value, name)\n        if filename is not None:\n            type_options['filename'] = filename\n            self._is_multipart = True\n\n        headers = {}\n        if content_type is not None:\n            if not isinstance(content_type, str):\n                raise TypeError('content_type must be an instance of str. '\n                                'Got: %s' % content_type)\n            headers[hdrs.CONTENT_TYPE] = content_type\n            self._is_multipart = True\n        if content_transfer_encoding is not None:\n            if not isinstance(content_transfer_encoding, str):\n                raise TypeError('content_transfer_encoding must be an instance'\n                                ' of str. Got: %s' % content_transfer_encoding)\n            headers[hdrs.CONTENT_TRANSFER_ENCODING] = content_transfer_encoding\n            self._is_multipart = True\n\n        self._fields.append((type_options, headers, value))\n\n    def add_fields(self, *fields):\n        to_add = list(fields)\n\n        while to_add:\n            rec = to_add.pop(0)\n\n            if isinstance(rec, io.IOBase):\n                k = guess_filename(rec, 'unknown')\n                self.add_field(k, rec)\n\n            elif isinstance(rec,\n                            (multidict.MultiDictProxy,\n                             multidict.MultiDict)):\n                to_add.extend(rec.items())\n\n            elif isinstance(rec, (list, tuple)) and len(rec) == 2:\n                k, fp = rec\n                self.add_field(k, fp)\n\n            else:\n                raise TypeError('Only io.IOBase, multidict and (name, file) '\n                                'pairs allowed, use .add_field() for passing '\n                                'more complex parameters')\n\n    def _gen_form_urlencoded(self, encoding):\n        # form data (x-www-form-urlencoded)\n        data = []\n        for type_options, _, value in self._fields:\n            data.append((type_options['name'], value))\n\n        data = urllib.parse.urlencode(data, doseq=True)\n        return data.encode(encoding)\n\n    def _gen_form_data(self, *args, **kwargs):\n        \"\"\"Encode a list of fields using the multipart/form-data MIME format\"\"\"\n        for dispparams, headers, value in self._fields:\n            part = self._writer.append(value, headers)\n            if dispparams:\n                part.set_content_disposition('form-data', **dispparams)\n                # FIXME cgi.FieldStorage doesn't likes body parts with\n                # Content-Length which were sent via chunked transfer encoding\n                part.headers.pop(hdrs.CONTENT_LENGTH, None)\n        yield from self._writer.serialize()\n\n    def __call__(self, encoding):\n        if self._is_multipart:\n            return self._gen_form_data(encoding)\n        else:\n            return self._gen_form_urlencoded(encoding)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 37,
                            "end_lineno": 144,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "import unittest\nimport unittest.mock\n\nfrom aiohttp import helpers\nfrom aiohttp import MultiDict\n\n\nclass HelpersTests(unittest.TestCase):\n\n    def test_parse_mimetype(self):\n        self.assertEqual(\n            helpers.parse_mimetype(''), ('', '', '', {}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('*'), ('*', '*', '', {}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('application/json'),\n            ('application', 'json', '', {}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('application/json;  charset=utf-8'),\n            ('application', 'json', '', {'charset': 'utf-8'}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('''application/json; charset=utf-8;'''),\n            ('application', 'json', '', {'charset': 'utf-8'}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('ApPlIcAtIoN/JSON;ChaRseT=\"UTF-8\"'),\n            ('application', 'json', '', {'charset': 'UTF-8'}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('application/rss+xml'),\n            ('application', 'rss', 'xml', {}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('text/plain;base64'),\n            ('text', 'plain', '', {'base64': ''}))\n\n    def test_basic_auth(self):\n        # missing password here\n        self.assertRaises(\n            ValueError, helpers.BasicAuth, None)\n        self.assertRaises(\n            ValueError, helpers.BasicAuth, 'nkim', None)\n\n        auth = helpers.BasicAuth('nkim')\n        self.assertEqual(auth.login, 'nkim')\n        self.assertEqual(auth.password, '')\n\n        auth = helpers.BasicAuth('nkim', 'pwd')\n        self.assertEqual(auth.login, 'nkim')\n        self.assertEqual(auth.password, 'pwd')\n        self.assertEqual(auth.encode(), 'Basic bmtpbTpwd2Q=')\n\n    def test_invalid_formdata_params(self):\n        with self.assertRaises(TypeError):\n            helpers.FormData('asdasf')\n\n    def test_invalid_formdata_params2(self):\n        with self.assertRaises(TypeError):\n            helpers.FormData('as')  # 2-char str is not allowed\n\n    def test_reify(self):\n        class A:\n            @helpers.reify\n            def prop(self):\n                return 1\n\n        a = A()\n        self.assertEqual(1, a.prop)\n\n    def test_reify_class(self):\n        class A:\n            @helpers.reify\n            def prop(self):\n                \"\"\"Docstring.\"\"\"\n                return 1\n\n        self.assertIsInstance(A.prop, helpers.reify)\n        self.assertEqual('Docstring.', A.prop.__doc__)\n\n\nclass SafeAtomsTests(unittest.TestCase):\n\n    def test_get_non_existing(self):\n        atoms = helpers.SafeAtoms(\n            {}, MultiDict(), MultiDict())\n        self.assertEqual(atoms['unknown'], '-')\n\n    def test_get_lower(self):\n        i_headers = MultiDict([('test', '123')])\n        o_headers = MultiDict([('TEST', '123')])\n\n        atoms = helpers.SafeAtoms({}, i_headers, o_headers)\n        self.assertEqual(atoms['{test}i'], '123')\n        self.assertEqual(atoms['{test}o'], '-')\n        self.assertEqual(atoms['{TEST}o'], '123')\n        self.assertEqual(atoms['{UNKNOWN}o'], '-')\n        self.assertEqual(atoms['{UNKNOWN}'], '-')\n",
            "new_file_content": "import unittest\nimport unittest.mock\n\nfrom aiohttp import helpers\nfrom aiohttp import MultiDict\n\n\nclass HelpersTests(unittest.TestCase):\n\n    def test_parse_mimetype(self):\n        self.assertEqual(\n            helpers.parse_mimetype(''), ('', '', '', {}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('*'), ('*', '*', '', {}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('application/json'),\n            ('application', 'json', '', {}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('application/json;  charset=utf-8'),\n            ('application', 'json', '', {'charset': 'utf-8'}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('''application/json; charset=utf-8;'''),\n            ('application', 'json', '', {'charset': 'utf-8'}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('ApPlIcAtIoN/JSON;ChaRseT=\"UTF-8\"'),\n            ('application', 'json', '', {'charset': 'UTF-8'}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('application/rss+xml'),\n            ('application', 'rss', 'xml', {}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('text/plain;base64'),\n            ('text', 'plain', '', {'base64': ''}))\n\n    def test_basic_auth(self):\n        # missing password here\n        self.assertRaises(\n            ValueError, helpers.BasicAuth, None)\n        self.assertRaises(\n            ValueError, helpers.BasicAuth, 'nkim', None)\n\n        auth = helpers.BasicAuth('nkim')\n        self.assertEqual(auth.login, 'nkim')\n        self.assertEqual(auth.password, '')\n\n        auth = helpers.BasicAuth('nkim', 'pwd')\n        self.assertEqual(auth.login, 'nkim')\n        self.assertEqual(auth.password, 'pwd')\n        self.assertEqual(auth.encode(), 'Basic bmtpbTpwd2Q=')\n\n    def test_invalid_formdata_params(self):\n        with self.assertRaises(TypeError):\n            helpers.FormData('asdasf')\n\n    def test_invalid_formdata_params2(self):\n        with self.assertRaises(TypeError):\n            helpers.FormData('as')  # 2-char str is not allowed\n\n    def test_invalid_formdata_fields(self):\n        form = helpers.FormData()\n        invalid_vals = [0, 0.1, {}, []]\n        param_names = ['content_type', 'filename', 'content_transfer_encoding']\n        for param_name in param_names:\n            for invalid_val in invalid_vals:\n                with self.assertRaises(TypeError):\n                    form.add_field('foo', 'bar', **{param_name: invalid_val})\n\n    def test_reify(self):\n        class A:\n            @helpers.reify\n            def prop(self):\n                return 1\n\n        a = A()\n        self.assertEqual(1, a.prop)\n\n    def test_reify_class(self):\n        class A:\n            @helpers.reify\n            def prop(self):\n                \"\"\"Docstring.\"\"\"\n                return 1\n\n        self.assertIsInstance(A.prop, helpers.reify)\n        self.assertEqual('Docstring.', A.prop.__doc__)\n\n\nclass SafeAtomsTests(unittest.TestCase):\n\n    def test_get_non_existing(self):\n        atoms = helpers.SafeAtoms(\n            {}, MultiDict(), MultiDict())\n        self.assertEqual(atoms['unknown'], '-')\n\n    def test_get_lower(self):\n        i_headers = MultiDict([('test', '123')])\n        o_headers = MultiDict([('TEST', '123')])\n\n        atoms = helpers.SafeAtoms({}, i_headers, o_headers)\n        self.assertEqual(atoms['{test}i'], '123')\n        self.assertEqual(atoms['{test}o'], '-')\n        self.assertEqual(atoms['{TEST}o'], '123')\n        self.assertEqual(atoms['{UNKNOWN}o'], '-')\n        self.assertEqual(atoms['{UNKNOWN}'], '-')\n",
            "header": {
                "file": {
                    "path": "tests/test_helpers.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "3c3bbd5f",
                "new_commit_hash": "d9cbaf22",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/tests/test_helpers.py"
            },
            "plus_file": {
                "path": "b/tests/test_helpers.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 62,
                            "length": 6
                        },
                        "new_range": {
                            "start": 62,
                            "length": 15
                        },
                        "section": "class HelpersTests(unittest.TestCase):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        with self.assertRaises(TypeError):",
                                "type": "context"
                            },
                            {
                                "content": "            helpers.FormData('as')  # 2-char str is not allowed",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    def test_invalid_formdata_fields(self):",
                                "type": "added"
                            },
                            {
                                "content": "        form = helpers.FormData()",
                                "type": "added"
                            },
                            {
                                "content": "        invalid_vals = [0, 0.1, {}, []]",
                                "type": "added"
                            },
                            {
                                "content": "        param_names = ['content_type', 'filename', 'content_transfer_encoding']",
                                "type": "added"
                            },
                            {
                                "content": "        for param_name in param_names:",
                                "type": "added"
                            },
                            {
                                "content": "            for invalid_val in invalid_vals:",
                                "type": "added"
                            },
                            {
                                "content": "                with self.assertRaises(TypeError):",
                                "type": "added"
                            },
                            {
                                "content": "                    form.add_field('foo', 'bar', **{param_name: invalid_val})",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "    def test_reify(self):",
                                "type": "context"
                            },
                            {
                                "content": "        class A:",
                                "type": "context"
                            },
                            {
                                "content": "            @helpers.reify",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "tests/test_helpers.py",
                            "type": "class",
                            "name": "HelpersTests",
                            "content": "class HelpersTests(unittest.TestCase):\n\n    def test_parse_mimetype(self):\n        self.assertEqual(\n            helpers.parse_mimetype(''), ('', '', '', {}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('*'), ('*', '*', '', {}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('application/json'),\n            ('application', 'json', '', {}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('application/json;  charset=utf-8'),\n            ('application', 'json', '', {'charset': 'utf-8'}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('''application/json; charset=utf-8;'''),\n            ('application', 'json', '', {'charset': 'utf-8'}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('ApPlIcAtIoN/JSON;ChaRseT=\"UTF-8\"'),\n            ('application', 'json', '', {'charset': 'UTF-8'}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('application/rss+xml'),\n            ('application', 'rss', 'xml', {}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('text/plain;base64'),\n            ('text', 'plain', '', {'base64': ''}))\n\n    def test_basic_auth(self):\n        # missing password here\n        self.assertRaises(\n            ValueError, helpers.BasicAuth, None)\n        self.assertRaises(\n            ValueError, helpers.BasicAuth, 'nkim', None)\n\n        auth = helpers.BasicAuth('nkim')\n        self.assertEqual(auth.login, 'nkim')\n        self.assertEqual(auth.password, '')\n\n        auth = helpers.BasicAuth('nkim', 'pwd')\n        self.assertEqual(auth.login, 'nkim')\n        self.assertEqual(auth.password, 'pwd')\n        self.assertEqual(auth.encode(), 'Basic bmtpbTpwd2Q=')\n\n    def test_invalid_formdata_params(self):\n        with self.assertRaises(TypeError):\n            helpers.FormData('asdasf')\n\n    def test_invalid_formdata_params2(self):\n        with self.assertRaises(TypeError):\n            helpers.FormData('as')  # 2-char str is not allowed\n\n    def test_invalid_formdata_fields(self):\n        form = helpers.FormData()\n        invalid_vals = [0, 0.1, {}, []]\n        param_names = ['content_type', 'filename', 'content_transfer_encoding']\n        for param_name in param_names:\n            for invalid_val in invalid_vals:\n                with self.assertRaises(TypeError):\n                    form.add_field('foo', 'bar', **{param_name: invalid_val})\n\n    def test_reify(self):\n        class A:\n            @helpers.reify\n            def prop(self):\n                return 1\n\n        a = A()\n        self.assertEqual(1, a.prop)\n\n    def test_reify_class(self):\n        class A:\n            @helpers.reify\n            def prop(self):\n                \"\"\"Docstring.\"\"\"\n                return 1\n\n        self.assertIsInstance(A.prop, helpers.reify)\n        self.assertEqual('Docstring.', A.prop.__doc__)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 8,
                            "end_lineno": 91,
                            "parent": null
                        }
                    ],
                    "added_entities": [
                        {
                            "file_name": "tests/test_helpers.py",
                            "type": "method",
                            "name": "HelpersTests.test_invalid_formdata_fields",
                            "content": "class HelpersTests(unittest.TestCase):\n\n    def test_parse_mimetype(self):\n        self.assertEqual(\n            helpers.parse_mimetype(''), ('', '', '', {}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('*'), ('*', '*', '', {}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('application/json'),\n            ('application', 'json', '', {}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('application/json;  charset=utf-8'),\n            ('application', 'json', '', {'charset': 'utf-8'}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('''application/json; charset=utf-8;'''),\n            ('application', 'json', '', {'charset': 'utf-8'}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('ApPlIcAtIoN/JSON;ChaRseT=\"UTF-8\"'),\n            ('application', 'json', '', {'charset': 'UTF-8'}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('application/rss+xml'),\n            ('application', 'rss', 'xml', {}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('text/plain;base64'),\n            ('text', 'plain', '', {'base64': ''}))\n\n    def test_basic_auth(self):\n        # missing password here\n        self.assertRaises(\n            ValueError, helpers.BasicAuth, None)\n        self.assertRaises(\n            ValueError, helpers.BasicAuth, 'nkim', None)\n\n        auth = helpers.BasicAuth('nkim')\n        self.assertEqual(auth.login, 'nkim')\n        self.assertEqual(auth.password, '')\n\n        auth = helpers.BasicAuth('nkim', 'pwd')\n        self.assertEqual(auth.login, 'nkim')\n        self.assertEqual(auth.password, 'pwd')\n        self.assertEqual(auth.encode(), 'Basic bmtpbTpwd2Q=')\n\n    def test_invalid_formdata_params(self):\n        with self.assertRaises(TypeError):\n            helpers.FormData('asdasf')\n\n    def test_invalid_formdata_params2(self):\n        with self.assertRaises(TypeError):\n            helpers.FormData('as')  # 2-char str is not allowed\n\n    def test_invalid_formdata_fields(self):\n        form = helpers.FormData()\n        invalid_vals = [0, 0.1, {}, []]\n        param_names = ['content_type', 'filename', 'content_transfer_encoding']\n        for param_name in param_names:\n            for invalid_val in invalid_vals:\n                with self.assertRaises(TypeError):\n                    form.add_field('foo', 'bar', **{param_name: invalid_val})\n\n    def test_reify(self):\n        class A:\n            @helpers.reify\n            def prop(self):\n                return 1\n\n        a = A()\n        self.assertEqual(1, a.prop)\n\n    def test_reify_class(self):\n        class A:\n            @helpers.reify\n            def prop(self):\n                \"\"\"Docstring.\"\"\"\n                return 1\n\n        self.assertIsInstance(A.prop, helpers.reify)\n        self.assertEqual('Docstring.', A.prop.__doc__)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 65,
                            "end_lineno": 72,
                            "parent": {
                                "file_name": "tests/test_helpers.py",
                                "type": "class",
                                "name": "HelpersTests",
                                "content": "class HelpersTests(unittest.TestCase):\n\n    def test_parse_mimetype(self):\n        self.assertEqual(\n            helpers.parse_mimetype(''), ('', '', '', {}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('*'), ('*', '*', '', {}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('application/json'),\n            ('application', 'json', '', {}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('application/json;  charset=utf-8'),\n            ('application', 'json', '', {'charset': 'utf-8'}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('''application/json; charset=utf-8;'''),\n            ('application', 'json', '', {'charset': 'utf-8'}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('ApPlIcAtIoN/JSON;ChaRseT=\"UTF-8\"'),\n            ('application', 'json', '', {'charset': 'UTF-8'}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('application/rss+xml'),\n            ('application', 'rss', 'xml', {}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('text/plain;base64'),\n            ('text', 'plain', '', {'base64': ''}))\n\n    def test_basic_auth(self):\n        # missing password here\n        self.assertRaises(\n            ValueError, helpers.BasicAuth, None)\n        self.assertRaises(\n            ValueError, helpers.BasicAuth, 'nkim', None)\n\n        auth = helpers.BasicAuth('nkim')\n        self.assertEqual(auth.login, 'nkim')\n        self.assertEqual(auth.password, '')\n\n        auth = helpers.BasicAuth('nkim', 'pwd')\n        self.assertEqual(auth.login, 'nkim')\n        self.assertEqual(auth.password, 'pwd')\n        self.assertEqual(auth.encode(), 'Basic bmtpbTpwd2Q=')\n\n    def test_invalid_formdata_params(self):\n        with self.assertRaises(TypeError):\n            helpers.FormData('asdasf')\n\n    def test_invalid_formdata_params2(self):\n        with self.assertRaises(TypeError):\n            helpers.FormData('as')  # 2-char str is not allowed\n\n    def test_invalid_formdata_fields(self):\n        form = helpers.FormData()\n        invalid_vals = [0, 0.1, {}, []]\n        param_names = ['content_type', 'filename', 'content_transfer_encoding']\n        for param_name in param_names:\n            for invalid_val in invalid_vals:\n                with self.assertRaises(TypeError):\n                    form.add_field('foo', 'bar', **{param_name: invalid_val})\n\n    def test_reify(self):\n        class A:\n            @helpers.reify\n            def prop(self):\n                return 1\n\n        a = A()\n        self.assertEqual(1, a.prop)\n\n    def test_reify_class(self):\n        class A:\n            @helpers.reify\n            def prop(self):\n                \"\"\"Docstring.\"\"\"\n                return 1\n\n        self.assertIsInstance(A.prop, helpers.reify)\n        self.assertEqual('Docstring.', A.prop.__doc__)",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 8,
                                "end_lineno": 91,
                                "parent": null
                            }
                        }
                    ],
                    "deleted_entities": []
                }
            ]
        }
    ],
    "old_commit_hash": "dd5b9784e71ba3d4e806ea1020189b401479e977^",
    "new_commit_hash": "dd5b9784e71ba3d4e806ea1020189b401479e977",
    "commit_message": "Merge branch 'validate_formdata_add_field' of https://github.com/ttezel/aiohttp into ttezel-validate_formdata_add_field",
    "commit_date": "2015-04-19T20:08:20+03:00",
    "metadata": {}
}
{
    "repo_name": "aiohttp",
    "new_commit_hash": "dd5b9784e71ba3d4e806ea1020189b401479e977",
    "test_file_codes": [
        "import unittest\nimport unittest.mock\n\nfrom aiohttp import helpers\nfrom aiohttp import MultiDict\n\n\nclass HelpersTests(unittest.TestCase):\n\n    def test_parse_mimetype(self):\n        self.assertEqual(\n            helpers.parse_mimetype(''), ('', '', '', {}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('*'), ('*', '*', '', {}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('application/json'),\n            ('application', 'json', '', {}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('application/json;  charset=utf-8'),\n            ('application', 'json', '', {'charset': 'utf-8'}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('''application/json; charset=utf-8;'''),\n            ('application', 'json', '', {'charset': 'utf-8'}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('ApPlIcAtIoN/JSON;ChaRseT=\"UTF-8\"'),\n            ('application', 'json', '', {'charset': 'UTF-8'}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('application/rss+xml'),\n            ('application', 'rss', 'xml', {}))\n\n        self.assertEqual(\n            helpers.parse_mimetype('text/plain;base64'),\n            ('text', 'plain', '', {'base64': ''}))\n\n    def test_basic_auth(self):\n        # missing password here\n        self.assertRaises(\n            ValueError, helpers.BasicAuth, None)\n        self.assertRaises(\n            ValueError, helpers.BasicAuth, 'nkim', None)\n\n        auth = helpers.BasicAuth('nkim')\n        self.assertEqual(auth.login, 'nkim')\n        self.assertEqual(auth.password, '')\n\n        auth = helpers.BasicAuth('nkim', 'pwd')\n        self.assertEqual(auth.login, 'nkim')\n        self.assertEqual(auth.password, 'pwd')\n        self.assertEqual(auth.encode(), 'Basic bmtpbTpwd2Q=')\n\n    def test_invalid_formdata_params(self):\n        with self.assertRaises(TypeError):\n            helpers.FormData('asdasf')\n\n    def test_invalid_formdata_params2(self):\n        with self.assertRaises(TypeError):\n            helpers.FormData('as')  # 2-char str is not allowed\n\n    def test_invalid_formdata_fields(self):\n        form = helpers.FormData()\n        invalid_vals = [0, 0.1, {}, []]\n        param_names = ['content_type', 'filename', 'content_transfer_encoding']\n        for param_name in param_names:\n            for invalid_val in invalid_vals:\n                with self.assertRaises(TypeError):\n                    form.add_field('foo', 'bar', **{param_name: invalid_val})\n\n    def test_reify(self):\n        class A:\n            @helpers.reify\n            def prop(self):\n                return 1\n\n        a = A()\n        self.assertEqual(1, a.prop)\n\n    def test_reify_class(self):\n        class A:\n            @helpers.reify\n            def prop(self):\n                \"\"\"Docstring.\"\"\"\n                return 1\n\n        self.assertIsInstance(A.prop, helpers.reify)\n        self.assertEqual('Docstring.', A.prop.__doc__)\n\n\nclass SafeAtomsTests(unittest.TestCase):\n\n    def test_get_non_existing(self):\n        atoms = helpers.SafeAtoms(\n            {}, MultiDict(), MultiDict())\n        self.assertEqual(atoms['unknown'], '-')\n\n    def test_get_lower(self):\n        i_headers = MultiDict([('test', '123')])\n        o_headers = MultiDict([('TEST', '123')])\n\n        atoms = helpers.SafeAtoms({}, i_headers, o_headers)\n        self.assertEqual(atoms['{test}i'], '123')\n        self.assertEqual(atoms['{test}o'], '-')\n        self.assertEqual(atoms['{TEST}o'], '123')\n        self.assertEqual(atoms['{UNKNOWN}o'], '-')\n        self.assertEqual(atoms['{UNKNOWN}'], '-')\n"
    ],
    "test_file_names": [
        "test_1.py"
    ],
    "setup_res_code": 0,
    "setup_res_stdout": "Transforming aiohttp/worker.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 42ms\nInstalled 26 packages in 38ms\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.1\n + pytest-cov==6.0.0\n + pytest-mock==3.14.0\n + tomli==2.2.1\n + trustme==1.2.1\n + typing-extensions==4.12.2\n + yarl==1.18.3\n",
    "new_commit_res_code": 0,
    "new_commit_res_stdout": "============================= test session starts ==============================\nplatform linux -- Python 3.9.21, pytest-8.3.4, pluggy-1.5.0\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dd5b9784e71ba3d4e806ea1020189b401479e977\nplugins: mock-3.14.0, asyncio-0.25.1, cov-6.0.0\nasyncio: mode=strict, asyncio_default_fixture_loop_scope=None\ncollected 9 items\n\nr2e_tests/test_1.py .........                                            [100%]\n\n==================================== PASSES ====================================\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::HelpersTests::test_basic_auth\nPASSED r2e_tests/test_1.py::HelpersTests::test_invalid_formdata_fields\nPASSED r2e_tests/test_1.py::HelpersTests::test_invalid_formdata_params\nPASSED r2e_tests/test_1.py::HelpersTests::test_invalid_formdata_params2\nPASSED r2e_tests/test_1.py::HelpersTests::test_parse_mimetype\nPASSED r2e_tests/test_1.py::HelpersTests::test_reify\nPASSED r2e_tests/test_1.py::HelpersTests::test_reify_class\nPASSED r2e_tests/test_1.py::SafeAtomsTests::test_get_lower\nPASSED r2e_tests/test_1.py::SafeAtomsTests::test_get_non_existing\n============================== 9 passed in 0.33s ===============================\n",
    "new_commit_res_stderr": "/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dd5b9784e71ba3d4e806ea1020189b401479e977/.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_dd5b9784e71ba3d4e806ea1020189b401479e977\nplugins: mock-3.14.0, asyncio-0.25.1, cov-6.0.0\nasyncio: mode=strict, asyncio_default_fixture_loop_scope=None\ncollected 9 items\n\nr2e_tests/test_1.py .F.......                                            [100%]\n\n=================================== FAILURES ===================================\n__________________ HelpersTests.test_invalid_formdata_fields ___________________\n\nself = <r2e_tests.test_1.HelpersTests testMethod=test_invalid_formdata_fields>\n\n    def test_invalid_formdata_fields(self):\n        form = helpers.FormData()\n        invalid_vals = [0, 0.1, {}, []]\n        param_names = ['content_type', 'filename', 'content_transfer_encoding']\n        for param_name in param_names:\n            for invalid_val in invalid_vals:\n                with self.assertRaises(TypeError):\n>                   form.add_field('foo', 'bar', **{param_name: invalid_val})\nE                   AssertionError: TypeError not raised\n\nr2e_tests/test_1.py:72: AssertionError\n==================================== PASSES ====================================\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::HelpersTests::test_basic_auth\nPASSED r2e_tests/test_1.py::HelpersTests::test_invalid_formdata_params\nPASSED r2e_tests/test_1.py::HelpersTests::test_invalid_formdata_params2\nPASSED r2e_tests/test_1.py::HelpersTests::test_parse_mimetype\nPASSED r2e_tests/test_1.py::HelpersTests::test_reify\nPASSED r2e_tests/test_1.py::HelpersTests::test_reify_class\nPASSED r2e_tests/test_1.py::SafeAtomsTests::test_get_lower\nPASSED r2e_tests/test_1.py::SafeAtomsTests::test_get_non_existing\nFAILED r2e_tests/test_1.py::HelpersTests::test_invalid_formdata_fields - Asse...\n========================= 1 failed, 8 passed in 0.11s ==========================\n",
    "old_commit_res_stderr": "/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_dd5b9784e71ba3d4e806ea1020189b401479e977/.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/helpers.py tests/test_helpers.py
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]
**Title:** `FormData.add_field` Does Not Validate Parameter Types, Allowing Non-String Inputs

**Description:**
When using the `FormData.add_field` method, providing non-string types for parameters such as `filename`, `content_type`, or `content_transfer_encoding` does not raise a `TypeError`. This oversight can lead to unexpected behavior or errors further down the processing pipeline.

**Example Code:**
```python
form = FormData()
# Attempting to add a field with an integer filename
form.add_field('file', 'content', filename=123)

# Attempting to add a field with a list as content_type
form.add_field('file', 'content', content_type=['text/plain'])
```

**Expected Behavior:**
The method should raise a `TypeError` when non-string types are provided for `filename`, `content_type`, or `content_transfer_encoding`. This validation ensures that only appropriate types are accepted, preventing potential issues during form data processing.

**Actual Behavior:**
No error is raised when non-string types are used for the specified parameters. This lack of validation allows invalid data to be processed, which can cause unexpected errors or malfunctioning of the form handling mechanism.

[/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/helpers.py
"""Various helper functions"""
import base64
import io
import os
import urllib.parse
from collections import namedtuple
from wsgiref.handlers import format_date_time

from . import hdrs, multidict

__all__ = ('BasicAuth', 'FormData', 'parse_mimetype')


class BasicAuth(namedtuple('BasicAuth', ['login', 'password', 'encoding'])):
    """Http basic authentication helper.

    :param str login: Login
    :param str password: Password
    :param str encoding: (optional) encoding ('latin1' by default)
    """

    def __new__(cls, login, password='', encoding='latin1'):
        if login is None:
            raise ValueError('None is not allowed as login value')

        if password is None:
            raise ValueError('None is not allowed as password value')

        return super().__new__(cls, login, password, encoding)

    def encode(self):
        """Encode credentials."""
        creds = ('%s:%s' % (self.login, self.password)).encode(self.encoding)
        return 'Basic %s' % base64.b64encode(creds).decode(self.encoding)


class FormData:
    """Helper class for multipart/form-data and
    application/x-www-form-urlencoded body generation."""

    def __init__(self, fields=()):
        from . import multipart
        self._writer = multipart.MultipartWriter('form-data')
        self._fields = []
        self._is_multipart = False

        if isinstance(fields, dict):
            fields = list(fields.items())
        elif not isinstance(fields, (list, tuple)):
            fields = (fields,)
        self.add_fields(*fields)

    @property
    def is_multipart(self):
        return self._is_multipart

    @property
    def content_type(self):
        if self._is_multipart:
            return self._writer.headers[hdrs.CONTENT_TYPE]
        else:
            return 'application/x-www-form-urlencoded'

    def add_field(self, name, value, *, content_type=None, filename=None,
                  content_transfer_encoding=None):

        if isinstance(value, io.IOBase):
            self._is_multipart = True

        type_options = multidict.MultiDict({'name': name})
        if filename is None and isinstance(value, io.IOBase):
            filename = guess_filename(value, name)
        if filename is not None:
            type_options['filename'] = filename
            self._is_multipart = True

        headers = {}
        if content_type is not None:
            headers[hdrs.CONTENT_TYPE] = content_type
            self._is_multipart = True
        if content_transfer_encoding is not None:
            headers[hdrs.CONTENT_TRANSFER_ENCODING] = content_transfer_encoding
            self._is_multipart = True

        self._fields.append((type_options, headers, value))

    def add_fields(self, *fields):
        to_add = list(fields)

        while to_add:
            rec = to_add.pop(0)

            if isinstance(rec, io.IOBase):
                k = guess_filename(rec, 'unknown')
                self.add_field(k, rec)

            elif isinstance(rec,
                            (multidict.MultiDictProxy,
                             multidict.MultiDict)):
                to_add.extend(rec.items())

            elif isinstance(rec, (list, tuple)) and len(rec) == 2:
                k, fp = rec
                self.add_field(k, fp)

            else:
                raise TypeError('Only io.IOBase, multidict and (name, file) '
                                'pairs allowed, use .add_field() for passing '
                                'more complex parameters')

    def _gen_form_urlencoded(self, encoding):
        # form data (x-www-form-urlencoded)
        data = []
        for type_options, _, value in self._fields:
            data.append((type_options['name'], value))

        data = urllib.parse.urlencode(data, doseq=True)
        return data.encode(encoding)

    def _gen_form_data(self, *args, **kwargs):
        """Encode a list of fields using the multipart/form-data MIME format"""
        for dispparams, headers, value in self._fields:
            part = self._writer.append(value, headers)
            if dispparams:
                part.set_content_disposition('form-data', **dispparams)
                # FIXME cgi.FieldStorage doesn't likes body parts with
                # Content-Length which were sent via chunked transfer encoding
                part.headers.pop(hdrs.CONTENT_LENGTH, None)
        yield from self._writer.serialize()

    def __call__(self, encoding):
        if self._is_multipart:
            return self._gen_form_data(encoding)
        else:
            return self._gen_form_urlencoded(encoding)


def parse_mimetype(mimetype):
    """Parses a MIME type into its components.

    :param str mimetype: MIME type

    :returns: 4 element tuple for MIME type, subtype, suffix and parameters
    :rtype: tuple

    Example:

    >>> parse_mimetype('text/html; charset=utf-8')
    ('text', 'html', '', {'charset': 'utf-8'})

    """
    if not mimetype:
        return '', '', '', {}

    parts = mimetype.split(';')
    params = []
    for item in parts[1:]:
        if not item:
            continue
        key, value = item.split('=', 1) if '=' in item else (item, '')
        params.append((key.lower().strip(), value.strip(' "')))
    params = dict(params)

    fulltype = parts[0].strip().lower()
    if fulltype == '*':
        fulltype = '*/*'

    mtype, stype = fulltype.split('/', 1) \
        if '/' in fulltype else (fulltype, '')
    stype, suffix = stype.split('+', 1) if '+' in stype else (stype, '')

    return mtype, stype, suffix, params


def str_to_bytes(s, encoding='utf-8'):
    if isinstance(s, str):
        return s.encode(encoding)
    return s


def guess_filename(obj, default=None):
    name = getattr(obj, 'name', None)
    if name and name[0] != '<' and name[-1] != '>':
        return os.path.split(name)[-1]
    return default


def parse_remote_addr(forward):
    if isinstance(forward, str):
        # we only took the last one
        # http://en.wikipedia.org/wiki/X-Forwarded-For
        if ',' in forward:
            forward = forward.rsplit(',', 1)[-1].strip()

        # find host and port on ipv6 address
        if '[' in forward and ']' in forward:
            host = forward.split(']')[0][1:].lower()
        elif ':' in forward and forward.count(':') == 1:
            host = forward.split(':')[0].lower()
        else:
            host = forward

        forward = forward.split(']')[-1]
        if ':' in forward and forward.count(':') == 1:
            port = forward.split(':', 1)[1]
        else:
            port = 80

        remote = (host, port)
    else:
        remote = forward

    return remote[0], str(remote[1])


def atoms(message, environ, response, transport, request_time):
    """Gets atoms for log formatting."""
    if message:
        r = '{} {} HTTP/{}.{}'.format(
            message.method, message.path,
            message.version[0], message.version[1])
        headers = message.headers
    else:
        r = ''
        headers = {}

    if transport is not None:
        remote_addr = parse_remote_addr(
            transport.get_extra_info('addr', '127.0.0.1'))
    else:
        remote_addr = ('',)

    atoms = {
        'h': remote_addr[0],
        'l': '-',
        'u': '-',
        't': format_date_time(None),
        'r': r,
        's': str(getattr(response, 'status', '')),
        'b': str(getattr(response, 'output_length', '')),
        'f': headers.get(hdrs.REFERER, '-'),
        'a': headers.get(hdrs.USER_AGENT, '-'),
        'T': str(int(request_time)),
        'D': str(request_time).split('.', 1)[-1][:5],
        'p': "<%s>" % os.getpid()
    }

    return atoms


class SafeAtoms(dict):
    """Copy from gunicorn"""

    def __init__(self, atoms, i_headers, o_headers):
        dict.__init__(self)

        self._i_headers = i_headers
        self._o_headers = o_headers

        for key, value in atoms.items():
            self[key] = value.replace('"', '\\"')

    def __getitem__(self, k):
        if k.startswith('{'):
            if k.endswith('}i'):
                headers = self._i_headers
            elif k.endswith('}o'):
                headers = self._o_headers
            else:
                headers = None

            if headers is not None:
                return headers.get(k[1:-2], '-')

        if k in self:
            return super(SafeAtoms, self).__getitem__(k)
        else:
            return '-'


class reify:
    """Use as a class method decorator.  It operates almost exactly like
    the Python ``@property`` decorator, but it puts the result of the
    method it decorates into the instance dict after the first call,
    effectively replacing the function it decorates with an instance
    variable.  It is, in Python parlance, a non-data descriptor.

    """

    def __init__(self, wrapped):
        self.wrapped = wrapped
        try:
            self.__doc__ = wrapped.__doc__
        except:  # pragma: no cover
            pass

    def __get__(self, inst, objtype=None):
        if inst is None:
            return self
        val = self.wrapped(inst)
        setattr(inst, self.wrapped.__name__, val)
        return val

```
--- 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:** `FormData.add_field` Does Not Validate Parameter Types, Allowing Non-String Inputs

**Description:**
When using the `FormData.add_field` method, providing non-string types for parameters such as `filename`, `content_type`, or `content_transfer_encoding` does not raise a `TypeError`. This oversight can lead to unexpected behavior or errors further down the processing pipeline.

**Example Code:**
```python
form = FormData()
# Attempting to add a field with an integer filename
form.add_field('file', 'content', filename=123)

# Attempting to add a field with a list as content_type
form.add_field('file', 'content', content_type=['text/plain'])
```

**Expected Behavior:**
The method should raise a `TypeError` when non-string types are provided for `filename`, `content_type`, or `content_transfer_encoding`. This validation ensures that only appropriate types are accepted, preventing potential issues during form data processing.

**Actual Behavior:**
No error is raised when non-string types are used for the specified parameters. This lack of validation allows invalid data to be processed, which can cause unexpected errors or malfunctioning of the form handling mechanism.

[/ISSUE]
{
    "HelpersTests.test_basic_auth": "PASSED",
    "HelpersTests.test_invalid_formdata_fields": "PASSED",
    "HelpersTests.test_invalid_formdata_params": "PASSED",
    "HelpersTests.test_invalid_formdata_params2": "PASSED",
    "HelpersTests.test_parse_mimetype": "PASSED",
    "HelpersTests.test_reify": "PASSED",
    "HelpersTests.test_reify_class": "PASSED",
    "SafeAtomsTests.test_get_lower": "PASSED",
    "SafeAtomsTests.test_get_non_existing": "PASSED"
}
diff --git a/aiohttp/helpers.py b/aiohttp/helpers.py
index f2dfae0d..136f49a6 100644
--- a/aiohttp/helpers.py
+++ b/aiohttp/helpers.py
@@ -68,6 +68,9 @@ class FormData:
             self._is_multipart = True
 
         type_options = multidict.MultiDict({'name': name})
+        if filename is not None and not isinstance(filename, str):
+            raise TypeError('filename must be an instance of str. '
+                            'Got: %s' % filename)
         if filename is None and isinstance(value, io.IOBase):
             filename = guess_filename(value, name)
         if filename is not None:
@@ -76,9 +79,15 @@ class FormData:
 
         headers = {}
         if content_type is not None:
+            if not isinstance(content_type, str):
+                raise TypeError('content_type must be an instance of str. '
+                                'Got: %s' % content_type)
             headers[hdrs.CONTENT_TYPE] = content_type
             self._is_multipart = True
         if content_transfer_encoding is not None:
+            if not isinstance(content_transfer_encoding, str):
+                raise TypeError('content_transfer_encoding must be an instance'
+                                ' of str. Got: %s' % content_transfer_encoding)
             headers[hdrs.CONTENT_TRANSFER_ENCODING] = content_transfer_encoding
             self._is_multipart = True
 

{"aiohttp/helpers.py": "\"\"\"Various helper functions\"\"\"\nimport base64\nimport io\nimport os\nimport urllib.parse\nfrom collections import namedtuple\nfrom wsgiref.handlers import format_date_time\n\nfrom . import hdrs, multidict\n\n__all__ = ('BasicAuth', 'FormData', 'parse_mimetype')\n\n\nclass BasicAuth(namedtuple('BasicAuth', ['login', 'password', 'encoding'])):\n    \"\"\"Http basic authentication helper.\n\n    :param str login: Login\n    :param str password: Password\n    :param str encoding: (optional) encoding ('latin1' by default)\n    \"\"\"\n\n    def __new__(cls, login, password='', encoding='latin1'):\n        if login is None:\n            raise ValueError('None is not allowed as login value')\n\n        if password is None:\n            raise ValueError('None is not allowed as password value')\n\n        return super().__new__(cls, login, password, encoding)\n\n    def encode(self):\n        \"\"\"Encode credentials.\"\"\"\n        creds = ('%s:%s' % (self.login, self.password)).encode(self.encoding)\n        return 'Basic %s' % base64.b64encode(creds).decode(self.encoding)\n\n\nclass FormData:\n    \"\"\"Helper class for multipart/form-data and\n    application/x-www-form-urlencoded body generation.\"\"\"\n\n    def __init__(self, fields=()):\n        from . import multipart\n        self._writer = multipart.MultipartWriter('form-data')\n        self._fields = []\n        self._is_multipart = False\n\n        if isinstance(fields, dict):\n            fields = list(fields.items())\n        elif not isinstance(fields, (list, tuple)):\n            fields = (fields,)\n        self.add_fields(*fields)\n\n    @property\n    def is_multipart(self):\n        return self._is_multipart\n\n    @property\n    def content_type(self):\n        if self._is_multipart:\n            return self._writer.headers[hdrs.CONTENT_TYPE]\n        else:\n            return 'application/x-www-form-urlencoded'\n\n    def add_field(self, name, value, *, content_type=None, filename=None,\n                  content_transfer_encoding=None):\n\n        if isinstance(value, io.IOBase):\n            self._is_multipart = True\n\n        type_options = multidict.MultiDict({'name': name})\n        if filename is None and isinstance(value, io.IOBase):\n            filename = guess_filename(value, name)\n        if filename is not None:\n            type_options['filename'] = filename\n            self._is_multipart = True\n\n        headers = {}\n        if content_type is not None:\n            headers[hdrs.CONTENT_TYPE] = content_type\n            self._is_multipart = True\n        if content_transfer_encoding is not None:\n            headers[hdrs.CONTENT_TRANSFER_ENCODING] = content_transfer_encoding\n            self._is_multipart = True\n\n        self._fields.append((type_options, headers, value))\n\n    def add_fields(self, *fields):\n        to_add = list(fields)\n\n        while to_add:\n            rec = to_add.pop(0)\n\n            if isinstance(rec, io.IOBase):\n                k = guess_filename(rec, 'unknown')\n                self.add_field(k, rec)\n\n            elif isinstance(rec,\n                            (multidict.MultiDictProxy,\n                             multidict.MultiDict)):\n                to_add.extend(rec.items())\n\n            elif isinstance(rec, (list, tuple)) and len(rec) == 2:\n                k, fp = rec\n                self.add_field(k, fp)\n\n            else:\n                raise TypeError('Only io.IOBase, multidict and (name, file) '\n                                'pairs allowed, use .add_field() for passing '\n                                'more complex parameters')\n\n    def _gen_form_urlencoded(self, encoding):\n        # form data (x-www-form-urlencoded)\n        data = []\n        for type_options, _, value in self._fields:\n            data.append((type_options['name'], value))\n\n        data = urllib.parse.urlencode(data, doseq=True)\n        return data.encode(encoding)\n\n    def _gen_form_data(self, *args, **kwargs):\n        \"\"\"Encode a list of fields using the multipart/form-data MIME format\"\"\"\n        for dispparams, headers, value in self._fields:\n            part = self._writer.append(value, headers)\n            if dispparams:\n                part.set_content_disposition('form-data', **dispparams)\n                # FIXME cgi.FieldStorage doesn't likes body parts with\n                # Content-Length which were sent via chunked transfer encoding\n                part.headers.pop(hdrs.CONTENT_LENGTH, None)\n        yield from self._writer.serialize()\n\n    def __call__(self, encoding):\n        if self._is_multipart:\n            return self._gen_form_data(encoding)\n        else:\n            return self._gen_form_urlencoded(encoding)\n\n\ndef parse_mimetype(mimetype):\n    \"\"\"Parses a MIME type into its components.\n\n    :param str mimetype: MIME type\n\n    :returns: 4 element tuple for MIME type, subtype, suffix and parameters\n    :rtype: tuple\n\n    Example:\n\n    >>> parse_mimetype('text/html; charset=utf-8')\n    ('text', 'html', '', {'charset': 'utf-8'})\n\n    \"\"\"\n    if not mimetype:\n        return '', '', '', {}\n\n    parts = mimetype.split(';')\n    params = []\n    for item in parts[1:]:\n        if not item:\n            continue\n        key, value = item.split('=', 1) if '=' in item else (item, '')\n        params.append((key.lower().strip(), value.strip(' \"')))\n    params = dict(params)\n\n    fulltype = parts[0].strip().lower()\n    if fulltype == '*':\n        fulltype = '*/*'\n\n    mtype, stype = fulltype.split('/', 1) \\\n        if '/' in fulltype else (fulltype, '')\n    stype, suffix = stype.split('+', 1) if '+' in stype else (stype, '')\n\n    return mtype, stype, suffix, params\n\n\ndef str_to_bytes(s, encoding='utf-8'):\n    if isinstance(s, str):\n        return s.encode(encoding)\n    return s\n\n\ndef guess_filename(obj, default=None):\n    name = getattr(obj, 'name', None)\n    if name and name[0] != '<' and name[-1] != '>':\n        return os.path.split(name)[-1]\n    return default\n\n\ndef parse_remote_addr(forward):\n    if isinstance(forward, str):\n        # we only took the last one\n        # http://en.wikipedia.org/wiki/X-Forwarded-For\n        if ',' in forward:\n            forward = forward.rsplit(',', 1)[-1].strip()\n\n        # find host and port on ipv6 address\n        if '[' in forward and ']' in forward:\n            host = forward.split(']')[0][1:].lower()\n        elif ':' in forward and forward.count(':') == 1:\n            host = forward.split(':')[0].lower()\n        else:\n            host = forward\n\n        forward = forward.split(']')[-1]\n        if ':' in forward and forward.count(':') == 1:\n            port = forward.split(':', 1)[1]\n        else:\n            port = 80\n\n        remote = (host, port)\n    else:\n        remote = forward\n\n    return remote[0], str(remote[1])\n\n\ndef atoms(message, environ, response, transport, request_time):\n    \"\"\"Gets atoms for log formatting.\"\"\"\n    if message:\n        r = '{} {} HTTP/{}.{}'.format(\n            message.method, message.path,\n            message.version[0], message.version[1])\n        headers = message.headers\n    else:\n        r = ''\n        headers = {}\n\n    if transport is not None:\n        remote_addr = parse_remote_addr(\n            transport.get_extra_info('addr', '127.0.0.1'))\n    else:\n        remote_addr = ('',)\n\n    atoms = {\n        'h': remote_addr[0],\n        'l': '-',\n        'u': '-',\n        't': format_date_time(None),\n        'r': r,\n        's': str(getattr(response, 'status', '')),\n        'b': str(getattr(response, 'output_length', '')),\n        'f': headers.get(hdrs.REFERER, '-'),\n        'a': headers.get(hdrs.USER_AGENT, '-'),\n        'T': str(int(request_time)),\n        'D': str(request_time).split('.', 1)[-1][:5],\n        'p': \"<%s>\" % os.getpid()\n    }\n\n    return atoms\n\n\nclass SafeAtoms(dict):\n    \"\"\"Copy from gunicorn\"\"\"\n\n    def __init__(self, atoms, i_headers, o_headers):\n        dict.__init__(self)\n\n        self._i_headers = i_headers\n        self._o_headers = o_headers\n\n        for key, value in atoms.items():\n            self[key] = value.replace('\"', '\\\\\"')\n\n    def __getitem__(self, k):\n        if k.startswith('{'):\n            if k.endswith('}i'):\n                headers = self._i_headers\n            elif k.endswith('}o'):\n                headers = self._o_headers\n            else:\n                headers = None\n\n            if headers is not None:\n                return headers.get(k[1:-2], '-')\n\n        if k in self:\n            return super(SafeAtoms, self).__getitem__(k)\n        else:\n            return '-'\n\n\nclass reify:\n    \"\"\"Use as a class method decorator.  It operates almost exactly like\n    the Python ``@property`` decorator, but it puts the result of the\n    method it decorates into the instance dict after the first call,\n    effectively replacing the function it decorates with an instance\n    variable.  It is, in Python parlance, a non-data descriptor.\n\n    \"\"\"\n\n    def __init__(self, wrapped):\n        self.wrapped = wrapped\n        try:\n            self.__doc__ = wrapped.__doc__\n        except:  # pragma: no cover\n            pass\n\n    def __get__(self, inst, objtype=None):\n        if inst is None:\n            return self\n        val = self.wrapped(inst)\n        setattr(inst, self.wrapped.__name__, val)\n        return val\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:** `FormData.add_field` Does Not Validate Parameter Types, Allowing Non-String Inputs

**Description:**
When using the `FormData.add_field` method, providing non-string types for parameters such as `filename`, `content_type`, or `content_transfer_encoding` does not raise a `TypeError`. This oversight can lead to unexpected behavior or errors further down the processing pipeline.

**Example Code:**
```python
form = FormData()
# Attempting to add a field with an integer filename
form.add_field('file', 'content', filename=123)

# Attempting to add a field with a list as content_type
form.add_field('file', 'content', content_type=['text/plain'])
```

**Expected Behavior:**
The method should raise a `TypeError` when non-string types are provided for `filename`, `content_type`, or `content_transfer_encoding`. This validation ensures that only appropriate types are accepted, preventing potential issues during form data processing.

**Actual Behavior:**
No error is raised when non-string types are used for the specified parameters. This lack of validation allows invalid data to be processed, which can cause unexpected errors or malfunctioning of the form handling mechanism.

[/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/helpers.py
"""Various helper functions"""
import base64
import io
import os
import urllib.parse
from collections import namedtuple
from wsgiref.handlers import format_date_time

from . import hdrs, multidict

__all__ = ('BasicAuth', 'FormData', 'parse_mimetype')


class BasicAuth(namedtuple('BasicAuth', ['login', 'password', 'encoding'])):
    """Http basic authentication helper.

    :param str login: Login
    :param str password: Password
    :param str encoding: (optional) encoding ('latin1' by default)
    """

    def __new__(cls, login, password='', encoding='latin1'):
        if login is None:
            raise ValueError('None is not allowed as login value')

        if password is None:
            raise ValueError('None is not allowed as password value')

        return super().__new__(cls, login, password, encoding)

    def encode(self):
        """Encode credentials."""
        creds = ('%s:%s' % (self.login, self.password)).encode(self.encoding)
        return 'Basic %s' % base64.b64encode(creds).decode(self.encoding)


class FormData:
    """Helper class for multipart/form-data and
    application/x-www-form-urlencoded body generation."""

    def __init__(self, fields=()):
        from . import multipart
        self._writer = multipart.MultipartWriter('form-data')
        self._fields = []
        self._is_multipart = False

        if isinstance(fields, dict):
            fields = list(fields.items())
        elif not isinstance(fields, (list, tuple)):
            fields = (fields,)
        self.add_fields(*fields)

    @property
    def is_multipart(self):
        return self._is_multipart

    @property
    def content_type(self):
        if self._is_multipart:
            return self._writer.headers[hdrs.CONTENT_TYPE]
        else:
            return 'application/x-www-form-urlencoded'

    def add_field(self, name, value, *, content_type=None, filename=None,
                  content_transfer_encoding=None):

        if isinstance(value, io.IOBase):
            self._is_multipart = True

        type_options = multidict.MultiDict({'name': name})
        if filename is None and isinstance(value, io.IOBase):
            filename = guess_filename(value, name)
        if filename is not None:
            type_options['filename'] = filename
            self._is_multipart = True

        headers = {}
        if content_type is not None:
            headers[hdrs.CONTENT_TYPE] = content_type
            self._is_multipart = True
        if content_transfer_encoding is not None:
            headers[hdrs.CONTENT_TRANSFER_ENCODING] = content_transfer_encoding
            self._is_multipart = True

        self._fields.append((type_options, headers, value))

    def add_fields(self, *fields):
        to_add = list(fields)

        while to_add:
            rec = to_add.pop(0)

            if isinstance(rec, io.IOBase):
                k = guess_filename(rec, 'unknown')
                self.add_field(k, rec)

            elif isinstance(rec,
                            (multidict.MultiDictProxy,
                             multidict.MultiDict)):
                to_add.extend(rec.items())

            elif isinstance(rec, (list, tuple)) and len(rec) == 2:
                k, fp = rec
                self.add_field(k, fp)

            else:
                raise TypeError('Only io.IOBase, multidict and (name, file) '
                                'pairs allowed, use .add_field() for passing '
                                'more complex parameters')

    def _gen_form_urlencoded(self, encoding):
        # form data (x-www-form-urlencoded)
        data = []
        for type_options, _, value in self._fields:
            data.append((type_options['name'], value))

        data = urllib.parse.urlencode(data, doseq=True)
        return data.encode(encoding)

    def _gen_form_data(self, *args, **kwargs):
        """Encode a list of fields using the multipart/form-data MIME format"""
        for dispparams, headers, value in self._fields:
            part = self._writer.append(value, headers)
            if dispparams:
                part.set_content_disposition('form-data', **dispparams)
                # FIXME cgi.FieldStorage doesn't likes body parts with
                # Content-Length which were sent via chunked transfer encoding
                part.headers.pop(hdrs.CONTENT_LENGTH, None)
        yield from self._writer.serialize()

    def __call__(self, encoding):
        if self._is_multipart:
            return self._gen_form_data(encoding)
        else:
            return self._gen_form_urlencoded(encoding)


def parse_mimetype(mimetype):
    """Parses a MIME type into its components.

    :param str mimetype: MIME type

    :returns: 4 element tuple for MIME type, subtype, suffix and parameters
    :rtype: tuple

    Example:

    >>> parse_mimetype('text/html; charset=utf-8')
    ('text', 'html', '', {'charset': 'utf-8'})

    """
    if not mimetype:
        return '', '', '', {}

    parts = mimetype.split(';')
    params = []
    for item in parts[1:]:
        if not item:
            continue
        key, value = item.split('=', 1) if '=' in item else (item, '')
        params.append((key.lower().strip(), value.strip(' "')))
    params = dict(params)

    fulltype = parts[0].strip().lower()
    if fulltype == '*':
        fulltype = '*/*'

    mtype, stype = fulltype.split('/', 1) \
        if '/' in fulltype else (fulltype, '')
    stype, suffix = stype.split('+', 1) if '+' in stype else (stype, '')

    return mtype, stype, suffix, params


def str_to_bytes(s, encoding='utf-8'):
    if isinstance(s, str):
        return s.encode(encoding)
    return s


def guess_filename(obj, default=None):
    name = getattr(obj, 'name', None)
    if name and name[0] != '<' and name[-1] != '>':
        return os.path.split(name)[-1]
    return default


def parse_remote_addr(forward):
    if isinstance(forward, str):
        # we only took the last one
        # http://en.wikipedia.org/wiki/X-Forwarded-For
        if ',' in forward:
            forward = forward.rsplit(',', 1)[-1].strip()

        # find host and port on ipv6 address
        if '[' in forward and ']' in forward:
            host = forward.split(']')[0][1:].lower()
        elif ':' in forward and forward.count(':') == 1:
            host = forward.split(':')[0].lower()
        else:
            host = forward

        forward = forward.split(']')[-1]
        if ':' in forward and forward.count(':') == 1:
            port = forward.split(':', 1)[1]
        else:
            port = 80

        remote = (host, port)
    else:
        remote = forward

    return remote[0], str(remote[1])


def atoms(message, environ, response, transport, request_time):
    """Gets atoms for log formatting."""
    if message:
        r = '{} {} HTTP/{}.{}'.format(
            message.method, message.path,
            message.version[0], message.version[1])
        headers = message.headers
    else:
        r = ''
        headers = {}

    if transport is not None:
        remote_addr = parse_remote_addr(
            transport.get_extra_info('addr', '127.0.0.1'))
    else:
        remote_addr = ('',)

    atoms = {
        'h': remote_addr[0],
        'l': '-',
        'u': '-',
        't': format_date_time(None),
        'r': r,
        's': str(getattr(response, 'status', '')),
        'b': str(getattr(response, 'output_length', '')),
        'f': headers.get(hdrs.REFERER, '-'),
        'a': headers.get(hdrs.USER_AGENT, '-'),
        'T': str(int(request_time)),
        'D': str(request_time).split('.', 1)[-1][:5],
        'p': "<%s>" % os.getpid()
    }

    return atoms


class SafeAtoms(dict):
    """Copy from gunicorn"""

    def __init__(self, atoms, i_headers, o_headers):
        dict.__init__(self)

        self._i_headers = i_headers
        self._o_headers = o_headers

        for key, value in atoms.items():
            self[key] = value.replace('"', '\\"')

    def __getitem__(self, k):
        if k.startswith('{'):
            if k.endswith('}i'):
                headers = self._i_headers
            elif k.endswith('}o'):
                headers = self._o_headers
            else:
                headers = None

            if headers is not None:
                return headers.get(k[1:-2], '-')

        if k in self:
            return super(SafeAtoms, self).__getitem__(k)
        else:
            return '-'


class reify:
    """Use as a class method decorator.  It operates almost exactly like
    the Python ``@property`` decorator, but it puts the result of the
    method it decorates into the instance dict after the first call,
    effectively replacing the function it decorates with an instance
    variable.  It is, in Python parlance, a non-data descriptor.

    """

    def __init__(self, wrapped):
        self.wrapped = wrapped
        try:
            self.__doc__ = wrapped.__doc__
        except:  # pragma: no cover
            pass

    def __get__(self, inst, objtype=None):
        if inst is None:
            return self
        val = self.wrapped(inst)
        setattr(inst, self.wrapped.__name__, val)
        return val

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