def EnsureModule( typelibCLSID, lcid, major, minor, progressInstance=None, bValidateFile=not is_readonly, bForDemand=bForDemandDefault, bBuildHidden=1, ): """Ensure Python support is loaded for a type library, generating if necessary. Given the IID, LCID and version information for a type library, check and if necessary (re)generate, then import the necessary support files. If we regenerate the file, there is no way to totally snuff out all instances of the old module in Python, and thus we will regenerate the file more than necessary, unless makepy/genpy is modified accordingly. Returns the Python module. No exceptions are caught during the generate process. Params typelibCLSID -- IID of the type library. major -- Integer major version. minor -- Integer minor version lcid -- Integer LCID for the library. progressInstance -- Instance to use as progress indicator, or None to use the GUI progress bar. bValidateFile -- Whether or not to perform cache validation or not bForDemand -- Should a complete generation happen now, or on demand? bBuildHidden -- Should hidden members/attributes etc be generated? """ bReloadNeeded = 0 try: try: module = GetModuleForTypelib(typelibCLSID, lcid, major, minor) except ImportError: # If we get an ImportError # We may still find a valid cache file under a different MinorVersion # # (which windows will search out for us) # print "Loading reg typelib", typelibCLSID, major, minor, lcid module = None try: tlbAttr = pythoncom.LoadRegTypeLib(typelibCLSID, major, minor, lcid).GetLibAttr() # if the above line doesn't throw a pythoncom.com_error, check if # it is actually a different lib than we requested, and if so, suck it in if tlbAttr[1] != lcid or tlbAttr[4] != minor: # print "Trying 2nd minor #", tlbAttr[1], tlbAttr[3], tlbAttr[4] try: module = GetModuleForTypelib(typelibCLSID, tlbAttr[1], tlbAttr[3], tlbAttr[4]) except ImportError: # We don't have a module, but we do have a better minor # version - remember that. minor = tlbAttr[4] # else module remains None except pythoncom.com_error: # couldn't load any typelib - mod remains None pass if module is not None and bValidateFile: assert not is_readonly, "Can't validate in a read-only gencache" try: typLibPath = pythoncom.QueryPathOfRegTypeLib( typelibCLSID, major, minor, lcid) # windows seems to add an extra \0 (via the underlying BSTR) # The mainwin toolkit does not add this erroneous \0 if typLibPath[-1] == "\0": typLibPath = typLibPath[:-1] suf = getattr(os.path, "supports_unicode_filenames", 0) if not suf: # can't pass unicode filenames directly - convert try: typLibPath = typLibPath.encode( sys.getfilesystemencoding()) except AttributeError: # no sys.getfilesystemencoding typLibPath = str(typLibPath) tlbAttributes = pythoncom.LoadRegTypeLib( typelibCLSID, major, minor, lcid).GetLibAttr() except pythoncom.com_error: # We have a module, but no type lib - we should still # run with what we have though - the typelib may not be # deployed here. bValidateFile = 0 if module is not None and bValidateFile: assert not is_readonly, "Can't validate in a read-only gencache" filePathPrefix = "%s\\%s" % ( GetGeneratePath(), GetGeneratedFileName(typelibCLSID, lcid, major, minor), ) filePath = filePathPrefix + ".py" filePathPyc = filePathPrefix + ".py" if __debug__: filePathPyc = filePathPyc + "c" else: filePathPyc = filePathPyc + "o" # Verify that type library is up to date. # If we have a differing MinorVersion or genpy has bumped versions, update the file from . import genpy if (module.MinorVersion != tlbAttributes[4] or genpy.makepy_version != module.makepy_version): # print "Version skew: %d, %d" % (module.MinorVersion, tlbAttributes[4]) # try to erase the bad file from the cache try: os.unlink(filePath) except os.error: pass try: os.unlink(filePathPyc) except os.error: pass if os.path.isdir(filePathPrefix): import shutil shutil.rmtree(filePathPrefix) minor = tlbAttributes[4] module = None bReloadNeeded = 1 else: minor = module.MinorVersion filePathPrefix = "%s\\%s" % ( GetGeneratePath(), GetGeneratedFileName(typelibCLSID, lcid, major, minor), ) filePath = filePathPrefix + ".py" filePathPyc = filePathPrefix + ".pyc" # print "Trying py stat: ", filePath fModTimeSet = 0 try: pyModTime = os.stat(filePath)[8] fModTimeSet = 1 except os.error as e: # If .py file fails, try .pyc file # print "Trying pyc stat", filePathPyc try: pyModTime = os.stat(filePathPyc)[8] fModTimeSet = 1 except os.error as e: pass # print "Trying stat typelib", pyModTime # print str(typLibPath) typLibModTime = os.stat(typLibPath)[8] if fModTimeSet and (typLibModTime > pyModTime): bReloadNeeded = 1 module = None except (ImportError, os.error): module = None if module is None: # We need to build an item. If we are in a read-only cache, we # can't/don't want to do this - so before giving up, check for # a different minor version in our cache - according to COM, this is OK if is_readonly: key = str(typelibCLSID), lcid, major, minor # If we have been asked before, get last result. try: return versionRedirectMap[key] except KeyError: pass # Find other candidates. items = [] for desc in GetGeneratedInfos(): if key[0] == desc[0] and key[1] == desc[1] and key[2] == desc[ 2]: items.append(desc) if items: # Items are all identical, except for last tuple element # We want the latest minor version we have - so just sort and grab last items.sort() new_minor = items[-1][3] ret = GetModuleForTypelib(typelibCLSID, lcid, major, new_minor) else: ret = None # remember and return versionRedirectMap[key] = ret return ret # print "Rebuilding: ", major, minor module = MakeModuleForTypelib( typelibCLSID, lcid, major, minor, progressInstance, bForDemand=bForDemand, bBuildHidden=bBuildHidden, ) # If we replaced something, reload it if bReloadNeeded: module = reload(module) AddModuleToCache(typelibCLSID, lcid, major, minor) return module
def EnsureModule(typelibCLSID, lcid, major, minor, progressInstance=None, bValidateFile=1, bForDemand=bForDemandDefault, bBuildHidden=1): """Ensure Python support is loaded for a type library, generating if necessary. Given the IID, LCID and version information for a type library, check and if necessary (re)generate, then import the necessary support files. If we regenerate the file, there is no way to totally snuff out all instances of the old module in Python, and thus we will regenerate the file more than necessary, unless makepy/genpy is modified accordingly. Returns the Python module. No exceptions are caught during the generate process. Params typelibCLSID -- IID of the type library. major -- Integer major version. minor -- Integer minor version lcid -- Integer LCID for the library. progressInstance -- Instance to use as progress indicator, or None to use the GUI progress bar. bValidateFile -- Whether or not to perform cache validation or not bForDemand -- Should a complete generation happen now, or on demand? bBuildHidden -- Should hidden members/attributes etc be generated? """ bReloadNeeded = 0 try: try: #print "Try specified typelib" module = GetModuleForTypelib(typelibCLSID, lcid, major, minor) #print module except ImportError: # If we get an ImportError # We may still find a valid cache file under a different MinorVersion # #print "Loading reg typelib" tlbAttr = pythoncom.LoadRegTypeLib(typelibCLSID, major, minor, lcid).GetLibAttr() # if the above line doesn't throw a pythoncom.com_error # Let's suck it in #print "Trying 2nd minor #", tlbAttr[1], tlbAttr[3], tlbAttr[4] try: module = GetModuleForTypelib(typelibCLSID, tlbAttr[1], tlbAttr[3], tlbAttr[4]) except ImportError: module = None minor = tlbAttr[4] if module is not None and bValidateFile: try: typLibPath = pythoncom.QueryPathOfRegTypeLib( typelibCLSID, major, minor, lcid) tlbAttributes = pythoncom.LoadRegTypeLib( typelibCLSID, major, minor, lcid).GetLibAttr() except pythoncom.com_error: # We have a module, but no type lib - we should still # run with what we have though - the typelib may not be # deployed here. bValidateFile = 0 if module is not None and bValidateFile: filePathPrefix = "%s\\%s" % (GetGeneratePath(), GetGeneratedFileName( typelibCLSID, lcid, major, minor)) filePath = filePathPrefix + ".py" filePathPyc = filePathPrefix + ".py" if __debug__: filePathPyc = filePathPyc + "c" else: filePathPyc = filePathPyc + "o" # Verify that type library is up to date. #print "Grabbing typelib" # If the following doesn't throw an exception, then we have a valid type library typLibPath = pythoncom.QueryPathOfRegTypeLib( typelibCLSID, major, minor, lcid) tlbAttributes = pythoncom.LoadRegTypeLib(typelibCLSID, major, minor, lcid).GetLibAttr() #print "Grabbed typelib: ", tlbAttributes[3], tlbAttributes[4] ##print module.MinorVersion # If we have a differing MinorVersion or genpy has bumped versions, update the file import genpy if module.MinorVersion != tlbAttributes[ 4] or genpy.makepy_version != module.makepy_version: #print "Version skew: %d, %d" % (module.MinorVersion, tlbAttributes[4]) # try to erase the bad file from the cache try: os.unlink(filePath) except os.error: pass try: os.unlink(filePathPyc) except os.error: pass if os.path.isdir(filePathPrefix): import shutil shutil.rmtree(filePathPrefix) minor = tlbAttributes[4] module = None bReloadNeeded = 1 else: minor = module.MinorVersion filePathPrefix = "%s\\%s" % ( GetGeneratePath(), GetGeneratedFileName(typelibCLSID, lcid, major, minor)) filePath = filePathPrefix + ".py" filePathPyc = filePathPrefix + ".pyc" #print "Trying py stat: ", filePath fModTimeSet = 0 try: pyModTime = os.stat(filePath)[8] fModTimeSet = 1 except os.error, e: # If .py file fails, try .pyc file #print "Trying pyc stat", filePathPyc try: pyModTime = os.stat(filePathPyc)[8] fModTimeSet = 1 except os.error, e: pass #print "Trying stat typelib", pyModTime #print str(typLibPath) typLibModTime = os.stat(str(typLibPath[:-1]))[8] if fModTimeSet and (typLibModTime > pyModTime): bReloadNeeded = 1 module = None