Skip to content

Commit ebec50a

Browse files
Merge pull request #107 from wogsland/87-project-endpoints
project delete & get endpoints
2 parents b46a8f6 + f77258f commit ebec50a

File tree

5 files changed

+272
-0
lines changed

5 files changed

+272
-0
lines changed

CmixAPIClient/api.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,38 @@ def fetch_raw_results(self, survey_id, payload):
139139
response = requests.post(url, headers=self._authentication_headers, json=payload)
140140
return response.json()
141141

142+
def api_get(self, endpoint, error=''):
143+
self.check_auth_headers()
144+
url = '{}/{}'.format(CMIX_SERVICES['survey'][self.url_type], endpoint)
145+
response = requests.get(url, headers=self._authentication_headers)
146+
if response.status_code != 200:
147+
if '' == error:
148+
error = 'CMIX returned a non-200 response code'
149+
raise CmixError(
150+
'{}: {} and error {}'.format(
151+
error,
152+
response.status_code,
153+
response.text
154+
)
155+
)
156+
return response.json()
157+
158+
def api_delete(self, endpoint, error=''):
159+
self.check_auth_headers()
160+
url = '{}/{}'.format(CMIX_SERVICES['survey'][self.url_type], endpoint)
161+
response = requests.delete(url, headers=self._authentication_headers)
162+
if response.status_code != 200:
163+
if '' == error:
164+
error = 'CMIX returned a non-200 response code'
165+
raise CmixError(
166+
'{}: {} and error {}'.format(
167+
error,
168+
response.status_code,
169+
response.text
170+
)
171+
)
172+
return response.json()
173+
142174
def get_surveys(self, status, *args, **kwargs):
143175
'''kwargs:
144176
@@ -402,3 +434,9 @@ def get_survey_simulations(self, survey_id):
402434
)
403435
)
404436
return simulations_response.json()
437+
438+
def get_projects(self):
439+
project_endpoint = 'projects'
440+
project_error = 'CMIX returned a non-200 response code while getting projects'
441+
project_response = self.api_get(project_endpoint, project_error)
442+
return project_response

CmixAPIClient/project.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# -*- coding: utf-8 -*-
2+
from __future__ import unicode_literals
3+
4+
from .error import CmixError
5+
6+
7+
class CmixProject(object):
8+
def __init__(self, client, project_id):
9+
if None in [client, project_id]:
10+
raise CmixError("Client and project id are required.")
11+
self.client = client
12+
self.project_id = project_id
13+
14+
def delete_project(self):
15+
project_endpoint = 'projects/{}'.format(self.project_id)
16+
project_error = 'CMIX returned a non-200 response code while deleting project'
17+
project_response = self.client.api_delete(project_endpoint, project_error)
18+
return project_response
19+
20+
def delete_group(self, group_id):
21+
project_endpoint = 'projects/{}/groups/{}'.format(self.project_id, group_id)
22+
project_error = 'CMIX returned a non-200 response code while deleting group'
23+
project_response = self.client.api_delete(project_endpoint, project_error)
24+
return project_response
25+
26+
def get_project(self):
27+
project_endpoint = 'projects/{}'.format(self.project_id)
28+
project_error = 'CMIX returned a non-200 response code while getting project'
29+
project_response = self.client.api_get(project_endpoint, project_error)
30+
return project_response
31+
32+
def get_sources(self):
33+
project_endpoint = 'projects/{}/sources'.format(self.project_id)
34+
project_error = 'CMIX returned a non-200 response code while getting project sources'
35+
project_response = self.client.api_get(project_endpoint, project_error)
36+
return project_response
37+
38+
def get_groups(self):
39+
project_endpoint = 'projects/{}/groups'.format(self.project_id)
40+
project_error = 'CMIX returned a non-200 response code while getting project groups'
41+
project_response = self.client.api_get(project_endpoint, project_error)
42+
return project_response
43+
44+
def get_links(self):
45+
project_endpoint = 'projects/{}/links'.format(self.project_id)
46+
project_error = 'CMIX returned a non-200 response code while getting project links'
47+
project_response = self.client.api_get(project_endpoint, project_error)
48+
return project_response
49+
50+
def get_full_links(self):
51+
project_endpoint = 'projects/{}/full-links'.format(self.project_id)
52+
project_error = 'CMIX returned a non-200 response code while getting project full links'
53+
project_response = self.client.api_get(project_endpoint, project_error)
54+
return project_response
55+
56+
def get_locales(self):
57+
project_endpoint = 'projects/{}/locales'.format(self.project_id)
58+
project_error = 'CMIX returned a non-200 response code while getting project locales'
59+
project_response = self.client.api_get(project_endpoint, project_error)
60+
return project_response
61+
62+
def get_markup_files(self):
63+
project_endpoint = 'projects/{}/markup-files'.format(self.project_id)
64+
project_error = 'CMIX returned a non-200 response code while getting project markup files'
65+
project_response = self.client.api_get(project_endpoint, project_error)
66+
return project_response
67+
68+
def get_respondent_links(self):
69+
project_endpoint = 'projects/{}/respondent-links'.format(self.project_id)
70+
project_error = 'CMIX returned a non-200 response code while getting project respondent links'
71+
project_response = self.client.api_get(project_endpoint, project_error)
72+
return project_response
73+
74+
def get_surveys(self):
75+
project_endpoint = 'projects/{}/surveys'.format(self.project_id)
76+
project_error = 'CMIX returned a non-200 response code while getting project surveys'
77+
project_response = self.client.api_get(project_endpoint, project_error)
78+
return project_response

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@ A Python client library for the [Dynata Cmix API](https://wiki2.criticalmix.net/
2525

2626
## Supported API Functions
2727

28+
### CmixAPI
2829
authenticate(*args, **kwargs)
2930
fetch_banner_filter(survey_id, question_a, question_b, response_id)
3031
fetch_raw_results(survey_id, payload)
32+
get_projects()
3133
get_surveys(status, *args, **kwargs)
3234
get_survey_data_layouts(survey_id)
3335
get_survey_definition(survey_id)
@@ -46,6 +48,20 @@ A Python client library for the [Dynata Cmix API](https://wiki2.criticalmix.net/
4648
update_project(project_id, status=None)
4749
create_survey(xml_string)
4850

51+
### CmixProject
52+
53+
delete_group(group_id)
54+
delete_project()
55+
get_full_links()
56+
get_groups()
57+
get_links()
58+
get_locales()
59+
get_markup_files()
60+
get_project()
61+
get_respondent_links()
62+
get_sources()
63+
get_surveys()
64+
4965
## Contributing
5066

5167
Information on [contributing](https://github.com/dynata/python-cmixapi-client/blob/dev/CONTRIBUTING.md) to this python library.

tests/test_api.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,33 @@ def setUp(self):
2222
self.cmix_api = default_cmix_api()
2323
self.cmix_api._authentication_headers = {'Authorization': 'Bearer test'}
2424
self.survey_id = 1337
25+
self.project_id = 1492
26+
27+
def helper_get(self, function_name, endpoint):
28+
func = getattr(self.cmix_api, function_name)
29+
30+
# success case
31+
with mock.patch('CmixAPIClient.api.requests') as mock_request:
32+
mock_get = mock.Mock()
33+
mock_get.status_code = 200
34+
mock_get.json.return_value = {}
35+
mock_request.get.return_value = mock_get
36+
37+
func()
38+
39+
base_url = CMIX_SERVICES['survey']['BASE_URL']
40+
project_url = '{}/{}'.format(base_url, endpoint)
41+
mock_request.get.assert_any_call(project_url, headers=self.cmix_api._authentication_headers)
42+
43+
# error case (survey not found)
44+
with mock.patch('CmixAPIClient.api.requests') as mock_request:
45+
mock_get = mock.Mock()
46+
mock_get.status_code = 404
47+
mock_get.json.return_value = {}
48+
mock_request.get.return_value = mock_get
49+
50+
with self.assertRaises(CmixError):
51+
func()
2552

2653
def test_cmix_authentication_check(self):
2754
with self.assertRaises(CmixError):
@@ -424,3 +451,6 @@ def test_get_survey_simulations(self):
424451

425452
with self.assertRaises(CmixError):
426453
self.cmix_api.get_survey_simulations(self.survey_id)
454+
455+
def test_get_projects(self):
456+
self.helper_get('get_projects', 'projects')

tests/test_project.py

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# -*- coding: utf-8 -*-
2+
from __future__ import print_function
3+
from __future__ import unicode_literals
4+
import mock
5+
6+
from unittest import TestCase
7+
from CmixAPIClient.api import CMIX_SERVICES
8+
from CmixAPIClient.project import CmixProject
9+
from CmixAPIClient.error import CmixError
10+
from .test_api import default_cmix_api
11+
12+
13+
class TestCmixProject(TestCase):
14+
def setUp(self):
15+
self.cmix_api = default_cmix_api()
16+
self.cmix_api._authentication_headers = {'Authorization': 'Bearer test'}
17+
self.project_id = 1492
18+
19+
def helper_get(self, function_name, endpoint):
20+
project = CmixProject(self.cmix_api, self.project_id)
21+
func = getattr(project, function_name)
22+
23+
# success case
24+
with mock.patch('CmixAPIClient.api.requests') as mock_request:
25+
mock_get = mock.Mock()
26+
mock_get.status_code = 200
27+
mock_get.json.return_value = {}
28+
mock_request.get.return_value = mock_get
29+
30+
func()
31+
32+
base_url = CMIX_SERVICES['survey']['BASE_URL']
33+
project_url = '{}/projects{}'.format(base_url, endpoint)
34+
mock_request.get.assert_any_call(project_url, headers=self.cmix_api._authentication_headers)
35+
36+
# error case (survey not found)
37+
with mock.patch('CmixAPIClient.api.requests') as mock_request:
38+
mock_get = mock.Mock()
39+
mock_get.status_code = 404
40+
mock_get.json.return_value = {}
41+
mock_request.get.return_value = mock_get
42+
43+
with self.assertRaises(CmixError):
44+
func()
45+
46+
def helper_delete(self, function_name, endpoint, group_id=None):
47+
project = CmixProject(self.cmix_api, self.project_id)
48+
func = getattr(project, function_name)
49+
50+
# success case
51+
with mock.patch('CmixAPIClient.api.requests') as mock_request:
52+
mock_delete = mock.Mock()
53+
mock_delete.status_code = 200
54+
mock_delete.json.return_value = {}
55+
mock_request.delete.return_value = mock_delete
56+
57+
if group_id is not None:
58+
func(group_id)
59+
else:
60+
func()
61+
62+
base_url = CMIX_SERVICES['survey']['BASE_URL']
63+
project_url = '{}/projects{}'.format(base_url, endpoint)
64+
mock_request.delete.assert_any_call(project_url, headers=self.cmix_api._authentication_headers)
65+
66+
# error case (survey not found)
67+
with mock.patch('CmixAPIClient.api.requests') as mock_request:
68+
mock_delete = mock.Mock()
69+
mock_delete.status_code = 404
70+
mock_delete.json.return_value = {}
71+
mock_request.delete.return_value = mock_delete
72+
73+
with self.assertRaises(CmixError):
74+
if group_id is not None:
75+
func(group_id)
76+
else:
77+
func()
78+
79+
def test_delete_group(self):
80+
self.helper_delete('delete_group', '/{}/groups/{}'.format(self.project_id, 13), 13)
81+
82+
def test_delete_project(self):
83+
self.helper_delete('delete_project', '/{}'.format(self.project_id))
84+
85+
def test_get_project(self):
86+
self.helper_get('get_project', '/{}'.format(self.project_id))
87+
88+
def test_get_sources(self):
89+
self.helper_get('get_sources', '/{}/sources'.format(self.project_id))
90+
91+
def test_get_groups(self):
92+
self.helper_get('get_groups', '/{}/groups'.format(self.project_id))
93+
94+
def test_get_links(self):
95+
self.helper_get('get_links', '/{}/links'.format(self.project_id))
96+
97+
def test_get_full_links(self):
98+
self.helper_get('get_full_links', '/{}/full-links'.format(self.project_id))
99+
100+
def test_get_locales(self):
101+
self.helper_get('get_locales', '/{}/locales'.format(self.project_id))
102+
103+
def test_get_markup_files(self):
104+
self.helper_get('get_markup_files', '/{}/markup-files'.format(self.project_id))
105+
106+
def test_get_respondent_links(self):
107+
self.helper_get('get_respondent_links', '/{}/respondent-links'.format(self.project_id))
108+
109+
def test_get_surveys(self):
110+
self.helper_get('get_surveys', '/{}/surveys'.format(self.project_id))

0 commit comments

Comments
 (0)