Skip to content

Commit 77596e5

Browse files
committed
Add util methods for comparing strings
1 parent 4996ff6 commit 77596e5

File tree

2 files changed

+44
-3
lines changed

2 files changed

+44
-3
lines changed

posthog/feature_flags.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from dateutil import parser
88
from dateutil.relativedelta import relativedelta
99

10+
from posthog import utils
1011
from posthog.utils import convert_to_datetime_aware, is_valid_regex
1112

1213
__LONG_SCALE__ = float(0xFFFFFFFFFFFFFFF)
@@ -130,7 +131,7 @@ def match_property(property, property_values) -> bool:
130131
def compute_exact_match(value, override_value):
131132
if isinstance(value, list):
132133
return str(override_value).casefold() in [str(val).casefold() for val in value]
133-
return str(value).casefold() == str(override_value).casefold()
134+
return utils.str_icontains(value, override_value)
134135

135136
if operator == "exact":
136137
return compute_exact_match(value, override_value)
@@ -141,10 +142,10 @@ def compute_exact_match(value, override_value):
141142
return key in property_values
142143

143144
if operator == "icontains":
144-
return str(value).casefold() in str(override_value).casefold()
145+
return utils.str_icontains(override_value, value)
145146

146147
if operator == "not_icontains":
147-
return str(value).casefold() not in str(override_value).casefold()
148+
return not utils.str_icontains(override_value, value)
148149

149150
if operator == "regex":
150151
return is_valid_regex(str(value)) and re.compile(str(value)).search(str(override_value)) is not None

posthog/utils.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,3 +125,43 @@ def convert_to_datetime_aware(date_obj):
125125
if date_obj.tzinfo is None:
126126
date_obj = date_obj.replace(tzinfo=timezone.utc)
127127
return date_obj
128+
129+
130+
def str_icontains(source, search):
131+
"""
132+
Check if a string contains another string, ignoring case.
133+
134+
Args:
135+
source: The string to search within
136+
search: The substring to search for
137+
138+
Returns:
139+
bool: True if search is a substring of source (case-insensitive), False otherwise
140+
141+
Examples:
142+
>>> str_icontains("Hello World", "WORLD")
143+
True
144+
>>> str_icontains("Hello World", "python")
145+
False
146+
"""
147+
return str(search).casefold() in str(source).casefold()
148+
149+
150+
def str_iequals(value, comparand):
151+
"""
152+
Check if a string equals another string, ignoring case.
153+
154+
Args:
155+
value: The string to compare
156+
comparand: The string to compare with
157+
158+
Returns:
159+
bool: True if value and comparand are equal (case-insensitive), False otherwise
160+
161+
Examples:
162+
>>> str_iequals("Hello World", "hello world")
163+
True
164+
>>> str_iequals("Hello World", "hello")
165+
False
166+
"""
167+
return str(value).casefold() == str(comparand).casefold()

0 commit comments

Comments
 (0)