def _invokeex_(self, dispid, lcid, wFlags, args, kwArgs, serviceProvider): ### note: lcid is being ignored... if wFlags & DISPATCH_METHOD: try: funcname = self._dispid_to_func_[dispid] except KeyError: if not wFlags & DISPATCH_PROPERTYGET: raise COMException( scode=winerror.DISP_E_MEMBERNOTFOUND) # not found else: try: func = getattr(self._obj_, funcname) except AttributeError: # May have a dispid, but that doesnt mean we have the function! raise COMException(scode=winerror.DISP_E_MEMBERNOTFOUND) # Should check callable here try: return func(*args) except TypeError, v: # Particularly nasty is "wrong number of args" type error # This helps you see what 'func' and 'args' actually is if str(v).find("arguments") >= 0: print "** TypeError %s calling function %r(%r)" % ( v, func, args) raise
def Item(self, *args): if len(args) != 1: raise COMException(scode=winerror.DISP_E_BADPARAMCOUNT) try: return self.data[args[0]] except IndexError, desc: raise COMException(scode=winerror.DISP_E_BADINDEX, desc=str(desc))
def _getnextdispid_(self, fdex, dispid): ids = self._name_to_dispid_.values() ids.sort() if DISPID_STARTENUM in ids: ids.remove(DISPID_STARTENUM) if dispid == DISPID_STARTENUM: return ids[0] else: try: return ids[ids.index(dispid) + 1] except ValueError: # dispid not in list? raise COMException(scode=winerror.E_UNEXPECTED) except IndexError: # No more items raise COMException(scode=winerror.S_FALSE)
def _GetIDsOfNames_(self, names, lcid): """The main COM entry-point for GetIDsOfNames. This checks the validity of the arguments, and calls the _getidsofnames_ helper. """ if len(names) > 1: raise COMException(scode = winerror.DISP_E_INVALID, desc="Cannot support member argument names") return self._getidsofnames_(names, lcid)
def _getmembername_(self, dispid): if dispid in self._dispid_to_func_: return self._dispid_to_func_[dispid] elif dispid in self._dispid_to_get_: return self._dispid_to_get_[dispid] elif dispid in self._dispid_to_put_: return self._dispid_to_put_[dispid] else: raise COMException(scode=winerror.DISP_E_MEMBERNOTFOUND)
def _invokeex_(self, dispid, lcid, wFlags, args, kwargs, serviceProvider): ### note: lcid is being ignored... ### note: kwargs is being ignored... ### note: serviceProvider is being ignored... ### there might be assigned DISPID values to properties, too... try: name = self._dyn_dispid_to_name_[dispid] except KeyError: raise COMException(scode = winerror.DISP_E_MEMBERNOTFOUND, desc="Member not found") return self._obj_._dynamic_(name, lcid, wFlags, args)
def _InvokeEx_(self, dispid, lcid, wFlags, args, kwargs, serviceProvider): """The main COM entry-point for InvokeEx. This calls the _invokeex_ helper. """ #Translate a possible string dispid to real dispid. if type(dispid) == type(""): try: dispid = self._name_to_dispid_[string.lower(dispid)] except KeyError: raise COMException(scode = winerror.DISP_E_MEMBERNOTFOUND, desc="Member not found") return self._invokeex_(dispid, lcid, wFlags, args, kwargs, serviceProvider)
def Insert(self, index, value): try: index = int(index) except (ValueError, TypeError): raise COMException(scode=winerror.DISP_E_TYPEMISMATCH) self.data.insert(index, value)
def Remove(self, index): try: del self.data[index] except IndexError, desc: raise COMException(scode=winerror.DISP_E_BADINDEX, desc=str(desc))
def _getdispid_(self, name, fdex): try: ### TODO - look at the fdex flags!!! return self._name_to_dispid_[name.lower()] except KeyError: raise COMException(scode=winerror.DISP_E_UNKNOWNNAME)
class DesignatedWrapPolicy(MappedWrapPolicy): """A policy which uses a mapping to link functions and dispid A MappedWrappedPolicy which allows the wrapped object to specify, via certain special named attributes, exactly which methods and properties are exposed. All a wrapped object need do is provide the special attributes, and the policy will handle everything else. Attributes: _public_methods_ -- Required, unless a typelib GUID is given -- A list of strings, which must be the names of methods the object provides. These methods will be exposed and callable from other COM hosts. _public_attrs_ A list of strings, which must be the names of attributes on the object. These attributes will be exposed and readable and possibly writeable from other COM hosts. _readonly_attrs_ -- A list of strings, which must also appear in _public_attrs. These attributes will be readable, but not writable, by other COM hosts. _value_ -- A method that will be called if the COM host requests the "default" method (ie, calls Invoke with dispid==DISPID_VALUE) _NewEnum -- A method that will be called if the COM host requests an enumerator on the object (ie, calls Invoke with dispid==DISPID_NEWENUM.) It is the responsibility of the method to ensure the returned object conforms to the required Enum interface. _typelib_guid_ -- The GUID of the typelibrary with interface definitions we use. _typelib_version_ -- A tuple of (major, minor) with a default of 1,1 _typelib_lcid_ -- The LCID of the typelib, default = LOCALE_USER_DEFAULT _Evaluate -- Dunno what this means, except the host has called Invoke with dispid==DISPID_EVALUATE! See the COM documentation for details. """ def _wrap_(self, ob): # If we have nominated universal interfaces to support, load them now tlb_guid = getattr(ob, '_typelib_guid_', None) if tlb_guid is not None: tlb_major, tlb_minor = getattr(ob, '_typelib_version_', (1, 0)) tlb_lcid = getattr(ob, '_typelib_lcid_', 0) from win32com import universal # XXX - what if the user wants to implement interfaces from multiple # typelibs? # Filter out all 'normal' IIDs (ie, IID objects and strings starting with { interfaces = [ i for i in getattr(ob, '_com_interfaces_', []) if type(i) != pywintypes.IIDType and not i.startswith("{") ] universal_data = universal.RegisterInterfaces( tlb_guid, tlb_lcid, tlb_major, tlb_minor, interfaces) else: universal_data = [] MappedWrapPolicy._wrap_(self, ob) if not hasattr(ob, '_public_methods_') and not hasattr( ob, "_typelib_guid_"): raise error( "Object does not support DesignatedWrapPolicy, as it does not have either _public_methods_ or _typelib_guid_ attributes." ) # Copy existing _dispid_to_func_ entries to _name_to_dispid_ for dispid, name in self._dispid_to_func_.iteritems(): self._name_to_dispid_[name.lower()] = dispid for dispid, name in self._dispid_to_get_.iteritems(): self._name_to_dispid_[name.lower()] = dispid for dispid, name in self._dispid_to_put_.iteritems(): self._name_to_dispid_[name.lower()] = dispid # Patch up the universal stuff. for dispid, invkind, name in universal_data: self._name_to_dispid_[name.lower()] = dispid if invkind == DISPATCH_METHOD: self._dispid_to_func_[dispid] = name elif invkind in (DISPATCH_PROPERTYPUT, DISPATCH_PROPERTYPUTREF): self._dispid_to_put_[dispid] = name elif invkind == DISPATCH_PROPERTYGET: self._dispid_to_get_[dispid] = name else: raise ValueError("unexpected invkind: %d (%s)" % (invkind, name)) # look for reserved methods if hasattr(ob, '_value_'): self._dispid_to_get_[DISPID_VALUE] = '_value_' self._dispid_to_put_[DISPID_PROPERTYPUT] = '_value_' if hasattr(ob, '_NewEnum'): self._name_to_dispid_['_newenum'] = DISPID_NEWENUM self._dispid_to_func_[DISPID_NEWENUM] = '_NewEnum' if hasattr(ob, '_Evaluate'): self._name_to_dispid_['_evaluate'] = DISPID_EVALUATE self._dispid_to_func_[DISPID_EVALUATE] = '_Evaluate' next_dispid = self._allocnextdispid(999) # note: funcs have precedence over attrs (install attrs first) if hasattr(ob, '_public_attrs_'): if hasattr(ob, '_readonly_attrs_'): readonly = ob._readonly_attrs_ else: readonly = [] for name in ob._public_attrs_: dispid = self._name_to_dispid_.get(name.lower()) if dispid is None: dispid = next_dispid self._name_to_dispid_[name.lower()] = dispid next_dispid = self._allocnextdispid(next_dispid) self._dispid_to_get_[dispid] = name if name not in readonly: self._dispid_to_put_[dispid] = name for name in getattr(ob, "_public_methods_", []): dispid = self._name_to_dispid_.get(name.lower()) if dispid is None: dispid = next_dispid self._name_to_dispid_[name.lower()] = dispid next_dispid = self._allocnextdispid(next_dispid) self._dispid_to_func_[dispid] = name self._typeinfos_ = None # load these on demand. def _build_typeinfos_(self): # Can only ever be one for now. tlb_guid = getattr(self._obj_, '_typelib_guid_', None) if tlb_guid is None: return [] tlb_major, tlb_minor = getattr(self._obj_, '_typelib_version_', (1, 0)) tlb = pythoncom.LoadRegTypeLib(tlb_guid, tlb_major, tlb_minor) typecomp = tlb.GetTypeComp() # Not 100% sure what semantics we should use for the default interface. # Look for the first name in _com_interfaces_ that exists in the typelib. for iname in self._obj_._com_interfaces_: try: type_info, type_comp = typecomp.BindType(iname) if type_info is not None: return [type_info] except pythoncom.com_error: pass return [] def _GetTypeInfoCount_(self): if self._typeinfos_ is None: self._typeinfos_ = self._build_typeinfos_() return len(self._typeinfos_) def _GetTypeInfo_(self, index, lcid): if self._typeinfos_ is None: self._typeinfos_ = self._build_typeinfos_() if index < 0 or index >= len(self._typeinfos_): raise COMException(scode=winerror.DISP_E_BADINDEX) return 0, self._typeinfos_[index] def _allocnextdispid(self, last_dispid): while 1: last_dispid = last_dispid + 1 if last_dispid not in self._dispid_to_func_ and \ last_dispid not in self._dispid_to_get_ and \ last_dispid not in self._dispid_to_put_: return last_dispid def _invokeex_(self, dispid, lcid, wFlags, args, kwArgs, serviceProvider): ### note: lcid is being ignored... if wFlags & DISPATCH_METHOD: try: funcname = self._dispid_to_func_[dispid] except KeyError: if not wFlags & DISPATCH_PROPERTYGET: raise COMException( scode=winerror.DISP_E_MEMBERNOTFOUND) # not found else: try: func = getattr(self._obj_, funcname) except AttributeError: # May have a dispid, but that doesnt mean we have the function! raise COMException(scode=winerror.DISP_E_MEMBERNOTFOUND) # Should check callable here try: return func(*args) except TypeError, v: # Particularly nasty is "wrong number of args" type error # This helps you see what 'func' and 'args' actually is if str(v).find("arguments") >= 0: print "** TypeError %s calling function %r(%r)" % ( v, func, args) raise if wFlags & DISPATCH_PROPERTYGET: try: name = self._dispid_to_get_[dispid] except KeyError: raise COMException( scode=winerror.DISP_E_MEMBERNOTFOUND) # not found retob = getattr(self._obj_, name) if type(retob ) == types.MethodType: # a method as a property - call it. retob = retob(*args) return retob if wFlags & (DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF): ### correct? try: name = self._dispid_to_put_[dispid] except KeyError: raise COMException( scode=winerror.DISP_E_MEMBERNOTFOUND) # read-only # If we have a method of that name (ie, a property get function), and # we have an equiv. property set function, use that instead. if type(getattr(self._obj_, name, None)) == types.MethodType and \ type(getattr(self._obj_, "Set" + name, None)) == types.MethodType: fn = getattr(self._obj_, "Set" + name) fn(*args) else: # just set the attribute setattr(self._obj_, name, args[0]) return raise COMException(scode=winerror.E_INVALIDARG, desc="invalid wFlags")
def _GetTypeInfo_(self, index, lcid): if self._typeinfos_ is None: self._typeinfos_ = self._build_typeinfos_() if index < 0 or index >= len(self._typeinfos_): raise COMException(scode=winerror.DISP_E_BADINDEX) return 0, self._typeinfos_[index]
def _deletememberbyname_(self, name, fdex): raise COMException(scode=winerror.E_NOTIMPL)
def _getnamespaceparent_(self): raise COMException(scode=winerror.E_NOTIMPL)
def _deletememberbydispid_(self, id): raise COMException(scode=winerror.E_NOTIMPL)
def _getmembername_(self, dispid): raise COMException(scode=winerror.E_NOTIMPL)
def _getmemberproperties_(self, id, fdex): raise COMException(scode=winerror.E_NOTIMPL)