{
    "file_diffs": [
        {
            "old_file_content": "\"\"\"Various helper functions\"\"\"\n__all__ = ['BasicAuth', 'FormData', 'parse_mimetype']\n\nimport base64\nimport binascii\nimport io\nimport os\nimport uuid\nimport urllib.parse\nfrom collections import namedtuple\nfrom wsgiref.handlers import format_date_time\n\nfrom . import multidict\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        self._fields = []\n        self._is_multipart = False\n        self._boundary = uuid.uuid4().hex\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 'multipart/form-data; boundary=%s' % self._boundary\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.MutableMultiDict({'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['Content-Type'] = content_type\n            self._is_multipart = True\n        if content_transfer_encoding is not None:\n            headers['Content-Transfer-Encoding'] = content_transfer_encoding\n            self._is_multipart = True\n            supported_tranfer_encoding = {\n                'base64': binascii.b2a_base64,\n                'quoted-printable': binascii.b2a_qp\n            }\n            conv = supported_tranfer_encoding.get(content_transfer_encoding)\n            if conv is not None:\n                value = conv(value)\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, multidict.MultiDict):\n                to_add.extend(rec.items(getall=True))\n\n            elif 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, headers, 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, encoding='utf-8', chunk_size=8196):\n        \"\"\"Encode a list of fields using the multipart/form-data MIME format\"\"\"\n        boundary = self._boundary.encode('latin1')\n\n        for type_options, headers, value in self._fields:\n            yield b'--' + boundary + b'\\r\\n'\n\n            out_headers = []\n\n            opts = '; '.join('{0[0]}=\"{0[1]}\"'.format(i)\n                             for i in type_options.items())\n\n            out_headers.append(\n                ('Content-Disposition: form-data; ' + opts).encode(encoding)\n                + b'\\r\\n')\n\n            for k, v in headers.items():\n                out_headers.append('{}: {}\\r\\n'.format(k, v).encode(encoding))\n\n            out_headers.append(b'\\r\\n')\n\n            yield b''.join(out_headers)\n\n            if isinstance(value, str):\n                yield value.encode(encoding)\n            else:\n                if isinstance(value, (bytes, bytearray)):\n                    value = io.BytesIO(value)\n\n                while True:\n                    chunk = value.read(chunk_size)\n                    if not chunk:\n                        break\n                    yield str_to_bytes(chunk, encoding)\n\n            yield b'\\r\\n'\n\n        yield b'--' + boundary + b'--\\r\\n'\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 atoms(message, environ, response, 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    else:\n        r = ''\n\n    atoms = {\n        'h': environ.get('REMOTE_ADDR', '-'),\n        'l': '-',\n        'u': '-',\n        't': format_date_time(None),\n        'r': r,\n        's': str(response.status),\n        'b': str(response.output_length),\n        'f': environ.get('HTTP_REFERER', '-'),\n        'a': environ.get('HTTP_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",
            "new_file_content": "\"\"\"Various helper functions\"\"\"\n__all__ = ['BasicAuth', 'FormData', 'parse_mimetype']\n\nimport base64\nimport binascii\nimport io\nimport os\nimport uuid\nimport urllib.parse\nfrom collections import namedtuple\nfrom wsgiref.handlers import format_date_time\n\nfrom . import multidict\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        self._fields = []\n        self._is_multipart = False\n        self._boundary = uuid.uuid4().hex\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 'multipart/form-data; boundary=%s' % self._boundary\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.MutableMultiDict({'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['Content-Type'] = content_type\n            self._is_multipart = True\n        if content_transfer_encoding is not None:\n            headers['Content-Transfer-Encoding'] = content_transfer_encoding\n            self._is_multipart = True\n            supported_tranfer_encoding = {\n                'base64': binascii.b2a_base64,\n                'quoted-printable': binascii.b2a_qp\n            }\n            conv = supported_tranfer_encoding.get(content_transfer_encoding)\n            if conv is not None:\n                value = conv(value)\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, multidict.MultiDict):\n                to_add.extend(rec.items(getall=True))\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, headers, 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, encoding='utf-8', chunk_size=8196):\n        \"\"\"Encode a list of fields using the multipart/form-data MIME format\"\"\"\n        boundary = self._boundary.encode('latin1')\n\n        for type_options, headers, value in self._fields:\n            yield b'--' + boundary + b'\\r\\n'\n\n            out_headers = []\n\n            opts = '; '.join('{0[0]}=\"{0[1]}\"'.format(i)\n                             for i in type_options.items())\n\n            out_headers.append(\n                ('Content-Disposition: form-data; ' + opts).encode(encoding)\n                + b'\\r\\n')\n\n            for k, v in headers.items():\n                out_headers.append('{}: {}\\r\\n'.format(k, v).encode(encoding))\n\n            out_headers.append(b'\\r\\n')\n\n            yield b''.join(out_headers)\n\n            if isinstance(value, str):\n                yield value.encode(encoding)\n            else:\n                if isinstance(value, (bytes, bytearray)):\n                    value = io.BytesIO(value)\n\n                while True:\n                    chunk = value.read(chunk_size)\n                    if not chunk:\n                        break\n                    yield str_to_bytes(chunk, encoding)\n\n            yield b'\\r\\n'\n\n        yield b'--' + boundary + b'--\\r\\n'\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 atoms(message, environ, response, 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    else:\n        r = ''\n\n    atoms = {\n        'h': environ.get('REMOTE_ADDR', '-'),\n        'l': '-',\n        'u': '-',\n        't': format_date_time(None),\n        'r': r,\n        's': str(response.status),\n        'b': str(response.output_length),\n        'f': environ.get('HTTP_REFERER', '-'),\n        'a': environ.get('HTTP_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",
            "header": {
                "file": {
                    "path": "aiohttp/helpers.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "7cc918b1",
                "new_commit_hash": "223c1180",
                "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": 105,
                            "length": 7
                        },
                        "new_range": {
                            "start": 105,
                            "length": 7
                        },
                        "section": "class FormData:"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "            elif isinstance(rec, multidict.MultiDict):",
                                "type": "context"
                            },
                            {
                                "content": "                to_add.extend(rec.items(getall=True))",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "            elif len(rec) == 2:",
                                "type": "deleted"
                            },
                            {
                                "content": "            elif isinstance(rec, (list, tuple)) and len(rec) == 2:",
                                "type": "added"
                            },
                            {
                                "content": "                k, fp = rec",
                                "type": "context"
                            },
                            {
                                "content": "                self.add_field(k, fp)",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "aiohttp/helpers.py",
                            "type": "method",
                            "name": "FormData.add_fields",
                            "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        self._fields = []\n        self._is_multipart = False\n        self._boundary = uuid.uuid4().hex\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 'multipart/form-data; boundary=%s' % self._boundary\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.MutableMultiDict({'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['Content-Type'] = content_type\n            self._is_multipart = True\n        if content_transfer_encoding is not None:\n            headers['Content-Transfer-Encoding'] = content_transfer_encoding\n            self._is_multipart = True\n            supported_tranfer_encoding = {\n                'base64': binascii.b2a_base64,\n                'quoted-printable': binascii.b2a_qp\n            }\n            conv = supported_tranfer_encoding.get(content_transfer_encoding)\n            if conv is not None:\n                value = conv(value)\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, multidict.MultiDict):\n                to_add.extend(rec.items(getall=True))\n\n            elif 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, headers, 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, encoding='utf-8', chunk_size=8196):\n        \"\"\"Encode a list of fields using the multipart/form-data MIME format\"\"\"\n        boundary = self._boundary.encode('latin1')\n\n        for type_options, headers, value in self._fields:\n            yield b'--' + boundary + b'\\r\\n'\n\n            out_headers = []\n\n            opts = '; '.join('{0[0]}=\"{0[1]}\"'.format(i)\n                             for i in type_options.items())\n\n            out_headers.append(\n                ('Content-Disposition: form-data; ' + opts).encode(encoding)\n                + b'\\r\\n')\n\n            for k, v in headers.items():\n                out_headers.append('{}: {}\\r\\n'.format(k, v).encode(encoding))\n\n            out_headers.append(b'\\r\\n')\n\n            yield b''.join(out_headers)\n\n            if isinstance(value, str):\n                yield value.encode(encoding)\n            else:\n                if isinstance(value, (bytes, bytearray)):\n                    value = io.BytesIO(value)\n\n                while True:\n                    chunk = value.read(chunk_size)\n                    if not chunk:\n                        break\n                    yield str_to_bytes(chunk, encoding)\n\n            yield b'\\r\\n'\n\n        yield b'--' + boundary + b'--\\r\\n'\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": 95,
                            "end_lineno": 115,
                            "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        self._fields = []\n        self._is_multipart = False\n        self._boundary = uuid.uuid4().hex\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 'multipart/form-data; boundary=%s' % self._boundary\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.MutableMultiDict({'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['Content-Type'] = content_type\n            self._is_multipart = True\n        if content_transfer_encoding is not None:\n            headers['Content-Transfer-Encoding'] = content_transfer_encoding\n            self._is_multipart = True\n            supported_tranfer_encoding = {\n                'base64': binascii.b2a_base64,\n                'quoted-printable': binascii.b2a_qp\n            }\n            conv = supported_tranfer_encoding.get(content_transfer_encoding)\n            if conv is not None:\n                value = conv(value)\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, multidict.MultiDict):\n                to_add.extend(rec.items(getall=True))\n\n            elif 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, headers, 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, encoding='utf-8', chunk_size=8196):\n        \"\"\"Encode a list of fields using the multipart/form-data MIME format\"\"\"\n        boundary = self._boundary.encode('latin1')\n\n        for type_options, headers, value in self._fields:\n            yield b'--' + boundary + b'\\r\\n'\n\n            out_headers = []\n\n            opts = '; '.join('{0[0]}=\"{0[1]}\"'.format(i)\n                             for i in type_options.items())\n\n            out_headers.append(\n                ('Content-Disposition: form-data; ' + opts).encode(encoding)\n                + b'\\r\\n')\n\n            for k, v in headers.items():\n                out_headers.append('{}: {}\\r\\n'.format(k, v).encode(encoding))\n\n            out_headers.append(b'\\r\\n')\n\n            yield b''.join(out_headers)\n\n            if isinstance(value, str):\n                yield value.encode(encoding)\n            else:\n                if isinstance(value, (bytes, bytearray)):\n                    value = io.BytesIO(value)\n\n                while True:\n                    chunk = value.read(chunk_size)\n                    if not chunk:\n                        break\n                    yield str_to_bytes(chunk, encoding)\n\n            yield b'\\r\\n'\n\n        yield b'--' + boundary + b'--\\r\\n'\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": 39,
                                "end_lineno": 169,
                                "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        self._fields = []\n        self._is_multipart = False\n        self._boundary = uuid.uuid4().hex\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 'multipart/form-data; boundary=%s' % self._boundary\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.MutableMultiDict({'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['Content-Type'] = content_type\n            self._is_multipart = True\n        if content_transfer_encoding is not None:\n            headers['Content-Transfer-Encoding'] = content_transfer_encoding\n            self._is_multipart = True\n            supported_tranfer_encoding = {\n                'base64': binascii.b2a_base64,\n                'quoted-printable': binascii.b2a_qp\n            }\n            conv = supported_tranfer_encoding.get(content_transfer_encoding)\n            if conv is not None:\n                value = conv(value)\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, multidict.MultiDict):\n                to_add.extend(rec.items(getall=True))\n\n            elif 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, headers, 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, encoding='utf-8', chunk_size=8196):\n        \"\"\"Encode a list of fields using the multipart/form-data MIME format\"\"\"\n        boundary = self._boundary.encode('latin1')\n\n        for type_options, headers, value in self._fields:\n            yield b'--' + boundary + b'\\r\\n'\n\n            out_headers = []\n\n            opts = '; '.join('{0[0]}=\"{0[1]}\"'.format(i)\n                             for i in type_options.items())\n\n            out_headers.append(\n                ('Content-Disposition: form-data; ' + opts).encode(encoding)\n                + b'\\r\\n')\n\n            for k, v in headers.items():\n                out_headers.append('{}: {}\\r\\n'.format(k, v).encode(encoding))\n\n            out_headers.append(b'\\r\\n')\n\n            yield b''.join(out_headers)\n\n            if isinstance(value, str):\n                yield value.encode(encoding)\n            else:\n                if isinstance(value, (bytes, bytearray)):\n                    value = io.BytesIO(value)\n\n                while True:\n                    chunk = value.read(chunk_size)\n                    if not chunk:\n                        break\n                    yield str_to_bytes(chunk, encoding)\n\n            yield b'\\r\\n'\n\n        yield b'--' + boundary + b'--\\r\\n'\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": 39,
                            "end_lineno": 169,
                            "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\nclass SafeAtomsTests(unittest.TestCase):\n\n    def test_get_non_existing(self):\n        atoms = helpers.SafeAtoms(\n            {}, multidict.MultiDict(), multidict.MultiDict())\n        self.assertEqual(atoms['unknown'], '-')\n\n    def test_get_lower(self):\n        i_headers = multidict.MultiDict([('test', '123')])\n        o_headers = multidict.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')\n\n\nclass SafeAtomsTests(unittest.TestCase):\n\n    def test_get_non_existing(self):\n        atoms = helpers.SafeAtoms(\n            {}, multidict.MultiDict(), multidict.MultiDict())\n        self.assertEqual(atoms['unknown'], '-')\n\n    def test_get_lower(self):\n        i_headers = multidict.MultiDict([('test', '123')])\n        o_headers = multidict.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": "7bfeb5a1",
                "new_commit_hash": "476f2e1b",
                "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": 54,
                            "length": 6
                        },
                        "new_range": {
                            "start": 54,
                            "length": 14
                        },
                        "section": "class HelpersTests(unittest.TestCase):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        self.assertEqual(auth.password, 'pwd')",
                                "type": "context"
                            },
                            {
                                "content": "        self.assertEqual(auth.encode(), 'Basic bmtpbTpwd2Q=')",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    def test_invalid_formdata_params(self):",
                                "type": "added"
                            },
                            {
                                "content": "        with self.assertRaises(TypeError):",
                                "type": "added"
                            },
                            {
                                "content": "            helpers.FormData('asdasf')",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "    def test_invalid_formdata_params2(self):",
                                "type": "added"
                            },
                            {
                                "content": "        with self.assertRaises(TypeError):",
                                "type": "added"
                            },
                            {
                                "content": "            helpers.FormData('as')",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "class SafeAtomsTests(unittest.TestCase):",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "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')",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 8,
                            "end_lineno": 63,
                            "parent": null
                        }
                    ],
                    "added_entities": [
                        {
                            "file_name": "tests/test_helpers.py",
                            "type": "method",
                            "name": "HelpersTests.test_invalid_formdata_params",
                            "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')",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 57,
                            "end_lineno": 59,
                            "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')",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 8,
                                "end_lineno": 63,
                                "parent": null
                            }
                        },
                        {
                            "file_name": "tests/test_helpers.py",
                            "type": "method",
                            "name": "HelpersTests.test_invalid_formdata_params2",
                            "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')",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 61,
                            "end_lineno": 63,
                            "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')",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 8,
                                "end_lineno": 63,
                                "parent": null
                            }
                        }
                    ],
                    "deleted_entities": []
                }
            ]
        }
    ],
    "old_commit_hash": "e5106ef238ae8e14921c99ffc6b53969d7917d6d^",
    "new_commit_hash": "e5106ef238ae8e14921c99ffc6b53969d7917d6d",
    "commit_message": "Add tests for FormData",
    "commit_date": "2014-10-26T01:53:18-07:00",
    "metadata": {}
}
{
    "repo_name": "aiohttp",
    "new_commit_hash": "e5106ef238ae8e14921c99ffc6b53969d7917d6d",
    "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')\n\n\nclass SafeAtomsTests(unittest.TestCase):\n\n    def test_get_non_existing(self):\n        atoms = helpers.SafeAtoms(\n            {}, multidict.MultiDict(), multidict.MultiDict())\n        self.assertEqual(atoms['unknown'], '-')\n\n    def test_get_lower(self):\n        i_headers = multidict.MultiDict([('test', '123')])\n        o_headers = multidict.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 23ms\nInstalled 26 packages in 17ms\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_e5106ef238ae8e14921c99ffc6b53969d7917d6d\nplugins: mock-3.14.0, asyncio-0.25.1, cov-6.0.0\nasyncio: mode=strict, asyncio_default_fixture_loop_scope=None\ncollected 6 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_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::SafeAtomsTests::test_get_lower\nPASSED r2e_tests/test_1.py::SafeAtomsTests::test_get_non_existing\n============================== 6 passed in 0.38s ===============================\n",
    "new_commit_res_stderr": "/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e5106ef238ae8e14921c99ffc6b53969d7917d6d/.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_e5106ef238ae8e14921c99ffc6b53969d7917d6d\nplugins: mock-3.14.0, asyncio-0.25.1, cov-6.0.0\nasyncio: mode=strict, asyncio_default_fixture_loop_scope=None\ncollected 6 items\n\nr2e_tests/test_1.py ..F...                                               [100%]\n\n=================================== FAILURES ===================================\n__________________ HelpersTests.test_invalid_formdata_params2 __________________\n\nself = <r2e_tests.test_1.HelpersTests testMethod=test_invalid_formdata_params2>\n\n    def test_invalid_formdata_params2(self):\n        with self.assertRaises(TypeError):\n>           helpers.FormData('as')\nE           AssertionError: TypeError not raised\n\nr2e_tests/test_1.py:63: 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_parse_mimetype\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_params2 - Ass...\n========================= 1 failed, 5 passed in 0.12s ==========================\n",
    "old_commit_res_stderr": "/home/gcpuser/buckets/local_repoeval_bucket/repos/aiohttp_e5106ef238ae8e14921c99ffc6b53969d7917d6d/.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 allows invalid two-element string inputs without raising TypeError

**Description:**
When creating a `FormData` instance with a two-character string, it does not raise a `TypeError` as expected. This allows invalid parameters to be used, potentially leading to unexpected behavior.

**Example Code:**
```python
form = helpers.FormData('as')
```

**Expected Behavior:**
Initializing `FormData` with a two-element input that is not a list or tuple should raise a `TypeError`.

**Actual Behavior:**
No error is raised, and the `FormData` instance is created with invalid parameters.

[/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"""
__all__ = ['BasicAuth', 'FormData', 'parse_mimetype']

import base64
import binascii
import io
import os
import uuid
import urllib.parse
from collections import namedtuple
from wsgiref.handlers import format_date_time

from . import multidict


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=()):
        self._fields = []
        self._is_multipart = False
        self._boundary = uuid.uuid4().hex

        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 'multipart/form-data; boundary=%s' % self._boundary
        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.MutableMultiDict({'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['Content-Type'] = content_type
            self._is_multipart = True
        if content_transfer_encoding is not None:
            headers['Content-Transfer-Encoding'] = content_transfer_encoding
            self._is_multipart = True
            supported_tranfer_encoding = {
                'base64': binascii.b2a_base64,
                'quoted-printable': binascii.b2a_qp
            }
            conv = supported_tranfer_encoding.get(content_transfer_encoding)
            if conv is not None:
                value = conv(value)

        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.MultiDict):
                to_add.extend(rec.items(getall=True))

            elif 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, headers, 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, encoding='utf-8', chunk_size=8196):
        """Encode a list of fields using the multipart/form-data MIME format"""
        boundary = self._boundary.encode('latin1')

        for type_options, headers, value in self._fields:
            yield b'--' + boundary + b'\r\n'

            out_headers = []

            opts = '; '.join('{0[0]}="{0[1]}"'.format(i)
                             for i in type_options.items())

            out_headers.append(
                ('Content-Disposition: form-data; ' + opts).encode(encoding)
                + b'\r\n')

            for k, v in headers.items():
                out_headers.append('{}: {}\r\n'.format(k, v).encode(encoding))

            out_headers.append(b'\r\n')

            yield b''.join(out_headers)

            if isinstance(value, str):
                yield value.encode(encoding)
            else:
                if isinstance(value, (bytes, bytearray)):
                    value = io.BytesIO(value)

                while True:
                    chunk = value.read(chunk_size)
                    if not chunk:
                        break
                    yield str_to_bytes(chunk, encoding)

            yield b'\r\n'

        yield b'--' + boundary + b'--\r\n'

    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 atoms(message, environ, response, request_time):
    """Gets atoms for log formatting."""
    if message:
        r = '{} {} HTTP/{}.{}'.format(
            message.method, message.path,
            message.version[0], message.version[1])
    else:
        r = ''

    atoms = {
        'h': environ.get('REMOTE_ADDR', '-'),
        'l': '-',
        'u': '-',
        't': format_date_time(None),
        'r': r,
        's': str(response.status),
        'b': str(response.output_length),
        'f': environ.get('HTTP_REFERER', '-'),
        'a': environ.get('HTTP_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 '-'

```
--- 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 allows invalid two-element string inputs without raising TypeError

**Description:**
When creating a `FormData` instance with a two-character string, it does not raise a `TypeError` as expected. This allows invalid parameters to be used, potentially leading to unexpected behavior.

**Example Code:**
```python
form = helpers.FormData('as')
```

**Expected Behavior:**
Initializing `FormData` with a two-element input that is not a list or tuple should raise a `TypeError`.

**Actual Behavior:**
No error is raised, and the `FormData` instance is created with invalid parameters.

[/ISSUE]
{
    "HelpersTests.test_basic_auth": "PASSED",
    "HelpersTests.test_invalid_formdata_params": "PASSED",
    "HelpersTests.test_invalid_formdata_params2": "PASSED",
    "HelpersTests.test_parse_mimetype": "PASSED",
    "SafeAtomsTests.test_get_lower": "PASSED",
    "SafeAtomsTests.test_get_non_existing": "PASSED"
}
diff --git a/aiohttp/helpers.py b/aiohttp/helpers.py
index 7cc918b1..223c1180 100644
--- a/aiohttp/helpers.py
+++ b/aiohttp/helpers.py
@@ -105,7 +105,7 @@ class FormData:
             elif isinstance(rec, multidict.MultiDict):
                 to_add.extend(rec.items(getall=True))
 
-            elif len(rec) == 2:
+            elif isinstance(rec, (list, tuple)) and len(rec) == 2:
                 k, fp = rec
                 self.add_field(k, fp)
 

{"aiohttp/helpers.py": "\"\"\"Various helper functions\"\"\"\n__all__ = ['BasicAuth', 'FormData', 'parse_mimetype']\n\nimport base64\nimport binascii\nimport io\nimport os\nimport uuid\nimport urllib.parse\nfrom collections import namedtuple\nfrom wsgiref.handlers import format_date_time\n\nfrom . import multidict\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        self._fields = []\n        self._is_multipart = False\n        self._boundary = uuid.uuid4().hex\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 'multipart/form-data; boundary=%s' % self._boundary\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.MutableMultiDict({'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['Content-Type'] = content_type\n            self._is_multipart = True\n        if content_transfer_encoding is not None:\n            headers['Content-Transfer-Encoding'] = content_transfer_encoding\n            self._is_multipart = True\n            supported_tranfer_encoding = {\n                'base64': binascii.b2a_base64,\n                'quoted-printable': binascii.b2a_qp\n            }\n            conv = supported_tranfer_encoding.get(content_transfer_encoding)\n            if conv is not None:\n                value = conv(value)\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, multidict.MultiDict):\n                to_add.extend(rec.items(getall=True))\n\n            elif 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, headers, 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, encoding='utf-8', chunk_size=8196):\n        \"\"\"Encode a list of fields using the multipart/form-data MIME format\"\"\"\n        boundary = self._boundary.encode('latin1')\n\n        for type_options, headers, value in self._fields:\n            yield b'--' + boundary + b'\\r\\n'\n\n            out_headers = []\n\n            opts = '; '.join('{0[0]}=\"{0[1]}\"'.format(i)\n                             for i in type_options.items())\n\n            out_headers.append(\n                ('Content-Disposition: form-data; ' + opts).encode(encoding)\n                + b'\\r\\n')\n\n            for k, v in headers.items():\n                out_headers.append('{}: {}\\r\\n'.format(k, v).encode(encoding))\n\n            out_headers.append(b'\\r\\n')\n\n            yield b''.join(out_headers)\n\n            if isinstance(value, str):\n                yield value.encode(encoding)\n            else:\n                if isinstance(value, (bytes, bytearray)):\n                    value = io.BytesIO(value)\n\n                while True:\n                    chunk = value.read(chunk_size)\n                    if not chunk:\n                        break\n                    yield str_to_bytes(chunk, encoding)\n\n            yield b'\\r\\n'\n\n        yield b'--' + boundary + b'--\\r\\n'\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 atoms(message, environ, response, 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    else:\n        r = ''\n\n    atoms = {\n        'h': environ.get('REMOTE_ADDR', '-'),\n        'l': '-',\n        'u': '-',\n        't': format_date_time(None),\n        'r': r,\n        's': str(response.status),\n        'b': str(response.output_length),\n        'f': environ.get('HTTP_REFERER', '-'),\n        'a': environ.get('HTTP_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"}
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 allows invalid two-element string inputs without raising TypeError

**Description:**
When creating a `FormData` instance with a two-character string, it does not raise a `TypeError` as expected. This allows invalid parameters to be used, potentially leading to unexpected behavior.

**Example Code:**
```python
form = helpers.FormData('as')
```

**Expected Behavior:**
Initializing `FormData` with a two-element input that is not a list or tuple should raise a `TypeError`.

**Actual Behavior:**
No error is raised, and the `FormData` instance is created with invalid parameters.

[/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"""
__all__ = ['BasicAuth', 'FormData', 'parse_mimetype']

import base64
import binascii
import io
import os
import uuid
import urllib.parse
from collections import namedtuple
from wsgiref.handlers import format_date_time

from . import multidict


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=()):
        self._fields = []
        self._is_multipart = False
        self._boundary = uuid.uuid4().hex

        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 'multipart/form-data; boundary=%s' % self._boundary
        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.MutableMultiDict({'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['Content-Type'] = content_type
            self._is_multipart = True
        if content_transfer_encoding is not None:
            headers['Content-Transfer-Encoding'] = content_transfer_encoding
            self._is_multipart = True
            supported_tranfer_encoding = {
                'base64': binascii.b2a_base64,
                'quoted-printable': binascii.b2a_qp
            }
            conv = supported_tranfer_encoding.get(content_transfer_encoding)
            if conv is not None:
                value = conv(value)

        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.MultiDict):
                to_add.extend(rec.items(getall=True))

            elif 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, headers, 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, encoding='utf-8', chunk_size=8196):
        """Encode a list of fields using the multipart/form-data MIME format"""
        boundary = self._boundary.encode('latin1')

        for type_options, headers, value in self._fields:
            yield b'--' + boundary + b'\r\n'

            out_headers = []

            opts = '; '.join('{0[0]}="{0[1]}"'.format(i)
                             for i in type_options.items())

            out_headers.append(
                ('Content-Disposition: form-data; ' + opts).encode(encoding)
                + b'\r\n')

            for k, v in headers.items():
                out_headers.append('{}: {}\r\n'.format(k, v).encode(encoding))

            out_headers.append(b'\r\n')

            yield b''.join(out_headers)

            if isinstance(value, str):
                yield value.encode(encoding)
            else:
                if isinstance(value, (bytes, bytearray)):
                    value = io.BytesIO(value)

                while True:
                    chunk = value.read(chunk_size)
                    if not chunk:
                        break
                    yield str_to_bytes(chunk, encoding)

            yield b'\r\n'

        yield b'--' + boundary + b'--\r\n'

    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 atoms(message, environ, response, request_time):
    """Gets atoms for log formatting."""
    if message:
        r = '{} {} HTTP/{}.{}'.format(
            message.method, message.path,
            message.version[0], message.version[1])
    else:
        r = ''

    atoms = {
        'h': environ.get('REMOTE_ADDR', '-'),
        'l': '-',
        'u': '-',
        't': format_date_time(None),
        'r': r,
        's': str(response.status),
        'b': str(response.output_length),
        'f': environ.get('HTTP_REFERER', '-'),
        'a': environ.get('HTTP_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 '-'

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