PageRenderTime 62ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/External.LCA_RESTRICTED/Languages/IronPython/27/Lib/site-packages/win32com/client/genpy.py

http://github.com/IronLanguages/main
Python | 1056 lines | 870 code | 76 blank | 110 comment | 208 complexity | e2861815f8e910a3d9e98c410986c22b MD5 | raw file
Possible License(s): CPL-1.0, BSD-3-Clause, ISC, GPL-2.0, MPL-2.0-no-copyleft-exception
  1. """genpy.py - The worker for makepy. See makepy.py for more details
  2. This code was moved simply to speed Python in normal circumstances. As the makepy.py
  3. is normally run from the command line, it reparses the code each time. Now makepy
  4. is nothing more than the command line handler and public interface.
  5. The makepy command line etc handling is also getting large enough in its own right!
  6. """
  7. # NOTE - now supports a "demand" mechanism - the top-level is a package, and
  8. # each class etc can be made individually.
  9. # This should eventually become the default.
  10. # Then the old non-package technique should be removed.
  11. # There should be no b/w compat issues, and will just help clean the code.
  12. # This will be done once the new "demand" mechanism gets a good workout.
  13. import os
  14. import sys
  15. import time
  16. import win32com
  17. import pythoncom
  18. import build
  19. error = "makepy.error"
  20. makepy_version = "0.5.00" # Written to generated file.
  21. GEN_FULL="full"
  22. GEN_DEMAND_BASE = "demand(base)"
  23. GEN_DEMAND_CHILD = "demand(child)"
  24. # This map is used purely for the users benefit -it shows the
  25. # raw, underlying type of Alias/Enums, etc. The COM implementation
  26. # does not use this map at runtime - all Alias/Enum have already
  27. # been translated.
  28. mapVTToTypeString = {
  29. pythoncom.VT_I2: 'types.IntType',
  30. pythoncom.VT_I4: 'types.IntType',
  31. pythoncom.VT_R4: 'types.FloatType',
  32. pythoncom.VT_R8: 'types.FloatType',
  33. pythoncom.VT_BSTR: 'types.StringType',
  34. pythoncom.VT_BOOL: 'types.IntType',
  35. pythoncom.VT_VARIANT: 'types.TypeType',
  36. pythoncom.VT_I1: 'types.IntType',
  37. pythoncom.VT_UI1: 'types.IntType',
  38. pythoncom.VT_UI2: 'types.IntType',
  39. pythoncom.VT_UI4: 'types.IntType',
  40. pythoncom.VT_I8: 'types.LongType',
  41. pythoncom.VT_UI8: 'types.LongType',
  42. pythoncom.VT_INT: 'types.IntType',
  43. pythoncom.VT_DATE: 'pythoncom.PyTimeType',
  44. pythoncom.VT_UINT: 'types.IntType',
  45. }
  46. # Given a propget function's arg desc, return the default parameters for all
  47. # params bar the first. Eg, then Python does a:
  48. # object.Property = "foo"
  49. # Python can only pass the "foo" value. If the property has
  50. # multiple args, and the rest have default values, this allows
  51. # Python to correctly pass those defaults.
  52. def MakeDefaultArgsForPropertyPut(argsDesc):
  53. ret = []
  54. for desc in argsDesc[1:]:
  55. default = build.MakeDefaultArgRepr(desc)
  56. if default is None:
  57. break
  58. ret.append(default)
  59. return tuple(ret)
  60. def MakeMapLineEntry(dispid, wFlags, retType, argTypes, user, resultCLSID):
  61. # Strip the default value
  62. argTypes = tuple([what[:2] for what in argTypes])
  63. return '(%s, %d, %s, %s, "%s", %s)' % \
  64. (dispid, wFlags, retType[:2], argTypes, user, resultCLSID)
  65. def MakeEventMethodName(eventName):
  66. if eventName[:2]=="On":
  67. return eventName
  68. else:
  69. return "On"+eventName
  70. def WriteSinkEventMap(obj, stream):
  71. print >> stream, '\t_dispid_to_func_ = {'
  72. for name, entry in obj.propMapGet.items() + obj.propMapPut.items() + obj.mapFuncs.items():
  73. fdesc = entry.desc
  74. print >> stream, '\t\t%9d : "%s",' % (entry.desc[0], MakeEventMethodName(entry.names[0]))
  75. print >> stream, '\t\t}'
  76. # MI is used to join my writable helpers, and the OLE
  77. # classes.
  78. class WritableItem:
  79. # __cmp__ used for sorting in py2x...
  80. def __cmp__(self, other):
  81. "Compare for sorting"
  82. ret = cmp(self.order, other.order)
  83. if ret==0 and self.doc: ret = cmp(self.doc[0], other.doc[0])
  84. return ret
  85. # ... but not used in py3k - __lt__ minimum needed there
  86. def __lt__(self, other): # py3k variant
  87. if self.order == other.order:
  88. return self.doc < other.doc
  89. return self.order < other.order
  90. def __repr__(self):
  91. return "OleItem: doc=%s, order=%d" % (repr(self.doc), self.order)
  92. class RecordItem(build.OleItem, WritableItem):
  93. order = 9
  94. typename = "RECORD"
  95. def __init__(self, typeInfo, typeAttr, doc=None, bForUser=1):
  96. ## sys.stderr.write("Record %s: size %s\n" % (doc,typeAttr.cbSizeInstance))
  97. ## sys.stderr.write(" cVars = %s\n" % (typeAttr.cVars,))
  98. ## for i in range(typeAttr.cVars):
  99. ## vdesc = typeInfo.GetVarDesc(i)
  100. ## sys.stderr.write(" Var %d has value %s, type %d, desc=%s\n" % (i, vdesc.value, vdesc.varkind, vdesc.elemdescVar))
  101. ## sys.stderr.write(" Doc is %s\n" % (typeInfo.GetDocumentation(vdesc.memid),))
  102. build.OleItem.__init__(self, doc)
  103. self.clsid = typeAttr[0]
  104. def WriteClass(self, generator):
  105. pass
  106. # Given an enum, write all aliases for it.
  107. # (no longer necessary for new style code, but still used for old code.
  108. def WriteAliasesForItem(item, aliasItems, stream):
  109. for alias in aliasItems.itervalues():
  110. if item.doc and alias.aliasDoc and (alias.aliasDoc[0]==item.doc[0]):
  111. alias.WriteAliasItem(aliasItems, stream)
  112. class AliasItem(build.OleItem, WritableItem):
  113. order = 2
  114. typename = "ALIAS"
  115. def __init__(self, typeinfo, attr, doc=None, bForUser = 1):
  116. build.OleItem.__init__(self, doc)
  117. ai = attr[14]
  118. self.attr = attr
  119. if type(ai) == type(()) and \
  120. type(ai[1])==type(0): # XXX - This is a hack - why tuples? Need to resolve?
  121. href = ai[1]
  122. alinfo = typeinfo.GetRefTypeInfo(href)
  123. self.aliasDoc = alinfo.GetDocumentation(-1)
  124. self.aliasAttr = alinfo.GetTypeAttr()
  125. else:
  126. self.aliasDoc = None
  127. self.aliasAttr = None
  128. def WriteAliasItem(self, aliasDict, stream):
  129. # we could have been written as part of an alias dependency
  130. if self.bWritten:
  131. return
  132. if self.aliasDoc:
  133. depName = self.aliasDoc[0]
  134. if depName in aliasDict:
  135. aliasDict[depName].WriteAliasItem(aliasDict, stream)
  136. print >> stream, self.doc[0] + " = " + depName
  137. else:
  138. ai = self.attr[14]
  139. if type(ai) == type(0):
  140. try:
  141. typeStr = mapVTToTypeString[ai]
  142. print >> stream, "# %s=%s" % (self.doc[0], typeStr)
  143. except KeyError:
  144. print >> stream, self.doc[0] + " = None # Can't convert alias info " + str(ai)
  145. print >> stream
  146. self.bWritten = 1
  147. class EnumerationItem(build.OleItem, WritableItem):
  148. order = 1
  149. typename = "ENUMERATION"
  150. def __init__(self, typeinfo, attr, doc=None, bForUser=1):
  151. build.OleItem.__init__(self, doc)
  152. self.clsid = attr[0]
  153. self.mapVars = {}
  154. typeFlags = attr[11]
  155. self.hidden = typeFlags & pythoncom.TYPEFLAG_FHIDDEN or \
  156. typeFlags & pythoncom.TYPEFLAG_FRESTRICTED
  157. for j in range(attr[7]):
  158. vdesc = typeinfo.GetVarDesc(j)
  159. name = typeinfo.GetNames(vdesc[0])[0]
  160. self.mapVars[name] = build.MapEntry(vdesc)
  161. ## def WriteEnumerationHeaders(self, aliasItems, stream):
  162. ## enumName = self.doc[0]
  163. ## print >> stream "%s=constants # Compatibility with previous versions." % (enumName)
  164. ## WriteAliasesForItem(self, aliasItems)
  165. def WriteEnumerationItems(self, stream):
  166. enumName = self.doc[0]
  167. # Write in name alpha order
  168. names = list(self.mapVars.keys())
  169. names.sort()
  170. for name in names:
  171. entry = self.mapVars[name]
  172. vdesc = entry.desc
  173. if vdesc[4] == pythoncom.VAR_CONST:
  174. val = vdesc[1]
  175. if sys.version_info <= (2,4) and (isinstance(val, int) or isinstance(val, long)):
  176. # in python 2.3, 0x80000000L == 2147483648
  177. if val==2147483648: # == 0x80000000L - special case for 2.3...
  178. use = "0x80000000L" # 'L' for future warning
  179. elif val > 2147483648 or val < 0: # avoid a FutureWarning
  180. use = long(val)
  181. else:
  182. use = hex(val)
  183. else:
  184. use = repr(val)
  185. print >> stream, "\t%-30s=%-10s # from enum %s" % \
  186. (build.MakePublicAttributeName(name, True), use, enumName)
  187. class VTableItem(build.VTableItem, WritableItem):
  188. order = 4
  189. def WriteClass(self, generator):
  190. self.WriteVTableMap(generator)
  191. self.bWritten = 1
  192. def WriteVTableMap(self, generator):
  193. stream = generator.file
  194. print >> stream, "%s_vtables_dispatch_ = %d" % (self.python_name, self.bIsDispatch)
  195. print >> stream, "%s_vtables_ = [" % (self.python_name, )
  196. for v in self.vtableFuncs:
  197. names, dispid, desc = v
  198. arg_desc = desc[2]
  199. arg_reprs = []
  200. # more hoops so we don't generate huge lines.
  201. item_num = 0
  202. print >> stream, "\t((",
  203. for name in names:
  204. print >> stream, repr(name), ",",
  205. item_num = item_num + 1
  206. if item_num % 5 == 0:
  207. print >> stream, "\n\t\t\t",
  208. print >> stream, "), %d, (%r, %r, [" % (dispid, desc[0], desc[1]),
  209. for arg in arg_desc:
  210. item_num = item_num + 1
  211. if item_num % 5 == 0:
  212. print >> stream, "\n\t\t\t",
  213. defval = build.MakeDefaultArgRepr(arg)
  214. if arg[3] is None:
  215. arg3_repr = None
  216. else:
  217. arg3_repr = repr(arg[3])
  218. print >> stream, repr((arg[0], arg[1], defval, arg3_repr)), ",",
  219. print >> stream, "],",
  220. for d in desc[3:]:
  221. print >> stream, repr(d), ",",
  222. print >> stream, ")),"
  223. print >> stream, "]"
  224. print >> stream
  225. class DispatchItem(build.DispatchItem, WritableItem):
  226. order = 3
  227. def __init__(self, typeinfo, attr, doc=None):
  228. build.DispatchItem.__init__(self, typeinfo, attr, doc)
  229. self.type_attr = attr
  230. self.coclass_clsid = None
  231. def WriteClass(self, generator):
  232. if not self.bIsDispatch and not self.type_attr.typekind == pythoncom.TKIND_DISPATCH:
  233. return
  234. # This is pretty screwey - now we have vtable support we
  235. # should probably rethink this (ie, maybe write both sides for sinks, etc)
  236. if self.bIsSink:
  237. self.WriteEventSinkClassHeader(generator)
  238. self.WriteCallbackClassBody(generator)
  239. else:
  240. self.WriteClassHeader(generator)
  241. self.WriteClassBody(generator)
  242. print >> generator.file
  243. self.bWritten = 1
  244. def WriteClassHeader(self, generator):
  245. generator.checkWriteDispatchBaseClass()
  246. doc = self.doc
  247. stream = generator.file
  248. print >> stream, 'class ' + self.python_name + '(DispatchBaseClass):'
  249. if doc[1]: print >> stream, '\t' + build._safeQuotedString(doc[1])
  250. try:
  251. progId = pythoncom.ProgIDFromCLSID(self.clsid)
  252. print >> stream, "\t# This class is creatable by the name '%s'" % (progId)
  253. except pythoncom.com_error:
  254. pass
  255. print >> stream, "\tCLSID = " + repr(self.clsid)
  256. if self.coclass_clsid is None:
  257. print >> stream, "\tcoclass_clsid = None"
  258. else:
  259. print >> stream, "\tcoclass_clsid = " + repr(self.coclass_clsid)
  260. print >> stream
  261. self.bWritten = 1
  262. def WriteEventSinkClassHeader(self, generator):
  263. generator.checkWriteEventBaseClass()
  264. doc = self.doc
  265. stream = generator.file
  266. print >> stream, 'class ' + self.python_name + ':'
  267. if doc[1]: print >> stream, '\t' + build._safeQuotedString(doc[1])
  268. try:
  269. progId = pythoncom.ProgIDFromCLSID(self.clsid)
  270. print >> stream, "\t# This class is creatable by the name '%s'" % (progId)
  271. except pythoncom.com_error:
  272. pass
  273. print >> stream, '\tCLSID = CLSID_Sink = ' + repr(self.clsid)
  274. if self.coclass_clsid is None:
  275. print >> stream, "\tcoclass_clsid = None"
  276. else:
  277. print >> stream, "\tcoclass_clsid = " + repr(self.coclass_clsid)
  278. print >> stream, '\t_public_methods_ = [] # For COM Server support'
  279. WriteSinkEventMap(self, stream)
  280. print >> stream
  281. print >> stream, '\tdef __init__(self, oobj = None):'
  282. print >> stream, "\t\tif oobj is None:"
  283. print >> stream, "\t\t\tself._olecp = None"
  284. print >> stream, "\t\telse:"
  285. print >> stream, '\t\t\timport win32com.server.util'
  286. print >> stream, '\t\t\tfrom win32com.server.policy import EventHandlerPolicy'
  287. print >> stream, '\t\t\tcpc=oobj._oleobj_.QueryInterface(pythoncom.IID_IConnectionPointContainer)'
  288. print >> stream, '\t\t\tcp=cpc.FindConnectionPoint(self.CLSID_Sink)'
  289. print >> stream, '\t\t\tcookie=cp.Advise(win32com.server.util.wrap(self, usePolicy=EventHandlerPolicy))'
  290. print >> stream, '\t\t\tself._olecp,self._olecp_cookie = cp,cookie'
  291. print >> stream, '\tdef __del__(self):'
  292. print >> stream, '\t\ttry:'
  293. print >> stream, '\t\t\tself.close()'
  294. print >> stream, '\t\texcept pythoncom.com_error:'
  295. print >> stream, '\t\t\tpass'
  296. print >> stream, '\tdef close(self):'
  297. print >> stream, '\t\tif self._olecp is not None:'
  298. print >> stream, '\t\t\tcp,cookie,self._olecp,self._olecp_cookie = self._olecp,self._olecp_cookie,None,None'
  299. print >> stream, '\t\t\tcp.Unadvise(cookie)'
  300. print >> stream, '\tdef _query_interface_(self, iid):'
  301. print >> stream, '\t\timport win32com.server.util'
  302. print >> stream, '\t\tif iid==self.CLSID_Sink: return win32com.server.util.wrap(self)'
  303. print >> stream
  304. self.bWritten = 1
  305. def WriteCallbackClassBody(self, generator):
  306. stream = generator.file
  307. print >> stream, "\t# Event Handlers"
  308. print >> stream, "\t# If you create handlers, they should have the following prototypes:"
  309. for name, entry in self.propMapGet.items() + self.propMapPut.items() + self.mapFuncs.items():
  310. fdesc = entry.desc
  311. methName = MakeEventMethodName(entry.names[0])
  312. print >> stream, '#\tdef ' + methName + '(self' + build.BuildCallList(fdesc, entry.names, "defaultNamedOptArg", "defaultNamedNotOptArg","defaultUnnamedArg", "pythoncom.Missing", is_comment = True) + '):'
  313. if entry.doc and entry.doc[1]:
  314. print >> stream, '#\t\t' + build._safeQuotedString(entry.doc[1])
  315. print >> stream
  316. self.bWritten = 1
  317. def WriteClassBody(self, generator):
  318. stream = generator.file
  319. # Write in alpha order.
  320. names = list(self.mapFuncs.keys())
  321. names.sort()
  322. specialItems = {"count":None, "item":None,"value":None,"_newenum":None} # If found, will end up with (entry, invoke_tupe)
  323. itemCount = None
  324. for name in names:
  325. entry=self.mapFuncs[name]
  326. # skip [restricted] methods, unless it is the
  327. # enumerator (which, being part of the "system",
  328. # we know about and can use)
  329. dispid = entry.desc[0]
  330. if entry.desc[9] & pythoncom.FUNCFLAG_FRESTRICTED and \
  331. dispid != pythoncom.DISPID_NEWENUM:
  332. continue
  333. # If not accessible via IDispatch, then we can't use it here.
  334. if entry.desc[3] != pythoncom.FUNC_DISPATCH:
  335. continue
  336. if dispid==pythoncom.DISPID_VALUE:
  337. lkey = "value"
  338. elif dispid==pythoncom.DISPID_NEWENUM:
  339. specialItems["_newenum"] = (entry, entry.desc[4], None)
  340. continue # Dont build this one now!
  341. else:
  342. lkey = name.lower()
  343. if lkey in specialItems and specialItems[lkey] is None: # remember if a special one.
  344. specialItems[lkey] = (entry, entry.desc[4], None)
  345. if generator.bBuildHidden or not entry.hidden:
  346. if entry.GetResultName():
  347. print >> stream, '\t# Result is of type ' + entry.GetResultName()
  348. if entry.wasProperty:
  349. print >> stream, '\t# The method %s is actually a property, but must be used as a method to correctly pass the arguments' % name
  350. ret = self.MakeFuncMethod(entry,build.MakePublicAttributeName(name))
  351. for line in ret:
  352. print >> stream, line
  353. print >> stream, "\t_prop_map_get_ = {"
  354. names = self.propMap.keys(); names.sort()
  355. for key in names:
  356. entry = self.propMap[key]
  357. if generator.bBuildHidden or not entry.hidden:
  358. resultName = entry.GetResultName()
  359. if resultName:
  360. print >> stream, "\t\t# Property '%s' is an object of type '%s'" % (key, resultName)
  361. lkey = key.lower()
  362. details = entry.desc
  363. resultDesc = details[2]
  364. argDesc = ()
  365. mapEntry = MakeMapLineEntry(details[0], pythoncom.DISPATCH_PROPERTYGET, resultDesc, argDesc, key, entry.GetResultCLSIDStr())
  366. if entry.desc[0]==pythoncom.DISPID_VALUE:
  367. lkey = "value"
  368. elif entry.desc[0]==pythoncom.DISPID_NEWENUM:
  369. lkey = "_newenum"
  370. else:
  371. lkey = key.lower()
  372. if lkey in specialItems and specialItems[lkey] is None: # remember if a special one.
  373. specialItems[lkey] = (entry, pythoncom.DISPATCH_PROPERTYGET, mapEntry)
  374. # All special methods, except _newenum, are written
  375. # "normally". This is a mess!
  376. if entry.desc[0]==pythoncom.DISPID_NEWENUM:
  377. continue
  378. print >> stream, '\t\t"%s": %s,' % (build.MakePublicAttributeName(key), mapEntry)
  379. names = self.propMapGet.keys(); names.sort()
  380. for key in names:
  381. entry = self.propMapGet[key]
  382. if generator.bBuildHidden or not entry.hidden:
  383. if entry.GetResultName():
  384. print >> stream, "\t\t# Method '%s' returns object of type '%s'" % (key, entry.GetResultName())
  385. details = entry.desc
  386. lkey = key.lower()
  387. argDesc = details[2]
  388. resultDesc = details[8]
  389. mapEntry = MakeMapLineEntry(details[0], pythoncom.DISPATCH_PROPERTYGET, resultDesc, argDesc, key, entry.GetResultCLSIDStr())
  390. if entry.desc[0]==pythoncom.DISPID_VALUE:
  391. lkey = "value"
  392. elif entry.desc[0]==pythoncom.DISPID_NEWENUM:
  393. lkey = "_newenum"
  394. else:
  395. lkey = key.lower()
  396. if lkey in specialItems and specialItems[lkey] is None: # remember if a special one.
  397. specialItems[lkey]=(entry, pythoncom.DISPATCH_PROPERTYGET, mapEntry)
  398. # All special methods, except _newenum, are written
  399. # "normally". This is a mess!
  400. if entry.desc[0]==pythoncom.DISPID_NEWENUM:
  401. continue
  402. print >> stream, '\t\t"%s": %s,' % (build.MakePublicAttributeName(key), mapEntry)
  403. print >> stream, "\t}"
  404. print >> stream, "\t_prop_map_put_ = {"
  405. # These are "Invoke" args
  406. names = list(self.propMap.keys()); names.sort()
  407. for key in names:
  408. entry = self.propMap[key]
  409. if generator.bBuildHidden or not entry.hidden:
  410. lkey=key.lower()
  411. details = entry.desc
  412. # If default arg is None, write an empty tuple
  413. defArgDesc = build.MakeDefaultArgRepr(details[2])
  414. if defArgDesc is None:
  415. defArgDesc = ""
  416. else:
  417. defArgDesc = defArgDesc + ","
  418. print >> stream, '\t\t"%s" : ((%s, LCID, %d, 0),(%s)),' % (build.MakePublicAttributeName(key), details[0], pythoncom.DISPATCH_PROPERTYPUT, defArgDesc)
  419. names = list(self.propMapPut.keys()); names.sort()
  420. for key in names:
  421. entry = self.propMapPut[key]
  422. if generator.bBuildHidden or not entry.hidden:
  423. details = entry.desc
  424. defArgDesc = MakeDefaultArgsForPropertyPut(details[2])
  425. print >> stream, '\t\t"%s": ((%s, LCID, %d, 0),%s),' % (build.MakePublicAttributeName(key), details[0], details[4], defArgDesc)
  426. print >> stream, "\t}"
  427. if specialItems["value"]:
  428. entry, invoketype, propArgs = specialItems["value"]
  429. if propArgs is None:
  430. typename = "method"
  431. ret = self.MakeFuncMethod(entry,'__call__')
  432. else:
  433. typename = "property"
  434. ret = [ "\tdef __call__(self):\n\t\treturn self._ApplyTypes_(*%s)" % propArgs]
  435. print >> stream, "\t# Default %s for this class is '%s'" % (typename, entry.names[0])
  436. for line in ret:
  437. print >> stream, line
  438. print >> stream, "\t# str(ob) and int(ob) will use __call__"
  439. print >> stream, "\tdef __unicode__(self, *args):"
  440. print >> stream, "\t\ttry:"
  441. print >> stream, "\t\t\treturn unicode(self.__call__(*args))"
  442. print >> stream, "\t\texcept pythoncom.com_error:"
  443. print >> stream, "\t\t\treturn repr(self)"
  444. print >> stream, "\tdef __str__(self, *args):"
  445. print >> stream, "\t\treturn str(self.__unicode__(*args))"
  446. print >> stream, "\tdef __int__(self, *args):"
  447. print >> stream, "\t\treturn int(self.__call__(*args))"
  448. if specialItems["_newenum"]:
  449. enumEntry, invoketype, propArgs = specialItems["_newenum"]
  450. resultCLSID = enumEntry.GetResultCLSIDStr()
  451. # If we dont have a good CLSID for the enum result, assume it is the same as the Item() method.
  452. if resultCLSID == "None" and "Item" in self.mapFuncs:
  453. resultCLSID = self.mapFuncs["Item"].GetResultCLSIDStr()
  454. # "Native" Python iterator support
  455. print >> stream, '\tdef __iter__(self):'
  456. print >> stream, '\t\t"Return a Python iterator for this object"'
  457. print >> stream, '\t\tob = self._oleobj_.InvokeTypes(%d,LCID,%d,(13, 10),())' % (pythoncom.DISPID_NEWENUM, enumEntry.desc[4])
  458. print >> stream, '\t\treturn win32com.client.util.Iterator(ob, %s)' % resultCLSID
  459. # And 'old style' iterator support - magically used to simulate iterators
  460. # before Python grew them
  461. print >> stream, '\tdef _NewEnum(self):'
  462. print >> stream, '\t\t"Create an enumerator from this object"'
  463. print >> stream, '\t\treturn win32com.client.util.WrapEnum(self._oleobj_.InvokeTypes(%d,LCID,%d,(13, 10),()),%s)' % (pythoncom.DISPID_NEWENUM, enumEntry.desc[4], resultCLSID)
  464. print >> stream, '\tdef __getitem__(self, index):'
  465. print >> stream, '\t\t"Allow this class to be accessed as a collection"'
  466. print >> stream, "\t\tif '_enum_' not in self.__dict__:"
  467. print >> stream, "\t\t\tself.__dict__['_enum_'] = self._NewEnum()"
  468. print >> stream, "\t\treturn self._enum_.__getitem__(index)"
  469. else: # Not an Enumerator, but may be an "Item/Count" based collection
  470. if specialItems["item"]:
  471. entry, invoketype, propArgs = specialItems["item"]
  472. print >> stream, '\t#This class has Item property/method which may take args - allow indexed access'
  473. print >> stream, '\tdef __getitem__(self, item):'
  474. print >> stream, '\t\treturn self._get_good_object_(self._oleobj_.Invoke(*(%d, LCID, %d, 1, item)), "Item")' % (entry.desc[0], invoketype)
  475. if specialItems["count"]:
  476. entry, invoketype, propArgs = specialItems["count"]
  477. if propArgs is None:
  478. typename = "method"
  479. ret = self.MakeFuncMethod(entry,'__len__')
  480. else:
  481. typename = "property"
  482. ret = [ "\tdef __len__(self):\n\t\treturn self._ApplyTypes_(*%s)" % propArgs]
  483. print >> stream, "\t#This class has Count() %s - allow len(ob) to provide this" % (typename)
  484. for line in ret:
  485. print >> stream, line
  486. # Also include a __nonzero__
  487. print >> stream, "\t#This class has a __len__ - this is needed so 'if object:' always returns TRUE."
  488. print >> stream, "\tdef __nonzero__(self):"
  489. print >> stream, "\t\treturn True"
  490. class CoClassItem(build.OleItem, WritableItem):
  491. order = 5
  492. typename = "COCLASS"
  493. def __init__(self, typeinfo, attr, doc=None, sources = [], interfaces = [], bForUser=1):
  494. build.OleItem.__init__(self, doc)
  495. self.clsid = attr[0]
  496. self.sources = sources
  497. self.interfaces = interfaces
  498. self.bIsDispatch = 1 # Pretend it is so it is written to the class map.
  499. def WriteClass(self, generator):
  500. generator.checkWriteCoClassBaseClass()
  501. doc = self.doc
  502. stream = generator.file
  503. if generator.generate_type == GEN_DEMAND_CHILD:
  504. # Some special imports we must setup.
  505. referenced_items = []
  506. for ref, flag in self.sources:
  507. referenced_items.append(ref)
  508. for ref, flag in self.interfaces:
  509. referenced_items.append(ref)
  510. print >> stream, "import sys"
  511. for ref in referenced_items:
  512. print >> stream, "__import__('%s.%s')" % (generator.base_mod_name, ref.python_name)
  513. print >> stream, "%s = sys.modules['%s.%s'].%s" % (ref.python_name, generator.base_mod_name, ref.python_name, ref.python_name)
  514. # And pretend we have written it - the name is now available as if we had!
  515. ref.bWritten = 1
  516. try:
  517. progId = pythoncom.ProgIDFromCLSID(self.clsid)
  518. print >> stream, "# This CoClass is known by the name '%s'" % (progId)
  519. except pythoncom.com_error:
  520. pass
  521. print >> stream, 'class %s(CoClassBaseClass): # A CoClass' % (self.python_name)
  522. if doc and doc[1]: print >> stream, '\t# ' + doc[1]
  523. print >> stream, '\tCLSID = %r' % (self.clsid,)
  524. print >> stream, '\tcoclass_sources = ['
  525. defItem = None
  526. for item, flag in self.sources:
  527. if flag & pythoncom.IMPLTYPEFLAG_FDEFAULT:
  528. defItem = item
  529. # If we have written a Python class, reference the name -
  530. # otherwise just the IID.
  531. if item.bWritten: key = item.python_name
  532. else: key = repr(str(item.clsid)) # really the iid.
  533. print >> stream, '\t\t%s,' % (key)
  534. print >> stream, '\t]'
  535. if defItem:
  536. if defItem.bWritten: defName = defItem.python_name
  537. else: defName = repr(str(defItem.clsid)) # really the iid.
  538. print >> stream, '\tdefault_source = %s' % (defName,)
  539. print >> stream, '\tcoclass_interfaces = ['
  540. defItem = None
  541. for item, flag in self.interfaces:
  542. if flag & pythoncom.IMPLTYPEFLAG_FDEFAULT: # and dual:
  543. defItem = item
  544. # If we have written a class, refeence its name, otherwise the IID
  545. if item.bWritten: key = item.python_name
  546. else: key = repr(str(item.clsid)) # really the iid.
  547. print >> stream, '\t\t%s,' % (key,)
  548. print >> stream, '\t]'
  549. if defItem:
  550. if defItem.bWritten: defName = defItem.python_name
  551. else: defName = repr(str(defItem.clsid)) # really the iid.
  552. print >> stream, '\tdefault_interface = %s' % (defName,)
  553. self.bWritten = 1
  554. print >> stream
  555. class GeneratorProgress:
  556. def __init__(self):
  557. pass
  558. def Starting(self, tlb_desc):
  559. """Called when the process starts.
  560. """
  561. self.tlb_desc = tlb_desc
  562. def Finished(self):
  563. """Called when the process is complete.
  564. """
  565. def SetDescription(self, desc, maxticks = None):
  566. """We are entering a major step. If maxticks, then this
  567. is how many ticks we expect to make until finished
  568. """
  569. def Tick(self, desc = None):
  570. """Minor progress step. Can provide new description if necessary
  571. """
  572. def VerboseProgress(self, desc):
  573. """Verbose/Debugging output.
  574. """
  575. def LogWarning(self, desc):
  576. """If a warning is generated
  577. """
  578. def LogBeginGenerate(self, filename):
  579. pass
  580. def Close(self):
  581. pass
  582. class Generator:
  583. def __init__(self, typelib, sourceFilename, progressObject, bBuildHidden=1, bUnicodeToString=None):
  584. assert bUnicodeToString is None, "this is deprecated and will go away"
  585. self.bHaveWrittenDispatchBaseClass = 0
  586. self.bHaveWrittenCoClassBaseClass = 0
  587. self.bHaveWrittenEventBaseClass = 0
  588. self.typelib = typelib
  589. self.sourceFilename = sourceFilename
  590. self.bBuildHidden = bBuildHidden
  591. self.progress = progressObject
  592. # These 2 are later additions and most of the code still 'print's...
  593. self.file = None
  594. def CollectOleItemInfosFromType(self):
  595. ret = []
  596. for i in xrange(self.typelib.GetTypeInfoCount()):
  597. info = self.typelib.GetTypeInfo(i)
  598. infotype = self.typelib.GetTypeInfoType(i)
  599. doc = self.typelib.GetDocumentation(i)
  600. attr = info.GetTypeAttr()
  601. ret.append((info, infotype, doc, attr))
  602. return ret
  603. def _Build_CoClass(self, type_info_tuple):
  604. info, infotype, doc, attr = type_info_tuple
  605. # find the source and dispinterfaces for the coclass
  606. child_infos = []
  607. for j in range(attr[8]):
  608. flags = info.GetImplTypeFlags(j)
  609. try:
  610. refType = info.GetRefTypeInfo(info.GetRefTypeOfImplType(j))
  611. except pythoncom.com_error:
  612. # Can't load a dependent typelib?
  613. continue
  614. refAttr = refType.GetTypeAttr()
  615. child_infos.append( (info, refAttr.typekind, refType, refType.GetDocumentation(-1), refAttr, flags) )
  616. # Done generating children - now the CoClass itself.
  617. newItem = CoClassItem(info, attr, doc)
  618. return newItem, child_infos
  619. def _Build_CoClassChildren(self, coclass, coclass_info, oleItems, vtableItems):
  620. sources = {}
  621. interfaces = {}
  622. for info, info_type, refType, doc, refAttr, flags in coclass_info:
  623. # sys.stderr.write("Attr typeflags for coclass referenced object %s=%d (%d), typekind=%d\n" % (name, refAttr.wTypeFlags, refAttr.wTypeFlags & pythoncom.TYPEFLAG_FDUAL,refAttr.typekind))
  624. if refAttr.typekind == pythoncom.TKIND_DISPATCH or \
  625. (refAttr.typekind == pythoncom.TKIND_INTERFACE and refAttr[11] & pythoncom.TYPEFLAG_FDISPATCHABLE):
  626. clsid = refAttr[0]
  627. if clsid in oleItems:
  628. dispItem = oleItems[clsid]
  629. else:
  630. dispItem = DispatchItem(refType, refAttr, doc)
  631. oleItems[dispItem.clsid] = dispItem
  632. dispItem.coclass_clsid = coclass.clsid
  633. if flags & pythoncom.IMPLTYPEFLAG_FSOURCE:
  634. dispItem.bIsSink = 1
  635. sources[dispItem.clsid] = (dispItem, flags)
  636. else:
  637. interfaces[dispItem.clsid] = (dispItem, flags)
  638. # If dual interface, make do that too.
  639. if clsid not in vtableItems and refAttr[11] & pythoncom.TYPEFLAG_FDUAL:
  640. refType = refType.GetRefTypeInfo(refType.GetRefTypeOfImplType(-1))
  641. refAttr = refType.GetTypeAttr()
  642. assert refAttr.typekind == pythoncom.TKIND_INTERFACE, "must be interface bynow!"
  643. vtableItem = VTableItem(refType, refAttr, doc)
  644. vtableItems[clsid] = vtableItem
  645. coclass.sources = list(sources.values())
  646. coclass.interfaces = list(interfaces.values())
  647. def _Build_Interface(self, type_info_tuple):
  648. info, infotype, doc, attr = type_info_tuple
  649. oleItem = vtableItem = None
  650. if infotype == pythoncom.TKIND_DISPATCH or \
  651. (infotype == pythoncom.TKIND_INTERFACE and attr[11] & pythoncom.TYPEFLAG_FDISPATCHABLE):
  652. oleItem = DispatchItem(info, attr, doc)
  653. # If this DISPATCH interface dual, then build that too.
  654. if (attr.wTypeFlags & pythoncom.TYPEFLAG_FDUAL):
  655. # Get the vtable interface
  656. refhtype = info.GetRefTypeOfImplType(-1)
  657. info = info.GetRefTypeInfo(refhtype)
  658. attr = info.GetTypeAttr()
  659. infotype = pythoncom.TKIND_INTERFACE
  660. else:
  661. infotype = None
  662. assert infotype in [None, pythoncom.TKIND_INTERFACE], "Must be a real interface at this point"
  663. if infotype == pythoncom.TKIND_INTERFACE:
  664. vtableItem = VTableItem(info, attr, doc)
  665. return oleItem, vtableItem
  666. def BuildOleItemsFromType(self):
  667. assert self.bBuildHidden, "This code doesnt look at the hidden flag - I thought everyone set it true!?!?!"
  668. oleItems = {}
  669. enumItems = {}
  670. recordItems = {}
  671. vtableItems = {}
  672. for type_info_tuple in self.CollectOleItemInfosFromType():
  673. info, infotype, doc, attr = type_info_tuple
  674. clsid = attr[0]
  675. if infotype == pythoncom.TKIND_ENUM or infotype == pythoncom.TKIND_MODULE:
  676. newItem = EnumerationItem(info, attr, doc)
  677. enumItems[newItem.doc[0]] = newItem
  678. # We never hide interfaces (MSAccess, for example, nominates interfaces as
  679. # hidden, assuming that you only ever use them via the CoClass)
  680. elif infotype in [pythoncom.TKIND_DISPATCH, pythoncom.TKIND_INTERFACE]:
  681. if clsid not in oleItems:
  682. oleItem, vtableItem = self._Build_Interface(type_info_tuple)
  683. oleItems[clsid] = oleItem # Even "None" goes in here.
  684. if vtableItem is not None:
  685. vtableItems[clsid] = vtableItem
  686. elif infotype == pythoncom.TKIND_RECORD or infotype == pythoncom.TKIND_UNION:
  687. newItem = RecordItem(info, attr, doc)
  688. recordItems[newItem.clsid] = newItem
  689. elif infotype == pythoncom.TKIND_ALIAS:
  690. # We dont care about alias' - handled intrinsicly.
  691. continue
  692. elif infotype == pythoncom.TKIND_COCLASS:
  693. newItem, child_infos = self._Build_CoClass(type_info_tuple)
  694. self._Build_CoClassChildren(newItem, child_infos, oleItems, vtableItems)
  695. oleItems[newItem.clsid] = newItem
  696. else:
  697. self.progress.LogWarning("Unknown TKIND found: %d" % infotype)
  698. return oleItems, enumItems, recordItems, vtableItems
  699. def open_writer(self, filename, encoding="mbcs"):
  700. # A place to put code to open a file with the appropriate encoding.
  701. # Does *not* set self.file - just opens and returns a file.
  702. # Actually *deletes* the filename asked for and returns a handle to a
  703. # temp file - finish_writer then puts everything back in place. This
  704. # is so errors don't leave a 1/2 generated file around causing bizarre
  705. # errors later.
  706. # Could be a classmethod one day...
  707. try:
  708. os.unlink(filename)
  709. except os.error:
  710. pass
  711. filename = filename + ".temp"
  712. if sys.version_info > (3,0):
  713. ret = open(filename, "wt", encoding=encoding)
  714. else:
  715. import codecs # not available in py3k.
  716. ret = codecs.open(filename, "wt", encoding)
  717. return ret
  718. def finish_writer(self, filename, f, worked):
  719. f.close()
  720. if worked:
  721. os.rename(filename + ".temp", filename)
  722. else:
  723. os.unlink(filename + ".temp")
  724. def generate(self, file, is_for_demand = 0):
  725. if is_for_demand:
  726. self.generate_type = GEN_DEMAND_BASE
  727. else:
  728. self.generate_type = GEN_FULL
  729. self.file = file
  730. self.do_generate()
  731. self.file = None
  732. self.progress.Finished()
  733. def do_gen_file_header(self):
  734. la = self.typelib.GetLibAttr()
  735. moduleDoc = self.typelib.GetDocumentation(-1)
  736. docDesc = ""
  737. if moduleDoc[1]:
  738. docDesc = moduleDoc[1]
  739. # Reset all the 'per file' state
  740. self.bHaveWrittenDispatchBaseClass = 0
  741. self.bHaveWrittenCoClassBaseClass = 0
  742. self.bHaveWrittenEventBaseClass = 0
  743. # You must provide a file correctly configured for writing unicode.
  744. # We assert this is it may indicate somewhere in pywin32 that needs
  745. # upgrading.
  746. assert self.file.encoding, self.file
  747. encoding = self.file.encoding # or "mbcs"
  748. print >> self.file, '# -*- coding: %s -*-' % (encoding,)
  749. print >> self.file, '# Created by makepy.py version %s' % (makepy_version,)
  750. print >> self.file, '# By python version %s' % \
  751. (sys.version.replace("\n", "-"),)
  752. if self.sourceFilename:
  753. print >> self.file, "# From type library '%s'" % (os.path.split(self.sourceFilename)[1],)
  754. print >> self.file, '# On %s' % time.ctime(time.time())
  755. print >> self.file, '"""' + docDesc + '"""'
  756. print >> self.file, 'makepy_version =', repr(makepy_version)
  757. print >> self.file, 'python_version = 0x%x' % (sys.hexversion,)
  758. print >> self.file
  759. print >> self.file, 'import win32com.client.CLSIDToClass, pythoncom, pywintypes'
  760. print >> self.file, 'import win32com.client.util'
  761. print >> self.file, 'from pywintypes import IID'
  762. print >> self.file, 'from win32com.client import Dispatch'
  763. print >> self.file
  764. print >> self.file, '# The following 3 lines may need tweaking for the particular server'
  765. print >> self.file, '# Candidates are pythoncom.Missing, .Empty and .ArgNotFound'
  766. print >> self.file, 'defaultNamedOptArg=pythoncom.Empty'
  767. print >> self.file, 'defaultNamedNotOptArg=pythoncom.Empty'
  768. print >> self.file, 'defaultUnnamedArg=pythoncom.Empty'
  769. print >> self.file
  770. print >> self.file, 'CLSID = ' + repr(la[0])
  771. print >> self.file, 'MajorVersion = ' + str(la[3])
  772. print >> self.file, 'MinorVersion = ' + str(la[4])
  773. print >> self.file, 'LibraryFlags = ' + str(la[5])
  774. print >> self.file, 'LCID = ' + hex(la[1])
  775. print >> self.file
  776. def do_generate(self):
  777. moduleDoc = self.typelib.GetDocumentation(-1)
  778. stream = self.file
  779. docDesc = ""
  780. if moduleDoc[1]:
  781. docDesc = moduleDoc[1]
  782. self.progress.Starting(docDesc)
  783. self.progress.SetDescription("Building definitions from type library...")
  784. self.do_gen_file_header()
  785. oleItems, enumItems, recordItems, vtableItems = self.BuildOleItemsFromType()
  786. self.progress.SetDescription("Generating...", len(oleItems)+len(enumItems)+len(vtableItems))
  787. # Generate the constants and their support.
  788. if enumItems:
  789. print >> stream, "class constants:"
  790. items = enumItems.values()
  791. items.sort()
  792. for oleitem in items:
  793. oleitem.WriteEnumerationItems(stream)
  794. self.progress.Tick()
  795. print >> stream
  796. if self.generate_type == GEN_FULL:
  797. items = [l for l in oleItems.itervalues() if l is not None]
  798. items.sort()
  799. for oleitem in items:
  800. self.progress.Tick()
  801. oleitem.WriteClass(self)
  802. items = vtableItems.values()
  803. items.sort()
  804. for oleitem in items:
  805. self.progress.Tick()
  806. oleitem.WriteClass(self)
  807. else:
  808. self.progress.Tick(len(oleItems)+len(vtableItems))
  809. print >> stream, 'RecordMap = {'
  810. for record in recordItems.itervalues():
  811. if str(record.clsid) == pythoncom.IID_NULL:
  812. print >> stream, "\t###%s: %s, # Typedef disabled because it doesn't have a non-null GUID" % (repr(record.doc[0]), repr(str(record.clsid)))
  813. else:
  814. print >> stream, "\t%s: %s," % (repr(record.doc[0]), repr(str(record.clsid)))
  815. print >> stream, "}"
  816. print >> stream
  817. # Write out _all_ my generated CLSID's in the map
  818. if self.generate_type == GEN_FULL:
  819. print >> stream, 'CLSIDToClassMap = {'
  820. for item in oleItems.itervalues():
  821. if item is not None and item.bWritten:
  822. print >> stream, "\t'%s' : %s," % (str(item.clsid), item.python_name)
  823. print >> stream, '}'
  824. print >> stream, 'CLSIDToPackageMap = {}'
  825. print >> stream, 'win32com.client.CLSIDToClass.RegisterCLSIDsFromDict( CLSIDToClassMap )'
  826. print >> stream, "VTablesToPackageMap = {}"
  827. print >> stream, "VTablesToClassMap = {"
  828. for item in vtableItems.itervalues():
  829. print >> stream, "\t'%s' : '%s'," % (item.clsid,item.python_name)
  830. print >> stream, '}'
  831. print >> stream
  832. else:
  833. print >> stream, 'CLSIDToClassMap = {}'
  834. print >> stream, 'CLSIDToPackageMap = {'
  835. for item in oleItems.itervalues():
  836. if item is not None:
  837. print >> stream, "\t'%s' : %s," % (str(item.clsid), repr(item.python_name))
  838. print >> stream, '}'
  839. print >> stream, "VTablesToClassMap = {}"
  840. print >> stream, "VTablesToPackageMap = {"
  841. for item in vtableItems.itervalues():
  842. print >> stream, "\t'%s' : '%s'," % (item.clsid,item.python_name)
  843. print >> stream, '}'
  844. print >> stream
  845. print >> stream
  846. # Bit of a hack - build a temp map of iteItems + vtableItems - coClasses
  847. map = {}
  848. for item in oleItems.itervalues():
  849. if item is not None and not isinstance(item, CoClassItem):
  850. map[item.python_name] = item.clsid
  851. for item in vtableItems.itervalues(): # No nones or CoClasses in this map
  852. map[item.python_name] = item.clsid
  853. print >> stream, "NamesToIIDMap = {"
  854. for name, iid in map.iteritems():
  855. print >> stream, "\t'%s' : '%s'," % (name, iid)
  856. print >> stream, '}'
  857. print >> stream
  858. if enumItems:
  859. print >> stream, 'win32com.client.constants.__dicts__.append(constants.__dict__)'
  860. print >> stream
  861. def generate_child(self, child, dir):
  862. "Generate a single child. May force a few children to be built as we generate deps"
  863. self.generate_type = GEN_DEMAND_CHILD
  864. la = self.typelib.GetLibAttr()
  865. lcid = la[1]
  866. clsid = la[0]
  867. major=la[3]
  868. minor=la[4]
  869. self.base_mod_name = "win32com.gen_py." + str(clsid)[1:-1] + "x%sx%sx%s" % (lcid, major, minor)
  870. try:
  871. # Process the type library's CoClass objects, looking for the
  872. # specified name, or where a child has the specified name.
  873. # This ensures that all interesting things (including event interfaces)
  874. # are generated correctly.
  875. oleItems = {}
  876. vtableItems = {}
  877. infos = self.CollectOleItemInfosFromType()
  878. found = 0
  879. for type_info_tuple in infos:
  880. info, infotype, doc, attr = type_info_tuple
  881. if infotype == pythoncom.TKIND_COCLASS:
  882. coClassItem, child_infos = self._Build_CoClass(type_info_tuple)
  883. found = build.MakePublicAttributeName(doc[0])==child
  884. if not found:
  885. # OK, check the child interfaces
  886. for info, info_type, refType, doc, refAttr, flags in child_infos:
  887. if build.MakePublicAttributeName(doc[0]) == child:
  888. found = 1
  889. break
  890. if found:
  891. oleItems[coClassItem.clsid] = coClassItem
  892. self._Build_CoClassChildren(coClassItem, child_infos, oleItems, vtableItems)
  893. break
  894. if not found:
  895. # Doesn't appear in a class defn - look in the interface objects for it
  896. for type_info_tuple in infos:
  897. info, infotype, doc, attr = type_info_tuple
  898. if infotype in [pythoncom.TKIND_INTERFACE, pythoncom.TKIND_DISPATCH]:
  899. if build.MakePublicAttributeName(doc[0]) == child:
  900. found = 1
  901. oleItem, vtableItem = self._Build_Interface(type_info_tuple)
  902. oleItems[clsid] = oleItem # Even "None" goes in here.
  903. if vtableItem is not None:
  904. vtableItems[clsid] = vtableItem
  905. assert found, "Cant find the '%s' interface in the CoClasses, or the interfaces" % (child,)
  906. # Make a map of iid: dispitem, vtableitem)
  907. items = {}
  908. for key, value in oleItems.iteritems():
  909. items[key] = (value,None)
  910. for key, value in vtableItems.iteritems():
  911. existing = items.get(key, None)
  912. if existing is not None:
  913. new_val = existing[0], value
  914. else:
  915. new_val = None, value
  916. items[key] = new_val
  917. self.progress.SetDescription("Generating...", len(items))
  918. for oleitem, vtableitem in items.itervalues():
  919. an_item = oleitem or vtableitem
  920. assert not self.file, "already have a file?"
  921. # like makepy.py, we gen to a .temp file so failure doesn't
  922. # leave a 1/2 generated mess.
  923. out_name = os.path.join(dir, an_item.python_name) + ".py"
  924. worked = False
  925. self.file = self.open_writer(out_name)
  926. try:
  927. if oleitem is not None:
  928. self.do_gen_child_item(oleitem)
  929. if vtableitem is not None:
  930. self.do_gen_child_item(vtableitem)
  931. self.progress.Tick()
  932. worked = True
  933. finally:
  934. self.finish_writer(out_name, self.file, worked)
  935. self.file = None
  936. finally:
  937. self.progress.Finished()
  938. def do_gen_child_item(self, oleitem):
  939. moduleDoc = self.typelib.GetDocumentation(-1)
  940. docDesc = ""
  941. if moduleDoc[1]:
  942. docDesc = moduleDoc[1]
  943. self.progress.Starting(docDesc)
  944. self.progress.SetDescription("Building definitions from type library...")
  945. self.do_gen_file_header()
  946. oleitem.WriteClass(self)
  947. if oleitem.bWritten:
  948. print >> self.file, 'win32com.client.CLSIDToClass.RegisterCLSID( "%s", %s )' % (oleitem.clsid, oleitem.python_name)
  949. def checkWriteDispatchBaseClass(self):
  950. if not self.bHaveWrittenDispatchBaseClass:
  951. print >> self.file, "from win32com.client import DispatchBaseClass"
  952. self.bHaveWrittenDispatchBaseClass = 1
  953. def checkWriteCoClassBaseClass(self):
  954. if not self.bHaveWrittenCoClassBaseClass:
  955. print >> self.file, "from win32com.client import CoClassBaseClass"
  956. self.bHaveWrittenCoClassBaseClass = 1
  957. def checkWriteEventBaseClass(self):
  958. # Not a base class as such...
  959. if not self.bHaveWrittenEventBaseClass:
  960. # Nothing to do any more!
  961. self.bHaveWrittenEventBaseClass = 1
  962. if __name__=='__main__':
  963. print "This is a worker module. Please use makepy to generate Python files."