Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 2.1.1 - 2022-09-14

Changes:

1. Feature flags local evaluation now supports date property filters as well.
## 2.1.0 - 2022-08-11

Changes:
Expand Down
26 changes: 26 additions & 0 deletions posthog/feature_flags.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import datetime
import hashlib
import re

from dateutil import parser

from posthog.utils import is_valid_regex

__LONG_SCALE__ = float(0xFFFFFFFFFFFFFFF)
Expand Down Expand Up @@ -126,4 +129,27 @@ def match_property(property, property_values) -> bool:
if operator == "lte":
return type(override_value) == type(value) and override_value <= value

if operator in ["is_date_before", "is_date_after"]:
try:
parsed_date = parser.parse(value)
except Exception:
raise InconclusiveMatchError("The date set on the flag is not a valid format")

if isinstance(override_value, datetime.date):
if operator == "is_date_before":
return override_value < parsed_date
else:
return override_value > parsed_date
elif isinstance(override_value, str):
try:
override_date = parser.parse(override_value)
if operator == "is_date_before":
return override_date < parsed_date
else:
return override_date > parsed_date
except Exception:
raise InconclusiveMatchError("The date provided is not a valid format")
else:
raise InconclusiveMatchError("The date provided must be a string or date object")

return False
35 changes: 35 additions & 0 deletions posthog/test/test_feature_flags.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import unittest
from datetime import datetime

import mock
from dateutil import parser
from freezegun import freeze_time

from posthog.client import Client
Expand Down Expand Up @@ -1118,6 +1120,39 @@ def test_match_properties_math_operators(self):
self.assertFalse(match_property(property_d, {"key": "44"}))
self.assertFalse(match_property(property_d, {"key": 44}))

def test_match_property_date_operators(self):
property_a = self.property(key="key", value="2022-05-01", operator="is_date_before")
self.assertTrue(match_property(property_a, {"key": "2022-03-01"}))
self.assertTrue(match_property(property_a, {"key": "2022-04-30"}))
self.assertTrue(match_property(property_a, {"key": datetime(2022, 4, 30)}))
self.assertTrue(match_property(property_a, {"key": parser.parse("2022-04-30")}))
self.assertFalse(match_property(property_a, {"key": "2022-05-30"}))

# Can't be a number
with self.assertRaises(InconclusiveMatchError):
match_property(property_a, {"key": 1})

# can't be invalid string
with self.assertRaises(InconclusiveMatchError):
match_property(property_a, {"key": "abcdef"})

property_b = self.property(key="key", value="2022-05-01", operator="is_date_after")
self.assertTrue(match_property(property_b, {"key": "2022-05-02"}))
self.assertTrue(match_property(property_b, {"key": "2022-05-30"}))
self.assertTrue(match_property(property_b, {"key": datetime(2022, 5, 30)}))
self.assertTrue(match_property(property_b, {"key": parser.parse("2022-05-30")}))
self.assertFalse(match_property(property_b, {"key": "2022-04-30"}))

# can't be invalid string
with self.assertRaises(InconclusiveMatchError):
match_property(property_b, {"key": "abcdef"})

# Invalid flag property
property_c = self.property(key="key", value=1234, operator="is_date_before")

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


class TestCaptureCalls(unittest.TestCase):
@mock.patch.object(Client, "capture")
Expand Down
2 changes: 1 addition & 1 deletion posthog/version.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
VERSION = "2.1.0"
VERSION = "2.1.1"

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