Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes15kdownloads
intpyapp.py556 linesDownload Raw Back to framework
1# intpyapp.py  - Interactive Python application class2#3import os4import sys5import traceback6 7import __main__8import commctrl9import win32api10import win32con11import win32ui12from pywin.mfc import afxres, dialog13 14from . import app, dbgcommands15 16lastLocateFileName = ".py"  # used in the "File/Locate" dialog...17 18 19# todo - _SetupSharedMenu should be moved to a framework class.20def _SetupSharedMenu_(self):21    sharedMenu = self.GetSharedMenu()22    from pywin.framework import toolmenu23 24    toolmenu.SetToolsMenu(sharedMenu)25    from pywin.framework import help26 27    help.SetHelpMenuOtherHelp(sharedMenu)28 29 30from pywin.mfc import docview31 32docview.DocTemplate._SetupSharedMenu_ = _SetupSharedMenu_33 34 35class MainFrame(app.MainFrame):36    def OnCreate(self, createStruct):37        self.closing = 038        if app.MainFrame.OnCreate(self, createStruct) == -1:39            return -140        style = (41            win32con.WS_CHILD42            | afxres.CBRS_SIZE_DYNAMIC43            | afxres.CBRS_TOP44            | afxres.CBRS_TOOLTIPS45            | afxres.CBRS_FLYBY46        )47 48        self.EnableDocking(afxres.CBRS_ALIGN_ANY)49 50        tb = win32ui.CreateToolBar(self, style | win32con.WS_VISIBLE)51        tb.ModifyStyle(0, commctrl.TBSTYLE_FLAT)52        tb.LoadToolBar(win32ui.IDR_MAINFRAME)53        tb.EnableDocking(afxres.CBRS_ALIGN_ANY)54        tb.SetWindowText("Standard")55        self.DockControlBar(tb)56        # Any other packages which use toolbars57        from pywin.debugger.debugger import PrepareControlBars58 59        PrepareControlBars(self)60        # Note "interact" also uses dockable windows, but they already happen61 62        # And a "Tools" menu on the main frame.63        menu = self.GetMenu()64        from . import toolmenu65 66        toolmenu.SetToolsMenu(menu, 2)67        # And fix the "Help" menu on the main frame68        from pywin.framework import help69 70        help.SetHelpMenuOtherHelp(menu)71 72    def OnClose(self):73        try:74            import pywin.debugger75 76            if (77                pywin.debugger.currentDebugger is not None78                and pywin.debugger.currentDebugger.pumping79            ):80                try:81                    pywin.debugger.currentDebugger.close(1)82                except:83                    traceback.print_exc()84                return85        except win32ui.error:86            pass87        self.closing = 188        self.SaveBarState("ToolbarDefault")89        self.SetActiveView(None)  # Otherwise MFC's OnClose may _not_ prompt for save.90 91        from pywin.framework import help92 93        help.FinalizeHelp()94 95        self.DestroyControlBar(afxres.AFX_IDW_TOOLBAR)96        self.DestroyControlBar(win32ui.ID_VIEW_TOOLBAR_DBG)97 98        return self._obj_.OnClose()99 100    def DestroyControlBar(self, id):101        try:102            bar = self.GetControlBar(id)103        except win32ui.error:104            return105        bar.DestroyWindow()106 107    def OnCommand(self, wparam, lparam):108        # By default, the current MDI child frame will process WM_COMMAND109        # messages before any docked control bars - even if the control bar110        # has focus.  This is a problem for the interactive window when docked.111        # Therefore, we detect the situation of a view having the main frame112        # as its parent, and assume it must be a docked view (which it will in an MDI app)113        try:114            v = (115                self.GetActiveView()116            )  # Raise an exception if none - good - then we want default handling117            # Main frame _does_ have a current view (ie, a docking view) - see if it wants it.118            if v.OnCommand(wparam, lparam):119                return 1120        except (win32ui.error, AttributeError):121            pass122        return self._obj_.OnCommand(wparam, lparam)123 124 125class InteractivePythonApp(app.CApp):126    # This works if necessary - just we dont need to override the Run method.127    # 	def Run(self):128    # 		return self._obj_.Run()129 130    def HookCommands(self):131        app.CApp.HookCommands(self)132        dbgcommands.DebuggerCommandHandler().HookCommands()133        self.HookCommand(self.OnViewBrowse, win32ui.ID_VIEW_BROWSE)134        self.HookCommand(self.OnFileImport, win32ui.ID_FILE_IMPORT)135        self.HookCommand(self.OnFileCheck, win32ui.ID_FILE_CHECK)136        self.HookCommandUpdate(self.OnUpdateFileCheck, win32ui.ID_FILE_CHECK)137        self.HookCommand(self.OnFileRun, win32ui.ID_FILE_RUN)138        self.HookCommand(self.OnFileLocate, win32ui.ID_FILE_LOCATE)139        self.HookCommand(self.OnInteractiveWindow, win32ui.ID_VIEW_INTERACTIVE)140        self.HookCommandUpdate(141            self.OnUpdateInteractiveWindow, win32ui.ID_VIEW_INTERACTIVE142        )143        self.HookCommand(self.OnViewOptions, win32ui.ID_VIEW_OPTIONS)144        self.HookCommand(self.OnHelpIndex, afxres.ID_HELP_INDEX)145        self.HookCommand(self.OnFileSaveAll, win32ui.ID_FILE_SAVE_ALL)146        self.HookCommand(self.OnViewToolbarDbg, win32ui.ID_VIEW_TOOLBAR_DBG)147        self.HookCommandUpdate(self.OnUpdateViewToolbarDbg, win32ui.ID_VIEW_TOOLBAR_DBG)148 149    def CreateMainFrame(self):150        return MainFrame()151 152    def MakeExistingDDEConnection(self):153        # Use DDE to connect to an existing instance154        # Return None if no existing instance155        try:156            from . import intpydde157        except ImportError:158            # No dde support!159            return None160        conv = intpydde.CreateConversation(self.ddeServer)161        try:162            conv.ConnectTo("Pythonwin", "System")163            return conv164        except intpydde.error:165            return None166 167    def InitDDE(self):168        # Do all the magic DDE handling.169        # Returns TRUE if we have pumped the arguments to our170        # remote DDE app, and we should terminate.171        try:172            from . import intpydde173        except ImportError:174            self.ddeServer = None175            intpydde = None176        if intpydde is not None:177            self.ddeServer = intpydde.DDEServer(self)178            self.ddeServer.Create("Pythonwin", intpydde.CBF_FAIL_SELFCONNECTIONS)179            try:180                # If there is an existing instance, pump the arguments to it.181                connection = self.MakeExistingDDEConnection()182                if connection is not None:183                    connection.Exec("self.Activate()")184                    if self.ProcessArgs(sys.argv, connection) is None:185                        return 1186            except:187                # It is too early to 'print' an exception - we188                # don't have stdout setup yet!189                win32ui.DisplayTraceback(190                    sys.exc_info(), " - error in DDE conversation with Pythonwin"191                )192                return 1193 194    def InitInstance(self):195        # Allow "/nodde" and "/new" to optimize this!196        if (197            "/nodde" not in sys.argv198            and "/new" not in sys.argv199            and "-nodde" not in sys.argv200            and "-new" not in sys.argv201        ):202            if self.InitDDE():203                return 1  # A remote DDE client is doing it for us!204        else:205            self.ddeServer = None206 207        win32ui.SetRegistryKey(208            "Python %s" % (sys.winver,)209        )  # MFC automatically puts the main frame caption on!210        app.CApp.InitInstance(self)211 212        # Create the taskbar icon213        win32ui.CreateDebuggerThread()214 215        # Allow Pythonwin to host OCX controls.216        win32ui.EnableControlContainer()217 218        # Display the interactive window if the user wants it.219        from . import interact220 221        interact.CreateInteractiveWindowUserPreference()222 223        # Load the modules we use internally.224        self.LoadSystemModules()225 226        # Load additional module the user may want.227        self.LoadUserModules()228 229        # Load the ToolBar state near the end of the init process, as230        # there may be Toolbar IDs created by the user or other modules.231        # By now all these modules should be loaded, so all the toolbar IDs loaded.232        try:233            self.frame.LoadBarState("ToolbarDefault")234        except win32ui.error:235            # MFC sucks.  It does essentially "GetDlgItem(x)->Something", so if the236            # toolbar with ID x does not exist, MFC crashes!  Pythonwin has a trap for this237            # but I need to investigate more how to prevent it (AFAIK, ensuring all the238            # toolbars are created by now _should_ stop it!)239            pass240 241        # Finally process the command line arguments.242        try:243            self.ProcessArgs(sys.argv)244        except:245            # too early for printing anything.246            win32ui.DisplayTraceback(247                sys.exc_info(), " - error processing command line args"248            )249 250    def ExitInstance(self):251        win32ui.DestroyDebuggerThread()252        try:253            from . import interact254 255            interact.DestroyInteractiveWindow()256        except:257            pass258        if self.ddeServer is not None:259            self.ddeServer.Shutdown()260            self.ddeServer = None261        return app.CApp.ExitInstance(self)262 263    def Activate(self):264        # Bring to the foreground.  Mainly used when another app starts up, it asks265        # this one to activate itself, then it terminates.266        frame = win32ui.GetMainFrame()267        frame.SetForegroundWindow()268        if frame.GetWindowPlacement()[1] == win32con.SW_SHOWMINIMIZED:269            frame.ShowWindow(win32con.SW_RESTORE)270 271    def ProcessArgs(self, args, dde=None):272        # If we are going to talk to a remote app via DDE, then273        # activate it!274        if (275            len(args) < 1 or not args[0]276        ):  # argv[0]=='' when started without args, just like Python.exe!277            return278 279        i = 0280        while i < len(args):281            argType = args[i]282            i += 1283            if argType.startswith("-"):284                # Support dash options. Slash options are misinterpreted by python init285                # as path and not finding usually 'C:\\' ends up in sys.path[0]286                argType = "/" + argType[1:]287            if not argType.startswith("/"):288                argType = win32ui.GetProfileVal(289                    "Python", "Default Arg Type", "/edit"290                ).lower()291                i -= 1  #  arg is /edit's parameter292            par = i < len(args) and args[i] or "MISSING"293            if argType in ("/nodde", "/new", "-nodde", "-new"):294                # Already handled295                pass296            elif argType.startswith("/goto:"):297                gotoline = int(argType[len("/goto:") :])298                if dde:299                    dde.Exec(300                        "from pywin.framework import scriptutils\n"301                        "ed = scriptutils.GetActiveEditControl()\n"302                        "if ed: ed.SetSel(ed.LineIndex(%s - 1))" % gotoline303                    )304                else:305                    from . import scriptutils306 307                    ed = scriptutils.GetActiveEditControl()308                    if ed:309                        ed.SetSel(ed.LineIndex(gotoline - 1))310            elif argType == "/edit":311                # Load up the default application.312                i += 1313                fname = win32api.GetFullPathName(par)314                if not os.path.isfile(fname):315                    # if we don't catch this, OpenDocumentFile() (actually316                    # PyCDocument.SetPathName() in317                    # pywin.scintilla.document.CScintillaDocument.OnOpenDocument)318                    # segfaults Pythonwin on recent PY3 builds (b228)319                    win32ui.MessageBox(320                        "No such file: %s\n\nCommand Line: %s"321                        % (fname, win32api.GetCommandLine()),322                        "Open file for edit",323                        win32con.MB_ICONERROR,324                    )325                    continue326                if dde:327                    dde.Exec("win32ui.GetApp().OpenDocumentFile(%s)" % (repr(fname)))328                else:329                    win32ui.GetApp().OpenDocumentFile(par)330            elif argType == "/rundlg":331                if dde:332                    dde.Exec(333                        "from pywin.framework import scriptutils;scriptutils.RunScript(%r, %r, 1)"334                        % (par, " ".join(args[i + 1 :]))335                    )336                else:337                    from . import scriptutils338 339                    scriptutils.RunScript(par, " ".join(args[i + 1 :]))340                return341            elif argType == "/run":342                if dde:343                    dde.Exec(344                        "from pywin.framework import scriptutils;scriptutils.RunScript(%r, %r, 0)"345                        % (par, " ".join(args[i + 1 :]))346                    )347                else:348                    from . import scriptutils349 350                    scriptutils.RunScript(par, " ".join(args[i + 1 :]), 0)351                return352            elif argType == "/app":353                raise RuntimeError(354                    "/app only supported for new instances of Pythonwin.exe"355                )356            elif argType == "/dde":  # Send arbitary command357                if dde is not None:358                    dde.Exec(par)359                else:360                    win32ui.MessageBox(361                        "The /dde command can only be used\r\nwhen Pythonwin is already running"362                    )363                i += 1364            else:365                raise ValueError("Command line argument not recognised: %s" % argType)366 367    def LoadSystemModules(self):368        self.DoLoadModules("pywin.framework.editor,pywin.framework.stdin")369 370    def LoadUserModules(self, moduleNames=None):371        # Load the users modules.372        if moduleNames is None:373            default = "pywin.framework.sgrepmdi,pywin.framework.mdi_pychecker"374            moduleNames = win32ui.GetProfileVal("Python", "Startup Modules", default)375        self.DoLoadModules(moduleNames)376 377    def DoLoadModules(self, moduleNames):  # ", sep string of module names.378        if not moduleNames:379            return380        modules = moduleNames.split(",")381        for module in modules:382            try:383                __import__(module)384            except:  # Catch em all, else the app itself dies! 'ImportError:385                traceback.print_exc()386                msg = 'Startup import of user module "%s" failed' % module387                print(msg)388                win32ui.MessageBox(msg)389 390    #391    # DDE Callback392    #393    def OnDDECommand(self, command):394        try:395            exec(command + "\n")396        except:397            print("ERROR executing DDE command: ", command)398            traceback.print_exc()399            raise400 401    #402    # General handlers403    #404    def OnViewBrowse(self, id, code):405        "Called when ViewBrowse message is received"406        from pywin.tools import browser407 408        obName = dialog.GetSimpleInput("Object", "__builtins__", "Browse Python Object")409        if obName is None:410            return411        try:412            browser.Browse(eval(obName, __main__.__dict__, __main__.__dict__))413        except NameError:414            win32ui.MessageBox("This is no object with this name")415        except AttributeError:416            win32ui.MessageBox("The object has no attribute of that name")417        except:418            traceback.print_exc()419            win32ui.MessageBox("This object can not be browsed")420 421    def OnFileImport(self, id, code):422        "Called when a FileImport message is received. Import the current or specified file"423        from . import scriptutils424 425        scriptutils.ImportFile()426 427    def OnFileCheck(self, id, code):428        "Called when a FileCheck message is received. Check the current file."429        from . import scriptutils430 431        scriptutils.CheckFile()432 433    def OnUpdateFileCheck(self, cmdui):434        from . import scriptutils435 436        cmdui.Enable(scriptutils.GetActiveFileName(0) is not None)437 438    def OnFileRun(self, id, code):439        "Called when a FileRun message is received."440        from . import scriptutils441 442        showDlg = win32api.GetKeyState(win32con.VK_SHIFT) >= 0443        scriptutils.RunScript(None, None, showDlg)444 445    def OnFileLocate(self, id, code):446        from . import scriptutils447 448        global lastLocateFileName  # save the new version away for next time...449 450        name = dialog.GetSimpleInput(451            "File name", lastLocateFileName, "Locate Python File"452        )453        if name is None:  # Cancelled.454            return455        lastLocateFileName = name456        # if ".py" supplied, rip it off!457        # should also check for .pys and .pyw458        if lastLocateFileName[-3:].lower() == ".py":459            lastLocateFileName = lastLocateFileName[:-3]460        lastLocateFileName = lastLocateFileName.replace(".", "\\")461        newName = scriptutils.LocatePythonFile(lastLocateFileName)462        if newName is None:463            win32ui.MessageBox("The file '%s' can not be located" % lastLocateFileName)464        else:465            win32ui.GetApp().OpenDocumentFile(newName)466 467    # Display all the "options" proprety pages we can find468    def OnViewOptions(self, id, code):469        win32ui.InitRichEdit()470        sheet = dialog.PropertySheet("Pythonwin Options")471        # Add property pages we know about that need manual work.472        from pywin.dialogs import ideoptions473 474        sheet.AddPage(ideoptions.OptionsPropPage())475 476        from . import toolmenu477 478        sheet.AddPage(toolmenu.ToolMenuPropPage())479 480        # Get other dynamic pages from templates.481        pages = []482        for template in self.GetDocTemplateList():483            try:484                # Dont actually call the function with the exception handler.485                getter = template.GetPythonPropertyPages486            except AttributeError:487                # Template does not provide property pages!488                continue489            pages = pages + getter()490 491        # Debugger template goes at the end492        try:493            from pywin.debugger import configui494        except ImportError:495            configui = None496        if configui is not None:497            pages.append(configui.DebuggerOptionsPropPage())498        # Now simply add the pages, and display the dialog.499        for page in pages:500            sheet.AddPage(page)501 502        if sheet.DoModal() == win32con.IDOK:503            win32ui.SetStatusText("Applying configuration changes...", 1)504            win32ui.DoWaitCursor(1)505            # Tell every Window in our app that win.ini has changed!506            win32ui.GetMainFrame().SendMessageToDescendants(507                win32con.WM_WININICHANGE, 0, 0508            )509            win32ui.DoWaitCursor(0)510 511    def OnInteractiveWindow(self, id, code):512        # toggle the existing state.513        from . import interact514 515        interact.ToggleInteractiveWindow()516 517    def OnUpdateInteractiveWindow(self, cmdui):518        try:519            interact = sys.modules["pywin.framework.interact"]520            state = interact.IsInteractiveWindowVisible()521        except KeyError:  # Interactive module hasnt ever been imported.522            state = 0523        cmdui.Enable()524        cmdui.SetCheck(state)525 526    def OnFileSaveAll(self, id, code):527        # Only attempt to save editor documents.528        from pywin.framework.editor import editorTemplate529 530        num = 0531        for doc in editorTemplate.GetDocumentList():532            if doc.IsModified() and doc.GetPathName():533                num = num = 1534                doc.OnSaveDocument(doc.GetPathName())535        win32ui.SetStatusText("%d documents saved" % num, 1)536 537    def OnViewToolbarDbg(self, id, code):538        if code == 0:539            return not win32ui.GetMainFrame().OnBarCheck(id)540 541    def OnUpdateViewToolbarDbg(self, cmdui):542        win32ui.GetMainFrame().OnUpdateControlBarMenu(cmdui)543        cmdui.Enable(1)544 545    def OnHelpIndex(self, id, code):546        from . import help547 548        help.SelectAndRunHelpFile()549 550 551# As per the comments in app.py, this use is depreciated.552# app.AppBuilder = InteractivePythonApp553 554# Now all we do is create the application555thisApp = InteractivePythonApp()556 
codekingpro/portable-devtools · Team Ai