0001981: Update plugin status when reloading plugins

Plus some cleanup.

svn: r10439
This commit is contained in:
Brian Matherly 2008-04-01 03:12:08 +00:00
parent e7a6115c91
commit bfe3ee1590
4 changed files with 162 additions and 199 deletions

View File

@ -132,6 +132,71 @@ def load_plugins(direct):
return len(failmsg_list) != 0 # return True if there are errors return len(failmsg_list) != 0 # return True if there are errors
#-------------------------------------------------------------------------
#
# reload_plugins
#
#-------------------------------------------------------------------------
def reload_plugins():
""" Reload previously loaded plugins """
global success_list, attempt_list, loaddir_list, failmsg_list
pymod = re.compile(r"^(.*)\.py$")
oldfailmsg = failmsg_list[:]
failmsg_list = []
# attempt to reload all plugins that have succeeded in the past
for plugin in success_list:
filename = plugin[0]
filename = filename.replace('pyc','py')
filename = filename.replace('pyo','py')
try:
reload(plugin[1])
except:
failmsg_list.append((filename, sys.exc_info()))
# Remove previously good plugins that are now bad
# from the registered lists
purge_failed()
# attempt to load the plugins that have failed in the past
for (filename, message) in oldfailmsg:
name = os.path.split(filename)
match = pymod.match(name[1])
if not match:
continue
attempt_list.append(filename)
plugin = match.groups()[0]
try:
# For some strange reason second importing of a failed plugin
# results in success. Then reload reveals the actual error.
# Looks like a bug in Python.
a = __import__(plugin)
reload(a)
success_list.append((filename, a))
except:
failmsg_list.append((filename, sys.exc_info()))
# attempt to load any new files found
for directory in loaddir_list:
for filename in os.listdir(directory):
name = os.path.split(filename)
match = pymod.match(name[1])
if not match:
continue
if filename in attempt_list:
continue
attempt_list.append(filename)
plugin = match.groups()[0]
try:
a = __import__(plugin)
if a not in [plugin[1]
for plugin in success_list]:
success_list.append((filename, a))
except:
failmsg_list.append((filename, sys.exc_info()))
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
# Plugin registering # Plugin registering

View File

@ -55,10 +55,11 @@ import _Tool as Tool
class PluginStatus(ManagedWindow.ManagedWindow): class PluginStatus(ManagedWindow.ManagedWindow):
"""Displays a dialog showing the status of loaded plugins""" """Displays a dialog showing the status of loaded plugins"""
def __init__(self, state, uistate, track=[]): def __init__(self, uistate, track=[]):
self.__uistate = uistate
self.title = _("Plugin Status") self.title = _("Plugin Status")
ManagedWindow.ManagedWindow.__init__(self,uistate,track,self.__class__) ManagedWindow.ManagedWindow.__init__(self, uistate, track,
self.__class__)
self.set_window(gtk.Dialog("", uistate.window, self.set_window(gtk.Dialog("", uistate.window,
gtk.DIALOG_DESTROY_WITH_PARENT, gtk.DIALOG_DESTROY_WITH_PARENT,
@ -88,8 +89,19 @@ class PluginStatus(ManagedWindow.ManagedWindow):
scrolled_window.add(self.list) scrolled_window.add(self.list)
self.window.vbox.add(scrolled_window) self.window.vbox.add(scrolled_window)
self.window.show_all()
if __debug__:
# Only show the "Reload" button when in debug mode
# (without -O on the command line)
self.__reload_btn = gtk.Button("Reload")
self.window.action_area.add(self.__reload_btn)
self.__reload_btn.connect('clicked', self.__reload)
self.window.show_all()
self.__populate_list()
def __populate_list(self):
""" Build the list of plugins """
for i in PluginMgr.failmsg_list: for i in PluginMgr.failmsg_list:
err = i[1][0] err = i[1][0]
@ -110,6 +122,7 @@ class PluginStatus(ManagedWindow.ManagedWindow):
i[0], descr, None]) i[0], descr, None])
def button_press(self, obj, event): def button_press(self, obj, event):
""" Callback function from the user clicking on a line """
if event.type == gtk.gdk._2BUTTON_PRESS and event.button == 1: if event.type == gtk.gdk._2BUTTON_PRESS and event.button == 1:
model, node = self.selection.get_selected() model, node = self.selection.get_selected()
data = model.get_value(node, 3) data = model.get_value(node, 3)
@ -118,7 +131,15 @@ class PluginStatus(ManagedWindow.ManagedWindow):
PluginTrace(self.uistate, self.track, data, name) PluginTrace(self.uistate, self.track, data, name)
def build_menu_names(self, obj): def build_menu_names(self, obj):
return ( _('Summary'),self.title) return (self.title, "")
def __reload(self, obj):
""" Callback function from the "Reload" button """
PluginMgr.reload_plugins()
self.__uistate.emit('plugins-reloaded',
(PluginMgr.tool_list, PluginMgr.report_list))
self.model.clear()
self.__populate_list()
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
@ -266,7 +287,8 @@ class ToolManagedWindowBase(ManagedWindow.ManagedWindow):
iter = view.get_iter_at_location(*buffer_location) iter = view.get_iter_at_location(*buffer_location)
for (tag, person_handle) in self.tags: for (tag, person_handle) in self.tags:
if iter.has_tag(tag): if iter.has_tag(tag):
view.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(self.link_cursor) _window = view.get_window(gtk.TEXT_WINDOW_TEXT)
_window.set_cursor(self.link_cursor)
return False # handle event further, if necessary return False # handle event further, if necessary
view.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(self.standard_cursor) view.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(self.standard_cursor)
return False # handle event further, if necessary return False # handle event further, if necessary

