Skip to content

Commit

Permalink
Merge pull request #107 from wogsland/87-project-endpoints
Browse files Browse the repository at this point in the history
project delete & get endpoints
  • Loading branch information
dynata-bradley authored Jan 23, 2020
2 parents b46a8f6 + f77258f commit ebec50a
Showing 5 changed files with 272 additions and 0 deletions.
38 changes: 38 additions & 0 deletions CmixAPIClient/api.py
Original file line number Diff line number Diff line change
@@ -139,6 +139,38 @@ def fetch_raw_results(self, survey_id, payload):
response = requests.post(url, headers=self._authentication_headers, json=payload)
return response.json()

def api_get(self, endpoint, error=''):
self.check_auth_headers()
url = '{}/{}'.format(CMIX_SERVICES['survey'][self.url_type], endpoint)
response = requests.get(url, headers=self._authentication_headers)
if response.status_code != 200:
if '' == error:
error = 'CMIX returned a non-200 response code'
raise CmixError(
'{}: {} and error {}'.format(
error,
response.status_code,
response.text
)
)
return response.json()

def api_delete(self, endpoint, error=''):
self.check_auth_headers()
url = '{}/{}'.format(CMIX_SERVICES['survey'][self.url_type], endpoint)
response = requests.delete(url, headers=self._authentication_headers)
if response.status_code != 200:
if '' == error:
error = 'CMIX returned a non-200 response code'
raise CmixError(
'{}: {} and error {}'.format(
error,
response.status_code,
response.text
)
)
return response.json()

