Re: Python COM iterator
Carsten Haese wrote: [...] On Tue, 2007-04-17 at 16:54 -0500, Larry Bates wrote: Does anyone know if there is a way to make a Python COM object act like a proper iterator in VB/Delphi? [...] After more googling, staring at win32com's code, and a fair bit of trial and error, I've come up with the following working example: # server.py import pythoncom class HelloWorld: _reg_clsid_ = {CAB8BED1-9174-4AAD-ABC5-F377951CB71B} _reg_desc_ = Python Test COM Server _reg_progid_ = Python.TestServer _public_methods_ = ['Next'] _com_interfaces_ = [pythoncom.IID_IEnumVARIANT] def __init__(self): self.numbers=[1,2,3,4,5,6,7,8] def Next(self, count): assert count==1 try: return (self.numbers.pop(0),) except IndexError: return () def _NewEnum(self): import win32com.server.util return win32com.server.util.wrap(self) if __name__=='__main__': import win32com.server.register win32com.server.register.UseCommandLine(HelloWorld) # client.py import win32com.client comobj = win32com.client.Dispatch(Python.TestServer) for x in comobj: print x This works for me on Python 2.5 and pywin32 Build 210, but I don't know whether clients in VB or Delphi are able to use this iterator. -Carsten I tested in VB and by golly it works! What is odd is that this looks NOTHING like what we got from the docs earlier. No GetEnumerator method, no MoveNext method. I'm glad it works, but I'm a little puzzled as to why it works. Thanks loads. -Larry -- http://mail.python.org/mailman/listinfo/python-list
Re: Python COM iterator
Larry Bates wrote: Carsten Haese wrote: [iterative acess to COM objects] I tested in VB and by golly it works! What is odd is that this looks NOTHING like what we got from the docs earlier. No GetEnumerator method, no MoveNext method. I'm glad it works, but I'm a little puzzled as to why it works. Presumably the magic of mark Hammond's wrapper classes providing adaptation between Python iteration and COM enumerable collection objects. win32all is *very* Pythonic. Jim Hugunin, the author of IronPython (and of J[P]ython before that) has commented that Microsoft users are frequently surprised by the small amount of code required in IronPython to manipulate .NET objects. regards Steve -- Steve Holden +44 150 684 7255 +1 800 494 3119 Holden Web LLC/Ltd http://www.holdenweb.com Skype: holdenweb http://del.icio.us/steve.holden Recent Ramblings http://holdenweb.blogspot.com -- http://mail.python.org/mailman/listinfo/python-list
Re: Python COM iterator
On Thu, 2007-04-19 at 12:49 -0400, Steve Holden wrote: Larry Bates wrote: Carsten Haese wrote: [iterative acess to COM objects] I tested in VB and by golly it works! What is odd is that this looks NOTHING like what we got from the docs earlier. No GetEnumerator method, no MoveNext method. I'm glad it works, but I'm a little puzzled as to why it works. I'm glad, too. Presumably the magic of mark Hammond's wrapper classes providing adaptation between Python iteration and COM enumerable collection objects. win32all is *very* Pythonic. There is some magic, but it appears to be on the client side only. This magic is what allows you to stick the win32com.client.Dispatcher object into a for-loop. If there were magic on the server side, it shouldn't be necessary to declare that IID_IEnumVARIANT is exposed, and it shouldn't be necessary to implement the _NewEnum and Next methods; it should be enough to have __iter__ present and let the magic take care of the rest. It appears that the reason why my first completely uninformed guess didn't work and my second somewhat less uninformed guess did work is that there are two different enumeration protocols in the wonderfully confusing world of Win32. I'm guessing that GetEnumerator/MoveNext is the .NET enumeration protocol and IID_IEnumVARIANT/Next is the COM enumeration protocol. -Carsten -- http://mail.python.org/mailman/listinfo/python-list
Re: Python COM iterator
Larry Bates wrote: I tested in VB and by golly it works! What is odd is that this looks NOTHING like what we got from the docs earlier. No GetEnumerator method, no MoveNext method. I'm glad it works, but I'm a little puzzled as to why it works. The documention Carsten Haese referenced earlier was for the .NET version of VisualBasic, and shows how to use .NET's IEnumerate and IEnumerable interfaces. Steve Holden [EMAIL PROTECTED] wrote: Presumably the magic of mark Hammond's wrapper classes providing adaptation between Python iteration and COM enumerable collection objects. win32all is *very* Pythonic. Maybe Mark Hammond's win32all provides such a magic wrapper, but Cartsen Haese's example didn't use it. Instead it provided it own implementation of the COM IEnumVARIANT interface, the OLE Automation (ie. VisualBasic 6 compatable) way implementing iteratable objects. Ross Ridge -- l/ // Ross Ridge -- The Great HTMU [oo][oo] [EMAIL PROTECTED] -()-/()/ http://www.csclub.uwaterloo.ca/~rridge/ db // -- http://mail.python.org/mailman/listinfo/python-list
Re: Python COM iterator
Ross Ridge wrote: Larry Bates wrote: I tested in VB and by golly it works! What is odd is that this looks NOTHING like what we got from the docs earlier. No GetEnumerator method, no MoveNext method. I'm glad it works, but I'm a little puzzled as to why it works. The documention Carsten Haese referenced earlier was for the .NET version of VisualBasic, and shows how to use .NET's IEnumerate and IEnumerable interfaces. Steve Holden [EMAIL PROTECTED] wrote: Presumably the magic of mark Hammond's wrapper classes providing adaptation between Python iteration and COM enumerable collection objects. win32all is *very* Pythonic. Maybe Mark Hammond's win32all provides such a magic wrapper, but Cartsen Haese's example didn't use it. Instead it provided it own implementation of the COM IEnumVARIANT interface, the OLE Automation (ie. VisualBasic 6 compatable) way implementing iteratable objects. Ross Ridge So I saw when I read Carsten's reply to my post. Thanks. It's the difference between COM and .NET (something I am currently having to come to terms with myself, but strangely in C# rather than Python). regards Steve -- Steve Holden +44 150 684 7255 +1 800 494 3119 Holden Web LLC/Ltd http://www.holdenweb.com Skype: holdenweb http://del.icio.us/steve.holden Recent Ramblings http://holdenweb.blogspot.com -- http://mail.python.org/mailman/listinfo/python-list
Re: Python COM iterator
Carsten Haese wrote: On Tue, 2007-04-17 at 16:54 -0500, Larry Bates wrote: Does anyone know if there is a way to make a Python COM object act like a proper iterator in VB/Delphi? I don't use COM, VB, or Delphi, but Google turned up these two references: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbcn7/html/vaconUsingForEach.asp http://17slon.com/blogs/gabr/2007/03/fun-with-enumerators-part-1.html Judging from those links, an object is iterable in VB and Delphi (or as they call it, it is enumerable) if it exposes a GetEnumerator method that returns an enumerator. The enumerator in turn needs to expose a MoveNext method and a Current property. Assuming that the Enumerable and the Enumerator are allowed to be the same object, you'll probably need code that looks something like this: class foo: _public_methods_=['GetEnumerator','MoveNext'] # You'll need to figure out how to expose self.Current def __init__(self): self.numbers=[1,2,3,4,5,6,7,8] self.Current = None def MoveNext(self): try: self.Current = self.numbers.pop(0) return True except IndexError: return False def GetEnumerator(self): return self Good luck, Carsten. I looked over the links and what you have proposed seems to make sense, but I can't make it work. I have the following class defined and registered. class foo: _public_methods_=['GetEnumerator','MoveNext'] _public_attrs_=['Current'] _reg_clsid_='{FC2A0E7B-E428-4414-B1C4-60373BB12102}' _reg_progid_=Syscon.foo def __init__(self): self.numbers=[1,2,3,4,5,6,7,8] self.Current = None def MoveNext(self): try: self.Current = self.numbers.pop(0) rtnval=True except IndexError: self.Current=None rtnval=False def GetEnumerator(self): return self Then I do: import win32com.client typelib='Syscon.foo' F=win32com.client.Dispatch(typelib) for x in F: ... print x ... Traceback (most recent call last): File interactive input, line 1, in module File C:\Python25\lib\site-packages\win32com\client\dynamic.py, line 228, in __getitem__ raise TypeError, This object does not support enumeration TypeError: This object does not support enumeration but this works fine: F.MoveNext() F.Current 1 F.MoveNext() F.Current 2 I'm stumped. -Larry -- http://mail.python.org/mailman/listinfo/python-list
Re: Python COM iterator
[...] On Tue, 2007-04-17 at 16:54 -0500, Larry Bates wrote: Does anyone know if there is a way to make a Python COM object act like a proper iterator in VB/Delphi? [...] After more googling, staring at win32com's code, and a fair bit of trial and error, I've come up with the following working example: # server.py import pythoncom class HelloWorld: _reg_clsid_ = {CAB8BED1-9174-4AAD-ABC5-F377951CB71B} _reg_desc_ = Python Test COM Server _reg_progid_ = Python.TestServer _public_methods_ = ['Next'] _com_interfaces_ = [pythoncom.IID_IEnumVARIANT] def __init__(self): self.numbers=[1,2,3,4,5,6,7,8] def Next(self, count): assert count==1 try: return (self.numbers.pop(0),) except IndexError: return () def _NewEnum(self): import win32com.server.util return win32com.server.util.wrap(self) if __name__=='__main__': import win32com.server.register win32com.server.register.UseCommandLine(HelloWorld) # client.py import win32com.client comobj = win32com.client.Dispatch(Python.TestServer) for x in comobj: print x This works for me on Python 2.5 and pywin32 Build 210, but I don't know whether clients in VB or Delphi are able to use this iterator. -Carsten -- http://mail.python.org/mailman/listinfo/python-list
Python COM iterator
Does anyone know if there is a way to make a Python COM object act like a proper iterator in VB/Delphi? Example: Python COM object class foo: _public_methods_=['next'] def __init__(self): self.numbers=[1,2,3,4,5,6,7,8] def next(self): try: return self.numbers.pop(0) except IndexError: # # Normally in Python I would do this, but that raises a # COMexception when used in a COM object. # raise StopIteration def __iter__(self): return self I want to be able to write something like (VB): oFOO=foo() for each n in oFOO ' ' Do something with n ' next Seems like there should be a way. Hope explanation is clear enough. Regards, Larry -- http://mail.python.org/mailman/listinfo/python-list
Re: Python COM iterator
On Tue, 2007-04-17 at 16:54 -0500, Larry Bates wrote: Does anyone know if there is a way to make a Python COM object act like a proper iterator in VB/Delphi? I don't use COM, VB, or Delphi, but Google turned up these two references: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbcn7/html/vaconUsingForEach.asp http://17slon.com/blogs/gabr/2007/03/fun-with-enumerators-part-1.html Judging from those links, an object is iterable in VB and Delphi (or as they call it, it is enumerable) if it exposes a GetEnumerator method that returns an enumerator. The enumerator in turn needs to expose a MoveNext method and a Current property. Assuming that the Enumerable and the Enumerator are allowed to be the same object, you'll probably need code that looks something like this: class foo: _public_methods_=['GetEnumerator','MoveNext'] # You'll need to figure out how to expose self.Current def __init__(self): self.numbers=[1,2,3,4,5,6,7,8] self.Current = None def MoveNext(self): try: self.Current = self.numbers.pop(0) return True except IndexError: return False def GetEnumerator(self): return self Good luck, Carsten. -- http://mail.python.org/mailman/listinfo/python-list