[issue18857] urlencode of a None value uses the string 'None'
New submission from Joshua Johnston: This is strange behavior. When you encode nulls in other languages you don't get the string 'null' you usually get an empy string. Shouldn't str(None) == ''? If not str(None) == 'None' and the string representation of a None value should not match a known string >>> from urllib import urlencode >>> urlencode({'josh': None}) 'josh=None' -- components: Extension Modules messages: 196314 nosy: Joshua.Johnston priority: normal severity: normal status: open title: urlencode of a None value uses the string 'None' type: behavior versions: Python 2.7 ___ Python tracker <http://bugs.python.org/issue18857> ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue18857] urlencode of a None value uses the string 'None'
Joshua Johnston added the comment: Hi David, That is what I would expect it to do as well. I'm relatively new to Python but this is causing all kinds of problems with oauth signing using ims_lti_py as well as my own code using urlencode. -- ___ Python tracker <http://bugs.python.org/issue18857> ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue18857] urlencode of a None value uses the string 'None'
Joshua Johnston added the comment: I know that languages like php will treat ?josh= the same as ?josh Using the attached test form in Google Chrome, you will see the data passed as josh= when empty in both GET and POST requests. This is probably the way to go, key=str(value) if value is not None else '' -- Added file: http://bugs.python.org/file31798/test.html ___ Python tracker <http://bugs.python.org/issue18857> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue18857] urlencode of a None value uses the string 'None'
Joshua Johnston added the comment: Hi Senthil, You can open the html file with a browser and inspect the data posting to itself without a web server running. That is how I tested. -- ___ Python tracker <http://bugs.python.org/issue18857> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue18857] urlencode of a None value uses the string 'None'
Joshua Johnston added the comment: I still believe that since None represents the absence of a value it should not be urlencoded as the string 'None'. I am not sure what they best way to url encode it is, but I know that 'None' is not it. -- status: closed -> open ___ Python tracker <http://bugs.python.org/issue18857> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue18857] urlencode of a None value uses the string 'None'
Joshua Johnston added the comment: I agree with True == 'True' and False == 'False' but None should be empty since it represents the absence of a value akin to null, Nil, etc in other languages. Ultimately it is not my decision make so I can only agree to disagree. Thanks for having this discussion with me. So far the python community has been a pleasant change from what I am used to! -- ___ Python tracker <http://bugs.python.org/issue18857> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue18857] urlencode of a None value uses the string 'None'
Joshua Johnston added the comment: In this exact example it would be an empty string. It was a fake setup to illustrate a real problem. This is the important part: params = dict(screen_name=None,count=300) url = "https://api.twitter.com/1.1/friends/ids.json?"; + urllib.urlencode(params) print url # "https://api.twitter.com/1.1/friends/ids.json?screen_name=None&count=300"; screen_name=None is not the behavior you would want. Another example is in webapp2's uri_for function which uses urlencode internally. ref: http://stackoverflow.com/questions/7081250/webapp2-jinja2-how-can-i-get-uri-for-working-in-jinja2-views If you try to use uri_for in your jinja2 template you must jump through hoops like: {% if screen_name %} var url = '{{ uri_for('something', screen_name=screen_name) }}'; {% else %} var url = '{{ uri_for('something') }}'; {% endif %} -- ___ Python tracker <http://bugs.python.org/issue18857> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue18857] urlencode of a None value uses the string 'None'
Joshua Johnston added the comment: If this was a function to encode a dict into something then I would see your point and agree. urlencode is specifically designed to work within the domain or URIs. In this domain, it is acceptable to have an empty value for a key in a query string. None is a representation of nothing, empty, null, the absence of a value. Therefore you would expect a function in the domain of URIs to construct a valid URI component when you specifically tell it to use None. Valid is up to you, either ignore the key-value pair completely, or use key[=&] to represent the empty value. Take Requests as an example that gets it right: >>> import requests >>> requests.get('http://www.google.com/', params={'key': None}).url u'http://www.google.com/' >>> requests.get('http://www.google.com/', params={'key': ''}).url u'http://www.google.com/?key=' -- ___ Python tracker <http://bugs.python.org/issue18857> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue18857] urlencode of a None value uses the string 'None'
Joshua Johnston added the comment: I'm sorry to reopen this but after it biting me quite a few times more I still cannot think of a valid use-case for this behavior that someone would be depending on 'None' being passed. I think your backwards compatibility concerns are artificial. Can anyone describe a use-case that depended on arg=None being passed in a query string? I am sure that anyone who is encountering this behavior is treating the string 'None' as None when encountered in a request query string. Consider this example usage. A website presents a user with a form to search their twitter followers using the twitter api https://api.twitter.com/1.1/friends/ids.json Form fields optional screen_name: [] (assume more fields) Handler gets the form post and builds the dict for the search query string. # User entered nothing so params = {'screen_name': None, ..more fields} params = {k: self.request.get(k, None) for k in self.request.GET} url = "https://api.twitter.com/1.1/friends/ids.json?"; + urllib.urlencode(params) print url "https://api.twitter.com/1.1/friends/ids.json?screen_name=None"; This would cause the twitter search api to look for your friends with None in their screen name. Not exactly what you'd expect right? -- status: closed -> open ___ Python tracker <http://bugs.python.org/issue18857> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue18857] urlencode of a None value uses the string 'None'
Joshua Johnston added the comment: While the RFC makes no mention of empty values either way, it has become standard practice to either omit the key-value completely or pass a key (optional = sign) by itself in these situations so I would consider that as standard behavior. While I stand by my position that the function is broken in regards to None, I do not have the clout to make this change without support from the community so I will leave it at that. >>>Whether or not adding this feature would require a new keyword argument to >>>urlencode is a judgment call. >>>It might be an acceptable change in a feature release. I do believe that it should be changed in a future release and a new keyword argument would suffice except for when the abstraction level is high enough to shield you from being able to specify this new argument. >>I could imagine some programmer building an internal web service that >>turns the string 'None' back into a Python None value. The fact that it >>would have to be an internal thing would mean we'd never hear about >>it...until we broke it :) I was talking to someone about the same thing during lunch today. This whole bug report came about because I was finding 'None' string values in our app engine datastore because of optional parameters with None values being encoded as 'None'. -- ___ Python tracker <http://bugs.python.org/issue18857> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com