Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 34 additions & 3 deletions splitio/client/config.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
"""Default settings for the Split.IO SDK Python client."""
import os.path
import logging
import re

from splitio.engine.impressions import ImpressionsMode


_LOGGER = logging.getLogger(__name__)
DEFAULT_DATA_SAMPLING = 1

_FLAG_SETS_REGEX = '^[a-z0-9][_a-z0-9]{0,49}$'

DEFAULT_CONFIG = {
'operationMode': 'standalone',
Expand Down Expand Up @@ -58,10 +59,10 @@
'dataSampling': DEFAULT_DATA_SAMPLING,
'storageWrapper': None,
'storagePrefix': None,
'storageType': None
'storageType': None,
'FlagSets': None
}


def _parse_operation_mode(sdk_key, config):
"""
Process incoming config to determine operation mode and storage type
Expand Down Expand Up @@ -119,6 +120,34 @@ def _sanitize_impressions_mode(storage_type, mode, refresh_rate=None):
return mode, refresh_rate


def _sanitize_flag_sets(flag_sets):
"""
Check supplied flag sets list

:param flag_set: list of flag sets
:type flag_set: list[str]

:returns: Sanitized and sorted flag sets
:rtype: list[str]
"""
sanitized_flag_sets = set()
for flag_set in flag_sets:
if flag_set != flag_set.strip():
_LOGGER.warning("SDK config: Flag Set name %s has extra whitespace, trimming" % (flag_set))
flag_set = flag_set.strip()

if flag_set != flag_set.lower():
_LOGGER.warning("SDK config: Flag Set name %s should be all lowercase - converting string to lowercase" % (flag_set))
flag_set = flag_set.lower()

if re.search(_FLAG_SETS_REGEX, flag_set) is None or re.search(_FLAG_SETS_REGEX, flag_set).group() != flag_set:
_LOGGER.warning("SDK config: you passed %s, Flag Set must adhere to the regular expressions %s. This means a Flag Set must start with a letter, be in lowercase, alphanumeric and have a max length of 50 characteres. %s was discarded.", flag_set, _FLAG_SETS_REGEX, flag_set)
continue

sanitized_flag_sets.add(flag_set.strip())

return sorted(list(sanitized_flag_sets))

def sanitize(sdk_key, config):
"""
Look for inconsistencies or ill-formed configs and tune it accordingly.
Expand All @@ -143,4 +172,6 @@ def sanitize(sdk_key, config):
_LOGGER.warning('metricRefreshRate parameter minimum value is 60 seconds, defaulting to 3600 seconds.')
processed['metricsRefreshRate'] = 3600

processed['FlagSets'] = _sanitize_flag_sets(processed['FlagSets']) if processed['FlagSets'] is not None else None

return processed
21 changes: 21 additions & 0 deletions tests/client/test_config.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Configuration unit tests."""
# pylint: disable=protected-access,no-self-use,line-too-long
import pytest

from splitio.client import config
from splitio.engine.impressions.impressions import ImpressionsMode
Expand Down Expand Up @@ -68,3 +69,23 @@ def test_sanitize(self):
processed = config.sanitize('some', configs)

assert processed['redisLocalCacheEnabled'] # check default is True

def test_sanitize_flag_sets(self):
"""Test sanitization for flag sets."""
flag_sets = config._sanitize_flag_sets([' set1', 'set2 ', 'set3'])
assert flag_sets == ['set1', 'set2', 'set3']

flag_sets = config._sanitize_flag_sets(['1set', '_set2'])
assert flag_sets == ['1set']

flag_sets = config._sanitize_flag_sets(['Set1', 'SET2'])
assert flag_sets == ['set1', 'set2']

flag_sets = config._sanitize_flag_sets(['se\t1', 's/et2', 's*et3', 's!et4', 'se@t5', 'se#t5', 'se$t5', 'se^t5', 'se%t5', 'se&t5'])
assert flag_sets == []

flag_sets = config._sanitize_flag_sets(['set4', 'set1', 'set3', 'set1'])
assert flag_sets == ['set1', 'set3', 'set4']

flag_sets = config._sanitize_flag_sets(['w' * 50, 's' * 51])
assert flag_sets == ['w' * 50]