multipart/form-data and multiple fields with the same name

I'm sending a `POST` request with multiple fields with the same name which normally works well when passed in a `dict`:

```
>>> from requests import post
>>> print post('http://httpbin.org/post', data={'field': ['a', 'b']}).content
{
  "origin": "[...]",
  "files": {},
  "form": {
    "field": [
      "a",
      "b"
    ]
  },
  "url": "http://httpbin.org/post",
  "args": {},
  "headers": {
    "Content-Length": "15",
    "Accept-Encoding": "identity, deflate, compress, gzip",
    "Connection": "keep-alive",
    "Accept": "*/*",
    "User-Agent": "python-requests/0.13.1",
    "Host": "httpbin.org",
    "Content-Type": "application/x-www-form-urlencoded"
  },
  "json": null,
  "data": ""
}
```

But fails with a `TypeError` when the request is a `multipart/form-data` one:

```
>>> print post('http://httpbin.org/post', data={'field': ['a', 'b']}, files={'file': open('/etc/hosts')}).content
Traceback (most recent call last):
  File "<ipython-input-15-4008ff697f5a>", line 1, in <module>
    print requests.post('http://httpbin.org/post', data={'field': ['a', 'b']}, files={'file': open('/etc/hosts')}).content
  File "python2.7/site-packages/requests/api.py", line 87, in post
    return request('post', url, data=data, **kwargs)
  File "python2.7/site-packages/requests/safe_mode.py", line 37, in wrapped
    return function(method, url, **kwargs)
  File "python2.7/site-packages/requests/api.py", line 42, in request
    return s.request(method=method, url=url, **kwargs)
  File "python2.7/site-packages/requests/sessions.py", line 230, in request
    r.send(prefetch=prefetch)
  File "python2.7/site-packages/requests/models.py", line 507, in send
    (body, content_type) = self._encode_files(self.files)
  File "site-packages/requests/models.py", line 366, in _encode_files
    (body, content_type) = encode_multipart_formdata(fields)
  File "site-packages/requests/packages/urllib3/filepost.py", line 80, in encode_multipart_formdata
    body.write(data)
TypeError: 'list' does not have the buffer interface
```

Passing a `list` of  `tuple`s doesn't raise an exception but only the last item is included in the request:

```
>>> print requests.post('http://httpbin.org/post', data=[('field', 'a'),  ('field', 'b')], files={'file': open('/etc/hosts')}).content
{
  "origin": "[...]",
  "files": {
    "file": "[...]"
  },
  "form": {
    "field": "b"
  },
  "url": "http://httpbin.org/post",
  "args": {},
  "headers": {
    "Content-Length": "862",
    "Accept-Encoding": "identity, deflate, compress, gzip",
    "Connection": "keep-alive",
    "Accept": "*/*",
    "User-Agent": "python-requests/0.13.1",
    "Host": "httpbin.org",
    "Content-Type": "multipart/form-data; boundary=127.0.0.1.501.73436.1343139319.461.6"
  },
  "json": null,
  "data": ""
}
```


I've just started looking into this, and I can explain the behaviour of the second case. The list of tuples you provided to `data` has `dict()` called on it. Dictionaries (obviously) don't allow duplicate keys, but your list of tuples has duplicate keys, so the last item in the iterable takes the value for that key. Exactly the same behaviour is shown if you provide a list of tuples to `data` without the `files` argument, so I'd assume that this is intended behaviour.

I'm significantly less sure about your first case. The actual exception is occurring in urllib3, which does not expect to be passed a list. If I had to hazard a guess, I'd say that the fix should be applied to requests, not urllib3, because requests already has edge case code for lists in [`_encode_params()`](https://github.com/kennethreitz/requests/blob/develop/requests/models.py#L306). It's a fix I'm prepared to write, but I would want @kennethreitz to confirm that this is a bug, and not actually correct behaviour, first.


@Lukasa :+1:


Good news everybody! Unrelated problem #661 has led to pull request #729 fixing this issue. I'll push up my test for this issue, but otherwise it seems to be resolved.


Thanks! There is still a small problem, though: If there is a file with the same name as one of the data fields then the data fields are overwritten and only the file field is sent:

```
>>> print post('http://httpbin.org/post', data={'X': 'a'}, files={'X': open('/etc/hosts')}).content
{
  "origin": "[...]",
  "files": {
    "X": "[...]"
  },
  "form": {},
  "url": "http://httpbin.org/post",
  "args": {},
  "headers": {
    "Content-Length": "779",
    "Accept-Encoding": "identity, deflate, compress, gzip",
    "Connection": "keep-alive",
    "Accept": "*/*",
    "User-Agent": "python-requests/0.13.4 CPython/2.7.3 Darwin/12.0.0",
    "Host": "httpbin.org",
    "Content-Type": "multipart/form-data; boundary=f38e57e2619e4190b4b3b1399602ab40"
  },
  "json": null,
  "data": ""
}
```


Another problem is that now (after #729) the serialisation of lists is inconsistent between `application/x-www-form-urlencoded` and `multipart/form-data` requests.

With  `application/x-www-form-urlencoded` the field is repeated multiple times (which is think is a reasonable serialization):

```
>>> print post('http://httpbin.org/post', data={'X': ['a', 'b']}).content
{
  "origin": "195.249.187.189",
  "files": {},
  "form": {
    "X": [
      "a",
      "b"
    ]
  },
  "url": "http://httpbin.org/post",
  "args": {},
  "headers": {
    "Content-Length": "7",
    "Accept-Encoding": "identity, deflate, compress, gzip",
    "Connection": "keep-alive",
    "Accept": "*/*",
    "User-Agent": "python-requests/0.13.4 CPython/2.7.3 Darwin/12.0.0",
    "Host": "httpbin.org",
    "Content-Type": "application/x-www-form-urlencoded"
  },
  "json": null,
  "data": ""
}
```

Whereas with `multipart/form-data` the field is included only once with the values joined by `,` (which doesn't seem to follow any convention):

```
>>> print post('http://httpbin.org/post', data={'X': ['a', 'b']}, files={'Z': open('/etc/hosts')}).content
{
  "origin": "[...]",
  "files": {
    "Z": "[...]"
  },
  "form": {
    "X": "a, b"
  },
  "url": "http://httpbin.org/post",
  "args": {},
  "headers": {
    "Content-Length": "296",
    "Accept-Encoding": "identity, deflate, compress, gzip",
    "Connection": "keep-alive",
    "Accept": "*/*",
    "User-Agent": "python-requests/0.13.4 CPython/2.7.3 Darwin/12.0.0",
    "Host": "httpbin.org",
    "Content-Type": "multipart/form-data; boundary=c451c91af593431a8f0bf5c3ecb9c388"
  },
  "json": null,
  "data": ""
}
```


Good spot. The inconsistency is an easy fix. The overwrite is less so. I'll start a pull request to handle these problems, unless you want to do it yourself. =)


I actually think I have a fix for both – working on tests now, will send a pull in a minute


Brilliant! Always happy to have other people do work for me. =D


Fixed by #746.