|
From: <zk...@us...> - 2010-05-22 12:34:37
|
Revision: 678
http://pyphant.svn.sourceforge.net/pyphant/?rev=678&view=rev
Author: zklaus
Date: 2010-05-22 12:34:31 +0000 (Sat, 22 May 2010)
Log Message:
-----------
Merge branch 'master' into svn-trunk
* master:
Enh: Auto index rebuilding
Fix: global exception handling
Modified Paths:
--------------
trunk/src/pyphant/pyphant/core/KnowledgeManager.py
trunk/src/pyphant/pyphant/core/KnowledgeNode.py
trunk/src/pyphant/pyphant/core/SQLiteWrapper.py
trunk/src/pyphant/pyphant/wxgui2/PyphantCanvas.py
trunk/src/pyphant/pyphant/wxgui2/wxPyphantApplication.py
Modified: trunk/src/pyphant/pyphant/core/KnowledgeManager.py
===================================================================
--- trunk/src/pyphant/pyphant/core/KnowledgeManager.py 2010-04-19 18:15:08 UTC (rev 677)
+++ trunk/src/pyphant/pyphant/core/KnowledgeManager.py 2010-05-22 12:34:31 UTC (rev 678)
@@ -161,8 +161,6 @@
else:
self.dbase = KM_DBASE
self.any_value = AnyValue()
- with SQLiteWrapper(self.dbase) as wrapper:
- wrapper.setup_dbase()
self.node = None # for hooking up a KnowledgeNode
self.uuid = uuid1().urn
tmpdir = getPyphantPath(os.path.join(KM_PATH, 'tmp'))
@@ -172,7 +170,51 @@
rmtree(tmpdir)
except OSError:
self.logger.warn("Could not delete '%s'." % tmpdir)
+ with SQLiteWrapper(self.dbase) as wrapper:
+ rebuild = wrapper.dbase_broken()
+ if rebuild:
+ self.logger.info("dbase needs rebuild")
+ self.rebuildIndex()
+ else:
+ with SQLiteWrapper(self.dbase) as wrapper:
+ wrapper.setup_sqlite()
+ def rebuildIndex(self):
+ self.logger.info("rebuilding dbase...")
+ oldname = self.dbase + ".bak"
+ if os.path.exists(oldname):
+ os.remove(oldname)
+ os.rename(self.dbase, oldname)
+ with SQLiteWrapper(self.dbase) as wrapper:
+ wrapper.setup_dbase()
+ self.updateIndex()
+ self.logger.info("done rebuilding dbase")
+
+ def updateIndex(self):
+ file_list = []
+ def accumulate_files(flist, directory, files):
+ for fname in [afname for afname in files if afname.endswith('.h5')]:
+ flist.append(os.path.realpath(os.path.join(directory, fname)))
+ os.path.walk(getPyphantPath(KM_PATH), accumulate_files, file_list)
+ from wx import (ProgressDialog, PyNoAppError)
+ try:
+ pdial = ProgressDialog('Rebuilding index...', ' ' * 100,
+ maximum=len(file_list))
+ except PyNoAppError:
+ pdial = None
+ count = 1
+ for realname in file_list:
+ if pdial is not None:
+ pdial.Update(count, os.path.basename(realname))
+ count += 1
+ try:
+ self.registerH5(realname)
+ except:
+ self.logger.warn("Could not extract meta data from '%s'."\
+ % realname)
+ if pdial is not None:
+ pdial.Destroy()
+
def hasDataContainer(self, dcid):
"""
Returns whether the given DC is stored locally.
Modified: trunk/src/pyphant/pyphant/core/KnowledgeNode.py
===================================================================
--- trunk/src/pyphant/pyphant/core/KnowledgeNode.py 2010-04-19 18:15:08 UTC (rev 677)
+++ trunk/src/pyphant/pyphant/core/KnowledgeNode.py 2010-05-22 12:34:31 UTC (rev 678)
@@ -228,7 +228,7 @@
try:
columns = [('host', 'TEXT'), ('port', 'INT'), ('status', 'INT'),
('', 'UNIQUE(host, port)')]
- create_table('kn_remotes', columns, cursor)
+ create_table('kn_remotes', columns, cursor, ignore_exists=True)
cursor.execute("SELECT * FROM kn_remotes")
self.remotes = [RemoteKN(host, port, status) \
for host, port, status in cursor]
Modified: trunk/src/pyphant/pyphant/core/SQLiteWrapper.py
===================================================================
--- trunk/src/pyphant/pyphant/core/SQLiteWrapper.py 2010-04-19 18:15:08 UTC (rev 677)
+++ trunk/src/pyphant/pyphant/core/SQLiteWrapper.py 2010-05-22 12:34:31 UTC (rev 678)
@@ -45,6 +45,8 @@
from pyphant.quantities import (Quantity,PhysicalUnit,_base_units)
from types import (FloatType, IntType, LongType, StringTypes)
+DBASE_VERSION = 1 #increment if there have been structural changes to the dbase!
+
def quantity2powers(quantity):
numberOfBaseUnits = len(_base_units)
if isinstance(quantity, Quantity):
@@ -142,8 +144,11 @@
wc += ')'
return wc
-def create_table(table_name, columns, cursor):
- query = "CREATE TABLE IF NOT EXISTS %s (" % (table_name, )
+def create_table(table_name, columns, cursor, ignore_exists=False):
+ if ignore_exists:
+ query = "CREATE TABLE IF NOT EXISTS %s (" % (table_name, )
+ else:
+ query = "CREATE TABLE %s (" % (table_name, )
for name, type in columns:
query += name + " " + type + ", "
query = query[:-2] + ")"
@@ -151,7 +156,7 @@
def create_trigger(trigger_name, action, table_name,
statements, cursor):
- query = "CREATE TRIGGER IF NOT EXISTS %s AFTER %s ON %s "\
+ query = "CREATE TRIGGER %s AFTER %s ON %s "\
"FOR EACH ROW BEGIN %s END"
st_query = ''
for st in statements:
@@ -227,9 +232,13 @@
return SCRowWrapper(emd5, self.cursor)
raise KeyError(emd5)
- def setup_dbase(self):
+ def setup_sqlite(self):
sqlite3.register_converter('QUANTITY', dbase2quantity)
sqlite3.register_converter('LATEX', dbase2latex)
+ #clean tmp:
+ self.cursor.execute("DELETE FROM km_temporary")
+
+ def setup_dbase(self):
#create tables:
columns = [('sc_id', 'TEXT PRIMARY KEY UNIQUE NOT NULL'),
('longname', 'TEXT'),
@@ -279,6 +288,10 @@
('bit', 'INT'),
('', 'UNIQUE(m, g, s, A, K, mol, cd, rad, sr, EUR,bit)')]
create_table('km_base_units', columns, self.cursor)
+ columns = [('version', 'INT')]
+ create_table('db_info', columns, self.cursor)
+ self.cursor.execute("INSERT INTO db_info (version) VALUES (?)",
+ (DBASE_VERSION, ))
#create triggers:
create_trigger('trigger_del_fc', 'DELETE', 'km_fc',
['DELETE FROM km_attributes WHERE dc_id=OLD.fc_id',
@@ -292,9 +305,16 @@
['DELETE FROM km_fc WHERE fc_id=OLD.dc_id',
'DELETE FROM km_sc WHERE sc_id=OLD.dc_id'],
self.cursor)
- #clean tmp:
- self.cursor.execute("DELETE FROM km_temporary")
+ self.setup_sqlite()
+ def dbase_broken(self):
+ try:
+ self.cursor.execute("SELECT version FROM db_info")
+ version = self.cursor.fetchone()[0]
+ return version is not DBASE_VERSION
+ except sqlite3.OperationalError:
+ return True
+
def has_entry(self, id):
exe = self.cursor.execute
if id == 'IndexMarker':
Modified: trunk/src/pyphant/pyphant/wxgui2/PyphantCanvas.py
===================================================================
--- trunk/src/pyphant/pyphant/wxgui2/PyphantCanvas.py 2010-04-19 18:15:08 UTC (rev 677)
+++ trunk/src/pyphant/pyphant/wxgui2/PyphantCanvas.py 2010-05-22 12:34:31 UTC (rev 678)
@@ -46,7 +46,7 @@
class PyphantCanvas(sogl.ShapeCanvas):
def __init__(self,parent,recipe=CompositeWorker.CompositeWorker(), id=-1,pos=wx.DefaultPosition,
- size=wx.DefaultSize,style=wx.SUNKEN_BORDER,name="PyphantCanvas"):
+ size=wx.DefaultSize,style=wx.NO_BORDER,name="PyphantCanvas"):
sogl.ShapeCanvas.__init__(self,parent, id, pos, size, style, name)
#self.SetVirtualSize((1100,1000))
self.SetScrollRate(20,20)
Modified: trunk/src/pyphant/pyphant/wxgui2/wxPyphantApplication.py
===================================================================
--- trunk/src/pyphant/pyphant/wxgui2/wxPyphantApplication.py 2010-04-19 18:15:08 UTC (rev 677)
+++ trunk/src/pyphant/pyphant/wxgui2/wxPyphantApplication.py 2010-05-22 12:34:31 UTC (rev 678)
@@ -41,6 +41,7 @@
from pyphant.core.Helpers import getPyphantPath
LOGDIR = getPyphantPath()
import logging
+import logging.handlers
# logging.basicConfig(level=logging.DEBUG)
#else:
logging.basicConfig(level=logging.DEBUG,
@@ -50,10 +51,13 @@
"d:%(module)s.%(funcName)s(l %(lineno)d):%(message)s")
console = logging.StreamHandler()
console.setLevel(logging.WARNING)
+logbuffer = logging.handlers.MemoryHandler(1000)
logging.getLogger('').addHandler(console)
+logging.getLogger('').addHandler(logbuffer)
import sys
import wx
+import wx.aui
import sogl
import pyphant.wxgui2.paramvisualization.ParamVisReg as ParamVisReg
import pyphant.core.PyTablesPersister
@@ -74,7 +78,6 @@
if not wx.PySimpleApp.OnInit(self):
return False
self._logger = logging.getLogger("pyphant")
- self._excframe = wx.Frame(None, -2, "")
sys.excepthook = self.excepthook
sogl.SOGLInitialize()
self._knowledgeNode = None
@@ -87,16 +90,6 @@
self._logger.debug(u"An unhandled exception occured.",
exc_info=(type, value, trace))
sys.__excepthook__(type, value, trace)
- try:
- cpt = type.__name__
- #import traceback
- #traceStr = ''.join(traceback.format_exception(type, value, trace))
- msg = "Additional information:\n%s\n\n" % value
- dlg = wx.MessageDialog(self._excframe, msg, cpt, wx.OK)
- dlg.ShowModal()
- except:
- # avoid loop if displaying error message fails
- self._logger.debug(u"Failed to display error message in wxPyphant.")
def getMainFrame(self):
return self._frame
@@ -120,6 +113,8 @@
ID_WINDOW_BOTTOM = 103
ID_CLOSE_COMPOSITE_WORKER = wx.NewId()
ID_UPDATE_PYPHANT = wx.NewId()
+ ID_VIEW_WORKERREP = wx.NewId()
+ ID_VIEW_LOGFILE = wx.NewId()
def __init__(self, _wxPyphantApp):
wx.Frame.__init__(self, None, -1, "wxPyphant %s" % __version__,
@@ -131,11 +126,12 @@
self._initSash()
self.recipeState = None
self.onOpenCompositeWorker(None)
+ self._initAui()
self._workerRepository.Bind(wx.EVT_SASH_DRAGGED_RANGE,
self.onFoldPanelBarDrag,
id=self.ID_WINDOW_TOP,
id2=self.ID_WINDOW_BOTTOM)
- self.Bind(wx.EVT_SIZE, self.onSize)
+ #self.Bind(wx.EVT_SIZE, self.onSize)
self.compositeWorkerStack = []
wx.MessageBox("Located log directory at %s.\n"
"Logging will go to %s." %
@@ -144,15 +140,53 @@
def _initSash(self):
self._workerRepository = wx.SashLayoutWindow(
- self, self.ID_WINDOW_RIGHT, wx.DefaultPosition, wx.Size(200,1000),
- wx.NO_BORDER | wx.SW_3D | wx.CLIP_CHILDREN)
- self._workerRepository.SetDefaultSize(wx.Size(220,1000))
- self._workerRepository.SetOrientation(wx.LAYOUT_VERTICAL)
- self._workerRepository.SetAlignment(wx.LAYOUT_RIGHT)
- self._workerRepository.SetSashVisible(wx.SASH_LEFT, True)
- self._workerRepository.SetExtraBorderSize(10)
+ self, self.ID_WINDOW_RIGHT, wx.DefaultPosition, wx.Size(220,1000),
+ wx.NO_BORDER)
+ #self._workerRepository.SetDefaultSize(wx.Size(220,1000))
+ #self._workerRepository.SetOrientation(wx.LAYOUT_VERTICAL)
+ #self._workerRepository.SetAlignment(wx.LAYOUT_RIGHT)
+ #self._workerRepository.SetSashVisible(wx.SASH_LEFT, True)
+ #self._workerRepository.SetExtraBorderSize(10)
WorkerRepository.WorkerRepository(self._workerRepository)
+ def _initAui(self):
+ self._auiManager = wx.aui.AuiManager(self)
+ class ClickableText(wx.TextCtrl):
+ def __init__(self, *args, **kwargs):
+ wx.TextCtrl.__init__(self, *args, **kwargs)
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnClick)
+ def OnClick(self, event):
+ logbuffer.flush()
+ event.Skip()
+ self._logpane = ClickableText(self, -1, "",
+ wx.DefaultPosition, wx.Size(640, 200),
+ wx.NO_BORDER | wx.TE_MULTILINE \
+ | wx.TE_READONLY)
+ class WxHandler(logging.Handler):
+ def __init__(self, ctrl):
+ logging.Handler.__init__(self)
+ self.ctrl = ctrl
+ def emit(self, record):
+ try:
+ self.ctrl.AppendText(self.format(record) + "\n")
+ except wx.PyDeadObjectError:
+ pass
+ handler = WxHandler(self._logpane)
+ handler.setFormatter(logging.Formatter(
+ "%(asctime)s - %(levelname)s:%(name)s:%(thread)"\
+ "d:%(module)s.%(funcName)s(l %(lineno)d):%(message)s"))
+ logbuffer.setTarget(handler)
+ logbuffer.flush()
+ self._auiManager.AddPane(self._logpane, wx.BOTTOM, 'Logfile '\
+ '(click into text to update)')
+ self._auiManager.AddPane(self._workerRepository, wx.RIGHT,
+ 'Worker Repository')
+ self._auiManager.AddPane(self._remainingSpace, wx.CENTER, 'Main')
+ wrpane = self._auiManager.GetPane(self._workerRepository)
+ wrpane.Floatable(False)
+ wrpane.Movable(False)
+ self._auiManager.Update()
+
def onSize(self, event):
wx.LayoutAlgorithm().LayoutWindow(self,self._remainingSpace)
event.Skip()
@@ -164,7 +198,7 @@
self._workerRepository.SetDefaultSize(
wx.Size(event.GetDragRect().width, 1000))
# Leaves bits of itself behind sometimes
- wx.LayoutAlgorithm().LayoutWindow(self, self._remainingSpace)
+ #wx.LayoutAlgorithm().LayoutWindow(self, self._remainingSpace)
self._remainingSpace.Refresh()
event.Skip()
@@ -195,16 +229,24 @@
self._wxPyphantApp.pathToRecipe = path
dlg.Destroy()
import PyphantCanvas
- if self._wxPyphantApp.pathToRecipe[-3:] == '.h5':
- if os.path.exists(self._wxPyphantApp.pathToRecipe):
- recipe = pyphant.core.PyTablesPersister.loadRecipeFromHDF5File(
- self._wxPyphantApp.pathToRecipe)
- self._remainingSpace = PyphantCanvas.PyphantCanvas(self, recipe)
+ try:
+ if self._wxPyphantApp.pathToRecipe[-3:] == '.h5':
+ if os.path.exists(self._wxPyphantApp.pathToRecipe):
+ recipe = pyphant.core.PyTablesPersister.loadRecipeFromHDF5File(
+ self._wxPyphantApp.pathToRecipe)
+ self._remainingSpace = PyphantCanvas.PyphantCanvas(self, recipe)
+ else:
+ self._remainingSpace = PyphantCanvas.PyphantCanvas(self)
else:
- self._remainingSpace = PyphantCanvas.PyphantCanvas(self)
- else:
- raise IOError("Unknown file format in file \"%\""\
- % self._wxPyphantApp.pathToRecipe)
+ raise IOError('Unknown file format in file "%s"'\
+ % self._wxPyphantApp.pathToRecipe)
+ except:
+ wx.MessageBox("An error has occurred while opening "\
+ "the recipe.\nPlease investigate the logfile "\
+ "for further details.\nThe logfile is located at %s"\
+ % os.path.join(LOGDIR, 'pyphant.log'),
+ "Recipe broken, unknown format or outdated!")
+ raise
self.recipeState = 'clean'
self._remainingSpace.diagram.recipe.registerListener(self.recipeChanged)
@@ -257,6 +299,8 @@
"&Close Composite Worker")
self._updateMenu = self.createUpdateMenu()
self._menuBar.Append(self._updateMenu, "&Update")
+ self._viewMenu = self.createViewMenu()
+ self._menuBar.Append(self._viewMenu, "&View")
self.SetMenuBar(self._menuBar)
self._menuBar.EnableTop(1, False)
#self.Bind(wx.EVT_MENU, self.onCreateNew, id=wx.ID_NEW)
@@ -285,10 +329,28 @@
self.Bind(wx.EVT_MENU, self.onUpdatePyphant, id=nId)
return updateMenu
+ def createViewMenu(self):
+ viewMenu = wx.Menu()
+ viewMenu.Append(self.ID_VIEW_WORKERREP, "&Worker Repository")
+ viewMenu.Append(self.ID_VIEW_LOGFILE, "&Logfile")
+ self.Bind(wx.EVT_MENU, self.onWorkerRep, id=self.ID_VIEW_WORKERREP)
+ self.Bind(wx.EVT_MENU, self.onLogfile, id=self.ID_VIEW_LOGFILE)
+ return viewMenu
+
def onUpdatePyphant(self, event):
import pyphant.core.UpdateManager
pyphant.core.UpdateManager.updatePackage(self.updateIds[event.Id])
+ def onWorkerRep(self, event):
+ wrpane = self._auiManager.GetPane(self._workerRepository)
+ wrpane.Show(True)
+ self._auiManager.Update()
+
+ def onLogfile(self, event):
+ logpane = self._auiManager.GetPane(self._logpane)
+ logpane.Show(True)
+ self._auiManager.Update()
+
def onQuit(self,event):
self.Close()
@@ -309,7 +371,7 @@
self._wxPyphantApp._knowledgeNode.stop()
except AttributeError:
pass
- self._wxPyphantApp._excframe.Destroy()
+ self._auiManager.UnInit()
self.Destroy()
def editCompositeWorker(self, worker):
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|