Skip to content

Commit 72377b8

Browse files
committed
Moved schema validation to a module. Refactored schema validation.
1 parent 09aceca commit 72377b8

20 files changed

+533
-264
lines changed

dynatademand/api.py

Lines changed: 152 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,7 @@
44
import requests
55

66
from .errors import DemandAPIError
7-
8-
REQUEST_BODY_SCHEMAS = [
9-
'create_project',
10-
"update_project",
11-
'update_line_item',
12-
]
13-
14-
REQUEST_PATH_SCHEMAS = [
15-
'get_attributes',
16-
'get_event',
17-
'get_feasibility',
18-
'get_line_item',
19-
'get_line_item_detailed_report',
20-
'get_line_items',
21-
'get_project',
22-
'get_project_detailed_report',
23-
'update_line_item',
24-
'update_project'
25-
]
26-
27-
REQUEST_QUERY_SCHEMAS = [
28-
'get_attributes',
29-
'get_countries',
30-
'get_events',
31-
'get_line_items',
32-
'get_projects',
33-
'get_survey_topics',
34-
]
7+
from .validator import DemandAPIValidator
358

369

3710
class DemandAPIClient(object):
@@ -61,37 +34,7 @@ def __init__(self, client_id=None, username=None, password=None, base_host=None)
6134
self.auth_base_url = '{}/auth/v1'.format(self.base_host)
6235
self.base_url = '{}/sample/v1'.format(self.base_host)
6336

64-
self._load_schemas()
65-
66-
def _load_schemas(self):
67-
# Load the compiled schemas for use in validation.
68-
self._request_body_schemas = {}
69-
for schema_type in REQUEST_BODY_SCHEMAS:
70-
schema_file = open('dynatademand/schemas/request/body/{}.json'.format(schema_type), 'r')
71-
self._request_body_schemas[schema_type] = json.load(schema_file)
72-
schema_file.close()
73-
self._request_path_schemas = {}
74-
for schema_type in REQUEST_PATH_SCHEMAS:
75-
schema_file = open('dynatademand/schemas/request/path/{}.json'.format(schema_type), 'r')
76-
self._request_path_schemas[schema_type] = json.load(schema_file)
77-
schema_file.close()
78-
self._request_query_schemas = {}
79-
for schema_type in REQUEST_QUERY_SCHEMAS:
80-
schema_file = open('dynatademand/schemas/request/query/{}.json'.format(schema_type), 'r')
81-
self._request_query_schemas[schema_type] = json.load(schema_file)
82-
schema_file.close()
83-
84-
def _validate_object(self, object_type, schema_type, data):
85-
# jsonschema.validate will return none if there is no error,
86-
# otherwise it will raise its' own error with details on the failure.
87-
schema = ''
88-
if 'request_body' == object_type:
89-
schema = self._request_body_schemas[schema_type]
90-
elif 'request_path' == object_type:
91-
schema = self._request_path_schemas[schema_type]
92-
elif 'request_query' == object_type:
93-
schema = self._request_query_schemas[schema_type]
94-
jsonschema.validate(schema=schema, instance=data)
37+
self.validator = DemandAPIValidator()
9538

9639
def _check_authentication(self):
9740
# This doesn't check if the access token is valid, just that it exists.
@@ -130,13 +73,23 @@ def _api_get(self, uri, query_params=None):
13073
return response.json()
13174

