1- import json
2- import jsonschema
31import os
42import requests
53
64from .errors import DemandAPIError
7-
8- SCHEMAS = [
9- "project_new" ,
10- "project_buy" ,
11- "project_update" ,
12- "lineitem_update" ,
13- ]
5+ from .validator import DemandAPIValidator
146
157
168class DemandAPIClient (object ):
@@ -33,27 +25,14 @@ def __init__(self, client_id=None, username=None, password=None, base_host=None)
3325 self .base_host = os .getenv ('DYNATA_DEMAND_BASE_URL' , default = 'https://api.researchnow.com' )
3426
3527 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.' )
3729
3830 self ._access_token = None
3931 self ._refresh_token = None
4032 self .auth_base_url = '{}/auth/v1' .format (self .base_host )
4133 self .base_url = '{}/sample/v1' .format (self .base_host )
4234
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 ()
5736
5837 def _check_authentication (self ):
5938 # 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):
9271 return response .json ()
9372
9473 def authenticate (self ):
95- # Sends the authentication data to
74+ # Sends the authentication data to the access token endpoint.
9675 url = '{}/token/password' .format (self .auth_base_url )
97- auth_response = requests . post ( url , json = {
76+ payload = {
9877 'clientId' : self .client_id ,
9978 'password' : self .password ,
10079 '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 )
10291 if auth_response .status_code > 399 :
10392 raise DemandAPIError ('Authentication failed with status {} and error: {}' .format (
10493 auth_response .status_code ,
@@ -111,12 +100,18 @@ def authenticate(self):
111100
112101 def refresh_access_token (self ):
113102 url = '{}/token/refresh' .format (self .auth_base_url )
114- refresh_response = requests . post ( url , json = {
103+ payload = {
115104 'clientId' : self .client_id ,
116105 '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 )
118113 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 (
120115 refresh_response .status_code , refresh_response .content
121116 ))
122117 response_data = refresh_response .json ()
@@ -126,36 +121,67 @@ def refresh_access_token(self):
126121
127122 def logout (self ):
128123 url = '{}/logout' .format (self .auth_base_url )
129- logout_response = requests . post ( url , json = {
124+ payload = {
130125 'clientId' : self .client_id ,
131126 'refreshToken' : self ._refresh_token ,
132127 '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 )
134135 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 (
136137 logout_response .status_code , logout_response .content
137138 ))
138139 return logout_response .json ()
139140
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 )
145158
146159 def get_event (self , event_id ):
160+ self .validator .validate_request (
161+ 'get_event' ,
162+ path_data = {'eventId' : '{}' .format (event_id )},
163+ )
147164 return self ._api_get ('/events/{}' .format (event_id ))
148165
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 )
151172
152173 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+ '''
155181 response_data = self ._api_post ('/projects' , project_data )
156182 if response_data .get ('status' ).get ('message' ) != 'success' :
157183 raise DemandAPIError (
158- " Could not create project. Demand API responded with: {}" .format (
184+ ' Could not create project. Demand API responded with: {}' .format (
159185 response_data
160186 )
161187 )
@@ -178,13 +204,28 @@ def buy_project(self, project_id, buy_data):
178204 return response_data
179205
180206 def get_project (self , project_id ):
207+ self .validator .validate_request (
208+ 'get_project' ,
209+ path_data = {'extProjectId' : '{}' .format (project_id )},
210+ )
181211 return self ._api_get ('/projects/{}' .format (project_id ))
182212
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 )
185219
186220 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+ '''
188229 response_data = self ._api_post ('/projects/{}' .format (project_id ), update_data )
189230 if response_data .get ('status' ).get ('message' ) != 'success' :
190231 raise DemandAPIError (
@@ -195,19 +236,39 @@ def update_project(self, project_id, update_data):
195236 return response_data
196237
197238 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+ )
198243 return self ._api_get ('/projects/{}/detailedReport' .format (project_id ))
199244
200245 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+ )
201253 return self ._api_get ('/projects/{}/lineItems/{}' .format (project_id , line_item_id ))
202254
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 ):
204256 '''
205257 Updates the specified line item by setting the values of the parameters passed.
206258 Any parameters not provided will be left unchanged.
207259 '''
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 )
211272 if response_data .get ('status' ).get ('message' ) != 'success' :
212273 raise DemandAPIError (
213274 "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):
216277 )
217278 return response_data
218279
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 )
221287
222288 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+ )
223296 return self ._api_get ('/projects/{}/lineItems/{}/detailedReport' .format (project_id , line_item_id ))
224297
225298 def get_feasibility (self , project_id ):
299+ self .validator .validate_request (
300+ 'get_feasibility' ,
301+ path_data = {'extProjectId' : '{}' .format (project_id )},
302+ )
226303 return self ._api_get ('/projects/{}/feasibility' .format (project_id ))
227304
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 )
230311
231312 def get_sources (self ):
313+ self .validator .validate_request (
314+ 'get_sources' ,
315+ )
232316 return self ._api_get ('/sources' )
0 commit comments