Exemplo n.º 1
0
def ShowInfo(spec):
    if not spec:
        tlbSpec = selecttlb.SelectTlb(excludeFlags=selecttlb.FLAG_HIDDEN)
        if tlbSpec is None:
            return
        try:
            tlb = pythoncom.LoadRegTypeLib(tlbSpec.clsid, tlbSpec.major,
                                           tlbSpec.minor, tlbSpec.lcid)
        except pythoncom.com_error:  # May be badly registered.
            sys.stderr.write(
                "Warning - could not load registered typelib '%s'\n" %
                (tlbSpec.clsid))
            tlb = None

        infos = [(tlb, tlbSpec)]
    else:
        infos = GetTypeLibsForSpec(spec)
    for (tlb, tlbSpec) in infos:
        desc = tlbSpec.desc
        if desc is None:
            if tlb is None:
                desc = "<Could not load typelib %s>" % (tlbSpec.dll)
            else:
                desc = tlb.GetDocumentation(-1)[0]
        print(desc)
        print(" %s, lcid=%s, major=%s, minor=%s" %
              (tlbSpec.clsid, tlbSpec.lcid, tlbSpec.major, tlbSpec.minor))
        print(
            " >>> # Use these commands in Python code to auto generate .py support"
        )
        print(" >>> from win32com.client import gencache")
        print(" >>> gencache.EnsureModule('%s', %s, %s, %s)" %
              (tlbSpec.clsid, tlbSpec.lcid, tlbSpec.major, tlbSpec.minor))
Exemplo n.º 2
0
def GenerateChildFromTypeLibSpec(child, typelibInfo, verboseLevel = None, progressInstance = None, bUnicodeToString=None):
	assert bUnicodeToString is None, "this is deprecated and will go away"
	if verboseLevel is None:
		verboseLevel = 0 # By default, we use no gui, and no verbose level for the children.
	if type(typelibInfo)==type(()):
		typelibCLSID, lcid, major, minor  = typelibInfo
		tlb = pythoncom.LoadRegTypeLib(typelibCLSID, major, minor, lcid)
	else:
		tlb = typelibInfo
		tla = typelibInfo.GetLibAttr()
		typelibCLSID = tla[0]
		lcid = tla[1]
		major = tla[3]
		minor = tla[4]
	spec = selecttlb.TypelibSpec(typelibCLSID, lcid, major, minor)
	spec.FromTypelib(tlb, str(typelibCLSID))
	typelibs = [(tlb, spec)]

	if progressInstance is None:
		progressInstance = SimpleProgress(verboseLevel)
	progress = progressInstance

	for typelib, info in typelibs:
		dir_name = gencache.GetGeneratedFileName(info.clsid, info.lcid, info.major, info.minor)
		dir_path_name = os.path.join(gencache.GetGeneratePath(), dir_name)
		progress.LogBeginGenerate(dir_path_name)

		gen = genpy.Generator(typelib, info.dll, progress)
		gen.generate_child(child, dir_path_name)
		progress.SetDescription("Importing module")
		__import__("win32com.gen_py." + dir_name + "." + child)
	progress.Close()
Exemplo n.º 3
0
def GetTypeLibsForSpec(arg):
    """Given an argument on the command line (either a file name, library
	description, or ProgID of an object) return a list of actual typelibs
	to use. """
    typelibs = []
    try:
        try:
            tlb = pythoncom.LoadTypeLib(arg)
            spec = selecttlb.TypelibSpec(None, 0, 0, 0)
            spec.FromTypelib(tlb, arg)
            typelibs.append((tlb, spec))
        except pythoncom.com_error:
            # See if it is a description
            tlbs = selecttlb.FindTlbsWithDescription(arg)
            if len(tlbs) == 0:
                # Maybe it is the name of a COM object?
                try:
                    ob = Dispatch(arg)
                    # and if so, it must support typelib info
                    tlb, index = ob._oleobj_.GetTypeInfo(
                    ).GetContainingTypeLib()
                    spec = selecttlb.TypelibSpec(None, 0, 0, 0)
                    spec.FromTypelib(tlb)
                    tlbs.append(spec)
                except pythoncom.com_error:
                    pass
            if len(tlbs) == 0:
                print("Could not locate a type library matching '%s'" % (arg))
            for spec in tlbs:
                # Version numbers not always reliable if enumerated from registry.
                # (as some libs use hex, other's dont.  Both examples from MS, of course.)
                if spec.dll is None:
                    tlb = pythoncom.LoadRegTypeLib(spec.clsid, spec.major,
                                                   spec.minor, spec.lcid)
                else:
                    tlb = pythoncom.LoadTypeLib(spec.dll)

                # We have a typelib, but it may not be exactly what we specified
                # (due to automatic version matching of COM).  So we query what we really have!
                attr = tlb.GetLibAttr()
                spec.major = attr[3]
                spec.minor = attr[4]
                spec.lcid = attr[1]
                typelibs.append((tlb, spec))
        return typelibs
    except pythoncom.com_error:
        t, v, tb = sys.exc_info()
        sys.stderr.write("Unable to load type library from '%s' - %s\n" %
                         (arg, v))
        tb = None  # Storing tb in a local is a cycle!
        sys.exit(1)
