[Yt-svn] yt-commit r474 - in trunk/yt: . raven reason

mturk at wrangler.dreamhost.com mturk at wrangler.dreamhost.com
Thu May 15 16:14:06 PDT 2008


Author: mturk
Date: Thu May 15 16:14:03 2008
New Revision: 474
URL: http://yt.spacepope.org/changeset/474

Log:
Some major changes to reason, which are not yet finished, but at least ready to
function...  I think.

 * The shell has been detached from the main window, and moved into a menu
item.
 * Logging now goes to the main window.  (Repaint issues though.)
 * PyCrust has been utilized to allow for editing and running scripts inline,
modifying and interacting with the local namespace.

Also added a parameter for 'sphere' in the new threephase.



Added:
   trunk/yt/reason/LoggingSetup.py
Modified:
   trunk/yt/logger.py
   trunk/yt/raven/PlotCollection.py
   trunk/yt/reason/App.py
   trunk/yt/reason/Windows.py
   trunk/yt/reason/__init__.py

Modified: trunk/yt/logger.py
==============================================================================
--- trunk/yt/logger.py	(original)
+++ trunk/yt/logger.py	Thu May 15 16:14:03 2008
@@ -95,7 +95,11 @@
         reasonHandler.setFormatter(f)
         reasonLogger.addHandler(reasonHandler)
 
-if ytcfg.getboolean("yt","suppressStreamLogging"):
+def disable_stream_logging():
     # We just remove the root logger's handlers
     for handler in rootLogger.handlers:
-        handler.disabled = 1
+        if isinstance(handler, logging.StreamHandler):
+            rootLogger.removeHandler(handler)
+
+if ytcfg.getboolean("yt","suppressStreamLogging"):
+    disable_stream_logging()

Modified: trunk/yt/raven/PlotCollection.py
==============================================================================
--- trunk/yt/raven/PlotCollection.py	(original)
+++ trunk/yt/raven/PlotCollection.py	Thu May 15 16:14:03 2008
@@ -173,11 +173,12 @@
                                   weight="CellMassMsun", accumulation=False,
                                   x_bins=64, x_log=True, x_bounds=None,
                                   y_bins=64, y_log=True, y_bounds=None,
-                                  lazy_reader=False):
+                                  lazy_reader=False, sphere = None):
         if center == None:
             center = self.c
         r = radius/self.pf[unit]
-        sphere = self.pf.hierarchy.sphere(center, r, fields)
+        if sphere is None:
+            sphere = self.pf.hierarchy.sphere(center, r, fields)
         if x_bounds is None:
             x_min, x_max = sphere[fields[0]].min(), sphere[fields[0]].max()
         else:

Modified: trunk/yt/reason/App.py
==============================================================================
--- trunk/yt/reason/App.py	(original)
+++ trunk/yt/reason/App.py	Thu May 15 16:14:03 2008
@@ -81,8 +81,11 @@
                        'windows':self.windows,
                        'mainwindow':self,
                        'data_objects':self.data_objects}
+        wx.py.buffer.Buffer.updateNamespace = \
+                get_new_updateNamespace(self.locals)
         self.int_panel = wx.Panel(self.main_splitter, -1)
-        self.interpreter = ReasonInterpreterPanel(self.int_panel, -1, self.locals)
+        #self.interpreter = ReasonInterpreterPanel(self.int_panel, -1, self.locals)
+        self.interpreter = LoggingWindowBox(self.int_panel, -1)
 
     def __setup_menubar(self):
         menu_bar = wx.MenuBar()
@@ -93,12 +96,16 @@
 
         open_hierarchy = file_menu.Append(-1, "Open Hierarchy")
         field_inspector = file_menu.Append(-1, "Inspect Fields")
+        open_shell = file_menu.Append(-1, "Open Shell")
+        open_editor = file_menu.Append(-1, "Open Editor")
         save_image = file_menu.Append(-1, "Save Image")
         file_menu.AppendSeparator()
         exit = file_menu.Append(-1, "Exit")
 
         self.Bind(wx.EVT_MENU, self.OnOpenHierarchy, open_hierarchy)
         self.Bind(wx.EVT_MENU, self.OnInspectFields, field_inspector)
