1- import json
2- import jsonschema
31import os
42import requests
53
64from .errors import DemandAPIError
7-
8- SCHEMAS = [
9- "project_new" ,
10- "lineitem_update" ,
11- ]
5+ from .validator import DemandAPIValidator
126
137
148class DemandAPIClient (object ):
@@ -31,27 +25,14 @@ def __init__(self, client_id=None, username=None, password=None, base_host=None)
3125 self .base_host = os .getenv ('DYNATA_DEMAND_BASE_URL' , default = 'https://api.researchnow.com' )
3226
3327 if None in [self .client_id , self .username , self .password ]:
34- raise DemandAPIError (" All authentication data is required." )
28+ raise DemandAPIError (' All authentication data is required.' )
3529
3630 self ._access_token = None
3731 self ._refresh_token = None
3832 self .auth_base_url = '{}/auth/v1' .format (self .base_host )
3933 self .base_url = '{}/sample/v1' .format (self .base_host )
4034
41- self ._load_schemas ()
42-
43- def _load_schemas (self ):
44- # Load the compiled schemas for use in validation.
45- self ._schemas = {}
46- for schema_type in SCHEMAS :
47- schema_file = open ('dynatademand/schemas/{}.json' .format (schema_type ), 'r' )
48- self ._schemas [schema_type ] = json .load (schema_file )
49- schema_file .close ()
50-
51- def _validate_object (self , schema_type , data ):
52- # jsonschema.validate will return none if there is no error,
53- # otherwise it will raise its' own error with details on the failure.
54- jsonschema .validate (self ._schemas [schema_type ], data )
35+ self .validator = DemandAPIValidator ()
5536
5637 def _check_authentication (self ):
5738 # This doesn't check if the access token is valid, just that it exists.
@@ -90,13 +71,23 @@ def _api_get(self, uri, query_params=None):
9071 return response .json ()
9172
9273 def authenticate (self ):
93- # Sends the authentication data to
74+ # Sends the authentication data to the access token endpoint.
9475 url = '{}/token/password' .format (self .auth_base_url )
95- auth_response = requests . post ( url , json = {
76+ payload = {
9677 'clientId' : self .client_id ,
9778 'password' : self .password ,
9879 'username' : self .username ,
99- })
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 )
10091 if auth_response .status_code > 399 :
10192 raise DemandAPIError ('Authentication failed with status {} and error: {}' .format (
10293 auth_response .status_code ,
@@ -109,12 +100,18 @@ def authenticate(self):
109100
110101 def refresh_access_token (self ):
111102 url = '{}/token/refresh' .format (self .auth_base_url )
112- refresh_response = requests . post ( url , json = {
103+ payload = {
113104 'clientId' : self .client_id ,
114105 'refreshToken' : self ._refresh_token
115- })
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 )
116113 if refresh_response .status_code != 200 :
117- raise DemandAPIError (" Refreshing Access Token failed with status {} and error: {}" .format (
114+ raise DemandAPIError (' Refreshing Access Token failed with status {} and error: {}' .format (
118115 refresh_response .status_code , refresh_response .content
119116 ))
120117 response_data = refresh_response .json ()
@@ -124,48 +121,109 @@ def refresh_access_token(self):
124121
125122 def logout (self ):
126123 url = '{}/logout' .format (self .auth_base_url )
127- logout_response = requests . post ( url , json = {
124+ payload = {
128125 'clientId' : self .client_id ,
129126 'refreshToken' : self ._refresh_token ,
130127 'accessToken' : self ._access_token
131- })
128+ }
129+ self .validator .validate_request (
130+ 'logout' ,
131+ request_body = payload
132+ )
133+
134+ logout_response = requests .post (url , json = payload )
132135 if logout_response .status_code != 204 :
133- raise DemandAPIError (" Log out failed with status {} and error: {}" .format (
136+ raise DemandAPIError (' Log out failed with status {} and error: {}' .format (
134137 logout_response .status_code , logout_response .content
135138 ))
136139 return logout_response .json ()
137140
138- def get_attributes (self , country_code , language_code ):
139- 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 )
140151
141- def get_countries (self ):
142- 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 )
143158
144159 def get_event (self , event_id ):
160+ self .validator .validate_request (
161+ 'get_event' ,
162+ path_data = {'eventId' : '{}' .format (event_id )},
163+ )
145164 return self ._api_get ('/events/{}' .format (event_id ))
146165
147- def get_events (self ):
148- 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 )
149172
150173 def create_project (self , project_data ):
151- # Creates a new project. Uses the "new project" schema.
152- 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+ '''
153181 response_data = self ._api_post ('/projects' , project_data )
154182 if response_data .get ('status' ).get ('message' ) != 'success' :
155183 raise DemandAPIError (
156- " Could not create project. Demand API responded with: {}" .format (
184+ ' Could not create project. Demand API responded with: {}' .format (
157185 response_data
158186 )
159187 )
160188 return response_data
161189
162190 def get_project (self , project_id ):
191+ self .validator .validate_request (
192+ 'get_project' ,
193+ path_data = {'extProjectId' : '{}' .format (project_id )},
194+ )
163195 return self ._api_get ('/projects/{}' .format (project_id ))
164196
165- def get_projects (self ):
166- 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 )
203+
204+ def update_project (self , project_id , 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+ '''
213+ response_data = self ._api_post ('/projects/{}' .format (project_id ), update_data )
214+ if response_data .get ('status' ).get ('message' ) != 'success' :
215+ raise DemandAPIError (
216+ "Could not update project. Demand API responded with: {}" .format (
217+ response_data
218+ )
219+ )
220+ return response_data
167221
168222 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+ )
169227 return self ._api_get ('/projects/{}/detailedReport' .format (project_id ))
170228
171229 def pause_line_item (self , project_id , line_item_id ):
@@ -187,16 +245,32 @@ def pause_line_item(self, project_id, line_item_id):
187245 return response_data
188246
189247 def get_line_item (self , project_id , line_item_id ):
248+ self .validator .validate_request (
249+ 'get_line_item' ,
250+ path_data = {
251+ 'extProjectId' : '{}' .format (project_id ),
252+ 'extLineItemId' : '{}' .format (line_item_id )
253+ },
254+ )
190255 return self ._api_get ('/projects/{}/lineItems/{}' .format (project_id , line_item_id ))
191256
192- def update_line_item (self , project_id , lineitem_id , lineitem_data ):
257+ def update_line_item (self , project_id , line_item_id , line_item_data ):
193258 '''
194259 Updates the specified line item by setting the values of the parameters passed.
195260 Any parameters not provided will be left unchanged.
196261 '''
197- # Update an existing line item. Uses the "lineitem_update" schema.
198- self ._validate_object ("lineitem_update" , lineitem_data )
199- response_data = self ._api_post ('/projects/{}/lineItems/{}' .format (project_id , lineitem_id ), lineitem_data )
262+ '''
263+ #TODO: Waiting on a valid path and request body schema.
264+ self.validator.validate_request(
265+ 'update_line_item',
266+ path_data={
267+ 'extProjectId': '{}'.format(project_id),
268+ 'extLineItemId': '{}'.format(line_item_id),
269+ },
270+ request_body=line_item_data,
271+ )
272+ '''
273+ response_data = self ._api_post ('/projects/{}/lineItems/{}' .format (project_id , line_item_id ), line_item_data )
200274 if response_data .get ('status' ).get ('message' ) != 'success' :
201275 raise DemandAPIError (
202276 "Could not update line item. Demand API responded with: {}" .format (
@@ -205,17 +279,40 @@ def update_line_item(self, project_id, lineitem_id, lineitem_data):
205279 )
206280 return response_data
207281
208- def get_line_items (self , project_id ):
209- return self ._api_get ('/projects/{}/lineItems' .format (project_id ))
282+ def get_line_items (self , project_id , ** kwargs ):
283+ self .validator .validate_request (
284+ 'get_line_items' ,
285+ path_data = {'extProjectId' : '{}' .format (project_id )},
286+ query_params = kwargs ,
287+ )
288+ return self ._api_get ('/projects/{}/lineItems' .format (project_id ), kwargs )
210289
211290 def get_line_item_detailed_report (self , project_id , line_item_id ):
291+ self .validator .validate_request (
292+ 'get_line_item_detailed_report' ,
293+ path_data = {
294+ 'extProjectId' : '{}' .format (project_id ),
295+ 'extLineItemId' : '{}' .format (line_item_id ),
296+ },
297+ )
212298 return self ._api_get ('/projects/{}/lineItems/{}/detailedReport' .format (project_id , line_item_id ))
213299
214300 def get_feasibility (self , project_id ):
301+ self .validator .validate_request (
302+ 'get_feasibility' ,
303+ path_data = {'extProjectId' : '{}' .format (project_id )},
304+ )
215305 return self ._api_get ('/projects/{}/feasibility' .format (project_id ))
216306
217- def get_survey_topics (self ):
218- return self ._api_get ('/categories/surveyTopics' )
307+ def get_survey_topics (self , ** kwargs ):
308+ self .validator .validate_request (
309+ 'get_survey_topics' ,
310+ query_params = kwargs ,
311+ )
312+ return self ._api_get ('/categories/surveyTopics' , kwargs )
219313
220314 def get_sources (self ):
315+ self .validator .validate_request (
316+ 'get_sources' ,
317+ )
221318 return self ._api_get ('/sources' )
0 commit comments