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
- "project_buy" ,
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 (schema = self ._schemas [schema_type ], instance = 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,36 +121,67 @@ 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
)
@@ -178,13 +204,28 @@ def buy_project(self, project_id, buy_data):
178
204
return response_data
179
205
180
206
def get_project (self , project_id ):
207
+ self .validator .validate_request (
208
+ 'get_project' ,
209
+ path_data = {'extProjectId' : '{}' .format (project_id )},
210
+ )
181
211
return self ._api_get ('/projects/{}' .format (project_id ))
182
212
183
- def get_projects (self ):
184
- return self ._api_get ('/projects' )
213
+ def get_projects (self , ** kwargs ):
214
+ self .validator .validate_request (
215
+ 'get_projects' ,
216
+ query_params = kwargs ,
217
+ )
218
+ return self ._api_get ('/projects' , kwargs )
185
219
186
220
def update_project (self , project_id , update_data ):
187
- self ._validate_object ("project_update" , 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
+ request_body=update_data,
227
+ )
228
+ '''
188
229
response_data = self ._api_post ('/projects/{}' .format (project_id ), update_data )
189
230
if response_data .get ('status' ).get ('message' ) != 'success' :
190
231
raise DemandAPIError (
@@ -195,19 +236,39 @@ def update_project(self, project_id, update_data):
195
236
return response_data
196
237
197
238
def get_project_detailed_report (self , project_id ):
239
+ self .validator .validate_request (
240
+ 'get_project_detailed_report' ,
241
+ path_data = {'extProjectId' : '{}' .format (project_id )},
242
+ )
198
243
return self ._api_get ('/projects/{}/detailedReport' .format (project_id ))
199
244
200
245
def get_line_item (self , project_id , line_item_id ):
246
+ self .validator .validate_request (
247
+ 'get_line_item' ,
248
+ path_data = {
249
+ 'extProjectId' : '{}' .format (project_id ),
250
+ 'extLineItemId' : '{}' .format (line_item_id )
251
+ },
252
+ )
201
253
return self ._api_get ('/projects/{}/lineItems/{}' .format (project_id , line_item_id ))
202
254
203
- def update_line_item (self , project_id , lineitem_id , lineitem_data ):
255
+ def update_line_item (self , project_id , line_item_id , line_item_data ):
204
256
'''
205
257
Updates the specified line item by setting the values of the parameters passed.
206
258
Any parameters not provided will be left unchanged.
207
259
'''
208
- # Update an existing line item. Uses the "lineitem_update" schema.
209
- self ._validate_object ("lineitem_update" , lineitem_data )
210
- response_data = self ._api_post ('/projects/{}/lineItems/{}' .format (project_id , lineitem_id ), lineitem_data )
260
+ '''
261
+ #TODO: Waiting on a valid path and request body schema.
262
+ self.validator.validate_request(
263
+ 'update_line_item',
264
+ path_data={
265
+ 'extProjectId': '{}'.format(project_id),
266
+ 'extLineItemId': '{}'.format(line_item_id),
267
+ },
268
+ request_body=line_item_data,
269
+ )
270
+ '''
271
+ response_data = self ._api_post ('/projects/{}/lineItems/{}' .format (project_id , line_item_id ), line_item_data )
211
272
if response_data .get ('status' ).get ('message' ) != 'success' :
212
273
raise DemandAPIError (
213
274
"Could not update line item. Demand API responded with: {}" .format (
@@ -216,17 +277,40 @@ def update_line_item(self, project_id, lineitem_id, lineitem_data):
216
277
)
217
278
return response_data
218
279
219
- def get_line_items (self , project_id ):
220
- return self ._api_get ('/projects/{}/lineItems' .format (project_id ))
280
+ def get_line_items (self , project_id , ** kwargs ):
281
+ self .validator .validate_request (
282
+ 'get_line_items' ,
283
+ path_data = {'extProjectId' : '{}' .format (project_id )},
284
+ query_params = kwargs ,
285
+ )
286
+ return self ._api_get ('/projects/{}/lineItems' .format (project_id ), kwargs )
221
287
222
288
def get_line_item_detailed_report (self , project_id , line_item_id ):
289
+ self .validator .validate_request (
290
+ 'get_line_item_detailed_report' ,
291
+ path_data = {
292
+ 'extProjectId' : '{}' .format (project_id ),
293
+ 'extLineItemId' : '{}' .format (line_item_id ),
294
+ },
295
+ )
223
296
return self ._api_get ('/projects/{}/lineItems/{}/detailedReport' .format (project_id , line_item_id ))
224
297
225
298
def get_feasibility (self , project_id ):
299
+ self .validator .validate_request (
300
+ 'get_feasibility' ,
301
+ path_data = {'extProjectId' : '{}' .format (project_id )},
302
+ )
226
303
return self ._api_get ('/projects/{}/feasibility' .format (project_id ))
227
304
228
- def get_survey_topics (self ):
229
- return self ._api_get ('/categories/surveyTopics' )
305
+ def get_survey_topics (self , ** kwargs ):
306
+ self .validator .validate_request (
307
+ 'get_survey_topics' ,
308
+ query_params = kwargs ,
309
+ )
310
+ return self ._api_get ('/categories/surveyTopics' , kwargs )
230
311
231
312
def get_sources (self ):
313
+ self .validator .validate_request (
314
+ 'get_sources' ,
315
+ )
232
316
return self ._api_get ('/sources' )
0 commit comments