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,49 +121,95 @@ 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
+ 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 )
141
151
142
- def get_countries (self ):
143
- 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 )
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
)
161
188
return response_data
162
189
163
190
def get_project (self , project_id ):
191
+ self .validator .validate_request (
192
+ 'get_project' ,
193
+ path_data = {'extProjectId' : '{}' .format (project_id )},
194
+ )
164
195
return self ._api_get ('/projects/{}' .format (project_id ))
165
196
166
- def get_projects (self ):
167
- 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 )
168
203
169
204
def update_project (self , project_id , update_data ):
170
- 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
+ '''
171
213
response_data = self ._api_post ('/projects/{}' .format (project_id ), update_data )
172
214
if response_data .get ('status' ).get ('message' ) != 'success' :
173
215
raise DemandAPIError (
@@ -178,19 +220,39 @@ def update_project(self, project_id, update_data):
178
220
return response_data
179
221
180
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
+ )
181
227
return self ._api_get ('/projects/{}/detailedReport' .format (project_id ))
182
228
183
229
def get_line_item (self , project_id , line_item_id ):
230
+ self .validator .validate_request (
231
+ 'get_line_item' ,
232
+ path_data = {
233
+ 'extProjectId' : '{}' .format (project_id ),
234
+ 'extLineItemId' : '{}' .format (line_item_id )
235
+ },
236
+ )
184
237
return self ._api_get ('/projects/{}/lineItems/{}' .format (project_id , line_item_id ))
185
238
186
- def update_line_item (self , project_id , lineitem_id , lineitem_data ):
239
+ def update_line_item (self , project_id , line_item_id , line_item_data ):
187
240
'''
188
241
Updates the specified line item by setting the values of the parameters passed.
189
242
Any parameters not provided will be left unchanged.
190
243
'''
191
- # Update an existing line item. Uses the "lineitem_update" schema.
192
- self ._validate_object ("lineitem_update" , lineitem_data )
193
- response_data = self ._api_post ('/projects/{}/lineItems/{}' .format (project_id , lineitem_id ), lineitem_data )
244
+ '''
245
+ #TODO: Waiting on a valid path and request body schema.
246
+ self.validator.validate_request(
247
+ 'update_line_item',
248
+ path_data={
249
+ 'extProjectId': '{}'.format(project_id),
250
+ 'extLineItemId': '{}'.format(line_item_id),
251
+ },
252
+ request_body=line_item_data,
253
+ )
254
+ '''
255
+ response_data = self ._api_post ('/projects/{}/lineItems/{}' .format (project_id , line_item_id ), line_item_data )
194
256
if response_data .get ('status' ).get ('message' ) != 'success' :
195
257
raise DemandAPIError (
196
258
"Could not update line item. Demand API responded with: {}" .format (
@@ -199,17 +261,40 @@ def update_line_item(self, project_id, lineitem_id, lineitem_data):
199
261
)
200
262
return response_data
201
263
202
- def get_line_items (self , project_id ):
203
- return self ._api_get ('/projects/{}/lineItems' .format (project_id ))
264
+ def get_line_items (self , project_id , ** kwargs ):
265
+ self .validator .validate_request (
266
+ 'get_line_items' ,
267
+ path_data = {'extProjectId' : '{}' .format (project_id )},
268
+ query_params = kwargs ,
269
+ )
270
+ return self ._api_get ('/projects/{}/lineItems' .format (project_id ), kwargs )
204
271
205
272
def get_line_item_detailed_report (self , project_id , line_item_id ):
273
+ self .validator .validate_request (
274
+ 'get_line_item_detailed_report' ,
275
+ path_data = {
276
+ 'extProjectId' : '{}' .format (project_id ),
277
+ 'extLineItemId' : '{}' .format (line_item_id ),
278
+ },
279
+ )
206
280
return self ._api_get ('/projects/{}/lineItems/{}/detailedReport' .format (project_id , line_item_id ))
207
281
208
282
def get_feasibility (self , project_id ):
283
+ self .validator .validate_request (
284
+ 'get_feasibility' ,
285
+ path_data = {'extProjectId' : '{}' .format (project_id )},
286
+ )
209
287
return self ._api_get ('/projects/{}/feasibility' .format (project_id ))
210
288
211
- def get_survey_topics (self ):
212
- return self ._api_get ('/categories/surveyTopics' )
289
+ def get_survey_topics (self , ** kwargs ):
290
+ self .validator .validate_request (
291
+ 'get_survey_topics' ,
292
+ query_params = kwargs ,
293
+ )
294
+ return self ._api_get ('/categories/surveyTopics' , kwargs )
213
295
214
296
def get_sources (self ):
297
+ self .validator .validate_request (
298
+ 'get_sources' ,
299
+ )
215
300
return self ._api_get ('/sources' )
0 commit comments