source: sasview/src/sas/sasgui/perspectives/calculator/pyconsole.py @ a62945e

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalccostrafo411magnetic_scattrelease-4.1.1release-4.1.2release-4.2.2release_4.0.1ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since a62945e was d85c194, checked in by Piotr Rozyczko <piotr.rozyczko@…>, 9 years ago

Remaining modules refactored

  • Property mode set to 100644
File size: 10.2 KB
RevLine 
[ec6c520]1"""
2Console Module display Python console
3"""
4import sys
[5d1c1f4]5import os
[fb58234]6import wx
[5d1c1f4]7import wx.lib.dialogs
[fb58234]8import wx.py.editor as editor
[5d1c1f4]9import wx.py.frame as frame
10import py_compile
11
[49ab5d7]12if sys.platform.count("win32") > 0:
[ec6c520]13    PANEL_WIDTH = 800
[7c8d3093]14    PANEL_HEIGHT = 700
[ec6c520]15    FONT_VARIANT = 0
16else:
17    PANEL_WIDTH = 830
[7c8d3093]18    PANEL_HEIGHT = 730
[ec6c520]19    FONT_VARIANT = 1
[49ab5d7]20ID_COMPILE = wx.NewId()
21ID_RUN = wx.NewId()
[5d1c1f4]22
23def compile_file(path):
24    """
25    Compile a python file
26    """
27    try:
28        import py_compile
29        py_compile.compile(file=path, doraise=True)
30    except:
31        type, value, traceback = sys.exc_info()
32        return value
[49ab5d7]33    return None
[5d1c1f4]34
[fb58234]35class PyConsole(editor.EditorNotebookFrame):
[ec6c520]36    ## Internal nickname for the window, used by the AUI manager
[5d1c1f4]37    window_name = "Custom Model Editor"
[ec6c520]38    ## Name to appear on the window title bar
[5d1c1f4]39    window_caption = "Custom Model Editor"
[ec6c520]40    ## Flag to tell the AUI manager to put this panel in the center pane
41    CENTER_PANE = False
[ae84427]42    def __init__(self, parent=None, base=None, manager=None, panel=None,
[fb58234]43                    title='Python Shell/Editor', filename=None,
[ec6c520]44                    size=(PANEL_WIDTH, PANEL_HEIGHT)):
[fb58234]45        self.config = None
[49ab5d7]46        editor.EditorNotebookFrame.__init__(self, parent=parent,
[ec6c520]47                                        title=title, size=size,
[fb58234]48                                        filename=filename)
[ec6c520]49        self.parent = parent
50        self._manager = manager
[ae84427]51        self.base = base
[5d1c1f4]52        self.panel = panel
53        self._add_menu()
54        if filename != None:
55            dataDir = os.path.dirname(filename)
56        elif self.parent != None:
57            dataDir = self.parent._default_save_location
58        else:
59             dataDir = None
60        self.dataDir = dataDir
[ec6c520]61        self.Centre()
[49ab5d7]62
[7c8d3093]63        self.Bind(wx.EVT_MENU, self.OnNewFile, id=wx.ID_NEW)
[4c5448c]64        self.Bind(wx.EVT_MENU, self.OnOpenFile, id=wx.ID_OPEN)
[5d1c1f4]65        self.Bind(wx.EVT_MENU, self.OnSaveFile, id=wx.ID_SAVE)
66        self.Bind(wx.EVT_MENU, self.OnSaveAsFile, id=wx.ID_SAVEAS)
67        self.Bind(wx.EVT_MENU, self.OnCompile, id=ID_COMPILE)
68        self.Bind(wx.EVT_MENU, self.OnRun, id=ID_RUN)
69        self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateCompileMenu, id=ID_COMPILE)
70        self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateCompileMenu, id=ID_RUN)
[ae84427]71        self.Bind(wx.EVT_CLOSE, self.on_close)
[7c8d3093]72        if not title.count('Python Shell'):
73            # Delete menu item (open and new) if not python shell
[86be650]74            #self.fileMenu.Delete(wx.ID_NEW)
[7c8d3093]75            self.fileMenu.Delete(wx.ID_OPEN)
[49ab5d7]76
77
[5d1c1f4]78    def _add_menu(self):
[861f8317]79        """
[5d1c1f4]80        Add menu
[861f8317]81        """
[5d1c1f4]82        self.compileMenu = wx.Menu()
83        self.compileMenu.Append(ID_COMPILE, 'Compile',
84                 'Compile the file')
85        self.compileMenu.AppendSeparator()
[7c8d3093]86        self.compileMenu.Append(ID_RUN, 'Run in Shell',
[5d1c1f4]87                 'Run the file in the Python Shell')
[7c8d3093]88        self.MenuBar.Insert(3, self.compileMenu, '&Run')
[49ab5d7]89
[5d1c1f4]90    def OnHelp(self, event):
91        """
92        Show a help dialog.
93        """
94        import  wx.lib.dialogs
95        title = 'Help on key bindings'
96        text = wx.py.shell.HELP_TEXT
97        dlg = wx.lib.dialogs.ScrolledMessageDialog(self, text, title,
[49ab5d7]98                                                   size=((700, 540)))
[5d1c1f4]99        fnt = wx.Font(10, wx.TELETYPE, wx.NORMAL, wx.NORMAL)
100        dlg.GetChildren()[0].SetFont(fnt)
101        dlg.GetChildren()[0].SetInsertionPoint(0)
102        dlg.ShowModal()
103        dlg.Destroy()
104
[ec6c520]105    def set_manager(self, manager):
106        """
107        Set the manager of this window
108        """
109        self._manager = manager
[49ab5d7]110
[861f8317]111    def OnAbout(self, event):
112        """
113        On About
114        """
115        message = ABOUT
[b1bda35]116        dial = wx.MessageDialog(self, message, 'About',
[49ab5d7]117                           wx.OK | wx.ICON_INFORMATION)
[861f8317]118        dial.ShowModal()
[49ab5d7]119
[7c8d3093]120    def OnNewFile(self, event):
121        """
[49ab5d7]122        OnFileOpen
[7c8d3093]123        """
124        self.OnFileNew(event)
[4c5448c]125
126    def OnOpenFile(self, event):
127        """
[49ab5d7]128        OnFileOpen
[4c5448c]129        """
130        self.OnFileOpen(event)
131        self.Show(False)
132        self.Show(True)
[49ab5d7]133
[5d1c1f4]134    def OnSaveFile(self, event):
135        """
[49ab5d7]136        OnFileSave overwrite
[5d1c1f4]137        """
138        self.OnFileSave(event)
139        self.Show(False)
140        self.Show(True)
[49ab5d7]141
[5d1c1f4]142    def OnSaveAsFile(self, event):
143        """
[49ab5d7]144        OnFileSaveAs overwrite
[5d1c1f4]145        """
146        self.OnFileSaveAs(event)
147        self.Show(False)
148        self.Show(True)
149
[7c8d3093]150    def bufferOpen(self):
151        """
152        Open file in buffer, bypassing editor bufferOpen
153        """
154        if self.bufferHasChanged():
155            cancel = self.bufferSuggestSave()
156            if cancel:
157                return cancel
158        filedir = ''
159        if self.buffer and self.buffer.doc.filedir:
160            filedir = self.buffer.doc.filedir
[86be650]161        if not filedir:
162            filedir = self.dataDir
[49ab5d7]163        result = editor.openSingle(directory=filedir,
[7c8d3093]164                            wildcard='Python Files (*.py)|*.py')
165        if result.path:
166            self.bufferCreate(result.path)
167        cancel = False
168        return cancel
[49ab5d7]169
[5d1c1f4]170    def bufferSaveAs(self):
171        """
[7c8d3093]172        Save buffer to a new filename: Bypassing editor bufferSaveAs
[5d1c1f4]173        """
174        filedir = ''
175        if self.buffer and self.buffer.doc.filedir:
176            filedir = self.buffer.doc.filedir
[86be650]177        if not filedir:
178            filedir = self.dataDir
[49ab5d7]179        result = editor.saveSingle(directory=filedir,
[7c8d3093]180                                   filename='untitled.py',
181                                   wildcard='Python Files (*.py)|*.py')
[5d1c1f4]182        if result.path:
[f706e09c]183            self.buffer.confirmed = True
[5d1c1f4]184            self.buffer.saveAs(result.path)
185            cancel = False
186        else:
187            cancel = True
188        return cancel
[49ab5d7]189
[5d1c1f4]190    def OnRun(self, event):
191        """
192        Run
193        """
194        if self._check_changed():
195            return True
196        if self.buffer and self.buffer.doc.filepath:
197            self.editor.setFocus()
198            # Why we have to do this (Otherwise problems on Windows)?
199            forward_path = self.buffer.doc.filepath.replace('\\', '/')
[49ab5d7]200            self.shell.Execute("execfile('%s')" % forward_path)
[5d1c1f4]201            self.shell.Hide()
202            self.shell.Show(True)
[7c8d3093]203            return self.shell.GetText().split(">>>")[-2]
[5d1c1f4]204        else:
205            mssg = "\n This is not a python file."
206            title = 'Error'
207            icon = wx.ICON_ERROR
208            wx.MessageBox(str(mssg), title, style=icon)
[7c8d3093]209            return 0
[49ab5d7]210
[5d1c1f4]211    def OnCompile(self, event):
212        """
213        Compile
214        """
215        if self._check_changed():
216            return True
[7c8d3093]217        run_out = self.OnRun(None)
218        if self._get_err_msg(run_out):
[5d1c1f4]219            if self._manager != None and self.panel != None:
[7c8d3093]220                self._manager.set_edit_menu_helper(self.parent)
[491d0fc]221                # Update custom model list in fitpage combobox
222                wx.CallAfter(self._manager.update_custom_combo)
[49ab5d7]223
224    def _check_changed(self):
[5d1c1f4]225        """
226        If content was changed, suggest to save it first
227        """
228        if self.bufferHasChanged() and self.buffer.doc.filepath:
229            cancel = self.bufferSuggestSave()
230            if cancel:
231                return cancel
[49ab5d7]232
[7c8d3093]233    def _get_err_msg(self, text=''):
[5d1c1f4]234        """
235        Get err_msg
236        """
237        name = None
238        mssg = "\n This is not a python file."
239        title = 'Error'
240        icon = wx.ICON_ERROR
241        try:
242            fname = self.editor.getStatus()[0]
243            name = os.path.basename(fname)
244            if name.split('.')[-1] != 'py':
245                wx.MessageBox(str(mssg), title, style=icon)
246                return False
247            msg = compile_file(fname)
248        except:
249            msg = None
250        if name == None:
251            wx.MessageBox(str(mssg), title, style=icon)
252            return False
[49ab5d7]253        mssg = "Compiling '%s'...\n" % name
[5d1c1f4]254        if msg != None:
255            mssg += "Error occurred:\n"
[7c8d3093]256            mssg += str(msg) + "\n\n"
257            if text:
258                mssg += "Run-Test results:\n"
259                mssg += str(text)
260                title = 'Warning'
261                icon = wx.ICON_WARNING
[5d1c1f4]262        else:
[7c8d3093]263            mssg += "Successful.\n\n"
264            if text:
[9e5ec99]265                if text.count('Failed') or text.count('Error:') > 0:
[490b281]266                    mssg += "But Simple Test FAILED: Please check your code.\n"
[7c8d3093]267                mssg += "Run-Test results:\n"
268                mssg += str(text)
[5d1c1f4]269            title = 'Info'
270            icon = wx.ICON_INFORMATION
[49ab5d7]271        dlg = wx.lib.dialogs.ScrolledMessageDialog(self, mssg, title,
272                                                   size=((550, 250)))
[5d1c1f4]273        fnt = wx.Font(10, wx.TELETYPE, wx.NORMAL, wx.NORMAL)
274        dlg.GetChildren()[0].SetFont(fnt)
275        dlg.GetChildren()[0].SetInsertionPoint(0)
276        dlg.ShowModal()
277        dlg.Destroy()
278        return True
[49ab5d7]279
[5d1c1f4]280    def OnUpdateCompileMenu(self, event):
281        """
282        Update Compile menu items based on current tap.
283        """
284        win = wx.Window.FindFocus()
285        id = event.GetId()
286        event.Enable(True)
287        try:
288            if id == ID_COMPILE or id == ID_RUN:
289                menu_on = False
290                if self.buffer and self.buffer.doc.filepath:
291                    menu_on = True
292                event.Enable(menu_on)
293        except AttributeError:
294            # This menu option is not supported in the current context.
295            event.Enable(False)
[49ab5d7]296
[ae84427]297    def on_close(self, event):
298        """
299        Close event
300        """
301        if self.base != None:
302            self.base.py_frame = None
303        self.Destroy()
[49ab5d7]304
305ABOUT = "Welcome to Python %s! \n\n" % sys.version.split()[0]
[5d1c1f4]306ABOUT += "This uses Py Shell/Editor in wx (developed by Patrick K. O'Brien).\n"
[861f8317]307ABOUT += "If this is your first time using Python, \n"
308ABOUT += "you should definitely check out the tutorial "
309ABOUT += "on the Internet at http://www.python.org/doc/tut/."
[49ab5d7]310
311
[ec6c520]312if __name__ == "__main__":
[49ab5d7]313
314    app = wx.App()
[ec6c520]315    dlg = PyConsole()
316    dlg.Show()
[49ab5d7]317    app.MainLoop()
Note: See TracBrowser for help on using the repository browser.