I have data structures that may contain strings that are serialized dates.
Simplified I'm trying to read
{
'config':[
{'created': '2023-06-27T17:27:22.803255939-07:00'}
]
}
I have a rule like "[ cfg for cfg in config if cfg.created > $today ]"
I'm trying to have it explicitly cast to a datetime so I can evaluate the date, but no matter what I try, I can't find a flexible way to resolve it and keep a flexible description of the given object
When parsing I get
>>> r = Rule("[ cfg for cfg in config if cfg.created > $today ]",)
>>> r.matches(i)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/andrew.woodward/.pyenv/versions/3.8.16/lib/python3.8/site-packages/rule_engine/engine.py", line 636, in matches
return bool(self.evaluate(thing))
File "/Users/andrew.woodward/.pyenv/versions/3.8.16/lib/python3.8/site-packages/rule_engine/engine.py", line 625, in evaluate
return self.statement.evaluate(thing)
File "/Users/andrew.woodward/.pyenv/versions/3.8.16/lib/python3.8/site-packages/rule_engine/ast.py", line 1056, in evaluate
return self.expression.evaluate(thing)
File "/Users/andrew.woodward/.pyenv/versions/3.8.16/lib/python3.8/site-packages/rule_engine/ast.py", line 693, in evaluate
if self.condition is None or self.condition.evaluate(thing):
File "/Users/andrew.woodward/.pyenv/versions/3.8.16/lib/python3.8/site-packages/rule_engine/ast.py", line 386, in evaluate
return self._evaluator(thing)
File "/Users/andrew.woodward/.pyenv/versions/3.8.16/lib/python3.8/site-packages/rule_engine/ast.py", line 591, in __op_arithmetic
return self.__op_arithmetic_values(op, left_value, right_value)
File "/Users/andrew.woodward/.pyenv/versions/3.8.16/lib/python3.8/site-packages/rule_engine/ast.py", line 607, in __op_arithmetic_values
raise errors.EvaluationError('data type mismatch')
rule_engine.errors.EvaluationError: data type mismatch
If I change this to what appears to be the way to coerce it to a date, it still freaks out (both cfg.created.date
and (cfg.created).date
)
>>> r = Rule("[ cfg for cfg in config if (cfg.created).date > $today ]",)
>>> r.matches(i)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/andrew.woodward/.pyenv/versions/3.8.16/lib/python3.8/site-packages/rule_engine/engine.py", line 636, in matches
return bool(self.evaluate(thing))
File "/Users/andrew.woodward/.pyenv/versions/3.8.16/lib/python3.8/site-packages/rule_engine/engine.py", line 625, in evaluate
return self.statement.evaluate(thing)
File "/Users/andrew.woodward/.pyenv/versions/3.8.16/lib/python3.8/site-packages/rule_engine/ast.py", line 1056, in evaluate
return self.expression.evaluate(thing)
File "/Users/andrew.woodward/.pyenv/versions/3.8.16/lib/python3.8/site-packages/rule_engine/ast.py", line 693, in evaluate
if self.condition is None or self.condition.evaluate(thing):
File "/Users/andrew.woodward/.pyenv/versions/3.8.16/lib/python3.8/site-packages/rule_engine/ast.py", line 386, in evaluate
return self._evaluator(thing)
File "/Users/andrew.woodward/.pyenv/versions/3.8.16/lib/python3.8/site-packages/rule_engine/ast.py", line 589, in __op_arithmetic
left_value = self.left.evaluate(thing)
File "/Users/andrew.woodward/.pyenv/versions/3.8.16/lib/python3.8/site-packages/rule_engine/ast.py", line 806, in evaluate
raise attribute_error from None
File "/Users/andrew.woodward/.pyenv/versions/3.8.16/lib/python3.8/site-packages/rule_engine/ast.py", line 790, in evaluate
value = self.context.resolve_attribute(thing, resolved_obj, self.name)
File "/Users/andrew.woodward/.pyenv/versions/3.8.16/lib/python3.8/site-packages/rule_engine/engine.py", line 536, in resolve_attribute
return self.__resolve_attribute(thing, object_, name)
File "/Users/andrew.woodward/.pyenv/versions/3.8.16/lib/python3.8/site-packages/rule_engine/engine.py", line 140, in __call__
resolver = self._get_resolver(object_type, name, thing=thing)
File "/Users/andrew.woodward/.pyenv/versions/3.8.16/lib/python3.8/site-packages/rule_engine/engine.py", line 158, in _get_resolver
raise errors.AttributeResolutionError(name, object_type, thing=thing, suggestion=suggest_symbol(name, attribute_resolvers.keys()))
rule_engine.errors.AttributeResolutionError: ('date', <_DataTypeDef name=STRING python_type=str >)
If I load a context and explicitly declare the date it can resolve the value, but It doesn't look like there is a way to do this with out declaring the type for every possible object we want to access.
ctx = rule_engine.Context(
resolver=rule_engine.resolve_attribute,
type_resolver = rule_engine.type_resolver_from_dict({
'created': rule_engine.DataType.DATETIME,
})
)
>>> r = Rule("[ cfg for cfg in config if cfg.created > $today ]", context = ctx)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/andrew.woodward/.pyenv/versions/3.8.16/lib/python3.8/site-packages/rule_engine/engine.py", line 578, in __init__
self.statement = self.parser.parse(text, context)
File "/Users/andrew.woodward/.pyenv/versions/3.8.16/lib/python3.8/site-packages/rule_engine/parser.py", line 106, in parse
return result.build()
File "/Users/andrew.woodward/.pyenv/versions/3.8.16/lib/python3.8/site-packages/rule_engine/parser.py", line 60, in build
return constructor(*self.args, **self.kwargs)
File "/Users/andrew.woodward/.pyenv/versions/3.8.16/lib/python3.8/site-packages/rule_engine/ast.py", line 1053, in build
return cls(context, expression.build(), **kwargs).reduce()
File "/Users/andrew.woodward/.pyenv/versions/3.8.16/lib/python3.8/site-packages/rule_engine/parser.py", line 60, in build
return constructor(*self.args, **self.kwargs)
File "/Users/andrew.woodward/.pyenv/versions/3.8.16/lib/python3.8/site-packages/rule_engine/ast.py", line 672, in build
iterable = iterable.build()
File "/Users/andrew.woodward/.pyenv/versions/3.8.16/lib/python3.8/site-packages/rule_engine/parser.py", line 60, in build
return constructor(*self.args, **self.kwargs)
File "/Users/andrew.woodward/.pyenv/versions/3.8.16/lib/python3.8/site-packages/rule_engine/ast.py", line 102, in build
return cls(*args, **kwargs).reduce()
File "/Users/andrew.woodward/.pyenv/versions/3.8.16/lib/python3.8/site-packages/rule_engine/ast.py", line 991, in __init__
type_hint = context.resolve_type(name, scope=scope)
File "/Users/andrew.woodward/.pyenv/versions/3.8.16/lib/python3.8/site-packages/rule_engine/engine.py", line 555, in resolve_type
return self.__type_resolver(name)
File "/Users/andrew.woodward/.pyenv/versions/3.8.16/lib/python3.8/site-packages/rule_engine/engine.py", line 96, in _type_resolver
raise errors.SymbolResolutionError(name, suggestion=suggest_symbol(name, type_map.keys()))
rule_engine.errors.SymbolResolutionError: config
>>>