Skip to content
This repository was archived by the owner on Sep 28, 2023. It is now read-only.

Commit 422faac

Browse files
author
Andy Harris
committed
add project and experiment support
1 parent 106f663 commit 422faac

3 files changed

Lines changed: 158 additions & 24 deletions

File tree

.gitignore

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,9 @@
22
__pycache__/
33
*.py[cod]
44

5-
# C extensions
6-
*.so
7-
85
# Distribution / packaging
96
.Python
7+
.idea/
108
env/
119
build/
1210
develop-eggs/
@@ -31,24 +29,3 @@ var/
3129
# Installer logs
3230
pip-log.txt
3331
pip-delete-this-directory.txt
34-
35-
# Unit test / coverage reports
36-
htmlcov/
37-
.tox/
38-
.coverage
39-
.cache
40-
nosetests.xml
41-
coverage.xml
42-
43-
# Translations
44-
*.mo
45-
*.pot
46-
47-
# Django stuff:
48-
*.log
49-
50-
# Sphinx documentation
51-
docs/_build/
52-
53-
# PyBuilder
54-
target/

README.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,48 @@ Optimizely Python Client
22
=================
33

44
Optimizely's Python client library is an interface to its [REST API](http://developers.optimizely.com/rest/).
5+
6+
7+
Usage
8+
-----
9+
10+
Set your API key and you're ready to go!
11+
```python
12+
>>> import optimizely
13+
>>> optimizely.api_key = 'abcdefghijklmnopqrstuvwxyz:123456'
14+
>>> optimizely.Project.all()
15+
[
16+
{
17+
"code_revision": 8,
18+
"installation_verified": true,
19+
"project_name": "My new project",
20+
"ip_filter": null,
21+
"ip_anonymization": false,
22+
"created": "2014-04-14T23:09:03.429630Z",
23+
"library": "jquery-1.6.4-trim",
24+
"last_modified": "2014-05-21T23:03:06.968520Z",
25+
"project_status": "Active",
26+
"include_jquery": true,
27+
"js_file_size": 46176,
28+
"id": 819000157,
29+
"code_last_modified": "2014-05-21T23:03:04.918880Z",
30+
"account_id": 555650815
31+
},
32+
{
33+
"code_revision": 12,
34+
"installation_verified": null,
35+
"project_name": "My even newer project name",
36+
"ip_filter": "1.2.3.4",
37+
"ip_anonymization": false,
38+
"created": "2014-04-16T21:33:34.408430Z",
39+
"library": "jquery-1.6.4-trim",
40+
"last_modified": "2014-06-10T22:12:21.707170Z",
41+
"project_status": "Active",
42+
"include_jquery": false,
43+
"js_file_size": 23693,
44+
"id": 859720118,
45+
"code_last_modified": "2014-06-10T22:12:20.615820Z",
46+
"account_id": 555650815
47+
}
48+
]
49+
```

optimizely/__init__.py

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import json
2+
import requests
3+
4+
api_key = ''
5+
api_base = 'https://www.optimizelyapis.com/experiment/v1/'
6+
7+
8+
class APIResource(object):
9+
endpoint = ''
10+
11+
def __init__(self):
12+
raise NotImplementedError(self.__class__.__name__ +
13+
' contains only class methods and should not be instantiated.')
14+
15+
@staticmethod
16+
def _parse_response(r):
17+
if r.status_code in [200, 201, 202, 204]:
18+
return r.json()
19+
elif r.status_code == 400:
20+
raise BadRequestError(r.text)
21+
elif r.status_code == 401:
22+
raise UnauthorizedError(r.text)
23+
elif r.status_code == 403:
24+
raise ForbiddenError(r.text)
25+
elif r.status_code == 404:
26+
raise NotFoundError(r.text)
27+
elif r.status_code == 429:
28+
raise TooManyRequestsError(r.text)
29+
elif r.status_code == 503:
30+
raise ServiceUnavailableError(r.text)
31+
else:
32+
raise OptimizelyError(r.text)
33+
34+
@classmethod
35+
def all(cls):
36+
return cls._parse_response(requests.get(api_base + cls.endpoint, headers={'Token': api_key}))
37+
38+
@classmethod
39+
def get(cls, pid):
40+
return cls._parse_response(requests.get(api_base + cls.endpoint + str(pid), headers={'Token': api_key}))
41+
42+
@classmethod
43+
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'}))
46+
47+
@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'}))
51+
52+
@classmethod
53+
def delete(cls, pid):
54+
return cls._parse_response(requests.delete(api_base + cls.endpoint + str(pid), headers={'Token': api_key}))
55+
56+
57+
class Project(APIResource):
58+
endpoint = 'projects/'
59+
60+
61+
class Experiment(APIResource):
62+
endpoint = 'experiments/'
63+
64+
@classmethod
65+
def all(cls):
66+
raise NotImplementedError('There is no method to get all experiments. Try using get_from_project() instead.')
67+
68+
@classmethod
69+
def get_from_project(cls, pid):
70+
return cls._parse_response(requests.get(api_base + Project.endpoint + str(pid) + '/' + cls.endpoint,
71+
headers={'Token': api_key}))
72+
73+
@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}))
77+
78+
79+
class OptimizelyError(Exception):
80+
""" General exception for all Optimizely Experiments API related issues."""
81+
pass
82+
83+
84+
class BadRequestError(OptimizelyError):
85+
""" Exception for when request was not sent in valid JSON."""
86+
pass
87+
88+
89+
class UnauthorizedError(OptimizelyError):
90+
""" Exception for when API token is missing or included in the body rather than the header."""
91+
pass
92+
93+
94+
class ForbiddenError(OptimizelyError):
95+
""" Exception for when API token is provided but it is invalid or revoked."""
96+
pass
97+
98+
99+
class NotFoundError(OptimizelyError):
100+
""" Exception for when the id used in request is inaccurate or token user doesn't have permission to
101+
view/edit it."""
102+
pass
103+
104+
105+
class TooManyRequestsError(OptimizelyError):
106+
""" Exception for when a rate limit for the API is hit."""
107+
pass
108+
109+
110+
class ServiceUnavailableError(OptimizelyError):
111+
""" Exception for when the API is overloaded or down for maintenance."""
112+
pass

0 commit comments

Comments
 (0)