Uploaded Test files

This commit is contained in:
Batuhan Berk Başoğlu 2020-11-12 11:05:57 -05:00
parent f584ad9d97
commit 2e81cb7d99
16627 changed files with 2065359 additions and 102444 deletions

View file

@ -0,0 +1,84 @@
#
# Generate scripts needed for serious testing!
#
import win32com, win32com.client.makepy
import win32com.test
import pythoncom
import sys, os
genList = [
("msword8", "{00020905-0000-0000-C000-000000000046}",1033,8,0),
]
genDir = "Generated4Test"
def GetGenPath():
import win32api
return os.path.join(win32api.GetFullPathName(win32com.test.__path__[0]), genDir)
def GenerateFromRegistered(fname, *loadArgs):
# tlb = apply(pythoncom.LoadRegTypeLib, loadArgs)
genPath = GetGenPath()
try:
os.stat(genPath)
except os.error:
os.mkdir(genPath)
# Ensure an __init__ exists.
open(os.path.join(genPath, "__init__.py"), "w").close()
print(fname, ": generating -", end=' ')
f = open(os.path.join(genPath, fname + ".py"), "w")
win32com.client.makepy.GenerateFromTypeLibSpec(loadArgs, f, bQuiet = 1, bGUIProgress = 1)
f.close()
print("compiling -", end=' ')
fullModName = "win32com.test.%s.%s" % (genDir, fname)
exec("import " + fullModName)
# Inject the generated module as a top level module.
sys.modules[fname] = sys.modules[fullModName]
print("done")
def GenerateAll():
for args in genList:
try:
GenerateFromRegistered(*args)
except KeyboardInterrupt:
print("** Interrupted ***")
break
except pythoncom.com_error:
print("** Could not generate test code for ", args[0])
def CleanAll():
print("Cleaning generated test scripts...")
try: # Clear exceptions!
1/0
except:
pass
genPath = GetGenPath()
for args in genList:
try:
name = args[0]+".py"
os.unlink(os.path.join(genPath, name))
except os.error as details:
if type(details)==type(()) and details[0]!=2:
print("Could not deleted generated", name, details)
try:
name = args[0]+".pyc"
os.unlink(os.path.join(genPath, name))
except os.error as details:
if type(details)==type(()) and details[0]!=2:
print("Could not deleted generated", name, details)
try:
os.unlink(os.path.join(genPath, "__init__.py"))
except:
pass
try:
os.unlink(os.path.join(genPath, "__init__.pyc"))
except:
pass
try:
os.rmdir(genPath)
except os.error as details:
print("Could not delete test directory -", details)
if __name__=='__main__':
GenerateAll()
CleanAll()

View file

@ -0,0 +1,64 @@
<scriptlet>
<Registration
Description="TestPys"
ProgID="TestPys.Scriptlet"
Version="1"
ClassID="{2eeb6080-cd58-11d1-b81e-00a0240b2fef}">
<SCRIPT LANGUAGE="VBScript">
Function Register()
Msgbox "Scriptlet 'Test' registered."
End Function
Function Unregister()
Msgbox "Scriptlet 'Test' unregistered."
End Function
</SCRIPT>
</Registration>
<implements id=Automation type=Automation>
<property name=PyProp1>
<get/>
<put/>
</property>
<property name=PyProp2>
<get/>
<put/>
</property>
<method name=PyMethod1>
</method>
<method name=PyMethod2>
</method>
</implements>
<script language=python>
PyProp1 = "PyScript Property1";
PyProp2 = "PyScript Property2";
def get_PyProp1():
return PyProp1
def put_PyProp1(newValue):
global PyProp1
PyProp1 = newValue
def get_PyProp2():
return PyProp2
def put_PyProp2(newValue):
global PyProp2
PyProp2 = newValue
def PyMethod1():
return "PyMethod1 called"
def PyMethod2():
return "PyMethod2 called"
</script>
</scriptlet>

View file

@ -0,0 +1 @@
# Empty file to designate a Python package

View file

@ -0,0 +1,61 @@
# import dao3032
# No longer imported here - callers responsibility to load
#
import win32com.client
def DumpDB(db, bDeep = 1):
# MUST be a DB object.
DumpTables(db,bDeep)
DumpRelations(db,bDeep)
DumpAllContainers(db,bDeep)
def DumpTables(db, bDeep = 1):
for tab in db.TableDefs:
tab = db.TableDefs(tab.Name) # Redundant lookup for testing purposes.
print("Table %s - Fields: %d, Attributes:%d" % (tab.Name, len(tab.Fields), tab.Attributes))
if bDeep: DumpFields(tab.Fields)
def DumpFields(fields):
for field in fields:
print(" %s, size=%d, reqd=%d, type=%d, defVal=%s" % (field.Name, field.Size, field.Required, field.Type, str(field.DefaultValue)))
def DumpRelations(db, bDeep = 1):
for relation in db.Relations:
print("Relation %s - %s->%s" % (relation.Name, relation.Table, relation.ForeignTable))
#### This dont work. TLB says it is a Fields collection, but apparently not!
#### if bDeep: DumpFields(relation.Fields)
def DumpAllContainers(db, bDeep = 1):
for cont in db.Containers:
print("Container %s - %d documents" % (cont.Name, len(cont.Documents)))
if bDeep: DumpContainerDocuments(cont)
def DumpContainerDocuments(container):
for doc in container.Documents:
import time
timeStr = time.ctime(int(doc.LastUpdated))
print(" %s - updated %s (" % (doc.Name, timeStr), end=' ')
print(doc.LastUpdated,")") # test the _print_ method?
def TestEngine(engine):
import sys
if len(sys.argv)>1:
dbName = sys.argv[1]
else:
dbName = "e:\\temp\\TestPython.mdb"
db = engine.OpenDatabase(dbName)
DumpDB(db)
def test():
for progid in ("DAO.DBEngine.36", "DAO.DBEngine.35", "DAO.DBEngine.30"):
try:
ob = win32com.client.gencache.EnsureDispatch(progid)
except pythoncom.com_error:
print(progid, "does not seem to be installed")
else:
TestEngine(ob)
break
if __name__=='__main__':
test()

View file

@ -0,0 +1,151 @@
# errorSemantics.py
# Test the Python error handling semantics. Specifically:
#
# * When a Python COM object is called via IDispatch, the nominated
# scode is placed in the exception tuple, and the HRESULT is
# DISP_E_EXCEPTION
# * When the same interface is called via IWhatever, the
# nominated scode is returned directly (with the scode also
# reflected in the exception tuple)
# * In all cases, the description etc end up in the exception tuple
# * "Normal" Python exceptions resolve to an E_FAIL "internal error"
import pythoncom
from win32com.server.exception import COMException
from win32com.server.util import wrap
from win32com.client import Dispatch
import winerror
from win32com.test.util import CaptureWriter
class error(Exception):
def __init__(self, msg, com_exception=None):
Exception.__init__(self, msg, str(com_exception))
# Our COM server.
class TestServer:
_public_methods_ = [ 'Clone', 'Commit', 'LockRegion', 'Read']
_com_interfaces_ = [ pythoncom.IID_IStream ]
def Clone(self):
raise COMException("Not today", scode=winerror.E_UNEXPECTED)
def Commit(self, flags):
raise Exception("foo")
def test():
# Call via a native interface.
com_server = wrap(TestServer(), pythoncom.IID_IStream)
try:
com_server.Clone()
raise error("Expecting this call to fail!")
except pythoncom.com_error as com_exc:
if com_exc.hresult != winerror.E_UNEXPECTED:
raise error("Calling the object natively did not yield the correct scode", com_exc)
exc = com_exc.excepinfo
if not exc or exc[-1] != winerror.E_UNEXPECTED:
raise error("The scode element of the exception tuple did not yield the correct scode", com_exc)
if exc[2] != "Not today":
raise error("The description in the exception tuple did not yield the correct string", com_exc)
cap = CaptureWriter()
try:
cap.capture()
try:
com_server.Commit(0)
finally:
cap.release()
raise error("Expecting this call to fail!")
except pythoncom.com_error as com_exc:
if com_exc.hresult != winerror.E_FAIL:
raise error("The hresult was not E_FAIL for an internal error", com_exc)
if com_exc.excepinfo[1] != "Python COM Server Internal Error":
raise error("The description in the exception tuple did not yield the correct string", com_exc)
# Check we saw a traceback in stderr
if cap.get_captured().find("Traceback")<0:
raise error("Could not find a traceback in stderr: %r" % (cap.get_captured(),))
# Now do it all again, but using IDispatch
com_server = Dispatch(wrap(TestServer()))
try:
com_server.Clone()
raise error("Expecting this call to fail!")
except pythoncom.com_error as com_exc:
if com_exc.hresult != winerror.DISP_E_EXCEPTION:
raise error("Calling the object via IDispatch did not yield the correct scode", com_exc)
exc = com_exc.excepinfo
if not exc or exc[-1] != winerror.E_UNEXPECTED:
raise error("The scode element of the exception tuple did not yield the correct scode", com_exc)
if exc[2] != "Not today":
raise error("The description in the exception tuple did not yield the correct string", com_exc)
cap.clear()
try:
cap.capture()
try:
com_server.Commit(0)
finally:
cap.release()
raise error("Expecting this call to fail!")
except pythoncom.com_error as com_exc:
if com_exc.hresult != winerror.DISP_E_EXCEPTION:
raise error("Calling the object via IDispatch did not yield the correct scode", com_exc)
exc = com_exc.excepinfo
if not exc or exc[-1] != winerror.E_FAIL:
raise error("The scode element of the exception tuple did not yield the correct scode", com_exc)
if exc[1] != "Python COM Server Internal Error":
raise error("The description in the exception tuple did not yield the correct string", com_exc)
# Check we saw a traceback in stderr
if cap.get_captured().find("Traceback")<0:
raise error("Could not find a traceback in stderr: %r" % (cap.get_captured(),))
try:
import logging
except ImportError:
logging = None
if logging is not None:
import win32com
class TestLogHandler(logging.Handler):
def __init__(self):
self.num_emits = 0
logging.Handler.__init__(self)
def emit(self, record):
self.num_emits += 1
return
print("--- record start")
print(self.format(record))
print("--- record end")
def testLogger():
assert not hasattr(win32com, "logger")
handler = TestLogHandler()
formatter = logging.Formatter('%(message)s')
handler.setFormatter(formatter)
log = logging.getLogger("win32com_test")
log.addHandler(handler)
win32com.logger = log
# Now throw some exceptions!
# Native interfaces
com_server = wrap(TestServer(), pythoncom.IID_IStream)
try:
com_server.Commit(0)
raise RuntimeError("should have failed")
except pythoncom.error:
pass
assert handler.num_emits == 1, handler.num_emits
handler.num_emits = 0 # reset
com_server = Dispatch(wrap(TestServer()))
try:
com_server.Commit(0)
raise RuntimeError("should have failed")
except pythoncom.error:
pass
assert handler.num_emits == 1, handler.num_emits
if __name__=='__main__':
test()
if logging is not None:
testLogger()
from .util import CheckClean
CheckClean()
print("error semantic tests worked")

View file

@ -0,0 +1,66 @@
// TestServer.idl : IDL source for TestServer.dll
//
// This file will be processed by the MIDL tool to
// produce the type library (TestServer.tlb) and marshalling code.
import "oaidl.idl";
import "ocidl.idl";
[
object,
uuid(50086EE8-F535-464B-806E-365ADBB727CF),
dual,
helpstring("ITestServerApp Interface"),
pointer_default(unique)
]
interface ITestServerApp : IDispatch
{
[id(1), helpstring("method Test1")] HRESULT Test1([out, retval] ITestServerApp **pVal);
[id(2), helpstring("method Test2")] HRESULT Test2([out, retval] VARIANT *pVar);
[propget, id(3), helpstring("property MyProp1")] HRESULT MyProp1([out, retval] long *pVal);
};
[
object,
uuid(618DB2A3-D5BD-4850-B66A-828727EB37E5),
dual,
helpstring("IPippo Interface"),
pointer_default(unique)
]
interface IPippo : IDispatch
{
[id(1), helpstring("method Method1")] HRESULT Method1([out, retval] IPippo **val);
[propget, id(2), helpstring("property MyProp1")] HRESULT MyProp1([out, retval] long *pVal);
[id(3), helpstring("method Method2")] HRESULT Method2([in] long in1, [in, out] long *inout1,
[out, retval] long *val);
[id(4), helpstring("method Method3")] HRESULT Method3([in] VARIANT in1,
[out, retval] VARIANT *val);
};
[
uuid(7783054E-9A20-4584-8C62-6ED2A08F6AC6),
version(1.0),
helpstring("TestServer 1.0 Type Library")
]
library TESTSERVERLib
{
importlib("stdole32.tlb");
importlib("stdole2.tlb");
importlib("msado15.dll");
[
uuid(49E44E89-5A72-4456-B1D5-68268A19E798),
helpstring("TestServerApp Class")
]
coclass TestServerApp
{
[default] interface ITestServerApp;
};
[
uuid(1F0F75D6-BD63-41B9-9F88-2D9D2E1AA5C3),
helpstring("Pippo Class")
]
coclass Pippo
{
[default] interface IPippo;
};
};

View file

@ -0,0 +1,85 @@
# A little test server, complete with typelib, we can use for testing.
# Originally submitted with bug:
# [ 753154 ] memory leak wrapping object having _typelib_guid_ attribute
# but modified by mhammond for use as part of the test suite.
import sys, os
import pythoncom
import win32com
import winerror
from win32com.server.util import wrap
class CPippo:
#
# COM declarations
#
_reg_clsid_ = "{1F0F75D6-BD63-41B9-9F88-2D9D2E1AA5C3}"
_reg_desc_ = "Pippo Python test object"
_reg_progid_ = "Python.Test.Pippo"
#_reg_clsctx_ = pythoncom.CLSCTX_LOCAL_SERVER
###
### Link to typelib
_typelib_guid_ = '{7783054E-9A20-4584-8C62-6ED2A08F6AC6}'
_typelib_version_ = 1, 0
_com_interfaces_ = ['IPippo']
def __init__(self):
self.MyProp1 = 10
def Method1(self):
return wrap(CPippo())
def Method2(self, in1, inout1):
return in1, inout1 * 2
def Method3(self, in1):
# in1 will be a tuple, not a list.
# Yet, we are not allowed to return a tuple, but need to convert it to a list first. (Bug?)
return list(in1)
def BuildTypelib():
from distutils.dep_util import newer
this_dir = os.path.dirname(__file__)
idl = os.path.abspath(os.path.join(this_dir, "pippo.idl"))
tlb=os.path.splitext(idl)[0] + '.tlb'
if newer(idl, tlb):
print(("Compiling %s" % (idl,)))
rc = os.system ('midl "%s"' % (idl,))
if rc:
raise RuntimeError("Compiling MIDL failed!")
# Can't work out how to prevent MIDL from generating the stubs.
# just nuke them
for fname in "dlldata.c pippo_i.c pippo_p.c pippo.h".split():
os.remove(os.path.join(this_dir, fname))
print(("Registering %s" % (tlb,)))
tli=pythoncom.LoadTypeLib(tlb)
pythoncom.RegisterTypeLib(tli,tlb)
def UnregisterTypelib():
k = CPippo
try:
pythoncom.UnRegisterTypeLib(k._typelib_guid_,
k._typelib_version_[0],
k._typelib_version_[1],
0,
pythoncom.SYS_WIN32)
print("Unregistered typelib")
except pythoncom.error as details:
if details[0]==winerror.TYPE_E_REGISTRYACCESS:
pass
else:
raise
def main(argv=None):
if argv is None: argv = sys.argv[1:]
if '--unregister' in argv:
# Unregister the type-libraries.
UnregisterTypelib()
else:
# Build and register the type-libraries.
BuildTypelib()
import win32com.server.register
win32com.server.register.UseCommandLine(CPippo)
if __name__=='__main__':
main(sys.argv)

View file

@ -0,0 +1,90 @@
import win32com.server.util
import win32com.client
import pythoncom
import winerror
import win32com.test.util
import unittest
class Error(Exception):
pass
# An object representing a list of numbers
class PythonSemanticClass:
_public_methods_ = ["In"] # DISPIDs are allocated.
_dispid_to_func_ = { 10: 'Add', 11:'Remove'} # DISPIDs specified by the object.
def __init__(self):
self.list = []
def _NewEnum(self):
return win32com.server.util.NewEnum(self.list)
def _value_(self):
# should return an array.
return self.list
def _Evaluate(self):
# return the sum
return sum(self.list)
def In(self, value):
return value in self.list
def Add(self, value):
self.list.append(value)
def Remove(self, value):
self.list.remove(value)
def DispExTest(ob):
if not __debug__: print("WARNING: Tests dressed up as assertions are being skipped!")
assert ob.GetDispID("Add", 0)==10, "Policy did not honour the dispid"
# Not impl
# assert ob.GetMemberName(10, 0)=="add", "Policy did not give me the correct function for the dispid"
assert ob.GetDispID("Remove", 0)==11, "Policy did not honour the dispid"
assert ob.GetDispID("In", 0)==1000, "Allocated dispid unexpected value"
assert ob.GetDispID("_NewEnum", 0)==pythoncom.DISPID_NEWENUM, "_NewEnum() got unexpected DISPID"
dispids = []
dispid = -1
while 1:
try:
dispid = ob.GetNextDispID(0, dispid)
dispids.append(dispid)
except pythoncom.com_error as xxx_todo_changeme:
(hr, desc, exc, arg) = xxx_todo_changeme.args
assert hr==winerror.S_FALSE, "Bad result at end of enum"
break
dispids.sort()
if dispids != [pythoncom.DISPID_EVALUATE, pythoncom.DISPID_NEWENUM, 10, 11, 1000]:
raise Error("Got back the wrong dispids: %s" % dispids)
def SemanticTest(ob):
# First just check our object "generally" as expected.
ob.Add(1)
ob.Add(2)
ob.Add(3)
# invoke _value_
if ob() != (1,2,3):
raise Error("Bad result - got %s" % (repr(ob())))
dispob = ob._oleobj_
rc = dispob.Invoke(pythoncom.DISPID_EVALUATE, 0, pythoncom.DISPATCH_METHOD|pythoncom.DISPATCH_PROPERTYGET, 1)
if rc != 6:
raise Error("Evaluate returned %d" % rc)
class Tester(win32com.test.util.TestCase):
def setUp(self):
debug=0
import win32com.server.dispatcher
if debug:
dispatcher=win32com.server.dispatcher.DefaultDebugDispatcher
else:
dispatcher=None
disp = win32com.server.util.wrap(PythonSemanticClass(), useDispatcher=dispatcher)
self.ob = win32com.client.Dispatch(disp)
def tearDown(self):
self.ob = None
def testSemantics(self):
SemanticTest(self.ob)
def testIDispatchEx(self):
dispexob = self.ob._oleobj_.QueryInterface(pythoncom.IID_IDispatchEx)
DispExTest(dispexob)
if __name__=='__main__':
unittest.main()

View file

@ -0,0 +1,18 @@
COM Test Suite Readme
---------------------
Running the test suite:
-----------------------
* Open a command prompt
* Change to the "win32com\test" directory.
* run "testall.py". This will perform level 1 testing.
You may specify 1, 2, or 3 on the command line ("testutil 3")
to execute more tests.
In general, this should just run the best it can, utilizing what is available
on the machine. It is likely some tests will refuse to run due to objects not
being locally available - this is normal.
The win32com source tree has source code to a C++ and VB component used purely
for testing. You may like to build and register these, particularly if you
are doing anything related to argument/result handling.

View file

@ -0,0 +1,74 @@
from win32com.client import Dispatch, DispatchWithEvents, constants
import pythoncom
import os
import time
finished = 0 # Flag for the wait loop from (3) to test
class ADOEvents: # event handler class
def OnWillConnect(self, str, user, pw, opt, sts, cn):
# Must have this event, as if it is not handled, ADO assumes the
# operation is cancelled, and raises an error (Operation cancelled
# by the user)
pass
def OnConnectComplete(self, error, status, connection):
# Assume no errors, until we have the basic stuff
# working. Now, "connection" should be an open
# connection to my data source
# Do the "something" from (2). For now, just
# print the connection data source
print("connection is", connection)
print("Connected to", connection.Properties("Data Source"))
# OK, our work is done. Let the main loop know
global finished
finished = 1
def OnCommitTransComplete(self, pError, adStatus, pConnection):
pass
def OnInfoMessage(self, pError, adStatus, pConnection):
pass
def OnDisconnect(self, adStatus, pConnection):
pass
def OnBeginTransComplete(self, TransactionLevel, pError, adStatus, pConnection):
pass
def OnRollbackTransComplete(self, pError, adStatus, pConnection):
pass
def OnExecuteComplete(self, RecordsAffected, pError, adStatus, pCommand, pRecordset, pConnection):
pass
def OnWillExecute(self, Source, CursorType, LockType, Options, adStatus, pCommand, pRecordset, pConnection):
pass
def TestConnection(dbname):
# Create the ADO connection object, and link the event
# handlers into it
c = DispatchWithEvents("ADODB.Connection", ADOEvents)
# Initiate the asynchronous open
dsn = "Driver={Microsoft Access Driver (*.mdb)};Dbq=%s" % dbname
user = "system"
pw = "manager"
c.Open(dsn, user, pw, constants.adAsyncConnect)
# Sit in a loop, until our event handler (above) sets the
# "finished" flag or we time out.
end_time = time.clock() + 10
while time.clock() < end_time:
# Pump messages so that COM gets a look in
pythoncom.PumpWaitingMessages()
if not finished:
print("XXX - Failed to connect!")
def Test():
from . import testAccess
try:
testAccess.GenerateSupport()
except pythoncom.com_error:
print("*** Can not import the MSAccess type libraries - tests skipped")
return
dbname = testAccess.CreateTestAccessDatabase()
try:
TestConnection(dbname)
finally:
os.unlink(dbname)
if __name__=='__main__':
Test()

View file

@ -0,0 +1,34 @@
# Test AXScripting the best we can in an automated fashion...
import win32api, os, sys
import win32com.axscript
import win32com.axscript.client
import unittest
import win32com.test.util
verbose = "-v" in sys.argv
class AXScript(win32com.test.util.TestCase):
def setUp(self):
file = win32api.GetFullPathName(os.path.join(win32com.axscript.client.__path__[0], "pyscript.py"))
from win32com.test.util import RegisterPythonServer
self.verbose = verbose
RegisterPythonServer(file, 'python', verbose=self.verbose)
def testHost(self):
file = win32api.GetFullPathName(os.path.join(win32com.axscript.__path__[0], "test\\testHost.py"))
cmd = '%s "%s"' % (win32api.GetModuleFileName(0), file)
if verbose:
print("Testing Python Scripting host")
win32com.test.util.ExecuteShellCommand(cmd, self)
def testCScript(self):
file = win32api.GetFullPathName(os.path.join(win32com.axscript.__path__[0], "Demos\\Client\\wsh\\test.pys"))
cmd = 'cscript.exe "%s"' % (file)
if verbose:
print("Testing Windows Scripting host with Python script")
win32com.test.util.ExecuteShellCommand(cmd, self)
if __name__=='__main__':
win32com.test.util.testmain()

