team-10/venv/Lib/site-packages/win32comext/axscript/client/scriptdispatch.py
2025-08-02 02:00:33 +02:00

103 lines
3.7 KiB
Python

"""dynamic dispatch objects for AX Script.
This is an IDispatch object that a scripting host may use to
query and invoke methods on the main script. Not may hosts use
this yet, so it is not well tested!
"""
from __future__ import annotations
import types
import pythoncom
import win32com.server.policy
import win32com.server.util
import winerror
from win32com.client import Dispatch
from win32com.server.exception import COMException
debugging = 0
PyIDispatchType = pythoncom.TypeIIDs[pythoncom.IID_IDispatch]
# ignore hasattr(obj, "__call__") as this means all COM objects!
_CallableTypes = (types.FunctionType, types.MethodType)
class ScriptDispatch:
_public_methods_: list[str] = []
def __init__(self, engine, scriptNamespace):
self.engine = engine
self.scriptNamespace = scriptNamespace
def _dynamic_(self, name, lcid, wFlags, args):
# Ensure any newly added items are available.
self.engine.RegisterNewNamedItems()
self.engine.ProcessNewNamedItemsConnections()
if wFlags & pythoncom.INVOKE_FUNC:
# attempt to call a function
try:
func = getattr(self.scriptNamespace, name)
if not isinstance(func, _CallableTypes):
raise AttributeError(name) # Not a function.
realArgs = []
for arg in args:
if isinstance(arg, PyIDispatchType):
realArgs.append(Dispatch(arg))
else:
realArgs.append(arg)
# xxx - todo - work out what code block to pass???
return self.engine.ApplyInScriptedSection(None, func, tuple(realArgs))
except AttributeError:
if not wFlags & pythoncom.DISPATCH_PROPERTYGET:
raise COMException(scode=winerror.DISP_E_MEMBERNOTFOUND)
if wFlags & pythoncom.DISPATCH_PROPERTYGET:
# attempt to get a property
try:
ret = getattr(self.scriptNamespace, name)
if isinstance(ret, _CallableTypes):
raise AttributeError(name) # Not a property.
except AttributeError:
raise COMException(scode=winerror.DISP_E_MEMBERNOTFOUND)
except COMException as instance:
raise
except:
ret = self.engine.HandleException()
return ret
raise COMException(scode=winerror.DISP_E_MEMBERNOTFOUND)
class StrictDynamicPolicy(win32com.server.policy.DynamicPolicy):
def _wrap_(self, object):
win32com.server.policy.DynamicPolicy._wrap_(self, object)
if hasattr(self._obj_, "scriptNamespace"):
for name in dir(self._obj_.scriptNamespace):
self._dyn_dispid_to_name_[self._getdispid_(name, 0)] = name
def _getmembername_(self, dispid):
try:
return str(self._dyn_dispid_to_name_[dispid])
except KeyError:
raise COMException(scode=winerror.DISP_E_UNKNOWNNAME, desc="Name not found")
def _getdispid_(self, name, fdex):
try:
func = getattr(self._obj_.scriptNamespace, str(name))
except AttributeError:
raise COMException(scode=winerror.DISP_E_MEMBERNOTFOUND)
# if not isinstance(func, _CallableTypes):
return win32com.server.policy.DynamicPolicy._getdispid_(self, name, fdex)
def _wrap(obj):
useDispatcher = win32com.server.policy.DispatcherWin32trace if debugging else None
return win32com.server.util.wrap(
obj, usePolicy=StrictDynamicPolicy, useDispatcher=useDispatcher
)
def MakeScriptDispatch(engine, namespace):
return _wrap(ScriptDispatch(engine, namespace))