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_update" ,
11
- ]
5
+ from .validator import DemandAPIValidator
12
6
13
7
14
8
class DemandAPIClient (object ):
@@ -31,27 +25,14 @@ def __init__(self, client_id=None, username=None, password=None, base_host=None)
31
25
self .base_host = os .getenv ('DYNATA_DEMAND_BASE_URL' , default = 'https://api.researchnow.com' )
32
26
33
27
if None in [self .client_id , self .username , self .password ]:
34
- raise DemandAPIError (" All authentication data is required." )
28
+ raise DemandAPIError (' All authentication data is required.' )
35
29
36
30
self ._access_token = None
37
31
self ._refresh_token = None
38
32
self .auth_base_url = '{}/auth/v1' .format (self .base_host )
39
33
self .base_url = '{}/sample/v1' .format (self .base_host )
40
34
41
- self ._load_schemas ()
42
-
43
- def _load_schemas (self ):
44
- # Load the compiled schemas for use in validation.
45
- self ._schemas = {}
46
- for schema_type in SCHEMAS :
47
- schema_file = open ('dynatademand/schemas/{}.json' .format (schema_type ), 'r' )
48
- self ._schemas [schema_type ] = json .load (schema_file )
49
- schema_file .close ()
50
-
51
- def _validate_object (self , schema_type , data ):
52
- # jsonschema.validate will return none if there is no error,
53
- # otherwise it will raise its' own error with details on the failure.
54
- jsonschema .validate (self ._schemas [schema_type ], data )
35
+ self .validator = DemandAPIValidator ()
55
36
56
37
def _check_authentication (self ):
57
38
# This doesn't check if the access token is valid, just that it exists.
@@ -90,13 +71,23 @@ def _api_get(self, uri, query_params=None):
90
71
return response .json ()
91
72
92
73
def authenticate (self ):
93
- # Sends the authentication data to
74
+ # Sends the authentication data to the access token endpoint.
94
75
url = '{}/token/password' .format (self .auth_base_url )
95
- auth_response = requests . post ( url , json = {
76
+ payload = {
96
77
'clientId' : self .client_id ,
97
78
'password' : self .password ,
98
79
'username' : self .username ,
99
- })
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 )
100
91
if auth_response .status_code > 399 :
101
92
raise DemandAPIError ('Authentication failed with status {} and error: {}' .format (
102
93
auth_response .status_code ,
@@ -109,12 +100,18 @@ def authenticate(self):
109
100
110
101
def refresh_access_token (self ):
111
102
url = '{}/token/refresh' .format (self .auth_base_url )
112
- refresh_response = requests . post ( url , json = {
103
+ payload = {
113
104
'clientId' : self .client_id ,
114
105
'refreshToken' : self ._refresh_token
115
- })
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 )
116
113
if refresh_response .status_code != 200 :
117
- raise DemandAPIError (" Refreshing Access Token failed with status {} and error: {}" .format (
114
+ raise DemandAPIError (' Refreshing Access Token failed with status {} and error: {}' .format (
118
115
refresh_response .status_code , refresh_response .content
119
116
))
120
117
response_data = refresh_response .json ()
@@ -124,48 +121,109 @@ def refresh_access_token(self):
124
121
125
122
def logout (self ):
126
123
url = '{}/logout' .format (self .auth_base_url )
127
- logout_response = requests . post ( url , json = {
124
+ payload = {
128
125
'clientId' : self .client_id ,
129
126
'refreshToken' : self ._refresh_token ,
130
127
'accessToken' : self ._access_token
131
- })
128
+ }
129
+ self .validator .validate_request (
130
+ 'logout' ,
131
+ request_body = payload
132
+ )
133
+
134
+ logout_response = requests .post (url , json = payload )
132
135
if logout_response .status_code != 204 :
133
- raise DemandAPIError (" Log out failed with status {} and error: {}" .format (
136
+ raise DemandAPIError (' Log out failed with status {} and error: {}' .format (
134
137
logout_response .status_code , logout_response .content
135
138
))
136
139
return logout_response .json ()
137
140
138
- def get_attributes (self , country_code , language_code ):
139
- return self ._api_get ('/attributes/{}/{}' .format (country_code , language_code ))
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 )
140
151
141
- def get_countries (self ):
142
- return self ._api_get ('/countries' )
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 )
143
158
144
159
def get_event (self , event_id ):
160
+ self .validator .validate_request (
161
+ 'get_event' ,
162
+ path_data = {'eventId' : '{}' .format (event_id )},
163
+ )
145
164
return self ._api_get ('/events/{}' .format (event_id ))
146
165
147
- def get_events (self ):
148
- 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 )
149
172
150
173
def create_project (self , project_data ):
151
- # Creates a new project. Uses the "new project" schema.
152
- 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
+ '''
153
181
response_data = self ._api_post ('/projects' , project_data )
154
182
if response_data .get ('status' ).get ('message' ) != 'success' :
155
183
raise DemandAPIError (
156
- " Could not create project. Demand API responded with: {}" .format (
184
+ ' Could not create project. Demand API responded with: {}' .format (
157
185
response_data
158
186
)
159
187
)
160
188
return response_data
161
189
162
190
def get_project (self , project_id ):
191
+ self .validator .validate_request (
192
+ 'get_project' ,
193
+ path_data = {'extProjectId' : '{}' .format (project_id )},
194
+ )
163
195
return self ._api_get ('/projects/{}' .format (project_id ))
164
196
165
- def get_projects (self ):
166
- 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 )
203
+
204
+ def update_project (self , project_id , 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
+ '''
213
+ response_data = self ._api_post ('/projects/{}' .format (project_id ), update_data )
214
+ if response_data .get ('status' ).get ('message' ) != 'success' :
215
+ raise DemandAPIError (
216
+ "Could not update project. Demand API responded with: {}" .format (
217
+ response_data
218
+ )
219
+ )
220
+ return response_data
167
221
168
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
+ )
169
227
return self ._api_get ('/projects/{}/detailedReport' .format (project_id ))
170
228
171
229
def pause_line_item (self , project_id , line_item_id ):
@@ -187,16 +245,32 @@ def pause_line_item(self, project_id, line_item_id):
187
245
return response_data
188
246
189
247
def get_line_item (self , project_id , line_item_id ):
248
+ self .validator .validate_request (
249
+ 'get_line_item' ,
250
+ path_data = {
251
+ 'extProjectId' : '{}' .format (project_id ),
252
+ 'extLineItemId' : '{}' .format (line_item_id )
253
+ },
254
+ )
190
255
return self ._api_get ('/projects/{}/lineItems/{}' .format (project_id , line_item_id ))
191
256
192
- def update_line_item (self , project_id , lineitem_id , lineitem_data ):
257
+ def update_line_item (self , project_id , line_item_id , line_item_data ):
193
258
'''
194
259
Updates the specified line item by setting the values of the parameters passed.
195
260
Any parameters not provided will be left unchanged.
196
261
'''
197
- # Update an existing line item. Uses the "lineitem_update" schema.
198
- self ._validate_object ("lineitem_update" , lineitem_data )
199
- response_data = self ._api_post ('/projects/{}/lineItems/{}' .format (project_id , lineitem_id ), lineitem_data )
262
+ '''
263
+ #TODO: Waiting on a valid path and request body schema.
264
+ self.validator.validate_request(
265
+ 'update_line_item',
266
+ path_data={
267
+ 'extProjectId': '{}'.format(project_id),
268
+ 'extLineItemId': '{}'.format(line_item_id),
269
+ },
270
+ request_body=line_item_data,
271
+ )
272
+ '''
273
+ response_data = self ._api_post ('/projects/{}/lineItems/{}' .format (project_id , line_item_id ), line_item_data )
200
274
if response_data .get ('status' ).get ('message' ) != 'success' :
201
275
raise DemandAPIError (
202
276
"Could not update line item. Demand API responded with: {}" .format (
@@ -205,17 +279,40 @@ def update_line_item(self, project_id, lineitem_id, lineitem_data):
205
279
)
206
280
return response_data
207
281
208
- def get_line_items (self , project_id ):
209
- return self ._api_get ('/projects/{}/lineItems' .format (project_id ))
282
+ def get_line_items (self , project_id , ** kwargs ):
283
+ self .validator .validate_request (
284
+ 'get_line_items' ,
285
+ path_data = {'extProjectId' : '{}' .format (project_id )},
286
+ query_params = kwargs ,
287
+ )
288
+ return self ._api_get ('/projects/{}/lineItems' .format (project_id ), kwargs )
210
289
211
290
def get_line_item_detailed_report (self , project_id , line_item_id ):
291
+ self .validator .validate_request (
292
+ 'get_line_item_detailed_report' ,
293
+ path_data = {
294
+ 'extProjectId' : '{}' .format (project_id ),
295
+ 'extLineItemId' : '{}' .format (line_item_id ),
296
+ },
297
+ )
212
298
return self ._api_get ('/projects/{}/lineItems/{}/detailedReport' .format (project_id , line_item_id ))
213
299
214
300
def get_feasibility (self , project_id ):
301
+ self .validator .validate_request (
302
+ 'get_feasibility' ,
303
+ path_data = {'extProjectId' : '{}' .format (project_id )},
304
+ )
215
305
return self ._api_get ('/projects/{}/feasibility' .format (project_id ))
216
306
217
- def get_survey_topics (self ):
218
- return self ._api_get ('/categories/surveyTopics' )
307
+ def get_survey_topics (self , ** kwargs ):
308
+ self .validator .validate_request (
309
+ 'get_survey_topics' ,
310
+ query_params = kwargs ,
311
+ )
312
+ return self ._api_get ('/categories/surveyTopics' , kwargs )
219
313
220
314
def get_sources (self ):
315
+ self .validator .validate_request (
316
+ 'get_sources' ,
317
+ )
221
318
return self ._api_get ('/sources' )
0 commit comments