Skip to content

Commit 324fe0b

Browse files
authored
Merge pull request #102 from splitio/development
Python 6.1.0 Release
2 parents 28f25ae + c551f7d commit 324fe0b

24 files changed

+1936
-181
lines changed

.github/pull_request_template.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Python SDK
2+
3+
## Tickets covered:
4+
* [SDKS-{TICKET}](https://splitio.atlassian.net/browse/SDKS-{TICKET})
5+
6+
## What did you accomplish?
7+
* Bullet 1
8+
* Bullet 2
9+
10+
## How to test new changes?
11+
*
12+
13+
## Extra Notes
14+
* Bullet 1
15+
* Bullet 2

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ var/
2323
*.egg-info/
2424
.installed.cfg
2525
*.egg
26+
venv/
2627
.vscode
2728

2829
# PyInstaller

CHANGES.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
6.1.0 (Sep 25, 2018)
2+
- Add custom impression listener feature.
3+
- Input Sanitization for track, get_treatment and split.
14
6.0.0 (Aug 29, 2018)
25
- Add support for redis sentinel
36
- UWSGI performance boost (breaking change)

Detailed-README.md

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,120 @@ The following snippet shows you how to create a basic client using the default c
3232
'SOME_TREATMENT'
3333
```
3434

35+
## Logging
36+
Split SDK uses logging module from Python.
37+
38+
### Logging sample
39+
```python
40+
import logging
41+
logging.basicConfig(level=logging.DEBUG)
42+
```
43+
44+
## Cache
45+
Split SDK depends on the popular [redis-py](https://github.com/andymccurdy/redis-py) library.
46+
47+
### Cache Adapter
48+
The redis-py library is supported as the python interface to the Redis key-value store. This library uses a connection pool to manage connections to a Redis server. For further information about how to configure the ```redis-py``` client, please take a look on [redis-py official docs](https://github.com/andymccurdy/redis-py)
49+
50+
For ```redis``` and their dependencies such as ```jsonpickle``` you can use ```pip``` running the command ```pip install splitio_client[redis,cpphash]==5.5.0```
51+
52+
#### Provided redis-py connection - sample code
53+
```python
54+
#Default imports
55+
from __future__ import print_function
56+
57+
import sys
58+
59+
from splitio import get_factory
60+
from splitio.exceptions import TimeoutException
61+
62+
# redis-py options
63+
'''The options below, will be loaded as:
64+
r = redis.StrictRedis(host='localhost', port=6379, db=0, prefix='')
65+
'''
66+
config = {
67+
'redisDb' : 0,
68+
'redisHost' : 'localhost',
69+
'redisPosrt': 6379,
70+
'redisPrefix': ''
71+
}
72+
73+
# Create the Split Client instance.
74+
try:
75+
factory = get_factory('API_KEY', config=config)
76+
split = factory.client()
77+
except TimeoutException:
78+
sys.exit()
79+
```
80+
81+
#### Provided redis-py connection - sample code for Sentinel Support
82+
```python
83+
#Default imports
84+
from __future__ import print_function
85+
86+
import sys
87+
88+
from splitio import get_factory
89+
from splitio.exceptions import TimeoutException
90+
91+
# redis-py options
92+
'''
93+
The options below, will be loaded as:
94+
sentinel = Sentinel(redisSentinels, { db: redisDb, socket_timeout: redisSocketTimeout })
95+
master = sentinel.master_for(redisMasterService)
96+
'''
97+
config = {
98+
'redisDb': 0,
99+
'redisPrefix': '',
100+
'redisSentinels': [('IP', PORT), ('IP', PORT), ('IP', PORT)],
101+
'redisMasterService': 'SERVICE_MASTER_NAME',
102+
'redisSocketTimeout': 3
103+
}
104+
105+
# Create the Split Client instance.
106+
try:
107+
factory = get_factory('API_KEY', config=config)
108+
split = factory.client()
109+
except TimeoutException:
110+
sys.exit()
111+
```
112+
113+
## Impression Listener
114+
Split SDKs send impression data back to Split servers periodically and as a result of evaluating splits. In order to additionally send this information to a location of your choice, you could define and attach an Impression Listener. For that purpose, SDK's options have a parameter called `impressionListener` where an implementation of `ImpressionListener` could be added. This implementation **must** define the `log_impression` method and it will receive data in the following schema:
115+
116+
| Name | Type | Description |
117+
| --- | --- | --- |
118+
| impression | Impression | Impression object that has the feature_name, treatment result, label, etc. |
119+
| attributes | Array | A list of attributes passed by the client. |
120+
| instance-id | String | Corresponds to the IP of the machine where the SDK is running. |
121+
| sdk-language-version | String | Indicates the version of the sdk. In this case the language will be python plus the version of it. |
122+
123+
### Implementing custom Impression Listener
124+
Below you could find an example of how implement a custom Impression Listener:
125+
```python
126+
# Import ImpressionListener interface
127+
from splitio.impressions import ImpressionListener
128+
129+
# Implementation Sample for a Custom Impression Listener
130+
class CustomImpressionListener(ImpressionListener)
131+
{
132+
def log_impression(self, data):
133+
# Custom behavior
134+
}
135+
```
136+
137+
### Attaching custom Impression Listener
138+
```python
139+
factory = get_factory(
140+
'YOUR_API_KEY',
141+
config={
142+
# ...
143+
'impressionListener': CustomImpressionListener()
144+
},
145+
# ...
146+
)
147+
split = factory.client()
148+
35149
## Additional information
36150

37151
You can get more information on how to use this package in the included documentation.

splitio/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
unicode_literals
33

44
from .factories import get_factory # noqa
5-
from .clients import Key # noqa
5+
from .key import Key # noqa
66
from .version import __version__ # noqa
77

88
__all__ = ('api', 'brokers', 'cache', 'clients', 'matchers', 'segments',

splitio/brokers.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,13 @@ class BaseBroker(object):
5757

5858
__metaclass__ = abc.ABCMeta
5959

60-
def __init__(self):
60+
def __init__(self, config=None):
6161
"""
6262
Class constructor, only sets up the logger
6363
"""
6464
self._logger = logging.getLogger(self.__class__.__name__)
6565
self._destroyed = False
66+
self._config = config
6667

6768
def fetch_feature(self, name):
6869
"""
@@ -120,7 +121,7 @@ def destroy(self):
120121
pass
121122

122123
class JSONFileBroker(BaseBroker):
123-
def __init__(self, segment_changes_file_name, split_changes_file_name):
124+
def __init__(self, config, segment_changes_file_name, split_changes_file_name):
124125
"""
125126
A Broker implementation that uses responses from the segmentChanges and
126127
splitChanges resources to provide access to splits. It is intended to be
@@ -133,7 +134,7 @@ def __init__(self, segment_changes_file_name, split_changes_file_name):
133134
splitChanges response
134135
:type split_changes_file_name: str
135136
"""
136-
super(JSONFileBroker, self).__init__()
137+
super(JSONFileBroker, self).__init__(config)
137138
self._segment_changes_file_name = segment_changes_file_name
138139
self._split_changes_file_name = split_changes_file_name
139140
self._split_fetcher = self._build_split_fetcher()
@@ -310,7 +311,6 @@ def _build_treatment_log(self):
310311
self._sdk_api,
311312
max_count=self._max_impressions_log_size,
312313
interval=self._impressions_interval,
313-
listener=self._impression_listener
314314
)
315315
return AsyncTreatmentLog(self_updating_treatment_log)
316316

@@ -388,7 +388,7 @@ class LocalhostEventStorage(object):
388388
def log(self, event):
389389
pass
390390

391-
def __init__(self, split_definition_file_name=None, auto_refresh_period=2):
391+
def __init__(self, config, split_definition_file_name=None, auto_refresh_period=2):
392392
"""
393393
A broker implementation that builds its configuration from a split
394394
definition file. By default the definition is taken from $HOME/.split
@@ -398,7 +398,7 @@ def __init__(self, split_definition_file_name=None, auto_refresh_period=2):
398398
:param auto_refresh_period: Number of seconds between split refresh calls
399399
:type auto_refresh_period: int
400400
"""
401-
super(LocalhostBroker, self).__init__()
401+
super(LocalhostBroker, self).__init__(config)
402402

403403
if split_definition_file_name is None:
404404
self._split_definition_file_name = os.path.join(
@@ -503,11 +503,11 @@ def destroy(self):
503503

504504

505505
class RedisBroker(BaseBroker):
506-
def __init__(self, redis):
506+
def __init__(self, redis, config):
507507
"""A Broker implementation that uses Redis as its backend.
508508
:param redis: A redis broker
509509
:type redis: StrctRedis"""
510-
super(RedisBroker, self).__init__()
510+
super(RedisBroker, self).__init__(config)
511511

512512
split_cache = RedisSplitCache(redis)
513513
split_fetcher = CacheBasedSplitFetcher(split_cache)
@@ -571,7 +571,7 @@ def __init__(self, uwsgi, config=None):
571571
:param config: The configuration dictionary
572572
:type config: dict
573573
"""
574-
super(UWSGIBroker, self).__init__()
574+
super(UWSGIBroker, self).__init__(config)
575575

576576
split_cache = UWSGISplitCache(uwsgi)
577577
split_fetcher = CacheBasedSplitFetcher(split_cache)
@@ -712,7 +712,7 @@ def get_self_refreshing_broker(api_key, **kwargs):
712712
)
713713

714714
if api_key == 'localhost':
715-
return LocalhostBroker(**kwargs)
715+
return LocalhostBroker(config, **kwargs)
716716

717717
return SelfRefreshingBroker(
718718
api_key,
@@ -776,11 +776,11 @@ def get_redis_broker(api_key, **kwargs):
776776
api_key, config, _, _ = _init_config(api_key, **kwargs)
777777

778778
if api_key == 'localhost':
779-
return LocalhostBroker(**kwargs)
779+
return LocalhostBroker(config, **kwargs)
780780

781781
redis = get_redis(config)
782782

783-
redis_broker = RedisBroker(redis)
783+
redis_broker = RedisBroker(redis, config)
784784

785785
return redis_broker
786786

@@ -836,7 +836,7 @@ def get_uwsgi_broker(api_key, **kwargs):
836836
api_key, config, _, _ = _init_config(api_key, **kwargs)
837837

838838
if api_key == 'localhost':
839-
return LocalhostBroker(**kwargs)
839+
return LocalhostBroker(config, **kwargs)
840840

841841
uwsgi = get_uwsgi()
842842
uwsgi_broker = UWSGIBroker(uwsgi, config)

0 commit comments

Comments
 (0)