13275
def authenticate(self):
133-
# Sends the authentication data to
76+
# Sends the authentication data to the access token endpoint.
13477
url = '{}/token/password'.format(self.auth_base_url)
135-
auth_response = requests.post(url, json={
78+
payload = {
13679
'clientId': self.client_id,
13780
'password': self.password,
13881
'username': self.username,
139-
})
82+
}
83+
84+
'''
85+
#TODO: Waiting for a valid schema.
86+
self.validator.validate_request(
87+
'obtain_access_token',
88+
request_body=payload
89+
)
90+
'''
91+
92+
auth_response = requests.post(url, json=payload)
14093
if auth_response.status_code > 399:
14194
raise DemandAPIError('Authentication failed with status {} and error: {}'.format(
14295
auth_response.status_code,
@@ -149,10 +102,16 @@ def authenticate(self):
149102

150103
def refresh_access_token(self):
151104
url = '{}/token/refresh'.format(self.auth_base_url)
152-
refresh_response = requests.post(url, json={
105+
payload = {
153106
'clientId': self.client_id,
154107
'refreshToken': self._refresh_token
155-
})
108+
}
109+
# Validate the rqeuest before sending.
110+
self.validator.validate_request(
111+
'refresh_access_token',
112+
request_body=payload
113+
)
114+
refresh_response = requests.post(url, json=payload)
156115
if refresh_response.status_code != 200:
157116
raise DemandAPIError('Refreshing Access Token failed with status {} and error: {}'.format(
158117
refresh_response.status_code, refresh_response.content
@@ -164,43 +123,73 @@ def refresh_access_token(self):
164123

165124
def logout(self):
166125
url = '{}/logout'.format(self.auth_base_url)
167-
logout_response = requests.post(url, json={
126+
payload = {
168127
'clientId': self.client_id,
169128
'refreshToken': self._refresh_token,
170129
'accessToken': self._access_token
171-
})
130+
}
131+
self.validator.validate_request(
132+
'logout',
133+
request_body=payload
134+
)
135+
136+
logout_response = requests.post(url, json=payload)
172137
if logout_response.status_code != 204:
173138
raise DemandAPIError('Log out failed with status {} and error: {}'.format(
174139
logout_response.status_code, logout_response.content
175140
))
176141
return logout_response.json()
177142

178143
def get_attributes(self, country_code, language_code):
179-
# Validate path
180-
self._validate_object('request_path', 'get_attributes', {
181-
'countryCode': '{}'.format(country_code),
182-
'languageCode': '{}'.format(language_code)
183-
})
184-
# No query or request body schemas to validate.
144+
self.validator.validate_request(
145+
'get_attributes',
146+
path_data={
147+
'countryCode': '{}'.format(country_code),
148+
'languageCode': '{}'.format(language_code)
149+
},
150+
query_params={},
151+
request_body={},
152+
)
185153
return self._api_get('/attributes/{}/{}'.format(country_code, language_code))
186154

187155
def get_countries(self):
188-
# No schemas to validate.
156+
self.validator.validate_request(
157+
'get_countries',
158+
path_data={},
159+
query_params={},
160+
request_body={},
161+
)
189162
return self._api_get('/countries')
190163

191164
def get_event(self, event_id):
192-
# Validate path
193-
self._validate_object('request_path', 'get_event', {'eventId': '{}'.format(event_id)})
165+
self.validator.validate_request(
166+
'get_event',
167+
path_data={'eventId': '{}'.format(event_id)},
168+
query_params={},
169+
request_body={},
170+
)
194171
return self._api_get('/events/{}'.format(event_id))
195172

196-
def get_events(self):
197-
# No schemas to validate.
173+
def get_events(self, **kwargs):
174+
self.validator.validate_request(
175+
'get_events',
176+
path_data={},
177+
query_params=kwargs,
178+
request_body={},
179+
)
198180
return self._api_get('/events')
199181

200182
def create_project(self, project_data):
201-
# Validate request body
202-
self._validate_object('request_body', 'create_project', project_data)
203-
# No path or query schemas to validate.
183+
'''
184+
#TODO: Waiting on a valid request body schema.
185+
self.validator.validate_request(
186+
'create_project',
187+
path_data={},
188+
query_params={},
189+
request_body=project_data,
190+
)
191+
'''
192+
204193
response_data = self._api_post('/projects', project_data)
205194
if response_data.get('status').get('message') != 'success':
206195
raise DemandAPIError(
@@ -211,22 +200,33 @@ def create_project(self, project_data):
211200
return response_data
212201

213202
def get_project(self, project_id):
214-
# Validate path
215-
self._validate_object('request_path', 'get_project', {
216-
'extProjectId': '{}'.format(project_id)
217-
})
203+
self.validator.validate_request(
204+
'get_project',
205+
path_data={'extProjectId': '{}'.format(project_id)},
206+
query_params={},
207+
request_body={},
208+
)
218209
return self._api_get('/projects/{}'.format(project_id))
219210

220-
def get_projects(self):
221-
# No schemas to validate.
211+
def get_projects(self, **kwargs):
212+
self.validator.validate_request(
213+
'get_projects',
214+
path_data={},
215+
query_params=kwargs,
216+
request_body={},
217+
)
222218
return self._api_get('/projects')
223219

224220
def update_project(self, project_id, update_data):
225-
# Validate path and request body.
226-
self._validate_object('request_path', 'update_project', {
227-
'extProjectId': '{}'.format(project_id)
228-
})
229-
self._validate_object('request_body', 'update_project', update_data)
221+
'''
222+
#TODO: Waiting on a valid request body schema and path schema.
223+
self.validator.validate_request(
224+
'update_project',
225+
path_data={'extProjectId': '{}'.format(project_id)},
226+
query_params={},
227+
request_body=update_data,
228+
)
229+
'''
230230
response_data = self._api_post('/projects/{}'.format(project_id), update_data)
231231
if response_data.get('status').get('message') != 'success':
232232
raise DemandAPIError(
@@ -237,33 +237,43 @@ def update_project(self, project_id, update_data):
237237
return response_data
238238

239239
def get_project_detailed_report(self, project_id):
240-
# Validate path
241-
self._validate_object('request_path', 'get_project_detailed_report', {
242-
'extProjectId': '{}'.format(project_id)
243-
})
244-
# No query or request body to validate.
240+
self.validator.validate_request(
241+
'get_project_detailed_report',
242+
path_data={'extProjectId': '{}'.format(project_id)},
243+
query_params={},
244+
request_body={},
245+
)
245246
return self._api_get('/projects/{}/detailedReport'.format(project_id))
246247

247248
def get_line_item(self, project_id, line_item_id):
248-
# Validate path
249-
self._validate_object('request_path', 'get_line_item', {
250-
'extProjectId': '{}'.format(project_id),
251-
'extLineItemId': '{}'.format(line_item_id)
252-
})
253-
# No query or request body to validate.
249+
self.validator.validate_request(
250+
'get_line_item',
251+
path_data={
252+
'extProjectId': '{}'.format(project_id),
253+
'extLineItemId': '{}'.format(line_item_id)
254+
},
255+
query_params={},
256+
request_body={},
257+
)
254258
return self._api_get('/projects/{}/lineItems/{}'.format(project_id, line_item_id))
255259

256260
def update_line_item(self, project_id, line_item_id, line_item_data):
257261
'''
258262
Updates the specified line item by setting the values of the parameters passed.
259263
Any parameters not provided will be left unchanged.
260264
'''
261-
# Validate path and request body.
262-
self._validate_object('request_path', 'update_line_item', {
263-
'extProjectId': '{}'.format(project_id),
264-
'extLineItemId': '{}'.format(line_item_id),
265-
})
266-
self._validate_object('request_body', 'update_line_item', line_item_data)
265+
'''
266+
#TODO: Waiting on a valid path and request body schema.
267+
self.validator.validate_request(
268+
'update_line_item',
269+
path_data={
270+
'extProjectId': '{}'.format(project_id),
271+
'extLineItemId': '{}'.format(line_item_id),
272+
},
273+
query_params={},
274+
request_body=line_item_data,
275+
)
276+
'''
267277
response_data = self._api_post('/projects/{}/lineItems/{}'.format(project_id, line_item_id), line_item_data)
268278
if response_data.get('status').get('message') != 'success':
269279
raise DemandAPIError(
@@ -273,35 +283,50 @@ def update_line_item(self, project_id, line_item_id, line_item_data):
273283
)
274284
return response_data
275285

276-
def get_line_items(self, project_id):
277-
# Validate path
278-
self._validate_object('request_path', 'get_line_items', {
279-
'extProjectId': '{}'.format(project_id)
280-
})
281-
# No query or request body to validate.
286+
def get_line_items(self, project_id, **kwargs):
287+
self.validator.validate_request(
288+
'get_line_items',
289+
path_data={'extProjectId': '{}'.format(project_id)},
290+
query_params=kwargs,
291+
request_body={},
292+
)
282293
return self._api_get('/projects/{}/lineItems'.format(project_id))
283294

284295
def get_line_item_detailed_report(self, project_id, line_item_id):
285-
# Validate path
286-
self._validate_object('request_path', 'get_line_item_detailed_report', {
287-
'extProjectId': '{}'.format(project_id),
288-
'extLineItemId': '{}'.format(line_item_id),
289-
})
290-
# No query or request body to validate.
296+
self.validator.validate_request(
297+
'get_line_item_detailed_report',
298+
path_data={
299+
'extProjectId': '{}'.format(project_id),
300+
'extLineItemId': '{}'.format(line_item_id),
301+
},
302+
query_params={},
303+
request_body={},
304+
)
291305
return self._api_get('/projects/{}/lineItems/{}/detailedReport'.format(project_id, line_item_id))
292306

293307
def get_feasibility(self, project_id):
294-
# Validate path
295-
self._validate_object('request_path', 'get_feasibility', {
296-
'extProjectId': '{}'.format(project_id)
297-
})
298-
# No query or request body to validate.
308+
self.validator.validate_request(
309+
'get_feasibility',
310+
path_data={'extProjectId': '{}'.format(project_id)},
311+
query_params={},
312+
request_body={},
313+
)
299314
return self._api_get('/projects/{}/feasibility'.format(project_id))
300315

301316
def get_survey_topics(self):
302-
# No schemas to validate.
317+
self.validator.validate_request(
318+
'get_survey_topics',
319+
path_data={},
320+
query_params={},
321+
request_body={},
322+
)
303323
return self._api_get('/categories/surveyTopics')
304324

305325
def get_sources(self):
306-
# No schemas to validate.
326+
self.validator.validate_request(
327+
'get_sources',
328+
path_data={},
329+
query_params={},
330+
request_body={},
331+
)
307332
return self._api_get('/sources')

0 commit comments

Comments
 (0)