View file

@ -0,0 +1,169 @@
#
# This assumes that you have MSAccess and DAO installed.
# You need to run makepy.py over "msaccess.tlb" and
# "dao3032.dll", and ensure the generated files are on the
# path.
# You can run this with no args, and a test database will be generated.
# You can optionally pass a dbname on the command line, in which case it will be dumped.
import pythoncom
from win32com.client import gencache, constants, Dispatch
import win32api
import os, sys
def CreateTestAccessDatabase(dbname = None):
# Creates a test access database - returns the filename.
if dbname is None:
dbname = os.path.join( win32api.GetTempPath(), "COMTestSuiteTempDatabase.mdb" )
access = Dispatch("Access.Application")
dbEngine = access.DBEngine
workspace = dbEngine.Workspaces(0)
try:
os.unlink(dbname)
except os.error:
print("WARNING - Unable to delete old test database - expect a COM exception RSN!")
newdb = workspace.CreateDatabase( dbname, constants.dbLangGeneral, constants.dbEncrypt )
# Create one test table.
table = newdb.CreateTableDef("Test Table 1")
table.Fields.Append( table.CreateField("First Name", constants.dbText ) )
table.Fields.Append( table.CreateField("Last Name", constants.dbText ) )
index = table.CreateIndex("UniqueIndex")
index.Fields.Append( index.CreateField("First Name") )
index.Fields.Append( index.CreateField("Last Name") )
index.Unique = -1
table.Indexes.Append(index)
newdb.TableDefs.Append( table )
# Create a second test table.
table = newdb.CreateTableDef("Test Table 2")
table.Fields.Append( table.CreateField("First Name", constants.dbText ) )
table.Fields.Append( table.CreateField("Last Name", constants.dbText ) )
newdb.TableDefs.Append( table )
# Create a relationship between them
relation = newdb.CreateRelation("TestRelationship")
relation.Table = "Test Table 1"
relation.ForeignTable = "Test Table 2"
field = relation.CreateField("First Name")
field.ForeignName = "First Name"
relation.Fields.Append( field )
field = relation.CreateField("Last Name")
field.ForeignName = "Last Name"
relation.Fields.Append( field )
relation.Attributes = constants.dbRelationDeleteCascade + constants.dbRelationUpdateCascade
newdb.Relations.Append(relation)
# Finally we can add some data to the table.
tab1 = newdb.OpenRecordset("Test Table 1")
tab1.AddNew()
tab1.Fields("First Name").Value = "Mark"
tab1.Fields("Last Name").Value = "Hammond"
tab1.Update()
tab1.MoveFirst()
# We do a simple bookmark test which tests our optimized VT_SAFEARRAY|VT_UI1 support.
# The bookmark will be a buffer object - remember it for later.
bk = tab1.Bookmark
# Add a second record.
tab1.AddNew()
tab1.Fields("First Name").Value = "Second"
tab1.Fields("Last Name").Value = "Person"
tab1.Update()
# Reset the bookmark to the one we saved.
# But first check the test is actually doing something!
tab1.MoveLast()
if tab1.Fields("First Name").Value != "Second":
raise RuntimeError("Unexpected record is last - makes bookmark test pointless!")
tab1.Bookmark = bk
if tab1.Bookmark != bk:
raise RuntimeError("The bookmark data is not the same")
if tab1.Fields("First Name").Value != "Mark":
raise RuntimeError("The bookmark did not reset the record pointer correctly")
return dbname
def DoDumpAccessInfo(dbname):
from . import daodump
a = forms = None
try:
sys.stderr.write("Creating Access Application...\n")
a=Dispatch("Access.Application")
print("Opening database %s" % dbname)
a.OpenCurrentDatabase(dbname)
db = a.CurrentDb()
daodump.DumpDB(db,1)
forms = a.Forms
print("There are %d forms open." % (len(forms)))
# Uncommenting these lines means Access remains open.
# for form in forms:
# print " %s" % form.Name
reports = a.Reports
print("There are %d reports open" % (len(reports)))
finally:
if not a is None:
sys.stderr.write("Closing database\n")
try:
a.CloseCurrentDatabase()
except pythoncom.com_error:
pass
# Generate all the support we can.
def GenerateSupport():
# dao
gencache.EnsureModule("{00025E01-0000-0000-C000-000000000046}", 0, 4, 0)
# Access
# gencache.EnsureModule("{4AFFC9A0-5F99-101B-AF4E-00AA003F0F07}", 0, 8, 0)
gencache.EnsureDispatch("Access.Application")
def DumpAccessInfo(dbname):
amod = gencache.GetModuleForProgID("Access.Application")
dmod = gencache.GetModuleForProgID("DAO.DBEngine.35")
if amod is None and dmod is None:
DoDumpAccessInfo(dbname)
# Now generate all the support we can.
GenerateSupport()
else:
sys.stderr.write("testAccess not doing dynamic test, as generated code already exists\n")
# Now a generated version.
DoDumpAccessInfo(dbname)
def test(dbname = None):
if dbname is None:
# We need makepy support to create a database (just for the constants!)
try:
GenerateSupport()
except pythoncom.com_error:
print("*** Can not import the MSAccess type libraries - tests skipped")
return
dbname = CreateTestAccessDatabase()
print("A test database at '%s' was created" % dbname)
DumpAccessInfo(dbname)
if __name__=='__main__':
import sys
from .util import CheckClean
dbname = None
if len(sys.argv)>1:
dbname = sys.argv[1]
test(dbname)
CheckClean()

View file

@ -0,0 +1,124 @@
# Originally contributed by Stefan Schukat as part of this arbitrary-sized
# arrays patch.
from win32com.client import gencache
from win32com.test import util
import unittest
ZeroD = 0
OneDEmpty = []
OneD = [1,2,3]
TwoD = [
[1,2,3],
[1,2,3],
[1,2,3]
]
TwoD1 = [
[
[1,2,3,5],
[1,2,3],
[1,2,3]
],
[
[1,2,3],
[1,2,3],
[1,2,3]
]
]
OneD1 = [
[
[1,2,3],
[1,2,3],
[1,2,3]
],
[
[1,2,3],
[1,2,3]
]
]
OneD2 = [
[1,2,3],
[1,2,3,4,5],
[
[1,2,3,4,5],
[1,2,3,4,5],
[1,2,3,4,5]
]
]
ThreeD = [
[
[1,2,3],
[1,2,3],
[1,2,3]
],
[
[1,2,3],
[1,2,3],
[1,2,3]
]
]
FourD = [
[
[[1,2,3],[1,2,3],[1,2,3]],
[[1,2,3],[1,2,3],[1,2,3]],
[[1,2,3],[1,2,3],[1,2,3]]
],
[
[[1,2,3],[1,2,3],[1,2,3]],
[[1,2,3],[1,2,3],[1,2,3]],
[[1,2,3],[1,2,3],[1,2,3]]
]
]
LargeD = [
[ [list(range(10))] * 10],
] * 512
def _normalize_array(a):
if type(a) != type(()):
return a
ret = []
for i in a:
ret.append(_normalize_array(i))
return ret
class ArrayTest(util.TestCase):
def setUp(self):
self.arr = gencache.EnsureDispatch("PyCOMTest.ArrayTest")
def tearDown(self):
self.arr = None
def _doTest(self, array):
self.arr.Array = array
self.failUnlessEqual(_normalize_array(self.arr.Array), array)
def testZeroD(self):
self._doTest(ZeroD)
def testOneDEmpty(self):
self._doTest(OneDEmpty)
def testOneD(self):
self._doTest(OneD)
def testTwoD(self):
self._doTest(TwoD)
def testThreeD(self):
self._doTest(ThreeD)
def testFourD(self):
self._doTest(FourD)
def testTwoD1(self):
self._doTest(TwoD1)
def testOneD1(self):
self._doTest(OneD1)
def testOneD2(self):
self._doTest(OneD2)
def testLargeD(self):
self._doTest(LargeD)
if __name__ == "__main__":
try:
util.testmain()
except SystemExit as rc:
if not rc:
raise

View file

@ -0,0 +1,160 @@
# testClipboard.py
import unittest
import pythoncom
import win32con
import winerror
import win32clipboard
from pywin32_testutil import str2bytes
from win32com.server.util import NewEnum, wrap
from win32com.server.exception import COMException
IDataObject_Methods = """GetData GetDataHere QueryGetData
GetCanonicalFormatEtc SetData EnumFormatEtc
DAdvise DUnadvise EnumDAdvise""".split()
# A COM object implementing IDataObject used for basic testing.
num_do_objects = 0
def WrapCOMObject(ob, iid=None):
return wrap(ob, iid=iid, useDispatcher = 0)
class TestDataObject:
_com_interfaces_ = [pythoncom.IID_IDataObject]
_public_methods_ = IDataObject_Methods
def __init__(self, strval):
global num_do_objects
num_do_objects += 1
self.strval = strval
self.supported_fe = []
for cf in (win32con.CF_TEXT, win32con.CF_UNICODETEXT):
fe = cf, None, pythoncom.DVASPECT_CONTENT, -1, pythoncom.TYMED_HGLOBAL
self.supported_fe.append(fe)
def __del__(self):
global num_do_objects
num_do_objects -= 1
def _query_interface_(self, iid):
if iid==pythoncom.IID_IEnumFORMATETC:
return NewEnum(self.supported_fe, iid=iid)
def GetData(self, fe):
ret_stg = None
cf, target, aspect, index, tymed = fe
if aspect & pythoncom.DVASPECT_CONTENT and \
tymed==pythoncom.TYMED_HGLOBAL:
if cf == win32con.CF_TEXT:
ret_stg = pythoncom.STGMEDIUM()
# ensure always 'bytes' by encoding string.
ret_stg.set(pythoncom.TYMED_HGLOBAL, str2bytes(self.strval))
elif cf == win32con.CF_UNICODETEXT:
ret_stg = pythoncom.STGMEDIUM()
ret_stg.set(pythoncom.TYMED_HGLOBAL, str(self.strval))
if ret_stg is None:
raise COMException(hresult=winerror.E_NOTIMPL)
return ret_stg
def GetDataHere(self, fe):
raise COMException(hresult=winerror.E_NOTIMPL)
def QueryGetData(self, fe):
cf, target, aspect, index, tymed = fe
if aspect & pythoncom.DVASPECT_CONTENT == 0:
raise COMException(hresult=winerror.DV_E_DVASPECT)
if tymed!=pythoncom.TYMED_HGLOBAL:
raise COMException(hresult=winerror.DV_E_TYMED)
return None # should check better
def GetCanonicalFormatEtc(self, fe):
RaiseCOMException(winerror.DATA_S_SAMEFORMATETC)
# return fe
def SetData(self, fe, medium):
raise COMException(hresult=winerror.E_NOTIMPL)
def EnumFormatEtc(self, direction):
if direction != pythoncom.DATADIR_GET:
raise COMException(hresult=winerror.E_NOTIMPL)
return NewEnum(self.supported_fe, iid=pythoncom.IID_IEnumFORMATETC)
def DAdvise(self, fe, flags, sink):
raise COMException(hresult=winerror.E_NOTIMPL)
def DUnadvise(self, connection):
raise COMException(hresult=winerror.E_NOTIMPL)
def EnumDAdvise(self):
raise COMException(hresult=winerror.E_NOTIMPL)
class ClipboardTester(unittest.TestCase):
def setUp(self):
pythoncom.OleInitialize()
def tearDown(self):
try:
pythoncom.OleFlushClipboard()
except pythoncom.com_error:
# We never set anything!
pass
def testIsCurrentClipboard(self):
do = TestDataObject("Hello from Python")
do = WrapCOMObject(do, iid=pythoncom.IID_IDataObject)
pythoncom.OleSetClipboard(do)
self.failUnless(pythoncom.OleIsCurrentClipboard(do))
def testComToWin32(self):
# Set the data via our DataObject
do = TestDataObject("Hello from Python")
do = WrapCOMObject(do, iid=pythoncom.IID_IDataObject)
pythoncom.OleSetClipboard(do)
# Then get it back via the standard win32 clipboard functions.
win32clipboard.OpenClipboard()
got = win32clipboard.GetClipboardData(win32con.CF_TEXT)
# CF_TEXT gives bytes on py3k - use str2bytes() to ensure that's true.
expected = str2bytes("Hello from Python")
self.assertEqual(got, expected)
# Now check unicode
got = win32clipboard.GetClipboardData(win32con.CF_UNICODETEXT)
self.assertEqual(got, "Hello from Python")
win32clipboard.CloseClipboard()
def testWin32ToCom(self):
# Set the data via the std win32 clipboard functions.
val = str2bytes("Hello again!") # ensure always bytes, even in py3k
win32clipboard.OpenClipboard()
win32clipboard.SetClipboardData(win32con.CF_TEXT, val)
win32clipboard.CloseClipboard()
# and get it via an IDataObject provided by COM
do = pythoncom.OleGetClipboard()
cf = win32con.CF_TEXT, None, pythoncom.DVASPECT_CONTENT, -1, pythoncom.TYMED_HGLOBAL
stg = do.GetData(cf)
got = stg.data
# The data we get back has the \0, as our STGMEDIUM has no way of
# knowing if it meant to be a string, or a binary buffer, so
# it must return it too.
self.failUnlessEqual(got, str2bytes("Hello again!\0"))
def testDataObjectFlush(self):
do = TestDataObject("Hello from Python")
do = WrapCOMObject(do, iid=pythoncom.IID_IDataObject)
pythoncom.OleSetClipboard(do)
self.assertEqual(num_do_objects, 1)
do = None # clear my ref!
pythoncom.OleFlushClipboard()
self.assertEqual(num_do_objects, 0)
def testDataObjectReset(self):
do = TestDataObject("Hello from Python")
do = WrapCOMObject(do)
pythoncom.OleSetClipboard(do)
do = None # clear my ref!
self.assertEqual(num_do_objects, 1)
pythoncom.OleSetClipboard(None)
self.assertEqual(num_do_objects, 0)
if __name__=='__main__':
from win32com.test import util
util.testmain()

View file

@ -0,0 +1,147 @@
# testCollections.py
#
# This code tests both the client and server side of collections
# and enumerators.
#
# Also has the side effect of testing some of the PythonCOM error semantics.
import sys
import win32com.server.util
import win32com.test.util
import win32com.client
import traceback
import pythoncom
import pywintypes
import winerror
L=pywintypes.Unicode
import unittest
error = "collection test error"
def MakeEmptyEnum():
# create the Python enumerator object as a real COM object
o = win32com.server.util.wrap( win32com.server.util.Collection() )
return win32com.client.Dispatch(o)
def MakeTestEnum():
# create a sub-collection, just to make sure it works :-)
sub = win32com.server.util.wrap( win32com.server.util.Collection( ['Sub1', 2, 'Sub3']) )
# create the Python enumerator object as a real COM object
o = win32com.server.util.wrap( win32com.server.util.Collection( [1,'Two',3, sub]))
return win32com.client.Dispatch(o)
def TestEnumAgainst(o,check):
for i in range(len(check)):
if o(i) != check[i]:
raise error("Using default method gave the incorrect value - %s/%s" % (repr(o(i)), repr(check[i])))
for i in range(len(check)):
if o.Item(i) != check[i]:
raise error("Using Item method gave the incorrect value - %s/%s" % (repr(o(i)), repr(check[i])))
# First try looping.
cmp = []
for s in o:
cmp.append(s)
if cmp[:len(check)] != check:
raise error("Result after looping isnt correct - %s/%s" % (repr(cmp[:len(check)]), repr(check)))
for i in range(len(check)):
if o[i] != check[i]:
raise error("Using indexing gave the incorrect value")
def TestEnum(quiet=None):
if quiet is None:
quiet = not "-v" in sys.argv
if not quiet: print("Simple enum test")
o = MakeTestEnum()
check = [1,'Two',3]
TestEnumAgainst(o, check)
if not quiet: print("sub-collection test")
sub = o[3]
TestEnumAgainst(sub ,['Sub1', 2, 'Sub3'])
# Remove the sublist for this test!
o.Remove(o.Count()-1)
if not quiet: print("Remove item test")
del check[1]
o.Remove(1)
TestEnumAgainst(o, check)
if not quiet: print("Add item test")
o.Add('New Item')
check.append('New Item')
TestEnumAgainst(o, check)
if not quiet: print("Insert item test")
o.Insert(2, -1)
check.insert(2, -1)
TestEnumAgainst(o, check)
### This does not work!
# if not quiet: print "Indexed replace item test"
# o[2] = 'Replaced Item'
# check[2] = 'Replaced Item'
# TestEnumAgainst(o, check)
try:
o()
raise error("default method with no args worked when it shouldnt have!")
except pythoncom.com_error as xxx_todo_changeme:
(hr, desc, exc, argErr) = xxx_todo_changeme.args
if hr != winerror.DISP_E_BADPARAMCOUNT:
raise error("Expected DISP_E_BADPARAMCOUNT - got %d (%s)" % (hr, desc))
try:
o.Insert("foo", 2)
raise error("Insert worked when it shouldnt have!")
except pythoncom.com_error as xxx_todo_changeme1:
(hr, desc, exc, argErr) = xxx_todo_changeme1.args
if hr != winerror.DISP_E_TYPEMISMATCH:
raise error("Expected DISP_E_TYPEMISMATCH - got %d (%s)" % (hr, desc))
# Remove the sublist for this test!
try:
o.Remove(o.Count())
raise error("Remove worked when it shouldnt have!")
except pythoncom.com_error as xxx_todo_changeme2:
(hr, desc, exc, argErr) = xxx_todo_changeme2.args
if hr != winerror.DISP_E_BADINDEX:
raise error("Expected DISP_E_BADINDEX - got %d (%s)" % (hr, desc))
# Test an empty collection
if not quiet: print("Empty collection test")
o = MakeEmptyEnum()
for item in o:
raise error("Empty list performed an iteration")
try:
ob = o[1]
raise error("Empty list could be indexed")
except IndexError:
pass
try:
ob = o[0]
raise error("Empty list could be indexed")
except IndexError:
pass
try:
ob = o(0)
raise error("Empty list could be indexed")
except pythoncom.com_error as xxx_todo_changeme3:
(hr, fn, desc, arg) = xxx_todo_changeme3.args
if hr != winerror.DISP_E_BADINDEX:
raise error("Expected DISP_E_BADINDEX - got %d (%s)" % (hr, desc))
class TestCase(win32com.test.util.TestCase):
def testEnum(self):
TestEnum()
if __name__=='__main__':
unittest.main()

View file

@ -0,0 +1,40 @@
# testDCOM
usage="""\
testDCOM.py - Simple DCOM test
Usage: testDCOM.py serverName
Attempts to start the Python.Interpreter object on the named machine,
and checks that the object is indeed running remotely.
Requires the named server be configured to run DCOM (using dcomcnfg.exe),
and the Python.Interpreter object installed and registered on that machine.
The Python.Interpreter object must be installed on the local machine,
but no special DCOM configuration should be necessary.
"""
# NOTE: If you configured the object locally using dcomcnfg, you could
# simple use Dispatch rather than DispatchEx.
import pythoncom, win32com.client, win32api, string, sys
def test(serverName):
if string.lower(serverName)==string.lower(win32api.GetComputerName()):
print("You must specify a remote server name, not the local machine!")
return
# Hack to overcome a DCOM limitation. As the Python.Interpreter object
# is probably installed locally as an InProc object, DCOM seems to ignore
# all settings, and use the local object.
clsctx = pythoncom.CLSCTX_SERVER & ~pythoncom.CLSCTX_INPROC_SERVER
ob = win32com.client.DispatchEx("Python.Interpreter", serverName, clsctx=clsctx)
ob.Exec("import win32api")
actualName = ob.Eval("win32api.GetComputerName()")
if string.lower(serverName) != string.lower(actualName):
print("Error: The object created on server '%s' reported its name as '%s'" % (serverName, actualName))
else:
print("Object created and tested OK on server '%s'" % serverName)
if __name__=='__main__':
if len(sys.argv) == 2:
test(sys.argv[1])
else:
print(usage)

View file

@ -0,0 +1,42 @@
from __future__ import print_function
from datetime import datetime
import unittest
import pywintypes
import win32com.client
import win32com.test.util
import win32com.server.util
from win32timezone import TimeZoneInfo
# A COM object so we can pass dates to and from the COM boundary.
class Tester:
_public_methods_ = [ 'TestDate' ]
def TestDate(self, d):
assert isinstance(d, datetime)
return d
def test_ob():
return win32com.client.Dispatch(win32com.server.util.wrap(Tester()))
class TestCase(win32com.test.util.TestCase):
def check(self, d, expected = None):
if not issubclass(pywintypes.TimeType, datetime):
self.skipTest("this is testing pywintypes and datetime")
got = test_ob().TestDate(d)
self.assertEqual(got, expected or d)
def testUTC(self):
self.check(datetime(year=2000, month=12, day=25, microsecond=500000, tzinfo=TimeZoneInfo.utc()))
def testLocal(self):
self.check(datetime(year=2000, month=12, day=25, microsecond=500000, tzinfo=TimeZoneInfo.local()))
def testMSTruncated(self):
# milliseconds are kept but microseconds are lost after rounding.
self.check(datetime(year=2000, month=12, day=25, microsecond=500500, tzinfo=TimeZoneInfo.utc()),
datetime(year=2000, month=12, day=25, microsecond=500000, tzinfo=TimeZoneInfo.utc()))
if __name__=='__main__':
unittest.main()

View file

@ -0,0 +1,94 @@
# testDictionary.py
#
import sys
import datetime
import time
import win32com.server.util
import win32com.test.util
import win32com.client
import traceback
import pythoncom
import pywintypes
import winerror
import win32timezone
import unittest
def MakeTestDictionary():
return win32com.client.Dispatch("Python.Dictionary")
def TestDictAgainst(dict,check):
for key, value in list(check.items()):
if dict(key) != value:
raise Exception("Indexing for '%s' gave the incorrect value - %s/%s" % (repr(key), repr(dict[key]), repr(check[key])))
# Ensure we have the correct version registered.
def Register(quiet):
import win32com.servers.dictionary
from win32com.test.util import RegisterPythonServer
RegisterPythonServer(win32com.servers.dictionary.__file__, 'Python.Dictionary')
def TestDict(quiet=None):
if quiet is None:
quiet = not "-v" in sys.argv
Register(quiet)
if not quiet: print("Simple enum test")
dict = MakeTestDictionary()
checkDict = {}
TestDictAgainst(dict, checkDict)
dict["NewKey"] = "NewValue"
checkDict["NewKey"] = "NewValue"
TestDictAgainst(dict, checkDict)
dict["NewKey"] = None
del checkDict["NewKey"]
TestDictAgainst(dict, checkDict)
if issubclass(pywintypes.TimeType, datetime.datetime):
now = win32timezone.now()
# We want to keep the milliseconds but discard microseconds as they
# don't survive the conversion.
now = now.replace(microsecond = round(now.microsecond / 1000) * 1000)
else:
now = pythoncom.MakeTime(time.gmtime(time.time()))
dict["Now"] = now
checkDict["Now"] = now
TestDictAgainst(dict, checkDict)
if not quiet:
print("Failure tests")
try:
dict()
raise Exception("default method with no args worked when it shouldnt have!")
except pythoncom.com_error as xxx_todo_changeme:
(hr, desc, exc, argErr) = xxx_todo_changeme.args
if hr != winerror.DISP_E_BADPARAMCOUNT:
raise Exception("Expected DISP_E_BADPARAMCOUNT - got %d (%s)" % (hr, desc))
try:
dict("hi", "there")
raise Exception("multiple args worked when it shouldnt have!")
except pythoncom.com_error as xxx_todo_changeme1:
(hr, desc, exc, argErr) = xxx_todo_changeme1.args
if hr != winerror.DISP_E_BADPARAMCOUNT:
raise Exception("Expected DISP_E_BADPARAMCOUNT - got %d (%s)" % (hr, desc))
try:
dict(0)
raise Exception("int key worked when it shouldnt have!")
except pythoncom.com_error as xxx_todo_changeme2:
(hr, desc, exc, argErr) = xxx_todo_changeme2.args
if hr != winerror.DISP_E_TYPEMISMATCH:
raise Exception("Expected DISP_E_TYPEMISMATCH - got %d (%s)" % (hr, desc))
if not quiet:
print("Python.Dictionary tests complete.")
class TestCase(win32com.test.util.TestCase):
def testDict(self):
TestDict()
if __name__=='__main__':
unittest.main()

View file

@ -0,0 +1,26 @@
' Test Pyhon.Dictionary using VBScript - this uses
' IDispatchEx, so is an interesting test.
set ob = CreateObject("Python.Dictionary")
ob("hello") = "there"
' Our keys are case insensitive.
ob.Item("hi") = ob("HELLO")
dim ok
ok = true
if ob("hello") <> "there" then
WScript.Echo "**** The dictionary value was wrong!!"
ok = false
end if
if ob("hi") <> "there" then
WScript.Echo "**** The other dictionary value was wrong!!"
ok = false
end if
if ok then
WScript.Echo "VBScript has successfully tested Python.Dictionary"
end if

View file

@ -0,0 +1,75 @@
# Test dynamic policy, and running object table.
import pythoncom
import winerror
from win32com.server.exception import Exception
error = "testDynamic error"
iid = pythoncom.MakeIID("{b48969a0-784b-11d0-ae71-d23f56000000}")
class VeryPermissive:
def _dynamic_(self, name, lcid, wFlags, args):
if wFlags & pythoncom.DISPATCH_METHOD:
return getattr(self,name)(*args)
if wFlags & pythoncom.DISPATCH_PROPERTYGET:
try:
# to avoid problems with byref param handling, tuple results are converted to lists.
ret = self.__dict__[name]
if type(ret)==type(()):
ret = list(ret)
return ret
except KeyError: # Probably a method request.
raise Exception(scode=winerror.DISP_E_MEMBERNOTFOUND)
if wFlags & (pythoncom.DISPATCH_PROPERTYPUT | pythoncom.DISPATCH_PROPERTYPUTREF):
setattr(self, name, args[0])
return
raise Exception(scode=winerror.E_INVALIDARG, desc="invalid wFlags")
def write(self, *args):
if len(args)==0:
raise Exception(scode=winerror.DISP_E_BADPARAMCOUNT) # Probably call as PROPGET.
for arg in args[:-1]:
print(str(arg), end=' ')
print(str(args[-1]))
def Test():
import win32com.server.util, win32com.server.policy
# import win32dbg;win32dbg.brk()
ob = win32com.server.util.wrap(VeryPermissive(),usePolicy=win32com.server.policy.DynamicPolicy)
try:
handle = pythoncom.RegisterActiveObject(ob, iid, 0)
except pythoncom.com_error as details:
print("Warning - could not register the object in the ROT:", details)
handle = None
try:
import win32com.client.dynamic
client = win32com.client.dynamic.Dispatch(iid)
client.ANewAttr = "Hello"
if client.ANewAttr != "Hello":
raise error("Could not set dynamic property")
v = ["Hello","From","Python",1.4]
client.TestSequence = v
if v != list(client.TestSequence):
raise error("Dynamic sequences not working! %r/%r" % (repr(v), repr(client.testSequence)))
client.write("This","output","has","come","via","COM")
# Check our new "_FlagAsMethod" works (kinda!)
client._FlagAsMethod("NotReallyAMethod")
if not callable(client.NotReallyAMethod):
raise error("Method I flagged as callable isn't!")
client = None
finally:
if handle is not None:
pythoncom.RevokeActiveObject(handle)
if __name__=='__main__':
Test()

View file

@ -0,0 +1,112 @@
# TestExchange = Exchange Server Dump
# Note that this code uses "CDO", which is unlikely to get the best choice.
# You should use the Outlook object model, or
# the win32com.mapi examples for a low-level interface.
from win32com.client import gencache, constants
import pythoncom
import os
ammodule = None # was the generated module!
def GetDefaultProfileName():
import win32api, win32con
try:
key = win32api.RegOpenKey(win32con.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows Messaging Subsystem\\Profiles")
try:
return win32api.RegQueryValueEx(key, "DefaultProfile")[0]
finally:
key.Close()
except win32api.error:
return None
#
# Recursive dump of folders.
#
def DumpFolder(folder, indent = 0):
print(" " * indent, folder.Name)
folders = folder.Folders
folder = folders.GetFirst()
while folder:
DumpFolder(folder, indent+1)
folder = folders.GetNext()
def DumpFolders(session):
try:
infostores = session.InfoStores
except AttributeError:
# later outlook?
store = session.DefaultStore
folder = store.GetRootFolder()
DumpFolder(folder)
return
print(infostores)
print("There are %d infostores" % infostores.Count)
for i in range(infostores.Count):
infostore = infostores[i+1]
print("Infostore = ", infostore.Name)
try:
folder = infostore.RootFolder
except pythoncom.com_error as details:
hr, msg, exc, arg = details
# -2147221219 == MAPI_E_FAILONEPROVIDER - a single provider temporarily not available.
if exc and exc[-1]==-2147221219:
print("This info store is currently not available")
continue
DumpFolder(folder)
# Build a dictionary of property tags, so I can reverse look-up
#
PropTagsById={}
if ammodule:
for name, val in ammodule.constants.__dict__.items():
PropTagsById[val] = name
def TestAddress(session):
# entry = session.GetAddressEntry("Skip")
# print entry
pass
def TestUser(session):
ae = session.CurrentUser
fields = getattr(ae, "Fields", [])
print("User has %d fields" % len(fields))
for f in range(len(fields)):
field = fields[f+1]
try:
id = PropTagsById[field.ID]
except KeyError:
id = field.ID
print("%s/%s=%s" % (field.Name, id, field.Value))
def test():
import win32com.client
oldcwd = os.getcwd()
try:
session = gencache.EnsureDispatch("MAPI.Session")
try:
session.Logon(GetDefaultProfileName())
except pythoncom.com_error as details:
print("Could not log on to MAPI:", details)
return
except pythoncom.error:
# no mapi.session - let's try outlook
app = gencache.EnsureDispatch("Outlook.Application")
session = app.Session
try:
TestUser(session)
TestAddress(session)
DumpFolders(session)
finally:
session.Logoff()
# It appears Exchange will change the cwd on us :(
os.chdir(oldcwd)
if __name__=='__main__':
from .util import CheckClean
test()
CheckClean()

View file

@ -0,0 +1,106 @@
# testExplorer -
import sys
import os
import win32com.client.dynamic
from win32com.client import Dispatch
import win32api
import win32gui
import win32con
import winerror
import glob
import pythoncom
import time
from win32com.test.util import CheckClean
bVisibleEventFired = 0
class ExplorerEvents:
def OnVisible(self, visible):
global bVisibleEventFired
bVisibleEventFired = 1
def TestExplorerEvents():
global bVisibleEventFired
iexplore = win32com.client.DispatchWithEvents("InternetExplorer.Application", ExplorerEvents)
iexplore.Visible = 1
if not bVisibleEventFired:
raise RuntimeError("The IE event did not appear to fire!")
iexplore.Quit()
iexplore = None
bVisibleEventFired = 0
ie = win32com.client.Dispatch("InternetExplorer.Application")
ie_events = win32com.client.DispatchWithEvents(ie, ExplorerEvents)
ie.Visible = 1
if not bVisibleEventFired:
raise RuntimeError("The IE event did not appear to fire!")
ie.Quit()
ie = None
print("IE Event tests worked.")
def TestObjectFromWindow():
# Check we can use ObjectFromLresult to get the COM object from the
# HWND - see KB Q249232
# Locating the HWND is different than the KB says...
hwnd = win32gui.FindWindow('IEFrame', None)
for child_class in ['TabWindowClass', 'Shell DocObject View',
'Internet Explorer_Server']:
hwnd = win32gui.FindWindowEx(hwnd, 0, child_class, None)
# ack - not working for markh on vista with IE8 (or maybe it is the
# lack of the 'accessibility' components mentioned in Q249232)
# either way - not working!
return
# But here is the point - once you have an 'Internet Explorer_Server',
# you can send a message and use ObjectFromLresult to get it back.
msg = win32gui.RegisterWindowMessage("WM_HTML_GETOBJECT")
rc, result = win32gui.SendMessageTimeout(hwnd, msg, 0, 0, win32con.SMTO_ABORTIFHUNG, 1000)
ob = pythoncom.ObjectFromLresult(result, pythoncom.IID_IDispatch, 0)
doc = Dispatch(ob)
# just to prove it works, set the background color of the document.
for color in "red green blue orange white".split():
doc.bgColor = color
time.sleep(0.2)
def TestExplorer(iexplore):
if not iexplore.Visible: iexplore.Visible = -1
iexplore.Navigate(win32api.GetFullPathName('..\\readme.htm'))
win32api.Sleep(1000)
TestObjectFromWindow()
win32api.Sleep(3000)
try:
iexplore.Quit()
except (AttributeError, pythoncom.com_error):
# User got sick of waiting :)
pass
def TestAll():
try:
try:
iexplore = win32com.client.dynamic.Dispatch("InternetExplorer.Application")
TestExplorer(iexplore)
win32api.Sleep(1000)
iexplore = None
# Test IE events.
TestExplorerEvents()
# Give IE a chance to shutdown, else it can get upset on fast machines.
time.sleep(2)
# Note that the TextExplorerEvents will force makepy - hence
# this gencache is really no longer needed.
from win32com.client import gencache
gencache.EnsureModule("{EAB22AC0-30C1-11CF-A7EB-0000C05BAE0B}", 0, 1, 1)
iexplore = win32com.client.Dispatch("InternetExplorer.Application")
TestExplorer(iexplore)
except pythoncom.com_error as exc:
if exc.hresult!=winerror.RPC_E_DISCONNECTED: # user closed the app!
raise
finally:
iexplore = None
if __name__=='__main__':
TestAll()
CheckClean()

View file

@ -0,0 +1,119 @@
"""Testing pasing object between multiple COM threads
Uses standard COM marshalling to pass objects between threads. Even
though Python generally seems to work when you just pass COM objects
between threads, it shouldnt.
This shows the "correct" way to do it.
It shows that although we create new threads to use the Python.Interpreter,
COM marshalls back all calls to that object to the main Python thread,
which must be running a message loop (as this sample does).
When this test is run in "free threaded" mode (at this stage, you must
manually mark the COM objects as "ThreadingModel=Free", or run from a
service which has marked itself as free-threaded), then no marshalling
is done, and the Python.Interpreter object start doing the "expected" thing
- ie, it reports being on the same thread as its caller!
Python.exe needs a good way to mark itself as FreeThreaded - at the moment
this is a pain in the but!
"""
import _thread, traceback
import win32com.client
import win32event, win32api
import pythoncom
def TestInterp(interp):
if interp.Eval("1+1") != 2:
raise ValueError("The interpreter returned the wrong result.")
try:
interp.Eval(1+1)
raise ValueError("The interpreter did not raise an exception")
except pythoncom.com_error as details:
import winerror
if details[0]!=winerror.DISP_E_TYPEMISMATCH:
raise ValueError("The interpreter exception was not winerror.DISP_E_TYPEMISMATCH.")
def TestInterpInThread(stopEvent, cookie):
try:
DoTestInterpInThread(cookie)
finally:
win32event.SetEvent(stopEvent)
def CreateGIT():
return pythoncom.CoCreateInstance(pythoncom.CLSID_StdGlobalInterfaceTable,
None,
pythoncom.CLSCTX_INPROC,
pythoncom.IID_IGlobalInterfaceTable)
def DoTestInterpInThread(cookie):
try:
pythoncom.CoInitialize()
myThread = win32api.GetCurrentThreadId()
GIT = CreateGIT()
interp = GIT.GetInterfaceFromGlobal(cookie, pythoncom.IID_IDispatch)
interp = win32com.client.Dispatch(interp)
TestInterp(interp)
interp.Exec("import win32api")
print("The test thread id is %d, Python.Interpreter's thread ID is %d" % (myThread, interp.Eval("win32api.GetCurrentThreadId()")))
interp = None
pythoncom.CoUninitialize()
except:
traceback.print_exc()
def BeginThreadsSimpleMarshal(numThreads, cookie):
"""Creates multiple threads using simple (but slower) marshalling.
Single interpreter object, but a new stream is created per thread.
Returns the handles the threads will set when complete.
"""
ret = []
for i in range(numThreads):
hEvent = win32event.CreateEvent(None, 0, 0, None)
_thread.start_new(TestInterpInThread, (hEvent, cookie))
ret.append(hEvent)
return ret
def test(fn):
print("The main thread is %d" % (win32api.GetCurrentThreadId()))
GIT = CreateGIT()
interp = win32com.client.Dispatch("Python.Interpreter")
cookie = GIT.RegisterInterfaceInGlobal(interp._oleobj_, pythoncom.IID_IDispatch)
events = fn(4, cookie)
numFinished = 0
while 1:
try:
rc = win32event.MsgWaitForMultipleObjects(events, 0, 2000, win32event.QS_ALLINPUT)
if rc >= win32event.WAIT_OBJECT_0 and rc < win32event.WAIT_OBJECT_0+len(events):
numFinished = numFinished + 1
if numFinished >= len(events):
break
elif rc==win32event.WAIT_OBJECT_0 + len(events): # a message
# This is critical - whole apartment model demo will hang.
pythoncom.PumpWaitingMessages()
else: # Timeout
print("Waiting for thread to stop with interfaces=%d, gateways=%d" % (pythoncom._GetInterfaceCount(), pythoncom._GetGatewayCount()))
except KeyboardInterrupt:
break
GIT.RevokeInterfaceFromGlobal(cookie)
del interp
del GIT
if __name__=='__main__':
test(BeginThreadsSimpleMarshal)
win32api.Sleep(500)
# Doing CoUninit here stop Pythoncom.dll hanging when DLLMain shuts-down the process
pythoncom.CoUninitialize()
if pythoncom._GetInterfaceCount()!=0 or pythoncom._GetGatewayCount()!=0:
print("Done with interfaces=%d, gateways=%d" % (pythoncom._GetInterfaceCount(), pythoncom._GetGatewayCount()))
else:
print("Done.")

View file

@ -0,0 +1,133 @@
# The purpose of this test is to ensure that the gateways objects
# do the right thing WRT COM rules about object identity etc.
# Also includes a basic test that we support inheritance correctly in
# gateway interfaces.
# For our test, we create an object of type IID_IPersistStorage
# This interface derives from IPersist.
# Therefore, QI's for IID_IDispatch, IID_IUnknown, IID_IPersist and
# IID_IPersistStorage should all return the same gateway object.
#
# In addition, the interface should only need to declare itself as
# using the IPersistStorage interface, and as the gateway derives
# from IPersist, it should automatically be available without declaration.
#
# We also create an object of type IID_I??, and perform a QI for it.
# We then jump through a number of hoops, ensuring that the objects
# returned by the QIs follow all the rules.
#
# Here is Gregs summary of the rules:
# 1) the set of supported interfaces is static and unchanging
# 2) symmetric: if you QI an interface for that interface, it succeeds
# 3) reflexive: if you QI against A for B, the new pointer must succeed
# for a QI for A
# 4) transitive: if you QI for B, then QI that for C, then QI'ing A for C
# must succeed
#
#
# Note that 1) Requires cooperation of the Python programmer. The rule to keep is:
# "whenever you return an _object_ from _query_interface_(), you must return the
# same object each time for a given IID. Note that you must return the same
# _wrapped_ object
# you
# The rest are tested here.
from win32com.server.util import wrap
import pythoncom
from .util import CheckClean
numErrors = 0
# Check that the 2 objects both have identical COM pointers.
def CheckSameCOMObject(ob1, ob2):
addr1 = repr(ob1).split()[6][:-1]
addr2 = repr(ob2).split()[6][:-1]
return addr1==addr2
# Check that the objects conform to COM identity rules.
def CheckObjectIdentity(ob1, ob2):
u1 = ob1.QueryInterface(pythoncom.IID_IUnknown)
u2 = ob2.QueryInterface(pythoncom.IID_IUnknown)
return CheckSameCOMObject(u1, u2)
def FailObjectIdentity(ob1, ob2, when):
if not CheckObjectIdentity(ob1, ob2):
global numErrors
numErrors = numErrors + 1
print(when, "are not identical (%s, %s)" % (repr(ob1), repr(ob2)))
class Dummy:
_public_methods_ = [] # We never attempt to make a call on this object.
_com_interfaces_ = [pythoncom.IID_IPersistStorage]
class Dummy2:
_public_methods_ = [] # We never attempt to make a call on this object.
_com_interfaces_ = [pythoncom.IID_IPersistStorage, pythoncom.IID_IExternalConnection]
class DeletgatedDummy:
_public_methods_ = []
class Dummy3:
_public_methods_ = [] # We never attempt to make a call on this object.
_com_interfaces_ = [pythoncom.IID_IPersistStorage]
def _query_interface_(self, iid):
if iid==pythoncom.IID_IExternalConnection:
# This will NEVER work - can only wrap the object once!
return wrap(DelegatedDummy())
def TestGatewayInheritance():
# By default, wrap() creates and discards a temporary object.
# This is not necessary, but just the current implementation of wrap.
# As the object is correctly discarded, it doesnt affect this test.
o = wrap(Dummy(), pythoncom.IID_IPersistStorage)
o2 = o.QueryInterface(pythoncom.IID_IUnknown)
FailObjectIdentity(o, o2, "IID_IPersistStorage->IID_IUnknown")
o3 = o2.QueryInterface(pythoncom.IID_IDispatch)
FailObjectIdentity(o2, o3, "IID_IUnknown->IID_IDispatch")
FailObjectIdentity(o, o3, "IID_IPersistStorage->IID_IDispatch")
o4 = o3.QueryInterface(pythoncom.IID_IPersistStorage)
FailObjectIdentity(o, o4, "IID_IPersistStorage->IID_IPersistStorage(2)")
FailObjectIdentity(o2, o4, "IID_IUnknown->IID_IPersistStorage(2)")
FailObjectIdentity(o3, o4, "IID_IDispatch->IID_IPersistStorage(2)")
o5 = o4.QueryInterface(pythoncom.IID_IPersist)
FailObjectIdentity(o, o5, "IID_IPersistStorage->IID_IPersist")
FailObjectIdentity(o2, o5, "IID_IUnknown->IID_IPersist")
FailObjectIdentity(o3, o5, "IID_IDispatch->IID_IPersist")
FailObjectIdentity(o4, o5, "IID_IPersistStorage(2)->IID_IPersist")
def TestMultiInterface():
o = wrap(Dummy2(), pythoncom.IID_IPersistStorage)
o2 = o.QueryInterface(pythoncom.IID_IExternalConnection)
FailObjectIdentity(o, o2, "IID_IPersistStorage->IID_IExternalConnection")
# Make the same QI again, to make sure it is stable.
o22 = o.QueryInterface(pythoncom.IID_IExternalConnection)
FailObjectIdentity(o, o22, "IID_IPersistStorage->IID_IExternalConnection")
FailObjectIdentity(o2, o22, "IID_IPersistStorage->IID_IExternalConnection (stability)")
o3 = o2.QueryInterface(pythoncom.IID_IPersistStorage)
FailObjectIdentity(o2, o3, "IID_IExternalConnection->IID_IPersistStorage")
FailObjectIdentity(o, o3, "IID_IPersistStorage->IID_IExternalConnection->IID_IPersistStorage")
def test():
TestGatewayInheritance()
TestMultiInterface()
if numErrors==0:
print("Worked ok")
else:
print("There were", numErrors, "errors.")
if __name__=='__main__':
test()
CheckClean()

View file

@ -0,0 +1,12 @@
set o = CreateObject("Python.Interpreter")
if o.Eval("1+1") <> 2 Then
WScript.Echo "Eval('1+1') failed"
bFailed = True
end if
if bFailed then
WScript.Echo "*********** VBScript tests failed *********"
else
WScript.Echo "VBScript test worked OK"
end if

View file

@ -0,0 +1,132 @@
from __future__ import generators
# Some raw iter tests. Some "high-level" iterator tests can be found in
# testvb.py and testOutlook.py
import sys
import unittest
from win32com.client.gencache import EnsureDispatch
from win32com.client import Dispatch
import win32com.server.util
import win32com.test.util
import pythoncom
def yield_iter(iter):
while 1:
yield next(iter)
class _BaseTestCase(win32com.test.util.TestCase):
def test_enumvariant_vb(self):
ob, iter = self.iter_factory()
got=[]
for v in iter:
got.append(v)
self.assertEquals(got, self.expected_data)
def test_yield(self):
ob, i = self.iter_factory()
got=[]
for v in yield_iter(iter(i)):
got.append(v)
self.assertEquals(got, self.expected_data)
def _do_test_nonenum(self, object):
try:
for i in object:
pass
self.fail("Could iterate over a non-iterable object")
except TypeError:
pass # this is expected.
self.assertRaises(TypeError, iter, object)
self.assertRaises(AttributeError, getattr, object, "next")
def test_nonenum_wrapper(self):
# Check our raw PyIDispatch
ob = self.object._oleobj_
try:
for i in ob:
pass
self.fail("Could iterate over a non-iterable object")
except TypeError:
pass # this is expected.
self.assertRaises(TypeError, iter, ob)
self.assertRaises(AttributeError, getattr, ob, "next")
# And our Dispatch wrapper
ob = self.object
try:
for i in ob:
pass
self.fail("Could iterate over a non-iterable object")
except TypeError:
pass # this is expected.
# Note that as our object may be dynamic, we *do* have a __getitem__
# method, meaning we *can* call iter() on the object. In this case
# actual iteration is what fails.
# So either the 'iter(); will raise a type error, or an attempt to
# fetch it
try:
next(iter(ob))
self.fail("Expected a TypeError fetching this iterator")
except TypeError:
pass
# And it should never have a 'next' method
self.assertRaises(AttributeError, getattr, ob, "next")
class VBTestCase(_BaseTestCase):
def setUp(self):
def factory():
# Our VB test harness exposes a property with IEnumVariant.
ob = self.object.EnumerableCollectionProperty
for i in self.expected_data:
ob.Add(i)
# Get the raw IEnumVARIANT.
invkind = pythoncom.DISPATCH_METHOD | pythoncom.DISPATCH_PROPERTYGET
iter = ob._oleobj_.InvokeTypes(pythoncom.DISPID_NEWENUM,0,invkind,(13, 10),())
return ob, iter.QueryInterface(pythoncom.IID_IEnumVARIANT)
# We *need* generated dispatch semantics, so dynamic __getitem__ etc
# don't get in the way of our tests.
self.object = EnsureDispatch("PyCOMVBTest.Tester")
self.expected_data = [1, "Two", "3"]
self.iter_factory = factory
def tearDown(self):
self.object = None
# Test our client semantics, but using a wrapped Python list object.
# This has the effect of re-using our client specific tests, but in this
# case is exercising the server side.
class SomeObject:
_public_methods_ = ["GetCollection"]
def __init__(self, data):
self.data = data
def GetCollection(self):
return win32com.server.util.NewCollection(self.data)
class WrappedPythonCOMServerTestCase(_BaseTestCase):
def setUp(self):
def factory():
ob = self.object.GetCollection()
flags = pythoncom.DISPATCH_METHOD | pythoncom.DISPATCH_PROPERTYGET
enum = ob._oleobj_.Invoke(pythoncom.DISPID_NEWENUM, 0, flags, 1)
return ob, enum.QueryInterface(pythoncom.IID_IEnumVARIANT)
self.expected_data = [1,'Two',3]
sv = win32com.server.util.wrap(SomeObject(self.expected_data))
self.object = Dispatch(sv)
self.iter_factory = factory
def tearDown(self):
self.object = None
def suite():
# We dont want our base class run
suite = unittest.TestSuite()
for item in globals().values():
if type(item)==type(unittest.TestCase) and \
issubclass(item, unittest.TestCase) and \
item != _BaseTestCase:
suite.addTest(unittest.makeSuite(item))
return suite
if __name__=='__main__':
unittest.main(argv=sys.argv + ['suite'])

View file

@ -0,0 +1,163 @@
# Test MSOffice
#
# Main purpose of test is to ensure that Dynamic COM objects
# work as expected.
# Assumes Word and Excel installed on your machine.
import win32com, sys, string, win32api, traceback
import win32com.client.dynamic
from win32com.test.util import CheckClean
import pythoncom
from win32com.client import gencache
from pywintypes import Unicode
error = "MSOffice test error"
# Test a few of the MSOffice components.
def TestWord():
# Try and load the object exposed by Word 8
# Office 97 - _totally_ different object model!
try:
# NOTE - using "client.Dispatch" would return an msword8.py instance!
print("Starting Word 8 for dynamic test")
word = win32com.client.dynamic.Dispatch("Word.Application")
TestWord8(word)
word = None
# Now we will test Dispatch without the new "lazy" capabilities
print("Starting Word 8 for non-lazy dynamic test")
dispatch = win32com.client.dynamic._GetGoodDispatch("Word.Application")
typeinfo = dispatch.GetTypeInfo()
attr = typeinfo.GetTypeAttr()
olerepr = win32com.client.build.DispatchItem(typeinfo, attr, None, 0)
word = win32com.client.dynamic.CDispatch(dispatch, olerepr)
dispatch = typeinfo = attr = olerepr = None
TestWord8(word)
except pythoncom.com_error:
print("Starting Word 7 for dynamic test")
word = win32com.client.Dispatch("Word.Basic")
TestWord7(word)
print("Starting MSWord for generated test")
from win32com.client import gencache
word = gencache.EnsureDispatch("Word.Application.8")
TestWord8(word)
def TestWord7(word):
word.FileNew()
# If not shown, show the app.
if not word.AppShow(): word._proc_("AppShow")
for i in range(12):
word.FormatFont(Color=i+1, Points=i+12)
word.Insert("Hello from Python %d\n" % i)
word.FileClose(2)
def TestWord8(word):
word.Visible = 1
doc = word.Documents.Add()
wrange = doc.Range()
for i in range(10):
wrange.InsertAfter("Hello from Python %d\n" % i)
paras = doc.Paragraphs
for i in range(len(paras)):
p = paras[i]()
p.Font.ColorIndex = i+1
p.Font.Size = 12 + (4 * i)
# XXX - note that
# for para in paras:
# para().Font...
# doesnt seem to work - no error, just doesnt work
# Should check if it works for VB!
doc.Close(SaveChanges = 0)
word.Quit()
win32api.Sleep(1000) # Wait for word to close, else we
# may get OA error.
def TestWord8OldStyle():
try:
import win32com.test.Generated4Test.msword8
except ImportError:
print("Can not do old style test")
def TextExcel(xl):
xl.Visible = 0
if xl.Visible: raise error("Visible property is true.")
xl.Visible = 1
if not xl.Visible: raise error("Visible property not true.")
if int(xl.Version[0])>=8:
xl.Workbooks.Add()
else:
xl.Workbooks().Add()
xl.Range("A1:C1").Value = (1,2,3)
xl.Range("A2:C2").Value = ('x','y','z')
xl.Range("A3:C3").Value = ('3','2','1')
for i in range(20):
xl.Cells(i+1,i+1).Value = "Hi %d" % i
if xl.Range("A1").Value != "Hi 0":
raise error("Single cell range failed")
if xl.Range("A1:B1").Value != ((Unicode("Hi 0"),2),):
raise error("flat-horizontal cell range failed")
if xl.Range("A1:A2").Value != ((Unicode("Hi 0"),),(Unicode("x"),)):
raise error("flat-vertical cell range failed")
if xl.Range("A1:C3").Value != ((Unicode("Hi 0"),2,3),(Unicode("x"),Unicode("Hi 1"),Unicode("z")),(3,2,Unicode("Hi 2"))):
raise error("square cell range failed")
xl.Range("A1:C3").Value =((3,2,1),("x","y","z"),(1,2,3))
if xl.Range("A1:C3").Value != ((3,2,1),(Unicode("x"),Unicode("y"),Unicode("z")),(1,2,3)):
raise error("Range was not what I set it to!")
# test dates out with Excel
xl.Cells(5,1).Value = "Excel time"
xl.Cells(5,2).Formula = "=Now()"
import time
xl.Cells(6,1).Value = "Python time"
xl.Cells(6,2).Value = pythoncom.MakeTime(time.time())
xl.Cells(6,2).NumberFormat = "d/mm/yy h:mm"
xl.Columns("A:B").EntireColumn.AutoFit()
xl.Workbooks(1).Close(0)
xl.Quit()
def TestAll():
TestWord()
print("Starting Excel for Dynamic test...")
xl = win32com.client.dynamic.Dispatch("Excel.Application")
TextExcel(xl)
try:
print("Starting Excel 8 for generated excel8.py test...")
mod = gencache.EnsureModule("{00020813-0000-0000-C000-000000000046}", 0, 1, 2, bForDemand=1)
xl = win32com.client.Dispatch("Excel.Application")
TextExcel(xl)
except ImportError:
print("Could not import the generated Excel 97 wrapper")
try:
import xl5en32
mod = gencache.EnsureModule("{00020813-0000-0000-C000-000000000046}", 9, 1, 0)
xl = win32com.client.Dispatch("Excel.Application.5")
print("Starting Excel 95 for makepy test...")
TextExcel(xl)
except ImportError:
print("Could not import the generated Excel 95 wrapper")
if __name__=='__main__':
TestAll()
CheckClean()
pythoncom.CoUninitialize()

View file

@ -0,0 +1,115 @@
# OfficeEvents - test/demonstrate events with Word and Excel.
from win32com.client import DispatchWithEvents, Dispatch
import msvcrt, pythoncom
import time, sys
import types
import threading
stopEvent = threading.Event()
def TestExcel():
class ExcelEvents:
def OnNewWorkbook(self, wb):
if type(wb) != types.InstanceType:
raise RuntimeError("The transformer doesnt appear to have translated this for us!")
self.seen_events["OnNewWorkbook"] = None
def OnWindowActivate(self, wb, wn):
if type(wb) != types.InstanceType or type(wn) != types.InstanceType:
raise RuntimeError("The transformer doesnt appear to have translated this for us!")
self.seen_events["OnWindowActivate"] = None
def OnWindowDeactivate(self, wb, wn):
self.seen_events["OnWindowDeactivate"] = None
def OnSheetDeactivate(self, sh):
self.seen_events["OnSheetDeactivate"] = None
def OnSheetBeforeDoubleClick(self, Sh, Target, Cancel):
if Target.Column % 2 == 0:
print("You can double-click there...")
else:
print("You can not double-click there...")
# This function is a void, so the result ends up in
# the only ByRef - Cancel.
return 1
class WorkbookEvents:
def OnActivate(self):
print("workbook OnActivate")
def OnBeforeRightClick(self, Target, Cancel):
print("It's a Worksheet Event")
e = DispatchWithEvents("Excel.Application", ExcelEvents)
e.seen_events = {}
e.Visible=1
book = e.Workbooks.Add()
book = DispatchWithEvents(book, WorkbookEvents)
print("Have book", book)
# sheet = e.Worksheets(1)
# sheet = DispatchWithEvents(sheet, WorksheetEvents)
print("Double-click in a few of the Excel cells...")
print("Press any key when finished with Excel, or wait 10 seconds...")
if not _WaitForFinish(e, 10):
e.Quit()
if not _CheckSeenEvents(e, ["OnNewWorkbook", "OnWindowActivate"]):
sys.exit(1)
def TestWord():
class WordEvents:
def OnDocumentChange(self):
self.seen_events["OnDocumentChange"] = None
def OnWindowActivate(self, doc, wn):
self.seen_events["OnWindowActivate"] = None
def OnQuit(self):
self.seen_events["OnQuit"] = None
stopEvent.set()
w = DispatchWithEvents("Word.Application", WordEvents)
w.seen_events = {}
w.Visible = 1
w.Documents.Add()
print("Press any key when finished with Word, or wait 10 seconds...")
if not _WaitForFinish(w, 10):
w.Quit()
if not _CheckSeenEvents(w, ["OnDocumentChange", "OnWindowActivate"]):
sys.exit(1)
def _WaitForFinish(ob, timeout):
end = time.time() + timeout
while 1:
if msvcrt.kbhit():
msvcrt.getch()
break
pythoncom.PumpWaitingMessages()
stopEvent.wait(.2)
if stopEvent.isSet():
stopEvent.clear()
break
try:
if not ob.Visible:
# Gone invisible - we need to pretend we timed
# out, so the app is quit.
return 0
except pythoncom.com_error:
# Excel is busy (eg, editing the cell) - ignore
pass
if time.time() > end:
return 0
return 1
def _CheckSeenEvents(o, events):
rc = 1
for e in events:
if e not in o.seen_events:
print("ERROR: Expected event did not trigger", e)
rc = 0
return rc
def test():
import sys
if "noword" not in sys.argv[1:]:
TestWord()
if "noexcel" not in sys.argv[1:]:
TestExcel()
print("Word and Excel event tests passed.")
if __name__=='__main__':
test()

View file

@ -0,0 +1,140 @@
"""Testing pasing object between multiple COM threads
Uses standard COM marshalling to pass objects between threads. Even
though Python generally seems to work when you just pass COM objects
between threads, it shouldnt.
This shows the "correct" way to do it.
It shows that although we create new threads to use the Python.Interpreter,
COM marshalls back all calls to that object to the main Python thread,
which must be running a message loop (as this sample does).
When this test is run in "free threaded" mode (at this stage, you must
manually mark the COM objects as "ThreadingModel=Free", or run from a
service which has marked itself as free-threaded), then no marshalling
is done, and the Python.Interpreter object start doing the "expected" thing
- ie, it reports being on the same thread as its caller!
Python.exe needs a good way to mark itself as FreeThreaded - at the moment
this is a pain in the but!
"""
import threading, traceback
import win32com.client
import win32event, win32api
import pythoncom
import unittest
from .testServers import InterpCase
freeThreaded = 1
class ThreadInterpCase(InterpCase):
def _testInterpInThread(self, stopEvent, interp):
try:
self._doTestInThread(interp)
finally:
win32event.SetEvent(stopEvent)
def _doTestInThread(self, interp):
pythoncom.CoInitialize()
myThread = win32api.GetCurrentThreadId()
if freeThreaded:
interp = pythoncom.CoGetInterfaceAndReleaseStream(interp, pythoncom.IID_IDispatch)
interp = win32com.client.Dispatch(interp)
interp.Exec("import win32api")
#print "The test thread id is %d, Python.Interpreter's thread ID is %d" % (myThread, interp.Eval("win32api.GetCurrentThreadId()"))
pythoncom.CoUninitialize()
def BeginThreadsSimpleMarshal(self, numThreads):
"""Creates multiple threads using simple (but slower) marshalling.
Single interpreter object, but a new stream is created per thread.
Returns the handles the threads will set when complete.
"""
interp = win32com.client.Dispatch("Python.Interpreter")
events = []
threads = []
for i in range(numThreads):
hEvent = win32event.CreateEvent(None, 0, 0, None)
events.append(hEvent)
interpStream = pythoncom.CoMarshalInterThreadInterfaceInStream(pythoncom.IID_IDispatch, interp._oleobj_)
t = threading.Thread(target=self._testInterpInThread, args=(hEvent, interpStream))
t.setDaemon(1) # so errors dont cause shutdown hang
t.start()
threads.append(t)
interp = None
return threads, events
#
# NOTE - this doesnt quite work - Im not even sure it should, but Greg reckons
# you should be able to avoid the marshal per thread!
# I think that refers to CoMarshalInterface though...
def BeginThreadsFastMarshal(self, numThreads):
"""Creates multiple threads using fast (but complex) marshalling.
The marshal stream is created once, and each thread uses the same stream
Returns the handles the threads will set when complete.
"""
interp = win32com.client.Dispatch("Python.Interpreter")
if freeThreaded:
interp = pythoncom.CoMarshalInterThreadInterfaceInStream(pythoncom.IID_IDispatch, interp._oleobj_)
events = []
threads = []
for i in range(numThreads):
hEvent = win32event.CreateEvent(None, 0, 0, None)
t = threading.Thread(target=self._testInterpInThread, args=(hEvent, interp))
t.setDaemon(1) # so errors dont cause shutdown hang
t.start()
events.append(hEvent)
threads.append(t)
return threads, events
def _DoTestMarshal(self, fn, bCoWait = 0):
#print "The main thread is %d" % (win32api.GetCurrentThreadId())
threads, events = fn(2)
numFinished = 0
while 1:
try:
if bCoWait:
rc = pythoncom.CoWaitForMultipleHandles(0, 2000, events)
else:
# Specifying "bWaitAll" here will wait for messages *and* all events
# (which is pretty useless)
rc = win32event.MsgWaitForMultipleObjects(events, 0, 2000, win32event.QS_ALLINPUT)
if rc >= win32event.WAIT_OBJECT_0 and rc < win32event.WAIT_OBJECT_0+len(events):
numFinished = numFinished + 1
if numFinished >= len(events):
break
elif rc==win32event.WAIT_OBJECT_0 + len(events): # a message
# This is critical - whole apartment model demo will hang.
pythoncom.PumpWaitingMessages()
else: # Timeout
print("Waiting for thread to stop with interfaces=%d, gateways=%d" % (pythoncom._GetInterfaceCount(), pythoncom._GetGatewayCount()))
except KeyboardInterrupt:
break
for t in threads:
t.join(2)
self.failIf(t.isAlive(), "thread failed to stop!?")
threads = None # threads hold references to args
# Seems to be a leak here I can't locate :(
#self.failUnlessEqual(pythoncom._GetInterfaceCount(), 0)
#self.failUnlessEqual(pythoncom._GetGatewayCount(), 0)
def testSimpleMarshal(self):
self._DoTestMarshal(self.BeginThreadsSimpleMarshal)
def testSimpleMarshalCoWait(self):
self._DoTestMarshal(self.BeginThreadsSimpleMarshal, 1)
# def testFastMarshal(self):
# self._DoTestMarshal(self.BeginThreadsFastMarshal)
if __name__=='__main__':
unittest.main('testMarshal')

View file

@ -0,0 +1,25 @@
## AHH - I cant make this work!!!
# But this is the general idea.
import netscape
import sys
error = "Netscape Test Error"
if __name__=='__main__':
n=netscape.CNetworkCX()
rc = n.Open("http://d|/temp/apyext.html", 0, None, 0, None)
if not rc: raise error("Open method of Netscape failed")
while 1:
num, str = n.Read(None, 0)
print("Got ", num, str)
if num==0:
break # used to be continue - no idea!!
if num==-1:
break
# sys.stdout.write(str)
n.Close()
print("Done!")
del n
sys.last_type = sys.last_value = sys.last_traceback = None

View file

@ -0,0 +1,212 @@
import pythoncom
import win32com.server.util
import time
import win32com, sys, string, win32api, traceback
import win32com.client.dynamic
import win32com.client
import pythoncom
from win32com.axcontrol import axcontrol
from pywintypes import Unicode
from win32com import storagecon
from win32com.test.util import CheckClean
import pywintypes
import win32ui
import win32api, os
from pywin32_testutil import str2bytes
S_OK = 0
import datetime
if issubclass(pywintypes.TimeType, datetime.datetime):
import win32timezone
now = win32timezone.now()
else:
now = pywintypes.Time(time.time())
class LockBytes:
_public_methods_ = [ 'ReadAt', 'WriteAt', 'Flush', 'SetSize', 'LockRegion', 'UnlockRegion', 'Stat' ]
_com_interfaces_ = [ pythoncom.IID_ILockBytes ]
def __init__(self, data = ""):
self.data = str2bytes(data)
self.ctime = now
self.mtime = now
self.atime = now
def ReadAt(self, offset, cb):
print("ReadAt")
result = self.data[offset:offset + cb]
return result
def WriteAt(self, offset, data):
print("WriteAt " +str(offset))
print("len " + str(len(data)))
print("data:")
#print data
if len(self.data) >= offset:
newdata = self.data[0:offset] + data
print(len(newdata))
if len(self.data) >= offset + len(data):
newdata = newdata + self.data[offset + len(data):]
print(len(newdata))
self.data = newdata
return len(data)
def Flush(self, whatsthis=0):
print("Flush" + str(whatsthis))
fname = os.path.join(win32api.GetTempPath(), "persist.doc")
open(fname, "wb").write(self.data)
return S_OK
def SetSize(self, size):
print("Set Size" + str(size))
if size > len(self.data):
self.data = self.data + str2bytes("\000" * (size - len(self.data)))
else:
self.data = self.data[0:size]
return S_OK
def LockRegion(self, offset, size, locktype):
print("LockRegion")
pass
def UnlockRegion(self, offset, size, locktype):
print("UnlockRegion")
pass
def Stat(self, statflag):
print("returning Stat " + str(statflag))
return (
"PyMemBytes",
storagecon.STGTY_LOCKBYTES,
len(self.data),
self.mtime,
self.ctime,
self.atime,
storagecon.STGM_DIRECT|storagecon.STGM_READWRITE|storagecon.STGM_CREATE ,
storagecon.STGM_SHARE_EXCLUSIVE,
"{00020905-0000-0000-C000-000000000046}",
0, # statebits ?
0
)
class OleClientSite:
_public_methods_ = [ 'SaveObject', 'GetMoniker', 'GetContainer', 'ShowObject', 'OnShowWindow', 'RequestNewObjectLayout' ]
_com_interfaces_ = [ axcontrol.IID_IOleClientSite ]
def __init__(self, data = ""):
self.IPersistStorage = None
self.IStorage = None
def SetIPersistStorage(self, IPersistStorage):
self.IPersistStorage = IPersistStorage
def SetIStorage(self, IStorage):
self.IStorage = IStorage
def SaveObject(self):
print("SaveObject")
if self.IPersistStorage != None and self.IStorage != None:
self.IPersistStorage.Save(self.IStorage,1)
self.IStorage.Commit(0)
return S_OK
def GetMoniker(self, dwAssign, dwWhichMoniker):
print("GetMoniker " + str(dwAssign) + " " + str(dwWhichMoniker))
def GetContainer(self):
print("GetContainer")
def ShowObject(self):
print("ShowObject")
def OnShowWindow(self, fShow):
print("ShowObject" + str(fShow))
def RequestNewObjectLayout(self):
print("RequestNewObjectLayout")
def test():
# create a LockBytes object and
#wrap it as a COM object
# import win32com.server.dispatcher
lbcom = win32com.server.util.wrap(LockBytes(), pythoncom.IID_ILockBytes) #, useDispatcher=win32com.server.dispatcher.DispatcherWin32trace)
# create a structured storage on the ILockBytes object
stcom = pythoncom.StgCreateDocfileOnILockBytes(lbcom, storagecon.STGM_DIRECT| storagecon.STGM_CREATE | storagecon.STGM_READWRITE | storagecon.STGM_SHARE_EXCLUSIVE, 0)
# create our ClientSite
ocs = OleClientSite()
# wrap it as a COM object
ocscom = win32com.server.util.wrap(ocs, axcontrol.IID_IOleClientSite)
# create a Word OLE Document, connect it to our site and our storage
oocom=axcontrol.OleCreate("{00020906-0000-0000-C000-000000000046}",
axcontrol.IID_IOleObject,
0,
(0,),
ocscom,
stcom,
)
mf=win32ui.GetMainFrame()
hwnd=mf.GetSafeHwnd()
# Set the host and document name
# for unknown reason document name becomes hostname, and document name
# is not set, debugged it, but don't know where the problem is?
oocom.SetHostNames("OTPython", "This is Cool")
# activate the OLE document
oocom.DoVerb( -1, ocscom, 0, hwnd, mf.GetWindowRect())
# set the hostnames again
oocom.SetHostNames("OTPython2", "ThisisCool2")
# get IDispatch of Word
doc=win32com.client.Dispatch(oocom.QueryInterface(pythoncom.IID_IDispatch))
# get IPersistStorage of Word
dpcom=oocom.QueryInterface(pythoncom.IID_IPersistStorage)
# let our ClientSite know the interfaces
ocs.SetIPersistStorage(dpcom)
ocs.SetIStorage(stcom)
# use IDispatch to do the Office Word test
# pasted from TestOffice.py
wrange = doc.Range()
for i in range(10):
wrange.InsertAfter("Hello from Python %d\n" % i)
paras = doc.Paragraphs
for i in range(len(paras)):
paras[i]().Font.ColorIndex = i+1
paras[i]().Font.Size = 12 + (4 * i)
# XXX - note that
# for para in paras:
# para().Font...
# doesnt seem to work - no error, just doesnt work
# Should check if it works for VB!
dpcom.Save(stcom, 0)
dpcom.HandsOffStorage()
# oocom.Close(axcontrol.OLECLOSE_NOSAVE) # or OLECLOSE_SAVEIFDIRTY, but it fails???
#Save the ILockBytes data to "persist2.doc"
lbcom.Flush()
#exiting Winword will automatically update the ILockBytes data
#and flush it to "%TEMP%\persist.doc"
doc.Application.Quit()
if __name__=='__main__':
test()
pythoncom.CoUninitialize()
CheckClean()

View file

@ -0,0 +1,78 @@
import sys
import unittest
import pythoncom
from win32com.client import Dispatch
from win32com.client.gencache import EnsureDispatch
class PippoTester(unittest.TestCase):
def setUp(self):
from win32com.test.util import RegisterPythonServer
from win32com.test import pippo_server
RegisterPythonServer(pippo_server.__file__, "Python.Test.Pippo")
# create it.
self.object = Dispatch("Python.Test.Pippo")
def testLeaks(self):
try:
gtrc = sys.gettotalrefcount
except AttributeError:
print("Please run this with python_d for leak tests")
gtrc = lambda: 0
# note creating self.object() should have consumed our "one time" leaks
self.object.Method1()
start = gtrc()
for i in range(1000):
object = Dispatch("Python.Test.Pippo")
object.Method1()
object = None
end = gtrc()
if end-start > 5:
self.fail("We lost %d references!" % (end-start,))
def testResults(self):
rc, out1 = self.object.Method2(123, 111)
self.assertEqual(rc, 123)
self.assertEqual(out1, 222)
def testPythonArrays(self):
self._testArray([-3, -2, -1, 0, 1, 2, 3])
self._testArray([-3.14, -2, -.1, 0., 1.1, 2.5, 3])
def testNumpyArrays(self):
try:
import numpy
except:
print("Numpy test not possible because numpy module failed to import")
return
self._testArray(numpy.array([-3, -2, -1, 0, 1, 2, 3]))
self._testArray(numpy.array([-3.14, -2, -.1, 0., 1.1, 2.5, 3]))
def testByteArrays(self):
if 'bytes' in dir(__builtins__):
# Use eval to avoid compilation error in Python 2.
self._testArray(eval("b'abcdef'"))
self._testArray(eval("bytearray(b'abcdef')"))
def _testArray(self, inArray):
outArray = self.object.Method3(inArray)
self.assertEqual(list(outArray), list(inArray))
def testLeaksGencache(self):
try:
gtrc = sys.gettotalrefcount
except AttributeError:
print("Please run this with python_d for leak tests")
gtrc = lambda: 0
# note creating self.object() should have consumed our "one time" leaks
object = EnsureDispatch("Python.Test.Pippo")
start = gtrc()
for i in range(1000):
object = EnsureDispatch("Python.Test.Pippo")
object.Method1()
object = None
end = gtrc()
if end-start > 10:
self.fail("We lost %d references!" % (end-start,))
if __name__=='__main__':
unittest.main()

View file

@ -0,0 +1,730 @@
# NOTE - Still seems to be a leak here somewhere
# gateway count doesnt hit zero. Hence the print statements!
import sys; sys.coinit_flags=0 # Must be free-threaded!
import win32api, pythoncom, time
import pywintypes
import os
import winerror
import win32com
import win32com.client.connect
from win32com.test.util import CheckClean
from win32com.client import constants, DispatchBaseClass, CastTo, VARIANT
from win32com.test.util import RegisterPythonServer
from pywin32_testutil import str2memory
import datetime
import decimal
import win32timezone
importMsg = "**** PyCOMTest is not installed ***\n PyCOMTest is a Python test specific COM client and server.\n It is likely this server is not installed on this machine\n To install the server, you must get the win32com sources\n and build it using MS Visual C++"
error = Exception
# This test uses a Python implemented COM server - ensure correctly registered.
RegisterPythonServer(os.path.join(os.path.dirname(__file__), '..', "servers", "test_pycomtest.py"),
"Python.Test.PyCOMTest")
from win32com.client import gencache
try:
gencache.EnsureModule('{6BCDCB60-5605-11D0-AE5F-CADD4C000000}', 0, 1, 1)
except pythoncom.com_error:
print("The PyCOMTest module can not be located or generated.")
print(importMsg)
raise RuntimeError(importMsg)
# We had a bg where RegisterInterfaces would fail if gencache had
# already been run - exercise that here
from win32com import universal
universal.RegisterInterfaces('{6BCDCB60-5605-11D0-AE5F-CADD4C000000}', 0, 1, 1)
verbose = 0
# convert a normal int to a long int - used to avoid, eg, '1L' for py3k
# friendliness
def ensure_long(int_val):
if sys.version_info > (3,):
# py3k - no such thing as a 'long'
return int_val
# on py2x, we just use an expression that results in a long
return 0x100000000-0x100000000+int_val
def check_get_set(func, arg):
got = func(arg)
if got != arg:
raise error("%s failed - expected %r, got %r" % (func, arg, got))
def check_get_set_raises(exc, func, arg):
try:
got = func(arg)
except exc as e:
pass # what we expect!
else:
raise error("%s with arg %r didn't raise %s - returned %r" % (func, arg, exc, got))
def progress(*args):
if verbose:
for arg in args:
print(arg, end=' ')
print()
def TestApplyResult(fn, args, result):
try:
fnName = str(fn).split()[1]
except:
fnName = str(fn)
progress("Testing ", fnName)
pref = "function " + fnName
rc = fn(*args)
if rc != result:
raise error("%s failed - result not %r but %r" % (pref, result, rc))
def TestConstant(constName, pyConst):
try:
comConst = getattr(constants, constName)
except:
raise error("Constant %s missing" % (constName,))
if comConst != pyConst:
raise error("Constant value wrong for %s - got %s, wanted %s" % (constName, comConst, pyConst))
# Simple handler class. This demo only fires one event.
class RandomEventHandler:
def _Init(self):
self.fireds = {}
def OnFire(self, no):
try:
self.fireds[no] = self.fireds[no] + 1
except KeyError:
self.fireds[no] = 0
def OnFireWithNamedParams(self, no, a_bool, out1, out2):
# This test exists mainly to help with an old bug, where named
# params would come in reverse.
Missing = pythoncom.Missing
if no is not Missing:
# We know our impl called 'OnFire' with the same ID
assert no in self.fireds
assert no+1==out1, "expecting 'out1' param to be ID+1"
assert no+2==out2, "expecting 'out2' param to be ID+2"
# The middle must be a boolean.
assert a_bool is Missing or type(a_bool)==bool, "middle param not a bool"
return out1+2, out2+2
def _DumpFireds(self):
if not self.fireds:
print("ERROR: Nothing was received!")
for firedId, no in self.fireds.items():
progress("ID %d fired %d times" % (firedId, no))
# A simple handler class that derives from object (ie, a "new style class") -
# only relevant for Python 2.x (ie, the 2 classes should be identical in 3.x)
class NewStyleRandomEventHandler(object):
def _Init(self):
self.fireds = {}
def OnFire(self, no):
try:
self.fireds[no] = self.fireds[no] + 1
except KeyError:
self.fireds[no] = 0
def OnFireWithNamedParams(self, no, a_bool, out1, out2):
# This test exists mainly to help with an old bug, where named
# params would come in reverse.
Missing = pythoncom.Missing
if no is not Missing:
# We know our impl called 'OnFire' with the same ID
assert no in self.fireds
assert no+1==out1, "expecting 'out1' param to be ID+1"
assert no+2==out2, "expecting 'out2' param to be ID+2"
# The middle must be a boolean.
assert a_bool is Missing or type(a_bool)==bool, "middle param not a bool"
return out1+2, out2+2
def _DumpFireds(self):
if not self.fireds:
print("ERROR: Nothing was received!")
for firedId, no in self.fireds.items():
progress("ID %d fired %d times" % (firedId, no))
# Test everything which can be tested using both the "dynamic" and "generated"
# COM objects (or when there are very subtle differences)
def TestCommon(o, is_generated):
progress("Getting counter")
counter = o.GetSimpleCounter()
TestCounter(counter, is_generated)
progress("Checking default args")
rc = o.TestOptionals()
if rc[:-1] != ("def", 0, 1) or abs(rc[-1]-3.14)>.01:
print(rc)
raise error("Did not get the optional values correctly")
rc = o.TestOptionals("Hi", 2, 3, 1.1)
if rc[:-1] != ("Hi", 2, 3) or abs(rc[-1]-1.1)>.01:
print(rc)
raise error("Did not get the specified optional values correctly")
rc = o.TestOptionals2(0)
if rc != (0, "", 1):
print(rc)
raise error("Did not get the optional2 values correctly")
rc = o.TestOptionals2(1.1, "Hi", 2)
if rc[1:] != ("Hi", 2) or abs(rc[0]-1.1)>.01:
print(rc)
raise error("Did not get the specified optional2 values correctly")
progress("Checking getting/passing IUnknown")
check_get_set(o.GetSetUnknown, o)
progress("Checking getting/passing IDispatch")
if not isinstance(o.GetSetDispatch(o), o.__class__):
raise error("GetSetDispatch failed: %r" % (o.GetSetDispatch(o),))
progress("Checking getting/passing IDispatch of known type")
if o.GetSetInterface(o).__class__ != o.__class__:
raise error("GetSetDispatch failed")
progress("Checking misc args")
check_get_set(o.GetSetVariant, 4)
check_get_set(o.GetSetVariant, "foo")
check_get_set(o.GetSetVariant, o)
# signed/unsigned.
check_get_set(o.GetSetInt, 0)
check_get_set(o.GetSetInt, -1)
check_get_set(o.GetSetInt, 1)
check_get_set(o.GetSetUnsignedInt, 0)
check_get_set(o.GetSetUnsignedInt, 1)
check_get_set(o.GetSetUnsignedInt, 0x80000000)
if o.GetSetUnsignedInt(-1) != 0xFFFFFFFF:
# -1 is a special case - we accept a negative int (silently converting to
# unsigned) but when getting it back we convert it to a long.
raise error("unsigned -1 failed")
check_get_set(o.GetSetLong, 0)
check_get_set(o.GetSetLong, -1)
check_get_set(o.GetSetLong, 1)
check_get_set(o.GetSetUnsignedLong, 0)
check_get_set(o.GetSetUnsignedLong, 1)
check_get_set(o.GetSetUnsignedLong, 0x80000000)
# -1 is a special case - see above.
if o.GetSetUnsignedLong(-1) != 0xFFFFFFFF:
raise error("unsigned -1 failed")
# We want to explicitly test > 32 bits. py3k has no 'maxint' and
# 'maxsize+1' is no good on 64bit platforms as its 65 bits!
big = 2147483647 # sys.maxint on py2k
for l in big, big+1, 1 << 65:
check_get_set(o.GetSetVariant, l)
progress("Checking structs")
r = o.GetStruct()
assert r.int_value == 99 and str(r.str_value)=="Hello from C++"
assert o.DoubleString("foo") == "foofoo"
progress("Checking var args")
o.SetVarArgs("Hi", "There", "From", "Python", 1)
if o.GetLastVarArgs() != ("Hi", "There", "From", "Python", 1):
raise error("VarArgs failed -" + str(o.GetLastVarArgs()))
progress("Checking arrays")
l=[]
TestApplyResult(o.SetVariantSafeArray, (l,), len(l))
l=[1,2,3,4]
TestApplyResult(o.SetVariantSafeArray, (l,), len(l))
TestApplyResult(o.CheckVariantSafeArray, ((1,2,3,4,),), 1)
# and binary
TestApplyResult(o.SetBinSafeArray, (str2memory('foo\0bar'),), 7)
progress("Checking properties")
o.LongProp = 3
if o.LongProp != 3 or o.IntProp != 3:
raise error("Property value wrong - got %d/%d" % (o.LongProp,o.IntProp))
o.LongProp = o.IntProp = -3
if o.LongProp != -3 or o.IntProp != -3:
raise error("Property value wrong - got %d/%d" % (o.LongProp,o.IntProp))
# This number fits in an unsigned long. Attempting to set it to a normal
# long will involve overflow, which is to be expected. But we do
# expect it to work in a property explicitly a VT_UI4.
check = 3 *10 **9
o.ULongProp = check
if o.ULongProp != check:
raise error("Property value wrong - got %d (expected %d)" % (o.ULongProp, check))
TestApplyResult(o.Test, ("Unused", 99), 1) # A bool function
TestApplyResult(o.Test, ("Unused", -1), 1) # A bool function
TestApplyResult(o.Test, ("Unused", 1==1), 1) # A bool function
TestApplyResult(o.Test, ("Unused", 0), 0)
TestApplyResult(o.Test, ("Unused", 1==0), 0)
assert o.DoubleString("foo") == "foofoo"
TestConstant("ULongTest1", ensure_long(0xFFFFFFFF))
TestConstant("ULongTest2", ensure_long(0x7FFFFFFF))
TestConstant("LongTest1", ensure_long(-0x7FFFFFFF))
TestConstant("LongTest2", ensure_long(0x7FFFFFFF))
TestConstant("UCharTest", 255)
TestConstant("CharTest", -1)
# 'Hello Loraine', but the 'r' is the "Registered" sign (\xae)
TestConstant("StringTest", "Hello Lo\xaeaine")
progress("Checking dates and times")
if issubclass(pywintypes.TimeType, datetime.datetime):
# For now *all* times passed must be tz-aware.
now = win32timezone.now()
# but conversion to and from a VARIANT loses sub-second...
now = now.replace(microsecond=0)
later = now + datetime.timedelta(seconds=1)
TestApplyResult(o.EarliestDate, (now, later), now)
else:
# old PyTime object
now = pythoncom.MakeTime(time.gmtime(time.time()))
later = pythoncom.MakeTime(time.gmtime(time.time()+1))
TestApplyResult(o.EarliestDate, (now, later), now)
# But it can still *accept* tz-naive datetime objects...
now = datetime.datetime.now()
expect = pythoncom.MakeTime(now)
TestApplyResult(o.EarliestDate, (now, now), expect)
progress("Checking currency")
# currency.
pythoncom.__future_currency__ = 1
if o.CurrencyProp != 0:
raise error("Expecting 0, got %r" % (o.CurrencyProp,))
for val in ("1234.5678", "1234.56", "1234"):
o.CurrencyProp = decimal.Decimal(val)
if o.CurrencyProp != decimal.Decimal(val):
raise error("%s got %r" % (val, o.CurrencyProp))
v1 = decimal.Decimal("1234.5678")
TestApplyResult(o.DoubleCurrency, (v1,), v1*2)
v2 = decimal.Decimal("9012.3456")
TestApplyResult(o.AddCurrencies, (v1, v2), v1+v2)
TestTrickyTypesWithVariants(o, is_generated)
progress("Checking win32com.client.VARIANT")
TestPyVariant(o, is_generated)
def TestTrickyTypesWithVariants(o, is_generated):
# Test tricky stuff with type handling and generally only works with
# "generated" support but can be worked around using VARIANT.
if is_generated:
got = o.TestByRefVariant(2)
else:
v = VARIANT(pythoncom.VT_BYREF | pythoncom.VT_VARIANT, 2)
o.TestByRefVariant(v)
got = v.value
if got != 4:
raise error("TestByRefVariant failed")
if is_generated:
got = o.TestByRefString("Foo")
else:
v = VARIANT(pythoncom.VT_BYREF | pythoncom.VT_BSTR, "Foo")
o.TestByRefString(v)
got = v.value
if got != "FooFoo":
raise error("TestByRefString failed")
# check we can pass ints as a VT_UI1
vals=[1,2,3,4]
if is_generated:
arg = vals
else:
arg = VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_UI1, vals)
TestApplyResult(o.SetBinSafeArray, (arg,), len(vals))
# safearrays of doubles and floats
vals = [0, 1.1, 2.2, 3.3]
if is_generated:
arg = vals
else:
arg = VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, vals)
TestApplyResult(o.SetDoubleSafeArray, (arg,), len(vals))
if is_generated:
arg = vals
else:
arg = VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R4, vals)
TestApplyResult(o.SetFloatSafeArray, (arg,), len(vals))
vals=[1.1, 2.2, 3.3, 4.4]
expected = (1.1*2, 2.2*2, 3.3*2, 4.4*2)
if is_generated:
TestApplyResult(o.ChangeDoubleSafeArray, (vals,), expected)
else:
arg = VARIANT(pythoncom.VT_BYREF | pythoncom.VT_ARRAY | pythoncom.VT_R8, vals)
o.ChangeDoubleSafeArray(arg)
if arg.value != expected:
raise error("ChangeDoubleSafeArray got the wrong value")
if is_generated:
got = o.DoubleInOutString("foo")
else:
v = VARIANT(pythoncom.VT_BYREF | pythoncom.VT_BSTR, "foo")
o.DoubleInOutString(v)
got = v.value
assert got == "foofoo", got
val = decimal.Decimal("1234.5678")
if is_generated:
got = o.DoubleCurrencyByVal(val)
else:
v = VARIANT(pythoncom.VT_BYREF | pythoncom.VT_CY, val)
o.DoubleCurrencyByVal(v)
got = v.value
assert got == val * 2
def TestDynamic():
progress("Testing Dynamic")
import win32com.client.dynamic
o = win32com.client.dynamic.DumbDispatch("PyCOMTest.PyCOMTest")
TestCommon(o, False)
counter = win32com.client.dynamic.DumbDispatch("PyCOMTest.SimpleCounter")
TestCounter(counter, False)
# Dynamic doesn't know this should be an int, so we get a COM
# TypeMismatch error.
try:
check_get_set_raises(ValueError, o.GetSetInt, "foo")
raise error("no exception raised")
except pythoncom.com_error as exc:
if exc.hresult != winerror.DISP_E_TYPEMISMATCH:
raise
# damn - props with params don't work for dynamic objects :(
# o.SetParamProp(0, 1)
# if o.ParamProp(0) != 1:
# raise RuntimeError, o.paramProp(0)
def TestGenerated():
# Create an instance of the server.
from win32com.client.gencache import EnsureDispatch
o = EnsureDispatch("PyCOMTest.PyCOMTest")
TestCommon(o, True)
counter = EnsureDispatch("PyCOMTest.SimpleCounter")
TestCounter(counter, True)
# XXX - this is failing in dynamic tests, but should work fine.
i1, i2 = o.GetMultipleInterfaces()
if not isinstance(i1, DispatchBaseClass) or not isinstance(i2, DispatchBaseClass):
# Yay - is now an instance returned!
raise error("GetMultipleInterfaces did not return instances - got '%s', '%s'" % (i1, i2))
del i1
del i2
# Generated knows to only pass a 32bit int, so should fail.
check_get_set_raises(OverflowError, o.GetSetInt, 0x80000000)
check_get_set_raises(OverflowError, o.GetSetLong, 0x80000000)
# Generated knows this should be an int, so raises ValueError
check_get_set_raises(ValueError, o.GetSetInt, "foo")
check_get_set_raises(ValueError, o.GetSetLong, "foo")
# Pass some non-sequence objects to our array decoder, and watch it fail.
try:
o.SetVariantSafeArray("foo")
raise error("Expected a type error")
except TypeError:
pass
try:
o.SetVariantSafeArray(666)
raise error("Expected a type error")
except TypeError:
pass
o.GetSimpleSafeArray(None)
TestApplyResult(o.GetSimpleSafeArray, (None,), tuple(range(10)))
resultCheck = tuple(range(5)), tuple(range(10)), tuple(range(20))
TestApplyResult(o.GetSafeArrays, (None, None, None), resultCheck)
l=[]
TestApplyResult(o.SetIntSafeArray, (l,), len(l))
l=[1,2,3,4]
TestApplyResult(o.SetIntSafeArray, (l,), len(l))
ll=[1,2,3,0x100000000]
TestApplyResult(o.SetLongLongSafeArray, (ll,), len(ll))
TestApplyResult(o.SetULongLongSafeArray, (ll,), len(ll))
# Tell the server to do what it does!
TestApplyResult(o.Test2, (constants.Attr2,), constants.Attr2)
TestApplyResult(o.Test3, (constants.Attr2,), constants.Attr2)
TestApplyResult(o.Test4, (constants.Attr2,), constants.Attr2)
TestApplyResult(o.Test5, (constants.Attr2,), constants.Attr2)
TestApplyResult(o.Test6, (constants.WideAttr1,), constants.WideAttr1)
TestApplyResult(o.Test6, (constants.WideAttr2,), constants.WideAttr2)
TestApplyResult(o.Test6, (constants.WideAttr3,), constants.WideAttr3)
TestApplyResult(o.Test6, (constants.WideAttr4,), constants.WideAttr4)
TestApplyResult(o.Test6, (constants.WideAttr5,), constants.WideAttr5)
o.SetParamProp(0, 1)
if o.ParamProp(0) != 1:
raise RuntimeError(o.paramProp(0))
# Make sure CastTo works - even though it is only casting it to itself!
o2 = CastTo(o, "IPyCOMTest")
if o != o2:
raise error("CastTo should have returned the same object")
# Do the connection point thing...
# Create a connection object.
progress("Testing connection points")
o2 = win32com.client.DispatchWithEvents(o, RandomEventHandler)
TestEvents(o2, o2)
o2 = win32com.client.DispatchWithEvents(o, NewStyleRandomEventHandler)
TestEvents(o2, o2)
# and a plain "WithEvents".
handler = win32com.client.WithEvents(o, RandomEventHandler)
TestEvents(o, handler)
handler = win32com.client.WithEvents(o, NewStyleRandomEventHandler)
TestEvents(o, handler)
progress("Finished generated .py test.")
def TestEvents(o, handler):
sessions = []
handler._Init()
try:
for i in range(3):
session = o.Start()
sessions.append(session)
time.sleep(.5)
finally:
# Stop the servers
for session in sessions:
o.Stop(session)
handler._DumpFireds()
handler.close()
def _TestPyVariant(o, is_generated, val, checker = None):
if is_generated:
vt, got = o.GetVariantAndType(val)
else:
# Gotta supply all 3 args with the last 2 being explicit variants to
# get the byref behaviour.
var_vt = VARIANT(pythoncom.VT_UI2 | pythoncom.VT_BYREF, 0)
var_result = VARIANT(pythoncom.VT_VARIANT | pythoncom.VT_BYREF, 0)
o.GetVariantAndType(val, var_vt, var_result)
vt = var_vt.value
got = var_result.value
if checker is not None:
checker(got)
return
# default checking.
assert vt == val.varianttype, (vt, val.varianttype)
# Handle our safe-array test - if the passed value is a list of variants,
# compare against the actual values.
if type(val.value) in (tuple, list):
check = [v.value if isinstance(v, VARIANT) else v for v in val.value]
# pythoncom always returns arrays as tuples.
got = list(got)
else:
check = val.value
assert type(check) == type(got), (type(check), type(got))
assert check == got, (check, got)
def _TestPyVariantFails(o, is_generated, val, exc):
try:
_TestPyVariant(o, is_generated, val)
raise error("Setting %r didn't raise %s" % (val, exc))
except exc:
pass
def TestPyVariant(o, is_generated):
_TestPyVariant(o, is_generated, VARIANT(pythoncom.VT_UI1, 1))
_TestPyVariant(o, is_generated, VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_UI4, [1,2,3]))
_TestPyVariant(o, is_generated, VARIANT(pythoncom.VT_BSTR, "hello"))
_TestPyVariant(o, is_generated, VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_BSTR, ["hello", "there"]))
def check_dispatch(got):
assert isinstance(got._oleobj_, pythoncom.TypeIIDs[pythoncom.IID_IDispatch])
_TestPyVariant(o, is_generated, VARIANT(pythoncom.VT_DISPATCH, o), check_dispatch)
_TestPyVariant(o, is_generated, VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_DISPATCH, [o]))
# an array of variants each with a specific type.
v = VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_VARIANT,
[VARIANT(pythoncom.VT_UI4, 1),
VARIANT(pythoncom.VT_UI4, 2),
VARIANT(pythoncom.VT_UI4, 3)
]
)
_TestPyVariant(o, is_generated, v)
# and failures
_TestPyVariantFails(o, is_generated, VARIANT(pythoncom.VT_UI1, "foo"), ValueError)
def TestCounter(counter, bIsGenerated):
# Test random access into container
progress("Testing counter", repr(counter))
import random
for i in range(50):
num = int(random.random() * len(counter))
try:
# XXX - this appears broken by commit 08a14d4deb374eaa06378509cf44078ad467b9dc -
# We shouldn't need to do generated differently than dynamic.
if bIsGenerated:
ret = counter.Item(num+1)
else:
ret = counter[num]
if ret != num+1:
raise error("Random access into element %d failed - return was %s" % (num,repr(ret)))
except IndexError:
raise error("** IndexError accessing collection element %d" % num)
num = 0
if bIsGenerated:
counter.SetTestProperty(1)
counter.TestProperty = 1 # Note this has a second, default arg.
counter.SetTestProperty(1,2)
if counter.TestPropertyWithDef != 0:
raise error("Unexpected property set value!")
if counter.TestPropertyNoDef(1) != 1:
raise error("Unexpected property set value!")
else:
pass
# counter.TestProperty = 1
counter.LBound=1
counter.UBound=10
if counter.LBound != 1 or counter.UBound!=10:
print("** Error - counter did not keep its properties")
if bIsGenerated:
bounds = counter.GetBounds()
if bounds[0]!=1 or bounds[1]!=10:
raise error("** Error - counter did not give the same properties back")
counter.SetBounds(bounds[0], bounds[1])
for item in counter:
num = num + 1
if num != len(counter):
raise error("*** Length of counter and loop iterations dont match ***")
if num != 10:
raise error("*** Unexpected number of loop iterations ***")
counter = iter(counter)._iter_.Clone() # Test Clone() and enum directly
counter.Reset()
num = 0
for item in counter:
num = num + 1
if num != 10:
raise error("*** Unexpected number of loop iterations - got %d ***" % num)
progress("Finished testing counter")
def TestLocalVTable(ob):
# Python doesn't fully implement this interface.
if ob.DoubleString("foo") != "foofoo":
raise error("couldn't foofoo")
###############################
##
## Some vtable tests of the interface
##
def TestVTable(clsctx=pythoncom.CLSCTX_ALL):
# Any vtable interfaces marked as dual *should* be able to be
# correctly implemented as IDispatch.
ob = win32com.client.Dispatch("Python.Test.PyCOMTest")
TestLocalVTable(ob)
# Now test it via vtable - use some C++ code to help here as Python can't do it directly yet.
tester = win32com.client.Dispatch("PyCOMTest.PyCOMTest")
testee = pythoncom.CoCreateInstance("Python.Test.PyCOMTest", None, clsctx, pythoncom.IID_IUnknown)
# check we fail gracefully with None passed.
try:
tester.TestMyInterface(None)
except pythoncom.com_error as details:
pass
# and a real object.
tester.TestMyInterface(testee)
def TestVTable2():
# We once crashed creating our object with the native interface as
# the first IID specified. We must do it _after_ the tests, so that
# Python has already had the gateway registered from last run.
ob = win32com.client.Dispatch("Python.Test.PyCOMTest")
iid = pythoncom.InterfaceNames["IPyCOMTest"]
clsid = "Python.Test.PyCOMTest"
clsctx = pythoncom.CLSCTX_SERVER
try:
testee = pythoncom.CoCreateInstance(clsid, None, clsctx, iid)
except TypeError:
# Python can't actually _use_ this interface yet, so this is
# "expected". Any COM error is not.
pass
def TestVTableMI():
clsctx = pythoncom.CLSCTX_SERVER
ob = pythoncom.CoCreateInstance("Python.Test.PyCOMTestMI", None, clsctx, pythoncom.IID_IUnknown)
# This inherits from IStream.
ob.QueryInterface(pythoncom.IID_IStream)
# This implements IStorage, specifying the IID as a string
ob.QueryInterface(pythoncom.IID_IStorage)
# IDispatch should always work
ob.QueryInterface(pythoncom.IID_IDispatch)
iid = pythoncom.InterfaceNames["IPyCOMTest"]
try:
ob.QueryInterface(iid)
except TypeError:
# Python can't actually _use_ this interface yet, so this is
# "expected". Any COM error is not.
pass
def TestQueryInterface(long_lived_server = 0, iterations=5):
tester = win32com.client.Dispatch("PyCOMTest.PyCOMTest")
if long_lived_server:
# Create a local server
t0 = win32com.client.Dispatch("Python.Test.PyCOMTest", clsctx=pythoncom.CLSCTX_LOCAL_SERVER)
# Request custom interfaces a number of times
prompt = [
"Testing QueryInterface without long-lived local-server #%d of %d...",
"Testing QueryInterface with long-lived local-server #%d of %d..."
]
for i in range(iterations):
progress(prompt[long_lived_server!=0] % (i+1, iterations))
tester.TestQueryInterface()
class Tester(win32com.test.util.TestCase):
def testVTableInProc(self):
# We used to crash running this the second time - do it a few times
for i in range(3):
progress("Testing VTables in-process #%d..." % (i+1))
TestVTable(pythoncom.CLSCTX_INPROC_SERVER)
def testVTableLocalServer(self):
for i in range(3):
progress("Testing VTables out-of-process #%d..." % (i+1))
TestVTable(pythoncom.CLSCTX_LOCAL_SERVER)
def testVTable2(self):
for i in range(3):
TestVTable2()
def testVTableMI(self):
for i in range(3):
TestVTableMI()
def testMultiQueryInterface(self):
TestQueryInterface(0,6)
# When we use the custom interface in the presence of a long-lived
# local server, i.e. a local server that is already running when
# we request an instance of our COM object, and remains afterwards,
# then after repeated requests to create an instance of our object
# the custom interface disappears -- i.e. QueryInterface fails with
# E_NOINTERFACE. Set the upper range of the following test to 2 to
# pass this test, i.e. TestQueryInterface(1,2)
TestQueryInterface(1,6)
def testDynamic(self):
TestDynamic()
def testGenerated(self):
TestGenerated()
if __name__=='__main__':
# XXX - todo - Complete hack to crank threading support.
# Should NOT be necessary
def NullThreadFunc():
pass
import _thread
_thread.start_new( NullThreadFunc, () )
if "-v" in sys.argv: verbose = 1
win32com.test.util.testmain()

View file

@ -0,0 +1,33 @@
function print(msg)
{
WScript.Echo(msg) ;
}
function check(condition, msg)
{
if (!condition) {
print("***** testPyScriptlet.js failed *****");
print(msg);
}
}
var thisScriptEngine = ScriptEngine() ;
var majorVersion = ScriptEngineMajorVersion() ;
var minorVersion = ScriptEngineMinorVersion() ;
var buildVersion = ScriptEngineBuildVersion() ;
WScript.Echo(thisScriptEngine + " Version " + majorVersion + "." + minorVersion + " Build " + buildVersion) ;
var scriptlet = new ActiveXObject("TestPys.Scriptlet") ;
check(scriptlet.PyProp1=="PyScript Property1", "PyProp1 wasn't correct initial value");
scriptlet.PyProp1 = "New Value";
check(scriptlet.PyProp1=="New Value", "PyProp1 wasn't correct new value");
check(scriptlet.PyProp2=="PyScript Property2", "PyProp2 wasn't correct initial value");
scriptlet.PyProp2 = "Another New Value";
check(scriptlet.PyProp2=="Another New Value", "PyProp2 wasn't correct new value");
check(scriptlet.PyMethod1()=="PyMethod1 called", "Method1 wrong value");
check(scriptlet.PyMethod2()=="PyMethod2 called", "Method2 wrong value");

View file

@ -0,0 +1,26 @@
import pythoncom
import unittest
import win32com.test.util
import winerror
class TestROT(win32com.test.util.TestCase):
def testit(self):
ctx = pythoncom.CreateBindCtx()
rot = pythoncom.GetRunningObjectTable()
num = 0
for mk in rot:
name = mk.GetDisplayName(ctx, None)
num += 1
# Monikers themselves can iterate their contents (sometimes :)
try:
for sub in mk:
num += 1
except pythoncom.com_error as exc:
if exc.hresult != winerror.E_NOTIMPL:
raise
#if num < 2:
# print "Only", num, "objects in the ROT - this is unusual"
if __name__=='__main__':
unittest.main()

View file

@ -0,0 +1,39 @@
import pythoncom, win32com.client.dynamic, sys
import winerror
import win32com.test.util
import unittest
def TestConnections():
import win32com.demos.connect
win32com.demos.connect.test()
class InterpCase(win32com.test.util.TestCase):
def setUp(self):
# Ensure the correct version registered.
from win32com.test.util import RegisterPythonServer
from win32com.servers import interp
RegisterPythonServer(interp.__file__, "Python.Interpreter")
def _testInterp(self, interp):
self.assertEquals(interp.Eval("1+1"), 2)
win32com.test.util.assertRaisesCOM_HRESULT(self, winerror.DISP_E_TYPEMISMATCH,
interp.Eval, 2)
def testInproc(self):
interp = win32com.client.dynamic.Dispatch("Python.Interpreter", clsctx = pythoncom.CLSCTX_INPROC)
self._testInterp(interp)
def testLocalServer(self):
interp = win32com.client.dynamic.Dispatch("Python.Interpreter", clsctx = pythoncom.CLSCTX_LOCAL_SERVER)
self._testInterp(interp)
def testAny(self):
interp = win32com.client.dynamic.Dispatch("Python.Interpreter")
self._testInterp(interp)
class ConnectionsTestCase(win32com.test.util.TestCase):
def testConnections(self):
TestConnections()
if __name__=='__main__':
unittest.main('testServers')

View file

@ -0,0 +1,260 @@
import sys, os
import struct
import unittest
import copy
import datetime
import win32timezone
try:
sys_maxsize = sys.maxsize # 2.6 and later - maxsize != maxint on 64bits
except AttributeError:
sys_maxsize = sys.maxint
import win32con
import pythoncom
import pywintypes
from win32com.shell import shell
from win32com.shell.shellcon import *
from win32com.storagecon import *
import win32com.test.util
from pywin32_testutil import str2bytes
class ShellTester(win32com.test.util.TestCase):
def testShellLink(self):
desktop = str(shell.SHGetSpecialFolderPath(0, CSIDL_DESKTOP))
num = 0
shellLink = pythoncom.CoCreateInstance(shell.CLSID_ShellLink, None, pythoncom.CLSCTX_INPROC_SERVER, shell.IID_IShellLink)
persistFile = shellLink.QueryInterface(pythoncom.IID_IPersistFile)
names = [os.path.join(desktop, n) for n in os.listdir(desktop)]
programs = str(shell.SHGetSpecialFolderPath(0, CSIDL_PROGRAMS))
names.extend([os.path.join(programs, n) for n in os.listdir(programs)])
for name in names:
try:
persistFile.Load(name,STGM_READ)
except pythoncom.com_error:
continue
# Resolve is slow - avoid it for our tests.
#shellLink.Resolve(0, shell.SLR_ANY_MATCH | shell.SLR_NO_UI)
fname, findData = shellLink.GetPath(0)
unc = shellLink.GetPath(shell.SLGP_UNCPRIORITY)[0]
num += 1
if num == 0:
# This isn't a fatal error, but is unlikely.
print("Could not find any links on your desktop or programs dir, which is unusual")
def testShellFolder(self):
sf = shell.SHGetDesktopFolder()
names_1 = []
for i in sf: # Magically calls EnumObjects
name = sf.GetDisplayNameOf(i, SHGDN_NORMAL)
names_1.append(name)
# And get the enumerator manually
enum = sf.EnumObjects(0, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN)
names_2 = []
for i in enum:
name = sf.GetDisplayNameOf(i, SHGDN_NORMAL)
names_2.append(name)
names_1.sort()
names_2.sort()
self.assertEqual(names_1, names_2)
class PIDLTester(win32com.test.util.TestCase):
def _rtPIDL(self, pidl):
pidl_str = shell.PIDLAsString(pidl)
pidl_rt = shell.StringAsPIDL(pidl_str)
self.assertEqual(pidl_rt, pidl)
pidl_str_rt = shell.PIDLAsString(pidl_rt)
self.assertEqual(pidl_str_rt, pidl_str)
def _rtCIDA(self, parent, kids):
cida = parent, kids
cida_str = shell.CIDAAsString(cida)
cida_rt = shell.StringAsCIDA(cida_str)
self.assertEqual(cida, cida_rt)
cida_str_rt = shell.CIDAAsString(cida_rt)
self.assertEqual(cida_str_rt, cida_str)
def testPIDL(self):
# A PIDL of "\1" is: cb pidl cb
expect = str2bytes("\03\00" "\1" "\0\0")
self.assertEqual(shell.PIDLAsString([str2bytes("\1")]), expect)
self._rtPIDL([str2bytes("\0")])
self._rtPIDL([str2bytes("\1"), str2bytes("\2"), str2bytes("\3")])
self._rtPIDL([str2bytes("\0") * 2048] * 2048)
# PIDL must be a list
self.assertRaises(TypeError, shell.PIDLAsString, "foo")
def testCIDA(self):
self._rtCIDA([str2bytes("\0")], [ [str2bytes("\0")] ])
self._rtCIDA([str2bytes("\1")], [ [str2bytes("\2")] ])
self._rtCIDA([str2bytes("\0")], [ [str2bytes("\0")], [str2bytes("\1")], [str2bytes("\2")] ])
def testBadShortPIDL(self):
# A too-short child element: cb pidl cb
pidl = str2bytes("\01\00" "\1")
self.assertRaises(ValueError, shell.StringAsPIDL, pidl)
# ack - tried to test too long PIDLs, but a len of 0xFFFF may not
# always fail.
class FILEGROUPDESCRIPTORTester(win32com.test.util.TestCase):
def _getTestTimes(self):
if issubclass(pywintypes.TimeType, datetime.datetime):
ctime = win32timezone.now()
atime = ctime + datetime.timedelta(seconds=1)
wtime = atime + datetime.timedelta(seconds=1)
else:
ctime = pywintypes.Time(11)
atime = pywintypes.Time(12)
wtime = pywintypes.Time(13)
return ctime, atime, wtime
def _testRT(self, fd):
fgd_string = shell.FILEGROUPDESCRIPTORAsString([fd])
fd2 = shell.StringAsFILEGROUPDESCRIPTOR(fgd_string)[0]
fd = fd.copy()
fd2 = fd2.copy()
# The returned objects *always* have dwFlags and cFileName.
if 'dwFlags' not in fd:
del fd2['dwFlags']
if 'cFileName' not in fd:
self.assertEqual(fd2['cFileName'], '')
del fd2['cFileName']
self.assertEqual(fd, fd2)
def _testSimple(self, make_unicode):
fgd = shell.FILEGROUPDESCRIPTORAsString([], make_unicode)
header = struct.pack("i", 0)
self.assertEqual(header, fgd[:len(header)])
self._testRT(dict())
d = dict()
fgd = shell.FILEGROUPDESCRIPTORAsString([d], make_unicode)
header = struct.pack("i", 1)
self.assertEqual(header, fgd[:len(header)])
self._testRT(d)
def testSimpleBytes(self):
self._testSimple(False)
def testSimpleUnicode(self):
self._testSimple(True)
def testComplex(self):
clsid = pythoncom.MakeIID("{CD637886-DB8B-4b04-98B5-25731E1495BE}")
ctime, atime, wtime = self._getTestTimes()
d = dict(cFileName="foo.txt",
clsid=clsid,
sizel=(1,2),
pointl=(3,4),
dwFileAttributes = win32con.FILE_ATTRIBUTE_NORMAL,
ftCreationTime=ctime,
ftLastAccessTime=atime,
ftLastWriteTime=wtime,
nFileSize=sys_maxsize + 1)
self._testRT(d)
def testUnicode(self):
# exercise a bug fixed in build 210 - multiple unicode objects failed.
ctime, atime, wtime = self._getTestTimes()
d = [dict(cFileName="foo.txt",
sizel=(1,2),
pointl=(3,4),
dwFileAttributes = win32con.FILE_ATTRIBUTE_NORMAL,
ftCreationTime=ctime,
ftLastAccessTime=atime,
ftLastWriteTime=wtime,
nFileSize=sys_maxsize + 1),
dict(cFileName="foo2.txt",
sizel=(1,2),
pointl=(3,4),
dwFileAttributes = win32con.FILE_ATTRIBUTE_NORMAL,
ftCreationTime=ctime,
ftLastAccessTime=atime,
ftLastWriteTime=wtime,
nFileSize=sys_maxsize + 1),
dict(cFileName="foo\xa9.txt",
sizel=(1,2),
pointl=(3,4),
dwFileAttributes = win32con.FILE_ATTRIBUTE_NORMAL,
ftCreationTime=ctime,
ftLastAccessTime=atime,
ftLastWriteTime=wtime,
nFileSize=sys_maxsize + 1),
]
s = shell.FILEGROUPDESCRIPTORAsString(d, 1)
d2 = shell.StringAsFILEGROUPDESCRIPTOR(s)
# clobber 'dwFlags' - they are not expected to be identical
for t in d2:
del t['dwFlags']
self.assertEqual(d, d2)
class FileOperationTester(win32com.test.util.TestCase):
def setUp(self):
import tempfile
self.src_name = os.path.join(tempfile.gettempdir(), "pywin32_testshell")
self.dest_name = os.path.join(tempfile.gettempdir(), "pywin32_testshell_dest")
self.test_data = str2bytes("Hello from\0Python")
f=open(self.src_name, "wb")
f.write(self.test_data)
f.close()
try:
os.unlink(self.dest_name)
except os.error:
pass
def tearDown(self):
for fname in (self.src_name, self.dest_name):
if os.path.isfile(fname):
os.unlink(fname)
def testCopy(self):
s = (0, # hwnd,
FO_COPY, #operation
self.src_name,
self.dest_name)
rc, aborted = shell.SHFileOperation(s)
self.failUnless(not aborted)
self.failUnlessEqual(0, rc)
self.failUnless(os.path.isfile(self.src_name))
self.failUnless(os.path.isfile(self.dest_name))
def testRename(self):
s = (0, # hwnd,
FO_RENAME, #operation
self.src_name,
self.dest_name)
rc, aborted = shell.SHFileOperation(s)
self.failUnless(not aborted)
self.failUnlessEqual(0, rc)
self.failUnless(os.path.isfile(self.dest_name))
self.failUnless(not os.path.isfile(self.src_name))
def testMove(self):
s = (0, # hwnd,
FO_MOVE, #operation
self.src_name,
self.dest_name)
rc, aborted = shell.SHFileOperation(s)
self.failUnless(not aborted)
self.failUnlessEqual(0, rc)
self.failUnless(os.path.isfile(self.dest_name))
self.failUnless(not os.path.isfile(self.src_name))
def testDelete(self):
s = (0, # hwnd,
FO_DELETE, #operation
self.src_name, None,
FOF_NOCONFIRMATION)
rc, aborted = shell.SHFileOperation(s)
self.failUnless(not aborted)
self.failUnlessEqual(0, rc)
self.failUnless(not os.path.isfile(self.src_name))
if __name__=='__main__':
win32com.test.util.testmain()

View file

@ -0,0 +1,62 @@
from win32com import storagecon
import pythoncom, os, win32api
import win32com.test.util
import unittest
class TestEnum(win32com.test.util.TestCase):
def testit(self):
fname, tmp = win32api.GetTempFileName(win32api.GetTempPath(),'stg')
m=storagecon.STGM_READWRITE | storagecon.STGM_SHARE_EXCLUSIVE
## file, mode, format, attrs (always 0), IID (IStorage or IPropertySetStorage, storage options(only used with STGFMT_DOCFILE)
pss=pythoncom.StgOpenStorageEx(fname, m, storagecon.STGFMT_FILE, 0 , pythoncom.IID_IPropertySetStorage)
### {"Version":2,"reserved":0,"SectorSize":512,"TemplateFile":u'somefilename'})
## FMTID_SummaryInformation FMTID_DocSummaryInformation FMTID_UserDefinedProperties
psuser=pss.Create(pythoncom.FMTID_UserDefinedProperties,
pythoncom.IID_IPropertySetStorage,
storagecon.PROPSETFLAG_DEFAULT,
storagecon.STGM_READWRITE|storagecon.STGM_CREATE|storagecon.STGM_SHARE_EXCLUSIVE) ## its very picky about flag combinations!
psuser.WriteMultiple((3,4),('hey','bubba'))
psuser.WritePropertyNames((3,4),('property3','property4'))
expected_summaries = []
expected_summaries.append( ('property3', 3, pythoncom.VT_BSTR))
expected_summaries.append( ('property4', 4, pythoncom.VT_BSTR))
psuser=None
pssum=pss.Create(pythoncom.FMTID_SummaryInformation,
pythoncom.IID_IPropertySetStorage,
storagecon.PROPSETFLAG_DEFAULT,
storagecon.STGM_READWRITE|storagecon.STGM_CREATE|storagecon.STGM_SHARE_EXCLUSIVE)
pssum.WriteMultiple((storagecon.PIDSI_AUTHOR,storagecon.PIDSI_COMMENTS),('me', 'comment'))
pssum=None
pss=None ## doesn't seem to be a close or release method, and you can't even reopen it from the same process until previous object is gone
pssread=pythoncom.StgOpenStorageEx(fname, storagecon.STGM_READ|storagecon.STGM_SHARE_EXCLUSIVE, storagecon.STGFMT_FILE, 0 , pythoncom.IID_IPropertySetStorage)
found_summaries = []
for psstat in pssread:
ps=pssread.Open(psstat[0],storagecon.STGM_READ|storagecon.STGM_SHARE_EXCLUSIVE)
for p in ps:
p_val = ps.ReadMultiple((p[1],))[0]
if (p[1]==storagecon.PIDSI_AUTHOR and p_val=='me') or \
(p[1]==storagecon.PIDSI_COMMENTS and p_val=='comment'):
pass
else:
self.fail("Uxexpected property %s/%s" % (p, p_val))
ps=None
## FMTID_UserDefinedProperties can't exist without FMTID_DocSummaryInformation, and isn't returned independently from Enum
## also can't be open at same time
if psstat[0]==pythoncom.FMTID_DocSummaryInformation:
ps=pssread.Open(pythoncom.FMTID_UserDefinedProperties,storagecon.STGM_READ|storagecon.STGM_SHARE_EXCLUSIVE)
for p in ps:
found_summaries.append(p)
ps=None
psread=None
expected_summaries.sort()
found_summaries.sort()
self.assertEqual(expected_summaries, found_summaries)
if __name__=='__main__':
unittest.main()

