diff --git a/.sampo/changesets/resolute-guardian-ilmarinen.md b/.sampo/changesets/resolute-guardian-ilmarinen.md new file mode 100644 index 00000000..2ae86e58 --- /dev/null +++ b/.sampo/changesets/resolute-guardian-ilmarinen.md @@ -0,0 +1,5 @@ +--- +pypi/posthog: patch +--- + +add PROPERTY_OPERATORS constant for match_property diff --git a/posthog/feature_flags.py b/posthog/feature_flags.py index 5a5bf8e9..acd2d999 100644 --- a/posthog/feature_flags.py +++ b/posthog/feature_flags.py @@ -18,6 +18,30 @@ NONE_VALUES_ALLOWED_OPERATORS = ["is_not"] +# All operators supported by match_property, grouped by category. +EQUALITY_OPERATORS = ("exact", "is_not", "is_set", "is_not_set") +STRING_OPERATORS = ("icontains", "not_icontains", "regex", "not_regex") +NUMERIC_OPERATORS = ("gt", "gte", "lt", "lte") +DATE_OPERATORS = ("is_date_before", "is_date_after") +SEMVER_COMPARISON_OPERATORS = ( + "semver_eq", + "semver_neq", + "semver_gt", + "semver_gte", + "semver_lt", + "semver_lte", +) +SEMVER_RANGE_OPERATORS = ("semver_tilde", "semver_caret", "semver_wildcard") +SEMVER_OPERATORS = SEMVER_COMPARISON_OPERATORS + SEMVER_RANGE_OPERATORS + +PROPERTY_OPERATORS = ( + EQUALITY_OPERATORS + + STRING_OPERATORS + + NUMERIC_OPERATORS + + DATE_OPERATORS + + SEMVER_OPERATORS +) + class InconclusiveMatchError(Exception): pass @@ -385,6 +409,9 @@ def match_property(property, property_values) -> bool: operator = property.get("operator") or "exact" value = property.get("value") + if operator not in PROPERTY_OPERATORS: + raise InconclusiveMatchError(f"Unknown operator {operator}") + if key not in property_values: raise InconclusiveMatchError( "can't match properties without a given property value" @@ -505,17 +532,7 @@ def compare(lhs, rhs, operator): "The date provided must be a string or date object" ) - if operator in ( - "semver_eq", - "semver_neq", - "semver_gt", - "semver_gte", - "semver_lt", - "semver_lte", - "semver_tilde", - "semver_caret", - "semver_wildcard", - ): + if operator in SEMVER_OPERATORS: try: override_parsed = parse_semver(override_value) except (ValueError, TypeError): @@ -523,14 +540,7 @@ def compare(lhs, rhs, operator): f"Person property value '{override_value}' is not a valid semver" ) - if operator in ( - "semver_eq", - "semver_neq", - "semver_gt", - "semver_gte", - "semver_lt", - "semver_lte", - ): + if operator in SEMVER_COMPARISON_OPERATORS: try: flag_parsed = parse_semver(value) except (ValueError, TypeError): @@ -578,7 +588,8 @@ def compare(lhs, rhs, operator): ) return lower <= override_parsed < upper - # if we get here, we don't know how to handle the operator + # Unreachable: all operators in PROPERTY_OPERATORS are handled above, + # and unknown operators are rejected at the top of this function. raise InconclusiveMatchError(f"Unknown operator {operator}")