55api_base = 'https://www.optimizelyapis.com/experiment/v1/'
66
77
8- class APIResource (object ):
8+ class APIResource (dict ):
99 endpoint = ''
1010
11- def __init__ (self ):
12- raise NotImplementedError (self .__class__ .__name__ +
13- ' contains only class methods and should not be instantiated.' )
11+ def __init__ (self , * arg , ** kw ):
12+ super (APIResource , self ).__init__ (* arg , ** kw )
1413
15- @staticmethod
16- def _parse_response (r ):
17- if r .status_code in [200 , 201 , 202 , 204 ]:
18- return r .json ()
14+ @classmethod
15+ def from_json (cls , r ):
16+ if r .status_code in [200 , 201 , 202 ]:
17+ if type (r .json ()) == list :
18+ return [cls (resource ) for resource in r .json ()]
19+ else :
20+ return cls (r .json ())
21+ elif r .status_code == 204 :
22+ return
1923 elif r .status_code == 400 :
2024 raise BadRequestError (r .text )
2125 elif r .status_code == 401 :
@@ -32,48 +36,143 @@ def _parse_response(r):
3236 raise OptimizelyError (r .text )
3337
3438 @classmethod
35- def all (cls ):
36- return cls ._parse_response (requests .get (api_base + cls .endpoint , headers = {'Token' : api_key }))
39+ def list (cls ):
40+ return cls .from_json (requests .get (api_base + cls .endpoint , headers = {'Token' : api_key }))
3741
3842 @classmethod
39- def get (cls , pid ):
40- return cls ._parse_response (requests .get (api_base + cls .endpoint + str (pid ), headers = {'Token' : api_key }))
43+ def read (cls , pid ):
44+ return cls .from_json (requests .get (api_base + cls .endpoint + str (pid ), headers = {'Token' : api_key }))
4145
4246 @classmethod
4347 def create (cls , data ):
44- return cls ._parse_response (requests .post (api_base + cls .endpoint , data = json .dumps (data ),
45- headers = {'Token' : api_key , 'Content-Type' : 'application/json' }))
48+ return cls .from_json (requests .post (api_base + cls .endpoint , data = json .dumps (data ),
49+ headers = {'Token' : api_key , 'Content-Type' : 'application/json' }))
4650
4751 @classmethod
48- def update (cls , pid , data ):
49- return cls ._parse_response (requests .put (api_base + cls .endpoint + str (pid ), data = json .dumps (data ),
50- headers = {'Token' : api_key , 'Content-Type' : 'application/json' }))
52+ def put (cls , rid , data ):
53+ return cls .from_json (requests .put (api_base + cls .endpoint + str (rid ), data = json .dumps (data ),
54+ headers = {'Token' : api_key , 'Content-Type' : 'application/json' }))
5155
5256 @classmethod
5357 def delete (cls , pid ):
54- return cls ._parse_response (requests .delete (api_base + cls .endpoint + str (pid ), headers = {'Token' : api_key }))
58+ return cls .from_json (requests .delete (api_base + cls .endpoint + str (pid ), headers = {'Token' : api_key }))
5559
5660
5761class Project (APIResource ):
5862 endpoint = 'projects/'
5963
64+ @classmethod
65+ def delete (cls , pid ):
66+ raise NotImplementedError ('Projects may not be deleted through the API.' )
67+
68+ def experiments (self ):
69+ if not self .get ('id' ):
70+ raise InvalidIDError ('Project is missing its ID.' )
71+ return Experiment .from_json (requests .get (api_base + self .endpoint + str (self ['id' ]) + '/experiments' ,
72+ headers = {'Token' : api_key }))
73+
74+ def audiences (self ):
75+ if not self .get ('id' ):
76+ raise InvalidIDError ('Project is missing its ID.' )
77+ return Audience .from_json (requests .get (api_base + self .endpoint + str (self ['id' ]) + '/audiences' ,
78+ headers = {'Token' : api_key }))
79+
6080
6181class Experiment (APIResource ):
6282 endpoint = 'experiments/'
6383
6484 @classmethod
65- def all (cls ):
66- raise NotImplementedError ('There is no method to get all experiments. Try using get_from_project() instead.' )
85+ def list (cls ):
86+ raise NotImplementedError ('There is no method to list all experiments. '
87+ 'Try using Project.experiments() instead.' )
6788
6889 @classmethod
69- def get_from_project (cls , pid ):
70- return cls ._parse_response (requests .get (api_base + Project .endpoint + str (pid ) + '/' + cls .endpoint ,
90+ def create (cls , data ):
91+ return cls .from_json (requests .post (api_base + 'projects/' + str (data ['project_id' ]) + '/' + cls .endpoint ,
92+ data = json .dumps (data ),
93+ headers = {'Token' : api_key , 'Content-Type' : 'application/json' }))
94+
95+ def results (self ):
96+ return Result .from_json (requests .get (api_base + self .endpoint + str (self ['id' ]) + '/results' ,
97+ headers = {'Token' : api_key }))
98+
99+ def variations (self ):
100+ return Variation .from_json (requests .get (api_base + self .endpoint + str (self ['id' ]) + '/variations' ,
71101 headers = {'Token' : api_key }))
72102
103+ def add_goal (self , gid ):
104+ goal = Goal .read (gid )
105+ return Goal .from_json (Goal .put (goal .get ('id' ),
106+ {'experiment_ids' : goal .get ('experiment_ids' ).append (self ['id' ])}))
107+
108+ def remove_goal (self , gid ):
109+ goal = Goal .read (gid )
110+ experiment_ids = list (set (goal .get ('experiment_ids' )).remove (self ['id' ]))
111+ return Goal .from_json (Goal .put (goal .get ('id' ), {'experiment_ids' : experiment_ids }))
112+
113+
114+ class Result (APIResource ):
73115 @classmethod
74- def get_results (cls , eid ):
75- return cls ._parse_response (requests .get (api_base + cls .endpoint + str (eid ) + '/results' ,
76- headers = {'Token' : api_key }))
116+ def list (cls ):
117+ raise NotImplementedError ('There is no method to list all results. Try using Experiment.results() instead.' )
118+
119+ @classmethod
120+ def read (cls , pid ):
121+ raise NotImplementedError ('There is no method to get a single result.' )
122+
123+ @classmethod
124+ def create (cls , data ):
125+ return NotImplementedError ('There is no method to create a result.' )
126+
127+ @classmethod
128+ def put (cls , pid , data ):
129+ return NotImplementedError ('There is no method to update a result.' )
130+
131+ @classmethod
132+ def delete (cls , pid ):
133+ return NotImplementedError ('There is no method to delete a result.' )
134+
135+
136+ class Variation (APIResource ):
137+ endpoint = 'variations/'
138+
139+ @classmethod
140+ def list (cls ):
141+ raise NotImplementedError ('There is no method to list all results. Try using Experiment.variations() instead.' )
142+
143+ @classmethod
144+ def create (cls , data ):
145+ return cls .from_json (requests .post (api_base + 'experiments/' + str (data ['experiment_id' ]) + '/' + cls .endpoint ,
146+ data = json .dumps (data ),
147+ headers = {'Token' : api_key , 'Content-Type' : 'application/json' }))
148+
149+
150+ class Goal (APIResource ):
151+ endpoint = 'goals/'
152+
153+ @classmethod
154+ def list (cls ):
155+ raise NotImplementedError ('There is no method to list all goals.' )
156+
157+ @classmethod
158+ def create (cls , data ):
159+ return cls .from_json (requests .post (api_base + 'projects/' + str (data ['project_id' ]) + '/' + cls .endpoint ,
160+ data = json .dumps (data ),
161+ headers = {'Token' : api_key , 'Content-Type' : 'application/json' }))
162+
163+
164+ class Audience (APIResource ):
165+ endpoint = 'audiences/'
166+
167+ @classmethod
168+ def list (cls ):
169+ raise NotImplementedError ('There is no method to list all results. Try using Experiment.variations() instead.' )
170+
171+ @classmethod
172+ def create (cls , data ):
173+ return cls .from_json (requests .post (api_base + 'projects/' + str (data ['project_id' ]) + '/' + cls .endpoint ,
174+ data = json .dumps (data ),
175+ headers = {'Token' : api_key , 'Content-Type' : 'application/json' }))
77176
78177
79178class OptimizelyError (Exception ):
@@ -109,4 +208,9 @@ class TooManyRequestsError(OptimizelyError):
109208
110209class ServiceUnavailableError (OptimizelyError ):
111210 """ Exception for when the API is overloaded or down for maintenance."""
211+ pass
212+
213+
214+ class InvalidIDError (OptimizelyError ):
215+ """ Exception for when object is missing its ID."""
112216 pass
0 commit comments