From 59711ca6c6eacb663d5f772315a6aed3618c7f77 Mon Sep 17 00:00:00 2001 From: s2002a <38680131+dsun0720@users.noreply.github.com> Date: Wed, 15 May 2024 19:25:08 +0200 Subject: [PATCH] Feat/v1.1.6 (#12) * feat: opt flag change listener * bug fix and compatibility with 3.12 --- .github/workflows/code-quality.yaml | 2 +- README.md | 6 +++--- fbclient/client.py | 4 ++-- fbclient/flag_change_notification.py | 29 ++++++++++++++-------------- fbclient/utils/rwlock.py | 2 +- fbclient/version.py | 1 - release/package.json | 2 +- setup.py | 3 ++- 8 files changed, 25 insertions(+), 24 deletions(-) delete mode 100644 fbclient/version.py diff --git a/.github/workflows/code-quality.yaml b/.github/workflows/code-quality.yaml index 9894037..4bbc780 100644 --- a/.github/workflows/code-quality.yaml +++ b/.github/workflows/code-quality.yaml @@ -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 diff --git a/README.md b/README.md index fbdefad..5e79b3f 100644 --- a/README.md +++ b/README.md @@ -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. @@ -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 diff --git a/fbclient/client.py b/fbclient/client.py index 257b4bf..f6bd0fa 100644 --- a/fbclient/client.py +++ b/fbclient/client.py @@ -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: @@ -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) diff --git a/fbclient/flag_change_notification.py b/fbclient/flag_change_notification.py index 01bd658..731cb0c 100644 --- a/fbclient/flag_change_notification.py +++ b/fbclient/flag_change_notification.py @@ -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 @@ -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: @@ -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. @@ -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. """ @@ -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. @@ -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 @@ -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 diff --git a/fbclient/utils/rwlock.py b/fbclient/utils/rwlock.py index 9b25973..49876f1 100644 --- a/fbclient/utils/rwlock.py +++ b/fbclient/utils/rwlock.py @@ -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 diff --git a/fbclient/version.py b/fbclient/version.py deleted file mode 100644 index 4981593..0000000 --- a/fbclient/version.py +++ /dev/null @@ -1 +0,0 @@ -VERSION = "1.1.5" diff --git a/release/package.json b/release/package.json index 8716839..3ef3734 100644 --- a/release/package.json +++ b/release/package.json @@ -1,3 +1,3 @@ { - "version":"1.1.5" + "version":"1.1.6" } \ No newline at end of file diff --git a/setup.py b/setup.py index 9647cac..b31d1c0 100644 --- a/setup.py +++ b/setup.py @@ -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' )