import pythoncom import win32com.axscript.axscript import winerror from win32com.axscript import axscript from win32com.server import exception, util class AXEngine: def __init__(self, site, engine): self.eScript = self.eParse = self.eSafety = None if type(engine) == type(""): engine = pythoncom.CoCreateInstance( engine, None, pythoncom.CLSCTX_SERVER, pythoncom.IID_IUnknown ) self.eScript = engine.QueryInterface(axscript.IID_IActiveScript) self.eParse = engine.QueryInterface(axscript.IID_IActiveScriptParse) self.eSafety = engine.QueryInterface(axscript.IID_IObjectSafety) self.eScript.SetScriptSite(site) self.eParse.InitNew() def __del__(self): self.Close() def GetScriptDispatch(self, name=None): return self.eScript.GetScriptDispatch(name) def AddNamedItem(self, item, flags): return self.eScript.AddNamedItem(item, flags) # Some helpers. def AddCode(self, code, flags=0): self.eParse.ParseScriptText(code, None, None, None, 0, 0, flags) def EvalCode(self, code): return self.eParse.ParseScriptText( code, None, None, None, 0, 0, axscript.SCRIPTTEXT_ISEXPRESSION ) def Start(self): # Should maybe check state? # Do I need to transition through? self.eScript.SetScriptState(axscript.SCRIPTSTATE_STARTED) # self.eScript.SetScriptState(axscript.SCRIPTSTATE_CONNECTED) def Close(self): if self.eScript: self.eScript.Close() self.eScript = self.eParse = self.eSafety = None def SetScriptState(self, state): self.eScript.SetScriptState(state) IActiveScriptSite_methods = [ "GetLCID", "GetItemInfo", "GetDocVersionString", "OnScriptTerminate", "OnStateChange", "OnScriptError", "OnEnterScript", "OnLeaveScript", ] class AXSite: """An Active Scripting site. A Site can have exactly one engine.""" _public_methods_ = IActiveScriptSite_methods _com_interfaces_ = [axscript.IID_IActiveScriptSite] def __init__(self, objModel={}, engine=None, lcid=0): self.lcid = lcid self.objModel = {} for name, object in objModel.items(): # Gregs code did string.lower this - I think that is callers job if he wants! self.objModel[name] = object self.engine = None if engine: self._AddEngine(engine) def AddEngine(self, engine): """Adds a new engine to the site. engine can be a string, or a fully wrapped engine object. """ if type(engine) == type(""): newEngine = AXEngine(util.wrap(self), engine) else: newEngine = engine self.engine = newEngine flags = ( axscript.SCRIPTITEM_ISVISIBLE | axscript.SCRIPTITEM_NOCODE | axscript.SCRIPTITEM_GLOBALMEMBERS | axscript.SCRIPTITEM_ISPERSISTENT ) for name in self.objModel.keys(): newEngine.AddNamedItem(name, flags) newEngine.SetScriptState(axscript.SCRIPTSTATE_INITIALIZED) return newEngine # B/W compat _AddEngine = AddEngine def _Close(self): self.engine.Close() self.objModel = {} def GetLCID(self): return self.lcid def GetItemInfo(self, name, returnMask): if name not in self.objModel: raise exception.Exception( scode=winerror.TYPE_E_ELEMENTNOTFOUND, desc="item not found" ) ### for now, we don't have any type information if returnMask & axscript.SCRIPTINFO_IUNKNOWN: return (self.objModel[name], None) return (None, None) def GetDocVersionString(self): return "Python AXHost version 1.0" def OnScriptTerminate(self, result, excepInfo): pass def OnStateChange(self, state): pass def OnScriptError(self, errorInterface): return winerror.S_FALSE def OnEnterScript(self): pass def OnLeaveScript(self): pass