+        self.Bind(wx.EVT_MENU, self.OnOpenShell, open_shell)
+        self.Bind(wx.EVT_MENU, self.OnOpenEditor, open_editor)
         self.Bind(wx.EVT_MENU, self.OnSaveImage, save_image)
         self.Bind(wx.EVT_MENU, self.OnExit, exit)
 
@@ -258,7 +265,7 @@
 
     def _add_phase(self, event=None):
         MyID = wx.NewId()
-        self.interpreter.shell.writeOut("\n")
+#        self.interpreter.shell.writeOut("\n")
         o = self.get_output()
         t = "Phase Plot"
         self.windows.append( \
@@ -267,21 +274,21 @@
                           dataObject = o,
                           CreationID = MyID,
                           mw = self))
-        self.interpreter.shell.writeOut("Adding phase plot\n")
+#        self.interpreter.shell.writeOut("Adding phase plot\n")
         self.plot_panel.AddPlot(self.windows[-1], t, MyID)
         mylog.debug("Adding with ID: %s", MyID)
-        self.interpreter.shell.push("\n")
+#        self.interpreter.shell.push("\n")
 
     def _add_proj(self, event=None):
         MyID = wx.NewId()
-        self.interpreter.shell.writeOut("\n")
+#        self.interpreter.shell.writeOut("\n")
         o = self.get_output()
         field = "Density"
         width = 1.0
         unit = "1"
         for i, ax in zip(range(3), 'xyz'):
             t = "%s - Projection - %s" % (o.basename, ax)
