Skip to content

Commit e90348c

Browse files
authored
Merge pull request #15 from fbouliane/encode-enumberables-as-arguments
Use python style enumerables in calls
2 parents fa3d014 + 02e5e50 commit e90348c

File tree

5 files changed

+132
-2
lines changed

5 files changed

+132
-2
lines changed

tests/http_utils_test.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import unittest
2+
from ubersmith_client import _http_utils
3+
4+
5+
class HttpUtilsTest(unittest.TestCase):
6+
def test_form_encode_with_list(self):
7+
result = _http_utils.form_encode(dict(test=['a', 'b']))
8+
self.assertDictEqual({
9+
'test[0]': 'a',
10+
'test[1]': 'b',
11+
}, result)
12+
13+
def test_with_tuples(self):
14+
result = _http_utils.form_encode(dict(test=('a', 'b')))
15+
16+
self.assertDictEqual({
17+
'test[0]': 'a',
18+
'test[1]': 'b',
19+
}, result)
20+
21+
def test_with_dict(self):
22+
result = _http_utils.form_encode(dict(test={'a': '1', 'b': '2'}))
23+
24+
self.assertDictEqual({
25+
'test[a]': '1',
26+
'test[b]': '2'
27+
}, result)
28+
29+
def test_with_empty_dict(self):
30+
result = _http_utils.form_encode(dict(test_dict={}, test_list=[]))
31+
32+
self.assertDictEqual({
33+
'test_dict': {},
34+
'test_list': []
35+
}, result)
36+
37+
def test_with_nested_lists_and_dicts(self):
38+
result = _http_utils.form_encode(dict(test=[['a', 'b'], {'c': '1', 'd': '2'}]))
39+
40+
self.assertDictEqual({
41+
'test[0][0]': 'a',
42+
'test[0][1]': 'b',
43+
'test[1][c]': '1',
44+
'test[1][d]': '2'
45+
}, result)
46+
47+
def test_with_bools(self):
48+
result = _http_utils.form_encode(dict(true=True, false=False))
49+
50+
self.assertDictEqual({
51+
'true': True,
52+
'false': False
53+
}, result)
54+
55+
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import unittest
2+
3+
from mock import sentinel, patch, MagicMock
4+
5+
from ubersmith_client.ubersmith_request_get import UbersmithRequestGet
6+
from ubersmith_client.ubersmith_request_post import UbersmithRequestPost
7+
8+
9+
class UbersmithRequestFormEncodingTest(unittest.TestCase):
10+
def setUp(self):
11+
self.ubersmith_constructor_params = (sentinel.url, sentinel.username, sentinel.password,
12+
sentinel.module, sentinel.timeout)
13+
self._standard_kwargs = dict(auth=(sentinel.username, sentinel.password),
14+
timeout=sentinel.timeout,
15+
url=sentinel.url)
16+
17+
@patch('ubersmith_client.ubersmith_request_get.requests')
18+
def test_get_with_list(self, request_mock):
19+
request_mock.get.return_value = MagicMock(status_code=200)
20+
21+
self.client = UbersmithRequestGet(*self.ubersmith_constructor_params)
22+
self.client.call(test=['a'])
23+
24+
expected_args = self._standard_kwargs
25+
expected_args.update(dict(params={
26+
'method': 'sentinel.module.call',
27+
'test[0]': 'a',
28+
}))
29+
request_mock.get.assert_called_with(**expected_args)
30+
31+
@patch('ubersmith_client.ubersmith_request_post.requests')
32+
def test_post_with_list(self, request_mock):
33+
request_mock.post.return_value = MagicMock(status_code=200)
34+
35+
self.client = UbersmithRequestPost(*self.ubersmith_constructor_params)
36+
self.client.call(test=['a'])
37+
38+
expected_args = self._standard_kwargs
39+
expected_args.update(dict(data={
40+
'method': 'sentinel.module.call',
41+
'test[0]': 'a',
42+
}))
43+
request_mock.post.assert_called_with(**expected_args)

ubersmith_client/_http_utils.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
def form_encode(data):
2+
exploded_data = {}
3+
for k, v in data.items():
4+
items = _explode_enumerable(k, v)
5+
for new_key, new_val in items:
6+
exploded_data[new_key] = new_val
7+
return exploded_data
8+
9+
10+
def _explode_enumerable(k, v):
11+
exploded_items = []
12+
if isinstance(v, list) or isinstance(v, tuple):
13+
if len(v) == 0:
14+
exploded_items.append((k, v))
15+
else:
16+
for idx, item in enumerate(v):
17+
current_key = '{}[{}]'.format(k, idx)
18+
exploded_items.extend(_explode_enumerable(current_key, item))
19+
elif isinstance(v, dict):
20+
if len(v) == 0:
21+
exploded_items.append((k, v))
22+
else:
23+
for idx, item in v.items():
24+
current_key = '{}[{}]'.format(k, idx)
25+
exploded_items.extend(_explode_enumerable(current_key, item))
26+
else:
27+
exploded_items.append((k, v))
28+
return exploded_items

ubersmith_client/ubersmith_request_get.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,19 @@
1212
# limitations under the License.
1313
import requests
1414

15+
from ubersmith_client import _http_utils
1516
from ubersmith_client.ubersmith_request import UbersmithRequest
1617

1718

1819
class UbersmithRequestGet(UbersmithRequest):
1920
def __call__(self, **kwargs):
2021
self._build_request_params(kwargs)
22+
params = _http_utils.form_encode(kwargs)
2123

2224
response = self._process_request(method=requests.get,
2325
url=self.url,
2426
auth=(self.user, self.password),
2527
timeout=self.timeout,
26-
params=kwargs)
28+
params=params)
2729

2830
return UbersmithRequest.process_ubersmith_response(response)

ubersmith_client/ubersmith_request_post.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,19 @@
1212
# limitations under the License.
1313
import requests
1414

15+
from ubersmith_client import _http_utils
1516
from ubersmith_client.ubersmith_request import UbersmithRequest
1617

1718

1819
class UbersmithRequestPost(UbersmithRequest):
1920
def __call__(self, **kwargs):
2021
self._build_request_params(kwargs)
22+
params = _http_utils.form_encode(kwargs)
2123

2224
response = self._process_request(method=requests.post,
2325
url=self.url,
2426
auth=(self.user, self.password),
2527
timeout=self.timeout,
26-
data=kwargs)
28+
data=params)
2729

2830
return UbersmithRequest.process_ubersmith_response(response)

0 commit comments

Comments
 (0)