root/branches/stable-1.7/WikidPadStarter.py
| Revision 100 (by mbutscher, 01/01/07 07:06:50) |
|---|
#!/bin/python import sys, os, traceback, os.path, glob, time, socket os.stat_float_times(True) VERSION_STRING = "wikidPad 1.7" if not hasattr(sys, 'frozen'): sys.path.append("lib") import ExceptionLogger ExceptionLogger.startLogger(VERSION_STRING) ## import hotshot ## _prof = hotshot.Profile("hotshot.prf") sys.path.append(os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), "gadfly.zip")) # print "sys.path + ", os.path.join(os.path.abspath(sys.argv[0]), "gadfly.zip") from wxPython.wx import * import wxPython.xrc as xrc from pwiki import srePersistent srePersistent.loadCodeCache() from pwiki.PersonalWikiFrame import PersonalWikiFrame from pwiki.StringOps import mbcsDec, createRandomString from pwiki.CmdLineAction import CmdLineAction from pwiki.Serialization import SerializeStream from pwiki import Ipc from pwiki.Configuration import createGlobalConfiguration def findDirs(): """ Returns tuple (wikiAppDir, globalConfigDir) """ wikiAppDir = None try: wikiAppDir = os.path.dirname(os.path.abspath(sys.argv[0])) if not wikiAppDir: wikiAppDir = r"C:\Program Files\WikidPad" # This allows to keep the program with config on an USB stick if os.path.exists(os.path.join(wikiAppDir, "WikidPad.config")): globalConfigDir = wikiAppDir else: globalConfigDir = os.environ.get("HOME") if not (globalConfigDir and os.path.exists(globalConfigDir)): globalConfigDir = os.environ.get("USERPROFILE") if not (globalConfigDir and os.path.exists(globalConfigDir)): # Instead of checking USERNAME, the user config dir. is # now used globalConfigDir = wxStandardPaths.Get().GetUserConfigDir() # user = os.environ.get("USERNAME") # if user: # globalConfigDir = r"c:\Documents And Settings\%s" % user finally: pass # except Exception, e: # return None, None if not globalConfigDir: globalConfigDir = wikiAppDir # if not globalConfigDir or not os.path.exists(globalConfigDir): # globalConfigDir = "C:\Windows" # mbcs decoding if wikiAppDir is not None: wikiAppDir = mbcsDec(wikiAppDir, "replace")[0] if globalConfigDir is not None: globalConfigDir = mbcsDec(globalConfigDir, "replace")[0] ExceptionLogger._exceptionDestDir = globalConfigDir return (wikiAppDir, globalConfigDir) if len(sys.argv) == 2 and sys.argv[1] == "--deleteconfig": # Special option, called by deinstaller on request to delete personal # configuration files dummyApp = wxApp(0) dummyApp.SetAppName("WikidPad") wikiAppDir, globalConfigDir = findDirs() if globalConfigDir is None: sys.exit(1) try: globalConfigSubDir = os.path.join(globalConfigDir, ".WikidPadGlobals") subfiles = glob.glob(os.path.join(globalConfigSubDir, "*")) for f in subfiles: try: os.remove(f) except: pass try: os.rmdir(globalConfigSubDir) except: pass try: os.remove(os.path.join(globalConfigDir, "WikidPad.config")) except: pass sys.exit(0) except: sys.exit(1) class App(wxApp): def __init__(self, *args, **kwargs): wxApp.__init__(self, *args, **kwargs) self.SetAppName("WikidPad") # Do not initialize member variables here! def OnInit(self): # TODO Load global config here!!! ## _prof.start() self.SetAppName("WikidPad") self.removeAppLockOnExit = False appdir = os.path.dirname(os.path.abspath(sys.argv[0])) wikiAppDir, globalConfigDir = findDirs() if not globalConfigDir or not os.path.exists(globalConfigDir): raise Exception(u"Error initializing environment, couldn't locate " u"global config directory") self.wikiAppDir = wikiAppDir self.globalConfigDir = globalConfigDir self.globalConfigSubDir = os.path.join(self.globalConfigDir, ".WikidPadGlobals") if not os.path.exists(self.globalConfigSubDir): os.mkdir(self.globalConfigSubDir) # load or create global configuration globalConfigLoc = os.path.join(self.globalConfigDir, "WikidPad.config") self.globalConfig = createGlobalConfiguration() if os.path.exists(globalConfigLoc): try: self.globalConfig.loadConfig(globalConfigLoc) except Configuration.Error: self.createDefaultGlobalConfig(globalConfigLoc) else: self.createDefaultGlobalConfig(globalConfigLoc) if self.globalConfig.getboolean("main", "single_process"): # Single process mode means to create a server, detect an already # running server and, if there, just send the commandline to # the running server and quit then. # We create a "password" so that no other user can send commands to this # WikidPad instance. appCookie = createRandomString(30) port = Ipc.createCommandServer(appCookie) # True if this is the single existing instance which should write # a new "AppLock.lock" file which either didn't exist or was invalid singleInstance = True # TODO maybe more secure method to ensure atomic exist. check and # writing of file if os.path.exists(os.path.join(self.globalConfigSubDir, "AppLock.lock")): singleInstance = False # There seems to be(!) another instance already # TODO Try to send commandline f = open(os.path.join(self.globalConfigSubDir, "AppLock.lock"), "ra") appLockContent = f.read() f.close() lines = appLockContent.split("\n") if len(lines) != 3: return True # TODO Error handling!!! appCookie = lines[0] remotePort = int(lines[1]) if port != remotePort: # Everything ok so far sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(10.0) try: try: sock.connect(("127.0.0.1", remotePort)) greet = self._readSocketLine(sock) if greet == "WikidPad_command_server 1.0": sock.send("cmdline\n" + appCookie + "\n") ack = self._readSocketLine(sock) if ack[0] == "+": # app cookie ok sst = SerializeStream(stringBuf="", readMode=False) sst.serArrString(sys.argv[1:]) sock.send(sst.getBytes()) return True # Reaching this point means something went wrong singleInstance = True # TODO More fine grained reaction except socket.timeout, e: singleInstance = True except socket.error, e: if e.args[0] == 10061: # Connection refused (port not bound to a server) singleInstance = True else: raise finally: sock.close() else: # Sure indicator that AppLock file is invalid if newly # created server opened a port which is claimed to be used # already by previously started instance. singleInstance = True if not singleInstance: return False if port != -1: # Server is connected, start it Ipc.startCommandServer() appLockContent = appCookie + "\n" + str(port) + "\n" f = open(os.path.join(self.globalConfigSubDir, "AppLock.lock"), "wa") f.write(appLockContent) f.close() self.removeAppLockOnExit = True # Load wxPython XML resources rf = open(os.path.join(appdir, "WikidPad.xrc"), "r") rd = rf.read() rf.close() res = xrc.wxXmlResource.Get() res.SetFlags(0) res.LoadFromString(rd) self.startPersonalWikiFrame(CmdLineAction(sys.argv[1:])) return True def _readSocketLine(self, sock): result = [] read = 0 while read < 300: c = sock.recv(1) if c == "\n" or c == "": return "".join(result) result.append(c) read += 1 return "" def OnExit(self): if self.removeAppLockOnExit: try: os.remove(os.path.join(self.globalConfigSubDir, "AppLock.lock")) except: # OSError, ex: traceback.print_exc() # TODO Error message! try: Ipc.stopCommandServer() except: traceback.print_exc() if ExceptionLogger._exceptionOccurred and hasattr(sys, 'frozen'): wxMessageBox("An error occurred during this session\nSee file %s" % os.path.join(ExceptionLogger._exceptionDestDir, "WikidPad_Error.log"), "Error", style = wxOK) def startPersonalWikiFrame(self, clAction): wikiFrame = PersonalWikiFrame(None, -1, "WikidPad", self.wikiAppDir, self.globalConfigDir, self.globalConfigSubDir, clAction) self.SetTopWindow(wikiFrame) ## _prof.stop() # set the icon of the app try: wikiFrame.SetIcon(wxIcon(os.path.join(self.wikiAppDir, 'icons', 'pwiki.ico'), wxBITMAP_TYPE_ICO)) except: pass def createDefaultGlobalConfig(self, globalConfigLoc): self.globalConfig.createEmptyConfig(globalConfigLoc) self.globalConfig.fillWithDefaults() wikidPadHelp = os.path.join(self.wikiAppDir, 'WikidPadHelp', 'WikidPadHelp.wiki') self.globalConfig.set("main", "wiki_history", wikidPadHelp) self.globalConfig.set("main", "last_wiki", wikidPadHelp) self.globalConfig.set("main", "last_active_dir", os.getcwd()) def getGlobalConfigSubDir(self): return self.globalConfigSubDir def getGlobalConfig(self): return self.globalConfig class ErrorFrame(wxFrame): def __init__(self, parent, id, title): wxFrame.__init__(self, parent, -1, title, size = (300, 200), style=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE) dlg_m = wxMessageDialog(self, "%s. %s." % ("Error starting wikidPad", e), 'Error!', wxOK) dlg_m.ShowModal() dlg_m.Destroy() self.Close() class Error(wxApp): def OnInit(self): errorFrame = ErrorFrame(None, -1, "Error") self.SetTopWindow(errorFrame) return False app = None exception = None try: app = App(0) app.MainLoop() srePersistent.saveCodeCache() except Exception, e: traceback.print_exc() exception = e error = Error(0) error.MainLoop() sys.exit()
Note: See TracBrowser for help on using the browser.