Exemplo n.º 4
0
 def _build_typeinfos_(self):
     # Can only ever be one for now.
     tlb_guid = getattr(self._obj_, '_typelib_guid_', None)
     if tlb_guid is None:
         return []
     tlb_major, tlb_minor = getattr(self._obj_, '_typelib_version_', (1, 0))
     tlb = pythoncom.LoadRegTypeLib(tlb_guid, tlb_major, tlb_minor)
     typecomp = tlb.GetTypeComp()
     # Not 100% sure what semantics we should use for the default interface.
     # Look for the first name in _com_interfaces_ that exists in the typelib.
     for iname in self._obj_._com_interfaces_:
         try:
             type_info, type_comp = typecomp.BindType(iname)
             if type_info is not None:
                 return [type_info]
         except pythoncom.com_error:
             pass
     return []
Exemplo n.º 5
0
def BuildOleItems(clsid):
    tlbs = selecttlb.EnumTlbs()
    tlbs = {tlb.clsid: tlb for tlb in tlbs}

    tlbSpec = tlbs.get(clsid)

    if tlbSpec is None:
        return {}
        raise LookupError('KHOpenAPI Module not found')

    if tlbSpec.dll is None:
        tlb = pythoncom.LoadRegTypeLib(tlbSpec.clsid, int(tlbSpec.major, 16), int(tlbSpec.minor, 16), tlbSpec.lcid)
    else:
        tlb = pythoncom.LoadTypeLib(tlbSpec.dll)

    gen = genpy.Generator(tlb, tlbSpec.dll, None, bBuildHidden=1)
    oleItems, _enumItems, _recordItems, _vtableItems = gen.BuildOleItemsFromType()

    oleItems = {str(clsId): oleItem for clsId, oleItem in oleItems.items()}

    return oleItems
Exemplo n.º 6
0
def RegisterInterfaces(typelibGUID, lcid, major, minor, interface_names=None):
    ret = []  # return a list of (dispid, funcname for our policy's benefit
    # First see if we have makepy support.  If so, we can probably satisfy the request without loading the typelib.
    try:
        mod = gencache.GetModuleForTypelib(typelibGUID, lcid, major, minor)
    except ImportError:
        mod = None
    if mod is None:
        import win32com.client.build
        # Load up the typelib and build (but don't cache) it now
        tlb = pythoncom.LoadRegTypeLib(typelibGUID, major, minor, lcid)
        typecomp_lib = tlb.GetTypeComp()
        if interface_names is None:
            interface_names = []
            for i in range(tlb.GetTypeInfoCount()):
                info = tlb.GetTypeInfo(i)
                doc = tlb.GetDocumentation(i)
                attr = info.GetTypeAttr()
                if attr.typekind == pythoncom.TKIND_INTERFACE or \
                   (attr.typekind == pythoncom.TKIND_DISPATCH and attr.wTypeFlags & pythoncom.TYPEFLAG_FDUAL):
                    interface_names.append(doc[0])
        for name in interface_names:
            type_info, type_comp = typecomp_lib.BindType(name, )
            # Not sure why we don't get an exception here - BindType's C
            # impl looks correct..
            if type_info is None:
                raise ValueError("The interface '%s' can not be located" %
                                 (name, ))
            # If we got back a Dispatch interface, convert to the real interface.
            attr = type_info.GetTypeAttr()
            if attr.typekind == pythoncom.TKIND_DISPATCH:
                refhtype = type_info.GetRefTypeOfImplType(-1)
                type_info = type_info.GetRefTypeInfo(refhtype)
                attr = type_info.GetTypeAttr()
            item = win32com.client.build.VTableItem(
                type_info, attr, type_info.GetDocumentation(-1))
            _doCreateVTable(item.clsid, item.python_name, item.bIsDispatch,
                            item.vtableFuncs)
            for info in item.vtableFuncs:
                names, dispid, desc = info
                invkind = desc[4]
                ret.append((dispid, invkind, names[0]))
    else:
        # Cool - can used cached info.
        if not interface_names:
            interface_names = list(mod.VTablesToClassMap.values())
        for name in interface_names:
            try:
                iid = mod.NamesToIIDMap[name]
            except KeyError:
                raise ValueError(
                    "Interface '%s' does not exist in this cached typelib" %
                    (name, ))


