debugger.py :  » IDE » PIDA » pida-0.6beta3 » pida » utils » debugger » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » IDE » PIDA 
PIDA » pida 0.6beta3 » pida » utils » debugger » debugger.py
# -*- coding: utf-8 -*-
"""
    :copyright: 2005-2008 by The PIDA Project
    :license: GPL 2 or later (see README/COPYING/LICENSE)
"""

# PIDA Imports
from pida.core.service import Service
from pida.core.features import FeaturesConfig
from pida.core.events import EventsConfig
from pida.core.actions import ActionsConfig
from pida.core.options import OptionsConfig
from pida.core.actions import TYPE_NORMAL,TYPE_TOGGLE
from pida.core.environment import get_pixmap_path
from pida.core.projects import ProjectController,\
    ProjectKeyDefinition
from pida.core.interfaces import IProjectController

from pida.utils.debugger.views import DebuggerBreakPointsView,DebuggerStackView

# Breakpoints

class Breakpoint(object):
    def __init__(self, file, line, enabled=False, ident=None):
        self.file = file
        self.line = line
        self.enabled = enabled
        self.ident = ident
    
    def get_location(self):
        return (self.file, self.line)
    location = property(get_location)

class BreakpointHandlerInterface(object):
    __breakpoints = {}
    def on_add_breakpoint(self, b, enabled=True):
        """
        if enabled
            if b in breakpoints:
                if b is disabled:
                    enable b
            else
                if b in breakpoi
                add b
        else



        """
        if b.enabled is True:
            if b.location not in self.__breakpoints:
                self.__breakpoints[b.location] = b
        else:
            self.__breakpoints[b.location].enabled = True

    def on_del_breakpoint(self, b, enabled=True):
        if b.enabled is True:
            if b.location in self.__breakpoints:
                self.__breakpoints[b.location].enabled = False
        else:
            if b.location in self.__breakpoints:
                self.__breakpoints.remove(b.location)


    def on_toggle(self, b):
        if (file, line) in self.__breakpoints:
            self.on_del_breakpoint(file, line, False)
        else:
            self.on_add_breakpoint(file, line, False)

    def add_breakpoint(self, b):
        raise NotImplementedError

    def del_breakpoint(self, b):
        raise NotImplementedError

# Actions
class DebuggerActionsConfig(ActionsConfig):
    def create_actions(self):
        # Menu
        self.create_action(
            'debug_show_breakpoints_view',
            TYPE_TOGGLE,
            'Debugger breakpoints list',
            'Show the breakpoints list',
            'accessories-text-editor',
            self.on_show_breakpoints_view,
            '<Shift><Control>b',
        )
        self.create_action(
            'debug_show_stack_view',
            TYPE_TOGGLE,
            "Debugger's stack view",
            'Show the stack of current debugger',
            'accessories-text-editor',
            self.on_show_stack_view,
            '<Shift><Control>s',
        )
    
        # Toolbar
        self.create_action(
            'debug_start',
            TYPE_NORMAL,
            'Continue',
            'Start debugger or Continue debbuging',
            'gdb-go',
            self.on_start,
            '<F3>',
        )
        self.create_action(
            'debug_stop',
            TYPE_NORMAL,
            'Break',
            'Stop debbuging',
            'gdb-break',
            self.on_stop,
            '<F4>',
        )
        self.create_action(
            'debug_next',
            TYPE_NORMAL,
            'Step Over',
            'Step over highlighted statement',
            'gdb-next',
            self.on_step_over,
            '<F6>',
        )
        self.create_action(
            'debug_step',
            TYPE_NORMAL,
            'Step In',
            'Step in highlighted statement',
            'gdb-step',
            self.on_step_in,
            '<F5>',
        )
        self.create_action(
            'debug_return',
            TYPE_NORMAL,
            'Finish function',
            'Step until end of current function',
            'gdb-return',
            self.on_return,
            '<F7>',
        )
        self.create_action(
            'debug_toggle_breakpoint',
            TYPE_NORMAL,
            'Toggle breakpoint',
            'Toggle breakpoint on selected line',
            'gdb-toggle-bp',
            self.on_toggle_breakpoint,
            '<F3>',
        )

    # Buttonbar
    def on_step_over(self, action):
        self.svc.step_over()

    def on_step_in(self, action):
        self.svc.step_in()

    def on_start(self, action):
        self.svc.cont()

    def on_stop(self, action):
        self.svc.end()

    def on_return(self, action):
        self.svc.finish()

    # Menu
    def on_show_breakpoints_view(self, action):
        if action.get_active():
            self.svc.boss.cmd('window', 'add_view', paned='Plugin', view=self.svc._breakpoints_view)
        else:
            self.svc.boss.cmd('window', 'remove_view', view=self.svc._breakpoints_view)

    def on_show_stack_view(self, action):
        if not self.svc._stack_view:
            self.svc._stack_view = DebuggerStackView(self.svc)

        if action.get_active():
            self.svc.boss.cmd('window', 'add_view', paned='Terminal', view=self.svc._stack_view)
        else:
            self.svc.boss.cmd('window', 'remove_view', view=self.svc._stack_view)
        
    #
    def on_toggle_breakpoint(self, action):
