Skip to content

Commit

Permalink
Feat/v1.1.6 (#12)
Browse files Browse the repository at this point in the history
* feat: opt flag change listener

* bug fix and compatibility with 3.12
  • Loading branch information
dsun0720 authored May 15, 2024
1 parent c97af1f commit 59711ca
Show file tree
Hide file tree
Showing 8 changed files with 25 additions and 24 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/code-quality.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
strategy:
# You can use PyPy versions in python-version.
matrix:
python-version: ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11"]
python-version: ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11", "3.12"]

steps:
- uses: actions/checkout@v3
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ Note that a flag value change listener is bound to a specific user and flag key.
The flag value change listener will be notified whenever the SDK receives any change to any feature flag's configuration,
or to a user segment that is referenced by a feature flag. To register a flag value change listener, use `add_flag_value_may_changed_listener` or `add_flag_value_changed_listener`

When you track a flag change using `add_flag_value_may_changed_listener`, this does not necessarily mean the flag's value has changed for any particular flag, only that some part of the flag configuration was changed so that it *_MAY_* return a different value than it previously returned for some user.
When you track a flag change using `add_flag_value_maybe_changed_listener`, this does not necessarily mean the flag's value has changed for any particular flag, only that some part of the flag configuration was changed so that it *_MAY_* return a different value than it previously returned for some user.

If you want to track a flag whose value *_MUST_* be changed, `add_flag_value_changed_listener` will register a listener that will be notified if and only if the flag value changes.

Expand All @@ -175,9 +175,9 @@ If the SDK is in offline mode, then it cannot know when there is a change, becau
```python
if client.initialize:
# flag value may be changed
client.flag_tracker.add_flag_value_may_changed_listener(flag_key, user, callback_fn)
client.flag_tracker.add_flag_value_maybe_changed_listener(flag_key, user, flag_value_maybe_changed_callback_fn)
# flag value must be changed
client.flag_tracker.add_flag_value_changed_listener(flag_key, user, callback_fn)
client.flag_tracker.add_flag_value_changed_listener(flag_key, user, flag_value_changed_callback_fn)

```
`flag_key`: the key of the feature flag to track
Expand Down
4 changes: 2 additions & 2 deletions fbclient/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ def track_metric(self, user: dict, event_name: str, metric_value: float = 1.0):
:param event_name: the name of the event, which may correspond to a goal in A/B tests
:param metric_value: a numeric value used by the experiment, default value is 1.0
"""
if not event_name or metric_value <= 0:
if not event_name:
log.warning('FB Python SDK: event/metric invalid')
return
try:
Expand Down Expand Up @@ -375,7 +375,7 @@ def track_metrics(self, user: dict, metrics: Mapping[str, float]):

metric_event = MetricEvent(fb_user)
for event_name, metric_value in metrics.items():
if event_name and metric_value > 0:
if event_name:
metric_event.add(Metric(event_name, metric_value))
self._event_handler(metric_event)

Expand Down
29 changes: 15 additions & 14 deletions fbclient/flag_change_notification.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def __init__(self,
flag_key: str,
user: dict,
evaluate_fn: Callable[[str, dict, Any], Any],
flag_value_changed_fn: Callable[[str, Any], None]):
flag_value_changed_fn: Callable[[str, Any, Any], None]):
self.__flag_key = flag_key
self.__user = user
self.__evaluate_fn = evaluate_fn
Expand All @@ -51,20 +51,20 @@ def on_flag_change(self, notice: FlagChangedNotice):
prev_flag_value = self.__prvious_flag_value
curr_flag_value = self.__evaluate_fn(self.__flag_key, self.__user, None)
if prev_flag_value != curr_flag_value:
self.__fn(self.__flag_key, curr_flag_value)
self.__fn(self.__flag_key, prev_flag_value, curr_flag_value)
self.__prvious_flag_value = curr_flag_value


class FlagValueMayChangedListener(FlagChangedListener):
class FlagValueMaybeChangedListener(FlagChangedListener):
def __init__(self,
flag_key: str,
user: dict,
evaluate_fn: Callable[[str, dict, Any], Any],
flag_value_changed_fn: Callable[[str, Any], None]):
flag_value_maybe_changed_fn: Callable[[str, Any], None]):
self.__flag_key = flag_key
self.__user = user
self.__evaluate_fn = evaluate_fn
self.__fn = flag_value_changed_fn
self.__fn = flag_value_maybe_changed_fn

def on_flag_change(self, notice: FlagChangedNotice):
if notice.flag_key == self.__flag_key:
Expand Down Expand Up @@ -95,7 +95,7 @@ def __init__(self,
def add_flag_value_changed_listener(self,
flag_key: str,
user: dict,
flag_value_changed_fn: Callable[[str, Any], None]) -> FlagValueChangedListener:
flag_value_changed_fn: Callable[[str, Any, Any], None]) -> FlagValueChangedListener:
"""
Registers a listener to be notified of a change in a specific feature flag's value for a specific FeatBit user.
Expand All @@ -110,7 +110,8 @@ def add_flag_value_changed_listener(self,
:param user: The user to evaluate the flag value
:param flag_value_changed_fn: The function to be called only when this flag value changes
* the first argument is the flag key
* the second argument is the latest flag value, this value must be different from the previous value
* the second argument is the previous flag value
* the third argument is the current flag value
:return: A listener object that can be used to remove it later on.
"""
Expand All @@ -128,10 +129,10 @@ def add_flag_value_changed_listener(self,
self.add_flag_changed_listener(listener)
return listener

def add_flag_value_may_changed_listener(self,
flag_key: str,
user: dict,
flag_value_changed_fn: Callable[[str, Any], None]) -> FlagValueMayChangedListener:
def add_flag_value_maybe_changed_listener(self,
flag_key: str,
user: dict,
flag_value_maybe_changed_fn: Callable[[str, Any], None]) -> FlagValueMaybeChangedListener:
"""
Registers a listener to be notified of a change in a specific feature flag's value for a specific FeatBit user.
Expand All @@ -145,7 +146,7 @@ def add_flag_value_may_changed_listener(self,
:param flag_key: The key of the feature flag to track
:param user: The user to evaluate the flag value
:param flag_value_changed_fn: The function to be called only if any changes to a specific flag
:param flag_value_maybe_changed_fn: The function to be called if any changes to a specific flag
* the first argument is the flag key
* the second argument is the latest flag value, this value may be same as the previous value
Expand All @@ -159,10 +160,10 @@ def add_flag_value_may_changed_listener(self,
# check user
FBUser.from_dict(user)
# check flag_value_changed_fn
if not isinstance(flag_value_changed_fn, Callable) or not flag_value_changed_fn:
if not isinstance(flag_value_maybe_changed_fn, Callable) or not flag_value_maybe_changed_fn:
raise ValueError('flag_value_changed_fn must be a callable function')

listener = FlagValueMayChangedListener(flag_key, user, self.__evaluate_fn, flag_value_changed_fn)
listener = FlagValueMaybeChangedListener(flag_key, user, self.__evaluate_fn, flag_value_maybe_changed_fn)
self.add_flag_changed_listener(listener)
return listener

Expand Down
2 changes: 1 addition & 1 deletion fbclient/utils/rwlock.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def release_read_lock(self):
with self._read_ready:
self._readers = self._readers - 1 if self._readers > 0 else 0
if self._readers == 0:
self._read_ready.notifyAll()
self._read_ready.notify_all()

def write_lock(self):
""" Acquire a write lock. Blocks until there are no
Expand Down
1 change: 0 additions & 1 deletion fbclient/version.py

This file was deleted.

2 changes: 1 addition & 1 deletion release/package.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"version":"1.1.5"
"version":"1.1.6"
}
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,11 @@ def parse_requirements(filename):
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12',
],
extras_require={
"dev": dev_reqs
},
tests_require=dev_reqs,
python_requires='>=3.6, <=3.11'
python_requires='>=3.6, <=3.12'
)

0 comments on commit 59711ca

Please sign in to comment.