PyXR

c:\python24\lib\site-packages\win32 \ com \ client \ build.py



0001 """Contains knowledge to build a COM object definition.
0002 
0003 This module is used by both the @dynamic@ and @makepy@ modules to build
0004 all knowledge of a COM object.
0005 
0006 This module contains classes which contain the actual knowledge of the object.
0007 This include parameter and return type information, the COM dispid and CLSID, etc.
0008 
0009 Other modules may use this information to generate .py files, use the information
0010 dynamically, or possibly even generate .html documentation for objects.
0011 """
0012 
0013 #
0014 # NOTES: DispatchItem and MapEntry used by dynamic.py.
0015 #        the rest is used by makepy.py
0016 #
0017 #        OleItem, DispatchItem, MapEntry, BuildCallList() is used by makepy
0018 
0019 import sys
0020 import string
0021 import types
0022 from keyword import iskeyword
0023 from win32com.client import NeedUnicodeConversions
0024 
0025 import pythoncom
0026 from pywintypes import UnicodeType, TimeType
0027 
0028 # A string ending with a quote can not be safely triple-quoted.
0029 def _safeQuotedString(s):
0030         if s[-1]=='"': s = s[:-1]+'\\"'
0031         return '"""%s"""' % s
0032 
0033 error = "PythonCOM.Client.Build error"
0034 class NotSupportedException(Exception): pass # Raised when we cant support a param type.
0035 DropIndirection="DropIndirection"
0036 
0037 NoTranslateTypes = [
0038         pythoncom.VT_BOOL,          pythoncom.VT_CLSID,        pythoncom.VT_CY,
0039         pythoncom.VT_DATE,          pythoncom.VT_DECIMAL,       pythoncom.VT_EMPTY,
0040         pythoncom.VT_ERROR,         pythoncom.VT_FILETIME,     pythoncom.VT_HRESULT,
0041         pythoncom.VT_I1,            pythoncom.VT_I2,           pythoncom.VT_I4,
0042         pythoncom.VT_I8,            pythoncom.VT_INT,          pythoncom.VT_NULL,
0043         pythoncom.VT_R4,            pythoncom.VT_R8,           pythoncom.VT_NULL,
0044         pythoncom.VT_STREAM,
0045         pythoncom.VT_UI1,            pythoncom.VT_UI2,           pythoncom.VT_UI4,
0046         pythoncom.VT_UI8,            pythoncom.VT_UINT,          pythoncom.VT_VOID,
0047 ]
0048 
0049 NoTranslateMap = {}
0050 for v in NoTranslateTypes:
0051         NoTranslateMap[v] = None
0052 
0053 class MapEntry:
0054         "Simple holder for named attibutes - items in a map."
0055         def __init__(self, desc_or_id, names=None, doc=None, resultCLSID=pythoncom.IID_NULL, resultDoc = None, hidden=0):
0056                 if type(desc_or_id)==type(0):
0057                         self.dispid = desc_or_id
0058                         self.desc = None
0059                 else:
0060                         self.dispid = desc_or_id[0]
0061                         self.desc = desc_or_id
0062 
0063                 self.names = names
0064                 self.doc = doc
0065                 self.resultCLSID = resultCLSID
0066                 self.resultDocumentation = resultDoc
0067                 self.wasProperty = 0 # Have I been transformed into a function so I can pass args?
0068                 self.hidden = hidden
0069         def GetResultCLSID(self):
0070                 rc = self.resultCLSID
0071                 if rc == pythoncom.IID_NULL: return None
0072                 return rc
0073         # Return a string, suitable for output - either "'{...}'" or "None"
0074         def GetResultCLSIDStr(self):
0075                 rc = self.GetResultCLSID()
0076                 if rc is None: return "None"
0077                 return repr(str(rc)) # Convert the IID object to a string, then to a string in a string.
0078 
0079         def GetResultName(self):
0080                 if self.resultDocumentation is None:
0081                         return None
0082                 return self.resultDocumentation[0]
0083 
0084 class OleItem:
0085   typename = "OleItem"
0086 
0087   def __init__(self, doc=None):
0088     self.doc = doc
0089     if self.doc:
0090         self.python_name = MakePublicAttributeName(self.doc[0])
0091     else:
0092         self.python_name = None
0093     self.bWritten = 0
0094     self.bIsDispatch = 0
0095     self.bIsSink = 0
0096     self.clsid = None
0097     self.co_class = None
0098 
0099 class DispatchItem(OleItem):
0100         typename = "DispatchItem"
0101 
0102         def __init__(self, typeinfo=None, attr=None, doc=None, bForUser=1):
0103                 OleItem.__init__(self,doc)
0104                 self.propMap = {}
0105                 self.propMapGet = {}
0106                 self.propMapPut = {}
0107                 self.mapFuncs = {}
0108                 self.defaultDispatchName = None
0109                 self.hidden = 0
0110 
0111                 if typeinfo:
0112                         self.Build(typeinfo, attr, bForUser)
0113 
0114         def _propMapPutCheck_(self,key,item):
0115                 ins, outs, opts = self.CountInOutOptArgs(item.desc[2])
0116                 if ins>1: # if a Put property takes more than 1 arg:
0117                         if opts+1==ins or ins==item.desc[6]+1:
0118                                 newKey = "Set" + key
0119                                 deleteExisting = 0 # This one is still OK
0120                         else:
0121                                 deleteExisting = 1 # No good to us
0122                                 if self.mapFuncs.has_key(key) or self.propMapGet.has_key(key):
0123                                         newKey = "Set" + key
0124                                 else:
0125                                         newKey = key
0126                         item.wasProperty = 1
0127                         self.mapFuncs[newKey] = item
0128                         if deleteExisting:
0129                                 del self.propMapPut[key]
0130 
0131         def _propMapGetCheck_(self,key,item):
0132                 ins, outs, opts = self.CountInOutOptArgs(item.desc[2])
0133                 if ins > 0: # if a Get property takes _any_ in args:
0134                         if item.desc[6]==ins or ins==opts:
0135                                 newKey = "Get" + key
0136                                 deleteExisting = 0 # This one is still OK
0137                         else:
0138                                 deleteExisting = 1 # No good to us
0139                                 if self.mapFuncs.has_key(key):
0140                                         newKey = "Get" + key
0141                                 else:
0142                                         newKey = key
0143                         item.wasProperty = 1
0144                         self.mapFuncs[newKey] = item
0145                         if deleteExisting:
0146                                 del self.propMapGet[key]
0147 
0148         def        _AddFunc_(self,typeinfo,fdesc,bForUser):
0149                 id = fdesc.memid
0150                 funcflags = fdesc.wFuncFlags
0151                 try:
0152                         names = typeinfo.GetNames(id)
0153                         name=names[0]
0154                 except pythoncom.ole_error:
0155                         name = ""
0156                         names = None
0157 
0158                 doc = None
0159                 try:
0160                         if bForUser:
0161                                 doc = typeinfo.GetDocumentation(id)
0162                 except pythoncom.ole_error:
0163                         pass
0164 
0165                 if id==0 and name:
0166                         self.defaultDispatchName = name
0167 
0168                 invkind = fdesc.invkind
0169 
0170                 # We need to translate any Alias', Enums, structs etc in result and args
0171                 typerepr, flag, defval = fdesc.rettype
0172 #         sys.stderr.write("%s result - %s -> " % (name, typerepr))
0173                 typerepr, resultCLSID, resultDoc = _ResolveType(typerepr, typeinfo)
0174 #         sys.stderr.write("%s\n" % (typerepr,))
0175                 fdesc.rettype = typerepr, flag, defval, resultCLSID
0176                 # Translate any Alias or Enums in argument list.
0177                 argList = []
0178                 for argDesc in fdesc.args:
0179                         typerepr, flag, defval = argDesc
0180 #                 sys.stderr.write("%s arg - %s -> " % (name, typerepr))
0181                         arg_type, arg_clsid, arg_doc = _ResolveType(typerepr, typeinfo)
0182                         argDesc = arg_type, flag, defval, arg_clsid
0183 #                 sys.stderr.write("%s\n" % (argDesc[0],))
0184                         argList.append(argDesc)
0185                 fdesc.args = tuple(argList)
0186 
0187                 hidden = (funcflags & pythoncom.FUNCFLAG_FHIDDEN) != 0
0188                 if invkind == pythoncom.INVOKE_PROPERTYGET:
0189                         map = self.propMapGet
0190                 # This is not the best solution, but I dont think there is
0191                 # one without specific "set" syntax.
0192                 # If there is a single PUT or PUTREF, it will function as a property.
0193                 # If there are both, then the PUT remains a property, and the PUTREF
0194                 # gets transformed into a function.
0195                 # (in vb, PUT=="obj=other_obj", PUTREF="set obj=other_obj
0196                 elif invkind in (pythoncom.INVOKE_PROPERTYPUT, pythoncom.INVOKE_PROPERTYPUTREF):
0197                         # Special case
0198                         existing = self.propMapPut.get(name, None)
0199                         if existing is not None:
0200                                 if existing.desc[4]==pythoncom.INVOKE_PROPERTYPUT: # Keep this one
0201                                         map = self.mapFuncs
0202                                         name = "Set"+name
0203                                 else: # Existing becomes a func.
0204                                         existing.wasProperty = 1
0205                                         self.mapFuncs["Set"+name]=existing
0206                                         map = self.propMapPut # existing gets overwritten below.
0207                         else:
0208                                 map = self.propMapPut # first time weve seen it.
0209 
0210                 elif invkind == pythoncom.INVOKE_FUNC:
0211                         map = self.mapFuncs
0212                 else:
0213                         map = None
0214                 if not map is None: 
0215 #                         if map.has_key(name):
0216 #                                 sys.stderr.write("Warning - overwriting existing method/attribute %s\n" % name)
0217                         map[name] = MapEntry(tuple(fdesc), names, doc, resultCLSID, resultDoc, hidden)
0218                         # any methods that can't be reached via DISPATCH we return None
0219                         # for, so dynamic dispatch doesnt see it.
0220                         if fdesc.funckind != pythoncom.FUNC_DISPATCH:
0221                                 return None
0222                         return (name,map)
0223                 return None
0224 
0225         def _AddVar_(self,typeinfo,fdesc,bForUser):
0226                 ### need pythoncom.VARFLAG_FRESTRICTED ...
0227                 ### then check it
0228 
0229                 if fdesc.varkind == pythoncom.VAR_DISPATCH:
0230                         id = fdesc.memid
0231                         names = typeinfo.GetNames(id)
0232                         # Translate any Alias or Enums in result.
0233                         typerepr, flags, defval = fdesc.elemdescVar
0234                         typerepr, resultCLSID, resultDoc = _ResolveType(typerepr, typeinfo)
0235                         fdesc.elemdescVar = typerepr, flags, defval
0236                         doc = None
0237                         try:
0238                                 if bForUser: doc = typeinfo.GetDocumentation(id)
0239                         except pythoncom.ole_error:
0240                                 pass
0241 
0242                         # handle the enumerator specially
0243                         map = self.propMap
0244                         # Check if the element is hidden.
0245                         hidden = 0
0246                         if hasattr(fdesc,"wVarFlags"):
0247                                 hidden = (fdesc.wVarFlags & 0x40) != 0 # VARFLAG_FHIDDEN
0248                         map[names[0]] = MapEntry(tuple(fdesc), names, doc, resultCLSID, resultDoc, hidden)
0249                         return (names[0],map)
0250                 else:
0251                         return None
0252 
0253         def Build(self, typeinfo, attr, bForUser = 1):
0254                 self.clsid = attr[0]
0255                 self.bIsDispatch = (attr.wTypeFlags & pythoncom.TYPEFLAG_FDISPATCHABLE) != 0
0256                 if typeinfo is None: return
0257                 # Loop over all methods
0258                 for j in xrange(attr[6]):
0259                         fdesc = typeinfo.GetFuncDesc(j)
0260                         self._AddFunc_(typeinfo,fdesc,bForUser)
0261 
0262                 # Loop over all variables (ie, properties)
0263                 for j in xrange(attr[7]):
0264                         fdesc = typeinfo.GetVarDesc(j)
0265                         self._AddVar_(typeinfo,fdesc,bForUser)
0266                 
0267                 # Now post-process the maps.  For any "Get" or "Set" properties
0268                 # that have arguments, we must turn them into methods.  If a method
0269                 # of the same name already exists, change the name.
0270                 for key, item in self.propMapGet.items():
0271                         self._propMapGetCheck_(key,item)
0272                                         
0273                 for key, item in self.propMapPut.items():
0274                         self._propMapPutCheck_(key,item)
0275 
0276         def CountInOutOptArgs(self, argTuple):
0277                 "Return tuple counting in/outs/OPTS.  Sum of result may not be len(argTuple), as some args may be in/out."
0278                 ins = out = opts = 0
0279                 for argCheck in argTuple:
0280                         inOut = argCheck[1]
0281                         if inOut==0:
0282                                 ins = ins + 1
0283                                 out = out + 1
0284                         else:
0285                                 if inOut & pythoncom.PARAMFLAG_FIN:
0286                                         ins = ins + 1
0287                                 if inOut & pythoncom.PARAMFLAG_FOPT:
0288                                         opts = opts + 1
0289                                 if inOut & pythoncom.PARAMFLAG_FOUT:
0290                                         out = out + 1
0291                 return ins, out, opts
0292 
0293         def MakeFuncMethod(self, entry, name, bMakeClass = 1):
0294                 # If we have a type description, and not varargs...
0295                 if entry.desc is not None and (len(entry.desc) < 6 or entry.desc[6]!=-1):
0296                         return self.MakeDispatchFuncMethod(entry, name, bMakeClass)
0297                 else:
0298                         return self.MakeVarArgsFuncMethod(entry, name, bMakeClass)
0299 
0300         def MakeDispatchFuncMethod(self, entry, name, bMakeClass = 1):
0301                 fdesc = entry.desc
0302                 doc = entry.doc
0303                 names = entry.names
0304                 ret = []
0305                 if bMakeClass:
0306                         linePrefix = "\t"
0307                         defNamedOptArg = "defaultNamedOptArg"
0308                         defNamedNotOptArg = "defaultNamedNotOptArg"
0309                         defUnnamedArg = "defaultUnnamedArg"
0310                 else:
0311                         linePrefix = ""
0312                         defNamedOptArg = "pythoncom.Missing"
0313                         defNamedNotOptArg = "pythoncom.Missing"
0314                         defUnnamedArg = "pythoncom.Missing"
0315                 defOutArg = "pythoncom.Missing"
0316                 id = fdesc[0]
0317                 s = linePrefix + 'def ' + name + '(self' + BuildCallList(fdesc, names, defNamedOptArg, defNamedNotOptArg, defUnnamedArg, defOutArg) + '):'
0318                 ret.append(s)
0319                 if doc and doc[1]:
0320                         ret.append(linePrefix + '\t' + _safeQuotedString(doc[1]))
0321 
0322 #         print "fdesc is ", fdesc
0323 
0324                 resclsid = entry.GetResultCLSID()
0325                 if resclsid:
0326                         resclsid = "'%s'" % resclsid
0327                 else:
0328                         resclsid = 'None'
0329                 # Strip the default values from the arg desc
0330                 retDesc = fdesc[8][:2]
0331                 argsDesc = tuple(map(lambda what: what[:2], fdesc[2]))
0332                 # The runtime translation of the return types is expensive, so when we know the
0333                 # return type of the function, there is no need to check the type at runtime.
0334                 # To qualify, this function must return a "simple" type, and have no byref args.
0335                 # Check if we have byrefs or anything in the args which mean we still need a translate.
0336                 param_flags = map(lambda what: what[1], fdesc[2])
0337                 bad_params = filter(lambda flag: flag & (pythoncom.PARAMFLAG_FOUT | pythoncom.PARAMFLAG_FRETVAL)!=0, param_flags)
0338                 s = None
0339                 if len(bad_params)==0 and len(retDesc)==2 and retDesc[1]==0:
0340                         rd = retDesc[0]
0341                         if NoTranslateMap.has_key(rd):
0342                                 s = '%s\treturn self._oleobj_.InvokeTypes(%d, LCID, %s, %s, %s%s)' % (linePrefix, id, fdesc[4], retDesc, argsDesc, _BuildArgList(fdesc, names))
0343                         elif rd in [pythoncom.VT_DISPATCH, pythoncom.VT_UNKNOWN]:
0344                                 s = '%s\tret = self._oleobj_.InvokeTypes(%d, LCID, %s, %s, %s%s)\n' % (linePrefix, id, fdesc[4], retDesc, `argsDesc`, _BuildArgList(fdesc, names))
0345                                 s = s + '%s\tif ret is not None:\n' % (linePrefix,)
0346                                 if rd == pythoncom.VT_UNKNOWN:
0347                                         s = s + "%s\t\t# See if this IUnknown is really an IDispatch\n" % (linePrefix,)
0348                                         s = s + "%s\t\ttry:\n" % (linePrefix,)
0349                                         s = s + "%s\t\t\tret = ret.QueryInterface(pythoncom.IID_IDispatch)\n" % (linePrefix,)
0350                                         s = s + "%s\t\texcept pythoncom.error:\n" % (linePrefix,)
0351                                         s = s + "%s\t\t\treturn ret\n" % (linePrefix,)
0352                                 s = s + '%s\t\tret = Dispatch(ret, %s, %s, UnicodeToString=%d)\n' % (linePrefix,`name`, resclsid, NeedUnicodeConversions) 
0353                                 s = s + '%s\treturn ret' % (linePrefix)
0354                         elif rd == pythoncom.VT_BSTR:
0355                                 if NeedUnicodeConversions:
0356                                         s = "%s\t# Result is a Unicode object - perform automatic string conversion\n" % (linePrefix,)
0357                                         s = s + '%s\treturn str(self._oleobj_.InvokeTypes(%d, LCID, %s, %s, %s%s))' % (linePrefix, id, fdesc[4], retDesc, `argsDesc`, _BuildArgList(fdesc, names))
0358                                 else:
0359                                         s = "%s\t# Result is a Unicode object - return as-is for this version of Python\n" % (linePrefix,)
0360                                         s = s + '%s\treturn self._oleobj_.InvokeTypes(%d, LCID, %s, %s, %s%s)' % (linePrefix, id, fdesc[4], retDesc, `argsDesc`, _BuildArgList(fdesc, names))
0361                         # else s remains None
0362                 if s is None:
0363                         s = '%s\treturn self._ApplyTypes_(%d, %s, %s, %s, %s, %s%s)' % (linePrefix, id, fdesc[4], retDesc, argsDesc, `name`, resclsid, _BuildArgList(fdesc, names))
0364 
0365                 ret.append(s)
0366                 ret.append("")
0367                 return ret
0368 
0369         def MakeVarArgsFuncMethod(self, entry, name, bMakeClass = 1):
0370                 fdesc = entry.desc
0371                 names = entry.names
0372                 doc = entry.doc
0373                 ret = []
0374                 argPrefix = "self"
0375                 if bMakeClass:
0376                         linePrefix = "\t"
0377                 else:
0378                         linePrefix = ""
0379                 ret.append(linePrefix + 'def ' + name + '(' + argPrefix + ', *args):')
0380                 if doc and doc[1]: ret.append(linePrefix + '\t' + _safeQuotedString(doc[1]))
0381                 if fdesc:
0382                         invoketype = fdesc[4]
0383                 else:
0384                         invoketype = pythoncom.DISPATCH_METHOD
0385                 s = linePrefix + '\treturn self._get_good_object_(self._oleobj_.Invoke(*(('
0386                 ret.append(s + str(entry.dispid) + ",0,%d,1)+args)),'%s')" % (invoketype, names[0]))
0387                 ret.append("")
0388                 return ret
0389 
0390 # Note - "DispatchItem" poorly named - need a new intermediate class.
0391 class VTableItem(DispatchItem):
0392         def Build(self, typeinfo, attr, bForUser = 1):
0393                 DispatchItem.Build(self, typeinfo, attr, bForUser)
0394                 assert typeinfo is not None, "Cant build vtables without type info!"
0395 
0396                 def cmp_vtable_off(m1, m2):
0397                         return cmp(m1.desc[7], m2.desc[7])
0398 
0399                 meth_list = self.mapFuncs.values() + self.propMapGet.values() + self.propMapPut.values()
0400 
0401                 meth_list.sort( cmp_vtable_off )
0402                 # Now turn this list into the run-time representation
0403                 # (ready for immediate use or writing to gencache)
0404                 self.vtableFuncs = []
0405                 for entry in meth_list:
0406                         self.vtableFuncs.append( (entry.names, entry.dispid, entry.desc) )
0407 
0408 # A Lazy dispatch item - builds an item on request using info from
0409 # an ITypeComp.  The dynamic module makes the called to build each item,
0410 # and also holds the references to the typeinfo and typecomp.
0411 class LazyDispatchItem(DispatchItem):
0412         typename = "LazyDispatchItem"
0413         def __init__(self, attr, doc):
0414                 self.clsid = attr[0]
0415                 DispatchItem.__init__(self, None, attr, doc, 0)
0416 
0417 typeSubstMap = {
0418         pythoncom.VT_INT: pythoncom.VT_I4,
0419         pythoncom.VT_UINT: pythoncom.VT_I4,
0420         pythoncom.VT_HRESULT: pythoncom.VT_I4,
0421 }
0422 
0423 def _ResolveType(typerepr, itypeinfo):
0424         # Resolve VT_USERDEFINED (often aliases or typed IDispatches)
0425 
0426         if type(typerepr)==types.TupleType:
0427                 indir_vt, subrepr = typerepr
0428                 if indir_vt == pythoncom.VT_PTR:
0429                         # If it is a VT_PTR to a VT_USERDEFINED that is an IDispatch/IUnknown,
0430                         # then it resolves to simply the object.
0431                         # Otherwise, it becomes a ByRef of the resolved type
0432                         # We need to drop an indirection level on pointer to user defined interfaces.
0433                         # eg, (VT_PTR, (VT_USERDEFINED, somehandle)) needs to become VT_DISPATCH
0434                         # only when "somehandle" is an object.
0435                         # but (VT_PTR, (VT_USERDEFINED, otherhandle)) doesnt get the indirection dropped.
0436                         was_user = type(subrepr)==types.TupleType and subrepr[0]==pythoncom.VT_USERDEFINED
0437                         subrepr, sub_clsid, sub_doc = _ResolveType(subrepr, itypeinfo)
0438                         if was_user and subrepr in [pythoncom.VT_DISPATCH, pythoncom.VT_UNKNOWN, pythoncom.VT_RECORD]:
0439                                 # Drop the VT_PTR indirection
0440                                 return subrepr, sub_clsid, sub_doc
0441                         # Change PTR indirection to byref
0442                         return subrepr | pythoncom.VT_BYREF, sub_clsid, sub_doc
0443                 if indir_vt == pythoncom.VT_SAFEARRAY:
0444                         # resolve the array element, and convert to VT_ARRAY
0445                         subrepr, sub_clsid, sub_doc = _ResolveType(subrepr, itypeinfo)
0446                         return pythoncom.VT_ARRAY | subrepr, sub_clsid, sub_doc
0447                 if indir_vt == pythoncom.VT_CARRAY: # runtime has no support for this yet.
0448                         # resolve the array element, and convert to VT_CARRAY
0449                         # sheesh - return _something_
0450                         return pythoncom.VT_CARRAY, None, None
0451                 if indir_vt == pythoncom.VT_USERDEFINED:
0452                         resultTypeInfo = itypeinfo.GetRefTypeInfo(subrepr)
0453                         resultAttr = resultTypeInfo.GetTypeAttr()
0454                         typeKind = resultAttr.typekind
0455                         if typeKind == pythoncom.TKIND_ALIAS:
0456                                 tdesc = resultAttr.tdescAlias
0457                                 return _ResolveType(tdesc, resultTypeInfo)
0458                         elif typeKind in [pythoncom.TKIND_ENUM, pythoncom.TKIND_MODULE]:
0459                                 # For now, assume Long
0460                                 return pythoncom.VT_I4, None, None
0461 
0462                         elif typeKind == pythoncom.TKIND_DISPATCH:
0463                                 clsid = resultTypeInfo.GetTypeAttr()[0]
0464                                 retdoc = resultTypeInfo.GetDocumentation(-1)
0465                                 return pythoncom.VT_DISPATCH, clsid, retdoc
0466 
0467                         elif typeKind in [pythoncom.TKIND_INTERFACE,
0468                                                           pythoncom.TKIND_COCLASS]:
0469                                 # XXX - should probably get default interface for CO_CLASS???
0470                                 clsid = resultTypeInfo.GetTypeAttr()[0]
0471                                 retdoc = resultTypeInfo.GetDocumentation(-1)
0472                                 return pythoncom.VT_UNKNOWN, clsid, retdoc
0473 
0474                         elif typeKind == pythoncom.TKIND_RECORD:
0475                                 return pythoncom.VT_RECORD, None, None
0476                         raise NotSupportedException("Can not resolve alias or user-defined type")
0477         return typeSubstMap.get(typerepr,typerepr), None, None
0478 
0479 def _BuildArgList(fdesc, names):
0480     "Builds list of args to the underlying Invoke method."
0481     # Word has TypeInfo for Insert() method, but says "no args"
0482     numArgs = max(fdesc[6], len(fdesc[2]))
0483     names = list(names)
0484     while None in names:
0485         i = names.index(None)
0486         names[i] = "arg%d" % (i,)
0487     names = map(MakePublicAttributeName, names[1:])
0488     while len(names) < numArgs:
0489         names.append("arg%d" % (len(names),))
0490     return "," + string.join(names, ", ")
0491 
0492 valid_identifier_chars = string.letters + string.digits + "_"
0493 
0494 def demunge_leading_underscores(className):
0495         i = 0
0496         while className[i] == "_":
0497                 i += 1
0498         assert i >= 2, "Should only be here with names starting with '__'"
0499         return className[i-1:] + className[:i-1]
0500 
0501 # Given a "public name" (eg, the name of a class, function, etc)
0502 # make sure it is a legal (and reasonable!) Python name.
0503 def MakePublicAttributeName(className, is_global = False):
0504         # Given a class attribute that needs to be public, convert it to a
0505         # reasonable name.
0506         # Also need to be careful that the munging doesnt
0507         # create duplicates - eg, just removing a leading "_" is likely to cause
0508         # a clash.
0509         # if is_global is True, then the name is a global variable that may
0510         # overwrite a builtin - eg, "None"
0511         if className[:2]=='__':
0512                 return demunge_leading_underscores(className)
0513         elif iskeyword(className): # all keywords are lower case
0514                 return string.capitalize(className)
0515         elif is_global and __builtins__.has_key(className):
0516                 # builtins may be mixed case.  If capitalizing it doesn't change it,
0517                 # force to all uppercase (eg, "None", "True" become "NONE", "TRUE"
0518                 ret = className.capitalize()
0519                 if ret==className: # didn't change - force all uppercase.
0520                         ret = ret.upper()
0521                 return ret
0522         # Strip non printable chars
0523         return filter( lambda char: char in valid_identifier_chars, className)
0524 
0525 # Given a default value passed by a type library, return a string with
0526 # an appropriate repr() for the type.
0527 # Takes a raw ELEMDESC and returns a repr string, or None
0528 # (NOTE: The string itself may be '"None"', which is valid, and different to None.
0529 # XXX - To do: Dates are probably screwed, but can they come in?
0530 def MakeDefaultArgRepr(defArgVal):
0531   try:
0532     inOut = defArgVal[1]
0533   except IndexError:
0534     # something strange - assume is in param.
0535     inOut = pythoncom.PARAMFLAG_FIN
0536 
0537   if inOut & pythoncom.PARAMFLAG_FHASDEFAULT:
0538     # hack for Unicode until it repr's better.
0539     val = defArgVal[2]
0540     if type(val) is UnicodeType:
0541       return repr(str(val))
0542     elif type(val) is TimeType:
0543       year=val.year; month=val.month; day=val.day; hour=val.hour; minute=val.minute; second=val.second; msec=val.msec
0544       return "pythoncom.MakeTime((%(year)d, %(month)d, %(day)d, %(hour)d, %(minute)d, %(second)d,0,0,0,%(msec)d))" % locals()
0545     else:
0546       return repr(val)
0547   return None
0548 
0549 def BuildCallList(fdesc, names, defNamedOptArg, defNamedNotOptArg, defUnnamedArg, defOutArg):
0550   "Builds a Python declaration for a method."
0551   # Names[0] is the func name - param names are from 1.
0552   numArgs = len(fdesc[2])
0553   numOptArgs = fdesc[6]
0554   strval = ''
0555   if numOptArgs==-1:        # Special value that says "var args after here"
0556     firstOptArg = numArgs
0557     numArgs = numArgs - 1
0558   else:
0559     firstOptArg = numArgs - numOptArgs
0560   for arg in xrange(numArgs):
0561     try:
0562       argName = names[arg+1] 
0563       namedArg = argName is not None
0564     except IndexError:
0565       namedArg = 0
0566     if not namedArg: argName = "arg%d" % (arg)
0567     thisdesc = fdesc[2][arg]
0568     # See if the IDL specified a default value
0569     defArgVal = MakeDefaultArgRepr(thisdesc)
0570     if defArgVal is None:
0571       # Out params always get their special default
0572       if thisdesc[1] & (pythoncom.PARAMFLAG_FOUT | pythoncom.PARAMFLAG_FIN) == pythoncom.PARAMFLAG_FOUT:
0573         defArgVal = defOutArg
0574       else:          
0575         # Unnamed arg - always allow default values.
0576         if namedArg:
0577           # Is a named argument
0578           if arg >= firstOptArg:
0579             defArgVal = defNamedOptArg
0580           else:
0581             defArgVal = defNamedNotOptArg
0582         else:
0583           defArgVal = defUnnamedArg
0584 
0585     argName = MakePublicAttributeName(argName)
0586     strval = strval + ", " + argName
0587     if defArgVal:
0588       strval = strval + "=" + defArgVal
0589   if numOptArgs==-1:
0590     strval = strval + ", *" + names[-1]
0591 
0592   return strval
0593 
0594 
0595 if __name__=='__main__':
0596   print "Use 'makepy.py' to generate Python code - this module is just a helper"
0597 

Generated by PyXR 0.9.4
SourceForge.net Logo