Python and COM: a bug? (long)

Gaetan Corneau Gaetan_Corneau at
Thu Nov 25 16:46:27 CET 1999


I got help and traced the C++ code. Here's a partial  description of the COM
object hierarchy.

ITK.AdapterManager (Root class)
   ITKAdapter      (Used to connect to data sources. Ex: OLEDB)
  ITKConnection    (Actual connection to data source)
    ITKClass       (Meta-data)
  ITKDataObject    (Actual data)

Here is a small example of usage. Suppose tou have an Oracle database you
want to access using OLEDB. In that database, you have an employee table,
with the following fields: Name, address, ID, etc. To get a list of all
employees names, I write:

fromwin32com.client.dynamic import Dispatch

am = Dispatch("ITK.AdapterManager")
ad = am.GetAdapter("OLEDB")
Conn = ad.NewConnection()
Conn.Open("/dsn:HPD380 /user:gc /pwd:qwerty")

for Employee in Conn.Classes("Employee").GetObjects():
    print Employee.Name

What do we use all that for? In an integration server that manipulates
abstract data, reading from a source, writing to a destination. The server
lets you define data magppings graphically (for simple one to one field
mapping). All that stuff has nothing to do with COM. The objects containing
the data are C++ object. But when the mapping is complex, we create a COM
wrapper over those C++ object (ITKDataObject) and send them to a script
using ActiveX Scripting.

So, the problem is this. When I access "Employee.Name", I get the ID for the
Name property of Employee, but the Python COM caches it for ITKDataObject
(which, according to what Bill and you told me, is OK). If I access the name
property from another object (I mean another table), say department, then
the pythoncom tries to access the property usinf the ID generated on the fly
by Employee.

> Yes - VBScript does indeed re-query for the DISPID before each call -
> ie, it does not cache the items.  I would put money on the fact that
> this is your problem.
> I am quite confident that we do not have anything this fundamental
> broken.

So our code is not OK. You are right, I was wrong. I'm glad I didn't bet,
and, more important, I'm glad I have enough experience to fall in
finger-pointing mode. I was *quite* sure our code was OK, but I would have
been a fool if I had said I was 100% sure :)

> If it is the problem, you are clearly breaking the rules, and there is
> a good chance that later versions of VBScript, or indeed any other COM
> compatible language would also break.

Now, this is a potentially severe bug. For the time being, the integration
server is "locked" so all scripts must be written in VBScript, but it may
not be so in future version. Another thing that could go wrong is that there
is a new version of VBScript available. I haven't tried it yet, but I will:
maybe this version uses caching.

> ob = pythoncom.CoCreateInstance("Your.ProgID", None, pythoncom.CLSCTX_ALL,
> dispid = ob.GetIDsOfNames("foo")
> print dispid
> dispid2 = ob.GetIDsOfNames("foo")
> print dispid2
> if dispid != dispid2:
>   print "Eeek"

That test would be useful (I would put it as an attachment to my bug report)
if I could make it work with the architecture I described earlier. I mean, I
must compare dispids from ITKDataObjects. 
I tried Employee.GetIDsOfNames("Name"), but I get:

  File "d:\Apps\Python\win32com\client\", line 400, in __getattr__
    raise AttributeError, "%s.%s" % (self._username_, attr)
AttributeError: <unknown>.GetIDsOfNames

I tried  a couple of things (like QueryInterface), but nothing worked. 

Anyway, thanks a lot for your help! 
I have endured this bug for six months without being able to point what the
problem was!

   Gaetan Corneau
   Software Developer (Quality Assurance Team)
   BaaN  Supply Chain Solutions
   E-mail: Gaetan_Corneau at                  
   Tel: (418) 266-8252          
"Profanity is the one language all programmers know best"


More information about the Python-list mailing list