Skip to content

Commit fec875f

Browse files
committed
Python object error exceptions
1 parent f39c59d commit fec875f

2 files changed

Lines changed: 42 additions & 18 deletions

File tree

rivescript/python.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,15 +67,15 @@ def load(self, name, code):
6767

6868
try:
6969
exec(source)
70-
#self._objects[name] = RSOBJ
70+
# self._objects[name] = RSOBJ
7171
except Exception as e:
7272
print("Failed to load code from object", name)
7373
print("The error given was: ", e)
7474

7575
def call(self, rs, name, user, fields):
7676
"""Invoke a previously loaded object."""
7777
# Call the dynamic method.
78-
if not name in self._objects:
78+
if name not in self._objects:
7979
return '[ERR: Object Not Found]'
8080
func = self._objects[name]
8181
reply = ''
@@ -84,6 +84,9 @@ def call(self, rs, name, user, fields):
8484
if reply is None:
8585
reply = ''
8686
except Exception as e:
87-
print("Error executing Python object:", e)
88-
reply = '[ERR: Error when executing Python object]'
87+
raise PythonObjectError("Error executing Python object: " + str(e))
8988
return str(reply)
89+
90+
91+
class PythonObjectError(Exception):
92+
pass

rivescript/rivescript.py

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ class RE(object):
7878
RS_ERR_MATCH = "[ERR: No reply matched]"
7979
RS_ERR_REPLY = "[ERR: No reply found]"
8080
RS_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

8386
class 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+
24482463
class 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+
24672488
class DeepRecursionError(RiveScriptError):
24682489
"""Prevented an infinite loop / deep recursion, unable to retrieve a reply for this message"""
24692490
def __init__(self):

0 commit comments

Comments
 (0)