Skip to content

Commit

Permalink
Change the default value of the 'extra' parameter in the 'create' met…
Browse files Browse the repository at this point in the history
…hod of tagSAFEARRAY subtypes. (enthought#576)

* Changed the default value of the 'extra' parameter in the 'create' method
of tagSAFEARRAY subtypes which are generated by '_midlSAFEARRAY' to the
setting for 'extra' identified in the '_make_safearray_type' method.

The 'extra' value required for the creation of SAFEARRAYs with VT_RECORD,
VT_DISPATCH or VT_UNKNOWN elements is already identified at the time when
the associated tagSAFEARRAY subtype is created in the '_make_safearray_type'
method. Using this value by default for the 'extra' parameter when creating
an instance of the type does avoid performing the same identification process
again in user code.

* Added a unittest for the changed default value of the 'extra'
parameter in the 'create' method of tagSAFEARRAY subtypes.

* Changed the dispatch interface test to use the 'IDispSafearrayParamTest'
interface of the C++ COM test server instead of the 'IDictionary' interface
of the Microsoft Script Runtime.

* Removed unused import of 'ctypes.byref'.

Added values for the 'answer' and 'needs_clarification' fields of
the 'StructRecordParamTest' structure and included them in the
assertion testing.
  • Loading branch information
geppi authored Jun 29, 2024
1 parent 11d7651 commit 716719d
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 1 deletion.
2 changes: 1 addition & 1 deletion comtypes/safearray.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ class _(object):
_needsfree = False

@classmethod
def create(cls, value, extra=None):
def create(cls, value, extra=extra):
"""Create a POINTER(SAFEARRAY_...) instance of the correct
type; value is an object containing the items to store.
Expand Down
100 changes: 100 additions & 0 deletions comtypes/test/test_midl_safearray_create.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# coding: utf-8

from ctypes import c_int, pointer, POINTER
import unittest

import comtypes
import comtypes.safearray
from comtypes import CLSCTX_INPROC_SERVER, CLSCTX_LOCAL_SERVER
from comtypes.client import CreateObject, GetModule
import comtypes.typeinfo

GetModule("UIAutomationCore.dll")
from comtypes.gen.UIAutomationClient import CUIAutomation, IUIAutomation

ComtypesCppTestSrvLib_GUID = "{07D2AEE5-1DF8-4D2C-953A-554ADFD25F99}"

try:
GetModule((ComtypesCppTestSrvLib_GUID, 1, 0, 0))
from comtypes.gen.ComtypesCppTestSrvLib import StructRecordParamTest
from comtypes.gen.ComtypesCppTestSrvLib import IDispSafearrayParamTest

IMPORT_FAILED = False
except (ImportError, OSError):
IMPORT_FAILED = True


class Test_midlSAFEARRAY_create(unittest.TestCase):
def test_iunk(self):
extra = pointer(IUIAutomation._iid_)
iuia = CreateObject(
CUIAutomation().IPersist_GetClassID(),
interface=IUIAutomation,
clsctx=CLSCTX_INPROC_SERVER,
)
sa_type = comtypes.safearray._midlSAFEARRAY(POINTER(IUIAutomation))
for ptn, sa in [
("with extra", sa_type.create([iuia], extra=extra)),
("without extra", sa_type.create([iuia])),
]:
with self.subTest(ptn=ptn):
(unpacked,) = sa.unpack()
self.assertIsInstance(unpacked, POINTER(IUIAutomation))

@unittest.skipIf(IMPORT_FAILED, "This depends on the out of process COM-server.")
def test_idisp(self):
extra = pointer(IDispSafearrayParamTest._iid_)
idisp = CreateObject(
"Comtypes.DispSafearrayParamTest",
clsctx=CLSCTX_LOCAL_SERVER,
interface=IDispSafearrayParamTest,
)
sa_type = comtypes.safearray._midlSAFEARRAY(POINTER(IDispSafearrayParamTest))
for ptn, sa in [
("with extra", sa_type.create([idisp], extra=extra)),
("without extra", sa_type.create([idisp])),
]:
with self.subTest(ptn=ptn):
(unpacked,) = sa.unpack()
self.assertIsInstance(unpacked, POINTER(IDispSafearrayParamTest))

@unittest.skipIf(IMPORT_FAILED, "This depends on the out of process COM-server.")
def test_record(self):
extra = comtypes.typeinfo.GetRecordInfoFromGuids(
*StructRecordParamTest._recordinfo_
)
record = StructRecordParamTest()
record.question = "The meaning of life, the universe and everything?"
record.answer = 42
record.needs_clarification = True
sa_type = comtypes.safearray._midlSAFEARRAY(StructRecordParamTest)
for ptn, sa in [
("with extra", sa_type.create([record], extra=extra)),
("without extra", sa_type.create([record])),
]:
with self.subTest(ptn=ptn):
(unpacked,) = sa.unpack()
self.assertIsInstance(unpacked, StructRecordParamTest)
self.assertEqual(
unpacked.question,
"The meaning of life, the universe and everything?",
)
self.assertEqual(unpacked.answer, 42)
self.assertEqual(unpacked.needs_clarification, True)

def test_ctype(self):
extra = None
cdata = c_int(1)
sa_type = comtypes.safearray._midlSAFEARRAY(c_int)
for ptn, sa in [
("with extra", sa_type.create([cdata], extra=extra)),
("without extra", sa_type.create([cdata])),
]:
with self.subTest(ptn=ptn):
(unpacked,) = sa.unpack()
self.assertIsInstance(unpacked, int)
self.assertEqual(unpacked, 1)


if __name__ == "__main__":
unittest.main()
2 changes: 2 additions & 0 deletions source/CppTestSrv/SERVER.IDL
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

import "oaidl.idl" ;

// Simple structure used for tests related to IRecordInfo or GetRecordInfoFromGuids functionality.
// If a new test would require other fields do NOT modify this structure but add a new structure instead.
typedef [uuid(00FABB0F-5691-41A6-B7C1-11606671F8E5)]
struct StructRecordParamTest {
BSTR question ;
Expand Down

0 comments on commit 716719d

Please sign in to comment.