Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error handling behaving differently for rule syntax and python code #48

Closed
ana-barbosa opened this issue Oct 31, 2021 · 3 comments
Closed

Comments

@ana-barbosa
Copy link

ana-barbosa commented Oct 31, 2021

Hello! I new to clipspy and I am currently designing some rules based on dates.
When running my test scenarios with invalid dates, I noticed that exceptions throw by my python code are not reaching my except clause.

The simplified example is:

def is_date_in_range(date: str, initial_date_range: str, final_date_range: str):
    date = datetime.strptime(date, "%Y-%m-%d")
    initial_date_range = datetime.strptime(initial_date_range, "%Y-%m-%d")
    final_date_range = datetime.strptime(final_date_range, "%Y-%m-%d")

    return initial_date_range <= date <= final_date_range


rule = """
(
  defrule issue_date_rule
    (issue_date ?issue_date)
  =>
    (bind ?is_date_in_range (is_date_in_range ?issue_date "2004-01-02" "2013-12-31"))
    (
      if (eq ?is_date_in_range TRUE) then 
        (println "condition satisfied")
      else 
        (println "condition not satisfied")
    )
)
"""

env = clips.Environment()

try:
    env.define_function(is_date_in_range)
    env.build(rule)

    env.assert_string("(issue_date \"gibberish\")")
    env.run()
except Exception as error:
    print("Found an error")

In this code snippet I am asserting gibberish to force the error on is_date_in_range, which is thrown, but my application ends without printing condition satisfied neither condition not satisfied neither Found an error.

If I debug is_date_in_range I can see on the console:

ValueError: time data 'gibberish' does not match format '%Y-%m-%d'
ffi.error: struct udfContext: wrong offset for field 'context' (cdef says 0, but C compiler says 8). fix it or use "...;" as the last field in the cdef for struct udfContext to make it flexible

On the other hand if I purposefully add a typo to my if statement, like if (eqq ?is_date_in_range TRUE) then, then I also won't see the condition satisfied neither condition satisfied, but I'll be able to catch CLIPSError and see the Found an error message printed.

I am running this snippet using Python 3.7.11 on MAC and also on Debian image, both showing the same results.

Am I missing some configuration that would allow me to catch it? I understand that defensive programming would be a better solution in this case, but I am concerned that my service won't be aware of unexpected errors.

Thanks in advance!

@noxdafox noxdafox added bug and removed bug labels Oct 31, 2021
@noxdafox
Copy link
Owner

noxdafox commented Nov 1, 2021

CLIPS does not implement exceptions. Therefore, it won't raise any CLIPSError when invoking the run function. The run function always returns the amount of fired rules.

The reason why you see a CLIPSError when you add a typo in your code is because the build function fails to build the code due to your typo.

What is happening is your function throws the error and stops the execution of your CLIPS rules. This mechanism is silent and the only way for you to verify whether everything ran smoothly is via the CLIPS get-error function.

env = clips.Environment()

try:
    env.define_function(is_date_in_range)
    env.build(rule)

    env.assert_string("(issue_date \"gibberish\")")
    env.run()
    print(env.eval('(get-error)'))
except Exception as error:
    print("Found an error")

Will print:

Traceback (most recent call last):
  File "/usr/local/lib/python3.9/dist-packages/clips/functions.py", line 440, in python_function
    ret = environment_data(env, 'user_functions')[funcname](*arguments)
  File "/home/noxdafox/issue-48.py", line 6, in is_date_in_range
    date = datetime.strptime(date, "%Y-%m-%d")
  File "/usr/lib/python3.9/_strptime.py", line 568, in _strptime_datetime
    tt, fraction, gmtoff_fraction = _strptime(data_string, format)
  File "/usr/lib/python3.9/_strptime.py", line 349, in _strptime
    raise ValueError("time data %r does not match format %r" %
ValueError: time data 'gibberish' does not match format '%Y-%m-%d'

Nevertheless, the mechanism is indeed imperfect and the library should be more explicit when handling these situations. I will soon come with improvements in merit.

@ana-barbosa
Copy link
Author

Awesome! Thanks for the answer, that will already help me proceed with my developments!

noxdafox added a commit that referenced this issue Nov 3, 2021
Signed-off-by: Matteo Cafasso <noxdafox@gmail.com>
noxdafox added a commit that referenced this issue Nov 3, 2021
Signed-off-by: Matteo Cafasso <noxdafox@gmail.com>
noxdafox added a commit that referenced this issue Nov 3, 2021
When exceptions happen in a Python defined function, the execution of
the Rule is interrupted. The error and traceback are logged on
`stdwrn` routers and the error message is forwarded back to CLIPS.

A new set of API `error_state` and `clear_error_state()` are provided
to check if errors during rule execution happened.

Signed-off-by: Matteo Cafasso <noxdafox@gmail.com>
@noxdafox
Copy link
Owner

Issue fixed in release 1.0.1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants