Cache functions from plugins lazily as methods in debugger obj.

This commit is contained in:
Dmitry Trofimov
2014-09-05 19:39:09 +02:00
parent 7ab59b3c96
commit 84023a4c15
3 changed files with 32 additions and 22 deletions
+14 -6
View File
@@ -9,7 +9,7 @@ pydev_monkey_qt.patch_qt()
import traceback
from pydevd_plugin_utils import load_plugins, NullProxy, PluginProxy
from pydevd_plugin_utils import load_plugins, NullProxy, bind_func_to_method, clear_bindings
from pydevd_frame_utils import add_exception_to_frame
import pydev_imports
@@ -349,7 +349,13 @@ class PyDB:
self.plugins = load_plugins('pydevd_plugins')
self.plugin = NullProxy()
self._plugin_method_prefix = 'plugin_'
def __getattr__(self, item):
if item.startswith(self._plugin_method_prefix):
# we lazily cache plugin functions as methods of debugger object
return bind_func_to_method(self.plugin, item[len(self._plugin_method_prefix):], self, item)
raise AttributeError(item)
def haveAliveThreads(self):
for t in threadingEnumerate():
@@ -902,7 +908,7 @@ class PyDB:
breakpoints = self.breakpoints
file_to_id_to_breakpoint = self.file_to_id_to_line_breakpoint
else:
result = self.plugin.get_breakpoints(self, breakpoint_type)
result = self.plugin_get_breakpoints(breakpoint_type)
if result is not None:
file_to_id_to_breakpoint = self.file_to_id_to_plugin_breakpoint
breakpoints = result
@@ -1084,7 +1090,7 @@ class PyDB:
pydev_log.debug("Error while removing exception %s"%sys.exc_info()[0])
update_exception_hook(self)
else:
supported_type = self.plugin.remove_exception_breakpoint(self, type, exception)
supported_type = self.plugin_remove_exception_breakpoint(type, exception)
if not supported_type:
raise NameError(type)
@@ -1107,7 +1113,7 @@ class PyDB:
elif cmd_id == CMD_REMOVE_DJANGO_EXCEPTION_BREAK:
exception = text
self.plugin.remove_exception_breakpoint(self, 'django', exception)
self.plugin_remove_exception_breakpoint('django', exception)
elif cmd_id == CMD_EVALUATE_CONSOLE_EXPRESSION:
# Command which takes care for the debug console communication
@@ -1589,7 +1595,7 @@ class PyDB:
self.writer.addCommand(cmd)
def add_plugin_breakpoint(self, func_name, *args, **kwargs):
# add breakpoint from plugin and remember plugin to use
# add breakpoint for plugin and remember which plugin to use in tracing
for plugin in self.plugins:
if hasattr(plugin, func_name):
func = getattr(plugin, func_name)
@@ -1597,7 +1603,9 @@ class PyDB:
if result:
# On adding breakpoint we override plugin that will be used
# That means that we don't work with more then 1 plugin at a time
self.plugin = plugin
if self.plugin != plugin:
clear_bindings(self, self._plugin_method_prefix) # remove plugin methods that are cached already
self.plugin = plugin
return result
return None
+8 -8
View File
@@ -93,7 +93,7 @@ class PyDBFrame:
flag = False
else:
try:
result = mainDebugger.plugin.exception_break(mainDebugger, self, frame, event, self._args, arg)
result = mainDebugger.plugin_exception_break(self, frame, event, self._args, arg)
if result:
(flag, frame) = result
@@ -239,7 +239,7 @@ class PyDBFrame:
is_exception_event = event == 'exception'
has_exception_breakpoints = main_debugger.break_on_caught_exceptions \
or main_debugger.plugin.has_exception_breaks(main_debugger)
or main_debugger.plugin_has_exception_breaks()
if is_exception_event:
if has_exception_breakpoints:
@@ -280,7 +280,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(main_debugger, frame)
can_skip = main_debugger.plugin_can_skip(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
@@ -335,7 +335,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(main_debugger, frame, event, self._args)
result = main_debugger.plugin_get_breakpoint(frame, event, self._args)
if result:
exist_result = True
(flag, breakpoint, new_frame) = result
@@ -366,7 +366,7 @@ class PyDBFrame:
if stop_info['stop']:
self.setSuspend(thread, CMD_SET_BREAK)
elif flag:
result = main_debugger.plugin.suspend(main_debugger, self, thread, frame)
result = main_debugger.plugin_suspend(self, thread, frame)
if result:
frame = result
@@ -396,11 +396,11 @@ class PyDBFrame:
elif step_cmd == CMD_STEP_INTO:
stop_info['stop'] = event in ('line', 'return')
main_debugger.plugin.cmd_step_into(main_debugger, frame, event, self._args, stop_info)
main_debugger.plugin_cmd_step_into(frame, event, self._args, stop_info)
elif step_cmd == CMD_STEP_OVER:
stop_info['stop'] = info.pydev_step_stop is frame and event in ('line', 'return')
main_debugger.plugin.cmd_step_over(main_debugger, frame, event, self._args, stop_info)
main_debugger.plugin_cmd_step_over(frame, event, self._args, stop_info)
elif step_cmd == CMD_SMART_STEP_INTO:
stop_info['stop'] = False
@@ -449,7 +449,7 @@ class PyDBFrame:
stop_info['stop'] = False
if True in stop_info.values():
stopped_on_plugin = main_debugger.plugin.stop(main_debugger, frame, event, self._args, stop_info, arg, step_cmd)
stopped_on_plugin = main_debugger.plugin_stop(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)
+10 -8
View File
@@ -1,4 +1,5 @@
import os
import types
import pydev_log
from pluginbase import PluginBase
@@ -30,16 +31,17 @@ class NullProxy(object):
def __getattr__(self, name):
return self.null_func
class PluginProxy(object):
def __init__(self, plugin):
self.plugin = plugin
self.cache = {}
def __getattr__(self, name):
if not hasattr(self.cache, name):
self.cache[name] = getattr(self.plugin, name)
def bind_func_to_method(plugin, func_name, obj, method_name):
foo = types.MethodType(getattr(plugin, func_name), obj)
setattr(obj, method_name, foo)
return foo
return self.cache[name]
def clear_bindings(obj, method_prefix):
for attr in dir(obj):
if attr.startswith(method_prefix):
delattr(obj, attr)