Fixed incorrect information on Python frames in MuranoPL stack traces
Python frames in mixed stack traces were missing file name and pointed to a line below correct position Change-Id: I335292f40b3b6ea3dbca80b84f1d8dbed9a6581d Fixes: bug #1331113
This commit is contained in:
parent
a6d377d992
commit
705a0f5838
@ -123,7 +123,7 @@ class TaskExecutor(object):
|
||||
self._invoke(exc)
|
||||
except Exception as e:
|
||||
if isinstance(e, dsl_exception.MuranoPlException):
|
||||
LOG.error(e.format())
|
||||
LOG.error('\n' + e.format(prefix=' '))
|
||||
else:
|
||||
LOG.exception(e)
|
||||
reporter = status_reporter.StatusReporter()
|
||||
|
@ -71,8 +71,8 @@ class MuranoPlException(Exception):
|
||||
else:
|
||||
return self._names
|
||||
|
||||
def format(self, prefix=' '):
|
||||
text = '\n{3}{0}: {1}\n' \
|
||||
def format(self, prefix=''):
|
||||
text = '{3}{0}: {1}\n' \
|
||||
'{3}Traceback (most recent call last):\n' \
|
||||
'{2}'.format(self._format_name(), self.message,
|
||||
self.stacktrace.toString(prefix + ' '), prefix)
|
||||
|
@ -45,25 +45,15 @@ class StackTrace(murano_object.MuranoObject):
|
||||
frames.reverse()
|
||||
|
||||
if includeNativeFrames:
|
||||
class InstructionStub(object):
|
||||
def __init__(self, title, position):
|
||||
self._title = title
|
||||
self.source_file_position = position
|
||||
|
||||
def __str__(self):
|
||||
return self._title
|
||||
|
||||
native_frames = []
|
||||
for frame in inspect.trace()[1:]:
|
||||
info = inspect.getframeinfo(frame[0])
|
||||
position = yaql_expression.YaqlExpressionFilePosition(
|
||||
os.path.abspath(info.filename), info.lineno,
|
||||
location = yaql_expression.YaqlExpressionFilePosition(
|
||||
os.path.abspath(frame[1]), frame[2],
|
||||
-1, -1, -1, -1, -1)
|
||||
instruction = InstructionStub(
|
||||
info.code_context[0].strip(), position)
|
||||
method = info.function
|
||||
method = frame[3]
|
||||
native_frames.append({
|
||||
'instruction': instruction,
|
||||
'instruction': frame[4][0].strip(),
|
||||
'location': location,
|
||||
'method': method,
|
||||
'class': None
|
||||
})
|
||||
@ -77,6 +67,8 @@ class StackTrace(murano_object.MuranoObject):
|
||||
method = frame['method']
|
||||
murano_class = frame['class']
|
||||
location = frame['location']
|
||||
if murano_class:
|
||||
method += ' of class ' + murano_class.name
|
||||
|
||||
if location:
|
||||
args = (
|
||||
@ -86,14 +78,12 @@ class StackTrace(murano_object.MuranoObject):
|
||||
if location.start_column >= 0 else '',
|
||||
method,
|
||||
instruction,
|
||||
prefix,
|
||||
'' if not murano_class else murano_class.name + '::'
|
||||
prefix
|
||||
)
|
||||
return '{5}File "{0}", line {1}{2} in method {6}{3}\n' \
|
||||
return '{5}File "{0}", line {1}{2} in method {3}\n' \
|
||||
'{5} {4}'.format(*args)
|
||||
else:
|
||||
return '{2}File <unknown> in method {3}{0}\n{2} {1}'.format(
|
||||
method, instruction, prefix,
|
||||
'' if not murano_class else murano_class.name + '::')
|
||||
return '{2}File <unknown> in method {0}\n{2} {1}'.format(
|
||||
method, instruction, prefix)
|
||||
|
||||
return '\n'.join([format_frame(t)for t in self.get_property('frames')])
|
||||
|
@ -49,3 +49,7 @@ Methods:
|
||||
- Return:
|
||||
Value: $enum
|
||||
|
||||
testStackTrace:
|
||||
Body:
|
||||
raisePythonException()
|
||||
|
||||
|
@ -12,6 +12,12 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import inspect
|
||||
import os.path
|
||||
import re
|
||||
|
||||
from testtools import matchers
|
||||
|
||||
from murano.dsl import dsl_exception
|
||||
from murano.tests.dsl.foundation import object_model as om
|
||||
from murano.tests.dsl.foundation import test_case
|
||||
@ -20,6 +26,16 @@ from murano.tests.dsl.foundation import test_case
|
||||
class TestExceptions(test_case.DslTestCase):
|
||||
def setUp(self):
|
||||
super(TestExceptions, self).setUp()
|
||||
|
||||
def exception_func():
|
||||
exc = LookupError('just random Python exception')
|
||||
frameinfo = inspect.getframeinfo(inspect.currentframe())
|
||||
exc._position = \
|
||||
os.path.basename(frameinfo.filename), frameinfo.lineno + 4
|
||||
# line below must be exactly 4 lines after currentframe()
|
||||
raise exc
|
||||
|
||||
self.register_function(exception_func, 'raisePythonException')
|
||||
self._runner = self.new_runner(om.Object('ExceptionHandling'))
|
||||
|
||||
def test_throw_catch(self):
|
||||
@ -54,3 +70,27 @@ class TestExceptions(test_case.DslTestCase):
|
||||
self.assertEqual(
|
||||
['enter try', 'exit try', 'else section', 'finally section'],
|
||||
self.traces)
|
||||
|
||||
def test_stack_trace(self):
|
||||
self._runner.preserve_exception = True
|
||||
e = self.assertRaises(
|
||||
dsl_exception.MuranoPlException,
|
||||
self._runner.testStackTrace)
|
||||
call_stack = e.format()
|
||||
self.assertThat(
|
||||
call_stack,
|
||||
matchers.StartsWith(
|
||||
'exceptions.LookupError: just random Python exception'))
|
||||
|
||||
self.assertIsInstance(e.original_exception, LookupError)
|
||||
|
||||
filename, line = e.original_exception._position
|
||||
self.assertThat(
|
||||
call_stack,
|
||||
matchers.MatchesRegex(
|
||||
r'.*^ File \".*ExceptionHandling\.yaml\", '
|
||||
r'line \d+:\d+ in method testStackTrace .*'
|
||||
r'of class ExceptionHandling$.*'
|
||||
r'^ File \".*{0}\", line {1} '
|
||||
r'in method exception_func$.*'.format(filename, line),
|
||||
re.MULTILINE | re.DOTALL))
|
||||
|
Loading…
Reference in New Issue
Block a user