#            print "Processing interface", name
            sub_mod = gencache.GetModuleForCLSID(iid)
            is_dispatch = getattr(sub_mod, name + "_vtables_dispatch_", None)
            method_defs = getattr(sub_mod, name + "_vtables_", None)
            if is_dispatch is None or method_defs is None:
                raise ValueError("Interface '%s' is IDispatch only" % (name, ))

            # And create the univgw defn
            _doCreateVTable(iid, name, is_dispatch, method_defs)
            for info in method_defs:
                names, dispid, desc = info
                invkind = desc[4]
                ret.append((dispid, invkind, names[0]))
    return ret
Exemplo n.º 7
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
Exemplo n.º 8
0
def GenerateFromTypeLibSpec(typelibInfo, file = None, verboseLevel = None, progressInstance = None, bUnicodeToString=None, bForDemand = bForDemandDefault, bBuildHidden = 1):
	assert bUnicodeToString is None, "this is deprecated and will go away"
	if verboseLevel is None:
		verboseLevel = 0 # By default, we use no gui and no verbose level!

	if bForDemand and file is not None:
		raise RuntimeError("You can only perform a demand-build when the output goes to the gen_py directory")
	if isinstance(typelibInfo, tuple):
		# Tuple
		typelibCLSID, lcid, major, minor  = typelibInfo
		tlb = pythoncom.LoadRegTypeLib(typelibCLSID, major, minor, lcid)
		spec = selecttlb.TypelibSpec(typelibCLSID, lcid, major, minor)
		spec.FromTypelib(tlb, str(typelibCLSID))
		typelibs = [(tlb, spec)]
	elif isinstance(typelibInfo, selecttlb.TypelibSpec):
		if typelibInfo.dll is None:
			# Version numbers not always reliable if enumerated from registry.
			tlb = pythoncom.LoadRegTypeLib(typelibInfo.clsid, typelibInfo.major, typelibInfo.minor, typelibInfo.lcid)
		else:
			tlb = pythoncom.LoadTypeLib(typelibInfo.dll)
		typelibs = [(tlb, typelibInfo)]
	elif hasattr(typelibInfo, "GetLibAttr"):
		# A real typelib object!
		# Could also use isinstance(typelibInfo, PyITypeLib) instead, but PyITypeLib is not directly exposed by pythoncom.
		#	pythoncom.TypeIIDs[pythoncom.IID_ITypeLib] seems to work
		tla = typelibInfo.GetLibAttr()
		guid = tla[0]
		lcid = tla[1]
		major = tla[3]
		minor = tla[4]
		spec = selecttlb.TypelibSpec(guid, lcid, major, minor)
		typelibs = [(typelibInfo, spec)]
	else:
		typelibs = GetTypeLibsForSpec(typelibInfo)

	if progressInstance is None:
		progressInstance = SimpleProgress(verboseLevel)
	progress = progressInstance

	bToGenDir = (file is None)

	for typelib, info in typelibs:
		gen = genpy.Generator(typelib, info.dll, progress, bBuildHidden=bBuildHidden)

		if file is None:
			this_name = gencache.GetGeneratedFileName(info.clsid, info.lcid, info.major, info.minor)
			full_name = os.path.join(gencache.GetGeneratePath(), this_name)
			if bForDemand:
				try: os.unlink(full_name + ".py")
				except os.error: pass
				try: os.unlink(full_name + ".pyc")
				except os.error: pass
				try: os.unlink(full_name + ".pyo")
				except os.error: pass
				if not os.path.isdir(full_name):
					os.mkdir(full_name)
				outputName = os.path.join(full_name, "__init__.py")
			else:
				outputName = full_name + ".py"
			fileUse = gen.open_writer(outputName)
			progress.LogBeginGenerate(outputName)
		else:
			fileUse = file

		worked = False
		try:
			gen.generate(fileUse, bForDemand)
			worked = True
		finally:
			if file is None:
				gen.finish_writer(outputName, fileUse, worked)
		if bToGenDir:
			progress.SetDescription("Importing module")
			gencache.AddModuleToCache(info.clsid, info.lcid, info.major, info.minor)

	progress.Close()