View file

@ -0,0 +1,131 @@
import pythoncom
import win32com.server.util
import win32com.test.util
import unittest
from pywin32_testutil import str2bytes
class Persists:
_public_methods_ = [ 'GetClassID', 'IsDirty', 'Load', 'Save',
'GetSizeMax', 'InitNew' ]
_com_interfaces_ = [ pythoncom.IID_IPersistStreamInit ]
def __init__(self):
self.data = str2bytes("abcdefg")
self.dirty = 1
def GetClassID(self):
return pythoncom.IID_NULL
def IsDirty(self):
return self.dirty
def Load(self, stream):
self.data = stream.Read(26)
def Save(self, stream, clearDirty):
stream.Write(self.data)
if clearDirty:
self.dirty = 0
def GetSizeMax(self):
return 1024
def InitNew(self):
pass
class Stream:
_public_methods_ = [ 'Read', 'Write', 'Seek' ]
_com_interfaces_ = [ pythoncom.IID_IStream ]
def __init__(self, data):
self.data = data
self.index = 0
def Read(self, amount):
result = self.data[self.index : self.index + amount]
self.index = self.index + amount
return result
def Write(self, data):
self.data = data
self.index = 0
return len(data)
def Seek(self, dist, origin):
if origin==pythoncom.STREAM_SEEK_SET:
self.index = dist
elif origin==pythoncom.STREAM_SEEK_CUR:
self.index = self.index + dist
elif origin==pythoncom.STREAM_SEEK_END:
self.index = len(self.data)+dist
else:
raise ValueError('Unknown Seek type: ' +str(origin))
if self.index < 0:
self.index = 0
else:
self.index = min(self.index, len(self.data))
return self.index
class BadStream(Stream):
""" PyGStream::Read could formerly overflow buffer if the python implementation
returned more data than requested.
"""
def Read(self, amount):
return str2bytes('x')*(amount+1)
class StreamTest(win32com.test.util.TestCase):
def _readWrite(self, data, write_stream, read_stream = None):
if read_stream is None: read_stream = write_stream
write_stream.Write(data)
read_stream.Seek(0, pythoncom.STREAM_SEEK_SET)
got = read_stream.Read(len(data))
self.assertEqual(data, got)
read_stream.Seek(1, pythoncom.STREAM_SEEK_SET)
got = read_stream.Read(len(data)-2)
self.assertEqual(data[1:-1], got)
def testit(self):
mydata = str2bytes('abcdefghijklmnopqrstuvwxyz')
# First test the objects just as Python objects...
s = Stream(mydata)
p = Persists()
p.Load(s)
p.Save(s, 0)
self.assertEqual(s.data, mydata)
# Wrap the Python objects as COM objects, and make the calls as if
# they were non-Python COM objects.
s2 = win32com.server.util.wrap(s, pythoncom.IID_IStream)
p2 = win32com.server.util.wrap(p, pythoncom.IID_IPersistStreamInit)
self._readWrite(mydata, s, s)
self._readWrite(mydata, s, s2)
self._readWrite(mydata, s2, s)
self._readWrite(mydata, s2, s2)
self._readWrite(str2bytes("string with\0a NULL"), s2, s2)
# reset the stream
s.Write(mydata)
p2.Load(s2)
p2.Save(s2, 0)
self.assertEqual(s.data, mydata)
def testseek(self):
s = Stream(str2bytes('yo'))
s = win32com.server.util.wrap(s, pythoncom.IID_IStream)
# we used to die in py3k passing a value > 32bits
s.Seek(0x100000000, pythoncom.STREAM_SEEK_SET)
def testerrors(self):
# setup a test logger to capture tracebacks etc.
records, old_log = win32com.test.util.setup_test_logger()
## check for buffer overflow in Read method
badstream = BadStream('Check for buffer overflow')
badstream2 = win32com.server.util.wrap(badstream, pythoncom.IID_IStream)
self.assertRaises(pythoncom.com_error, badstream2.Read, 10)
win32com.test.util.restore_test_logger(old_log)
# expecting 2 pythoncom errors to have been raised by the gateways.
self.assertEqual(len(records), 2)
self.failUnless(records[0].msg.startswith('pythoncom error'))
self.failUnless(records[1].msg.startswith('pythoncom error'))
if __name__=='__main__':
unittest.main()

View file

@ -0,0 +1,17 @@
from win32com.client import GetObject
import win32com.test.util
import unittest
class Simple(win32com.test.util.TestCase):
def testit(self):
cses = GetObject("WinMgMts:").InstancesOf("Win32_Process")
vals = []
for cs in cses:
val = cs.Properties_("Caption").Value
vals.append(val)
self.failIf(len(vals)<5, "We only found %d processes!" % len(vals))
if __name__=='__main__':
unittest.main()

View file

@ -0,0 +1,263 @@
import sys, os, string, re
import pythoncom
import win32com.client
from win32com.test.util import CheckClean, TestCase, \
CapturingFunctionTestCase, ShellTestCase, \
TestLoader, TestRunner, RegisterPythonServer
import traceback
import getopt
import unittest
verbosity = 1 # default unittest verbosity.
try:
this_file = __file__
except NameError:
this_file = sys.argv[0]
def GenerateAndRunOldStyle():
from . import GenTestScripts
GenTestScripts.GenerateAll()
try:
pass #
finally:
GenTestScripts.CleanAll()
def CleanGenerated():
import win32com, shutil
if os.path.isdir(win32com.__gen_path__):
if verbosity > 1:
print("Deleting files from %s" % (win32com.__gen_path__))
shutil.rmtree(win32com.__gen_path__)
import win32com.client.gencache
win32com.client.gencache.__init__() # Reset
def RemoveRefCountOutput(data):
while 1:
last_line_pos = data.rfind("\n")
if not re.match("\[\d+ refs\]", data[last_line_pos+1:]):
break
if last_line_pos < 0:
# All the output
return ''
data = data[:last_line_pos]
return data
def ExecuteSilentlyIfOK(cmd, testcase):
f = os.popen(cmd)
data = f.read().strip()
rc = f.close()
if rc:
print(data)
testcase.fail("Executing '%s' failed (%d)" % (cmd, rc))
# for "_d" builds, strip the '[xxx refs]' line
return RemoveRefCountOutput(data)
class PyCOMTest(TestCase):
no_leak_tests = True # done by the test itself
def testit(self):
# Check that the item is registered, so we get the correct
# 'skipped' behaviour (and recorded as such) rather than either
# error or silence due to non-registration.
RegisterPythonServer(os.path.join(os.path.dirname(__file__), '..', "servers", "test_pycomtest.py"),
"Python.Test.PyCOMTest")
# Execute testPyComTest in its own process so it can play
# with the Python thread state
fname = os.path.join(os.path.dirname(this_file), "testPyComTest.py")
cmd = '%s "%s" -q 2>&1' % (sys.executable, fname)
data = ExecuteSilentlyIfOK(cmd, self)
class PippoTest(TestCase):
def testit(self):
# Check we are registered before spawning the process.
from win32com.test import pippo_server
RegisterPythonServer(pippo_server.__file__, "Python.Test.Pippo")
python = sys.executable
fname = os.path.join(os.path.dirname(this_file), "testPippo.py")
cmd = '%s "%s" 2>&1' % (python, fname)
ExecuteSilentlyIfOK(cmd, self)
# This is a list of "win32com.test.???" module names, optionally with a
# function in that module if the module isn't unitest based...
unittest_modules = [
# Level 1 tests.
"""testIterators testvbscript_regexp testStorage
testStreams testWMI policySemantics testShell testROT
testAXScript testxslt testDictionary testCollections
testServers errorSemantics.test testvb testArrays
testClipboard testMarshal
""".split(),
# Level 2 tests.
"""testMSOffice.TestAll testMSOfficeEvents.test testAccess.test
testExplorer.TestAll testExchange.test
""".split(),
# Level 3 tests.
"""testmakepy.TestAll
""".split()
]
# A list of other unittest modules we use - these are fully qualified module
# names and the module is assumed to be unittest based.
unittest_other_modules = [
# Level 1 tests.
"""win32com.directsound.test.ds_test
""".split(),
# Level 2 tests.
[],
# Level 3 tests.
[]
]
output_checked_programs = [
# Level 1 tests.
[
("cscript.exe /nologo //E:vbscript testInterp.vbs", "VBScript test worked OK"),
("cscript.exe /nologo //E:vbscript testDictionary.vbs",
"VBScript has successfully tested Python.Dictionary"),
],
# Level 2 tests.
[
],
# Level 3 tests
[
],
]
custom_test_cases = [
# Level 1 tests.
[
PyCOMTest,
PippoTest,
],
# Level 2 tests.
[
],
# Level 3 tests
[
],
]
def get_test_mod_and_func(test_name, import_failures):
if test_name.find(".")>0:
mod_name, func_name = test_name.split(".")
else:
mod_name = test_name
func_name = None
fq_mod_name = "win32com.test." + mod_name
try:
__import__(fq_mod_name)
mod = sys.modules[fq_mod_name]
except:
import_failures.append((mod_name, sys.exc_info()[:2]))
return None, None
if func_name is None:
func = None
else:
func = getattr(mod, func_name)
return mod, func
# Return a test suite all loaded with the tests we want to run
def make_test_suite(test_level = 1):
suite = unittest.TestSuite()
import_failures = []
loader = TestLoader()
for i in range(testLevel):
for mod_name in unittest_modules[i]:
mod, func = get_test_mod_and_func(mod_name, import_failures)
if mod is None:
continue
if func is not None:
test = CapturingFunctionTestCase(func, description=mod_name)
else:
if hasattr(mod, "suite"):
test = mod.suite()
else:
test = loader.loadTestsFromModule(mod)
assert test.countTestCases() > 0, "No tests loaded from %r" % mod
suite.addTest(test)
for cmd, output in output_checked_programs[i]:
suite.addTest(ShellTestCase(cmd, output))
for test_class in custom_test_cases[i]:
suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(test_class))
# other "normal" unittest modules.
for i in range(testLevel):
for mod_name in unittest_other_modules[i]:
try:
__import__(mod_name)
except:
import_failures.append((mod_name, sys.exc_info()[:2]))
continue
mod = sys.modules[mod_name]
if hasattr(mod, "suite"):
test = mod.suite()
else:
test = loader.loadTestsFromModule(mod)
assert test.countTestCases() > 0, "No tests loaded from %r" % mod
suite.addTest(test)
return suite, import_failures
def usage(why):
print(why)
print()
print("win32com test suite")
print("usage: testall [-v] test_level")
print(" where test_level is an integer 1-3. Level 1 tests are quick,")
print(" level 2 tests invoke Word, IE etc, level 3 take ages!")
sys.exit(1)
if __name__=='__main__':
try:
opts, args = getopt.getopt(sys.argv[1:], "v")
except getopt.error as why:
usage(why)
for opt, val in opts:
if opt=='-v':
verbosity += 1
testLevel = 1 # default to quick test
test_names = []
for arg in args:
try:
testLevel = int(arg)
if testLevel < 0 or testLevel > 3:
raise ValueError("Only levels 1-3 are supported")
except ValueError:
test_names.append(arg)
if test_names:
usage("Test names are not supported yet")
CleanGenerated()
suite, import_failures = make_test_suite(testLevel)
if verbosity:
if hasattr(sys, "gettotalrefcount"):
print("This is a debug build - memory leak tests will also be run.")
print("These tests may take *many* minutes to run - be patient!")
print("(running from python.exe will avoid these leak tests)")
print("Executing level %d tests - %d test cases will be run" \
% (testLevel, suite.countTestCases()))
if verbosity==1 and suite.countTestCases() < 70:
# A little row of markers so the dots show how close to finished
print('|' * suite.countTestCases())
testRunner = TestRunner(verbosity=verbosity)
testResult = testRunner.run(suite)
if import_failures:
testResult.stream.writeln("*** The following test modules could not be imported ***")
for mod_name, (exc_type, exc_val) in import_failures:
desc = '\n'.join(traceback.format_exception_only(exc_type, exc_val))
testResult.stream.write("%s: %s" % (mod_name, desc))
testResult.stream.writeln("*** %d test(s) could not be run ***" % len(import_failures))
# re-print unit-test error here so it is noticed
if not testResult.wasSuccessful():
print("*" * 20, "- unittest tests FAILED")
CheckClean()
pythoncom.CoUninitialize()
CleanGenerated()

View file

@ -0,0 +1,53 @@
# Test makepy - try and run it over every OCX in the windows system directory.
import sys
import win32api
import traceback
import glob
import os
import traceback
import win32com.test.util
from win32com.client import makepy, selecttlb, gencache
import pythoncom
import winerror
def TestBuildAll(verbose = 1):
num = 0
tlbInfos = selecttlb.EnumTlbs()
for info in tlbInfos:
if verbose:
print("%s (%s)" % (info.desc, info.dll))
try:
makepy.GenerateFromTypeLibSpec(info)
# sys.stderr.write("Attr typeflags for coclass referenced object %s=%d (%d), typekind=%d\n" % (name, refAttr.wTypeFlags, refAttr.wTypeFlags & pythoncom.TYPEFLAG_FDUAL,refAttr.typekind))
num += 1
except pythoncom.com_error as details:
# Ignore these 2 errors, as the are very common and can obscure
# useful warnings.
if details.hresult not in [winerror.TYPE_E_CANTLOADLIBRARY,
winerror.TYPE_E_LIBNOTREGISTERED]:
print("** COM error on", info.desc)
print(details)
except KeyboardInterrupt:
print("Interrupted!")
raise KeyboardInterrupt
except:
print("Failed:", info.desc)
traceback.print_exc()
if makepy.bForDemandDefault:
# This only builds enums etc by default - build each
# interface manually
tinfo = (info.clsid, info.lcid, info.major, info.minor)
mod = gencache.EnsureModule(info.clsid, info.lcid, info.major, info.minor)
for name in mod.NamesToIIDMap.keys():
makepy.GenerateChildFromTypeLibSpec(name, tinfo)
return num
def TestAll(verbose = 0):
num = TestBuildAll(verbose)
print("Generated and imported", num, "modules")
win32com.test.util.CheckClean()
if __name__=='__main__':
TestAll("-q" not in sys.argv)

View file

