#626 Cannot pass array of arrays

closed-wont-fix
nobody
None
5
2014-11-16
2013-02-02
Wesley Tanaka
No

With code that looks like this:

instance = win32com.client.gencache.EnsureDispatch("InDesign.Application")
doc = instance.Open("some_path")
pages = doc.Pages
page0 = pages.FirstItem()
opposing_corners=((0.0, 0.0), (72.0, 72.0))
page0.Reframe(
In=2021222766,
OpposingCorners=opposing_corners)

The reframe method:
http://cssdk.host.adobe.com/sdk/1.0/docs/WebHelp/references/csawlib/com/adobe/indesign/Page.html#reframe%28%29

expects an array containing two arrays, where each of those two arrays contains two doubles.

If I pass in a scalar like 5.0
or a 1-D array like (1.0, 1.0)
or even if I add an extra item to the array like ((0.0, 0.0), (72.0, 72.0), 5.0) or ((0.0, 0.0), (72.0, 72.0), None), the exception coming back from InDesign references the value that I passed to the Reframe method. However, if I pass ((0.0, 0.0), (72.0, 72.0)), then InDesign says that it is receiving "()"

This thread looks similar: http://stackoverflow.com/questions/10166064/python-win32com-and-2-dimensional-arrays/10167882#10167882 and the solution there is to use comtypes instead of win32com.

Is this a known issue with win32com? I tried looking at the underlying InvokeTypes call but stopped when I saw this mailing list post saying that it's poorly documented: http://mail.python.org/pipermail/python-win32/2005-December/004031.html

Discussion

  • Mark Hammond
    Mark Hammond
    2013-02-03

    Multi-dimension arrays are covered by the tests and work fine with other objects. It might be that the COM object isn't given appropriate type information for the method, meaning python might be passing arrays of, eg, doubles or variants, where the object expects just floats.

    You could try something like:

    from win32com.client import VARIANT
    import pythoncom
    arg = VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_DOUBLE, [(1.0, 1.0), (10.0, 10.0))
    and pass 'arg' as the array argument - this will force the type of the param to double. Unfortunately the docs don't indicate what specific type is needed.

     
  • Wesley Tanaka
    Wesley Tanaka
    2013-02-05

    Thanks for that tip! The COM object was expecting this:

    topleft = VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, (0.0, 0.0))
    bottomright = VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, (72.0, 72.0))
    opposing_corners = VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_VARIANT, (topleft, bottomright))

    If you don't mind too terribly, this has brought up a few other questions:

    1. To get VARIANT, I needed to upgrade pywin32 from version 214 to the latest version 218. When I was running version 214, this class:

    http://cssdk.host.adobe.com/sdk/1.0/docs/WebHelp/references/csawlib/com/adobe/indesign/Pages.html

    had a __getitem__() function defined, allowing me to do things like:

    doc = instance.Open("some_path")
    pages = doc.Pages
    page0 = pages[0]

    But after the upgrade to 218 (with no other changes), this leads to an error:

    ...
    File "C:\Python27\lib\site-packages\win32com\client\__init__.py", line 465,
    in
    __getattr__
    raise AttributeError("'%s' object has no attribute '%s'" % (repr(self),
    attr
    ))
    AttributeError: '<win32com.gen_py.Adobe InDesign CS5.5 Type Library.Pages
    instance at 0x94471592>' object has no attribute '__getitem__'

    Was support for __getitem__ removed between 214 and 218? Is there a way to get it back, or do I need to switch to calling the object-specific methods like:

    page0 = pages.FirstItem()

    Question 2. I didn't find VT_DOUBLE in pythoncom. I did find VT_R8, and that seemed to work. Am I doing something wrong/looking in the wrong place?

     
  • Mark Hammond
    Mark Hammond
    2013-02-05

    • status: open --> closed-wont-fix
     
  • Mark Hammond
    Mark Hammond
    2013-02-05

    > Was support for __getitem__ removed between 214 and 218? Is there a way to
    > get it back, or do I need to switch to calling the object-specific methods
    > like:

    I can't recall any such change. It would be interesting to know if the generated file (probably in win32com\gen_py) has __getitem__ in 214 but doesn't in 218. The other possibility is that you were not using the generated file in 214.

    > Question 2. I didn't find VT_DOUBLE in pythoncom. I did find VT_R8, and
    > that seemed to work. Am I doing something wrong/looking in the wrong
    > place?

    No, I was mistaken - VT_R8 is how COM spells a double.

    Closing this issue as there isn't much we can do to correctly guess what variant type is necessary in the array. If there turns out to be a problem with __getitem__ we should open a new bug for that