Beispiel #1
0
    def WriteVTableMap(self, generator):
        stream = generator.file
        print >> stream, "%s_vtables_dispatch_ = %d" % (self.python_name, self.bIsDispatch)
        print >> stream, "%s_vtables_ = [" % (self.python_name, ) 
        for v in self.vtableFuncs:
            names, dispid, desc = v
            arg_desc = desc[2]

            arg_reprs = []
            # more hoops so we don't generate huge lines.
            item_num = 0
            print >> stream, "\t((",
            for name in names:
                print >> stream, repr(name), ",",
                item_num = item_num + 1
                if item_num % 5 == 0:
                    print >> stream, "\n\t\t\t",
            print >> stream, "), %d, (%r, %r, [" % (dispid, desc[0], desc[1]),
            for arg in arg_desc:
                item_num = item_num + 1
                if item_num % 5 == 0:
                    print >> stream, "\n\t\t\t",
                defval = build.MakeDefaultArgRepr(arg)
                if arg[3] is None:
                    arg3_repr = None
                else:
                    arg3_repr = repr(arg[3])
                print >> stream, repr((arg[0], arg[1], defval, arg3_repr)), ",",
            print >> stream, "],",
            for d in desc[3:]:
                print >> stream, repr(d), ",", 
            print >> stream, ")),"
        print >> stream, "]"
        print >> stream
Beispiel #2
0
def MakeDefaultArgsForPropertyPut(argsDesc):
    ret = []
    for desc in argsDesc[1:]:
        default = build.MakeDefaultArgRepr(desc)
        if default is None:
            break
        ret.append(default)
    return tuple(ret)
Beispiel #3
0
    def WriteClassBody(self, generator):
        stream = generator.file
        # Write in alpha order.
        names = list(self.mapFuncs.keys())
        names.sort()
        specialItems = {
            "count": None,
            "item": None,
            "value": None,
            "_newenum": None
        }  # If found, will end up with (entry, invoke_tupe)
        itemCount = None
        for name in names:
            entry = self.mapFuncs[name]
            # skip [restricted] methods, unless it is the
            # enumerator (which, being part of the "system",
            # we know about and can use)
            dispid = entry.desc[0]
            if entry.desc[9] & pythoncom.FUNCFLAG_FRESTRICTED and \
                dispid != pythoncom.DISPID_NEWENUM:
                continue
            # If not accessible via IDispatch, then we can't use it here.
            if entry.desc[3] != pythoncom.FUNC_DISPATCH:
                continue
            if dispid == pythoncom.DISPID_VALUE:
                lkey = "value"
            elif dispid == pythoncom.DISPID_NEWENUM:
                specialItems["_newenum"] = (entry, entry.desc[4], None)
                continue  # Dont build this one now!
            else:
                lkey = name.lower()
            if lkey in specialItems and specialItems[
                    lkey] is None:  # remember if a special one.
                specialItems[lkey] = (entry, entry.desc[4], None)
            if generator.bBuildHidden or not entry.hidden:
                if entry.GetResultName():
                    print >> stream, '\t# Result is of type ' + entry.GetResultName(
                    )
                if entry.wasProperty:
                    print >> stream, '\t# The method %s is actually a property, but must be used as a method to correctly pass the arguments' % name
                ret = self.MakeFuncMethod(entry,
                                          build.MakePublicAttributeName(name))
                for line in ret:
                    print >> stream, line
        print >> stream, "\t_prop_map_get_ = {"
        names = self.propMap.keys()
        names.sort()
        for key in names:
            entry = self.propMap[key]
            if generator.bBuildHidden or not entry.hidden:
                resultName = entry.GetResultName()
                if resultName:
                    print >> stream, "\t\t# Property '%s' is an object of type '%s'" % (
                        key, resultName)
                lkey = key.lower()
                details = entry.desc
                resultDesc = details[2]
                argDesc = ()
                mapEntry = MakeMapLineEntry(details[0],
                                            pythoncom.DISPATCH_PROPERTYGET,
                                            resultDesc, argDesc, key,
                                            entry.GetResultCLSIDStr())

                if entry.desc[0] == pythoncom.DISPID_VALUE:
                    lkey = "value"
                elif entry.desc[0] == pythoncom.DISPID_NEWENUM:
                    lkey = "_newenum"
                else:
                    lkey = key.lower()
                if lkey in specialItems and specialItems[
                        lkey] is None:  # remember if a special one.
                    specialItems[lkey] = (entry,
                                          pythoncom.DISPATCH_PROPERTYGET,
                                          mapEntry)
                    # All special methods, except _newenum, are written
                    # "normally".  This is a mess!
                    if entry.desc[0] == pythoncom.DISPID_NEWENUM:
                        continue

                print >> stream, '\t\t"%s": %s,' % (
                    build.MakePublicAttributeName(key), mapEntry)
        names = self.propMapGet.keys()
        names.sort()
        for key in names:
            entry = self.propMapGet[key]
            if generator.bBuildHidden or not entry.hidden:
                if entry.GetResultName():
                    print >> stream, "\t\t# Method '%s' returns object of type '%s'" % (
                        key, entry.GetResultName())
                details = entry.desc
                lkey = key.lower()
                argDesc = details[2]
                resultDesc = details[8]
                mapEntry = MakeMapLineEntry(details[0],
                                            pythoncom.DISPATCH_PROPERTYGET,
                                            resultDesc, argDesc, key,
                                            entry.GetResultCLSIDStr())
                if entry.desc[0] == pythoncom.DISPID_VALUE:
                    lkey = "value"
                elif entry.desc[0] == pythoncom.DISPID_NEWENUM:
                    lkey = "_newenum"
                else:
                    lkey = key.lower()
                if lkey in specialItems and specialItems[
                        lkey] is None:  # remember if a special one.
                    specialItems[lkey] = (entry,
                                          pythoncom.DISPATCH_PROPERTYGET,
                                          mapEntry)
                    # All special methods, except _newenum, are written
                    # "normally".  This is a mess!
                    if entry.desc[0] == pythoncom.DISPID_NEWENUM:
                        continue
                print >> stream, '\t\t"%s": %s,' % (
                    build.MakePublicAttributeName(key), mapEntry)

        print >> stream, "\t}"

        print >> stream, "\t_prop_map_put_ = {"
        # These are "Invoke" args
        names = list(self.propMap.keys())
        names.sort()
        for key in names:
            entry = self.propMap[key]
            if generator.bBuildHidden or not entry.hidden:
                lkey = key.lower()
                details = entry.desc
                # If default arg is None, write an empty tuple
                defArgDesc = build.MakeDefaultArgRepr(details[2])
                if defArgDesc is None:
                    defArgDesc = ""
                else:
                    defArgDesc = defArgDesc + ","
                print >> stream, '\t\t"%s" : ((%s, LCID, %d, 0),(%s)),' % (
                    build.MakePublicAttributeName(key), details[0],
                    pythoncom.DISPATCH_PROPERTYPUT, defArgDesc)

        names = list(self.propMapPut.keys())
        names.sort()
        for key in names:
            entry = self.propMapPut[key]
            if generator.bBuildHidden or not entry.hidden:
                details = entry.desc
                defArgDesc = MakeDefaultArgsForPropertyPut(details[2])
                print >> stream, '\t\t"%s": ((%s, LCID, %d, 0),%s),' % (
                    build.MakePublicAttributeName(key), details[0], details[4],
                    defArgDesc)
        print >> stream, "\t}"

        if specialItems["value"]:
            entry, invoketype, propArgs = specialItems["value"]
            if propArgs is None:
                typename = "method"
                ret = self.MakeFuncMethod(entry, '__call__')
            else:
                typename = "property"
                ret = [
                    "\tdef __call__(self):\n\t\treturn self._ApplyTypes_(*%s)"
                    % propArgs
                ]
            print >> stream, "\t# Default %s for this class is '%s'" % (
                typename, entry.names[0])
            for line in ret:
                print >> stream, line
            if sys.version_info > (3, 0):
                print >> stream, "\tdef __str__(self, *args):"
                print >> stream, "\t\treturn str(self.__call__(*args))"
            else:
                print >> stream, "\tdef __unicode__(self, *args):"
                print >> stream, "\t\ttry:"
                print >> stream, "\t\t\treturn unicode(self.__call__(*args))"
                print >> stream, "\t\texcept pythoncom.com_error:"
                print >> stream, "\t\t\treturn repr(self)"
                print >> stream, "\tdef __str__(self, *args):"
                print >> stream, "\t\treturn str(self.__unicode__(*args))"
            print >> stream, "\tdef __int__(self, *args):"
            print >> stream, "\t\treturn int(self.__call__(*args))"

        if specialItems["_newenum"]:
            enumEntry, invoketype, propArgs = specialItems["_newenum"]
            resultCLSID = enumEntry.GetResultCLSIDStr()
            # If we dont have a good CLSID for the enum result, assume it is the same as the Item() method.
            if resultCLSID == "None" and "Item" in self.mapFuncs:
                resultCLSID = self.mapFuncs["Item"].GetResultCLSIDStr()
            # "Native" Python iterator support
            print >> stream, '\tdef __iter__(self):'
            print >> stream, '\t\t"Return a Python iterator for this object"'
            print >> stream, '\t\tob = self._oleobj_.InvokeTypes(%d,LCID,%d,(13, 10),())' % (
                pythoncom.DISPID_NEWENUM, enumEntry.desc[4])
            print >> stream, '\t\treturn win32com.client.util.Iterator(ob, %s)' % resultCLSID
            # And 'old style' iterator support - magically used to simulate iterators
            # before Python grew them
            print >> stream, '\tdef _NewEnum(self):'
            print >> stream, '\t\t"Create an enumerator from this object"'
            print >> stream, '\t\treturn win32com.client.util.WrapEnum(self._oleobj_.InvokeTypes(%d,LCID,%d,(13, 10),()),%s)' % (
                pythoncom.DISPID_NEWENUM, enumEntry.desc[4], resultCLSID)
            print >> stream, '\tdef __getitem__(self, index):'
            print >> stream, '\t\t"Allow this class to be accessed as a collection"'
            print >> stream, "\t\tif '_enum_' not in self.__dict__:"
            print >> stream, "\t\t\tself.__dict__['_enum_'] = self._NewEnum()"
            print >> stream, "\t\treturn self._enum_.__getitem__(index)"
        else:  # Not an Enumerator, but may be an "Item/Count" based collection
            if specialItems["item"]:
                entry, invoketype, propArgs = specialItems["item"]
                print >> stream, '\t#This class has Item property/method which may take args - allow indexed access'
                print >> stream, '\tdef __getitem__(self, item):'
                print >> stream, '\t\treturn self._get_good_object_(self._oleobj_.Invoke(*(%d, LCID, %d, 1, item)), "Item")' % (
                    entry.desc[0], invoketype)
        if specialItems["count"]:
            entry, invoketype, propArgs = specialItems["count"]
            if propArgs is None:
                typename = "method"
                ret = self.MakeFuncMethod(entry, '__len__')
            else:
                typename = "property"
                ret = [
                    "\tdef __len__(self):\n\t\treturn self._ApplyTypes_(*%s)" %
                    propArgs
                ]
            print >> stream, "\t#This class has Count() %s - allow len(ob) to provide this" % (
                typename)
            for line in ret:
                print >> stream, line
            # Also include a __nonzero__
            print >> stream, "\t#This class has a __len__ - this is needed so 'if object:' always returns TRUE."
            print >> stream, "\tdef __nonzero__(self):"
            print >> stream, "\t\treturn True"