-            self.interpreter.shell.writeOut("Adding %s projection of %s\n" % (ax, o))
+#            self.interpreter.shell.writeOut("Adding %s projection of %s\n" % (ax, o))
             self.windows.append( \
                 ProjPlotPage(parent=self.plot_panel.nb,
                               status_bar=self.status_bar,
@@ -295,18 +302,20 @@
                                _ProjObjectMenuItems)
             print "Adding with ID:", MyID
         for w in self.windows[-3:]: w.ChangeWidth(1,'1')
-        self.interpreter.shell.push("\n")
+#        self.interpreter.shell.push("\n")
 
     def _add_slice(self, event=None):
+        wx.SafeYield()
         MyID = wx.NewId()
-        self.interpreter.shell.writeOut("\n")
+#        self.interpreter.shell.writeOut("\n")
         o = self.get_output()
         field = "Density"
         width = 1.0
         unit = "1"
         for i, ax in zip(range(3), 'xyz'):
+            wx.Yield()
             t = "%s - Slice - %s" % (o.basename, ax)
-            self.interpreter.shell.writeOut("Adding %s slice of %s\n" % (ax, o))
+#            self.interpreter.shell.writeOut("Adding %s slice of %s\n" % (ax, o))
             self.windows.append( \
                 SlicePlotPage(parent=self.plot_panel.nb,
                               status_bar=self.status_bar,
@@ -320,7 +329,7 @@
                                _SliceObjectMenuItems)
             print "Adding with ID:", MyID
         for w in self.windows[-3:]: w.ChangeWidth(1,'1')
-        self.interpreter.shell.push("\n")
+#        self.interpreter.shell.push("\n")
 
     def get_output(self, event=None):
         # Figure out which outputs are selected
@@ -367,6 +376,18 @@
             #self.RefreshOutputs()
         dialog.Destroy()
 
+    def OnOpenEditor(self, event):
+        frame = ReasonEditorNotebookFrame(parent=self,
+                                          title="Editor")
+        frame.SetStatusText("Reason Shell")
+        frame.Show()
+        self.ff = frame
+
+    def OnOpenShell(self, event):
+        frame = wx.py.shell.ShellFrame(parent=self, locals=self.locals)
+        frame.SetStatusText("Reason Shell")
+        frame.Show()
+
     def OnSaveImage(self, event):
         pgI = self.plot_panel.nb.Selection
         pg = self.plot_panel.nb.GetPage(pgI)

Added: trunk/yt/reason/LoggingSetup.py
==============================================================================
--- (empty file)
+++ trunk/yt/reason/LoggingSetup.py	Thu May 15 16:14:03 2008
@@ -0,0 +1,138 @@
+"""
+Logging facilities for Reason
+
+ at author: U{Matthew Turk<http://www.stanford.edu/~mturk/>}
+ at organization: U{KIPAC<http://www-group.slac.stanford.edu/KIPAC/>}
+ at contact: U{mturk at slac.stanford.edu<mailto:mturk at slac.stanford.edu>}
+ at license:
+  Copyright (C) 2008 Matthew Turk.  All Rights Reserved.
+
+  This file is part of yt.
+
+  yt is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""
+
+from yt.reason import *
+
+import logging, sys
+import wx.lib.mixins.listctrl as listmix
+
+class LoggingListBox(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin):
+    def __init__(self, parent, dataSource):
+        wx.ListCtrl.__init__(self, parent,
+                             style=wx.LC_REPORT|wx.LC_SINGLE_SEL|wx.LC_VIRTUAL)
+        listmix.ListCtrlAutoWidthMixin.__init__(self)
+        columns = dataSource.GetColumnHeaders()
+        for col, text in enumerate(columns):
+            self.InsertColumn(col, text)
+        self.SetItemCount(dataSource.GetCount())
+        self.dataSource = dataSource
+
+    def UpdateCounts(self):
+        c = self.dataSource.GetCount()
+        self.SetItemCount(c)
+        self.EnsureVisible(c-1)
+        self.Refresh()
+
+    def OnGetItemText(self, item, col):
+        return self.dataSource.GetItem(item)[col]
+
+    def OnGetItemAttr(self, item): return None
+    def OnGetItemImage(self, item): return -1
+
+class LoggingWindowBox(wx.Panel):
+    def __init__(self, parent, id):
+        wx.Panel.__init__(self, parent, id)
+        self.__redirect_logging()
+        self.__setup_controls()
+        mylog.info("Welcome to Reason.")
+
+    def __setup_controls(self):
+        self.event_list = LoggingListBox(self, self.handler.output)
+        self.handler.setTextBox(self.event_list)
+        self.sizer = wx.BoxSizer(wx.VERTICAL)
+        self.sizer.Add(self.event_list, 1, wx.EXPAND)
+        self.SetSizer(self.sizer)
+        self.Fit()
+
+    def __redirect_logging(self):
+        yt.logger.disable_stream_logging()
+        self.handler = OutputWindowStream()
+        self.handler.setFormatter(logging.Formatter(yt.logger.fstring))
+        yt.logger.rootLogger.addHandler(self.handler)
+
+class OutputWindowStream(logging.Handler):
+    # Shamelessly borrowed from:
+    #   http://lists.wxwidgets.org/pipermail/wxpython-users/2007-October/069288.html
+    def __init__(self):
+        logging.Handler.__init__(self)
+        self.output = LoggingDataSource()
+        self.buffer = []
+        self.events = []
+
+    def setTextBox(self, textbox):
+        """
+        textbox presents the instance of textctrl in the mainframe
+        Method is called after frame is up and running
+        """
+        self.textbox = textbox
+
+    def shouldFlush(self):
+        if self.textbox:
+            return True
+        else:
+            return False
+
+    def emit(self, record):
+        self.buffer.append(record)
+        if self.shouldFlush():
+            self.flush()
+
+    def flush(self):
+        """
+        Thread safe flush method which schedule the
+        textbox update after a wx main loop ends
+        """
+        for record in self.buffer:
+            self.format(record)
+            wx.CallAfter(self.output.AppendItem, record)
+            wx.CallAfter(self.textbox.UpdateCounts)
+            wx.CallAfter(wx.YieldIfNeeded)
+        self.buffer = []
+
+    def close(self):
+        self.flush()
+        self.textbox = None
+        logging.Handler.close(self)
+
+class LoggingDataSource(object):
+    cols = ("Component","Level","Time","Message")
+    attrs = ("name","levelname","asctime","message")
+    def __init__(self):
+        self.records = []
+
+    def GetColumnHeaders(self):
+        return self.cols
+
+    def GetCount(self):
+        return len(self.records)
+
+    def GetItem(self, index):
+        return [getattr(self.records[index],att) for att in self.attrs]
+
+    def UpdateCache(self, start, end):
+        pass
+
+    def AppendItem(self, rec):
+        self.records.append(rec)
\ No newline at end of file

Modified: trunk/yt/reason/Windows.py
==============================================================================
--- trunk/yt/reason/Windows.py	(original)
+++ trunk/yt/reason/Windows.py	Thu May 15 16:14:03 2008
@@ -37,6 +37,7 @@
         self.SetSizer(self.sizer)
         self.Fit()
 
+
 def ChooseField(page):
     allFields = page.QueryFields()
     toChoose = nativeFields + [''] + derivedFields
@@ -184,3 +185,64 @@
 
         self.SetSizer(self.MainSizer)
         self.Layout()
+
+def get_new_updateNamespace(my_locals):
+    def updateNamespace(self):
+        """Update the namespace for autocompletion and calltips.
+
+        Return True if updated, False if there was an error."""
+        if not self.interp or not hasattr(self.editor, 'getText'):
+            return False
+        syspath = sys.path
+        sys.path = self.syspath
+        text = self.editor.getText()
+        text = text.replace('\r\n', '\n')
+        text = text.replace('\r', '\n')
+        name = self.modulename or self.name
+        try:
+            try:
+                code = compile(text, name, 'exec')
+            except:
+                raise
+            try:
+                exec code in my_locals
+            except:
+                raise
+        finally:
+            sys.path = syspath
+            for m in sys.modules.keys():
+                if m not in self.modules:
+                    del sys.modules[m]
+    return updateNamespace
+
+
+class ReasonEditorNotebookFrame(wx.py.editor.EditorNotebookFrame):
+
+    def _setup(self):
+        """Setup prior to first buffer creation.
+        Called automatically by base class during init.
+
+        Mostly taken from the wx.py.editor source.
+        """
+        self.notebook = wx.py.editor.EditorNotebook(parent=self)
+        intro = 'Reason 0.3'
+        if hasattr(self.Parent, 'locals'):
+            namespace = self.Parent.locals
+        else:
+            import imp
+            module = imp.new_module('__main__')
+            import __builtin__
+            module.__dict__['__builtins__'] = __builtin__
+            namespace = module.__dict__.copy()
+        self.crust = wx.py.crust.Crust(parent=self.notebook, intro=intro, locals=namespace)
+        self.shell = self.crust.shell
+        # Override the filling so that status messages go to the status bar.
+        self.crust.filling.tree.setStatusText = self.SetStatusText
+        # Override the shell so that status messages go to the status bar.
+        self.shell.setStatusText = self.SetStatusText
+        # Fix a problem with the sash shrinking to nothing.
+        self.crust.filling.SetSashPosition(40)
+        self.notebook.AddPage(page=self.crust, text='*Shell*', select=True)
+        self.setEditor(self.crust.editor)
+        self.crust.editor.SetFocus()
+        self.MenuBar.GetMenu(0).GetMenuItems()[11].SetText("Run Script")

Modified: trunk/yt/reason/__init__.py
==============================================================================
--- trunk/yt/reason/__init__.py	(original)
+++ trunk/yt/reason/__init__.py	Thu May 15 16:14:03 2008
@@ -25,7 +25,8 @@
 
 
 from yt.config import ytcfg
-from yt.logger import lagosLogger as mylog
+import yt.logger
+mylog = yt.logger.reasonLogger
 
 import yt.lagos as lagos
 import yt.raven as raven
@@ -43,10 +44,12 @@
 from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
 from matplotlib.backends.backend_agg import FigureCanvasAgg
 import wx, wx.py, wx.aui
+import wx.lib.mixins.listctrl as listmix
 from wx.lib.pubsub import Publisher
 import matplotlib.backends.backend_wx as be_wx
 import matplotlib.figure
 
+from LoggingSetup import *
 from Windows import *
 from Notebook import *
 from App import *



More information about the yt-svn mailing list