Skip to content

Commit dbc05fe

Browse files
author
Akop Kesheshyan
authored
Merge pull request #1 from akopkesheshyan/v1.1.0
V1.1.0
2 parents df9bc58 + f225b9c commit dbc05fe

File tree

3 files changed

+112
-26
lines changed

3 files changed

+112
-26
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@ except BitrixError as message:
5656
List methods return all available items at once. For large collections
5757
of data use limits.
5858

59+
## Tests
60+
61+
```
62+
python -m unittest discover
63+
```
64+
5965
## Author
6066

6167
Akop Kesheshyan - <akop.kesheshyan@icloud.com>

bitrix24/bitrix24.py

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"""
1212
import requests
1313
from time import sleep
14+
from urllib.parse import urlparse
1415
from .exceptions import BitrixError
1516

1617

@@ -27,20 +28,48 @@ class Bitrix24(object):
2728
"""
2829

2930
def __init__(self, domain, timeout=60):
30-
self.domain = domain
31+
"""Create Bitrix24 API object
32+
:param domain: str Bitrix24 webhook domain
33+
:param timeout: int Timeout for API request in seconds
34+
"""
35+
self.domain = self._prepare_domain(domain)
3136
self.timeout = timeout
3237

33-
def _prepare_params(self, params):
34-
"""Transforms list of params to a valid bitrix array."""
38+
def _prepare_domain(self, domain):
39+
"""Normalize user passed domain to a valid one."""
40+
if domain == '' or not isinstance(domain, str):
41+
raise Exception('Empty domain')
3542

36-
new_params = {}
37-
for index, value in params.items():
38-
if type(value) is dict:
39-
for i, v in value.items():
40-
new_params['%s[%s]' % (index, i)] = v
41-
else:
42-
new_params[index] = value
43-
return new_params
43+
o = urlparse(domain)
44+
user_id, code = o.path.split('/')[2:4]
45+
return "{0}://{1}/rest/{2}/{3}".format(o.scheme, o.netloc, user_id, code)
46+
47+
def _prepare_params(self, params, prev=''):
48+
"""Transforms list of params to a valid bitrix array."""
49+
ret = ''
50+
if isinstance(params, dict):
51+
for key, value in params.items():
52+
if isinstance(value, dict):
53+
if prev:
54+
key = "{0}[{1}]".format(prev, key)
55+
ret += self._prepare_params(value, key)
56+
elif (isinstance(value, list) or isinstance(value, tuple)) and len(value) > 0:
57+
for offset, val in enumerate(value):
58+
if isinstance(val, dict):
59+
ret += self._prepare_params(
60+
val, "{0}[{1}][{2}]".format(prev, key, offset))
61+
else:
62+
if prev:
63+
ret += "{0}[{1}][{2}]={3}&".format(
64+
prev, key, offset, val)
65+
else:
66+
ret += "{0}[{1}]={2}&".format(key, offset, val)
67+
else:
68+
if prev:
69+
ret += "{0}[{1}]={2}&".format(prev, key, value)
70+
else:
71+
ret += "{0}={1}&".format(key, value)
72+
return ret
4473

