Skip to content

Commit 8554b51

Browse files
authored
fix(flags): Update relative date op names (#113)
1 parent d0d962a commit 8554b51

File tree

8 files changed

+63
-41
lines changed

8 files changed

+63
-41
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 3.3.3 - 2024-01-26
2+
3+
1. Remove new relative date operators, combine into regular date operators
4+
15
## 3.3.2 - 2024-01-19
26

37
1. Return success/failure with all capture calls from module functions

posthog/client.py

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,16 @@ def load_feature_flags(self):
464464
self.poller = Poller(interval=timedelta(seconds=self.poll_interval), execute=self._load_feature_flags)
465465
self.poller.start()
466466

467-
def _compute_flag_locally(self, feature_flag, distinct_id, *, groups={}, person_properties={}, group_properties={}):
467+
def _compute_flag_locally(
468+
self,
469+
feature_flag,
470+
distinct_id,
471+
*,
472+
groups={},
473+
person_properties={},
474+
group_properties={},
475+
warn_on_unknown_groups=True,
476+
):
468477
if feature_flag.get("ensure_experience_continuity", False):
469478
raise InconclusiveMatchError("Flag has experience continuity enabled")
470479

@@ -486,9 +495,14 @@ def _compute_flag_locally(self, feature_flag, distinct_id, *, groups={}, person_
486495
if group_name not in groups:
487496
# Group flags are never enabled in `groups` aren't passed in
488497
# don't failover to `/decide/`, since response will be the same
489-
self.log.warning(
490-
f"[FEATURE FLAGS] Can't compute group feature flag: {feature_flag['key']} without group names passed in"
491-
)
498+
if warn_on_unknown_groups:
499+
self.log.warning(
500+
f"[FEATURE FLAGS] Can't compute group feature flag: {feature_flag['key']} without group names passed in"
501+
)
502+
else:
503+
self.log.debug(
504+
f"[FEATURE FLAGS] Can't compute group feature flag: {feature_flag['key']} without group names passed in"
505+
)
492506
return False
493507

494508
focused_group_properties = group_properties[group_name]
@@ -717,7 +731,9 @@ def get_all_flags_and_payloads(
717731

718732
return response
719733

720-
def _get_all_flags_and_payloads_locally(self, distinct_id, *, groups={}, person_properties={}, group_properties={}):
734+
def _get_all_flags_and_payloads_locally(
735+
self, distinct_id, *, groups={}, person_properties={}, group_properties={}, warn_on_unknown_groups=False
736+
):
721737
require("distinct_id", distinct_id, ID_TYPES)
722738
require("groups", groups, dict)
723739

@@ -737,6 +753,7 @@ def _get_all_flags_and_payloads_locally(self, distinct_id, *, groups={}, person_
737753
groups=groups,
738754
person_properties=person_properties,
739755
group_properties=group_properties,
756+
warn_on_unknown_groups=warn_on_unknown_groups,
740757
)
741758
matched_payload = self._compute_payload_locally(flag["key"], flags[flag["key"]])
742759
if matched_payload:
@@ -756,7 +773,7 @@ def feature_flag_definitions(self):
756773
return self.feature_flags
757774

758775
def _add_local_person_and_group_properties(self, distinct_id, groups, person_properties, group_properties):
759-
all_person_properties = {"$current_distinct_id": distinct_id, **(person_properties or {})}
776+
all_person_properties = {"distinct_id": distinct_id, **(person_properties or {})}
760777

761778
all_group_properties = {}
762779
if groups:

posthog/feature_flags.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -175,11 +175,11 @@ def compare(lhs, rhs, operator):
175175
else:
176176
return compare(str(override_value), str(value), operator)
177177

178-
if operator in ["is_date_before", "is_date_after", "is_relative_date_before", "is_relative_date_after"]:
178+
if operator in ["is_date_before", "is_date_after"]:
179179
try:
180-
if operator in ["is_relative_date_before", "is_relative_date_after"]:
181-
parsed_date = relative_date_parse_for_feature_flag_matching(str(value))
182-
else:
180+
parsed_date = relative_date_parse_for_feature_flag_matching(str(value))
181+
182+
if not parsed_date:
183183
parsed_date = parser.parse(str(value))
184184
parsed_date = convert_to_datetime_aware(parsed_date)
185185
except Exception as e:
@@ -190,20 +190,20 @@ def compare(lhs, rhs, operator):
190190

191191
if isinstance(override_value, datetime.datetime):
192192
override_date = convert_to_datetime_aware(override_value)
193-
if operator in ("is_date_before", "is_relative_date_before"):
193+
if operator == "is_date_before":
194194
return override_date < parsed_date
195195
else:
196196
return override_date > parsed_date
197197
elif isinstance(override_value, datetime.date):
198-
if operator in ("is_date_before", "is_relative_date_before"):
198+
if operator == "is_date_before":
199199
return override_value < parsed_date.date()
200200
else:
201201
return override_value > parsed_date.date()
202202
elif isinstance(override_value, str):
203203
try:
204204
override_date = parser.parse(override_value)
205205
override_date = convert_to_datetime_aware(override_date)
206-
if operator in ("is_date_before", "is_relative_date_before"):
206+
if operator == "is_date_before":
207207
return override_date < parsed_date
208208
else:
209209
return override_date > parsed_date
@@ -302,7 +302,7 @@ def match_property_group(property_group, property_values, cohort_properties) ->
302302

303303

304304
def relative_date_parse_for_feature_flag_matching(value: str) -> Optional[datetime.datetime]:
305-
regex = r"^(?P<number>[0-9]+)(?P<interval>[a-z])$"
305+
regex = r"^-?(?P<number>[0-9]+)(?P<interval>[a-z])$"
306306
match = re.search(regex, value)
307307
parsed_dt = datetime.datetime.now(datetime.timezone.utc)
308308
if match:

posthog/sentry/posthog_integration.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ def processor(event, hint):
4343
not not Hub.current.client.dsn and Dsn(Hub.current.client.dsn).project_id
4444
)
4545
if project_id:
46-
properties[
47-
"$sentry_url"
48-
] = f"{PostHogIntegration.prefix}{PostHogIntegration.organization}/issues/?project={project_id}&query={event['event_id']}"
46+
properties["$sentry_url"] = (
47+
f"{PostHogIntegration.prefix}{PostHogIntegration.organization}/issues/?project={project_id}&query={event['event_id']}"
48+
)
4949

5050
posthog.capture(posthog_distinct_id, "$exception", properties)
5151

posthog/test/test_client.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -783,7 +783,7 @@ def test_disable_geoip_default_on_decide(self, patch_decide):
783783
timeout=10,
784784
distinct_id="some_id",
785785
groups={},
786-
person_properties={"$current_distinct_id": "some_id"},
786+
person_properties={"distinct_id": "some_id"},
787787
group_properties={},
788788
disable_geoip=True,
789789
)
@@ -795,7 +795,7 @@ def test_disable_geoip_default_on_decide(self, patch_decide):
795795
timeout=10,
796796
distinct_id="feature_enabled_distinct_id",
797797
groups={},
798-
person_properties={"$current_distinct_id": "feature_enabled_distinct_id"},
798+
person_properties={"distinct_id": "feature_enabled_distinct_id"},
799799
group_properties={},
800800
disable_geoip=True,
801801
)
@@ -807,7 +807,7 @@ def test_disable_geoip_default_on_decide(self, patch_decide):
807807
timeout=10,
808808
distinct_id="all_flags_payloads_id",
809809
groups={},
810-
person_properties={"$current_distinct_id": "all_flags_payloads_id"},
810+
person_properties={"distinct_id": "all_flags_payloads_id"},
811811
group_properties={},
812812
disable_geoip=False,
813813
)
@@ -843,7 +843,7 @@ def test_default_properties_get_added_properly(self, patch_decide):
843843
timeout=10,
844844
distinct_id="some_id",
845845
groups={"company": "id:5", "instance": "app.posthog.com"},
846-
person_properties={"$current_distinct_id": "some_id", "x1": "y1"},
846+
person_properties={"distinct_id": "some_id", "x1": "y1"},
847847
group_properties={
848848
"company": {"$group_key": "id:5", "x": "y"},
849849
"instance": {"$group_key": "app.posthog.com"},
@@ -856,7 +856,7 @@ def test_default_properties_get_added_properly(self, patch_decide):
856856
"random_key",
857857
"some_id",
858858
groups={"company": "id:5", "instance": "app.posthog.com"},
859-
person_properties={"$current_distinct_id": "override"},
859+
person_properties={"distinct_id": "override"},
860860
group_properties={
861861
"company": {
862862
"$group_key": "group_override",
@@ -869,7 +869,7 @@ def test_default_properties_get_added_properly(self, patch_decide):
869869
timeout=10,
870870
distinct_id="some_id",
871871
groups={"company": "id:5", "instance": "app.posthog.com"},
872-
person_properties={"$current_distinct_id": "override"},
872+
person_properties={"distinct_id": "override"},
873873
group_properties={
874874
"company": {"$group_key": "group_override"},
875875
"instance": {"$group_key": "app.posthog.com"},
@@ -886,7 +886,7 @@ def test_default_properties_get_added_properly(self, patch_decide):
886886
timeout=10,
887887
distinct_id="some_id",
888888
groups={},
889-
person_properties={"$current_distinct_id": "some_id"},
889+
person_properties={"distinct_id": "some_id"},
890890
group_properties={},
891891
disable_geoip=False,
892892
)

posthog/test/test_feature_flags.py

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1873,7 +1873,7 @@ def test_match_property_date_operators(self):
18731873

18741874
@freeze_time("2022-05-01")
18751875
def test_match_property_relative_date_operators(self):
1876-
property_a = self.property(key="key", value="6h", operator="is_relative_date_before")
1876+
property_a = self.property(key="key", value="-6h", operator="is_date_before")
18771877
self.assertTrue(match_property(property_a, {"key": "2022-03-01"}))
18781878
self.assertTrue(match_property(property_a, {"key": "2022-04-30"}))
18791879
self.assertTrue(match_property(property_a, {"key": datetime.datetime(2022, 4, 30, 1, 2, 3)}))
@@ -1898,7 +1898,7 @@ def test_match_property_relative_date_operators(self):
18981898
with self.assertRaises(InconclusiveMatchError):
18991899
match_property(property_a, {"key": "abcdef"})
19001900

1901-
property_b = self.property(key="key", value="1h", operator="is_relative_date_after")
1901+
property_b = self.property(key="key", value="1h", operator="is_date_after")
19021902
self.assertTrue(match_property(property_b, {"key": "2022-05-02"}))
19031903
self.assertTrue(match_property(property_b, {"key": "2022-05-30"}))
19041904
self.assertTrue(match_property(property_b, {"key": datetime.datetime(2022, 5, 30)}))
@@ -1910,16 +1910,16 @@ def test_match_property_relative_date_operators(self):
19101910
self.assertFalse(match_property(property_b, {"key": "abcdef"}))
19111911

19121912
# Invalid flag property
1913-
property_c = self.property(key="key", value=1234, operator="is_relative_date_after")
1913+
property_c = self.property(key="key", value=1234, operator="is_date_after")
19141914

19151915
with self.assertRaises(InconclusiveMatchError):
19161916
self.assertFalse(match_property(property_c, {"key": 1}))
19171917

1918-
with self.assertRaises(InconclusiveMatchError):
1919-
self.assertFalse(match_property(property_c, {"key": "2022-05-30"}))
1918+
# parsed as 1234-05-01 for some reason?
1919+
self.assertTrue(match_property(property_c, {"key": "2022-05-30"}))
19201920

19211921
# # Timezone aware property
1922-
property_d = self.property(key="key", value="12d", operator="is_relative_date_before")
1922+
property_d = self.property(key="key", value="12d", operator="is_date_before")
19231923
self.assertFalse(match_property(property_d, {"key": "2022-05-30"}))
19241924

19251925
self.assertTrue(match_property(property_d, {"key": "2022-03-30"}))
@@ -1929,45 +1929,45 @@ def test_match_property_relative_date_operators(self):
19291929
self.assertFalse(match_property(property_d, {"key": "2022-04-19 02:00:01+02:00"}))
19301930

19311931
# Try all possible relative dates
1932-
property_e = self.property(key="key", value="1h", operator="is_relative_date_before")
1932+
property_e = self.property(key="key", value="1h", operator="is_date_before")
19331933
self.assertFalse(match_property(property_e, {"key": "2022-05-01 00:00:00"}))
19341934
self.assertTrue(match_property(property_e, {"key": "2022-04-30 22:00:00"}))
19351935

1936-
property_f = self.property(key="key", value="1d", operator="is_relative_date_before")
1936+
property_f = self.property(key="key", value="-1d", operator="is_date_before")
19371937
self.assertTrue(match_property(property_f, {"key": "2022-04-29 23:59:00"}))
19381938
self.assertFalse(match_property(property_f, {"key": "2022-04-30 00:00:01"}))
19391939

1940-
property_g = self.property(key="key", value="1w", operator="is_relative_date_before")
1940+
property_g = self.property(key="key", value="1w", operator="is_date_before")
19411941
self.assertTrue(match_property(property_g, {"key": "2022-04-23 00:00:00"}))
19421942
self.assertFalse(match_property(property_g, {"key": "2022-04-24 00:00:00"}))
19431943
self.assertFalse(match_property(property_g, {"key": "2022-04-24 00:00:01"}))
19441944

1945-
property_h = self.property(key="key", value="1m", operator="is_relative_date_before")
1945+
property_h = self.property(key="key", value="1m", operator="is_date_before")
19461946
self.assertTrue(match_property(property_h, {"key": "2022-03-01 00:00:00"}))
19471947
self.assertFalse(match_property(property_h, {"key": "2022-04-05 00:00:00"}))
19481948

1949-
property_i = self.property(key="key", value="1y", operator="is_relative_date_before")
1949+
property_i = self.property(key="key", value="1y", operator="is_date_before")
19501950
self.assertTrue(match_property(property_i, {"key": "2021-04-28 00:00:00"}))
19511951
self.assertFalse(match_property(property_i, {"key": "2021-05-01 00:00:01"}))
19521952

1953-
property_j = self.property(key="key", value="122h", operator="is_relative_date_after")
1953+
property_j = self.property(key="key", value="122h", operator="is_date_after")
19541954
self.assertTrue(match_property(property_j, {"key": "2022-05-01 00:00:00"}))
19551955
self.assertFalse(match_property(property_j, {"key": "2022-04-23 01:00:00"}))
19561956

1957-
property_k = self.property(key="key", value="2d", operator="is_relative_date_after")
1957+
property_k = self.property(key="key", value="2d", operator="is_date_after")
19581958
self.assertTrue(match_property(property_k, {"key": "2022-05-01 00:00:00"}))
19591959
self.assertTrue(match_property(property_k, {"key": "2022-04-29 00:00:01"}))
19601960
self.assertFalse(match_property(property_k, {"key": "2022-04-29 00:00:00"}))
19611961

1962-
property_l = self.property(key="key", value="02w", operator="is_relative_date_after")
1962+
property_l = self.property(key="key", value="-02w", operator="is_date_after")
19631963
self.assertTrue(match_property(property_l, {"key": "2022-05-01 00:00:00"}))
19641964
self.assertFalse(match_property(property_l, {"key": "2022-04-16 00:00:00"}))
19651965

1966-
property_m = self.property(key="key", value="1m", operator="is_relative_date_after")
1966+
property_m = self.property(key="key", value="1m", operator="is_date_after")
19671967
self.assertTrue(match_property(property_m, {"key": "2022-04-01 00:00:01"}))
19681968
self.assertFalse(match_property(property_m, {"key": "2022-04-01 00:00:00"}))
19691969

1970-
property_n = self.property(key="key", value="1y", operator="is_relative_date_after")
1970+
property_n = self.property(key="key", value="1y", operator="is_date_after")
19711971
self.assertTrue(match_property(property_n, {"key": "2022-05-01 00:00:00"}))
19721972
self.assertTrue(match_property(property_n, {"key": "2021-05-01 00:00:01"}))
19731973
self.assertFalse(match_property(property_n, {"key": "2021-05-01 00:00:00"}))

posthog/version.py

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

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

sentry_django_example/sentry_django_example/urls.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
1. Import the include() function: from django.urls import include, path
1414
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
1515
"""
16+
1617
from django.contrib import admin
1718
from django.urls import path
1819

0 commit comments

Comments
 (0)