1
- import json
2
- import jsonschema
3
1
import os
4
2
import requests
5
3
6
4
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
14
6
15
7
16
8
class DemandAPIClient (object ):
@@ -33,27 +25,14 @@ def __init__(self, client_id=None, username=None, password=None, base_host=None)
33
25
self .base_host = os .getenv ('DYNATA_DEMAND_BASE_URL' , default = 'https://api.researchnow.com' )
34
26
35
27
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.' )
37
29
38
30
self ._access_token = None
39
31
self ._refresh_token = None
40
32
self .auth_base_url = '{}/auth/v1' .format (self .base_host )
41
33
self .base_url = '{}/sample/v1' .format (self .base_host )
42
34
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 ()
57
36
58
37
def _check_authentication (self ):
59
38
# 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):
92
71
return response .json ()
93
72
94
73
def authenticate (self ):
95
- # Sends the authentication data to
74
+ # Sends the authentication data to the access token endpoint.
96
75
url = '{}/token/password' .format (self .auth_base_url )
97
- auth_response = requests . post ( url , json = {
76
+ payload = {
98
77
'clientId' : self .client_id ,
99
78
'password' : self .password ,
100
79
'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 )
102
91
if auth_response .status_code > 399 :
103
92
raise DemandAPIError ('Authentication failed with status {} and error: {}' .format (
104
93
auth_response .status_code ,
@@ -111,12 +100,18 @@ def authenticate(self):
111
100
112
101
def refresh_access_token (self ):
113
102
url = '{}/token/refresh' .format (self .auth_base_url )
114
- refresh_response = requests . post ( url , json = {
103
+ payload = {
115
104
'clientId' : self .client_id ,
116
105
'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 )
118
113
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 (
120
115
refresh_response .status_code , refresh_response .content
121
116
))
122
117
response_data = refresh_response .json ()
@@ -126,49 +121,95 @@ def refresh_access_token(self):
126
121
127
122
def logout (self ):
128
123
url = '{}/logout' .format (self .auth_base_url )
129
- logout_response = requests . post ( url , json = {
124
+ payload = {
130
125
'clientId' : self .client_id ,
131
126
'refreshToken' : self ._refresh_token ,
132
127
'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 )
134
135
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 (
136
137
logout_response .status_code , logout_response .content
137
138
))
138
139
return logout_response .json ()
139
140
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 )
145
158
146
159
def get_event (self , event_id ):
160
+ self .validator .validate_request (
161
+ 'get_event' ,
162
+ path_data = {'eventId' : '{}' .format (event_id )},
163
+ )
147
164
return self ._api_get ('/events/{}' .format (event_id ))
148
165
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 )
151
172
152
173
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
+ '''
155
181
response_data = self ._api_post ('/projects' , project_data )
156
182
if response_data .get ('status' ).get ('message' ) != 'success' :
157
183
raise DemandAPIError (
158
- " Could not create project. Demand API responded with: {}" .format (
184
+ ' Could not create project. Demand API responded with: {}' .format (
159
185
response_data
160
186
)
161
187
)
162
188
return response_data
163
189
164
190
def get_project (self , project_id ):
191
+ self .validator .validate_request (
192
+ 'get_project' ,
193
+ path_data = {'extProjectId' : '{}' .format (project_id )},
194
+ )
165
195
return self ._api_get ('/projects/{}' .format (project_id ))
166
196
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 )
169
203
170
204
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
+ '''
172
213
response_data = self ._api_post ('/projects/{}' .format (project_id ), update_data )
173
214
if response_data .get ('status' ).get ('message' ) != 'success' :
174
215
raise DemandAPIError (
@@ -179,6 +220,10 @@ def update_project(self, project_id, update_data):
179
220
return response_data
180
221
181
222
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
+ )
182
227
return self ._api_get ('/projects/{}/detailedReport' .format (project_id ))
183
228
184
229
def add_line_item (self , project_id , lineitem_data ):
@@ -189,8 +234,16 @@ def add_line_item(self, project_id, lineitem_data):
189
234
completes required. A line item is our unit of work and is what
190
235
gets billed to you.
191
236
'''
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
+ '''
194
247
response_data = self ._api_post ('/projects/{}/lineItems' .format (project_id ), lineitem_data )
195
248
if response_data .get ('status' ).get ('message' ) != 'success' :
196
249
raise DemandAPIError (
@@ -201,16 +254,32 @@ def add_line_item(self, project_id, lineitem_data):
201
254
return response_data
202
255
203
256
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
+ )
204
264
return self ._api_get ('/projects/{}/lineItems/{}' .format (project_id , line_item_id ))
205
265
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 ):
207
267
'''
208
268
Updates the specified line item by setting the values of the parameters passed.
209
269
Any parameters not provided will be left unchanged.
210
270
'''
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 )
214
283
if response_data .get ('status' ).get ('message' ) != 'success' :
215
284
raise DemandAPIError (
216
285
"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):
219
288
)
220
289
return response_data
221
290
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 )
224
298
225
299
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
+ )
226
307
return self ._api_get ('/projects/{}/lineItems/{}/detailedReport' .format (project_id , line_item_id ))
227
308
228
309
def get_feasibility (self , project_id ):
310
+ self .validator .validate_request (
311
+ 'get_feasibility' ,
312
+ path_data = {'extProjectId' : '{}' .format (project_id )},
313
+ )
229
314
return self ._api_get ('/projects/{}/feasibility' .format (project_id ))
230
315
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 )
233
322
234
323
def get_sources (self ):
324
+ self .validator .validate_request (
325
+ 'get_sources' ,
326
+ )
235
327
return self ._api_get ('/sources' )
0 commit comments