def get_surveys(self, status, *args, **kwargs):
'''kwargs:
@@ -402,3 +434,9 @@ def get_survey_simulations(self, survey_id):
)
)
return simulations_response.json()

def get_projects(self):
project_endpoint = 'projects'
project_error = 'CMIX returned a non-200 response code while getting projects'
project_response = self.api_get(project_endpoint, project_error)
return project_response
78 changes: 78 additions & 0 deletions CmixAPIClient/project.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from .error import CmixError


class CmixProject(object):
def __init__(self, client, project_id):
if None in [client, project_id]:
raise CmixError("Client and project id are required.")
self.client = client
self.project_id = project_id

def delete_project(self):
project_endpoint = 'projects/{}'.format(self.project_id)
project_error = 'CMIX returned a non-200 response code while deleting project'
project_response = self.client.api_delete(project_endpoint, project_error)
return project_response

def delete_group(self, group_id):
project_endpoint = 'projects/{}/groups/{}'.format(self.project_id, group_id)
project_error = 'CMIX returned a non-200 response code while deleting group'
project_response = self.client.api_delete(project_endpoint, project_error)
return project_response

def get_project(self):
project_endpoint = 'projects/{}'.format(self.project_id)
project_error = 'CMIX returned a non-200 response code while getting project'
project_response = self.client.api_get(project_endpoint, project_error)
return project_response

def get_sources(self):
project_endpoint = 'projects/{}/sources'.format(self.project_id)
project_error = 'CMIX returned a non-200 response code while getting project sources'
project_response = self.client.api_get(project_endpoint, project_error)
return project_response

def get_groups(self):
project_endpoint = 'projects/{}/groups'.format(self.project_id)
project_error = 'CMIX returned a non-200 response code while getting project groups'
project_response = self.client.api_get(project_endpoint, project_error)
return project_response

def get_links(self):
project_endpoint = 'projects/{}/links'.format(self.project_id)
project_error = 'CMIX returned a non-200 response code while getting project links'
project_response = self.client.api_get(project_endpoint, project_error)
return project_response

def get_full_links(self):
project_endpoint = 'projects/{}/full-links'.format(self.project_id)
project_error = 'CMIX returned a non-200 response code while getting project full links'
project_response = self.client.api_get(project_endpoint, project_error)
return project_response

def get_locales(self):
project_endpoint = 'projects/{}/locales'.format(self.project_id)
project_error = 'CMIX returned a non-200 response code while getting project locales'
project_response = self.client.api_get(project_endpoint, project_error)
return project_response

def get_markup_files(self):
project_endpoint = 'projects/{}/markup-files'.format(self.project_id)
project_error = 'CMIX returned a non-200 response code while getting project markup files'
project_response = self.client.api_get(project_endpoint, project_error)
return project_response

def get_respondent_links(self):
project_endpoint = 'projects/{}/respondent-links'.format(self.project_id)
project_error = 'CMIX returned a non-200 response code while getting project respondent links'
project_response = self.client.api_get(project_endpoint, project_error)
return project_response

def get_surveys(self):
project_endpoint = 'projects/{}/surveys'.format(self.project_id)
project_error = 'CMIX returned a non-200 response code while getting project surveys'
project_response = self.client.api_get(project_endpoint, project_error)
return project_response
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -25,9 +25,11 @@ A Python client library for the [Dynata Cmix API](https://wiki2.criticalmix.net/

## Supported API Functions

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

### CmixProject

delete_group(group_id)
delete_project()
get_full_links()
get_groups()
get_links()
get_locales()
get_markup_files()
get_project()
get_respondent_links()
get_sources()
get_surveys()

## Contributing

Information on [contributing](https://github.com/dynata/python-cmixapi-client/blob/dev/CONTRIBUTING.md) to this python library.
30 changes: 30 additions & 0 deletions tests/test_api.py
Original file line number Diff line number Diff line change
@@ -22,6 +22,33 @@ def setUp(self):
self.cmix_api = default_cmix_api()
self.cmix_api._authentication_headers = {'Authorization': 'Bearer test'}
self.survey_id = 1337
self.project_id = 1492

def helper_get(self, function_name, endpoint):
func = getattr(self.cmix_api, function_name)

# success case
with mock.patch('CmixAPIClient.api.requests') as mock_request:
mock_get = mock.Mock()
mock_get.status_code = 200
mock_get.json.return_value = {}
mock_request.get.return_value = mock_get

func()

base_url = CMIX_SERVICES['survey']['BASE_URL']
project_url = '{}/{}'.format(base_url, endpoint)
mock_request.get.assert_any_call(project_url, headers=self.cmix_api._authentication_headers)

# error case (survey not found)
with mock.patch('CmixAPIClient.api.requests') as mock_request:
mock_get = mock.Mock()
mock_get.status_code = 404
mock_get.json.return_value = {}
mock_request.get.return_value = mock_get

with self.assertRaises(CmixError):
func()

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

with self.assertRaises(CmixError):
self.cmix_api.get_survey_simulations(self.survey_id)

def test_get_projects(self):
self.helper_get('get_projects', 'projects')
110 changes: 110 additions & 0 deletions tests/test_project.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# -*- coding: utf-8 -*-
from __future__ import print_function
from __future__ import unicode_literals
import mock

from unittest import TestCase
from CmixAPIClient.api import CMIX_SERVICES
from CmixAPIClient.project import CmixProject
from CmixAPIClient.error import CmixError
from .test_api import default_cmix_api


class TestCmixProject(TestCase):
def setUp(self):
self.cmix_api = default_cmix_api()
self.cmix_api._authentication_headers = {'Authorization': 'Bearer test'}
self.project_id = 1492

def helper_get(self, function_name, endpoint):
project = CmixProject(self.cmix_api, self.project_id)
func = getattr(project, function_name)

# success case
with mock.patch('CmixAPIClient.api.requests') as mock_request:
mock_get = mock.Mock()
mock_get.status_code = 200
mock_get.json.return_value = {}
mock_request.get.return_value = mock_get

func()

base_url = CMIX_SERVICES['survey']['BASE_URL']
project_url = '{}/projects{}'.format(base_url, endpoint)
mock_request.get.assert_any_call(project_url, headers=self.cmix_api._authentication_headers)

# error case (survey not found)
with mock.patch('CmixAPIClient.api.requests') as mock_request:
mock_get = mock.Mock()
mock_get.status_code = 404
mock_get.json.return_value = {}
mock_request.get.return_value = mock_get

with self.assertRaises(CmixError):
func()

def helper_delete(self, function_name, endpoint, group_id=None):
project = CmixProject(self.cmix_api, self.project_id)
func = getattr(project, function_name)

# success case
with mock.patch('CmixAPIClient.api.requests') as mock_request:
mock_delete = mock.Mock()
mock_delete.status_code = 200
mock_delete.json.return_value = {}
mock_request.delete.return_value = mock_delete

if group_id is not None:
func(group_id)
else:
func()

base_url = CMIX_SERVICES['survey']['BASE_URL']
project_url = '{}/projects{}'.format(base_url, endpoint)
mock_request.delete.assert_any_call(project_url, headers=self.cmix_api._authentication_headers)

# error case (survey not found)
with mock.patch('CmixAPIClient.api.requests') as mock_request:
mock_delete = mock.Mock()
mock_delete.status_code = 404
mock_delete.json.return_value = {}
mock_request.delete.return_value = mock_delete

with self.assertRaises(CmixError):
if group_id is not None:
func(group_id)
else:
func()

def test_delete_group(self):
self.helper_delete('delete_group', '/{}/groups/{}'.format(self.project_id, 13), 13)

def test_delete_project(self):
self.helper_delete('delete_project', '/{}'.format(self.project_id))

def test_get_project(self):
self.helper_get('get_project', '/{}'.format(self.project_id))

def test_get_sources(self):
self.helper_get('get_sources', '/{}/sources'.format(self.project_id))

def test_get_groups(self):
self.helper_get('get_groups', '/{}/groups'.format(self.project_id))

def test_get_links(self):
self.helper_get('get_links', '/{}/links'.format(self.project_id))

def test_get_full_links(self):
self.helper_get('get_full_links', '/{}/full-links'.format(self.project_id))

def test_get_locales(self):
self.helper_get('get_locales', '/{}/locales'.format(self.project_id))

def test_get_markup_files(self):
self.helper_get('get_markup_files', '/{}/markup-files'.format(self.project_id))

def test_get_respondent_links(self):
self.helper_get('get_respondent_links', '/{}/respondent-links'.format(self.project_id))

def test_get_surveys(self):
self.helper_get('get_surveys', '/{}/surveys'.format(self.project_id))

0 comments on commit ebec50a

Please sign in to comment.