mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Cache is_django_render_call in PyDBFrame object (the same for Jinja).
This commit is contained in:
@@ -2,6 +2,8 @@ import sys
|
||||
from pydevd_constants import DebugInfoHolder
|
||||
from pydevd_constants import DictContains
|
||||
|
||||
import traceback
|
||||
|
||||
WARN_ONCE_MAP = {}
|
||||
|
||||
def stderr_write(message):
|
||||
@@ -18,11 +20,16 @@ def warn(message):
|
||||
if DebugInfoHolder.DEBUG_TRACE_LEVEL>1:
|
||||
stderr_write(message)
|
||||
|
||||
|
||||
def info(message):
|
||||
stderr_write(message)
|
||||
|
||||
def error(message):
|
||||
|
||||
def error(message, tb=False):
|
||||
stderr_write(message)
|
||||
if tb:
|
||||
traceback.print_exc()
|
||||
|
||||
|
||||
def error_once(message):
|
||||
if not DictContains(WARN_ONCE_MAP, message):
|
||||
|
||||
@@ -101,7 +101,6 @@ class PyDBAdditionalThreadInfoWithoutCurrentFramesSupport(AbstractPyDBAdditional
|
||||
#1. we can't have weak-references to python frame object
|
||||
#2. only from 2.5 onwards we have _current_frames support from the interpreter
|
||||
db_frame = PyDBFrame(args)
|
||||
db_frame.frame = args[-1]
|
||||
self._AddDbFrame(db_frame)
|
||||
return db_frame
|
||||
|
||||
|
||||
@@ -40,8 +40,8 @@ class ExceptionBreakpoint:
|
||||
def __str__(self):
|
||||
return self.qname
|
||||
|
||||
class LineBreakpoint:
|
||||
|
||||
class LineBreakpoint(object):
|
||||
def __init__(self, line, condition, func_name, expression):
|
||||
self.line = line
|
||||
self.condition = condition
|
||||
|
||||
@@ -10,7 +10,8 @@ from pydevd_comm import CMD_STEP_CAUGHT_EXCEPTION, CMD_STEP_RETURN, CMD_STEP_OVE
|
||||
from pydevd_constants import * # @UnusedWildImport
|
||||
from pydevd_file_utils import GetFilenameAndBase
|
||||
|
||||
from pydevd_frame_utils import add_exception_to_frame
|
||||
from pydevd_frame_utils import add_exception_to_frame, just_raised
|
||||
|
||||
try:
|
||||
from pydevd_signature import sendSignatureCallTrace
|
||||
except ImportError:
|
||||
@@ -43,6 +44,7 @@ class PyDBFrame:
|
||||
def __init__(self, args):
|
||||
#args = mainDebugger, filename, base, info, t, frame
|
||||
#yeap, much faster than putting in self and then getting it from self later on
|
||||
self.frame = args[-1]
|
||||
self._args = args[:-1]
|
||||
|
||||
def setSuspend(self, *args, **kwargs):
|
||||
@@ -51,17 +53,6 @@ class PyDBFrame:
|
||||
def doWaitSuspend(self, *args, **kwargs):
|
||||
self._args[0].doWaitSuspend(*args, **kwargs)
|
||||
|
||||
def _is_django_render_call(self, frame): # todo: cache in plugins the same way
|
||||
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)
|
||||
@@ -93,7 +84,7 @@ class PyDBFrame:
|
||||
flag = False
|
||||
else:
|
||||
try:
|
||||
result = mainDebugger.plugin_exception_break(self, frame, event, self._args, arg)
|
||||
result = mainDebugger.plugin_exception_break(self, self._args, arg)
|
||||
if result:
|
||||
(flag, frame) = result
|
||||
|
||||
@@ -280,7 +271,7 @@ class PyDBFrame:
|
||||
or (step_cmd in (CMD_STEP_RETURN, CMD_STEP_OVER) and stop_frame is not frame)
|
||||
|
||||
if can_skip:
|
||||
can_skip = main_debugger.plugin_can_skip(frame)
|
||||
can_skip = main_debugger.plugin_can_skip(self)
|
||||
|
||||
# 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
|
||||
@@ -335,7 +326,7 @@ class PyDBFrame:
|
||||
if info.pydev_step_cmd == CMD_STEP_OVER and info.pydev_step_stop is frame and event in ('line', 'return'):
|
||||
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(frame, event, self._args)
|
||||
result = main_debugger.plugin_get_breakpoint(self, event, self._args)
|
||||
if result:
|
||||
exist_result = True
|
||||
(flag, breakpoint, new_frame) = result
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
class Frame:
|
||||
class Frame(object):
|
||||
def __init__(
|
||||
self,
|
||||
f_back,
|
||||
@@ -17,10 +17,28 @@ class Frame:
|
||||
if self.f_globals is None:
|
||||
self.f_globals = {}
|
||||
|
||||
class FCode:
|
||||
|
||||
class FCode(object):
|
||||
def __init__(self, name, filename):
|
||||
self.co_name = name
|
||||
self.co_filename = filename
|
||||
|
||||
|
||||
def add_exception_to_frame(frame, exception_info):
|
||||
frame.f_locals['__exception__'] = exception_info
|
||||
|
||||
|
||||
def just_raised(trace):
|
||||
if trace is None:
|
||||
return False
|
||||
return trace.tb_next is None
|
||||
|
||||
|
||||
def cached_call(obj, func, *args):
|
||||
cached_name = '_cached_' + func.__name__
|
||||
if not hasattr(obj, cached_name):
|
||||
setattr(obj, cached_name, func(*args))
|
||||
|
||||
return getattr(obj, cached_name)
|
||||
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ def load_plugins(package):
|
||||
try:
|
||||
loaded_plugin = plugin_source.load_plugin(plugin)
|
||||
except:
|
||||
pydev_log.error("Failed to load plugin %s" % plugin)
|
||||
pydev_log.error("Failed to load plugin %s" % plugin, True)
|
||||
if loaded_plugin:
|
||||
plugins.append(loaded_plugin)
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ from pydevd_breakpoints import LineBreakpoint, get_exception_name
|
||||
import pydevd_vars
|
||||
import traceback
|
||||
import pydev_log
|
||||
from pydevd_frame_utils import add_exception_to_frame, FCode
|
||||
from pydevd_frame_utils import add_exception_to_frame, FCode, cached_call, just_raised
|
||||
|
||||
|
||||
class DjangoLineBreakpoint(LineBreakpoint):
|
||||
@@ -251,7 +251,6 @@ class DjangoTemplateFrame:
|
||||
if k == name:
|
||||
d[k] = value
|
||||
|
||||
|
||||
def is_django_exception_break_context(frame):
|
||||
try:
|
||||
name = frame.f_code.co_name
|
||||
@@ -260,18 +259,13 @@ def is_django_exception_break_context(frame):
|
||||
return name in ['_resolve_lookup', 'find_template']
|
||||
|
||||
|
||||
def just_raised(trace):
|
||||
if trace is None:
|
||||
return False
|
||||
return trace.tb_next is None
|
||||
|
||||
|
||||
#=======================================================================================================================
|
||||
# Django Step Commands
|
||||
#=======================================================================================================================
|
||||
|
||||
def can_skip(mainDebugger, frame):
|
||||
if hasattr(mainDebugger, 'django_breakpoints') and mainDebugger.django_breakpoints and is_django_render_call(frame):
|
||||
def can_skip(mainDebugger, pydb_frame):
|
||||
frame = pydb_frame.frame
|
||||
if hasattr(mainDebugger, 'django_breakpoints') and mainDebugger.django_breakpoints and cached_call(pydb_frame, is_django_render_call, frame):
|
||||
filename = get_template_file_name(frame)
|
||||
django_breakpoints_for_file = mainDebugger.django_breakpoints.get(filename)
|
||||
if django_breakpoints_for_file:
|
||||
@@ -285,7 +279,7 @@ def has_exception_breaks(mainDebugger):
|
||||
def cmd_step_into(mainDebugger, frame, event, args, stop_info):
|
||||
mainDebugger, filename, info, thread = args
|
||||
if is_django_suspended(thread):
|
||||
#stop_info['django_stop'] = event == 'call' and is_django_render_call(frame)
|
||||
#stop_info['django_stop'] = event == 'call' and cached_call(frame, is_django_render_call)
|
||||
stop_info['stop'] = stop_info['stop'] and is_django_resolve_call(frame.f_back) and not is_django_context_get_call(frame)
|
||||
if stop_info['stop']:
|
||||
info.pydev_django_resolve_frame = 1 #we remember that we've go into python code from django rendering frame
|
||||
@@ -318,14 +312,15 @@ def stop(mainDebugger, frame, event, args, stop_info, arg, step_cmd):
|
||||
return False
|
||||
|
||||
|
||||
def get_breakpoint(mainDebugger, frame, event, args):
|
||||
def get_breakpoint(mainDebugger, pydb_frame, event, args):
|
||||
mainDebugger, filename, info, thread = args
|
||||
frame = pydb_frame.frame
|
||||
flag = False
|
||||
django_breakpoint = None
|
||||
new_frame = None
|
||||
|
||||
if event == 'call' and info.pydev_state != STATE_SUSPEND and hasattr(mainDebugger, 'django_breakpoints') and \
|
||||
mainDebugger.django_breakpoints and is_django_render_call(frame):
|
||||
mainDebugger.django_breakpoints and cached_call(pydb_frame, is_django_render_call, frame):
|
||||
filename = get_template_file_name(frame)
|
||||
pydev_log.debug("Django is rendering a template: %s\n" % filename)
|
||||
django_breakpoints_for_file = mainDebugger.django_breakpoints.get(filename)
|
||||
@@ -344,8 +339,9 @@ def get_breakpoint(mainDebugger, frame, event, args):
|
||||
def suspend(mainDebugger, pydb_frame, thread, frame):
|
||||
return suspend_django(pydb_frame, mainDebugger, thread, frame)
|
||||
|
||||
def exception_break(mainDebugger, pydb_frame, frame, event, args, arg):
|
||||
def exception_break(mainDebugger, pydb_frame, args, arg):
|
||||
mainDebugger, filename, info, thread = args
|
||||
frame = pydb_frame.frame
|
||||
exception, value, trace = arg
|
||||
if hasattr(mainDebugger, 'django_exception_break') and mainDebugger.django_exception_break and \
|
||||
get_exception_name(exception) in ['VariableDoesNotExist', 'TemplateDoesNotExist', 'TemplateSyntaxError'] and \
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import traceback
|
||||
from pydevd_breakpoints import LineBreakpoint, get_exception_name
|
||||
from pydevd_constants import JINJA2_SUSPEND, GetThreadId, STATE_SUSPEND, DictContains
|
||||
from pydevd_comm import CMD_SET_BREAK, CMD_STEP_OVER, CMD_ADD_EXCEPTION_BREAK
|
||||
import pydevd_vars
|
||||
from pydevd_file_utils import GetFileNameAndBaseFromFile
|
||||
from pydevd_frame_utils import add_exception_to_frame, FCode
|
||||
from pydevd_frame_utils import add_exception_to_frame, FCode, cached_call
|
||||
|
||||
class Jinja2LineBreakpoint(LineBreakpoint):
|
||||
|
||||
@@ -191,8 +192,9 @@ def get_jinja2_template_filename(frame):
|
||||
def has_exception_breaks(mainDebugger):
|
||||
return hasattr(mainDebugger, 'jinja2_exception_break') and mainDebugger.jinja2_exception_break
|
||||
|
||||
def can_skip(mainDebugger, frame):
|
||||
if hasattr(mainDebugger, 'jinja2_breakpoints') and mainDebugger.jinja2_breakpoints and is_jinja2_render_call(frame):
|
||||
def can_skip(mainDebugger, pydb_frame):
|
||||
frame = pydb_frame.frame
|
||||
if hasattr(mainDebugger, 'jinja2_breakpoints') and mainDebugger.jinja2_breakpoints and cached_call(pydb_frame, is_jinja2_render_call, frame):
|
||||
filename = get_jinja2_template_filename(frame)
|
||||
jinja2_breakpoints_for_file = mainDebugger.jinja2_breakpoints.get(filename)
|
||||
if jinja2_breakpoints_for_file:
|
||||
@@ -284,13 +286,14 @@ def stop(mainDebugger, frame, event, args, stop_info, arg, step_cmd):
|
||||
return False
|
||||
|
||||
|
||||
def get_breakpoint(mainDebugger, frame, event, args):
|
||||
def get_breakpoint(mainDebugger, pydb_frame, event, args):
|
||||
mainDebugger, filename, info, thread = args
|
||||
frame = pydb_frame.frame
|
||||
new_frame = None
|
||||
jinja2_breakpoint = None
|
||||
flag = False
|
||||
if event in ('line', 'call') and info.pydev_state != STATE_SUSPEND and hasattr(mainDebugger, 'jinja2_breakpoints') and \
|
||||
mainDebugger.jinja2_breakpoints and is_jinja2_render_call(frame):
|
||||
mainDebugger.jinja2_breakpoints and cached_call(pydb_frame, is_jinja2_render_call, frame):
|
||||
filename = get_jinja2_template_filename(frame)
|
||||
jinja2_breakpoints_for_file = mainDebugger.jinja2_breakpoints.get(filename)
|
||||
new_frame = Jinja2TemplateFrame(frame)
|
||||
@@ -310,8 +313,9 @@ def suspend(mainDebugger, pydb_frame, thread, frame):
|
||||
return suspend_jinja2(pydb_frame, mainDebugger, thread, frame)
|
||||
|
||||
|
||||
def exception_break(mainDebugger, pydb_frame, frame, event, args, arg):
|
||||
def exception_break(mainDebugger, pydb_frame, args, arg):
|
||||
mainDebugger, filename, info, thread = args
|
||||
frame = pydb_frame.frame
|
||||
exception, value, trace = arg
|
||||
if hasattr(mainDebugger, 'jinja2_exception_break') and mainDebugger.jinja2_exception_break:
|
||||
if get_exception_name(exception) in ('UndefinedError', 'TemplateNotFound', 'TemplatesNotFound'):
|
||||
@@ -324,7 +328,7 @@ def exception_break(mainDebugger, pydb_frame, frame, event, args, arg):
|
||||
flag = True
|
||||
suspend_frame.f_back = frame
|
||||
frame = suspend_frame
|
||||
return (flag, frame)
|
||||
return flag, frame
|
||||
elif get_exception_name(exception) in ('TemplateSyntaxError', 'TemplateAssertionError'):
|
||||
#errors in compile time
|
||||
name = frame.f_code.co_name
|
||||
@@ -334,5 +338,5 @@ def exception_break(mainDebugger, pydb_frame, frame, event, args, arg):
|
||||
add_exception_to_frame(frame, (exception, value, trace))
|
||||
thread.additionalInfo.suspend_type = JINJA2_SUSPEND
|
||||
flag = True
|
||||
return (flag, frame)
|
||||
return flag, frame
|
||||
return None
|
||||
Reference in New Issue
Block a user