Skip to content

Commit

Permalink
Merge 480a92c into 7c23847
Browse files Browse the repository at this point in the history
  • Loading branch information
TheseusGrey committed Sep 6, 2018
2 parents 7c23847 + 480a92c commit 7f70035
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 1 deletion.
24 changes: 23 additions & 1 deletion aimmo-game-worker/avatar_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,18 @@ def process_avatar_turn(self, world_map, avatar_state, src_code):

action = self.decide_action(world_map, avatar_state)

# When an InvalidActionException is raised, the traceback might not contain
# reference to the user's code as it can still technically be correct. so we
# handle this case explicitly to avoid printing out unwanted parts of the traceback
except InvalidActionException as e:
print(e)
action = WaitAction().serialise()

except Exception as e:
traceback.print_exc()
user_traceback = self.get_only_user_traceback(e)
for trace in user_traceback:
print(trace)

LOGGER.info("Code failed to run")
LOGGER.info(e)
action = WaitAction().serialise()
Expand All @@ -62,3 +72,15 @@ def decide_action(self, world_map, avatar_state):
if not isinstance(action, Action):
raise InvalidActionException(action)
return action.serialise()

@staticmethod
def get_only_user_traceback(e):
""" If the traceback does not contain any reference to the user code, found by '<string>',
then this method will just return the full traceback. """
traceback_list = traceback.format_exc().split('\n')
start_of_user_traceback = 0
for i in range(len(traceback_list)):
if '<string>' in traceback_list[i]:
start_of_user_traceback = i
break
return traceback_list[start_of_user_traceback:]
50 changes: 50 additions & 0 deletions aimmo-game-worker/tests/test_avatar_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,53 @@ def handle_turn(self, world_map, avatar_state):
runner._update_avatar(src_code=avatar)
with self.assertRaises(InvalidActionException):
runner.decide_action(world_map={}, avatar_state={})

def test_runtime_error_contains_only_user_traceback(self):
avatar = '''class Avatar(object):
def handle_turn(self, world_map, avatar_state):
from simulation.action import MoveAction
from simulation.direction import NORTH
1 + 'foo'
return MoveAction(NORTH)
'''
runner = AvatarRunner()
response = runner.process_avatar_turn(world_map={}, avatar_state={}, src_code=avatar)
self.assertFalse('/usr/src/app/' in response['log'])

def test_syntax_error_contains_only_user_traceback(self):
avatar = '''class Avatar(object):
def handle_turn(self, world_map, avatar_state):
from simulation.action import MoveAction
from simulation.direction import NORTH
return MoveAction(NORTH))))
'''
runner = AvatarRunner()
response = runner.process_avatar_turn(world_map={}, avatar_state={}, src_code=avatar)
self.assertFalse('/usr/src/app/' in response['log'])

def test_invalid_action_exception_contains_only_user_traceback(self):
avatar1 = '''class Avatar(object):
def handle_turn(self, world_map, avatar_state):
from simulation.action import MoveAction
from simulation.direction import NORTH
return None
'''
avatar2 = '''class Avatar(object):
def handle_turn(self, world_map, avatar_state):
from simulation.action import MoveAction
from simulation.direction import NORTH
return 1
'''
runner = AvatarRunner()
response = runner.process_avatar_turn(world_map={}, avatar_state={}, src_code=avatar1)
self.assertFalse('/usr/src/app/' in response['log'])
response = runner.process_avatar_turn(world_map={}, avatar_state={}, src_code=avatar2)
self.assertFalse('/usr/src/app/' in response['log'])

0 comments on commit 7f70035

Please sign in to comment.