Exemplo n.º 9
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
Exemplo n.º 10
0
def GenerateFromTypeLibSpec(typelibInfo, file = None, verboseLevel = None, progressInstance = None, bUnicodeToString=NeedUnicodeConversions, bForDemand = bForDemandDefault, bBuildHidden = 1):
	if verboseLevel is None:
		verboseLevel = 0 # By default, we use no gui and no verbose level!

	if bForDemand and file is not None:
		raise RuntimeError, "You can only perform a demand-build when the output goes to the gen_py directory"
	if type(typelibInfo)==type(()):
		# Tuple
		typelibCLSID, lcid, major, minor  = typelibInfo
		tlb = pythoncom.LoadRegTypeLib(typelibCLSID, major, minor, lcid)
		spec = selecttlb.TypelibSpec(typelibCLSID, lcid, major, minor)
		spec.FromTypelib(tlb, str(typelibCLSID))
		typelibs = [(tlb, spec)]
	elif type(typelibInfo)==types.InstanceType:
		if typelibInfo.dll is None:
			# Version numbers not always reliable if enumerated from registry.
			tlb = pythoncom.LoadRegTypeLib(typelibInfo.clsid, typelibInfo.major, typelibInfo.minor, typelibInfo.lcid)
		else:
			tlb = pythoncom.LoadTypeLib(typelibInfo.dll)
		typelibs = [(tlb, typelibInfo)]
	elif hasattr(typelibInfo, "GetLibAttr"):
		# A real typelib object!
		tla = typelibInfo.GetLibAttr()
		guid = tla[0]
		lcid = tla[1]
		major = tla[3]
		minor = tla[4]
		spec = selecttlb.TypelibSpec(guid, lcid, major, minor)
		typelibs = [(typelibInfo, spec)]
	else:
		typelibs = GetTypeLibsForSpec(typelibInfo)

	if progressInstance is None:
		progressInstance = SimpleProgress(verboseLevel)
	progress = progressInstance

	bToGenDir = (file is None)

	for typelib, info in typelibs:
		if file is None:
			this_name = gencache.GetGeneratedFileName(info.clsid, info.lcid, info.major, info.minor)
			full_name = os.path.join(gencache.GetGeneratePath(), this_name)
			if bForDemand:
				try: os.unlink(full_name + ".py")
				except os.error: pass
				try: os.unlink(full_name + ".pyc")
				except os.error: pass
				try: os.unlink(full_name + ".pyo")
				except os.error: pass
				if not os.path.isdir(full_name):
					os.mkdir(full_name)
				outputName = os.path.join(full_name, "__init__.py")
			else:
				outputName = full_name + ".py"
			# generate to a temp file (so errors don't leave a 1/2
			# generated file) and one which can handle unicode!
			try:
				os.unlink(outputName)
			except os.error:
				pass
			encoding = 'mbcs' # could make this a param.
			fileUse = codecs.open(outputName + ".temp", "wt",
			                      encoding)
			progress.LogBeginGenerate(outputName)
		else:
			fileUse = file

		gen = genpy.Generator(typelib, info.dll, progress, bUnicodeToString=bUnicodeToString, bBuildHidden=bBuildHidden)

		gen.generate(fileUse, bForDemand)
		
		if file is None:
			fileUse.close()
			os.rename(outputName + ".temp", outputName)
		
		if bToGenDir:
			progress.SetDescription("Importing module")
			gencache.AddModuleToCache(info.clsid, info.lcid, info.major, info.minor)

	progress.Close()