1- import json
2- import jsonschema
31import os
42import requests
53
64from .errors import DemandAPIError
7-
8- SCHEMAS = [
9- "project_new" ,
10- "project_update" ,
11- "lineitem_update" ,
12- ]
5+ from .validator import DemandAPIValidator
136
147
158class DemandAPIClient (object ):
@@ -32,27 +25,14 @@ def __init__(self, client_id=None, username=None, password=None, base_host=None)
3225 self .base_host = os .getenv ('DYNATA_DEMAND_BASE_URL' , default = 'https://api.researchnow.com' )
3326
3427 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.' )
3629
3730 self ._access_token = None
3831 self ._refresh_token = None
3932 self .auth_base_url = '{}/auth/v1' .format (self .base_host )
4033 self .base_url = '{}/sample/v1' .format (self .base_host )
4134
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 ()
5636
5737 def _check_authentication (self ):
5838 # 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):
9171 return response .json ()
9272
9373 def authenticate (self ):
94- # Sends the authentication data to
74+ # Sends the authentication data to the access token endpoint.
9575 url = '{}/token/password' .format (self .auth_base_url )
96- auth_response = requests . post ( url , json = {
76+ payload = {
9777 'clientId' : self .client_id ,
9878 'password' : self .password ,
9979 '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 )
10191 if auth_response .status_code > 399 :
10292 raise DemandAPIError ('Authentication failed with status {} and error: {}' .format (
10393 auth_response .status_code ,
@@ -110,12 +100,18 @@ def authenticate(self):
110100
111101 def refresh_access_token (self ):
112102 url = '{}/token/refresh' .format (self .auth_base_url )
113- refresh_response = requests . post ( url , json = {
103+ payload = {
114104 'clientId' : self .client_id ,
115105 '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 )
117113 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 (
119115 refresh_response .status_code , refresh_response .content
120116 ))
121117 response_data = refresh_response .json ()
@@ -125,49 +121,95 @@ def refresh_access_token(self):
125121
126122 def logout (self ):
127123 url = '{}/logout' .format (self .auth_base_url )
128- logout_response = requests . post ( url , json = {
124+ payload = {
129125 'clientId' : self .client_id ,
130126 'refreshToken' : self ._refresh_token ,
131127 '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 )
133135 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 (
135137 logout_response .status_code , logout_response .content
136138 ))
137139 return logout_response .json ()
138140
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 )
141151
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 )
144158
145159 def get_event (self , event_id ):
160+ self .validator .validate_request (
161+ 'get_event' ,
162+ path_data = {'eventId' : '{}' .format (event_id )},
163+ )
146164 return self ._api_get ('/events/{}' .format (event_id ))
147165
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 )
150172
151173 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+ '''
154181 response_data = self ._api_post ('/projects' , project_data )
155182 if response_data .get ('status' ).get ('message' ) != 'success' :
156183 raise DemandAPIError (
157- " Could not create project. Demand API responded with: {}" .format (
184+ ' Could not create project. Demand API responded with: {}' .format (
158185 response_data
159186 )
160187 )
161188 return response_data
162189
163190 def get_project (self , project_id ):
191+ self .validator .validate_request (
192+ 'get_project' ,
193+ path_data = {'extProjectId' : '{}' .format (project_id )},
194+ )
164195 return self ._api_get ('/projects/{}' .format (project_id ))
165196
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 )
168203
169204 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+ '''
171213 response_data = self ._api_post ('/projects/{}' .format (project_id ), update_data )
172214 if response_data .get ('status' ).get ('message' ) != 'success' :
173215 raise DemandAPIError (
@@ -178,19 +220,39 @@ def update_project(self, project_id, update_data):
178220 return response_data
179221
180222 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+ )
181227 return self ._api_get ('/projects/{}/detailedReport' .format (project_id ))
182228
183229 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+ )
184237 return self ._api_get ('/projects/{}/lineItems/{}' .format (project_id , line_item_id ))
185238
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 ):
187240 '''
188241 Updates the specified line item by setting the values of the parameters passed.
189242 Any parameters not provided will be left unchanged.
190243 '''
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 )
194256 if response_data .get ('status' ).get ('message' ) != 'success' :
195257 raise DemandAPIError (
196258 "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):
199261 )
200262 return response_data
201263
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 )
204271
205272 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+ )
206280 return self ._api_get ('/projects/{}/lineItems/{}/detailedReport' .format (project_id , line_item_id ))
207281
208282 def get_feasibility (self , project_id ):
283+ self .validator .validate_request (
284+ 'get_feasibility' ,
285+ path_data = {'extProjectId' : '{}' .format (project_id )},
286+ )
209287 return self ._api_get ('/projects/{}/feasibility' .format (project_id ))
210288
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 )
213295
214296 def get_sources (self ):
297+ self .validator .validate_request (
298+ 'get_sources' ,
299+ )
215300 return self ._api_get ('/sources' )
0 commit comments