123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687 |
- """Manages the cache of generated Python code.
- Description
- This file manages the cache of generated Python code. When run from the
- command line, it also provides a number of options for managing that cache.
- Implementation
- Each typelib is generated into a filename of format "{guid}x{lcid}x{major}x{minor}.py"
- An external persistant dictionary maps from all known IIDs in all known type libraries
- to the type library itself.
- Thus, whenever Python code knows the IID of an object, it can find the IID, LCID and version of
- the type library which supports it. Given this information, it can find the Python module
- with the support.
- If necessary, this support can be generated on the fly.
- Hacks, to do, etc
- Currently just uses a pickled dictionary, but should used some sort of indexed file.
- Maybe an OLE2 compound file, or a bsddb file?
- """
- import pywintypes, os, sys
- import pythoncom
- import win32com, win32com.client
- import glob
- import traceback
- from . import CLSIDToClass
- import operator
- from importlib import reload
- bForDemandDefault = 0 # Default value of bForDemand - toggle this to change the world - see also makepy.py
- # The global dictionary
- clsidToTypelib = {}
- # If we have a different version of the typelib generated, this
- # maps the "requested version" to the "generated version".
- versionRedirectMap = {}
- # There is no reason we *must* be readonly in a .zip, but we are now,
- # Rather than check for ".zip" or other tricks, PEP302 defines
- # a "__loader__" attribute, so we use that.
- # (Later, it may become necessary to check if the __loader__ can update files,
- # as a .zip loader potentially could - but punt all that until a need arises)
- is_readonly = is_zip = hasattr(win32com, "__loader__") and hasattr(win32com.__loader__, "archive")
- # A dictionary of ITypeLibrary objects for demand generation explicitly handed to us
- # Keyed by usual clsid, lcid, major, minor
- demandGeneratedTypeLibraries = {}
- import pickle as pickle
- def __init__():
- # Initialize the module. Called once explicitly at module import below.
- try:
- _LoadDicts()
- except IOError:
- Rebuild()
- pickleVersion = 1
- def _SaveDicts():
- if is_readonly:
- raise RuntimeError("Trying to write to a readonly gencache ('%s')!" \
- % win32com.__gen_path__)
- f = open(os.path.join(GetGeneratePath(), "dicts.dat"), "wb")
- try:
- p = pickle.Pickler(f)
- p.dump(pickleVersion)
- p.dump(clsidToTypelib)
- finally:
- f.close()
- def _LoadDicts():
- # Load the dictionary from a .zip file if that is where we live.
- if is_zip:
- import io as io
- loader = win32com.__loader__
- arc_path = loader.archive
- dicts_path = os.path.join(win32com.__gen_path__, "dicts.dat")
- if dicts_path.startswith(arc_path):
- dicts_path = dicts_path[len(arc_path)+1:]
- else:
- # Hm. See below.
- return
- try:
- data = loader.get_data(dicts_path)
- except AttributeError:
- # The __loader__ has no get_data method. See below.
- return
- except IOError:
- # Our gencache is in a .zip file (and almost certainly readonly)
- # but no dicts file. That actually needn't be fatal for a frozen
- # application. Assuming they call "EnsureModule" with the same
- # typelib IDs they have been frozen with, that EnsureModule will
- # correctly re-build the dicts on the fly. However, objects that
- # rely on the gencache but have not done an EnsureModule will
- # fail (but their apps are likely to fail running from source
- # with a clean gencache anyway, as then they would be getting
- # Dynamic objects until the cache is built - so the best answer
- # for these apps is to call EnsureModule, rather than freezing
- # the dict)
- return
- f = io.BytesIO(data)
- else:
- # NOTE: IOError on file open must be caught by caller.
- f = open(os.path.join(win32com.__gen_path__, "dicts.dat"), "rb")
- try:
- p = pickle.Unpickler(f)
- version = p.load()
- global clsidToTypelib
- clsidToTypelib = p.load()
- versionRedirectMap.clear()
- finally:
- f.close()
- def GetGeneratedFileName(clsid, lcid, major, minor):
- """Given the clsid, lcid, major and minor for a type lib, return
- the file name (no extension) providing this support.
- """
- return str(clsid).upper()[1:-1] + "x%sx%sx%s" % (lcid, major, minor)
- def SplitGeneratedFileName(fname):
- """Reverse of GetGeneratedFileName()
- """
- return tuple(fname.split('x',4))
- def GetGeneratePath():
- """Returns the name of the path to generate to.
- Checks the directory is OK.
- """
- assert not is_readonly, "Why do you want the genpath for a readonly store?"
- try:
- os.makedirs(win32com.__gen_path__)
- #os.mkdir(win32com.__gen_path__)
- except os.error:
- pass
- try:
- fname = os.path.join(win32com.__gen_path__, "__init__.py")
- os.stat(fname)
- except os.error:
- f = open(fname,"w")
- f.write('# Generated file - this directory may be deleted to reset the COM cache...\n')
- f.write('import win32com\n')
- f.write('if __path__[:-1] != win32com.__gen_path__: __path__.append(win32com.__gen_path__)\n')
- f.close()
- return win32com.__gen_path__
- #
- # The helpers for win32com.client.Dispatch and OCX clients.
- #
- def GetClassForProgID(progid):
- """Get a Python class for a Program ID
- Given a Program ID, return a Python class which wraps the COM object
- Returns the Python class, or None if no module is available.
- Params
- progid -- A COM ProgramID or IID (eg, "Word.Application")
- """
- clsid = pywintypes.IID(progid) # This auto-converts named to IDs.
- return GetClassForCLSID(clsid)
- def GetClassForCLSID(clsid):
- """Get a Python class for a CLSID
- Given a CLSID, return a Python class which wraps the COM object
- Returns the Python class, or None if no module is available.
- Params
- clsid -- A COM CLSID (or string repr of one)
- """
- # first, take a short-cut - we may already have generated support ready-to-roll.
- clsid = str(clsid)
- if CLSIDToClass.HasClass(clsid):
- return CLSIDToClass.GetClass(clsid)
- mod = GetModuleForCLSID(clsid)
- if mod is None:
- return None
- try:
- return CLSIDToClass.GetClass(clsid)
- except KeyError:
- return None
- def GetModuleForProgID(progid):
- """Get a Python module for a Program ID
- Given a Program ID, return a Python module which contains the
- class which wraps the COM object.
- Returns the Python module, or None if no module is available.
- Params
- progid -- A COM ProgramID or IID (eg, "Word.Application")
- """
- try:
- iid = pywintypes.IID(progid)
- except pywintypes.com_error:
- return None
- return GetModuleForCLSID(iid)
- def GetModuleForCLSID(clsid):
- """Get a Python module for a CLSID
- Given a CLSID, return a Python module which contains the
- class which wraps the COM object.
- Returns the Python module, or None if no module is available.
- Params
- progid -- A COM CLSID (ie, not the description)
- """
- clsid_str = str(clsid)
- try:
- typelibCLSID, lcid, major, minor = clsidToTypelib[clsid_str]
- except KeyError:
- return None
- try:
- mod = GetModuleForTypelib(typelibCLSID, lcid, major, minor)
- except ImportError:
- mod = None
- if mod is not None:
- sub_mod = mod.CLSIDToPackageMap.get(clsid_str)
- if sub_mod is None:
- sub_mod = mod.VTablesToPackageMap.get(clsid_str)
- if sub_mod is not None:
- sub_mod_name = mod.__name__ + "." + sub_mod
- try:
- __import__(sub_mod_name)
- except ImportError:
- info = typelibCLSID, lcid, major, minor
- # Force the generation. If this typelibrary has explicitly been added,
- # use it (it may not be registered, causing a lookup by clsid to fail)
- if info in demandGeneratedTypeLibraries:
- info = demandGeneratedTypeLibraries[info]
- from . import makepy
- makepy.GenerateChildFromTypeLibSpec(sub_mod, info)
- # Generate does an import...
- mod = sys.modules[sub_mod_name]
- return mod
- def GetModuleForTypelib(typelibCLSID, lcid, major, minor):
- """Get a Python module for a type library ID
- Given the CLSID of a typelibrary, return an imported Python module,
- else None
- Params
- typelibCLSID -- IID of the type library.
- major -- Integer major version.
- minor -- Integer minor version
- lcid -- Integer LCID for the library.
- """
- modName = GetGeneratedFileName(typelibCLSID, lcid, major, minor)
- mod = _GetModule(modName)
- # If the import worked, it doesn't mean we have actually added this
- # module to our cache though - check that here.
- if "_in_gencache_" not in mod.__dict__:
- AddModuleToCache(typelibCLSID, lcid, major, minor)
- assert "_in_gencache_" in mod.__dict__
- return mod
- def MakeModuleForTypelib(typelibCLSID, lcid, major, minor, progressInstance = None, bForDemand = bForDemandDefault, bBuildHidden = 1):
- """Generate support for a type library.
- Given the IID, LCID and version information for a type library, generate
- and import the necessary support files.
- Returns the Python module. No exceptions are caught.
- 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.
- """
- from . import makepy
- makepy.GenerateFromTypeLibSpec( (typelibCLSID, lcid, major, minor), progressInstance=progressInstance, bForDemand = bForDemand, bBuildHidden = bBuildHidden)
- return GetModuleForTypelib(typelibCLSID, lcid, major, minor)
- def MakeModuleForTypelibInterface(typelib_ob, progressInstance = None, bForDemand = bForDemandDefault, bBuildHidden = 1):
- """Generate support for a type library.
- Given a PyITypeLib interface generate and import the necessary support files. This is useful
- for getting makepy support for a typelibrary that is not registered - the caller can locate
- and load the type library itself, rather than relying on COM to find it.
- Returns the Python module.
- Params
- typelib_ob -- The type library itself
- progressInstance -- Instance to use as progress indicator, or None to
- use the GUI progress bar.
- """
- from . import makepy
- try:
- makepy.GenerateFromTypeLibSpec( typelib_ob, progressInstance=progressInstance, bForDemand = bForDemandDefault, bBuildHidden = bBuildHidden)
- except pywintypes.com_error:
- return None
- tla = typelib_ob.GetLibAttr()
- guid = tla[0]
- lcid = tla[1]
- major = tla[3]
- minor = tla[4]
- return GetModuleForTypelib(guid, lcid, major, minor)
- def EnsureModuleForTypelibInterface(typelib_ob, progressInstance = None, bForDemand = bForDemandDefault, bBuildHidden = 1):
- """Check we have support for a type library, generating if not.
- Given a PyITypeLib interface generate and import the necessary
- support files if necessary. This is useful for getting makepy support
- for a typelibrary that is not registered - the caller can locate and
- load the type library itself, rather than relying on COM to find it.
- Returns the Python module.
- Params
- typelib_ob -- The type library itself
- progressInstance -- Instance to use as progress indicator, or None to
- use the GUI progress bar.
- """
- tla = typelib_ob.GetLibAttr()
- guid = tla[0]
- lcid = tla[1]
- major = tla[3]
- minor = tla[4]
- #If demand generated, save the typelib interface away for later use
- if bForDemand:
- demandGeneratedTypeLibraries[(str(guid), lcid, major, minor)] = typelib_ob
- try:
- return GetModuleForTypelib(guid, lcid, major, minor)
- except ImportError:
- pass
- # Generate it.
- return MakeModuleForTypelibInterface(typelib_ob, progressInstance, bForDemand, bBuildHidden)
- def ForgetAboutTypelibInterface(typelib_ob):
- """Drop any references to a typelib previously added with EnsureModuleForTypelibInterface and forDemand"""
- tla = typelib_ob.GetLibAttr()
- guid = tla[0]
- lcid = tla[1]
- major = tla[3]
- minor = tla[4]
- info = str(guid), lcid, major, minor
- try:
- del demandGeneratedTypeLibraries[info]
- except KeyError:
- # Not worth raising an exception - maybe they dont know we only remember for demand generated, etc.
- print("ForgetAboutTypelibInterface:: Warning - type library with info %s is not being remembered!" % (info,))
- # and drop any version redirects to it
- for key, val in list(versionRedirectMap.items()):
- if val==info:
- del versionRedirectMap[key]
- 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 EnsureDispatch(prog_id, bForDemand = 1): # New fn, so we default the new demand feature to on!
- """Given a COM prog_id, return an object that is using makepy support, building if necessary"""
- disp = win32com.client.Dispatch(prog_id)
- if not disp.__dict__.get("CLSID"): # Eeek - no makepy support - try and build it.
- try:
- ti = disp._oleobj_.GetTypeInfo()
- disp_clsid = ti.GetTypeAttr()[0]
- tlb, index = ti.GetContainingTypeLib()
- tla = tlb.GetLibAttr()
- mod = EnsureModule(tla[0], tla[1], tla[3], tla[4], bForDemand=bForDemand)
- GetModuleForCLSID(disp_clsid)
- # Get the class from the module.
- from . import CLSIDToClass
- disp_class = CLSIDToClass.GetClass(str(disp_clsid))
- disp = disp_class(disp._oleobj_)
- except pythoncom.com_error:
- raise TypeError("This COM object can not automate the makepy process - please run makepy manually for this object")
- return disp
- def AddModuleToCache(typelibclsid, lcid, major, minor, verbose = 1, bFlushNow = not is_readonly):
- """Add a newly generated file to the cache dictionary.
- """
- fname = GetGeneratedFileName(typelibclsid, lcid, major, minor)
- mod = _GetModule(fname)
- # if mod._in_gencache_ is already true, then we are reloading this
- # module - this doesn't mean anything special though!
- mod._in_gencache_ = 1
- info = str(typelibclsid), lcid, major, minor
- dict_modified = False
- def SetTypelibForAllClsids(dict):
- nonlocal dict_modified
- for clsid, cls in dict.items():
- if clsidToTypelib.get(clsid) != info:
- clsidToTypelib[clsid] = info
- dict_modified = True
- SetTypelibForAllClsids(mod.CLSIDToClassMap)
- SetTypelibForAllClsids(mod.CLSIDToPackageMap)
- SetTypelibForAllClsids(mod.VTablesToClassMap)
- SetTypelibForAllClsids(mod.VTablesToPackageMap)
- # If this lib was previously redirected, drop it
- if info in versionRedirectMap:
- del versionRedirectMap[info]
- if bFlushNow and dict_modified:
- _SaveDicts()
- def GetGeneratedInfos():
- zip_pos = win32com.__gen_path__.find(".zip\\")
- if zip_pos >= 0:
- import zipfile
- zip_file = win32com.__gen_path__[:zip_pos+4]
- zip_path = win32com.__gen_path__[zip_pos+5:].replace("\\", "/")
- zf = zipfile.ZipFile(zip_file)
- infos = {}
- for n in zf.namelist():
- if not n.startswith(zip_path):
- continue
- base = n[len(zip_path)+1:].split("/")[0]
- try:
- iid, lcid, major, minor = base.split("x")
- lcid = int(lcid)
- major = int(major)
- minor = int(minor)
- iid = pywintypes.IID("{" + iid + "}")
- except ValueError:
- continue
- except pywintypes.com_error:
- # invalid IID
- continue
- infos[(iid, lcid, major, minor)] = 1
- zf.close()
- return list(infos.keys())
- else:
- # on the file system
- files = glob.glob(win32com.__gen_path__+ "\\*")
- ret = []
- for file in files:
- if not os.path.isdir(file) and not os.path.splitext(file)[1]==".py":
- continue
- name = os.path.splitext(os.path.split(file)[1])[0]
- try:
- iid, lcid, major, minor = name.split("x")
- iid = pywintypes.IID("{" + iid + "}")
- lcid = int(lcid)
- major = int(major)
- minor = int(minor)
- except ValueError:
- continue
- except pywintypes.com_error:
- # invalid IID
- continue
- ret.append((iid, lcid, major, minor))
- return ret
- def _GetModule(fname):
- """Given the name of a module in the gen_py directory, import and return it.
- """
- mod_name = "win32com.gen_py.%s" % fname
- mod = __import__(mod_name)
- return sys.modules[mod_name]
- def Rebuild(verbose = 1):
- """Rebuild the cache indexes from the file system.
- """
- clsidToTypelib.clear()
- infos = GetGeneratedInfos()
- if verbose and len(infos): # Dont bother reporting this when directory is empty!
- print("Rebuilding cache of generated files for COM support...")
- for info in infos:
- iid, lcid, major, minor = info
- if verbose:
- print("Checking", GetGeneratedFileName(*info))
- try:
- AddModuleToCache(iid, lcid, major, minor, verbose, 0)
- except:
- print("Could not add module %s - %s: %s" % (info, sys.exc_info()[0],sys.exc_info()[1]))
- if verbose and len(infos): # Dont bother reporting this when directory is empty!
- print("Done.")
- _SaveDicts()
- def _Dump():
- print("Cache is in directory", win32com.__gen_path__)
- # Build a unique dir
- d = {}
- for clsid, (typelibCLSID, lcid, major, minor) in clsidToTypelib.items():
- d[typelibCLSID, lcid, major, minor] = None
- for typelibCLSID, lcid, major, minor in d.keys():
- mod = GetModuleForTypelib(typelibCLSID, lcid, major, minor)
- print("%s - %s" % (mod.__doc__, typelibCLSID))
- # Boot up
- __init__()
- def usage():
- usageString = """\
- Usage: gencache [-q] [-d] [-r]
- -q - Quiet
- -d - Dump the cache (typelibrary description and filename).
- -r - Rebuild the cache dictionary from the existing .py files
- """
- print(usageString)
- sys.exit(1)
- if __name__=='__main__':
- import getopt
- try:
- opts, args = getopt.getopt(sys.argv[1:], "qrd")
- except getopt.error as message:
- print(message)
- usage()
- # we only have options - complain about real args, or none at all!
- if len(sys.argv)==1 or args:
- print(usage())
- verbose = 1
- for opt, val in opts:
- if opt=='-d': # Dump
- _Dump()
- if opt=='-r':
- Rebuild(verbose)
- if opt=='-q':
- verbose = 0
|