File size: 4,143 Bytes
10865e1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
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