Skip to content

Commit 4c2f546

Browse files
feat(analytics): Introduce new Analytics class
1 parent 88f9b98 commit 4c2f546

File tree

5 files changed

+100
-0
lines changed

5 files changed

+100
-0
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55

66
<Contributors, please add your changes below this line>
77

8+
* Introduce AB Testing feature - PR [#408](https://github.com/algolia/algoliasearch-client-php/pull/#408)
9+
List/Create/Stop/Delete AB Tests programmatically
10+
Introduce new Analytics object, wrapper around the
11+
[Analytics API](https://www.algolia.com/doc/rest-api/analytics/) (more methods to come).
12+
813
* 2 methods about taskID initially available in the `Index` moved to the `Client`.
914
You could get some taskID from the engine without necessarily have an instance of Index,
1015
instead of instantiating an index that you won't need, you can now call wait_task and get_task_status on the client.

algoliasearch/analytics.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# -*- coding: utf-8 -*-
2+
from algoliasearch.helpers import AlgoliaException
3+
from .helpers import safe
4+
5+
6+
class Analytics:
7+
8+
def __init__(self, client, _transport):
9+
self.client = client
10+
self._transport = _transport
11+
self._transport.read_hosts = ['analytics.algolia.com']
12+
self._transport.write_hosts = ['analytics.algolia.com']
13+
14+
def get_ab_tests(self, args=None):
15+
params = {'offest': 0, 'limit': 10}
16+
if args is not None:
17+
params.update(args)
18+
19+
return self._req('/2/abtests', 'GET', params)
20+
21+
def add_ab_test(self, ab_test):
22+
return self._req('/2/abtests', 'POST', None, ab_test)
23+
24+
def get_ab_test(self, ab_test_id):
25+
if ab_test_id == '':
26+
raise AlgoliaException('ab_test_id cannot be empty')
27+
28+
return self._req('/2/abtests/%s' % safe(ab_test_id), 'GET')
29+
30+
def stop_ab_test(self, ab_test_id):
31+
if ab_test_id == '':
32+
raise AlgoliaException('ab_test_id cannot be empty')
33+
34+
return self._req('/2/abtests/%s/stop' % safe(ab_test_id), 'POST')
35+
36+
def delete_ab_test(self, ab_test_id):
37+
if ab_test_id == '':
38+
raise AlgoliaException('ab_test_id cannot be empty')
39+
40+
return self._req('/2/abtests/%s' % safe(ab_test_id), 'DELETE')
41+
42+
def wait_task(self, index_name, task_id, time_before_retry=100, request_options=None):
43+
return self.client.wait_task(index_name, task_id, time_before_retry, request_options)
44+
45+
def _req(self, path, method, params=None, data=None):
46+
return self._transport.req(False, path, method, params, data)

algoliasearch/client.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import random
2929
import sys
3030
import time
31+
import copy
3132
from platform import python_version
3233

3334
try:
@@ -37,6 +38,7 @@
3738

3839
from .version import VERSION
3940
from .index import Index
41+
from .analytics import Analytics
4042

4143
from .transport import Transport
4244
from .helpers import deprecated
@@ -377,6 +379,9 @@ def init_index(self, index_name):
377379
"""
378380
return Index(self, index_name)
379381

382+
def init_analytics(self):
383+
return Analytics(self, copy.deepcopy(self._transport))
384+
380385
@deprecated
381386
def listUserKeys(self):
382387
return self.list_user_keys()

tests/conftest.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ def client():
1414
return create_client()
1515

1616

17+
@pytest.fixture
18+
def analytics():
19+
return create_client().init_analytics()
20+
21+
1722
@pytest.fixture
1823
def index(client):
1924
idx = create_index(client)

tests/test_analytics.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
from __future__ import print_function
2+
from datetime import datetime
3+
4+
from algoliasearch.helpers import AlgoliaException
5+
6+
7+
8+
def test_ab_test_features(analytics, double_indexes):
9+
ab_test = {
10+
'name': "Python client integration test",
11+
'variants': [
12+
{'index': double_indexes[0].index_name, 'trafficPercentage': 90},
13+
{'index': double_indexes[1].index_name, 'trafficPercentage': 10},
14+
],
15+
'endAt': datetime.utcnow().replace(day=29).strftime("%Y-%m-%dT%H:%M:%SZ"),
16+
}
17+
response = analytics.add_ab_test(ab_test)
18+
analytics.wait_task(response['index'], response['taskID'])
19+
ab_test_id = response['abTestID']
20+
21+
response = analytics.get_ab_test(ab_test_id)
22+
assert response['name'] == ab_test['name']
23+
24+
response = analytics.get_ab_tests()
25+
assert len(response['abtests']) == response['count']
26+
assert response['total'] >= response['count']
27+
28+
response = analytics.stop_ab_test(ab_test_id)
29+
analytics.wait_task(response['index'], response['taskID'])
30+
response = analytics.get_ab_test(ab_test_id)
31+
assert response['status'] == 'stopped'
32+
33+
response = analytics.delete_ab_test(ab_test_id)
34+
analytics.wait_task(response['index'], response['taskID'])
35+
try:
36+
response = analytics.get_ab_test(ab_test_id)
37+
assert False
38+
except AlgoliaException as e:
39+
assert True

0 commit comments

Comments
 (0)