Skip to content

Commit c1b7fd1

Browse files
authored
Add special case context handling for prefab.current-time (#124)
1 parent 1271d0d commit c1b7fd1

File tree

2 files changed

+102
-1
lines changed

2 files changed

+102
-1
lines changed

prefab_cloud_python/config_resolver.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22
import functools
3+
import time
34
from collections.abc import Sequence
45

56
from .read_write_lock import ReadWriteLock
@@ -129,7 +130,11 @@ def all_criteria_match(self, conditional_value, props):
129130
return True
130131

131132
def evaluate_criterion(self, criterion, properties):
132-
value_from_properties = properties.get(criterion.property_name)
133+
if criterion.property_name == "prefab.current-time":
134+
value_from_properties = int(time.time() * 1000)
135+
else:
136+
value_from_properties = properties.get(criterion.property_name)
137+
133138
deepest_value = ConfigValueUnwrapper.deepest_value(
134139
criterion.value_to_match, self.config, properties
135140
)

tests/test_criteria_evaluator.py

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
from prefab_cloud_python.config_resolver import CriteriaEvaluator
22
from prefab_cloud_python.context import Context
33
import prefab_pb2 as Prefab
4+
from datetime import datetime, timezone, timedelta
5+
from unittest.mock import patch
46

57
project_env_id = 1
68
test_env_id = 2
@@ -1019,6 +1021,100 @@ def test_stringifying_property_values_and_names(self):
10191021
== desired_value
10201022
)
10211023

1024+
def test_prefab_current_time(self):
1025+
# Set up a fixed time for testing
1026+
test_time = datetime(2024, 1, 1, 12, 0, 0, tzinfo=timezone.utc)
1027+
int(test_time.timestamp() * 1000)
1028+
1029+
# Create a config that checks if current time is before a future time
1030+
future_time = test_time + timedelta(hours=1)
1031+
future_time_millis = int(future_time.timestamp() * 1000)
1032+
1033+
config = Prefab.Config(
1034+
key=key,
1035+
rows=[
1036+
default_row,
1037+
Prefab.ConfigRow(
1038+
project_env_id=project_env_id,
1039+
values=[
1040+
Prefab.ConditionalValue(
1041+
criteria=[
1042+
Prefab.Criterion(
1043+
operator=Prefab.Criterion.CriterionOperator.PROP_BEFORE,
1044+
property_name="prefab.current-time",
1045+
value_to_match=Prefab.ConfigValue(
1046+
int=future_time_millis
1047+
),
1048+
)
1049+
],
1050+
value=Prefab.ConfigValue(string=desired_value),
1051+
)
1052+
],
1053+
),
1054+
],
1055+
)
1056+
1057+
# Create a config that checks if current time is after a past time
1058+
past_time = test_time - timedelta(hours=1)
1059+
past_time_millis = int(past_time.timestamp() * 1000)
1060+
1061+
config_past = Prefab.Config(
1062+
key=key,
1063+
rows=[
1064+
default_row,
1065+
Prefab.ConfigRow(
1066+
project_env_id=project_env_id,
1067+
values=[
1068+
Prefab.ConditionalValue(
1069+
criteria=[
1070+
Prefab.Criterion(
1071+
operator=Prefab.Criterion.CriterionOperator.PROP_AFTER,
1072+
property_name="prefab.current-time",
1073+
value_to_match=Prefab.ConfigValue(
1074+
int=past_time_millis
1075+
),
1076+
)
1077+
],
1078+
value=Prefab.ConfigValue(string=desired_value),
1079+
)
1080+
],
1081+
),
1082+
],
1083+
)
1084+
1085+
with patch("time.time") as mock_time:
1086+
# Set the mock to return our test time
1087+
mock_time.return_value = test_time.timestamp()
1088+
1089+
evaluator = CriteriaEvaluator(
1090+
config, project_env_id, resolver=None, base_client=None
1091+
)
1092+
evaluator_past = CriteriaEvaluator(
1093+
config_past, project_env_id, resolver=None, base_client=None
1094+
)
1095+
1096+
# Test current time is before future time
1097+
evaluation = evaluator.evaluate(context({}))
1098+
assert evaluation.raw_config_value().string == desired_value
1099+
1100+
# Test current time is after past time
1101+
evaluation = evaluator_past.evaluate(context({}))
1102+
assert evaluation.raw_config_value().string == desired_value
1103+
1104+
# Test with a different time that's after the future time
1105+
mock_time.return_value = (
1106+
future_time.timestamp() + 3600
1107+
) # 1 hour after future_time
1108+
evaluation = evaluator.evaluate(context({}))
1109+
assert evaluation.raw_config_value().string == default_value
1110+
1111+
# Test with a different time that's before the past time
1112+
mock_time.return_value = (
1113+
past_time.timestamp() - 3600
1114+
) # 1 hour before past_time
1115+
evaluation = evaluator_past.evaluate(context({}))
1116+
assert evaluation.raw_config_value().string == default_value
1117+
10221118
@staticmethod
10231119
def mock_resolver(config):
10241120
return MockResolver(config)

0 commit comments

Comments
 (0)