#        print 'act.on_toggle_breakpoint'
        self.svc.emit('toggle_breakpoint', file=self.svc._current.get_filename(),
                        line=self.svc.boss.editor.cmd('get_current_line_number'))

# Events
class DebuggerEventsConfig(EventsConfig):
    _breakpoints = {}

    def create(self):
        # UI events
        self.publish('toggle_breakpoint')

        # Debugger events
        self.publish(
                'debugger_started',
                'reset',
                'step',
                'thread',
                'function_call',
                'function_return',
                'add_breakpoint',
                'del_breakpoint',
                'debugger_ended')

        self.subscribe('toggle_breakpoint', self.on_toggle_breakpoint)
        self.subscribe('add_breakpoint', self.on_add_breakpoint)
        self.subscribe('del_breakpoint', self.on_del_breakpoint)
        self.subscribe('debugger_started', self.on_start_debugging)
        self.subscribe('debugger_ended', self.on_end_debugging)

        self.subscribe('step', self.on_step)

    def on_step(self, file, line, function):
        self.svc.boss.cmd('buffer', 'open_file', file_name=file)

        if self.svc._current is not None and file == self.svc._current.get_filename():
            for (oldfile, oldline) in self.svc._step:
                if oldfile == self.svc._current.get_filename():
                    self.svc.boss.editor.cmd('hide_sign', type='step', 
                                                            file_name=oldfile,
                                                            line=oldline)
                    self.svc._step.remove((oldfile, oldline))

            self.svc.boss.editor.cmd('goto_line', line=line)
            self.svc.boss.editor.cmd('show_sign', type='step', 
                                                    file_name=file,
                                                    line=line)
            self.svc._step.append((file, line))

    def on_toggle_breakpoint(self, file, line):
        """
        Toggles a breakpoint in a file on line
        Sends the command to the debugger if it is active
        or update the interfaces
        """
#        print 'evt.on_toggle_breakpoint', file, line
        if self.svc._is_running:
#            print 'is running:', self._breakpoints
            if not (file, str(line)) in self._breakpoints.values():
                self.svc.add_breakpoint(file, line)
            else:
                self.svc.del_breakpoint(file, line)
        else:
            self.svc._toggle_breakpoint(file, line)

    def on_add_breakpoint(self, ident, file, line):
        """
        Add a breakpoint on line of file
        Store it with the current controller
        """
#        print 'evt.on_add_breakpoint', ident, file, line
        self._breakpoints[ident] = (file, line)
        self.svc._controller.store_breakpoint(file, line)
        if self.svc._is_running:
#            print 'show'
            self.svc.boss.editor.cmd('show_sign', type='breakpoint', 
                                                    file_name=file,
                                                    line=line)

    def on_del_breakpoint(self, ident):
        """
        Deletes a breakpoint on line of file 
        Store it with the current controller
        """
#        print 'evt.on_del_breakpoint', ident
        if ident in self._breakpoints:
            (file, line) = self._breakpoints[str(ident)]
            del(self._breakpoints[str(ident)])
            if self.svc._is_running and file == self.svc._current.get_filename():
#                print 'hide'
                self.svc.boss.editor.cmd('hide_sign', type='breakpoint', 
                                                        file_name=file, 
                                                        line=line)
        self.svc._controller.flush_breakpoint(file, line)

    def on_end_debugging(self):
#        print 'evt.on_end_debugging'
        self._breakpoints = {}

    def on_start_debugging(self):
