Skip to content

Instantly share code, notes, and snippets.

@RichardFord
Created February 10, 2020 13:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RichardFord/ac26b726f33330c4d06d1bd3ef423e31 to your computer and use it in GitHub Desktop.
Save RichardFord/ac26b726f33330c4d06d1bd3ef423e31 to your computer and use it in GitHub Desktop.
import unittest
from urllib.parse import quote
def walk(k, v):
join_list = []
for sk, sv in v.items():
if isinstance(sv, dict):
walk(sk, sv)
sub_value = "{}[{}]={}".format(quote(str(k)), quote(str(sk)), quote(str(sv)))
join_list.append(sub_value)
return '&'.join(join_list)
def encodeUrl(params):
"""
This function is expected to return the URL encoded version of the input dictionary.
For example:
- Input: { "name": Marco, "surname": "Pracucci" }
- Output: "name=Marco&surname=Pracucci"
Reserved characters in parameter names and values should be percent encoded
using the `quote` function from `urllib.parse`.
If a nested dictionary is encountered as a paramter value, it should be encoded as
TOP-LEVEL-KEY[SUB-KEY]=VALUE. For example:
- Input: { "person": { "name": "Marco", "surname": "Pracucci" }}
- Output: "person[name]=Marco&person[surname]=Pracucci"
You are NOT allowed to use any of the other function offered by `urllib` or other
Python modules / libraries already implementing this functionality.
You ARE allowed to look for online reference whenever required.
"""
join_list = []
for key, value in params.items():
if isinstance(value, dict):
joined = walk(key, value)
join_list.append(joined)
elif value:
val = "{}={}".format(quote(key), quote(str(value)))
join_list.append(val)
return '&'.join(join_list)
class EncodeUrlTest(unittest.TestCase):
def testShouldEncodeEmptyParameters(self):
self.assertEqual(encodeUrl({}), "")
def testShouldEncodePlainStringParameters(self):
self.assertEqual(encodeUrl({
"name": "Marco",
"surname": "Pracucci"
}), "name=Marco&surname=Pracucci")
def testShouldEncodePlainNumericParameters(self):
self.assertEqual(encodeUrl({
"name": "Marco",
"surname": "Pracucci",
"age": 36
}), "name=Marco&surname=Pracucci&age=36")
def testShouldEncodeWhitespacesInParameterNames(self):
self.assertEqual(encodeUrl({
"name": "Marco",
"surname": "Pracucci",
"street address": "123"
}), "name=Marco&surname=Pracucci&street%20address=123")
def testShouldEncodeWhitespacesInParameterNamesAndValues(self):
self.assertEqual(encodeUrl({
"name": "Marco",
"surname": "Pracucci",
"street address": "123 Main Road"
}), "name=Marco&surname=Pracucci&street%20address=123%20Main%20Road")
def testShouldEncodeNestedObjectsOnOneLevel(self):
self.assertEqual(encodeUrl({
"name": "Marco",
"surname": "Pracucci",
"address": {
"street": "123 Main Road",
"city": "New York",
}
}), "name=Marco&surname=Pracucci&address[street]=123%20Main%20Road&address[city]=New%20York")
def testShouldEncodeNestedObjectsOnMultipleLevels(self):
self.assertEqual(encodeUrl({
"name": "Marco",
"surname": "Pracucci",
"address": {
"street": {
"name": "Main Road",
"number": 123
},
"city": "New York",
}
}), "name=Marco&surname=Pracucci&address[street][name]=Main%20Road&address[street][number]=123&address[city]=New%20York")
def testShouldFilterOutNoneValues(self):
self.assertEqual(encodeUrl({
"name": "Marco",
"surname": "Pracucci",
"address": None
}), "name=Marco&surname=Pracucci")
if __name__ == "__main__":
unittest.main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment