Adding all project files
This commit is contained in:
parent
6c9e127bdc
commit
cd4316ad0f
42289 changed files with 8009643 additions and 0 deletions
|
@ -0,0 +1 @@
|
|||
# This is a Python package
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
223
venv/Lib/site-packages/win32comext/axscript/client/debug.py
Normal file
223
venv/Lib/site-packages/win32comext/axscript/client/debug.py
Normal file
|
@ -0,0 +1,223 @@
|
|||
import os
|
||||
import sys
|
||||
|
||||
import pythoncom
|
||||
import win32api
|
||||
import winerror
|
||||
from win32com.axdebug import adb, axdebug, documents, gateways
|
||||
from win32com.axdebug.codecontainer import SourceCodeContainer
|
||||
from win32com.axdebug.util import _wrap
|
||||
from win32com.server.exception import COMException
|
||||
|
||||
debuggingTrace = "DEBUG_AXDEBUG" in os.environ # Should we print "trace" output?
|
||||
|
||||
|
||||
def trace(*args):
|
||||
"""A function used instead of "print" for debugging output."""
|
||||
if not debuggingTrace:
|
||||
return
|
||||
print(win32api.GetCurrentThreadId(), end=" ")
|
||||
for arg in args:
|
||||
print(arg, end=" ")
|
||||
print()
|
||||
|
||||
|
||||
# Note that the DebugManager is not a COM gateway class for the
|
||||
# debugger - but it does create and manage them.
|
||||
class DebugManager:
|
||||
_debugger_interfaces_ = [axdebug.IID_IActiveScriptDebug]
|
||||
|
||||
def __init__(self, scriptEngine):
|
||||
self.scriptEngine = scriptEngine
|
||||
self.adb = adb.Debugger()
|
||||
self.rootNode = None
|
||||
self.debugApplication = None
|
||||
self.ccProvider = documents.CodeContainerProvider()
|
||||
try:
|
||||
self.scriptSiteDebug = scriptEngine.GetScriptSite(
|
||||
axdebug.IID_IActiveScriptSiteDebug
|
||||
)
|
||||
except pythoncom.com_error:
|
||||
# No debugger interface (ie, dumb host). Do the extra work.
|
||||
trace("Scripting site has no debugger interface")
|
||||
self.scriptSiteDebug = None
|
||||
# Get the debug application object.
|
||||
self.debugApplication = None
|
||||
if self.scriptSiteDebug is not None:
|
||||
# Spec says that we should test for this, and if it fails revert to
|
||||
# PDM application.
|
||||
try:
|
||||
self.debugApplication = self.scriptSiteDebug.GetApplication()
|
||||
self.rootNode = self.scriptSiteDebug.GetRootApplicationNode()
|
||||
except pythoncom.com_error:
|
||||
self.debugApplication = None
|
||||
|
||||
if self.debugApplication is None:
|
||||
# Try to get/create the default one
|
||||
# NOTE - Don't catch exceptions here - let the parent do it,
|
||||
# so it knows debug support is available.
|
||||
pdm = pythoncom.CoCreateInstance(
|
||||
axdebug.CLSID_ProcessDebugManager,
|
||||
None,
|
||||
pythoncom.CLSCTX_ALL,
|
||||
axdebug.IID_IProcessDebugManager,
|
||||
)
|
||||
self.debugApplication = pdm.GetDefaultApplication()
|
||||
self.rootNode = self.debugApplication.GetRootNode()
|
||||
|
||||
assert self.debugApplication is not None, (
|
||||
"Need to have a DebugApplication object by now!"
|
||||
)
|
||||
self.activeScriptDebug = None
|
||||
|
||||
if self.debugApplication is not None:
|
||||
self.adb.AttachApp(self.debugApplication, self.ccProvider)
|
||||
self.codeContainers = {}
|
||||
self.activeScriptDebug = _wrap(
|
||||
ActiveScriptDebug(self, self.codeContainers), axdebug.IID_IActiveScriptDebug
|
||||
)
|
||||
|
||||
def Close(self):
|
||||
# Called by the language engine when it receives a close request
|
||||
self.activeScriptDebug = None
|
||||
self.scriptEngine = None
|
||||
self.rootNode = None
|
||||
self.debugApplication = None
|
||||
self.scriptSiteDebug = None
|
||||
if self.ccProvider is not None:
|
||||
self.ccProvider.Close()
|
||||
self.ccProvider = None
|
||||
self.codeContainers = {}
|
||||
if self.adb:
|
||||
self.adb.CloseApp()
|
||||
self.adb = None
|
||||
|
||||
# print("Close complete")
|
||||
|
||||
def IsAnyHost(self):
|
||||
"Do we have _any_ debugging interfaces installed?"
|
||||
return self.debugApplication is not None
|
||||
|
||||
def IsSimpleHost(self):
|
||||
return self.scriptSiteDebug is None
|
||||
|
||||
def HandleRuntimeError(self):
|
||||
"""Called by the engine when a runtime error occurs. If we have a debugger,
|
||||
we let it know.
|
||||
|
||||
The result is a boolean which indicates if the error handler should call
|
||||
IActiveScriptSite::OnScriptError()
|
||||
"""
|
||||
# if self.IsAnyHost:
|
||||
# site = _wrap(self, axdebug.IID_IActiveScriptSite)
|
||||
# breakResume, errorResume, fCallOnError = self.debugApplication(activeScriptErrorDebug, site)
|
||||
# Do something with these!
|
||||
# else:
|
||||
trace("HandleRuntimeError")
|
||||
fCallOnError = 1
|
||||
return fCallOnError
|
||||
|
||||
def _query_interface_for_debugger_(self, iid):
|
||||
if iid in self._debugger_interfaces_:
|
||||
return self.activeScriptDebug
|
||||
trace("DebugManager QI - unknown IID", iid)
|
||||
return 0
|
||||
|
||||
def OnEnterScript(self):
|
||||
trace("OnEnterScript")
|
||||
self.adb.SetupAXDebugging(sys._getframe().f_back)
|
||||
|
||||
def OnLeaveScript(self):
|
||||
trace("OnLeaveScript")
|
||||
self.adb.ResetAXDebugging()
|
||||
|
||||
def AddScriptBlock(self, codeBlock):
|
||||
# If we don't have debugging support, don't bother.
|
||||
cc = DebugCodeBlockContainer(codeBlock, self.scriptSiteDebug)
|
||||
if self.IsSimpleHost():
|
||||
document = documents.DebugDocumentText(cc)
|
||||
document = _wrap(document, axdebug.IID_IDebugDocument)
|
||||
provider = documents.DebugDocumentProvider(document)
|
||||
provider = _wrap(provider, axdebug.IID_IDebugDocumentProvider)
|
||||
cc.debugDocument = document
|
||||
newNode = self.debugApplication.CreateApplicationNode()
|
||||
newNode.SetDocumentProvider(provider)
|
||||
newNode.Attach(self.rootNode)
|
||||
else:
|
||||
newNode = None # Managed by smart host.
|
||||
self.codeContainers[cc.sourceContext] = cc
|
||||
self.ccProvider.AddCodeContainer(cc, newNode)
|
||||
|
||||
|
||||
class DebugCodeBlockContainer(SourceCodeContainer):
|
||||
def __init__(self, codeBlock, site):
|
||||
self.codeBlock = codeBlock
|
||||
SourceCodeContainer.__init__(
|
||||
self,
|
||||
codeBlock.codeText,
|
||||
codeBlock.GetFileName(),
|
||||
codeBlock.sourceContextCookie,
|
||||
codeBlock.startLineNumber,
|
||||
site,
|
||||
)
|
||||
|
||||
def GetName(self, dnt):
|
||||
if dnt == axdebug.DOCUMENTNAMETYPE_APPNODE:
|
||||
return self.codeBlock.GetDisplayName()
|
||||
elif dnt == axdebug.DOCUMENTNAMETYPE_TITLE:
|
||||
return self.codeBlock.GetDisplayName()
|
||||
# elif dnt==axdebug.DOCUMENTNAMETYPE_FILE_TAIL:
|
||||
# elif dnt==axdebug.DOCUMENTNAMETYPE_URL:
|
||||
else:
|
||||
raise COMException(scode=winerror.S_FALSE)
|
||||
|
||||
|
||||
class EnumDebugCodeContexts(gateways.EnumDebugCodeContexts):
|
||||
def _wrap(self, ob):
|
||||
return ob
|
||||
|
||||
|
||||
class ActiveScriptDebug:
|
||||
"""The class which implements the IActiveScriptDebug interface for the Active Script engine.
|
||||
|
||||
Only ever used by smart hosts.
|
||||
"""
|
||||
|
||||
_public_methods_ = [
|
||||
"GetScriptTextAttributes",
|
||||
"GetScriptletTextAttributes",
|
||||
"EnumCodeContextsOfPosition",
|
||||
]
|
||||
_com_interfaces_ = [axdebug.IID_IActiveScriptDebug]
|
||||
|
||||
def __init__(self, debugMgr, codeContainers):
|
||||
self.debugMgr = debugMgr
|
||||
self.scriptSiteDebug = debugMgr.scriptSiteDebug
|
||||
self.codeContainers = codeContainers
|
||||
|
||||
def _Close(self):
|
||||
self.debugMgr = None
|
||||
self.scriptSiteDebug = None
|
||||
self.codeContainers = {}
|
||||
|
||||
def _query_interface_(self, iid):
|
||||
trace("DebuggerQI with", iid)
|
||||
return _wrap(self.debugMgr.scriptEngine, iid)
|
||||
|
||||
def GetScriptTextAttributes(self, code, delim, flags):
|
||||
container = SourceCodeContainer(code, "<Temp Code Block>")
|
||||
return container.GetSyntaxColorAttributes()
|
||||
|
||||
def GetScriptletTextAttributes(self, code, delim, flags):
|
||||
trace("GetScriptletTextAttributes", code, delim, flags)
|
||||
container = SourceCodeContainer(code, "<Temp Code Block>")
|
||||
return container.GetSyntaxColorAttributes()
|
||||
|
||||
def EnumCodeContextsOfPosition(self, context, charOffset, numChars):
|
||||
trace("EnumCodeContextsOfPosition", context, charOffset, numChars)
|
||||
try:
|
||||
context = self.codeContainers[context].GetCodeContextAtPosition(charOffset)
|
||||
except KeyError:
|
||||
raise COMException(scode=winerror.E_UNEXPECTED)
|
||||
enum = EnumDebugCodeContexts([context])
|
||||
return _wrap(enum, axdebug.IID_IEnumDebugCodeContexts)
|
260
venv/Lib/site-packages/win32comext/axscript/client/error.py
Normal file
260
venv/Lib/site-packages/win32comext/axscript/client/error.py
Normal file
|
@ -0,0 +1,260 @@
|
|||
"""Exception and error handling.
|
||||
|
||||
This contains the core exceptions that the implementations should raise
|
||||
as well as the IActiveScriptError interface code.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
import traceback
|
||||
import warnings
|
||||
from types import TracebackType
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import pythoncom
|
||||
import win32com.server.util
|
||||
import winerror
|
||||
from win32com.axscript import axscript
|
||||
from win32com.server.exception import COMException
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from win32comext.axscript.client.debug import DebugManager
|
||||
from win32comext.axscript.client.framework import AXScriptCodeBlock, COMScript
|
||||
from win32comext.axscript.server.axsite import AXSite
|
||||
|
||||
debugging = 0
|
||||
|
||||
|
||||
def FormatForAX(text: str):
|
||||
"""Format a string suitable for an AX Host"""
|
||||
# Replace all " with ', so it works OK in HTML (ie, ASP)
|
||||
return ExpandTabs(AddCR(text))
|
||||
|
||||
|
||||
def ExpandTabs(text: str):
|
||||
return re.sub(r"\t", " ", text)
|
||||
|
||||
|
||||
def AddCR(text: str):
|
||||
return re.sub(r"\n", "\r\n", text)
|
||||
|
||||
|
||||
class IActiveScriptError:
|
||||
"""An implementation of IActiveScriptError
|
||||
|
||||
The ActiveX Scripting host calls this client whenever we report
|
||||
an exception to it. This interface provides the exception details
|
||||
for the host to report to the user.
|
||||
"""
|
||||
|
||||
_com_interfaces_ = [axscript.IID_IActiveScriptError]
|
||||
_public_methods_ = ["GetSourceLineText", "GetSourcePosition", "GetExceptionInfo"]
|
||||
|
||||
def _query_interface_(self, iid):
|
||||
print("IActiveScriptError QI - unknown IID", iid)
|
||||
return 0
|
||||
|
||||
def _SetExceptionInfo(self, exc: AXScriptException):
|
||||
self.exception = exc
|
||||
|
||||
def GetSourceLineText(self):
|
||||
return self.exception.linetext
|
||||
|
||||
def GetSourcePosition(self):
|
||||
ctx = self.exception.sourceContext
|
||||
# Zero based in the debugger (but our columns are too!)
|
||||
return (
|
||||
ctx,
|
||||
self.exception.lineno + self.exception.startLineNo - 1,
|
||||
self.exception.colno,
|
||||
)
|
||||
|
||||
def GetExceptionInfo(self):
|
||||
return self.exception
|
||||
|
||||
|
||||
class AXScriptException(COMException):
|
||||
"""A class used as a COM exception.
|
||||
|
||||
Note this has attributes which conform to the standard attributes
|
||||
for COM exceptions, plus a few others specific to our IActiveScriptError
|
||||
object.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
site: COMScript,
|
||||
codeBlock: AXScriptCodeBlock | None,
|
||||
exc_type: None = None,
|
||||
exc_value: BaseException | None = None,
|
||||
exc_traceback: None = None,
|
||||
):
|
||||
# set properties base class shares via base ctor...
|
||||
super().__init__(
|
||||
description="Unknown Exception",
|
||||
scode=winerror.DISP_E_EXCEPTION,
|
||||
source="Python ActiveX Scripting Engine",
|
||||
)
|
||||
|
||||
if exc_type is not None or exc_traceback is not None:
|
||||
warnings.warn(
|
||||
"`exc_type` and `exc_traceback` were redundant and are now unused.",
|
||||
category=DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
|
||||
# And my other values...
|
||||
if codeBlock is None:
|
||||
self.sourceContext = 0
|
||||
self.startLineNo = 0
|
||||
else:
|
||||
self.sourceContext = codeBlock.sourceContextCookie
|
||||
self.startLineNo = codeBlock.startLineNumber
|
||||
self.linetext = ""
|
||||
|
||||
self.__BuildFromException(site, exc_value)
|
||||
|
||||
def __BuildFromException(self, site: COMScript, value: BaseException | None):
|
||||
if debugging:
|
||||
import linecache
|
||||
|
||||
linecache.clearcache()
|
||||
try:
|
||||
if isinstance(value, SyntaxError):
|
||||
self._BuildFromSyntaxError(value)
|
||||
else:
|
||||
self._BuildFromOther(site, value)
|
||||
except: # Error extracting traceback info!!!
|
||||
traceback.print_exc()
|
||||
# re-raise.
|
||||
raise
|
||||
|
||||
def _BuildFromSyntaxError(self, exc: SyntaxError):
|
||||
# Some of these may be None, which upsets us!
|
||||
msg = exc.msg or "Unknown Error"
|
||||
offset = exc.offset or 0
|
||||
line = exc.text or ""
|
||||
lineno = exc.lineno or 0
|
||||
|
||||
self.description = FormatForAX(msg)
|
||||
self.lineno = lineno
|
||||
self.colno = offset - 1
|
||||
self.linetext = ExpandTabs(line.rstrip())
|
||||
|
||||
def _BuildFromOther(self, site: COMScript, value: BaseException | None):
|
||||
tb = value.__traceback__ if value else None
|
||||
exc_type = type(value) if value else None
|
||||
self.colno = -1
|
||||
self.lineno = 0
|
||||
if debugging: # Full traceback if debugging.
|
||||
list = traceback.format_exception(exc_type, value, tb)
|
||||
self.description = ExpandTabs("".join(list))
|
||||
return
|
||||
# Run down the traceback list, looking for the first "<Script..>"
|
||||
# Hide traceback above this. In addition, keep going down
|
||||
# looking for a "_*_" attribute, and below hide these also.
|
||||
hide_names = [
|
||||
"r_import",
|
||||
"r_reload",
|
||||
"r_open",
|
||||
] # hide from these functions down in the traceback.
|
||||
tb_top = tb
|
||||
while tb_top:
|
||||
filename, lineno, name, line = self.ExtractTracebackInfo(tb_top, site)
|
||||
if filename[:7] == "<Script":
|
||||
break
|
||||
tb_top = tb_top.tb_next
|
||||
format_items = []
|
||||
if tb_top: # found one.
|
||||
tb_look: TracebackType | None = tb_top
|
||||
# Look down for our bottom
|
||||
while tb_look:
|
||||
filename, lineno, name, line = self.ExtractTracebackInfo(tb_look, site)
|
||||
if name in hide_names:
|
||||
break
|
||||
# We can report a line-number, but not a filename. Therefore,
|
||||
# we return the last line-number we find in one of our script
|
||||
# blocks.
|
||||
if filename.startswith("<Script"):
|
||||
self.lineno = lineno
|
||||
self.linetext = line
|
||||
format_items.append((filename, lineno, name, line))
|
||||
tb_look = tb_look.tb_next
|
||||
else:
|
||||
tb_top = tb
|
||||
|
||||
bits = ["Traceback (most recent call last):\n"]
|
||||
bits.extend(traceback.format_list(format_items))
|
||||
if isinstance(value, pythoncom.com_error):
|
||||
desc = f"{value.strerror} (0x{value.hresult:x})"
|
||||
if (
|
||||
value.hresult == winerror.DISP_E_EXCEPTION
|
||||
and value.excepinfo
|
||||
and value.excepinfo[2]
|
||||
):
|
||||
desc = value.excepinfo[2]
|
||||
bits.append("COM Error: " + desc)
|
||||
else:
|
||||
bits.extend(traceback.format_exception_only(exc_type, value))
|
||||
|
||||
self.description = ExpandTabs("".join(bits))
|
||||
|
||||
def ExtractTracebackInfo(self, tb: TracebackType, site: COMScript):
|
||||
import linecache
|
||||
|
||||
lineno = tb.tb_lineno
|
||||
co = tb.tb_frame.f_code
|
||||
filename = co.co_filename
|
||||
name = co.co_name
|
||||
line: str | None = linecache.getline(filename, lineno)
|
||||
if not line:
|
||||
codeBlock = site.scriptCodeBlocks.get(filename)
|
||||
if codeBlock:
|
||||
# Note: 'line' will now be unicode.
|
||||
line = codeBlock.GetLineNo(lineno)
|
||||
if line:
|
||||
line = line.strip()
|
||||
else:
|
||||
line = None
|
||||
return filename, lineno, name, line
|
||||
|
||||
|
||||
def ProcessAXScriptException(
|
||||
scriptingSite: AXSite,
|
||||
debugManager: DebugManager,
|
||||
exceptionInstance: AXScriptException,
|
||||
):
|
||||
"""General function to handle any exception in AX code
|
||||
|
||||
This function creates an instance of our IActiveScriptError interface, and
|
||||
gives it to the host, along with out exception class. The host will
|
||||
likely call back on the IActiveScriptError interface to get the source text
|
||||
and other information not normally in COM exceptions.
|
||||
"""
|
||||
# traceback.print_exc()
|
||||
instance = IActiveScriptError()
|
||||
instance._SetExceptionInfo(exceptionInstance)
|
||||
gateway = win32com.server.util.wrap(instance, axscript.IID_IActiveScriptError)
|
||||
if debugManager:
|
||||
fCallOnError = debugManager.HandleRuntimeError()
|
||||
if not fCallOnError:
|
||||
return None
|
||||
|
||||
try:
|
||||
result = scriptingSite.OnScriptError(gateway)
|
||||
except pythoncom.com_error as details:
|
||||
print("**OnScriptError failed:", details)
|
||||
print(f"Exception description: '{exceptionInstance.description!r}'")
|
||||
print(f"Exception text: '{exceptionInstance.linetext!r}'")
|
||||
result = winerror.S_FALSE
|
||||
|
||||
if result == winerror.S_OK:
|
||||
# If the above returns NOERROR, it is assumed the error has been
|
||||
# correctly registered and the value SCRIPT_E_REPORTED is returned.
|
||||
ret = COMException(scode=axscript.SCRIPT_E_REPORTED)
|
||||
return ret
|
||||
else:
|
||||
# The error is taken to be unreported and is propagated up the call stack
|
||||
# via the IDispatch::Invoke's EXCEPINFO parameter (hr returned is DISP_E_EXCEPTION.
|
||||
return exceptionInstance
|
1291
venv/Lib/site-packages/win32comext/axscript/client/framework.py
Normal file
1291
venv/Lib/site-packages/win32comext/axscript/client/framework.py
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,78 @@
|
|||
# pydumper.py
|
||||
#
|
||||
# This is being worked on - it does not yet work at all, in ay way
|
||||
# shape or form :-)
|
||||
#
|
||||
# A new script engine, derived from the standard scripting engine,
|
||||
# which dumps information.
|
||||
|
||||
# This generally can be used to grab all sorts of useful details about
|
||||
# an engine - expose bugs in it or Python, dump the object model, etc.
|
||||
|
||||
# As it is derived from the standard engine, it fully supports Python
|
||||
# as a scripting language - meaning the dumps produced can be quite dynamic,
|
||||
# and based on the script code you execute.
|
||||
|
||||
import sys
|
||||
|
||||
import win32api
|
||||
import win32con
|
||||
from win32com.axscript import axscript
|
||||
|
||||
from . import pyscript
|
||||
|
||||
PyDump_CLSID = "{ac527e60-c693-11d0-9c25-00aa00125a98}"
|
||||
|
||||
|
||||
class AXScriptAttribute(pyscript.AXScriptAttribute):
|
||||
pass
|
||||
|
||||
|
||||
class NamedScriptAttribute(pyscript.NamedScriptAttribute):
|
||||
pass
|
||||
|
||||
|
||||
class PyScript(pyscript.PyScript):
|
||||
pass
|
||||
|
||||
|
||||
def Register():
|
||||
if "-d" in sys.argv:
|
||||
dispatcher = "DispatcherWin32trace"
|
||||
debug_desc = " (" + dispatcher + ")"
|
||||
debug_option = "Yes"
|
||||
else:
|
||||
dispatcher = None
|
||||
debug_desc = ""
|
||||
debug_option = ""
|
||||
|
||||
categories = [axscript.CATID_ActiveScript, axscript.CATID_ActiveScriptParse]
|
||||
clsid = PyDump_CLSID
|
||||
lcid = 0x0409 # // english
|
||||
policy = None # "win32com.axscript.client.axspolicy.AXScriptPolicy"
|
||||
|
||||
print("Registering COM server%s..." % debug_desc)
|
||||
from win32com.server.register import RegisterServer, _set_string
|
||||
|
||||
languageName = "PyDump"
|
||||
verProgId = "Python.Dumper.1"
|
||||
RegisterServer(
|
||||
clsid=clsid,
|
||||
pythonInstString="win32com.axscript.client.pyscript.PyDumper",
|
||||
desc="Python Debugging/Dumping ActiveX Scripting Engine",
|
||||
progID=languageName,
|
||||
verProgID=verProgId,
|
||||
policy=policy,
|
||||
catids=categories,
|
||||
dispatcher=dispatcher,
|
||||
)
|
||||
|
||||
win32api.RegCreateKey(win32con.HKEY_CLASSES_ROOT, languageName + "\\OLEScript")
|
||||
# Basic Registration for wsh.
|
||||
_set_string(".pysDump", "pysDumpFile")
|
||||
_set_string("pysDumpFile\\ScriptEngine", languageName)
|
||||
print("Dumping Server registered.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
Register()
|
438
venv/Lib/site-packages/win32comext/axscript/client/pyscript.py
Normal file
438
venv/Lib/site-packages/win32comext/axscript/client/pyscript.py
Normal file
|
@ -0,0 +1,438 @@
|
|||
"""Python ActiveX Scripting Implementation
|
||||
|
||||
This module implements the Python ActiveX Scripting client.
|
||||
|
||||
To register the implementation, simply "run" this Python program - ie
|
||||
either double-click on it, or run "python.exe pyscript.py" from the
|
||||
command line.
|
||||
"""
|
||||
|
||||
import re
|
||||
import types
|
||||
|
||||
import pythoncom
|
||||
import win32com
|
||||
import win32com.client.dynamic
|
||||
import win32com.server.register
|
||||
import winerror
|
||||
from win32com.axscript import axscript
|
||||
from win32com.axscript.client import framework, scriptdispatch
|
||||
from win32com.axscript.client.framework import (
|
||||
SCRIPTTEXT_FORCEEXECUTION,
|
||||
SCRIPTTEXT_ISEXPRESSION,
|
||||
SCRIPTTEXT_ISPERSISTENT,
|
||||
trace,
|
||||
)
|
||||
from win32com.server.exception import COMException
|
||||
|
||||
PyScript_CLSID = "{DF630910-1C1D-11d0-AE36-8C0F5E000000}"
|
||||
|
||||
debugging_attr = 0
|
||||
|
||||
|
||||
def debug_attr_print(*args):
|
||||
if debugging_attr:
|
||||
trace(*args)
|
||||
|
||||
|
||||
def ExpandTabs(text):
|
||||
return re.sub(r"\t", " ", text)
|
||||
|
||||
|
||||
def AddCR(text):
|
||||
return re.sub(r"\n", "\r\n", text)
|
||||
|
||||
|
||||
class AXScriptCodeBlock(framework.AXScriptCodeBlock):
|
||||
def GetDisplayName(self):
|
||||
return "PyScript - " + framework.AXScriptCodeBlock.GetDisplayName(self)
|
||||
|
||||
|
||||
# There is only ever _one_ ax object - it exists in the global namespace
|
||||
# for all script items.
|
||||
# It performs a search from all global/visible objects
|
||||
# down.
|
||||
# This means that if 2 sub-objects of the same name are used
|
||||
# then only one is ever reachable using the ax shortcut.
|
||||
class AXScriptAttribute:
|
||||
"An attribute in a scripts namespace."
|
||||
|
||||
def __init__(self, engine):
|
||||
self.__dict__["_scriptEngine_"] = engine
|
||||
|
||||
def __getattr__(self, attr):
|
||||
if attr[1] == "_" and attr[:-1] == "_":
|
||||
raise AttributeError(attr)
|
||||
rc = self._FindAttribute_(attr)
|
||||
if rc is None:
|
||||
raise AttributeError(attr)
|
||||
return rc
|
||||
|
||||
def _Close_(self):
|
||||
self.__dict__["_scriptEngine_"] = None
|
||||
|
||||
def _DoFindAttribute_(self, obj, attr):
|
||||
try:
|
||||
return obj.subItems[attr.lower()].attributeObject
|
||||
except KeyError:
|
||||
pass
|
||||
# Check out the sub-items
|
||||
for item in obj.subItems.values():
|
||||
try:
|
||||
return self._DoFindAttribute_(item, attr)
|
||||
except AttributeError:
|
||||
pass
|
||||
raise AttributeError(attr)
|
||||
|
||||
def _FindAttribute_(self, attr):
|
||||
for item in self._scriptEngine_.subItems.values():
|
||||
try:
|
||||
return self._DoFindAttribute_(item, attr)
|
||||
except AttributeError:
|
||||
pass
|
||||
# All else fails, see if it is a global
|
||||
# (mainly b/w compat)
|
||||
return getattr(self._scriptEngine_.globalNameSpaceModule, attr)
|
||||
|
||||
|
||||
# raise AttributeError(attr)
|
||||
|
||||
|
||||
class NamedScriptAttribute:
|
||||
"An explicitly named object in an objects namespace"
|
||||
|
||||
# Each named object holds a reference to one of these.
|
||||
# Whenever a sub-item appears in a namespace, it is really one of these
|
||||
# objects. Has a circular reference back to the item itself, which is
|
||||
# closed via _Close_()
|
||||
def __init__(self, scriptItem):
|
||||
self.__dict__["_scriptItem_"] = scriptItem
|
||||
|
||||
def __repr__(self):
|
||||
return f"{self.__class__.__name__}({self._scriptItem_!r})"
|
||||
|
||||
def __getattr__(self, attr):
|
||||
# If a known subitem, return it.
|
||||
try:
|
||||
return self._scriptItem_.subItems[attr.lower()].attributeObject
|
||||
except KeyError:
|
||||
# Otherwise see if the dispatch can give it to us
|
||||
if self._scriptItem_.dispatchContainer:
|
||||
return getattr(self._scriptItem_.dispatchContainer, attr)
|
||||
raise AttributeError(attr)
|
||||
|
||||
def __setattr__(self, attr, value):
|
||||
# XXX - todo - if a known item, then should call its default
|
||||
# dispatch method.
|
||||
attr = attr.lower()
|
||||
if self._scriptItem_.dispatchContainer:
|
||||
try:
|
||||
return setattr(self._scriptItem_.dispatchContainer, attr, value)
|
||||
except AttributeError:
|
||||
pass
|
||||
raise AttributeError(attr)
|
||||
|
||||
def _Close_(self):
|
||||
self.__dict__["_scriptItem_"] = None
|
||||
|
||||
|
||||
class ScriptItem(framework.ScriptItem):
|
||||
def __init__(self, parentItem, name, dispatch, flags):
|
||||
framework.ScriptItem.__init__(self, parentItem, name, dispatch, flags)
|
||||
self.scriptlets = {}
|
||||
self.attributeObject = None
|
||||
|
||||
def Reset(self):
|
||||
framework.ScriptItem.Reset(self)
|
||||
if self.attributeObject:
|
||||
self.attributeObject._Close_()
|
||||
self.attributeObject = None
|
||||
|
||||
def Close(self):
|
||||
framework.ScriptItem.Close(self) # calls reset.
|
||||
self.dispatchContainer = None
|
||||
self.scriptlets = {}
|
||||
|
||||
def Register(self):
|
||||
framework.ScriptItem.Register(self)
|
||||
self.attributeObject = NamedScriptAttribute(self)
|
||||
if self.dispatch:
|
||||
# Need to avoid the new Python "lazy" dispatch behaviour.
|
||||
olerepr = clsid = None
|
||||
try:
|
||||
engine = self.GetEngine()
|
||||
typeinfo = self.dispatch.GetTypeInfo()
|
||||
clsid = typeinfo.GetTypeAttr()[0]
|
||||
olerepr = engine.mapKnownCOMTypes.get(clsid)
|
||||
except pythoncom.com_error:
|
||||
typeinfo = None
|
||||
if olerepr is None:
|
||||
olerepr = win32com.client.dynamic.MakeOleRepr(
|
||||
self.dispatch, typeinfo, None
|
||||
)
|
||||
if clsid is not None:
|
||||
engine.mapKnownCOMTypes[clsid] = olerepr
|
||||
self.dispatchContainer = win32com.client.dynamic.CDispatch(
|
||||
self.dispatch, olerepr, self.name
|
||||
)
|
||||
|
||||
|
||||
# self.dispatchContainer = win32com.client.dynamic.Dispatch(self.dispatch, userName = self.name)
|
||||
# self.dispatchContainer = win32com.client.dynamic.DumbDispatch(self.dispatch, userName = self.name)
|
||||
|
||||
# def Connect(self):
|
||||
# framework.ScriptItem.Connect(self)
|
||||
# def Disconnect(self):
|
||||
# framework.ScriptItem.Disconnect(self)
|
||||
|
||||
|
||||
class PyScript(framework.COMScript):
|
||||
# Setup the auto-registration stuff...
|
||||
_reg_verprogid_ = "Python.AXScript.2"
|
||||
_reg_progid_ = "Python"
|
||||
# _reg_policy_spec_ = default
|
||||
_reg_catids_ = [axscript.CATID_ActiveScript, axscript.CATID_ActiveScriptParse]
|
||||
_reg_desc_ = "Python ActiveX Scripting Engine"
|
||||
_reg_clsid_ = PyScript_CLSID
|
||||
_reg_class_spec_ = "win32com.axscript.client.pyscript.PyScript"
|
||||
_reg_remove_keys_ = [(".pys",), ("pysFile",)]
|
||||
_reg_threading_ = "both"
|
||||
|
||||
def __init__(self):
|
||||
framework.COMScript.__init__(self)
|
||||
self.globalNameSpaceModule = None
|
||||
self.codeBlocks = []
|
||||
self.scriptDispatch = None
|
||||
|
||||
def InitNew(self):
|
||||
framework.COMScript.InitNew(self)
|
||||
|
||||
self.scriptDispatch = None
|
||||
self.globalNameSpaceModule = types.ModuleType("__ax_main__")
|
||||
self.globalNameSpaceModule.__dict__["ax"] = AXScriptAttribute(self)
|
||||
|
||||
self.codeBlocks = []
|
||||
self.persistedCodeBlocks = []
|
||||
self.mapKnownCOMTypes = {} # Map of known CLSID to typereprs
|
||||
self.codeBlockCounter = 0
|
||||
|
||||
def Stop(self):
|
||||
# Flag every pending script as already done
|
||||
for b in self.codeBlocks:
|
||||
b.beenExecuted = 1
|
||||
return framework.COMScript.Stop(self)
|
||||
|
||||
def Reset(self):
|
||||
# Reset all code-blocks that are persistent, and discard the rest
|
||||
oldCodeBlocks = self.codeBlocks[:]
|
||||
self.codeBlocks = []
|
||||
for b in oldCodeBlocks:
|
||||
if b.flags & SCRIPTTEXT_ISPERSISTENT:
|
||||
b.beenExecuted = 0
|
||||
self.codeBlocks.append(b)
|
||||
return framework.COMScript.Reset(self)
|
||||
|
||||
def _GetNextCodeBlockNumber(self):
|
||||
self.codeBlockCounter += 1
|
||||
return self.codeBlockCounter
|
||||
|
||||
def RegisterNamedItem(self, item):
|
||||
wasReg = item.isRegistered
|
||||
framework.COMScript.RegisterNamedItem(self, item)
|
||||
if not wasReg:
|
||||
# Insert into our namespace.
|
||||
# Add every item by name
|
||||
if item.IsVisible():
|
||||
self.globalNameSpaceModule.__dict__[item.name] = item.attributeObject
|
||||
if item.IsGlobal():
|
||||
# Global items means sub-items are also added...
|
||||
for subitem in item.subItems.values():
|
||||
self.globalNameSpaceModule.__dict__[subitem.name] = (
|
||||
subitem.attributeObject
|
||||
)
|
||||
# Also add all methods
|
||||
for name, entry in item.dispatchContainer._olerepr_.mapFuncs.items():
|
||||
if not entry.hidden:
|
||||
self.globalNameSpaceModule.__dict__[name] = getattr(
|
||||
item.dispatchContainer, name
|
||||
)
|
||||
|
||||
def DoExecutePendingScripts(self):
|
||||
try:
|
||||
globs = self.globalNameSpaceModule.__dict__
|
||||
for codeBlock in self.codeBlocks:
|
||||
if not codeBlock.beenExecuted:
|
||||
if self.CompileInScriptedSection(codeBlock, "exec"):
|
||||
self.ExecInScriptedSection(codeBlock, globs)
|
||||
finally:
|
||||
pass
|
||||
|
||||
def DoRun(self):
|
||||
pass
|
||||
|
||||
def Close(self):
|
||||
self.ResetNamespace()
|
||||
self.globalNameSpaceModule = None
|
||||
self.codeBlocks = []
|
||||
self.scriptDispatch = None
|
||||
framework.COMScript.Close(self)
|
||||
|
||||
def GetScriptDispatch(self, name):
|
||||
# trace("GetScriptDispatch with", name)
|
||||
# if name is not None: return None
|
||||
if self.scriptDispatch is None:
|
||||
self.scriptDispatch = scriptdispatch.MakeScriptDispatch(
|
||||
self, self.globalNameSpaceModule
|
||||
)
|
||||
return self.scriptDispatch
|
||||
|
||||
def MakeEventMethodName(self, subItemName, eventName):
|
||||
return (
|
||||
subItemName[0].upper()
|
||||
+ subItemName[1:]
|
||||
+ "_"
|
||||
+ eventName[0].upper()
|
||||
+ eventName[1:]
|
||||
)
|
||||
|
||||
def DoAddScriptlet(
|
||||
self,
|
||||
defaultName,
|
||||
code,
|
||||
itemName,
|
||||
subItemName,
|
||||
eventName,
|
||||
delimiter,
|
||||
sourceContextCookie,
|
||||
startLineNumber,
|
||||
):
|
||||
# Just store the code away - compile when called. (JIT :-)
|
||||
item = self.GetNamedItem(itemName)
|
||||
if (
|
||||
itemName == subItemName
|
||||
): # Explicit handlers - eg <SCRIPT LANGUAGE="Python" for="TestForm" Event="onSubmit">
|
||||
subItem = item
|
||||
else:
|
||||
subItem = item.GetCreateSubItem(item, subItemName, None, None)
|
||||
funcName = self.MakeEventMethodName(subItemName, eventName)
|
||||
|
||||
codeBlock = AXScriptCodeBlock(
|
||||
"Script Event %s" % funcName, code, sourceContextCookie, startLineNumber, 0
|
||||
)
|
||||
self._AddScriptCodeBlock(codeBlock)
|
||||
subItem.scriptlets[funcName] = codeBlock
|
||||
|
||||
def DoProcessScriptItemEvent(self, item, event, lcid, wFlags, args):
|
||||
# trace("ScriptItemEvent", self, item, event, event.name, lcid, wFlags, args)
|
||||
funcName = self.MakeEventMethodName(item.name, event.name)
|
||||
codeBlock = function = None
|
||||
try:
|
||||
function = item.scriptlets[funcName]
|
||||
if isinstance(function, PyScript): # ie, is a CodeBlock instance
|
||||
codeBlock = function
|
||||
function = None
|
||||
except KeyError:
|
||||
pass
|
||||
if codeBlock is not None:
|
||||
realCode = "def %s():\n" % funcName
|
||||
for line in framework.RemoveCR(codeBlock.codeText).split("\n"):
|
||||
realCode += "\t" + line + "\n"
|
||||
realCode += "\n"
|
||||
if not self.CompileInScriptedSection(codeBlock, "exec", realCode):
|
||||
return
|
||||
dict = {}
|
||||
self.ExecInScriptedSection(
|
||||
codeBlock, self.globalNameSpaceModule.__dict__, dict
|
||||
)
|
||||
function = dict[funcName]
|
||||
# cache back in scriptlets as a function.
|
||||
item.scriptlets[funcName] = function
|
||||
if function is None:
|
||||
# still no function - see if in the global namespace.
|
||||
try:
|
||||
function = self.globalNameSpaceModule.__dict__[funcName]
|
||||
except KeyError:
|
||||
# Not there _exactly_ - do case ins search.
|
||||
funcNameLook = funcName.lower()
|
||||
for attr in self.globalNameSpaceModule.__dict__:
|
||||
if funcNameLook == attr.lower():
|
||||
function = self.globalNameSpaceModule.__dict__[attr]
|
||||
# cache back in scriptlets, to avoid this overhead next time
|
||||
item.scriptlets[funcName] = function
|
||||
|
||||
if function is None:
|
||||
raise COMException(scode=winerror.DISP_E_MEMBERNOTFOUND)
|
||||
return self.ApplyInScriptedSection(codeBlock, function, args)
|
||||
|
||||
def DoParseScriptText(
|
||||
self, code, sourceContextCookie, startLineNumber, bWantResult, flags
|
||||
):
|
||||
code = framework.RemoveCR(code) + "\n"
|
||||
if flags & SCRIPTTEXT_ISEXPRESSION:
|
||||
name = "Script Expression"
|
||||
exec_type = "eval"
|
||||
else:
|
||||
name = "Script Block"
|
||||
exec_type = "exec"
|
||||
num = self._GetNextCodeBlockNumber()
|
||||
if num == 1:
|
||||
num = ""
|
||||
name += f" {num}"
|
||||
codeBlock = AXScriptCodeBlock(
|
||||
name, code, sourceContextCookie, startLineNumber, flags
|
||||
)
|
||||
self._AddScriptCodeBlock(codeBlock)
|
||||
globs = self.globalNameSpaceModule.__dict__
|
||||
if bWantResult: # always immediate.
|
||||
if self.CompileInScriptedSection(codeBlock, exec_type):
|
||||
if flags & SCRIPTTEXT_ISEXPRESSION:
|
||||
return self.EvalInScriptedSection(codeBlock, globs)
|
||||
else:
|
||||
return self.ExecInScriptedSection(codeBlock, globs)
|
||||
|
||||
# else compile failed, but user chose to keep running...
|
||||
else:
|
||||
if flags & SCRIPTTEXT_FORCEEXECUTION:
|
||||
if self.CompileInScriptedSection(codeBlock, exec_type):
|
||||
self.ExecInScriptedSection(codeBlock, globs)
|
||||
else:
|
||||
self.codeBlocks.append(codeBlock)
|
||||
|
||||
def GetNamedItemClass(self):
|
||||
return ScriptItem
|
||||
|
||||
def ResetNamespace(self):
|
||||
if self.globalNameSpaceModule is not None:
|
||||
try:
|
||||
self.globalNameSpaceModule.ax._Reset_()
|
||||
except AttributeError:
|
||||
pass # ???
|
||||
globalNameSpaceModule = None
|
||||
|
||||
|
||||
def DllRegisterServer():
|
||||
klass = PyScript
|
||||
win32com.server.register._set_subkeys(
|
||||
klass._reg_progid_ + "\\OLEScript", {}
|
||||
) # Just a CreateKey
|
||||
# Basic Registration for wsh.
|
||||
win32com.server.register._set_string(".pys", "pysFile")
|
||||
win32com.server.register._set_string("pysFile\\ScriptEngine", klass._reg_progid_)
|
||||
guid_wsh_shellex = "{60254CA5-953B-11CF-8C96-00AA00B8708C}"
|
||||
win32com.server.register._set_string(
|
||||
"pysFile\\ShellEx\\DropHandler", guid_wsh_shellex
|
||||
)
|
||||
win32com.server.register._set_string(
|
||||
"pysFile\\ShellEx\\PropertySheetHandlers\\WSHProps", guid_wsh_shellex
|
||||
)
|
||||
|
||||
|
||||
def Register(klass=PyScript):
|
||||
ret = win32com.server.register.UseCommandLine(
|
||||
klass, finalize_register=DllRegisterServer
|
||||
)
|
||||
return ret
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
Register()
|
|
@ -0,0 +1,54 @@
|
|||
# A version of the ActiveScripting engine that enables rexec support
|
||||
# This version supports hosting by IE - however, due to Python's
|
||||
# rexec module being neither completely trusted nor private, it is
|
||||
# *not* enabled by default.
|
||||
# As of Python 2.2, rexec is simply not available - thus, if you use this,
|
||||
# a HTML page can do almost *anything* at all on your machine.
|
||||
|
||||
# You almost certainly do NOT want to use this!
|
||||
|
||||
import pythoncom
|
||||
from win32com.axscript import axscript
|
||||
|
||||
from . import pyscript
|
||||
|
||||
INTERFACE_USES_DISPEX = 0x00000004 # Object knows to use IDispatchEx
|
||||
INTERFACE_USES_SECURITY_MANAGER = (
|
||||
0x00000008 # Object knows to use IInternetHostSecurityManager
|
||||
)
|
||||
|
||||
|
||||
class PyScriptRExec(pyscript.PyScript):
|
||||
# Setup the auto-registration stuff...
|
||||
_reg_verprogid_ = "Python.AXScript-rexec.2"
|
||||
_reg_progid_ = "Python" # Same ProgID as the standard engine.
|
||||
# _reg_policy_spec_ = default
|
||||
_reg_catids_ = [axscript.CATID_ActiveScript, axscript.CATID_ActiveScriptParse]
|
||||
_reg_desc_ = "Python ActiveX Scripting Engine (with rexec support)"
|
||||
_reg_clsid_ = "{69c2454b-efa2-455b-988c-c3651c4a2f69}"
|
||||
_reg_class_spec_ = "win32com.axscript.client.pyscript_rexec.PyScriptRExec"
|
||||
_reg_remove_keys_ = [(".pys",), ("pysFile",)]
|
||||
_reg_threading_ = "Apartment"
|
||||
|
||||
def _GetSupportedInterfaceSafetyOptions(self):
|
||||
# print(
|
||||
# "**** calling",
|
||||
# pyscript.PyScript._GetSupportedInterfaceSafetyOptions,
|
||||
# "**->",
|
||||
# pyscript.PyScript._GetSupportedInterfaceSafetyOptions(self),
|
||||
# )
|
||||
return (
|
||||
INTERFACE_USES_DISPEX
|
||||
| INTERFACE_USES_SECURITY_MANAGER
|
||||
| axscript.INTERFACESAFE_FOR_UNTRUSTED_DATA
|
||||
| axscript.INTERFACESAFE_FOR_UNTRUSTED_CALLER
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("WARNING: By registering this engine, you are giving remote HTML code")
|
||||
print("the ability to execute *any* code on your system.")
|
||||
print()
|
||||
print("You almost certainly do NOT want to do this.")
|
||||
print("You have been warned, and are doing this at your own (significant) risk")
|
||||
pyscript.Register(PyScriptRExec)
|
|
@ -0,0 +1,103 @@
|
|||
"""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))
|
Loading…
Add table
Add a link
Reference in a new issue