summaryrefslogtreecommitdiff
path: root/python/helpers/pydev/pydevd_frame.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/helpers/pydev/pydevd_frame.py')
-rw-r--r--python/helpers/pydev/pydevd_frame.py274
1 files changed, 90 insertions, 184 deletions
diff --git a/python/helpers/pydev/pydevd_frame.py b/python/helpers/pydev/pydevd_frame.py
index 5d1e78458391..922133ba1512 100644
--- a/python/helpers/pydev/pydevd_frame.py
+++ b/python/helpers/pydev/pydevd_frame.py
@@ -3,18 +3,15 @@ import os.path
import re
import traceback # @Reimport
-from django_debug import find_django_render_frame
-from django_debug import is_django_render_call, is_django_suspended, suspend_django, is_django_resolve_call, is_django_context_get_call
-from django_frame import DjangoTemplateFrame
-from django_frame import is_django_exception_break_context
-from django_frame import just_raised, get_template_file_name, get_template_line
import pydev_log
from pydevd_breakpoints import get_exception_breakpoint, get_exception_name
-from pydevd_comm import CMD_ADD_DJANGO_EXCEPTION_BREAK, \
- CMD_STEP_CAUGHT_EXCEPTION, CMD_STEP_RETURN, CMD_STEP_OVER, CMD_SET_BREAK, \
+from pydevd_comm import CMD_STEP_CAUGHT_EXCEPTION, CMD_STEP_RETURN, CMD_STEP_OVER, CMD_SET_BREAK, \
CMD_STEP_INTO, CMD_SMART_STEP_INTO, CMD_RUN_TO_LINE, CMD_SET_NEXT_STATEMENT
from pydevd_constants import * # @UnusedWildImport
from pydevd_file_utils import GetFilenameAndBase
+
+from pydevd_frame_utils import add_exception_to_frame, just_raised
+
try:
from pydevd_signature import sendSignatureCallTrace
except ImportError:
@@ -55,17 +52,6 @@ class PyDBFrame:
def doWaitSuspend(self, *args, **kwargs):
self._args[0].doWaitSuspend(*args, **kwargs)
- def _is_django_render_call(self, frame):
- try:
- return self._cached_is_django_render_call
- except:
- # Calculate lazily: note that a PyDBFrame always deals with the same
- # frame over and over, so, we can cache this.
- # -- although we can't cache things which change over time (such as
- # the breakpoints for the file).
- ret = self._cached_is_django_render_call = is_django_render_call(frame)
- return ret
-
def trace_exception(self, frame, event, arg):
if event == 'exception':
flag, frame = self.should_stop_on_exception(frame, event, arg)
@@ -97,22 +83,11 @@ class PyDBFrame:
flag = False
else:
try:
- if mainDebugger.django_exception_break and get_exception_name(exception) in [
- 'VariableDoesNotExist', 'TemplateDoesNotExist', 'TemplateSyntaxError'] \
- and just_raised(trace) and is_django_exception_break_context(frame):
-
- render_frame = find_django_render_frame(frame)
- if render_frame:
- suspend_frame = suspend_django(
- self, mainDebugger, thread, render_frame, CMD_ADD_DJANGO_EXCEPTION_BREAK)
-
- if suspend_frame:
- add_exception_to_frame(suspend_frame, (exception, value, trace))
- flag = True
- thread.additionalInfo.message = 'VariableDoesNotExist'
- suspend_frame.f_back = frame
- frame = suspend_frame
- except :
+ result = mainDebugger.plugin.exception_break(mainDebugger, self, frame, self._args, arg)
+ if result:
+ (flag, frame) = result
+
+ except:
flag = False
return flag, frame
@@ -253,7 +228,8 @@ class PyDBFrame:
sendSignatureCallTrace(main_debugger, frame, filename)
is_exception_event = event == 'exception'
- has_exception_breakpoints = main_debugger.break_on_caught_exceptions or main_debugger.django_exception_break
+ has_exception_breakpoints = main_debugger.break_on_caught_exceptions \
+ or main_debugger.plugin.has_exception_breaks(main_debugger)
if is_exception_event:
if has_exception_breakpoints:
@@ -293,9 +269,8 @@ class PyDBFrame:
can_skip = (step_cmd is None and stop_frame is None)\
or (step_cmd in (CMD_STEP_RETURN, CMD_STEP_OVER) and stop_frame is not frame)
- check_stop_on_django_render_call = main_debugger.django_breakpoints and self._is_django_render_call(frame)
- if check_stop_on_django_render_call:
- can_skip = False
+ if can_skip:
+ can_skip = not main_debugger.plugin.can_not_skip(main_debugger, self, frame)
# Let's check to see if we are in a function that has a breakpoint. If we don't have a breakpoint,
# we will return nothing for the next trace
@@ -334,29 +309,35 @@ class PyDBFrame:
try:
line = frame.f_lineno
-
-
flag = False
- if event == 'call' and info.pydev_state != STATE_SUSPEND and check_stop_on_django_render_call:
- flag, frame = self.should_stop_on_django_breakpoint(frame, event, arg)
-
#return is not taken into account for breakpoint hit because we'd have a double-hit in this case
#(one for the line and the other for the return).
- if not flag and event != 'return' and info.pydev_state != STATE_SUSPEND and breakpoints_for_file is not None\
- and DictContains(breakpoints_for_file, line):
- #ok, hit breakpoint, now, we have to discover if it is a conditional breakpoint
- # lets do the conditional stuff here
+ stop_info = {}
+ breakpoint = None
+ exist_result = False
+ stop_info['stop'] = False
+ if not flag and event != 'return' and info.pydev_state != STATE_SUSPEND and breakpoints_for_file is not None \
+ and DictContains(breakpoints_for_file, line):
breakpoint = breakpoints_for_file[line]
-
- stop = True
+ new_frame = frame
+ stop_info['stop'] = True
if step_cmd == CMD_STEP_OVER and stop_frame is frame and event in ('line', 'return'):
- stop = False #we don't stop on breakpoint if we have to stop by step-over (it will be processed later)
- else:
+ stop_info['stop'] = False #we don't stop on breakpoint if we have to stop by step-over (it will be processed later)
+ else:
+ result = main_debugger.plugin.get_breakpoint(main_debugger, self, frame, event, self._args)
+ if result:
+ exist_result = True
+ (flag, breakpoint, new_frame) = result
+
+ if breakpoint:
+ #ok, hit breakpoint, now, we have to discover if it is a conditional breakpoint
+ # lets do the conditional stuff here
+ if stop_info['stop'] or exist_result:
condition = breakpoint.condition
if condition is not None:
try:
- val = eval(condition, frame.f_globals, frame.f_locals)
+ val = eval(condition, new_frame.f_globals, new_frame.f_locals)
if not val:
return self.trace_dispatch
@@ -371,7 +352,7 @@ class PyDBFrame:
if not main_debugger.suspend_on_breakpoint_exception:
return self.trace_dispatch
else:
- stop = True
+ stop_info['stop'] = True
try:
additional_info = None
try:
@@ -395,18 +376,21 @@ class PyDBFrame:
except:
traceback.print_exc()
- if breakpoint.expression is not None:
- try:
+ if breakpoint.expression is not None:
try:
- val = eval(breakpoint.expression, frame.f_globals, frame.f_locals)
- except:
- val = sys.exc_info()[1]
- finally:
- if val is not None:
- thread.additionalInfo.message = val
-
- if stop:
- self.setSuspend(thread, CMD_SET_BREAK)
+ try:
+ val = eval(breakpoint.expression, new_frame.f_globals, new_frame.f_locals)
+ except:
+ val = sys.exc_info()[1]
+ finally:
+ if val is not None:
+ thread.additionalInfo.message = val
+ if stop_info['stop']:
+ self.setSuspend(thread, CMD_SET_BREAK)
+ elif flag:
+ result = main_debugger.plugin.suspend(main_debugger, thread, frame)
+ if result:
+ frame = result
# if thread has a suspend flag, we suspend with a busy wait
if info.pydev_state == STATE_SUSPEND:
@@ -419,8 +403,6 @@ class PyDBFrame:
#step handling. We stop when we hit the right frame
try:
- django_stop = False
-
should_skip = False
if pydevd_dont_trace.should_trace_hook is not None:
if not hasattr(self, 'should_skip'):
@@ -432,34 +414,18 @@ class PyDBFrame:
should_skip = self.should_skip
if should_skip:
- stop = False
+ stop_info['stop'] = False
elif step_cmd == CMD_STEP_INTO:
- stop = event in ('line', 'return')
-
- if is_django_suspended(thread):
- #django_stop = event == 'call' and is_django_render_call(frame)
- stop = stop and is_django_resolve_call(frame.f_back) and not is_django_context_get_call(frame)
- if stop:
- info.pydev_django_resolve_frame = 1 #we remember that we've go into python code from django rendering frame
+ stop_info['stop'] = event in ('line', 'return')
+ main_debugger.plugin.cmd_step_into(main_debugger, frame, event, self._args, stop_info)
elif step_cmd == CMD_STEP_OVER:
- if is_django_suspended(thread):
- django_stop = event == 'call' and self._is_django_render_call(frame)
-
- stop = False
- else:
- if event == 'return' and info.pydev_django_resolve_frame is not None and is_django_resolve_call(frame.f_back):
- #we return to Django suspend mode and should not stop before django rendering frame
- stop_frame = info.pydev_step_stop = info.pydev_django_resolve_frame
- info.pydev_django_resolve_frame = None
- thread.additionalInfo.suspend_type = DJANGO_SUSPEND
-
-
- stop = stop_frame is frame and event in ('line', 'return')
+ stop_info['stop'] = stop_frame is frame and event in ('line', 'return')
+ main_debugger.plugin.cmd_step_over(main_debugger, frame, event, self._args, stop_info)
elif step_cmd == CMD_SMART_STEP_INTO:
- stop = False
+ stop_info['stop'] = False
if info.pydev_smart_step_stop is frame:
info.pydev_func_name = None
info.pydev_smart_step_stop = None
@@ -472,13 +438,13 @@ class PyDBFrame:
curr_func_name = ''
if curr_func_name == info.pydev_func_name:
- stop = True
+ stop_info['stop'] = True
elif step_cmd == CMD_STEP_RETURN:
- stop = event == 'return' and stop_frame is frame
+ stop_info['stop'] = event == 'return' and stop_frame is frame
elif step_cmd == CMD_RUN_TO_LINE or step_cmd == CMD_SET_NEXT_STATEMENT:
- stop = False
+ stop_info['stop'] = False
if event == 'line' or event == 'exception':
#Yes, we can only act on line events (weird hum?)
@@ -493,50 +459,47 @@ class PyDBFrame:
if curr_func_name == info.pydev_func_name:
line = info.pydev_next_line
if frame.f_lineno == line:
- stop = True
+ stop_info['stop'] = True
else:
if frame.f_trace is None:
frame.f_trace = self.trace_dispatch
frame.f_lineno = line
frame.f_trace = None
- stop = True
+ stop_info['stop'] = True
else:
- stop = False
-
- if django_stop:
- frame = suspend_django(self, main_debugger, thread, frame)
- if frame:
- self.doWaitSuspend(thread, frame, event, arg)
- elif stop:
- #event is always == line or return at this point
- if event == 'line':
- self.setSuspend(thread, step_cmd)
- self.doWaitSuspend(thread, frame, event, arg)
- else: #return event
- back = frame.f_back
- if back is not None:
- #When we get to the pydevd run function, the debugging has actually finished for the main thread
- #(note that it can still go on for other threads, but for this one, we just make it finish)
- #So, just setting it to None should be OK
- base = basename(back.f_code.co_filename)
- if base == 'pydevd.py' and back.f_code.co_name == 'run':
- back = None
-
- elif base == 'pydevd_traceproperty.py':
- # We dont want to trace the return event of pydevd_traceproperty (custom property for debugging)
- #if we're in a return, we want it to appear to the user in the previous frame!
- return None
+ stop_info['stop'] = False
- if back is not None:
- #if we're in a return, we want it to appear to the user in the previous frame!
+ if True in DictIterValues(stop_info):
+ stopped_on_plugin = main_debugger.plugin.stop(main_debugger, frame, event, self._args, stop_info, arg, step_cmd)
+ if DictContains(stop_info, 'stop') and stop_info['stop'] and not stopped_on_plugin:
+ if event == 'line':
self.setSuspend(thread, step_cmd)
- self.doWaitSuspend(thread, back, event, arg)
- else:
- #in jython we may not have a back frame
- info.pydev_step_stop = None
- info.pydev_step_cmd = None
- info.pydev_state = STATE_RUN
+ self.doWaitSuspend(thread, frame, event, arg)
+ else: #return event
+ back = frame.f_back
+ if back is not None:
+ #When we get to the pydevd run function, the debugging has actually finished for the main thread
+ #(note that it can still go on for other threads, but for this one, we just make it finish)
+ #So, just setting it to None should be OK
+ base = basename(back.f_code.co_filename)
+ if base == 'pydevd.py' and back.f_code.co_name == 'run':
+ back = None
+
+ elif base == 'pydevd_traceproperty.py':
+ # We dont want to trace the return event of pydevd_traceproperty (custom property for debugging)
+ #if we're in a return, we want it to appear to the user in the previous frame!
+ return None
+
+ if back is not None:
+ #if we're in a return, we want it to appear to the user in the previous frame!
+ self.setSuspend(thread, step_cmd)
+ self.doWaitSuspend(thread, back, event, arg)
+ else:
+ #in jython we may not have a back frame
+ info.pydev_step_stop = None
+ info.pydev_step_cmd = None
+ info.pydev_state = STATE_RUN
except:
@@ -562,61 +525,4 @@ class PyDBFrame:
except ImportError:
if hasattr(sys, 'exc_clear'): #jython does not have it
sys.exc_clear() #don't keep the traceback
- pass #ok, psyco not available
-
- def should_stop_on_django_breakpoint(self, frame, event, arg):
- mainDebugger = self._args[0]
- thread = self._args[3]
- flag = False
- template_frame_file = get_template_file_name(frame)
-
- #pydev_log.debug("Django is rendering a template: %s\n" % template_frame_file)
-
- django_breakpoints_for_file = mainDebugger.django_breakpoints.get(template_frame_file)
- if django_breakpoints_for_file:
-
- #pydev_log.debug("Breakpoints for that file: %s\n" % django_breakpoints_for_file)
-
- template_frame_line = get_template_line(frame, template_frame_file)
-
- #pydev_log.debug("Tracing template line: %d\n" % template_frame_line)
-
- if DictContains(django_breakpoints_for_file, template_frame_line):
- django_breakpoint = django_breakpoints_for_file[template_frame_line]
-
- if django_breakpoint.is_triggered(template_frame_file, template_frame_line):
-
- #pydev_log.debug("Breakpoint is triggered.\n")
-
- flag = True
- new_frame = DjangoTemplateFrame(
- frame,
- template_frame_file=template_frame_file,
- template_frame_line=template_frame_line,
- )
-
- if django_breakpoint.condition is not None:
- try:
- val = eval(django_breakpoint.condition, new_frame.f_globals, new_frame.f_locals)
- if not val:
- flag = False
- pydev_log.debug("Condition '%s' is evaluated to %s. Not suspending.\n" % (django_breakpoint.condition, val))
- except:
- pydev_log.info(
- 'Error while evaluating condition \'%s\': %s\n' % (django_breakpoint.condition, sys.exc_info()[1]))
-
- if django_breakpoint.expression is not None:
- try:
- try:
- val = eval(django_breakpoint.expression, new_frame.f_globals, new_frame.f_locals)
- except:
- val = sys.exc_info()[1]
- finally:
- if val is not None:
- thread.additionalInfo.message = val
- if flag:
- frame = suspend_django(self, mainDebugger, thread, frame)
- return flag, frame
-
-def add_exception_to_frame(frame, exception_info):
- frame.f_locals['__exception__'] = exception_info \ No newline at end of file
+ pass #ok, psyco not available \ No newline at end of file