0001 # Originally written by Curt Hagenlocher, and various bits 0002 # and pieces by Mark Hammond (and now Greg Stein has had 0003 # a go too :-) 0004 0005 # Note that the main worker code has been moved to genpy.py 0006 # As this is normally run from the command line, it reparses the code each time. 0007 # Now this is nothing more than the command line handler and public interface. 0008 0009 # XXX - TO DO 0010 # XXX - Greg and Mark have some ideas for a revamp - just no 0011 # time - if you want to help, contact us for details. 0012 # Main idea is to drop the classes exported and move to a more 0013 # traditional data driven model. 0014 0015 """Generate a .py file from an OLE TypeLibrary file. 0016 0017 0018 This module is concerned only with the actual writing of 0019 a .py file. It draws on the @build@ module, which builds 0020 the knowledge of a COM interface. 0021 0022 """ 0023 usageHelp = """ \ 0024 Usage: 0025 0026 makepy.py [-h] [-x0|1] [-u] [-o filename] [-d] [typelib, ...] 0027 0028 typelib -- A TLB, DLL, OCX, Description, or possibly something else. 0029 -h -- Do not generate hidden methods. 0030 -u -- Python 1.5 and earlier: Do not convert all Unicode objects to strings. 0031 Python 1.6 and later: Do convert all Unicode objects to strings. 0032 -o outputFile -- Generate to named file - dont generate to standard directory. 0033 -i [typelib] -- Show info for specified typelib, or select the typelib if not specified. 0034 -v -- Verbose output 0035 -q -- Quiet output 0036 -d -- Generate the base code now and classes code on demand 0037 0038 Examples: 0039 makepy.py 0040 Present a list of type libraries. 0041 0042 makepy.py "Microsoft Excel 8.0 Object Library" 0043 Generate support for the typelibrary with the specified description 0044 (in this case, MS Excel object model) 0045 0046 """ 0047 0048 import genpy, string, sys, os, types, pythoncom 0049 import selecttlb 0050 import gencache 0051 from win32com.client import NeedUnicodeConversions 0052 0053 bForDemandDefault = 0 # Default value of bForDemand - toggle this to change the world - see also gencache.py 0054 0055 error = "makepy.error" 0056 0057 def usage(): 0058 sys.stderr.write (usageHelp) 0059 sys.exit(2) 0060 0061 def ShowInfo(spec): 0062 if not spec: 0063 tlbSpec = selecttlb.SelectTlb(excludeFlags=selecttlb.FLAG_HIDDEN) 0064 if tlbSpec is None: 0065 return 0066 try: 0067 tlb = pythoncom.LoadRegTypeLib(tlbSpec.clsid, tlbSpec.major, tlbSpec.minor, tlbSpec.lcid) 0068 except pythoncom.com_error: # May be badly registered. 0069 sys.stderr.write("Warning - could not load registered typelib '%s'\n" % (tlbSpec.clsid)) 0070 tlb = None 0071 0072 infos = [(tlb, tlbSpec)] 0073 else: 0074 infos = GetTypeLibsForSpec(spec) 0075 for (tlb, tlbSpec) in infos: 0076 desc = tlbSpec.desc 0077 if desc is None: 0078 if tlb is None: 0079 desc = "<Could not load typelib %s>" % (tlbSpec.dll) 0080 else: 0081 desc = tlb.GetDocumentation(-1)[0] 0082 print desc 0083 print " %s, lcid=%s, major=%s, minor=%s" % (tlbSpec.clsid, tlbSpec.lcid, tlbSpec.major, tlbSpec.minor) 0084 print " >>> # Use these commands in Python code to auto generate .py support" 0085 print " >>> from win32com.client import gencache" 0086 print " >>> gencache.EnsureModule('%s', %s, %s, %s)" % (tlbSpec.clsid, tlbSpec.lcid, tlbSpec.major, tlbSpec.minor) 0087 0088 class SimpleProgress(genpy.GeneratorProgress): 0089 """A simple progress class prints its output to stderr 0090 """ 0091 def __init__(self, verboseLevel): 0092 self.verboseLevel = verboseLevel 0093 def Close(self): 0094 pass 0095 def Finished(self): 0096 if self.verboseLevel>1: 0097 sys.stderr.write("Generation complete..\n") 0098 def SetDescription(self, desc, maxticks = None): 0099 if self.verboseLevel: 0100 sys.stderr.write(desc + "\n") 0101 def Tick(self, desc = None): 0102 pass 0103 0104 def VerboseProgress(self, desc, verboseLevel = 2): 0105 if self.verboseLevel >= verboseLevel: 0106 sys.stderr.write(desc + "\n") 0107 0108 def LogBeginGenerate(self, filename): 0109 self.VerboseProgress("Generating to %s" % filename, 1) 0110 0111 def LogWarning(self, desc): 0112 self.VerboseProgress("WARNING: " + desc, 1) 0113 0114 class GUIProgress(SimpleProgress): 0115 def __init__(self, verboseLevel): 0116 # Import some modules we need to we can trap failure now. 0117 import win32ui, pywin 0118 SimpleProgress.__init__(self, verboseLevel) 0119 self.dialog = None 0120 0121 def Close(self): 0122 if self.dialog is not None: 0123 self.dialog.Close() 0124 self.dialog = None 0125 0126 def Starting(self, tlb_desc): 0127 SimpleProgress.Starting(self, tlb_desc) 0128 if self.dialog is None: 0129 from pywin.dialogs import status 0130 self.dialog=status.ThreadedStatusProgressDialog(tlb_desc) 0131 else: 0132 self.dialog.SetTitle(tlb_desc) 0133 0134 def SetDescription(self, desc, maxticks = None): 0135 self.dialog.SetText(desc) 0136 if maxticks: 0137 self.dialog.SetMaxTicks(maxticks) 0138 0139 def Tick(self, desc = None): 0140 self.dialog.Tick() 0141 if desc is not None: 0142 self.dialog.SetText(desc) 0143 0144 def GetTypeLibsForSpec(arg): 0145 """Given an argument on the command line (either a file name or a library description) 0146 return a list of actual typelibs to use. 0147 """ 0148 typelibs = [] 0149 try: 0150 try: 0151 tlb = pythoncom.LoadTypeLib(arg) 0152 spec = selecttlb.TypelibSpec(None, 0,0,0) 0153 spec.FromTypelib(tlb, arg) 0154 typelibs.append((tlb, spec)) 0155 except pythoncom.com_error: 0156 # See if it is a description 0157 tlbs = selecttlb.FindTlbsWithDescription(arg) 0158 if len(tlbs)==0: 0159 print "Could not locate a type library matching '%s'" % (arg) 0160 for spec in tlbs: 0161 # Version numbers not always reliable if enumerated from registry. 0162 # (as some libs use hex, other's dont. Both examples from MS, of course.) 0163 if spec.dll is None: 0164 tlb = pythoncom.LoadRegTypeLib(spec.clsid, spec.major, spec.minor, spec.lcid) 0165 else: 0166 tlb = pythoncom.LoadTypeLib(spec.dll) 0167 0168 # We have a typelib, but it may not be exactly what we specified 0169 # (due to automatic version matching of COM). So we query what we really have! 0170 attr = tlb.GetLibAttr() 0171 spec.major = attr[3] 0172 spec.minor = attr[4] 0173 spec.lcid = attr[1] 0174 typelibs.append((tlb, spec)) 0175 return typelibs 0176 except pythoncom.com_error: 0177 t,v,tb=sys.exc_info() 0178 sys.stderr.write ("Unable to load type library from '%s' - %s\n" % (arg, v)) 0179 tb = None # Storing tb in a local is a cycle! 0180 sys.exit(1) 0181 0182 def GenerateFromTypeLibSpec(typelibInfo, file = None, verboseLevel = None, progressInstance = None, bUnicodeToString=NeedUnicodeConversions, bQuiet = None, bGUIProgress = None, bForDemand = bForDemandDefault, bBuildHidden = 1): 0183 if bQuiet is not None or bGUIProgress is not None: 0184 print "Please dont use the bQuiet or bGUIProgress params" 0185 print "use the 'verboseLevel', and 'progressClass' params" 0186 if verboseLevel is None: 0187 verboseLevel = 0 # By default, we use a gui, and no verbose level! 0188 0189 if bForDemand and file is not None: 0190 raise RuntimeError, "You can only perform a demand-build when the output goes to the gen_py directory" 0191 if type(typelibInfo)==type(()): 0192 # Tuple 0193 typelibCLSID, lcid, major, minor = typelibInfo 0194 tlb = pythoncom.LoadRegTypeLib(typelibCLSID, major, minor, lcid) 0195 spec = selecttlb.TypelibSpec(typelibCLSID, lcid, major, minor) 0196 spec.FromTypelib(tlb, str(typelibCLSID)) 0197 typelibs = [(tlb, spec)] 0198 elif type(typelibInfo)==types.InstanceType: 0199 if typelibInfo.dll is None: 0200 # Version numbers not always reliable if enumerated from registry. 0201 tlb = pythoncom.LoadRegTypeLib(typelibInfo.clsid, typelibInfo.major, typelibInfo.minor, typelibInfo.lcid) 0202 else: 0203 tlb = pythoncom.LoadTypeLib(typelibInfo.dll) 0204 typelibs = [(tlb, typelibInfo)] 0205 elif hasattr(typelibInfo, "GetLibAttr"): 0206 # A real typelib object! 0207 tla = typelibInfo.GetLibAttr() 0208 guid = tla[0] 0209 lcid = tla[1] 0210 major = tla[3] 0211 minor = tla[4] 0212 spec = selecttlb.TypelibSpec(guid, lcid, major, minor) 0213 typelibs = [(typelibInfo, spec)] 0214 else: 0215 typelibs = GetTypeLibsForSpec(typelibInfo) 0216 0217 if progressInstance is None: 0218 try: 0219 if not bForDemand: # Only go for GUI progress if not doing a demand-import 0220 # Win9x console programs don't seem to like our GUI! 0221 # (Actually, NT/2k wouldnt object to having them threaded - later!) 0222 import win32api, win32con 0223 if win32api.GetVersionEx()[3]==win32con.VER_PLATFORM_WIN32_NT: 0224 bMakeGuiProgress = 1 0225 else: 0226 try: 0227 win32api.GetConsoleTitle() 0228 # Have a console - can't handle GUI 0229 bMakeGuiProgress = 0 0230 except win32api.error: 0231 # no console - we can have a GUI 0232 bMakeGuiProgress = 1 0233 if bMakeGuiProgress: 0234 progressInstance = GUIProgress(verboseLevel) 0235 except ImportError: # No Pythonwin GUI around. 0236 pass 0237 if progressInstance is None: 0238 progressInstance = SimpleProgress(verboseLevel) 0239 progress = progressInstance 0240 0241 bToGenDir = (file is None) 0242 0243 for typelib, info in typelibs: 0244 if file is None: 0245 this_name = gencache.GetGeneratedFileName(info.clsid, info.lcid, info.major, info.minor) 0246 full_name = os.path.join(gencache.GetGeneratePath(), this_name) 0247 if bForDemand: 0248 try: os.unlink(full_name + ".py") 0249 except os.error: pass 0250 try: os.unlink(full_name + ".pyc") 0251 except os.error: pass 0252 try: os.unlink(full_name + ".pyo") 0253 except os.error: pass 0254 if not os.path.isdir(full_name): 0255 os.mkdir(full_name) 0256 outputName = os.path.join(full_name, "__init__.py") 0257 else: 0258 outputName = full_name + ".py" 0259 fileUse = open(outputName, "wt") 0260 progress.LogBeginGenerate(outputName) 0261 else: 0262 fileUse = file 0263 0264 gen = genpy.Generator(typelib, info.dll, progress, bUnicodeToString=bUnicodeToString, bBuildHidden=bBuildHidden) 0265 0266 gen.generate(fileUse, bForDemand) 0267 0268 if file is None: 0269 fileUse.close() 0270 0271 if bToGenDir: 0272 progress.SetDescription("Importing module") 0273 gencache.AddModuleToCache(info.clsid, info.lcid, info.major, info.minor) 0274 0275 progress.Close() 0276 0277 def GenerateChildFromTypeLibSpec(child, typelibInfo, verboseLevel = None, progressInstance = None, bUnicodeToString=NeedUnicodeConversions): 0278 if verboseLevel is None: 0279 verboseLevel = 0 # By default, we use no gui, and no verbose level for the children. 0280 if type(typelibInfo)==type(()): 0281 typelibCLSID, lcid, major, minor = typelibInfo 0282 tlb = pythoncom.LoadRegTypeLib(typelibCLSID, major, minor, lcid) 0283 else: 0284 tlb = typelibInfo 0285 tla = typelibInfo.GetLibAttr() 0286 typelibCLSID = tla[0] 0287 lcid = tla[1] 0288 major = tla[3] 0289 minor = tla[4] 0290 spec = selecttlb.TypelibSpec(typelibCLSID, lcid, major, minor) 0291 spec.FromTypelib(tlb, str(typelibCLSID)) 0292 typelibs = [(tlb, spec)] 0293 0294 if progressInstance is None: 0295 progressInstance = SimpleProgress(verboseLevel) 0296 progress = progressInstance 0297 0298 for typelib, info in typelibs: 0299 dir_name = gencache.GetGeneratedFileName(info.clsid, info.lcid, info.major, info.minor) 0300 dir_path_name = os.path.join(gencache.GetGeneratePath(), dir_name) 0301 progress.LogBeginGenerate(dir_path_name) 0302 0303 gen = genpy.Generator(typelib, info.dll, progress, bUnicodeToString=bUnicodeToString) 0304 gen.generate_child(child, dir_path_name) 0305 progress.SetDescription("Importing module") 0306 __import__("win32com.gen_py." + dir_name + "." + child) 0307 progress.Close() 0308 0309 def main(): 0310 import getopt 0311 hiddenSpec = 1 0312 bUnicodeToString = NeedUnicodeConversions 0313 outputName = None 0314 verboseLevel = 1 0315 doit = 1 0316 bForDemand = bForDemandDefault 0317 try: 0318 opts, args = getopt.getopt(sys.argv[1:], 'vo:huiqd') 0319 for o,v in opts: 0320 if o=='-h': 0321 hiddenSpec = 0 0322 elif o=='-u': 0323 bUnicodeToString = not NeedUnicodeConversions 0324 elif o=='-o': 0325 outputName = v 0326 elif o=='-v': 0327 verboseLevel = verboseLevel + 1 0328 elif o=='-q': 0329 verboseLevel = verboseLevel - 1 0330 elif o=='-i': 0331 if len(args)==0: 0332 ShowInfo(None) 0333 else: 0334 for arg in args: 0335 ShowInfo(arg) 0336 doit = 0 0337 elif o=='-d': 0338 bForDemand = not bForDemand 0339 0340 except (getopt.error, error), msg: 0341 sys.stderr.write (str(msg) + "\n") 0342 usage() 0343 0344 if bForDemand and outputName is not None: 0345 sys.stderr.write("Can not use -d and -o together\n") 0346 usage() 0347 0348 if not doit: 0349 return 0 0350 if len(args)==0: 0351 rc = selecttlb.SelectTlb() 0352 if rc is None: 0353 sys.exit(1) 0354 args = [ rc ] 0355 0356 if outputName is not None: 0357 f = open(outputName, "w") 0358 else: 0359 f = None 0360 0361 for arg in args: 0362 GenerateFromTypeLibSpec(arg, f, verboseLevel = verboseLevel, bForDemand = bForDemand, bBuildHidden = hiddenSpec) 0363 0364 if f: 0365 f.close() 0366 0367 0368 if __name__=='__main__': 0369 rc = main() 0370 if rc: 0371 sys.exit(rc) 0372 sys.exit(0) 0373
Generated by PyXR 0.9.4