Skip to content

Commit 06f405d

Browse files
committed
Merge branch 'dev' into POP-2287
2 parents f17cd4d + 6d29cf3 commit 06f405d

32 files changed

+951
-251
lines changed

dynatademand/api.py

Lines changed: 138 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,8 @@
1-
import json
2-
import jsonschema
31
import os
42
import requests
53

64
from .errors import DemandAPIError
7-
8-
SCHEMAS = [
9-
"project_new",
10-
"project_update",
11-
"lineitem_update",
12-
]
5+
from .validator import DemandAPIValidator
136

147

158
class DemandAPIClient(object):
@@ -32,27 +25,14 @@ def __init__(self, client_id=None, username=None, password=None, base_host=None)
3225
self.base_host = os.getenv('DYNATA_DEMAND_BASE_URL', default='https://api.researchnow.com')
3326

3427
if None in [self.client_id, self.username, self.password]:
35-
raise DemandAPIError("All authentication data is required.")
28+
raise DemandAPIError('All authentication data is required.')
3629

3730
self._access_token = None
3831
self._refresh_token = None
3932
self.auth_base_url = '{}/auth/v1'.format(self.base_host)
4033
self.base_url = '{}/sample/v1'.format(self.base_host)
4134

42-
self._load_schemas()
43-
44-
def _load_schemas(self):
45-
# Load the compiled schemas for use in validation.
46-
self._schemas = {}
47-
for schema_type in SCHEMAS:
48-
schema_file = open('dynatademand/schemas/{}.json'.format(schema_type), 'r')
49-
self._schemas[schema_type] = json.load(schema_file)
50-
schema_file.close()
51-
52-
def _validate_object(self, schema_type, data):
53-
# jsonschema.validate will return none if there is no error,
54-
# otherwise it will raise its' own error with details on the failure.
55-
jsonschema.validate(self._schemas[schema_type], data)
35+
self.validator = DemandAPIValidator()
5636

5737
def _check_authentication(self):
5838
# This doesn't check if the access token is valid, just that it exists.
@@ -91,13 +71,23 @@ def _api_get(self, uri, query_params=None):
9171
return response.json()
9272

