COM bites - help please

Karl Putland kperacles at geocities.com
Fri Jul 23 11:10:07 EDT 1999


Bill Tutt <billtut at microsoft.com> wrote in message news:4D0A23B3F74DD111ACCD00805F31D8100DB90F9C at RED-MSG-50...
> 
> 
> > From: Karl Putland [mailto:kperacles at geocities.com]
> 
> > I've got a couple of pyCOM things that are kicking my @$$! 
> > 
> > 1.  Trying to wrap a list of instances into a 
> > util.Collection.  All instances have been prepped with 
> > _public_methods_ and _public_attrs_ and have been wrapped 
> > with a call to win32com.server.util.wrap(field) Trying to 
> > access the Collection from a com instance produces the 
> > following error.
> > 
> [...]
> > >>> c1.fields        # This is a util.Collection(list of 
> > GMField instances)
> > Traceback (innermost last):
> >   File "<pyshell#56>", line 1, in ?
> >     c1.fields
> >   File "D:\Python\win32com\client\dynamic.py", line 394, in 
> > __getattr__
> >     raise pythoncom.com_error, details
> > com_error: (-2147467259, 'Unspecified error', None, None)
> > 
> 
> Not having the source makes it more difficult to help here...
> If memory serves given a list of Python instances that can be wrapped as COM
> objects, the way to make a collection is:
> 

I can e-mail the source if you would like to take a look.  I thought it was going to be to large.  There are four tightly connected modules and most of it is specific to GoldMine.  I couldn't really reduce it beyond what it is.

> collection = util.Collection(map(lambda x: util.wrap(x), list)
> 

Thanks,
Kind of what I've done, but this is how I had it done with the error being produced.

def gm_com_table_prep(table_inst):
    """Preppare for COM wrapper of gmtasble.GMTable

    Need to see if we can generate the COM specific attributes on a per
    instance basis.

    The GMTable class is not pulicly accesable.  GMTables are only created by
    the factory in GMcomConnector.  They get wrapped in the COM interface
    there.  This just gives each instance the appropriate COM attributes

    """

    # Changes the date format to a string from a date tuple
    table_inst.COM = 1
    
    table_inst._public_methods_ = ['append',
                        'bottom',
                        'close',
                        'delete',
                        'filter',
                        'goto',
                        'is_sql',
                        'new',
                        'open',
                        'range',
                        'read',
                        'replace',
                        'search',
                        'seek',
                        'set_order',
                        'skip',
                        'tables',
                        'top',
                        'unlock']

    table_inst._public_attrs_ = ['name',
                                 'handle',
                                 'records',
                                 'rec_no',
                                 'fields',
                                 'fieldnames']
    if debug: print "\nLooping over fields to set _public_attrs_ for table", table_inst.name
    for name in table_inst.fieldnames:
        table_inst._public_attrs_.append(string.lower(name))
    if debug: print "\nWrapping Fields"
    tmpfields=[]
    for field in table_inst.fields:
        field._public_methods_ = ['read',
                                  'write',
                                  'append']
        field._public_attrs_ = ['name',
                                'size',
                                'type'
                                'value']
        name = string.lower(field.name)
        field = win32com.server.util.wrap(field)
        tmpfields.append(field)
        setattr(table_inst, name, field)
    table_inst.fields=tmpfields


> > 3. PyUnicode objects bit me in the ass when strings are 
> > passed into methods and manipulated.
> > class Foo:
> >     <COM stuff>
> >     def bar(self, somestring):
> >         somestring = string.upper(somestring)
> >         return somestring
> > 
> > >>>foo = win32com.client.Dispatch("Python.Foo")
> > >>>foo.bar("Hello World")
> > 
> 
> PyUnicode strings have an upper and a lower method so this becomes:
> def bar(self, somestring):
> somestring = somestring.upper()
> return somestring
> 

Sorry simplistic example.  Don't remember the exact error but I had to do it here and I don't even manipulate the string.

    def seek(self, indexvalue=''):
        """Not quite sure how to handle this.
        
        Currently no err is exact match.
        0 == Error
        1 == Exact match - no error
        2 == Close match - no error???
        """

        # String conversion for COM
        indexvalue = str(indexvalue)
        
        res = self.gmdll.db_seek(self.handle, indexvalue)
        if res == 0:
            raise GMSeekError, 0
        elif res == 2:
            raise GMMatchError, indexvalue

> > Some traceback about TypeError PyUnicode.
> > 
> > Causing a need to change bar to
> >     def bar(self, somestring):
> >         somestring=str(somestring)
> >         somestring = string.upper(somestring)
> >         return somestring
> > This change needs to be made in ALL methods that accept and 
> > manipulate strings???
> > 
> 
> This is the bane of Unicode, the string module can't handle them.
> You either have to pass Unicode into functions that like Unicode, or convert
> the Unicode into a normal Python string. Not much else you can do about
> this.
> It's been rumored that Unicode support will get better in Python 1.6.
> 

That would be good.

> > Is there a better method than COM for allowing someone who 
> > uses VB access to Python objects, short of converting all of 
> > the VB users to Python or resorting to reimplementing in VB 
> > or C++?  
> 
> Using Python is good. :) But yes, this is the easiest way for Python and VB
> to talk to each other.
> 
> > The COM interface I've been able to expose is 
> > sufficient for now but does not allow some of the access that 
> > I have in Python.  Maybe that's good in the end?
> > 
> 
> I think so. :)
> 
> Hope this helps out a little bit...
> 
> Bill

Thanks Bill.  Just got a little frustrated having to pollute the Python too much.  I would love it if you or someone else could look over what I have so far, but I know all to well the time constraints of family and job.  

I know that I have a couple things to work out.  Like right now each field holds a reference to it's parent table.  And there might be another reference floating around that doesn't let it die.  TP's Cyclops might help me here.  Other than that most of it is pretty solid.

Thanks for the help.

Karl Putland
kperacles at geocities.com





More information about the Python-list mailing list