#        print 'evt.on_start_debugging'
        self._breakpoints = {}

        self.svc.get_action('debug_start').set_sensitive(True)
        self.svc.get_action('debug_stop').set_sensitive(True)
        self.svc.get_action('debug_return').set_sensitive(True)
        self.svc.get_action('debug_step').set_sensitive(True)
        self.svc.get_action('debug_next').set_sensitive(True)

    def subscribe_all_foreign(self):
        self.subscribe_foreign('buffer', 'document-changed',
                                     self.on_document_changed)
        self.subscribe_foreign('editor', 'started',
                                     self.on_editor_startup)

    def on_editor_startup(self):
        """
        Set the highlights in vim
        """
        self.svc.boss.editor.cmd('define_sign_type', type="breakpoint", icon=get_pixmap_path("stop.svg"), 
                                                linehl="", text="X", texthl="Search")
        self.svc.boss.editor.cmd('define_sign_type', type="step", icon=get_pixmap_path("forward.svg"), 
                                                linehl="lCursor", text=">", texthl="lCursor")

    def on_document_changed(self, document):
        if document is not None:
            self.svc.get_action('debug_toggle_breakpoint').set_sensitive(True)
            self.svc.update_editor(document)
        else:
            self.svc.get_action('debug_toggle_breakpoint').set_sensitive(False)

# Controller
class GenericDebuggerController(ProjectController):
    name = 'GENERIC_DEBUGGER'

    label = 'Generic Debugger'

    svcname = ''

    debugger = None

    # parameters of the debugger

    attributes = [
        ProjectKeyDefinition('executable', 'Path to the executable', True),
        ProjectKeyDefinition('parameters', 'Parameters to give to the executable', True),
    ] + ProjectController.attributes

    def execute(self):
        """
        Execute debugger
        """
        self.svc = self.boss.get_service(self.svcname)
        self.svc._executable = self.get_option('executable')
        self.svc._parameters = self.get_option('parameters')
        self.svc._controller = self

        if not self.svc._executable:
            self.boss.window.error_dlg(
                'Debug controller is not fully configured.')
        else:
            if self.svc._is_running:
                self.boss.window.error_dlg(
                    'Debugger already running.')
            else:
                if self.svc._init():
                    self.svc.emit('debugger_started')
                else:
                    self.boss.window.error_dlg(
                        'Debug session failed to launch.')

    # breakpoint recording management
    _breakpoints = {}

    def init_breakpoint(self):
        """
        init breakpoint storage
        """
#        print 'controller.init_breakpoint'
        if self.get_option('breakpoint') is None:
            self.set_option('breakpoint', dict())

    def store_breakpoint(self, file, line):
        """
        Store breakpoint
        """
#        print 'controller.store_breakpoint', file, line
        if file not in self.get_option('breakpoint'):
            self.get_option('breakpoint')[file] = []

        if line not in self.get_option('breakpoint')[file]:
            self.get_option('breakpoint')[file].append(line)
            self.project.options.write()
            return True
        else:
            return False

    def flush_breakpoint(self, file, line):
        """
        Remove breakpoint from recorded list
        """
#        print 'controller.flush_breakpoint', file, line
        if file in self.get_option('breakpoint'):
            if line in self.get_option('breakpoint')[file]:
                self.get_option('breakpoint')[file].remove(line)
            if self.get_option('breakpoint')[file] == []:
                del(self.get_option('breakpoint')[file])
        self.project.options.write()

    def list_breakpoints(self):
        l = self.get_option('breakpoint')
#        print 'controller.list_breakpoints', l
        if l is None:
            return {}
        return l
        
class DebuggerFeaturesConfig(FeaturesConfig):
    def subscribe_all_foreign(self):
        self.subscribe_foreign('project', IProjectController, 
                                                    self.svc.controller_config)

class DebuggerOptionsConfig(OptionsConfig):
    def create_options(self):
        self.create_option(
            'breakpoint_pixmap',
            "Breakpoint's pixmap",
            file,
            get_pixmap_path("stop.svg"),
            'Path to a pixmap for the breakpoints to be displayed at '
            'beginning of line',
        )
        self.create_option(
            'cursor_pixmap',
            "Debugging cursor's pixmap",
            file,
            get_pixmap_path("forward.svg"),
            'Path to a pixmap for the cursor to be displayed at \
beginning of line where debugger is halted')

        self.create_option(
            'executable_path',
            'Pathes to the GDB-compatible debugger : ',
            str,
            self.svc.DEFAULT_DEBUGGER_PATH_OPTION,
            ('Set the path to the debugger executable.')
        )

