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