Skip to content

Commit

Permalink
Add simple poc tests for event callbacks.
Browse files Browse the repository at this point in the history
  • Loading branch information
ivanklee86 committed Apr 5, 2023
1 parent a00975a commit dd6a99f
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 29 deletions.
6 changes: 1 addition & 5 deletions .devcontainer/post_install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@
set -ex

# Install package
sudo python -m venv .venv
source .venv/bin/activate
pip install -U -r requirements.txt
python setup.py install
./get-spec.sh
sudo su - vscode bash -c "cd /workspaces/unleash-client-python; python -m venv .venv; source .venv/bin/activate; pip install -U -r requirements.txt; python setup.py install; ./get-spec.sh;"

# Install pre-config
# pip install pre-commit
Expand Down
50 changes: 29 additions & 21 deletions UnleashClient/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class UnleashClient:
:param scheduler: Custom APScheduler object. Use this if you want to customize jobstore or executors. When unset, UnleashClient will create it's own scheduler.
:param scheduler_executor: Name of APSCheduler executor to use if using a custom scheduler.
:param multiple_instance_mode: Determines how multiple instances being instantiated is handled by the SDK, when set to InstanceAllowType.BLOCK, the client constructor will fail when more than one instance is detected, when set to InstanceAllowType.WARN, multiple instances will be allowed but log a warning, when set to InstanceAllowType.SILENTLY_ALLOW, no warning or failure will be raised when instantiating multiple instances of the client. Defaults to InstanceAllowType.WARN
:param event_callback: Function to call if impression events are enabled.
:param event_callback: Function to call if impression events are enabled. WARNING: Depending on your event library, this may have performance implications!
"""
def __init__(self,
url: str,
Expand Down Expand Up @@ -302,16 +302,20 @@ def is_enabled(self,
feature = self.features[feature_name]
feature_check = feature.is_enabled(context)

if self.unleash_event_callback and feature.impression_data:
event = UnleashEvent(
event_type=UnleashEventType.FEATURE_FLAG,
event_id=uuid.uuid1(),
context=context,
enabled=feature_check,
feature_name=feature_name
)

self.unleash_event_callback(event)
try:
if self.unleash_event_callback and feature.impression_data:
event = UnleashEvent(
event_type=UnleashEventType.FEATURE_FLAG,
event_id=uuid.uuid4(),
context=context,
enabled=feature_check,
feature_name=feature_name
)

self.unleash_event_callback(event)
except Exception as excep:
LOGGER.log(self.unleash_verbose_log_level, "Error in event callback: %s", excep)
return feature_check

return feature_check
except Exception as excep:
Expand Down Expand Up @@ -347,16 +351,20 @@ def get_variant(self,
variant_check = feature.get_variant(context)

if self.unleash_event_callback and feature.impression_data:
event = UnleashEvent(
event_type=UnleashEventType.VARIANT,
event_id=uuid.uuid1(),
context=context,
enabled=variant_check['enabled'],
feature_name=feature_name,
variant=variant_check['enabled']
)

self.unleash_event_callback(event)
try:
event = UnleashEvent(
event_type=UnleashEventType.VARIANT,
event_id=uuid.uuid4(),
context=context,
enabled=variant_check['enabled'],
feature_name=feature_name,
variant=variant_check['name']
)

self.unleash_event_callback(event)
except Exception as excep:
LOGGER.log(self.unleash_verbose_log_level, "Error in event callback: %s", excep)
return variant_check

return variant_check
except Exception as excep:
Expand Down
2 changes: 1 addition & 1 deletion UnleashClient/api/features.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def get_feature_toggles(url: str,
if resp.status_code not in [200, 304]:
log_resp_info(resp)
LOGGER.warning("Unleash Client feature fetch failed due to unexpected HTTP status code.")
raise Exception("Unleash Client feature fetch failed!") # pylint: disable=broad-exception-raised
raise Exception("Unleash Client feature fetch failed!") # pylint: disable=broad-exception-raised

etag = ''
if 'etag' in resp.headers.keys():
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,4 @@ m2r2
tox
types-requests
twine
blinker
48 changes: 48 additions & 0 deletions tests/unit_tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import responses
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.executors.pool import ThreadPoolExecutor
from blinker import signal

from UnleashClient import UnleashClient, INSTANCES
from UnleashClient.strategies import Strategy
from UnleashClient.utils import InstanceAllowType
Expand All @@ -17,6 +19,7 @@
from tests.utilities.mocks.mock_all_features import MOCK_ALL_FEATURES
from UnleashClient.constants import REGISTER_URL, FEATURES_URL, METRICS_URL
from UnleashClient.cache import FileCache
from UnleashClient.events import UnleashEvent, UnleashEventType


class EnvironmentStrategy(Strategy):
Expand Down Expand Up @@ -574,3 +577,48 @@ def test_multiple_instances_are_unique_on_api_key(caplog):
UnleashClient(URL, "some-probably-unique-app-name", custom_headers={"Authorization": "penguins"})
UnleashClient(URL, "some-probably-unique-app-name", custom_headers={"Authorization": "hamsters"})
assert not all(["Multiple instances has been disabled" in r.msg for r in caplog.records])

@responses.activate
def test_signals_feature_flag(cache):
# Set up API
responses.add(responses.POST, URL + REGISTER_URL, json={}, status=202)
responses.add(responses.GET, URL + FEATURES_URL, json=MOCK_FEATURE_RESPONSE, status=200)
responses.add(responses.POST, URL + METRICS_URL, json={}, status=202)

# Set up signals
send_data = signal('send-data')

@send_data.connect
def receive_data(sender, **kw):
print("Caught signal from %r, data %r" % (sender, kw))

if kw['data'].event_type == UnleashEventType.FEATURE_FLAG:
assert kw['data'].feature_name == 'testFlag'
assert kw['data'].enabled == True
elif kw['data'].event_type == UnleashEventType.VARIANT:
assert kw['data'].feature_name == 'testVariations'
assert kw['data'].enabled == True
assert kw['data'].variant == 'VarA'

raise Exception("Random!")

def example_callback(event: UnleashEvent):
send_data.send('anonymous', data=event)

# Set up Unleash
unleash_client = UnleashClient(
URL,
APP_NAME,
refresh_interval=REFRESH_INTERVAL,
metrics_interval=METRICS_INTERVAL,
cache=cache,
event_callback=example_callback
)

# Create Unleash client and check initial load
unleash_client.initialize_client()
time.sleep(1)

assert unleash_client.is_enabled("testFlag")
variant = unleash_client.get_variant("testVariations", context={'userId': '2'})
assert variant['name'] == 'VarA'
4 changes: 2 additions & 2 deletions tests/utilities/mocks/mock_features.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
}
],
"createdAt": "2018-10-04T01:27:28.477Z",
"impressionData": False
"impressionData": True
},
{
"name": "testFlag2",
Expand Down Expand Up @@ -113,7 +113,7 @@
}
],
"createdAt": "2019-10-25T13:22:02.035Z",
"impressionData": False
"impressionData": True
}
]
}
Expand Down

0 comments on commit dd6a99f

Please sign in to comment.