# Service class
class Debugger(Service):
    """Debugging a project service""" 

    DEFAULT_DEBUGGER_PATH_OPTION = None

    actions_config = DebuggerActionsConfig
    events_config = DebuggerEventsConfig
    features_config = DebuggerFeaturesConfig
    options_config = DebuggerOptionsConfig

    controller_config = GenericDebuggerController

    _controller = None

    def _toggle_breakpoint(self, file, line):
        if self._controller.store_breakpoint(file, line):
            self.boss.editor.cmd('show_sign', type='breakpoint', 
                                                file_name=file,
                                                line=line)
        else:
            self._controller.flush_breakpoint(file, line)
            self.boss.editor.cmd('hide_sign', type='breakpoint', 
                                                file_name=file,
                                                line=line)

    def _list_breakpoints(self, file=None):
        """
        Lists all breakpoints choosed by the user
        """
#        print 'svc._list_breakpoints'
        if self._controller is not None:
            if file is not None:
                for line in self._controller.list_breakpoints()[file]:
                    yield (file, line)
            else:
                for file in self._controller.list_breakpoints():
                    for line in self._controller.list_breakpoints()[file]:
                        yield (file, line)

    def _flush_breakpoints(self):
        """
        Removes all breakpoints from the debugger
        """
#        print 'svc._flush_breakpoints'
        for (file, line) in self._list_breakpoints():
            self._controller.flush_breakpoint(file, line)
        self._breakpoints_view.clear_items()

    def _load_breakpoints(self):
        """
        Load all breakpoints in the debugger
        """
#        print 'svc._load_breakpoints'
        lb = self._list_breakpoints()
        self._flush_breakpoints()
        for (file, line) in lb:
            self.emit('toggle_breakpoint', file=file, line=line)

    def _init(self):
        """
        Initialisation of the debugging session
        """
#        print 'svc._init'
        # set session state
        self._is_running = True

        if not self.init():
            return False
        
        # load breakpoints
        self._controller.init_breakpoint()
        self._load_breakpoints()

        # open views
        self.get_action('debug_show_breakpoints_view').set_active(True)
        self.get_action('debug_show_stack_view').set_active(True)
        
        return True

    def _end(self):
        """
        Termination of the debugging session
        """
#        print 'svc._end'
        self._is_running = False
        self.emit('debugger_ended')

        self.get_action('debug_start').set_sensitive(False)
        self.get_action('debug_stop').set_sensitive(False)
        self.get_action('debug_step').set_sensitive(False)
        self.get_action('debug_next').set_sensitive(False)
        self.get_action('debug_return').set_sensitive(False)

        # removing old cursor
        for (oldfile, oldline) in self._step:
            self.boss.editor.cmd('hide_sign', type='step', 
                                                    file_name=oldfile,
                                                    line=oldline)
            self._step.remove((oldfile, oldline))

        return self.end()

    def start(self):
        """
        Starts the service
        """
        self._step = []
        self._current = None
        self._controller = None
        self._is_running = False

        # initiate the views
        self._breakpoints_view = DebuggerBreakPointsView(self)
        self._stack_view = DebuggerStackView(self)

        # Sets default sensitivity for button bar
        self.get_action('debug_step').set_sensitive(False)
        self.get_action('debug_next').set_sensitive(False)
        self.get_action('debug_return').set_sensitive(False)
        self.get_action('debug_start').set_sensitive(False)
        self.get_action('debug_stop').set_sensitive(False)
        self.get_action('debug_toggle_breakpoint').set_sensitive(False)

        # load cached breakpoints
        self._load_breakpoints()

    def update_editor(self, document):
        """
        Updates the editor with current's document breakpoints
        """
        # update the editor
        self._current = document
        if document.get_filename() in self._list_breakpoints():
            line = self._list_breakpoints(document.get_filename())
            self.boss.editor.cmd('show_sign', type='breakpoint', 
                                                file_name=document.get_filename(),
                                                line=line)
        if self._is_running and self._step != []:
            (file, line) = self._step[-1]
            if file is document.get_filename():
                self.boss.editor.cmd('show_sign', type='step', 
                                                    file_name=file,
                                                    line=line)

    # abstract interface to be implemented by services
    def init(self, executable, parameters, controller):
        """
        Initiates the debugging session
        """
        raise NotImplementedError

    def end(self):
        """
        Ends the debugging session
        """
        raise NotImplementedError

    def step_in(self):
        """
        step in instruction
        """
        raise NotImplementedError
        
    def step_over(self):
        """
        Step over instruction
        """
        raise NotImplementedError

    def cont(self):
        """
        Continue execution
        """
        raise NotImplementedError

    def finish(self):
        """
        Finish current function call
        """
        raise NotImplementedError

    def add_breakpoint(self, file, line):
        raise NotImplementedError

    def del_breakpoint(self, file, line):
        raise NotImplementedError

# Required Service attribute for service loading
Service = Debugger

# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79:
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.