View File

@ -41,9 +41,6 @@ from gtk import glade
# Standard Python modules # Standard Python modules
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
import os
import sys
import re
from gettext import gettext as _ from gettext import gettext as _
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
@ -52,12 +49,9 @@ from gettext import gettext as _
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
import const import const
import Config
import Errors
from ReportBase import report, standalone_categories from ReportBase import report, standalone_categories
import _Tool import _Tool
import _PluginMgr import _PluginMgr
import _PluginWindows
import ManagedWindow import ManagedWindow
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
@ -74,7 +68,6 @@ UNSUPPORTED = _("Unsupported")
# PluginDialog interface class # PluginDialog interface class
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
class PluginDialog(ManagedWindow.ManagedWindow): class PluginDialog(ManagedWindow.ManagedWindow):
"""Displays the dialog box that allows the user to select the """Displays the dialog box that allows the user to select the
report that is desired.""" report that is desired."""
@ -130,9 +123,9 @@ class PluginDialog(ManagedWindow.ManagedWindow):
self.apply_button.set_use_underline(True) self.apply_button.set_use_underline(True)
if tool_tip: if tool_tip:
try: try:
tt = gtk.tooltips_data_get(self.apply_button) tttips = gtk.tooltips_data_get(self.apply_button)
if tt: if tttips:
tt[0].set_tip(self.apply_button,tool_tip) tttips[0].set_tip(self.apply_button, tool_tip)
except AttributeError: except AttributeError:
pass pass
@ -155,7 +148,8 @@ class PluginDialog(ManagedWindow.ManagedWindow):
name, require_active) = self.item name, require_active) = self.item
if self.content == REPORTS: if self.content == REPORTS:
report(self.state, self.uistate, self.state.active, report(self.state, self.uistate, self.state.active,
item_class, options_class,title, name,category,require_active) item_class, options_class, title, name,
category, require_active)
else: else:
_Tool.gui_tool(self.state, self.uistate, _Tool.gui_tool(self.state, self.uistate,
item_class, options_class,title, name,category, item_class, options_class,title, name,category,
@ -308,115 +302,3 @@ class ToolPlugins(PluginDialog):
def rebuild(self, tool_list, report_list): def rebuild(self, tool_list, report_list):
self.build_plugin_tree(tool_list, _Tool.tool_categories) self.build_plugin_tree(tool_list, _Tool.tool_categories)
#-------------------------------------------------------------------------
#
# Reload plugins
#
#-------------------------------------------------------------------------
class Reload(_Tool.Tool):
def __init__(self, dbstate, uistate, options_class, name, callback=None):
"""
Treated as a callback, causes all plugins to get reloaded.
This is useful when writing and debugging a plugin.
"""
_Tool.Tool.__init__(self,dbstate, options_class, name)
pymod = re.compile(r"^(.*)\.py$")
oldfailmsg = _PluginMgr.failmsg_list[:]
_PluginMgr.failmsg_list = []
# attempt to reload all plugins that have succeeded in the past
for plugin in _PluginMgr.success_list:
filename = plugin[0]
filename = filename.replace('pyc','py')
filename = filename.replace('pyo','py')
try:
reload(plugin[1])
except:
_PluginMgr.failmsg_list.append((filename,sys.exc_info()))
# Remove previously good plugins that are now bad
# from the registered lists
_PluginMgr.purge_failed()
# attempt to load the plugins that have failed in the past
for (filename,message) in oldfailmsg:
name = os.path.split(filename)
match = pymod.match(name[1])
if not match:
continue
_PluginMgr.attempt_list.append(filename)
plugin = match.groups()[0]
try:
# For some strange reason second importing of a failed plugin
# results in success. Then reload reveals the actual error.
# Looks like a bug in Python.
a = __import__(plugin)
reload(a)
_PluginMgr.success_list.append((filename,a))
except:
_PluginMgr.failmsg_list.append((filename,sys.exc_info()))
# attempt to load any new files found
for directory in _PluginMgr.loaddir_list:
for filename in os.listdir(directory):
name = os.path.split(filename)
match = pymod.match(name[1])
if not match:
continue
if filename in _PluginMgr.attempt_list:
continue
_PluginMgr.attempt_list.append(filename)
plugin = match.groups()[0]
try:
a = __import__(plugin)
if a not in [plugin[1]
for plugin in _PluginMgr.success_list]:
_PluginMgr.success_list.append((filename,a))
except:
_PluginMgr.failmsg_list.append((filename,sys.exc_info()))
if Config.get(Config.POP_PLUGIN_STATUS) \
and len(_PluginMgr.failmsg_list):
try:
_PluginWindows.PluginStatus(dbstate,uistate)
except Errors.WindowActiveError:
old_win = uistate.gwm.get_item_from_id(
_PluginWindows.PluginStatus)
old_win.close()
_PluginWindows.PluginStatus(dbstate,uistate)
# Emit signal to re-generate tool and report menus
uistate.emit('plugins-reloaded',
(_PluginMgr.tool_list,_PluginMgr.report_list))
class ReloadOptions(_Tool.ToolOptions):
"""
Defines options and provides handling interface.
"""
def __init__(self, name,person_id=None):
_Tool.ToolOptions.__init__(self, name,person_id)
#-------------------------------------------------------------------------
#
# Register the plugin reloading tool
#
#-------------------------------------------------------------------------
if __debug__:
_PluginMgr.register_tool(
name = 'reload',
category = _Tool.TOOL_DEBUG,
tool_class = Reload,
options_class = ReloadOptions,
modes = _Tool.MODE_GUI,
translated_name = _("Reload Plugins"),
status=(_("Stable")),
author_name = "Donald N. Allingham",
author_email = "don@gramps-project.org",
description=_("Attempt to reload plugins. "
"Note: This tool itself is not reloaded!"),
)

View File

@ -402,7 +402,7 @@ class ViewManager:
('About', gtk.STOCK_ABOUT, _('_About'), None, None, ('About', gtk.STOCK_ABOUT, _('_About'), None, None,
display_about_box), display_about_box),
('PluginStatus', None, _('_Plugin Status'), None, None, ('PluginStatus', None, _('_Plugin Status'), None, None,
self.plugin_status), self.__plugin_status),
('FAQ', None, _('_FAQ'), None, None, faq_activate), ('FAQ', None, _('_FAQ'), None, None, faq_activate),
('KeyBindings', None, _('_Key Bindings'), None, None, key_bindings), ('KeyBindings', None, _('_Key Bindings'), None, None, key_bindings),
('UserManual', gtk.STOCK_HELP, _('_User Manual'), 'F1', None, ('UserManual', gtk.STOCK_HELP, _('_User Manual'), 'F1', None,
@ -607,14 +607,8 @@ class ViewManager:
error |= load_plugins(const.USER_PLUGINS) error |= load_plugins(const.USER_PLUGINS)
# get to ssee if we need to open the plugin status window # get to ssee if we need to open the plugin status window
if Config.get(Config.POP_PLUGIN_STATUS) and error: if error and Config.get(Config.POP_PLUGIN_STATUS):
try: self.__plugin_status()
PluginWindows.PluginStatus(self.state, self.uistate, [])
except Errors.WindowActiveError:
old_win = self.uistate.gwm.get_item_from_id(
PluginWindows.PluginStatus)
old_win.close()
PluginWindows.PluginStatus(self.state, self.uistate, [])
self.uistate.push_message(self.state, _('Ready')) self.uistate.push_message(self.state, _('Ready'))
@ -734,17 +728,17 @@ class ViewManager:
import TipOfDay import TipOfDay
TipOfDay.TipOfDay(self.uistate) TipOfDay.TipOfDay(self.uistate)
def plugin_status(self, obj): def __plugin_status(self, obj=None):
""" """
Display plugin status dialog Display plugin status dialog
""" """
try: try:
PluginWindows.PluginStatus(self.state, self.uistate, []) PluginWindows.PluginStatus(self.uistate, [])
except Errors.WindowActiveError: except Errors.WindowActiveError:
old_win = self.uistate.gwm.get_item_from_id( old_win = self.uistate.gwm.get_item_from_id(
PluginWindows.PluginStatus) PluginWindows.PluginStatus)
old_win.close() old_win.close()
PluginWindows.PluginStatus(self.state, self.uistate, []) PluginWindows.PluginStatus(self.uistate, [])
def sidebar_toggle(self, obj): def sidebar_toggle(self, obj):
""" """