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