Skip to content

Commit 54b8c39

Browse files
committed
Fixed merge conflicts and also updated create_line_item with validation.
2 parents 95a6ab0 + 6d29cf3 commit 54b8c39

35 files changed

+986
-257
lines changed

dynatademand/api.py

Lines changed: 148 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +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-
"lineitem_new",
11-
"project_update",
12-
"lineitem_update",
13-
]
5+
from .validator import DemandAPIValidator
146

157

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

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

3830
self._access_token = None
3931
self._refresh_token = None
4032
self.auth_base_url = '{}/auth/v1'.format(self.base_host)
4133
self.base_url = '{}/sample/v1'.format(self.base_host)
4234

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

5837
def _check_authentication(self):
5938
# This doesn't check if the access token is valid, just that it exists.
@@ -92,13 +71,23 @@ def _api_get(self, uri, query_params=None):
9271
return response.json()
9372

9473
def authenticate(self):
95-
# Sends the authentication data to
74+
# Sends the authentication data to the access token endpoint.
9675
url = '{}/token/password'.format(self.auth_base_url)
97-
auth_response = requests.post(url, json={
76+
payload = {
9877
'clientId': self.client_id,
9978
'password': self.password,
10079
'username': self.username,
101-
})
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)
10291
if auth_response.status_code > 399:
10392
raise DemandAPIError('Authentication failed with status {} and error: {}'.format(
10493
auth_response.status_code,
@@ -111,12 +100,18 @@ def authenticate(self):
111100

112101
def refresh_access_token(self):
113102
url = '{}/token/refresh'.format(self.auth_base_url)
114-
refresh_response = requests.post(url, json={
103+
payload = {
115104
'clientId': self.client_id,
116105
'refreshToken': self._refresh_token
117-
})
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)
118113
if refresh_response.status_code != 200:
119-
raise DemandAPIError("Refreshing Access Token failed with status {} and error: {}".format(
114+
raise DemandAPIError('Refreshing Access Token failed with status {} and error: {}'.format(
120115
refresh_response.status_code, refresh_response.content
121116
))
122117
response_data = refresh_response.json()
@@ -126,49 +121,95 @@ def refresh_access_token(self):
126121

127122
def logout(self):
128123
url = '{}/logout'.format(self.auth_base_url)
129-
logout_response = requests.post(url, json={
124+
payload = {
130125
'clientId': self.client_id,
131126
'refreshToken': self._refresh_token,
132127
'accessToken': self._access_token
133-
})
128+
}
129+
self.validator.validate_request(
130+
'logout',
131+
request_body=payload
132+
)
133+
134+
logout_response = requests.post(url, json=payload)
134135
if logout_response.status_code != 204:
135-
raise DemandAPIError("Log out failed with status {} and error: {}".format(
136+
raise DemandAPIError('Log out failed with status {} and error: {}'.format(
136137
logout_response.status_code, logout_response.content
137138
))
138139
return logout_response.json()
139140

140-
def get_attributes(self, country_code, language_code):
141-
return self._api_get('/attributes/{}/{}'.format(country_code, language_code))
142-
143-
def get_countries(self):
144-
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)
145158

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

149-
def get_events(self):
150-
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)
151172

152173
def create_project(self, project_data):
153-
# Creates a new project. Uses the "new project" schema.
154-
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+
'''
155181
response_data = self._api_post('/projects', project_data)
156182
if response_data.get('status').get('message') != 'success':
157183
raise DemandAPIError(
158-
"Could not create project. Demand API responded with: {}".format(
184+
'Could not create project. Demand API responded with: {}'.format(
159185
response_data
160186
)
161187
)
162188
return response_data
163189

164190
def get_project(self, project_id):
191+
self.validator.validate_request(
192+
'get_project',
193+
path_data={'extProjectId': '{}'.format(project_id)},
194+
)
165195
return self._api_get('/projects/{}'.format(project_id))
166196

167-
def get_projects(self):
168-
return self._api_get('/projects')
197+
def get_projects(self, **kwargs):
198+
self.validator.validate_request(
199+
'get_projects',
200+
query_params=kwargs,
201+
)
202+
return self._api_get('/projects', kwargs)
169203

170204
def update_project(self, project_id, update_data):
171-
self._validate_object("project_update", update_data)
205+
'''
206+
#TODO: Waiting on a valid request body schema and path schema.
207+
self.validator.validate_request(
208+
'update_project',
209+
path_data={'extProjectId': '{}'.format(project_id)},
210+
request_body=update_data,
211+
)
212+
'''
172213
response_data = self._api_post('/projects/{}'.format(project_id), update_data)
173214
if response_data.get('status').get('message') != 'success':
174215
raise DemandAPIError(
@@ -179,6 +220,10 @@ def update_project(self, project_id, update_data):
179220
return response_data
180221

181222
def get_project_detailed_report(self, project_id):
223+
self.validator.validate_request(
224+
'get_project_detailed_report',
225+
path_data={'extProjectId': '{}'.format(project_id)},
226+
)
182227
return self._api_get('/projects/{}/detailedReport'.format(project_id))
183228

184229
def add_line_item(self, project_id, lineitem_data):
@@ -189,8 +234,16 @@ def add_line_item(self, project_id, lineitem_data):
189234
completes required. A line item is our unit of work and is what
190235
gets billed to you.
191236
'''
192-
# Creates a new line item. Uses the "new lineitem" schema.
193-
self._validate_object("lineitem_new", lineitem_data)
237+
'''
238+
#TODO: Waiting on a valid request body and path schema.
239+
self.validator.validate_request(
240+
'create_line_item',
241+
path_data={
242+
'extProjectId': '{}'.format(project_id)
243+
},
244+
request_body=lineitem_data
245+
)
246+
'''
194247
response_data = self._api_post('/projects/{}/lineItems'.format(project_id), lineitem_data)
195248
if response_data.get('status').get('message') != 'success':
196249
raise DemandAPIError(
@@ -201,16 +254,32 @@ def add_line_item(self, project_id, lineitem_data):
201254
return response_data
202255

203256
def get_line_item(self, project_id, line_item_id):
257+
self.validator.validate_request(
258+
'get_line_item',
259+
path_data={
260+
'extProjectId': '{}'.format(project_id),
261+
'extLineItemId': '{}'.format(line_item_id)
262+
},
263+
)
204264
return self._api_get('/projects/{}/lineItems/{}'.format(project_id, line_item_id))
205265

206-
def update_line_item(self, project_id, lineitem_id, lineitem_data):
266+
def update_line_item(self, project_id, line_item_id, line_item_data):
207267
'''
208268
Updates the specified line item by setting the values of the parameters passed.
209269
Any parameters not provided will be left unchanged.
210270
'''
211-
# Update an existing line item. Uses the "lineitem_update" schema.
212-
self._validate_object("lineitem_update", lineitem_data)
213-
response_data = self._api_post('/projects/{}/lineItems/{}'.format(project_id, lineitem_id), lineitem_data)
271+
'''
272+
#TODO: Waiting on a valid path and request body schema.
273+
self.validator.validate_request(
274+
'update_line_item',
275+
path_data={
276+
'extProjectId': '{}'.format(project_id),
277+
'extLineItemId': '{}'.format(line_item_id),
278+
},
279+
request_body=line_item_data,
280+
)
281+
'''
282+
response_data = self._api_post('/projects/{}/lineItems/{}'.format(project_id, line_item_id), line_item_data)
214283
if response_data.get('status').get('message') != 'success':
215284
raise DemandAPIError(
216285
"Could not update line item. Demand API responded with: {}".format(
@@ -219,17 +288,40 @@ def update_line_item(self, project_id, lineitem_id, lineitem_data):
219288
)
220289
return response_data
221290

222-
def get_line_items(self, project_id):
223-
return self._api_get('/projects/{}/lineItems'.format(project_id))
291+
def get_line_items(self, project_id, **kwargs):
292+
self.validator.validate_request(
293+
'get_line_items',
294+
path_data={'extProjectId': '{}'.format(project_id)},
295+
query_params=kwargs,
296+
)
297+
return self._api_get('/projects/{}/lineItems'.format(project_id), kwargs)
224298

225299
def get_line_item_detailed_report(self, project_id, line_item_id):
300+
self.validator.validate_request(
301+
'get_line_item_detailed_report',
302+
path_data={
303+
'extProjectId': '{}'.format(project_id),
304+
'extLineItemId': '{}'.format(line_item_id),
305+
},
306+
)
226307
return self._api_get('/projects/{}/lineItems/{}/detailedReport'.format(project_id, line_item_id))
227308

228309
def get_feasibility(self, project_id):
310+
self.validator.validate_request(
311+
'get_feasibility',
312+
path_data={'extProjectId': '{}'.format(project_id)},
313+
)
229314
return self._api_get('/projects/{}/feasibility'.format(project_id))
230315

231-
def get_survey_topics(self):
232-
return self._api_get('/categories/surveyTopics')
316+
def get_survey_topics(self, **kwargs):
317+
self.validator.validate_request(
318+
'get_survey_topics',
319+
query_params=kwargs,
320+
)
321+
return self._api_get('/categories/surveyTopics', kwargs)
233322

234323
def get_sources(self):
324+
self.validator.validate_request(
325+
'get_sources',
326+
)
235327
return self._api_get('/sources')

0 commit comments

Comments
 (0)