Пример #1
0
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
Пример #2
0
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