Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

scriptdispatch.py 3.8KB

1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. """dynamic dispatch objects for AX Script.
  2. This is an IDispatch object that a scripting host may use to
  3. query and invoke methods on the main script. Not may hosts use
  4. this yet, so it is not well tested!
  5. """
  6. import types
  7. import pythoncom
  8. import win32com.server.policy
  9. import win32com.server.util
  10. import winerror
  11. from win32com.axscript import axscript
  12. from win32com.client import Dispatch
  13. from win32com.server.exception import COMException
  14. debugging = 0
  15. PyIDispatchType = pythoncom.TypeIIDs[pythoncom.IID_IDispatch]
  16. def _is_callable(obj):
  17. return type(obj) in [types.FunctionType, types.MethodType]
  18. # ignore hasattr(obj, "__call__") as this means all COM objects!
  19. class ScriptDispatch:
  20. _public_methods_ = []
  21. def __init__(self, engine, scriptNamespace):
  22. self.engine = engine
  23. self.scriptNamespace = scriptNamespace
  24. def _dynamic_(self, name, lcid, wFlags, args):
  25. # Ensure any newly added items are available.
  26. self.engine.RegisterNewNamedItems()
  27. self.engine.ProcessNewNamedItemsConnections()
  28. if wFlags & pythoncom.INVOKE_FUNC:
  29. # attempt to call a function
  30. try:
  31. func = getattr(self.scriptNamespace, name)
  32. if not _is_callable(func):
  33. raise AttributeError(name) # Not a function.
  34. realArgs = []
  35. for arg in args:
  36. if type(arg) == PyIDispatchType:
  37. realArgs.append(Dispatch(arg))
  38. else:
  39. realArgs.append(arg)
  40. # xxx - todo - work out what code block to pass???
  41. return self.engine.ApplyInScriptedSection(None, func, tuple(realArgs))
  42. except AttributeError:
  43. if not wFlags & pythoncom.DISPATCH_PROPERTYGET:
  44. raise COMException(scode=winerror.DISP_E_MEMBERNOTFOUND)
  45. if wFlags & pythoncom.DISPATCH_PROPERTYGET:
  46. # attempt to get a property
  47. try:
  48. ret = getattr(self.scriptNamespace, name)
  49. if _is_callable(ret):
  50. raise AttributeError(name) # Not a property.
  51. except AttributeError:
  52. raise COMException(scode=winerror.DISP_E_MEMBERNOTFOUND)
  53. except COMException as instance:
  54. raise
  55. except:
  56. ret = self.engine.HandleException()
  57. return ret
  58. raise COMException(scode=winerror.DISP_E_MEMBERNOTFOUND)
  59. class StrictDynamicPolicy(win32com.server.policy.DynamicPolicy):
  60. def _wrap_(self, object):
  61. win32com.server.policy.DynamicPolicy._wrap_(self, object)
  62. if hasattr(self._obj_, "scriptNamespace"):
  63. for name in dir(self._obj_.scriptNamespace):
  64. self._dyn_dispid_to_name_[self._getdispid_(name, 0)] = name
  65. def _getmembername_(self, dispid):
  66. try:
  67. return str(self._dyn_dispid_to_name_[dispid])
  68. except KeyError:
  69. raise COMException(scode=winerror.DISP_E_UNKNOWNNAME, desc="Name not found")
  70. def _getdispid_(self, name, fdex):
  71. try:
  72. func = getattr(self._obj_.scriptNamespace, str(name))
  73. except AttributeError:
  74. raise COMException(scode=winerror.DISP_E_MEMBERNOTFOUND)
  75. # if not _is_callable(func):
  76. return win32com.server.policy.DynamicPolicy._getdispid_(self, name, fdex)
  77. def _wrap_debug(obj):
  78. return win32com.server.util.wrap(
  79. obj,
  80. usePolicy=StrictDynamicPolicy,
  81. useDispatcher=win32com.server.policy.DispatcherWin32trace,
  82. )
  83. def _wrap_nodebug(obj):
  84. return win32com.server.util.wrap(obj, usePolicy=StrictDynamicPolicy)
  85. if debugging:
  86. _wrap = _wrap_debug
  87. else:
  88. _wrap = _wrap_nodebug
  89. def MakeScriptDispatch(engine, namespace):
  90. return _wrap(ScriptDispatch(engine, namespace))