Restore the ability to use a list of 2-tuples for the data keyword argument with requests.post. #1103

Merged
merged 1 commit into from Jan 26, 2013

Conversation

Projects
None yet
3 participants

As of commit ef8563a the ability to pass a keyword argument like data=[('key', 'value'), ('key', 'value2')] was broken because the is_stream detection in PreparedRequest.prepare_body(self, data, files) fails to look for a list of 2-tuples.

Just in case this is deemed to be an unnecessary change (because the calling code could switch to using a dict), Il'l make note here that this is required in order to pass POST parameters where the key is the same, but values are different.

form_data = [('item', 1), ('item', 2), ('item', 3)]
resp = requests.post('http://www.example.com', data=form_data)
Owner

kennethreitz commented Jan 17, 2013

Actually, the proper syntax for that is slightly different.

form_data = {'item': [1, 2, 3]}
resp = requests.post('http://www.example.com', data=form_data)

I see the syntactical niceness of that example for simple cases(thanks for showing it, I didn't realize I could do that), but I'd still like to make my case for the way that it worked previously.

I'm currently using Werkzeug OrderedMultiDict to hold the parameters that eventually make it into the data argument. Some of my uses can have quite a few parameters and, since it's ordered, the order of the parameters does matter in the POST data (working with a legacy system).

WIth a list of 2-tuples I can do: data=ordered_multi_dict_instance.items(multi=true). So the 2-tuple is quite easy to create from a dict-like object that iterates. I may be wrong, but this new syntax deviates in such a way that I'd have to marshall all the data into it and maintain the order at the same time.

I also face an issue with the fact that this legacy system I'm working with requires not just multiple keys but ordered multiple keys. Something like: Item=1&Value=10&OtherValue=100&Item=2&Value=200&OtherValue=200&Item=3&Value=30&OtherValue=300. Presumably, that would result in form_data = {'Item': [1, 2, 3], 'Value': [10, 20, 30], 'OtherValue': [100, 200, 300]} in the new syntax, which would likely re-order the parameters based on the names of Item, Value and OtherValue, and not in the repeating ordered sequence: Item, Value, OtherValue.

Contributor

piotr-dobrogost commented Jan 17, 2013

Related: issue #522

Owner

kennethreitz commented Jan 17, 2013

We need to support MultiDict. This is long overdue.

Accepting MultiDict for the data= keyword would be acceptable for me.

So, moving this forward.

As it stands commit ef8563a is a breaking change from 1.0X to 1.10 for my particular use case. The workaround I have is:

form_data = RequestEncodingMixin._encode_params(request.values.items(multi=True))
resp = requests.post('http://www.example.com', data=form_data)

Is this particular pull request viable as a stop-gap between now and MultiDict support or is passing a 2-tuple list into data= a no-go for the future?

Owner

kennethreitz commented Jan 26, 2013

Merged.

@kennethreitz kennethreitz added a commit that referenced this pull request Jan 26, 2013

@kennethreitz kennethreitz Merge pull request #1103 from dmckeone/master
Restore the ability to use a list of 2-tuples for the data keyword argument with requests.post.
9d1d927

@kennethreitz kennethreitz merged commit 9d1d927 into requests:master Jan 26, 2013

1 check passed

default The Travis build passed
Details

dmckeone referenced this pull request Feb 19, 2013

Closed

Add MultiDict Support #1155

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment