[python] checking field existence results infinite loop
Hi again,
I've been trying to test against non-existent fields, but it seems there's a bug that causes an infinite loop of executing the consequent function.
Easy to reproduce:
jj = {'v': None}
with ruleset('does_exist'):
@when_all(-m.w)
def is_exist(c):
print(f'{c.m.w} is non-existent')
post('does_exist', jj)
Will print endlessly: "None is non-existent".
Just for the sake of it, the f-string or the reference to a non-existent value are NOT responsible for this issue. Removed both and the script will end up in an infinite loop again, printing w is non-existent endlessly.
jj = {'v': None}
with ruleset('does_exist'):
@when_all(-m.w)
def is_exist(c):
print('w is non-existent')
post('does_exist', jj)
I hope this is helpful.
Hi, thanks for asking the question. The problem is the context is asserted every time an action is executed. Because the context doesn't have a 'w' property it keeps satisfying the rule. This sample works as expected:
from durable.lang import *
jj = {'v': None}
with ruleset('does_exist'):
@when_all(-m.w)
def is_exist(c):
print(f'{c.m.w} is non-existent')
update_state('does_exist', { 'w': 1 })
post('does_exist', jj)
Hi,
Thanks, the update state() is new to me so as durable rules.
My use-case is fetching a number of SalesForce objects (btw SF returns non-sparse JSON objects) and parse them (cross-relating object fields) into a very complex and different JSON object. My hope was to able to use durable_rules as the heart of my application to build complex and well-organised rule-base. All rulesets stored in a separate Python module, and I call post() in a very concise, looped manner in the body of my application. Each rule returns a fix-structured dictionary, eg. for a missing value.
with ruleset('is_color'):
@when_all(m.source_object.Obj_color != None)
def is_color(c):
value = str(c.m.source_object.Obj_color)
c.s.wrt = {'path': 'target_obj.sub_obj.target_field',
'value': value}
@when_all(m.source_object.Obj_color == None)
def is_color(c):
value = str(c.m.source_object.Obj_color)
c.s.wrt = {'path': 'target_obj.sub_obj.target_field',
'value': None}
c.s.msg = {
'type': 'warning',
'name': 'Obj_color',
'msg': 'No color data found.',
'field': 'source_object.Obj_color',
'value': value
}
I'm trying to figure out a way to implement your example. But I feel like updating state, aka injecting a value - when the aim is to find out its existence - effectively hiding the fact of missing key/value and potentially lead to false evaluation by overwriting an existing value. Please correct me if my assumption was wrong.
Though, checking for missing key/value doesn't directly affect my actual project I feel this is certainly a misbehaviour of durable_rules library - rendering the - operator to be a "feature" that will 100% break the code.
Thanks again, G
You are right, context changes should not affect the fact/event rules unless explicitly stated (using s.field in the expressions). Let me think about this, the fix might be a little involved.
Hi Jesus, Hope you are doing well. Do you have any news/update on this issue?