4574
def callMethod(self, method, **params):
4675
"""Calls a REST method with specified parameters.
@@ -65,12 +94,12 @@ def callMethod(self, method, **params):
6594
# Looks like we need to wait until expires limitation time by Bitrix24 API
6695
sleep(2)
6796
return self.callMethod(method, **params)
68-
97+
6998
if 'error' in r:
7099
raise BitrixError(r)
71-
if 'page' not in params:
72-
params['page'] = 1
73-
if 'next' in r and r['total'] > (r['next']*params['page']):
74-
params['page'] += 1
100+
if 'start' not in params:
101+
params['start'] = 0
102+
if 'next' in r and r['total'] > params['start']:
103+
params['start'] += 50
75104
return r['result'] + self.callMethod(method, **params)
76105
return r['result']

tests/test_bitrix24.py

Lines changed: 61 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,11 @@
66
class Bitrix24Test(unittest.TestCase):
77

88
def setUp(self):
9-
self.b24 = Bitrix24(os.environ.get('TEST_DOMAIN'))
9+
self.b24 = Bitrix24('https://example.bitrix24.com/rest/1/123456789')
1010

11-
def test_call_post_method(self):
12-
r = self.b24.callMethod('crm.deal.add', fields={
13-
'TITLE': 'Hello World'})
14-
self.assertIs(type(r), int)
15-
16-
def test_call_get_method(self):
17-
r = self.b24.callMethod('crm.deal.list', filter={
18-
'TITLE': 'Hello World'})
19-
self.assertIs(type(r), list)
11+
def test_init_with_empty_domain(self):
12+
with self.assertRaises(Exception):
13+
Bitrix24('')
2014

2115
def test_call_with_empty_method(self):
2216
with self.assertRaises(BitrixError):
@@ -26,6 +20,63 @@ def test_call_non_exists_method(self):
2620
with self.assertRaises(BitrixError):
2721
self.b24.callMethod('hello.world')
2822

23+
def test_call_wrong_method(self):
24+
with self.assertRaises(BitrixError):
25+
self.b24.callMethod('helloworld')
26+
27+
class ParamsPreparationTest(unittest.TestCase):
28+
29+
def setUp(self):
30+
self.b24 = Bitrix24('https://example.bitrix24.com/rest/1/123456789')
31+
32+
def test_one_level(self):
33+
params = {"fruit": "apple"}
34+
param_string = self.b24._prepare_params(params)
35+
self.assertEqual(param_string, "fruit=apple&")
36+
37+
def test_one_level_several_items(self):
38+
params = {"fruit": "apple", "vegetable": "broccoli"}
39+
param_string = self.b24._prepare_params(params)
40+
self.assertEqual(param_string, "fruit=apple&vegetable=broccoli&")
41+
42+
def test_multi_level(self):
43+
params = {"fruit": {"citrus": "lemon"}}
44+
param_string = self.b24._prepare_params(params)
45+
self.assertEqual(param_string, "fruit[citrus]=lemon&")
46+
47+
def test_multi_level_deep(self):
48+
params = {"root": {"level 1": {"level 2": {"level 3": "value"}}}}
49+
param_string = self.b24._prepare_params(params)
50+
self.assertEqual(
51+
param_string, "root[level 1][level 2][level 3]=value&")
52+
53+
def test_list_dict_mixed(self):
54+
params = {"root": {"level 1": [
55+
{"list_dict 1": "value 1"}, {"list_dict 2": "value 2"}]}}
56+
param_string = self.b24._prepare_params(params)
57+
self.assertEqual(
58+
param_string, "root[level 1][0][list_dict 1]=value 1&root[level 1][1][list_dict 2]=value 2&")
59+
60+
def test_multi_level_several_items(self):
61+
params = {"fruit": {"citrus": "lemon", "sweet": "apple"}}
62+
param_string = self.b24._prepare_params(params)
63+
self.assertEqual(
64+
param_string, "fruit[citrus]=lemon&fruit[sweet]=apple&")
65+
66+
def test_list(self):
67+
params = {"fruit": ["lemon", "apple"]}
68+
param_string = self.b24._prepare_params(params)
69+
self.assertEqual(param_string, "fruit[0]=lemon&fruit[1]=apple&")
70+
71+
def test_tuple(self):
72+
params = {"fruit": ("lemon", "apple")}
73+
param_string = self.b24._prepare_params(params)
74+
self.assertEqual(param_string, "fruit[0]=lemon&fruit[1]=apple&")
75+
76+
def test_string(self):
77+
param_string = self.b24._prepare_params('')
78+
self.assertEqual(param_string, "")
79+
2980

3081
if __name__ == '__main__':
3182
unittest.main()

0 commit comments

Comments
 (0)