@@ -78,6 +78,9 @@ class RE(object):
7878RS_ERR_MATCH = "[ERR: No reply matched]"
7979RS_ERR_REPLY = "[ERR: No reply found]"
8080RS_ERR_DEEP_RECURSION = "[ERR: Deep recursion detected]"
81+ RS_ERR_OBJECT = "[ERR: Error when executing Python object]"
82+ RS_ERR_OBJECT_HANDLER = "[ERR: No Object Handler]"
83+ RS_ERR_OBJECT_MISSING = "[ERR: Error when executing Python object]"
8184
8285
8386class RiveScript (object ):
@@ -1525,12 +1528,12 @@ def reply(self, user, msg, errors_as_replies=True):
15251528
15261529 # If the BEGIN block exists, consult it first.
15271530 if "__begin__" in self ._topics :
1528- begin = self ._getreply (user , 'request' , context = 'begin' )
1531+ begin = self ._getreply (user , 'request' , context = 'begin' , ignore_object_errors = errors_as_replies )
15291532
15301533 # Okay to continue?
15311534 if '{ok}' in begin :
15321535 try :
1533- reply = self ._getreply (user , msg )
1536+ reply = self ._getreply (user , msg , ignore_object_errors = errors_as_replies )
15341537 except RiveScriptError as e :
15351538 if not errors_as_replies :
15361539 raise
@@ -1540,11 +1543,11 @@ def reply(self, user, msg, errors_as_replies=True):
15401543 reply = begin
15411544
15421545 # Run more tag substitutions.
1543- reply = self ._process_tags (user , msg , reply )
1546+ reply = self ._process_tags (user , msg , reply , ignore_object_errors = errors_as_replies )
15441547 else :
15451548 # Just continue then.
15461549 try :
1547- reply = self ._getreply (user , msg )
1550+ reply = self ._getreply (user , msg , ignore_object_errors = errors_as_replies )
15481551 except RiveScriptError as e :
15491552 if not errors_as_replies :
15501553 raise
@@ -1590,7 +1593,7 @@ def _format_message(self, msg, botreply=False):
15901593
15911594 return msg
15921595
1593- def _getreply (self , user , msg , context = 'normal' , step = 0 ):
1596+ def _getreply (self , user , msg , context = 'normal' , step = 0 , ignore_object_errors = True ):
15941597 # Needed to sort replies?
15951598 if 'topics' not in self ._sorted :
15961599 raise RepliesNotSortedError ("You must call sort_replies() once you are done loading RiveScript documents" )
@@ -1753,9 +1756,10 @@ def _getreply(self, user, msg, context='normal', step=0):
17531756 # See if there are any hard redirects.
17541757 if matched ["redirect" ]:
17551758 self ._say ("Redirecting us to " + matched ["redirect" ])
1756- redirect = self ._process_tags (user , msg , matched ["redirect" ], stars , thatstars , step )
1759+ redirect = self ._process_tags (user , msg , matched ["redirect" ], stars , thatstars , step ,
1760+ ignore_object_errors )
17571761 self ._say ("Pretend user said: " + redirect )
1758- reply = self ._getreply (user , redirect , step = (step + 1 ))
1762+ reply = self ._getreply (user , redirect , step = (step + 1 ), ignore_object_errors = ignore_object_errors )
17591763 break
17601764
17611765 # Check the conditionals.
@@ -1771,8 +1775,8 @@ def _getreply(self, user, msg, context='normal', step=0):
17711775 self ._say ("Left: " + left + "; eq: " + eq + "; right: " + right + " => " + potreply )
17721776
17731777 # Process tags all around.
1774- left = self ._process_tags (user , msg , left , stars , thatstars , step )
1775- right = self ._process_tags (user , msg , right , stars , thatstars , step )
1778+ left = self ._process_tags (user , msg , left , stars , thatstars , step , ignore_object_errors )
1779+ right = self ._process_tags (user , msg , right , stars , thatstars , step , ignore_object_errors )
17761780
17771781 # Defaults?
17781782 if len (left ) == 0 :
@@ -1861,7 +1865,7 @@ def _getreply(self, user, msg, context='normal', step=0):
18611865 reply = reply .replace ('<set {key}={value}>' .format (key = match [0 ], value = match [1 ]), '' )
18621866 else :
18631867 # Process more tags if not in BEGIN.
1864- reply = self ._process_tags (user , msg , reply , stars , thatstars , step )
1868+ reply = self ._process_tags (user , msg , reply , stars , thatstars , step , ignore_object_errors )
18651869
18661870 return reply
18671871
@@ -2018,7 +2022,7 @@ def _precompile_regexp(self, trigger):
20182022
20192023 self ._regexc ["trigger" ][trigger ] = self ._reply_regexp (None , trigger )
20202024
2021- def _process_tags (self , user , msg , reply , st = [], bst = [], depth = 0 ):
2025+ def _process_tags (self , user , msg , reply , st = [], bst = [], depth = 0 , ignore_object_errors = True ):
20222026 """Post process tags in a message."""
20232027 stars = ['' ]
20242028 stars .extend (st )
@@ -2207,11 +2211,21 @@ def _process_tags(self, user, msg, reply, st=[], bst=[], depth=0):
22072211 lang = self ._objlangs [obj ]
22082212 if lang in self ._handlers :
22092213 # We do.
2210- output = self ._handlers [lang ].call (self , obj , user , args )
2214+ try :
2215+ output = self ._handlers [lang ].call (self , obj , user , args )
2216+ except python .PythonObjectError as e :
2217+ self ._warn (str (e ))
2218+ if not ignore_object_errors :
2219+ raise ObjectError
2220+ output = RS_ERR_OBJECT
22112221 else :
2212- output = '[ERR: No Object Handler]'
2222+ if not ignore_object_errors :
2223+ raise ObjectError (RS_ERR_OBJECT_HANDLER )
2224+ output = RS_ERR_OBJECT_HANDLER
22132225 else :
2214- output = '[ERR: Object Not Found]'
2226+ if not ignore_object_errors :
2227+ raise ObjectError (RS_ERR_OBJECT_MISSING )
2228+ output = RS_ERR_OBJECT_MISSING
22152229
22162230 reply = reply .replace ('<call>{match}</call>' .format (match = match ), output )
22172231
@@ -2445,6 +2459,7 @@ def _dump(self):
24452459################################################################################
24462460# Exception Classes #
24472461################################################################################
2462+
24482463class RiveScriptError (Exception ):
24492464 """RiveScript base exception class"""
24502465 def __init__ (self , error_message = None ):
@@ -2464,6 +2479,12 @@ def __init__(self):
24642479 super (NoReplyError , self ).__init__ (RS_ERR_REPLY )
24652480
24662481
2482+ class ObjectError (RiveScriptError ):
2483+ """An error occurred when executing a Python object"""
2484+ def __init__ (self , error_message = RS_ERR_OBJECT ):
2485+ super (ObjectError , self ).__init__ (error_message )
2486+
2487+
24672488class DeepRecursionError (RiveScriptError ):
24682489 """Prevented an infinite loop / deep recursion, unable to retrieve a reply for this message"""
24692490 def __init__ (self ):
0 commit comments