Skip to content

Commit 81debce

Browse files
authored
fix: Remove defaults for feature flag calls (#72)
1 parent dac06ba commit 81debce

File tree

5 files changed

+38
-36
lines changed

5 files changed

+38
-36
lines changed

CHANGELOG.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## 2.1.0 - 2022-08-11
2+
3+
Changes:
4+
5+
1. Feature flag defaults have been removed
6+
2. Setup logging only when debug mode is enabled.
17
## 2.0.1 - 2022-08-04
28

39
- Make poll_interval configurable
@@ -9,7 +15,8 @@
915
Breaking changes:
1016

1117
1. The minimum version requirement for PostHog servers is now 1.38. If you're using PostHog Cloud, you satisfy this requirement automatically.
12-
2. Feature flag defaults apply only when there's an error fetching feature flag results. Earlier, if the default was set to `True`, even if a flag resolved to `False`, the default would override this.
18+
2. Feature flag defaults apply only when there's an error fetching feature flag results. Earlier, if the default was set to `True`, even if a flag resolved to `False`, the default would override this.
19+
**Note: These are removed in 2.0.2**
1320
3. Feature flag remote evaluation doesn't require a personal API key.
1421

1522
New Changes:

posthog/__init__.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,6 @@ def alias(
235235
def feature_enabled(
236236
key, # type: str,
237237
distinct_id, # type: str,
238-
default=False, # type: bool
239238
groups={}, # type: dict
240239
person_properties={}, # type: dict
241240
group_properties={}, # type: dict
@@ -260,7 +259,6 @@ def feature_enabled(
260259
"feature_enabled",
261260
key=key,
262261
distinct_id=distinct_id,
263-
default=default,
264262
groups=groups,
265263
person_properties=person_properties,
266264
group_properties=group_properties,
@@ -272,7 +270,6 @@ def feature_enabled(
272270
def get_feature_flag(
273271
key, # type: str,
274272
distinct_id, # type: str,
275-
default=False, # type: bool
276273
groups={}, # type: dict
277274
person_properties={}, # type: dict
278275
group_properties={}, # type: dict
@@ -305,7 +302,6 @@ def get_feature_flag(
305302
"get_feature_flag",
306303
key=key,
307304
distinct_id=distinct_id,
308-
default=default,
309305
groups=groups,
310306
person_properties=person_properties,
311307
group_properties=group_properties,

posthog/client.py

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,6 @@
2323
ID_TYPES = (numbers.Number, string_types, UUID)
2424
MAX_DICT_SIZE = 50_000
2525

26-
# Ensures that debug level messages are logged when debug mode is on.
27-
# Otherwise, defaults to WARNING level. See https://docs.python.org/3/howto/logging.html#what-happens-if-no-configuration-is-provided
28-
logging.basicConfig()
29-
3026

3127
class Client(object):
3228
"""Create a new PostHog client."""
@@ -76,6 +72,9 @@ def __init__(
7672
# personal_api_key: This should be a generated Personal API Key, private
7773
self.personal_api_key = personal_api_key
7874
if debug:
75+
# Ensures that debug level messages are logged when debug mode is on.
76+
# Otherwise, defaults to WARNING level. See https://docs.python.org/3/howto/logging.html#what-happens-if-no-configuration-is-provided
77+
logging.basicConfig()
7978
self.log.setLevel(logging.DEBUG)
8079
else:
8180
self.log.setLevel(logging.WARNING)
@@ -432,32 +431,31 @@ def feature_enabled(
432431
self,
433432
key,
434433
distinct_id,
435-
default=False,
436434
*,
437435
groups={},
438436
person_properties={},
439437
group_properties={},
440438
only_evaluate_locally=False,
441439
send_feature_flag_events=True,
442440
):
443-
return bool(
444-
self.get_feature_flag(
445-
key,
446-
distinct_id,
447-
default,
448-
groups=groups,
449-
person_properties=person_properties,
450-
group_properties=group_properties,
451-
only_evaluate_locally=only_evaluate_locally,
452-
send_feature_flag_events=send_feature_flag_events,
453-
)
441+
response = self.get_feature_flag(
442+
key,
443+
distinct_id,
444+
groups=groups,
445+
person_properties=person_properties,
446+
group_properties=group_properties,
447+
only_evaluate_locally=only_evaluate_locally,
448+
send_feature_flag_events=send_feature_flag_events,
454449
)
455450

451+
if response is None:
452+
return None
453+
return bool(response)
454+
456455
def get_feature_flag(
457456
self,
458457
key,
459458
distinct_id,
460-
default=False,
461459
*,
462460
groups={},
463461
person_properties={},
@@ -500,10 +498,11 @@ def get_feature_flag(
500498
distinct_id, groups=groups, person_properties=person_properties, group_properties=group_properties
501499
)
502500
response = feature_flags.get(key)
501+
if response is None:
502+
response = False
503503
self.log.debug(f"Successfully computed flag remotely: #{key} -> #{response}")
504504
except Exception as e:
505505
self.log.exception(f"[FEATURE FLAGS] Unable to get flag remotely: {e}")
506-
response = default
507506

508507
feature_flag_reported_key = f"{key}_{str(response)}"
509508
if (

posthog/test/test_feature_flags.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,7 @@ def test_feature_flags_dont_fallback_to_decide_when_only_local_evaluation_is_tru
385385

386386
feature_flag_match = client.feature_enabled("beta-feature", "some-distinct-id", only_evaluate_locally=True)
387387

388-
self.assertEqual(feature_flag_match, False)
388+
self.assertEqual(feature_flag_match, None)
389389
self.assertEqual(patch_decide.call_count, 0)
390390

391391
# beta-feature2 should fallback to decide because region property not given with call
@@ -394,13 +394,13 @@ def test_feature_flags_dont_fallback_to_decide_when_only_local_evaluation_is_tru
394394
self.assertEqual(feature_flag_match, None)
395395

396396
feature_flag_match = client.feature_enabled("beta-feature2", "some-distinct-id", only_evaluate_locally=True)
397-
self.assertEqual(feature_flag_match, False)
397+
self.assertEqual(feature_flag_match, None)
398398

399399
self.assertEqual(patch_decide.call_count, 0)
400400

401401
@mock.patch("posthog.client.decide")
402402
@mock.patch("posthog.client.get")
403-
def test_feature_flag_defaults_dont_hinder_regular_evaluation(self, patch_get, patch_decide):
403+
def test_feature_flag_never_returns_undefined_during_regular_evaluation(self, patch_get, patch_decide):
404404
patch_decide.return_value = {"featureFlags": {}}
405405
client = Client(FAKE_TEST_API_KEY, personal_api_key=FAKE_TEST_API_KEY)
406406
client.feature_flags = [
@@ -422,28 +422,28 @@ def test_feature_flag_defaults_dont_hinder_regular_evaluation(self, patch_get, p
422422
]
423423

424424
# beta-feature resolves to False, so no matter the default, stays False
425-
self.assertFalse(client.get_feature_flag("beta-feature", "some-distinct-id", default=True))
426-
self.assertFalse(client.get_feature_flag("beta-feature", "some-distinct-id", default=False))
425+
self.assertFalse(client.get_feature_flag("beta-feature", "some-distinct-id"))
426+
self.assertFalse(client.feature_enabled("beta-feature", "some-distinct-id"))
427427

428428
# beta-feature2 falls back to decide, and whatever decide returns is the value
429-
self.assertFalse(client.get_feature_flag("beta-feature2", "some-distinct-id", default=False))
429+
self.assertFalse(client.get_feature_flag("beta-feature2", "some-distinct-id"))
430430
self.assertEqual(patch_decide.call_count, 1)
431431

432-
self.assertFalse(client.get_feature_flag("beta-feature2", "some-distinct-id", default=True))
432+
self.assertFalse(client.feature_enabled("beta-feature2", "some-distinct-id"))
433433
self.assertEqual(patch_decide.call_count, 2)
434434

435435
@mock.patch("posthog.client.decide")
436436
@mock.patch("posthog.client.get")
437-
def test_feature_flag_defaults_come_into_play_only_when_decide_errors_out(self, patch_get, patch_decide):
437+
def test_feature_flag_return_none_when_decide_errors_out(self, patch_get, patch_decide):
438438
patch_decide.side_effect = APIError(400, "Decide error")
439439
client = Client(FAKE_TEST_API_KEY, personal_api_key=FAKE_TEST_API_KEY)
440440
client.feature_flags = []
441441

442-
# beta-feature2 falls back to decide, which on error falls back to default
443-
self.assertFalse(client.get_feature_flag("beta-feature2", "some-distinct-id", default=False))
442+
# beta-feature2 falls back to decide, which on error returns None
443+
self.assertIsNone(client.get_feature_flag("beta-feature2", "some-distinct-id"))
444444
self.assertEqual(patch_decide.call_count, 1)
445445

446-
self.assertTrue(client.get_feature_flag("beta-feature2", "some-distinct-id", default=True))
446+
self.assertIsNone(client.feature_enabled("beta-feature2", "some-distinct-id"))
447447
self.assertEqual(patch_decide.call_count, 2)
448448

449449
@mock.patch("posthog.client.decide")
@@ -943,7 +943,7 @@ def test_feature_enabled_doesnt_exist(self, patch_decide, patch_poll):
943943
self.assertFalse(client.feature_enabled("doesnt-exist", "distinct_id"))
944944

945945
patch_decide.side_effect = APIError(401, "decide error")
946-
self.assertTrue(client.feature_enabled("doesnt-exist", "distinct_id", True))
946+
self.assertIsNone(client.feature_enabled("doesnt-exist", "distinct_id"))
947947

948948
@mock.patch("posthog.client.Poller")
949949
@mock.patch("posthog.client.decide")

posthog/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
VERSION = "2.0.1"
1+
VERSION = "2.1.0"
22

33
if __name__ == "__main__":
44
print(VERSION, end="")

0 commit comments

Comments
 (0)