9373
def authenticate(self):
94-
# Sends the authentication data to
74+
# Sends the authentication data to the access token endpoint.
9575
url = '{}/token/password'.format(self.auth_base_url)
96-
auth_response = requests.post(url, json={
76+
payload = {
9777
'clientId': self.client_id,
9878
'password': self.password,
9979
'username': self.username,
100-
})
80+
}
81+
82+
'''
83+
#TODO: Waiting for a valid schema.
84+
self.validator.validate_request(
85+
'obtain_access_token',
86+
request_body=payload
87+
)
88+
'''
89+
90+
auth_response = requests.post(url, json=payload)
10191
if auth_response.status_code > 399:
10292
raise DemandAPIError('Authentication failed with status {} and error: {}'.format(
10393
auth_response.status_code,
@@ -110,12 +100,18 @@ def authenticate(self):
110100

111101
def refresh_access_token(self):
112102
url = '{}/token/refresh'.format(self.auth_base_url)
113-
refresh_response = requests.post(url, json={
103+
payload = {
114104
'clientId': self.client_id,
115105
'refreshToken': self._refresh_token
116-
})
106+
}
107+
# Validate the rqeuest before sending.
108+
self.validator.validate_request(
109+
'refresh_access_token',
110+
request_body=payload
111+
)
112+
refresh_response = requests.post(url, json=payload)
117113
if refresh_response.status_code != 200:
118-
raise DemandAPIError("Refreshing Access Token failed with status {} and error: {}".format(
114+
raise DemandAPIError('Refreshing Access Token failed with status {} and error: {}'.format(
119115
refresh_response.status_code, refresh_response.content
120116
))
121117
response_data = refresh_response.json()
@@ -125,36 +121,67 @@ def refresh_access_token(self):
125121

126122
def logout(self):
127123
url = '{}/logout'.format(self.auth_base_url)
128-
logout_response = requests.post(url, json={
124+
payload = {
129125
'clientId': self.client_id,
130126
'refreshToken': self._refresh_token,
131127
'accessToken': self._access_token
132-
})
128+
}
129+
self.validator.validate_request(
130+
'logout',
131+
request_body=payload
132+
)
133+
134+
logout_response = requests.post(url, json=payload)
133135
if logout_response.status_code != 204:
134-
raise DemandAPIError("Log out failed with status {} and error: {}".format(
136+
raise DemandAPIError('Log out failed with status {} and error: {}'.format(
135137
logout_response.status_code, logout_response.content
136138
))
137139
return logout_response.json()
138140

139-
def get_attributes(self, country_code, language_code):
140-
return self._api_get('/attributes/{}/{}'.format(country_code, language_code))
141-
142-
def get_countries(self):
143-
return self._api_get('/countries')
141+
def get_attributes(self, country_code, language_code, **kwargs):
142+
self.validator.validate_request(
143+
'get_attributes',
144+
path_data={
145+
'countryCode': '{}'.format(country_code),
146+
'languageCode': '{}'.format(language_code)
147+
},
148+
query_params=kwargs,
149+
)
150+
return self._api_get('/attributes/{}/{}'.format(country_code, language_code), kwargs)
151+
152+
def get_countries(self, **kwargs):
153+
self.validator.validate_request(
154+
'get_countries',
155+
query_params=kwargs,
156+
)
157+
return self._api_get('/countries', kwargs)
144158

145159
def get_event(self, event_id):
160+
self.validator.validate_request(
161+
'get_event',
162+
path_data={'eventId': '{}'.format(event_id)},
163+
)
146164
return self._api_get('/events/{}'.format(event_id))
147165

148-
def get_events(self):
149-
return self._api_get('/events')
166+
def get_events(self, **kwargs):
167+
self.validator.validate_request(
168+
'get_events',
169+
query_params=kwargs,
170+
)
171+
return self._api_get('/events', kwargs)
150172

151173
def create_project(self, project_data):
152-
# Creates a new project. Uses the "new project" schema.
153-
self._validate_object("project_new", project_data)
174+
'''
175+
#TODO: Waiting on a valid request body schema.
176+
self.validator.validate_request(
177+
'create_project',
178+
request_body=project_data,
179+
)
180+
'''
154181
response_data = self._api_post('/projects', project_data)
155182
if response_data.get('status').get('message') != 'success':
156183
raise DemandAPIError(
157-
"Could not create project. Demand API responded with: {}".format(
184+
'Could not create project. Demand API responded with: {}'.format(
158185
response_data
159186
)
160187
)
@@ -173,13 +200,28 @@ def close_project(self, project_id):
173200
return response_data
174201

175202
def get_project(self, project_id):
203+
self.validator.validate_request(
204+
'get_project',
205+
path_data={'extProjectId': '{}'.format(project_id)},
206+
)
176207
return self._api_get('/projects/{}'.format(project_id))
177208

178-
def get_projects(self):
179-
return self._api_get('/projects')
209+
def get_projects(self, **kwargs):
210+
self.validator.validate_request(
211+
'get_projects',
212+
query_params=kwargs,
213+
)
214+
return self._api_get('/projects', kwargs)
180215

181216
def update_project(self, project_id, update_data):
182-
self._validate_object("project_update", update_data)
217+
'''
218+
#TODO: Waiting on a valid request body schema and path schema.
219+
self.validator.validate_request(
220+
'update_project',
221+
path_data={'extProjectId': '{}'.format(project_id)},
222+
request_body=update_data,
223+
)
224+
'''
183225
response_data = self._api_post('/projects/{}'.format(project_id), update_data)
184226
if response_data.get('status').get('message') != 'success':
185227
raise DemandAPIError(
@@ -190,19 +232,39 @@ def update_project(self, project_id, update_data):
190232
return response_data
191233

192234
def get_project_detailed_report(self, project_id):
235+
self.validator.validate_request(
236+
'get_project_detailed_report',
237+
path_data={'extProjectId': '{}'.format(project_id)},
238+
)
193239
return self._api_get('/projects/{}/detailedReport'.format(project_id))
194240

195241
def get_line_item(self, project_id, line_item_id):
242+
self.validator.validate_request(
243+
'get_line_item',
244+
path_data={
245+
'extProjectId': '{}'.format(project_id),
246+
'extLineItemId': '{}'.format(line_item_id)
247+
},
248+
)
196249
return self._api_get('/projects/{}/lineItems/{}'.format(project_id, line_item_id))
197250

198-
def update_line_item(self, project_id, lineitem_id, lineitem_data):
251+
def update_line_item(self, project_id, line_item_id, line_item_data):
199252
'''
200253
Updates the specified line item by setting the values of the parameters passed.
201254
Any parameters not provided will be left unchanged.
202255
'''
203-
# Update an existing line item. Uses the "lineitem_update" schema.
204-
self._validate_object("lineitem_update", lineitem_data)
205-
response_data = self._api_post('/projects/{}/lineItems/{}'.format(project_id, lineitem_id), lineitem_data)
256+
'''
257+
#TODO: Waiting on a valid path and request body schema.
258+
self.validator.validate_request(
259+
'update_line_item',
260+
path_data={
261+
'extProjectId': '{}'.format(project_id),
262+
'extLineItemId': '{}'.format(line_item_id),
263+
},
264+
request_body=line_item_data,
265+
)
266+
'''
267+
response_data = self._api_post('/projects/{}/lineItems/{}'.format(project_id, line_item_id), line_item_data)
206268
if response_data.get('status').get('message') != 'success':
207269
raise DemandAPIError(
208270
"Could not update line item. Demand API responded with: {}".format(
@@ -211,17 +273,40 @@ def update_line_item(self, project_id, lineitem_id, lineitem_data):
211273
)
212274
return response_data
213275

214-
def get_line_items(self, project_id):
215-
return self._api_get('/projects/{}/lineItems'.format(project_id))
276+
def get_line_items(self, project_id, **kwargs):
277+
self.validator.validate_request(
278+
'get_line_items',
279+
path_data={'extProjectId': '{}'.format(project_id)},
280+
query_params=kwargs,
281+
)
282+
return self._api_get('/projects/{}/lineItems'.format(project_id), kwargs)
216283

217284
def get_line_item_detailed_report(self, project_id, line_item_id):
285+
self.validator.validate_request(
286+
'get_line_item_detailed_report',
287+
path_data={
288+
'extProjectId': '{}'.format(project_id),
289+
'extLineItemId': '{}'.format(line_item_id),
290+
},
291+
)
218292
return self._api_get('/projects/{}/lineItems/{}/detailedReport'.format(project_id, line_item_id))
219293

220294
def get_feasibility(self, project_id):
295+
self.validator.validate_request(
296+
'get_feasibility',
297+
path_data={'extProjectId': '{}'.format(project_id)},
298+
)
221299
return self._api_get('/projects/{}/feasibility'.format(project_id))
222300

223-
def get_survey_topics(self):
224-
return self._api_get('/categories/surveyTopics')
301+
def get_survey_topics(self, **kwargs):
302+
self.validator.validate_request(
303+
'get_survey_topics',
304+
query_params=kwargs,
305+
)
306+
return self._api_get('/categories/surveyTopics', kwargs)
225307

226308
def get_sources(self):
309+
self.validator.validate_request(
310+
'get_sources',
311+
)
227312
return self._api_get('/sources')

0 commit comments

Comments
 (0)