@ -0,0 +1,510 @@
# Test code for a VB Program.
#
# This requires the PythonCOM VB Test Harness.
#
import sys
import winerror
import pythoncom, win32com.client, win32com.client.dynamic, win32com.client.gencache
from win32com.server.util import NewCollection, wrap
from win32com.test import util
from pywin32_testutil import str2memory
import traceback
# for debugging
useDispatcher = None
## import win32com.server.dispatcher
## useDispatcher = win32com.server.dispatcher.DefaultDebugDispatcher
error = RuntimeError
# Set up a COM object that VB will do some callbacks on. This is used
# to test byref params for gateway IDispatch.
class TestObject:
_public_methods_ = ["CallbackVoidOneByRef","CallbackResultOneByRef", "CallbackVoidTwoByRef",
"CallbackString","CallbackResultOneByRefButReturnNone",
"CallbackVoidOneByRefButReturnNone",
"CallbackArrayResult", "CallbackArrayResultOneArrayByRef",
"CallbackArrayResultWrongSize"
]
def CallbackVoidOneByRef(self, intVal):
return intVal + 1
def CallbackResultOneByRef(self, intVal):
return intVal, intVal + 1
def CallbackVoidTwoByRef(self, int1, int2):
return int1+int2, int1-int2
def CallbackString(self, strVal):
return 0, strVal + " has visited Python"
def CallbackArrayResult(self, arrayVal):
ret = []
for i in arrayVal:
ret.append(i+1)
# returning as a list forces it be processed as a single result
# (rather than a tuple, where it may be interpreted as
# multiple results for byref unpacking)
return ret
def CallbackArrayResultWrongSize(self, arrayVal):
return list(arrayVal[:-1])
def CallbackArrayResultOneArrayByRef(self, arrayVal):
ret = []
for i in arrayVal:
ret.append(i+1)
# See above for list processing.
return list(arrayVal), ret
def CallbackResultOneByRefButReturnNone(self, intVal):
return
def CallbackVoidOneByRefButReturnNone(self, intVal):
return
def TestVB( vbtest, bUseGenerated ):
vbtest.LongProperty = -1
if vbtest.LongProperty != -1:
raise error("Could not set the long property correctly.")
vbtest.IntProperty = 10
if vbtest.IntProperty != 10:
raise error("Could not set the integer property correctly.")
vbtest.VariantProperty = 10
if vbtest.VariantProperty != 10:
raise error("Could not set the variant integer property correctly.")
vbtest.VariantProperty = str2memory('raw\0data')
if vbtest.VariantProperty != str2memory('raw\0data'):
raise error("Could not set the variant buffer property correctly.")
vbtest.StringProperty = "Hello from Python"
if vbtest.StringProperty != "Hello from Python":
raise error("Could not set the string property correctly.")
vbtest.VariantProperty = "Hello from Python"
if vbtest.VariantProperty != "Hello from Python":
raise error("Could not set the variant string property correctly.")
vbtest.VariantProperty = (1.0, 2.0, 3.0)
if vbtest.VariantProperty != (1.0, 2.0, 3.0):
raise error("Could not set the variant property to an array of floats correctly - '%s'." % (vbtest.VariantProperty,))
TestArrays(vbtest, bUseGenerated)
TestStructs(vbtest)
TestCollections(vbtest)
assert vbtest.TakeByValObject(vbtest)==vbtest
# Python doesnt support PUTREF properties without a typeref
# (although we could)
if bUseGenerated:
ob = vbtest.TakeByRefObject(vbtest)
assert ob[0]==vbtest and ob[1]==vbtest
# A property that only has PUTREF defined.
vbtest.VariantPutref = vbtest
if vbtest.VariantPutref._oleobj_!= vbtest._oleobj_:
raise error("Could not set the VariantPutref property correctly.")
# Cant test further types for this VariantPutref, as only
# COM objects can be stored ByRef.
# A "set" type property - only works for generated.
# VB recognizes a collection via a few "private" interfaces that we
# could later build support in for.
# vbtest.CollectionProperty = NewCollection((1,2,"3", "Four"))
# if vbtest.CollectionProperty != (1,2,"3", "Four"):
# raise error("Could not set the Collection property correctly - got back " + str(vbtest.CollectionProperty))
# These are sub's that have a single byref param
# Result should be just the byref.
if vbtest.IncrementIntegerParam(1) != 2:
raise error("Could not pass an integer byref")
# Sigh - we cant have *both* "ommited byref" and optional args
# We really have to opt that args nominated as optional work as optional
# rather than simply all byrefs working as optional.
# if vbtest.IncrementIntegerParam() != 1:
# raise error("Could not pass an omitted integer byref")
if vbtest.IncrementVariantParam(1) != 2:
raise error("Could not pass an int VARIANT byref:"+str(vbtest.IncrementVariantParam(1)))
if vbtest.IncrementVariantParam(1.5) != 2.5:
raise error("Could not pass a float VARIANT byref")
# Can't test IncrementVariantParam with the param omitted as it
# it not declared in the VB code as "Optional"
callback_ob = wrap(TestObject(), useDispatcher = useDispatcher)
vbtest.DoSomeCallbacks(callback_ob)
ret = vbtest.PassIntByVal(1)
if ret != 2:
raise error("Could not increment the integer - "+str(ret))
TestVBInterface(vbtest)
# Python doesnt support byrefs without some sort of generated support.
if bUseGenerated:
# This is a VB function that takes a single byref
# Hence 2 return values - function and byref.
ret = vbtest.PassIntByRef(1)
if ret != (1,2):
raise error("Could not increment the integer - "+str(ret))
# Check you can leave a byref arg blank.
# see above
# ret = vbtest.PassIntByRef()
# if ret != (0,1):
# raise error("Could not increment the integer with default arg- "+str(ret))
def _DoTestCollection(vbtest, col_name, expected):
# It sucks that some objects allow "Count()", but others "Count"
def _getcount(ob):
r = getattr(ob, "Count")
if type(r)!=type(0):
return r()
return r
c = getattr(vbtest, col_name)
check = []
for item in c:
check.append(item)
if check != list(expected):
raise error("Collection %s didn't have %r (had %r)" % (col_name, expected, check))
# Just looping over the collection again works (ie, is restartable)
check = []
for item in c:
check.append(item)
if check != list(expected):
raise error("Collection 2nd time around %s didn't have %r (had %r)" % (col_name, expected, check))
# Check we can get it via iter()
i = iter(getattr(vbtest, col_name))
check = []
for item in i:
check.append(item)
if check != list(expected):
raise error("Collection iterator %s didn't have %r 2nd time around (had %r)" % (col_name, expected, check))
# but an iterator is not restartable
check = []
for item in i:
check.append(item)
if check != []:
raise error("2nd time around Collection iterator %s wasn't empty (had %r)" % (col_name, check))
# Check len()==Count()
c = getattr(vbtest, col_name)
if len(c) != _getcount(c):
raise error("Collection %s __len__(%r) wasn't==Count(%r)" % (col_name, len(c), _getcount(c)))
# Check we can do it with zero based indexing.
c = getattr(vbtest, col_name)
check = []
for i in range(_getcount(c)):
check.append(c[i])
if check != list(expected):
raise error("Collection %s didn't have %r (had %r)" % (col_name, expected, check))
# Check we can do it with our old "Skip/Next" methods.
c = getattr(vbtest, col_name)._NewEnum()
check = []
while 1:
n = c.Next()
if not n:
break
check.append(n[0])
if check != list(expected):
raise error("Collection %s didn't have %r (had %r)" % (col_name, expected, check))
def TestCollections(vbtest):
_DoTestCollection(vbtest, "CollectionProperty", [1,"Two", "3"])
# zero based indexing works for simple VB collections.
if vbtest.CollectionProperty[0] != 1:
raise error("The CollectionProperty[0] element was not the default value")
_DoTestCollection(vbtest, "EnumerableCollectionProperty", [])
vbtest.EnumerableCollectionProperty.Add(1)
vbtest.EnumerableCollectionProperty.Add("Two")
vbtest.EnumerableCollectionProperty.Add("3")
_DoTestCollection(vbtest, "EnumerableCollectionProperty", [1,"Two", "3"])
def _DoTestArray(vbtest, data, expected_exception = None):
try:
vbtest.ArrayProperty = data
if expected_exception is not None:
raise error("Expected '%s'" % expected_exception)
except expected_exception:
return
got = vbtest.ArrayProperty
if got != data:
raise error(
"Could not set the array data correctly - got %r, expected %r"
% (got, data))
def TestArrays(vbtest, bUseGenerated):
# Try and use a safe array (note that the VB code has this declared as a VARIANT
# and I cant work out how to force it to use native arrays!
# (NOTE Python will convert incoming arrays to tuples, so we pass a tuple, even tho
# a list works fine - just makes it easier for us to compare the result!
# Empty array
_DoTestArray(vbtest, ())
# Empty child array
_DoTestArray(vbtest, ((), ()))
# ints
_DoTestArray(vbtest, tuple(range(1,100)))
# Floats
_DoTestArray(vbtest, (1.0, 2.0, 3.0))
# Strings.
_DoTestArray(vbtest, tuple("Hello from Python".split()))
# Date and Time?
# COM objects.
_DoTestArray(vbtest, (vbtest, vbtest))
# Mixed
_DoTestArray(vbtest, (1, 2.0, "3"))
# Array alements containing other arrays
_DoTestArray(vbtest, (1,(vbtest, vbtest),("3","4")))
# Multi-dimensional
_DoTestArray(vbtest, (( (1,2,3), (4,5,6) )))
_DoTestArray(vbtest, (( (vbtest,vbtest,vbtest), (vbtest,vbtest,vbtest) )))
# Another dimension!
arrayData = ( ((1,2),(3,4),(5,6)), ((7,8),(9,10),(11,12)) )
arrayData = ( ((vbtest,vbtest),(vbtest,vbtest),(vbtest,vbtest)),
((vbtest,vbtest),(vbtest,vbtest),(vbtest,vbtest)) )
_DoTestArray(vbtest, arrayData)
# Check that when a '__getitem__ that fails' object is the first item
# in the structure, we don't mistake it for a sequence.
_DoTestArray(vbtest, (vbtest, 2.0, "3"))
_DoTestArray(vbtest, (1, 2.0, vbtest))
# Pass arbitrarily sized arrays - these used to fail, but thanks to
# Stefan Schukat, they now work!
expected_exception = None
arrayData = ( ((1,2,1),(3,4),(5,6)), ((7,8),(9,10),(11,12)) )
_DoTestArray(vbtest, arrayData, expected_exception)
arrayData = ( ((vbtest,vbtest),), ((vbtest,),))
_DoTestArray(vbtest, arrayData, expected_exception)
# Pass bad data - last item wrong size
arrayData = ( ((1,2),(3,4),(5,6,8)), ((7,8),(9,10),(11,12)) )
_DoTestArray(vbtest, arrayData, expected_exception)
# byref safearray results with incorrect size.
callback_ob = wrap(TestObject(), useDispatcher = useDispatcher)
print("** Expecting a 'ValueError' exception to be printed next:")
try:
vbtest.DoCallbackSafeArraySizeFail(callback_ob)
except pythoncom.com_error as exc:
assert exc.excepinfo[1] == "Python COM Server Internal Error", "Didnt get the correct exception - '%s'" % (exc,)
if bUseGenerated:
# This one is a bit strange! The array param is "ByRef", as VB insists.
# The function itself also _returns_ the arram param.
# Therefore, Python sees _2_ result values - one for the result,
# and one for the byref.
testData = "Mark was here".split()
resultData, byRefParam = vbtest.PassSAFEARRAY(testData)
if testData != list(resultData):
raise error("The safe array data was not what we expected - got " + str(resultData))
if testData != list(byRefParam):
raise error("The safe array data was not what we expected - got " + str(byRefParam))
testData = [1.0, 2.0, 3.0]
resultData, byRefParam = vbtest.PassSAFEARRAYVariant(testData)
assert testData == list(byRefParam)
assert testData == list(resultData)
testData = ["hi", "from", "Python"]
resultData, byRefParam = vbtest.PassSAFEARRAYVariant(testData)
assert testData == list(byRefParam), "Expected '%s', got '%s'" % (testData, list(byRefParam))
assert testData == list(resultData), "Expected '%s', got '%s'" % (testData, list(resultData))
# This time, instead of an explicit str() for 1.5, we just
# pass Unicode, so the result should compare equal
testData = [1, 2.0, "3"]
resultData, byRefParam = vbtest.PassSAFEARRAYVariant(testData)
assert testData == list(byRefParam)
assert testData == list(resultData)
print("Array tests passed")
def TestStructs(vbtest):
try:
vbtest.IntProperty = "One"
raise error("Should have failed by now")
except pythoncom.com_error as exc:
if exc.hresult != winerror.DISP_E_TYPEMISMATCH:
raise error("Expected DISP_E_TYPEMISMATCH")
s = vbtest.StructProperty
if s.int_val != 99 or str(s.str_val) != "hello":
raise error("The struct value was not correct")
s.str_val = "Hi from Python"
s.int_val = 11
if s.int_val != 11 or str(s.str_val) != "Hi from Python":
raise error("The struct value didnt persist!")
if s.sub_val.int_val != 66 or str(s.sub_val.str_val) != "sub hello":
raise error("The sub-struct value was not correct")
sub = s.sub_val
sub.int_val = 22
if sub.int_val != 22:
print(sub.int_val)
raise error("The sub-struct value didnt persist!")
if s.sub_val.int_val != 22:
print(s.sub_val.int_val)
raise error("The sub-struct value (re-fetched) didnt persist!")
if s.sub_val.array_val[0].int_val != 0 or str(s.sub_val.array_val[0].str_val) != "zero":
print(s.sub_val.array_val[0].int_val)
raise error("The array element wasnt correct")
s.sub_val.array_val[0].int_val = 99
s.sub_val.array_val[1].int_val = 66
if s.sub_val.array_val[0].int_val != 99 or \
s.sub_val.array_val[1].int_val != 66:
print(s.sub_val.array_val[0].int_val)
raise error("The array element didnt persist.")
# Now pass the struct back to VB
vbtest.StructProperty = s
# And get it back again
s = vbtest.StructProperty
if s.int_val != 11 or str(s.str_val) != "Hi from Python":
raise error("After sending to VB, the struct value didnt persist!")
if s.sub_val.array_val[0].int_val != 99:
raise error("After sending to VB, the struct array value didnt persist!")
# Now do some object equality tests.
assert s==s
assert s!=None
if sys.version_info > (3,0):
try:
s < None
raise error("Expected type error")
except TypeError:
pass
try:
None < s
raise error("Expected type error")
except TypeError:
pass
assert s != s.sub_val
import copy
s2 = copy.copy(s)
assert s is not s2
assert s == s2
s2.int_val = 123
assert s != s2
# Make sure everything works with functions
s2 = vbtest.GetStructFunc()
assert s==s2
vbtest.SetStructSub(s2)
# Create a new structure, and set its elements.
s = win32com.client.Record("VBStruct", vbtest)
assert s.int_val == 0, "new struct inst initialized correctly!"
s.int_val = -1
vbtest.SetStructSub(s)
assert vbtest.GetStructFunc().int_val == -1, "new struct didnt make the round trip!"
# Finally, test stand-alone structure arrays.
s_array = vbtest.StructArrayProperty
assert s_array is None, "Expected None from the uninitialized VB array"
vbtest.MakeStructArrayProperty(3)
s_array = vbtest.StructArrayProperty
assert len(s_array)==3
for i in range(len(s_array)):
assert s_array[i].int_val == i
assert s_array[i].sub_val.int_val == i
assert s_array[i].sub_val.array_val[0].int_val == i
assert s_array[i].sub_val.array_val[1].int_val == i+1
assert s_array[i].sub_val.array_val[2].int_val == i+2
# Some error type checks.
try:
s.bad_attribute
raise RuntimeError("Could get a bad attribute")
except AttributeError:
pass
m = s.__members__
assert m[0]=="int_val" and m[1]=="str_val" and m[2]=="ob_val" and m[3]=="sub_val", m
# Test attribute errors.
try:
s.foo
raise RuntimeError("Expected attribute error")
except AttributeError as exc:
assert "foo" in str(exc), exc
# test repr - it uses repr() of the sub-objects, so check it matches.
expected = "com_struct(int_val=%r, str_val=%r, ob_val=%r, sub_val=%r)" % (s.int_val, s.str_val, s.ob_val, s.sub_val)
if repr(s) != expected:
print("Expected repr:", expected)
print("Actual repr :", repr(s))
raise RuntimeError("repr() of record object failed")
print("Struct/Record tests passed")
def TestVBInterface(ob):
t = ob.GetInterfaceTester(2)
if t.getn() != 2:
raise error("Initial value wrong")
t.setn(3)
if t.getn() != 3:
raise error("New value wrong")
def TestObjectSemantics(ob):
# a convenient place to test some of our equality semantics
assert ob==ob._oleobj_
assert not ob!=ob._oleobj_
# same test again, but lhs and rhs reversed.
assert ob._oleobj_==ob
assert not ob._oleobj_!=ob
# same tests but against different pointers. COM identity rules should
# still ensure all works
assert ob._oleobj_==ob._oleobj_.QueryInterface(pythoncom.IID_IUnknown)
assert not ob._oleobj_!=ob._oleobj_.QueryInterface(pythoncom.IID_IUnknown)
assert ob._oleobj_!=None
assert None!=ob._oleobj_
assert ob!=None
assert None!=ob
if sys.version_info > (3,0):
try:
ob < None
raise error("Expected type error")
except TypeError:
pass
try:
None < ob
raise error("Expected type error")
except TypeError:
pass
assert ob._oleobj_.QueryInterface(pythoncom.IID_IUnknown)==ob._oleobj_
assert not ob._oleobj_.QueryInterface(pythoncom.IID_IUnknown)!=ob._oleobj_
assert ob._oleobj_==ob._oleobj_.QueryInterface(pythoncom.IID_IDispatch)
assert not ob._oleobj_!=ob._oleobj_.QueryInterface(pythoncom.IID_IDispatch)
assert ob._oleobj_.QueryInterface(pythoncom.IID_IDispatch)==ob._oleobj_
assert not ob._oleobj_.QueryInterface(pythoncom.IID_IDispatch)!=ob._oleobj_
print("Object semantic tests passed")
def DoTestAll():
o = win32com.client.Dispatch("PyCOMVBTest.Tester")
TestObjectSemantics(o)
TestVB(o,1)
o = win32com.client.dynamic.DumbDispatch("PyCOMVBTest.Tester")
TestObjectSemantics(o)
TestVB(o,0)
def TestAll():
# Import the type library for the test module. Let the 'invalid clsid'
# exception filter up, where the test runner will treat it as 'skipped'
win32com.client.gencache.EnsureDispatch("PyCOMVBTest.Tester")
if not __debug__:
raise RuntimeError("This must be run in debug mode - we use assert!")
try:
DoTestAll()
print("All tests appear to have worked!")
except:
# ?????
print("TestAll() failed!!")
traceback.print_exc()
raise
# Make this test run under our test suite to leak tests etc work
def suite():
import unittest
test = util.CapturingFunctionTestCase(TestAll, description="VB tests")
suite = unittest.TestSuite()
suite.addTest(test)
return suite
if __name__=='__main__':
util.testmain()

View file

@ -0,0 +1,37 @@
import unittest
from win32com.client.gencache import EnsureDispatch
from win32com.client.dynamic import DumbDispatch
import win32com.test.util
class RegexTest(win32com.test.util.TestCase):
def _CheckMatches(self, match, expected):
found = []
for imatch in match:
found.append(imatch.FirstIndex)
self.assertEquals(list(found), list(expected))
def _TestVBScriptRegex(self, re):
StringToSearch = "Python python pYthon Python"
re.Pattern = "Python"
re.Global = True
re.IgnoreCase = True
match = re.Execute(StringToSearch)
expected = 0, 7, 14, 21
self._CheckMatches(match, expected)
re.IgnoreCase = False
match = re.Execute(StringToSearch)
expected = 0, 21
self._CheckMatches(match, expected)
def testDynamic(self):
re = DumbDispatch("VBScript.Regexp")
self._TestVBScriptRegex(re)
def testGenerated(self):
re = EnsureDispatch("VBScript.Regexp")
self._TestVBScriptRegex(re)
if __name__=='__main__':
unittest.main()

View file

@ -0,0 +1,12 @@
//Args: input-file style-file output-file
var xml = WScript.CreateObject("Microsoft.XMLDOM"); //input
xml.validateOnParse=false;
xml.load(WScript.Arguments(0));
var xsl = WScript.CreateObject("Microsoft.XMLDOM"); //style
xsl.validateOnParse=false;
xsl.load(WScript.Arguments(1));
var out = WScript.CreateObject("Scripting.FileSystemObject"); //output
var replace = true; var unicode = false; //output file properties
var hdl = out.CreateTextFile( WScript.Arguments(2), replace, unicode )
hdl.write( xml.transformNode( xsl.documentElement ));
//eof

View file

@ -0,0 +1,29 @@
import os
import tempfile
import unittest
import win32com.test.util
expected_output = "The jscript test worked.\nThe Python test worked"
class XSLT(win32com.test.util.TestCase):
def testAll(self):
output_name = tempfile.mktemp("-pycom-test")
cmd = "cscript //nologo testxslt.js doesnt_matter.xml testxslt.xsl " + output_name
win32com.test.util.ExecuteShellCommand(cmd, self)
try:
f=open(output_name)
try:
got = f.read()
if got != expected_output:
print("ERROR: XSLT expected output of %r" % (expected_output,))
print("but got %r" % (got,))
finally:
f.close()
finally:
try:
os.unlink(output_name)
except os.error:
pass
if __name__=='__main__':
unittest.main()

View file

@ -0,0 +1,55 @@
<!-- include in the xsl:stylesheet element:
(a) the version attribute as usual
(b) the XSLT namespace declaration as usual
(c) the MSXSL namespace declaration
(d) a namespace declaration to identify your functions
(e) the 'extension-element-prefixes' attribute to give the
namespace prefixes that indicate extension elements
(i.e. 'msxsl')
(f) the 'exclude-result-prefixes' attribute to indicate the
namespaces that aren't supposed to be part of the result
tree (i.e. 'foo') -->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:foo="http://www.pythoncom-test.com/foo"
xmlns:bar="http://www.pythoncom-test.com/bar"
extension-element-prefixes="msxsl"
exclude-result-prefixes="foo bar">
<!-- do whatever output you want - you can use full XSLT functionality
-->
<xsl:output method="html" />
<!-- define the Javascript functions that you want to include within
a msxsl:script element.
- language indicates the scripting language
- implements-prefix gives the namespace prefix that you declared
for your function (i.e. foo) -->
<msxsl:script language="javascript"
implements-prefix="foo">
function worked() {
return "The jscript test worked";
}
</msxsl:script>
<!-- ditto for Python, using the 'bar' namespace
-->
<msxsl:script language="python"
implements-prefix="bar">
def worked():
return "The Python test worked"
</msxsl:script>
<xsl:template match="/">
<!-- The output template. Keep whitespace down as our test matches text exactly -->
<!-- call your functions using the prefix that you've used (i.e.
foo) anywhere you can normally use an XPath function, but
make sure it's returning the right kind of object -->
<xsl:value-of select="foo:worked()" />.
<xsl:value-of select="bar:worked()" />
</xsl:template>
</xsl:stylesheet>

View file

@ -0,0 +1,225 @@
import sys, os
import win32api
import tempfile
import unittest
import gc
import pywintypes
import pythoncom
import winerror
from pythoncom import _GetInterfaceCount, _GetGatewayCount
import win32com
import logging
import winreg
import io as StringIO
import pywin32_testutil
from pywin32_testutil import TestLoader, TestResult, TestRunner, LeakTestCase
def CheckClean():
# Ensure no lingering exceptions - Python should have zero outstanding
# COM objects
try:
sys.exc_clear()
except AttributeError:
pass # py3k
c = _GetInterfaceCount()
if c:
print("Warning - %d com interface objects still alive" % c)
c = _GetGatewayCount()
if c:
print("Warning - %d com gateway objects still alive" % c)
def RegisterPythonServer(filename, progids=None, verbose=0):
if progids:
if isinstance(progids, str):
progids = [progids]
# we know the CLSIDs we need, but we might not be an admin user
# and otherwise unable to register them. So as long as the progids
# exist and the DLL points at our version, assume it already is.
why_not = None
for progid in progids:
clsid = pywintypes.IID(progid)
try:
HKCR = winreg.HKEY_CLASSES_ROOT
hk = winreg.OpenKey(HKCR, "CLSID\\%s" % clsid)
dll = winreg.QueryValue(hk, "InprocServer32")
except WindowsError:
# no CLSID or InProcServer32 - not registered
break
ok_files = [os.path.basename(pythoncom.__file__),
'pythoncomloader%d%d.dll' % (sys.version_info[0], sys.version_info[1])]
if os.path.basename(dll) not in ok_files:
why_not = "%r is registered against a different Python version (%s)" % (progid, dll)
break
else:
#print "Skipping registration of '%s' - already registered" % filename
return
# needs registration - see if its likely!
try:
from win32com.shell.shell import IsUserAnAdmin
except ImportError:
print("Can't import win32com.shell - no idea if you are an admin or not?")
is_admin = False
else:
try:
is_admin = IsUserAnAdmin()
except pythoncom.com_error:
# old, less-secure OS - assume *is* admin.
is_admin = True
if not is_admin:
msg = "%r isn't registered, but I'm not an administrator who can register it." % progids[0]
if why_not:
msg += "\n(registration check failed as %s)" % why_not
# throw a normal "class not registered" exception - we don't report
# them the same way as "real" errors.
raise pythoncom.com_error(winerror.CO_E_CLASSSTRING, msg, None, -1)
# so theoretically we are able to register it.
cmd = '%s "%s" --unattended > nul 2>&1' % (win32api.GetModuleFileName(0), filename)
if verbose:
print("Registering engine", filename)
# print cmd
rc = os.system(cmd)
if rc:
print("Registration command was:")
print(cmd)
raise RuntimeError("Registration of engine '%s' failed" % filename)
def ExecuteShellCommand(cmd, testcase,
expected_output = None, # Set to '' to check for nothing
tracebacks_ok = 0, # OK if the output contains a t/b?
):
output_name = tempfile.mktemp('win32com_test')
cmd = cmd + ' > "%s" 2>&1' % output_name
rc = os.system(cmd)
output = open(output_name, "r").read().strip()
os.remove(output_name)
class Failed(Exception): pass
try:
if rc:
raise Failed("exit code was " + str(rc))
if expected_output is not None and output != expected_output:
raise Failed("Expected output %r (got %r)" % (expected_output, output))
if not tracebacks_ok and \
output.find("Traceback (most recent call last)")>=0:
raise Failed("traceback in program output")
return output
except Failed as why:
print("Failed to exec command '%r'" % cmd)
print("Failed as", why)
print("** start of program output **")
print(output)
print("** end of program output **")
testcase.fail("Executing '%s' failed as %s" % (cmd, why))
def assertRaisesCOM_HRESULT(testcase, hresult, func, *args, **kw):
try:
func(*args, **kw)
except pythoncom.com_error as details:
if details.hresult==hresult:
return
testcase.fail("Excepected COM exception with HRESULT 0x%x" % hresult)
class CaptureWriter:
def __init__(self):
self.old_err = self.old_out = None
self.clear()
def capture(self):
self.clear()
self.old_out = sys.stdout
self.old_err = sys.stderr
sys.stdout = sys.stderr = self
def release(self):
if self.old_out:
sys.stdout = self.old_out
self.old_out = None
if self.old_err:
sys.stderr = self.old_err
self.old_err = None
def clear(self):
self.captured = []
def write(self, msg):
self.captured.append(msg)
def get_captured(self):
return "".join(self.captured)
def get_num_lines_captured(self):
return len("".join(self.captured).split("\n"))
# Utilities to set the win32com logger to something what just captures
# records written and doesn't print them.
class LogHandler(logging.Handler):
def __init__(self):
self.emitted = []
logging.Handler.__init__(self)
def emit(self, record):
self.emitted.append(record)
_win32com_logger = None
def setup_test_logger():
old_log = getattr(win32com, "logger", None)
global _win32com_logger
if _win32com_logger is None:
_win32com_logger = logging.Logger('test')
handler = LogHandler()
_win32com_logger.addHandler(handler)
win32com.logger = _win32com_logger
handler = _win32com_logger.handlers[0]
handler.emitted = []
return handler.emitted, old_log
def restore_test_logger(prev_logger):
assert prev_logger is None, "who needs this?"
if prev_logger is None:
del win32com.logger
else:
win32com.logger = prev_logger
# We used to override some of this (and may later!)
TestCase = unittest.TestCase
def CapturingFunctionTestCase(*args, **kw):
real_test = _CapturingFunctionTestCase(*args, **kw)
return LeakTestCase(real_test)
class _CapturingFunctionTestCase(unittest.FunctionTestCase):#, TestCaseMixin):
def __call__(self, result=None):
if result is None: result = self.defaultTestResult()
writer = CaptureWriter()
#self._preTest()
writer.capture()
try:
unittest.FunctionTestCase.__call__(self, result)
if getattr(self, "do_leak_tests", 0) and hasattr(sys, "gettotalrefcount"):
self.run_leak_tests(result)
finally:
writer.release()
#self._postTest(result)
output = writer.get_captured()
self.checkOutput(output, result)
if result.showAll:
print(output)
def checkOutput(self, output, result):
if output.find("Traceback")>=0:
msg = "Test output contained a traceback\n---\n%s\n---" % output
result.errors.append((self, msg))
class ShellTestCase(unittest.TestCase):
def __init__(self, cmd, expected_output):
self.__cmd = cmd
self.__eo = expected_output
unittest.TestCase.__init__(self)
def runTest(self):
ExecuteShellCommand(self.__cmd, self, self.__eo)
def __str__(self):
max = 30
if len(self.__cmd)>max:
cmd_repr = self.__cmd[:max] + "..."
else:
cmd_repr = self.__cmd
return "exec: " + cmd_repr
def testmain(*args, **kw):
pywin32_testutil.testmain(*args, **kw)
CheckClean()