Open DS-London opened 2 years ago
Note: This will also be handled by #1931 likely - after a pending push regarding common base class of the dynamic and gen wrappers and optimizations.
The dynamic wrapper (which was only duck type similar) tried and tries a COM enumeration even in absence of type info and also a .Count
/ .Item()
pseudo iteration.
An upload / attachment of the current generated Outlook gen file ( sys.modules[ol.__module__].__file__
) would though help to clarify.
I've attached the two .py files (with a .txt extension as can't seem to attached .py files) for the _Accounts
and _Folders
objects.
FWIW, I can access DISPID_NEWENUM
(-4) and iterate over the IEnumVARIANT
interface with Win32 in C++ for the Accounts
object.
Hi, have upgraded to pywin32 305
.
Still having the same issue with Outlook collections.
import win32com.client
ns = win32com.client.gencache.EnsureDispatch('outlook.application').GetNamespace("MAPI")
accs = ns.Accounts
This works:
for n in range(1,accs.Count+1):
ac = accs.Item(n)
print(ac.DisplayName)
As does this:
it = accs.__iter__()
ob = next(it,None)
while ob is not None:
print(ob.DisplayName)
ob = next(it,None)
This does not:
for ac in accs:
print(ac.DisplayName)
or even just this:
it = iter(accs)
Both return:
TypeError: 'Accounts' object is not iterable
I had assumed that iter()
was calling the __iter__()
method of the _Accounts
object. In my gen_py files, the _Accounts
python file has this section:
def __iter__(self):
"Return a Python iterator for this object"
try:
ob = self._oleobj_.InvokeTypes(-4,LCID,3,(13, 10),())
except pythoncom.error:
raise TypeError("This object does not support enumeration")
return win32com.client.util.Iterator(ob, '{000630C5-0000-0000-C000-000000000046}')
but this is not the case (I can test this by adding a print
statement to the code in _Accounts.py
and it gets printed if I call __iter__()
but not when I call iter()
).
Any idea what is going on?
One thing I have noticed for the _Namespace
interface on the Outlook Type Library:
The Accounts
property:
[id(0x0000fad0), propget, helpcontext(0x0000030a)]
Accounts* Accounts();
but the Folders
property:
[id(0x00002103), propget, helpcontext(0x000002f5)]
_Folders* Folders();
In Python:
import win32com.client
ns = win32com.client.gencache.EnsureDispatch('outlook.application').GetNamespace("MAPI")
accs = ns.Accounts
print(type(accs))
fldrs = ns.Folders
print(type(fldrs))
yields:
<class 'win32com.gen_py.00062FFF-0000-0000-C000-000000000046x0x9x6.Accounts.Accounts'>
<class 'win32com.gen_py.00062FFF-0000-0000-C000-000000000046x0x9x6._Folders._Folders'>
And drilling down:
itf = iter(fldrs)
print(type(itf))
returns:
<class 'win32com.client.util.Iterator'>
But
ita = iter(type(accs))
print(type(ita))
gives the error:
TypeError: 'type' object is not iterable
Hence I wonder if this is a bug in the Outlook Type Library? Other comments/questions on SO back up my experience that code was working fine, and then failed: perhaps the type library was updated?
There seems to be something amiss when
win32com
generates the wrapper for some MS Outlook collections.With no cached files, this code (late binding) runs successfully.
Using
gencache
(early binding), it does not:And instead throws the
'Accounts' object is not iterable
exception when attempting to iterate over theAccounts
collection.The same is true of the
Stores
collection for theNameSpace
object. However theFolders
collection does iterate without an error.As an aside, VBA using the MS Outlook Object Library reference can iterate over the Accounts collection without issue.
Using
pywin32
version304
on Python3.9 64-bit
.