Beispiel #4
0
    def WriteClassBody(self, generator):
        stream = generator.file
        # Write in alpha order.
        names = list(self.mapFuncs.keys())
        names.sort()
        specialItems = {"count":None, "item":None,"value":None,"_newenum":None} # If found, will end up with (entry, invoke_tupe)
        itemCount = None
        for name in names:
            entry=self.mapFuncs[name]
            # skip [restricted] methods, unless it is the
            # enumerator (which, being part of the "system",
            # we know about and can use)
            dispid = entry.desc[0]
            if entry.desc[9] & pythoncom.FUNCFLAG_FRESTRICTED and \
                dispid != pythoncom.DISPID_NEWENUM:
                continue
            # If not accessible via IDispatch, then we can't use it here.
            if entry.desc[3] != pythoncom.FUNC_DISPATCH:
                continue
            if dispid==pythoncom.DISPID_VALUE:
                lkey = "value"
            elif dispid==pythoncom.DISPID_NEWENUM:
                specialItems["_newenum"] = (entry, entry.desc[4], None)
                continue # Dont build this one now!
            else:
                lkey = name.lower()
            if lkey in specialItems and specialItems[lkey] is None: # remember if a special one.
                specialItems[lkey] = (entry, entry.desc[4], None)
            if generator.bBuildHidden or not entry.hidden:
                if entry.GetResultName():
                    print >> stream, '\t# Result is of type ' + entry.GetResultName()
                if entry.wasProperty:
                    print >> stream, '\t# The method %s is actually a property, but must be used as a method to correctly pass the arguments' % name
                ret = self.MakeFuncMethod(entry,build.MakePublicAttributeName(name))
                for line in ret:
                    print >> stream, line
        print >> stream, "\t_prop_map_get_ = {"
        names = self.propMap.keys(); names.sort()
        for key in names:
            entry = self.propMap[key]
            if generator.bBuildHidden or not entry.hidden:
                resultName = entry.GetResultName()
                if resultName:
                    print >> stream, "\t\t# Property '%s' is an object of type '%s'" % (key, resultName)
                lkey = key.lower()
                details = entry.desc
                resultDesc = details[2]
                argDesc = ()
                mapEntry = MakeMapLineEntry(details[0], pythoncom.DISPATCH_PROPERTYGET, resultDesc, argDesc, key, entry.GetResultCLSIDStr())
            
                if entry.desc[0]==pythoncom.DISPID_VALUE:
                    lkey = "value"
                elif entry.desc[0]==pythoncom.DISPID_NEWENUM:
                    lkey = "_newenum"
                else:
                    lkey = key.lower()
                if lkey in specialItems and specialItems[lkey] is None: # remember if a special one.
                    specialItems[lkey] = (entry, pythoncom.DISPATCH_PROPERTYGET, mapEntry)
                    # All special methods, except _newenum, are written
                    # "normally".  This is a mess!
                    if entry.desc[0]==pythoncom.DISPID_NEWENUM:
                        continue 

                print >> stream, '\t\t"%s": %s,' % (build.MakePublicAttributeName(key), mapEntry)
        names = self.propMapGet.keys(); names.sort()
        for key in names:
            entry = self.propMapGet[key]
            if generator.bBuildHidden or not entry.hidden:
                if entry.GetResultName():
                    print >> stream, "\t\t# Method '%s' returns object of type '%s'" % (key, entry.GetResultName())
                details = entry.desc
                lkey = key.lower()
                argDesc = details[2]
                resultDesc = details[8]
                mapEntry = MakeMapLineEntry(details[0], pythoncom.DISPATCH_PROPERTYGET, resultDesc, argDesc, key, entry.GetResultCLSIDStr())
                if entry.desc[0]==pythoncom.DISPID_VALUE:
                    lkey = "value"
                elif entry.desc[0]==pythoncom.DISPID_NEWENUM:
                    lkey = "_newenum"
                else:
                    lkey = key.lower()
                if lkey in specialItems and specialItems[lkey] is None: # remember if a special one.
                    specialItems[lkey]=(entry, pythoncom.DISPATCH_PROPERTYGET, mapEntry)
                    # All special methods, except _newenum, are written
                    # "normally".  This is a mess!
                    if entry.desc[0]==pythoncom.DISPID_NEWENUM:
                        continue 
                print >> stream, '\t\t"%s": %s,' % (build.MakePublicAttributeName(key), mapEntry)

        print >> stream, "\t}"

        print >> stream, "\t_prop_map_put_ = {"
        # These are "Invoke" args
        names = list(self.propMap.keys()); names.sort()
        for key in names:
            entry = self.propMap[key]
            if generator.bBuildHidden or not entry.hidden:
                lkey=key.lower()
                details = entry.desc
                # If default arg is None, write an empty tuple
                defArgDesc = build.MakeDefaultArgRepr(details[2])
                if defArgDesc is None:
                    defArgDesc = ""
                else:
                    defArgDesc = defArgDesc + ","
                print >> stream, '\t\t"%s" : ((%s, LCID, %d, 0),(%s)),' % (build.MakePublicAttributeName(key), details[0], pythoncom.DISPATCH_PROPERTYPUT, defArgDesc)

        names = list(self.propMapPut.keys()); names.sort()
        for key in names:
            entry = self.propMapPut[key]
            if generator.bBuildHidden or not entry.hidden:
                details = entry.desc
                defArgDesc = MakeDefaultArgsForPropertyPut(details[2])
                print >> stream, '\t\t"%s": ((%s, LCID, %d, 0),%s),' % (build.MakePublicAttributeName(key), details[0], details[4], defArgDesc)
        print >> stream, "\t}"
        
        if specialItems["value"]:
            entry, invoketype, propArgs = specialItems["value"]
            if propArgs is None:
                typename = "method"
                ret = self.MakeFuncMethod(entry,'__call__')
            else:
                typename = "property"
                ret = [ "\tdef __call__(self):\n\t\treturn self._ApplyTypes_(*%s)" % propArgs]
            print >> stream, "\t# Default %s for this class is '%s'" % (typename, entry.names[0])
            for line in ret:
                print >> stream, line
            if sys.version_info > (3,0):
                print >> stream, "\tdef __str__(self, *args):"
                print >> stream, "\t\treturn str(self.__call__(*args))"
            else:
                print >> stream, "\tdef __unicode__(self, *args):"
                print >> stream, "\t\ttry:"
                print >> stream, "\t\t\treturn unicode(self.__call__(*args))"
                print >> stream, "\t\texcept pythoncom.com_error:"
                print >> stream, "\t\t\treturn repr(self)"
                print >> stream, "\tdef __str__(self, *args):"
                print >> stream, "\t\treturn str(self.__unicode__(*args))"
            print >> stream, "\tdef __int__(self, *args):"
            print >> stream, "\t\treturn int(self.__call__(*args))"
            
        # _NewEnum (DISPID_NEWENUM) does not appear in typelib for many office objects,
        # but it can still be retrieved at runtime, so  always create __iter__.
        # Also, some of those same objects use 1-based indexing, causing the old-style
        # __getitem__ iteration to fail for index 0 where the dynamic iteration succeeds.
        if specialItems["_newenum"]:
            enumEntry, invoketype, propArgs = specialItems["_newenum"]
            invkind = enumEntry.desc[4]
            # ??? Wouldn't this be the resultCLSID for the iterator itself, rather than the resultCLSID
            #  for the result of each Next() call, which is what it's used for ???
            resultCLSID = enumEntry.GetResultCLSIDStr()
        else:
            invkind = pythoncom.DISPATCH_METHOD | pythoncom.DISPATCH_PROPERTYGET
            resultCLSID = "None"
        # If we dont have a good CLSID for the enum result, assume it is the same as the Item() method.
        if resultCLSID == "None" and "Item" in self.mapFuncs:
            resultCLSID = self.mapFuncs["Item"].GetResultCLSIDStr()
        print >> stream, '\tdef __iter__(self):'
        print >> stream, '\t\t"Return a Python iterator for this object"'
        print >> stream, '\t\ttry:'
        print >> stream, '\t\t\tob = self._oleobj_.InvokeTypes(%d,LCID,%d,(13, 10),())' % (pythoncom.DISPID_NEWENUM, invkind)
        print >> stream, '\t\texcept pythoncom.error:'
        print >> stream, '\t\t\traise TypeError("This object does not support enumeration")'
        # Iterator is wrapped as PyIEnumVariant, and each result of __next__ is Dispatch'ed if necessary
        print >> stream, '\t\treturn win32com.client.util.Iterator(ob, %s)' %resultCLSID
        
        if specialItems["item"]:
            entry, invoketype, propArgs = specialItems["item"]
            resultCLSID = entry.GetResultCLSIDStr()
            print >> stream, '\t#This class has Item property/method which allows indexed access with the object[key] syntax.'
            print >> stream, '\t#Some objects will accept a string or other type of key in addition to integers.'
            print >> stream, '\t#Note that many Office objects do not use zero-based indexing.'
            print >> stream, '\tdef __getitem__(self, key):'
            print >> stream, '\t\treturn self._get_good_object_(self._oleobj_.Invoke(*(%d, LCID, %d, 1, key)), "Item", %s)' \
                    % (entry.desc[0], invoketype, resultCLSID)

        if specialItems["count"]:
            entry, invoketype, propArgs = specialItems["count"]
            if propArgs is None:
                typename = "method"
                ret = self.MakeFuncMethod(entry,'__len__')
            else:
                typename = "property"
                ret = [ "\tdef __len__(self):\n\t\treturn self._ApplyTypes_(*%s)" % propArgs]
            print >> stream, "\t#This class has Count() %s - allow len(ob) to provide this" % (typename)
            for line in ret:
                print >> stream, line
            # Also include a __nonzero__
            print >> stream, "\t#This class has a __len__ - this is needed so 'if object:' always returns TRUE."
            print >> stream, "\tdef __nonzero__(self):"
            print >> stream, "\t\treturn True"