home *** CD-ROM | disk | FTP | other *** search
- """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, string, sys
- import pythoncom
- import win32com, win32com.client
- import glob
- import traceback
- import CLSIDToClass
- import operator
-
- 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 = hasattr(win32com, "__loader__")
-
- # A dictionary of ITypeLibrary objects for demand generation explicitly handed to us
- # Keyed by usual clsid, lcid, major, minor
- demandGeneratedTypeLibraries = {}
-
- 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__
- import cPickle
- f = open(os.path.join(GetGeneratePath(), "dicts.dat"), "wb")
- try:
- p = cPickle.Pickler(f)
- p.dump(pickleVersion)
- p.dump(clsidToTypelib)
- finally:
- f.close()
-
- def _LoadDicts():
- import cPickle
- # Load the dictionary from a .zip file if that is where we live.
- if hasattr(win32com, "__loader__"):
- import cStringIO
- 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 = cStringIO.StringIO(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 = cPickle.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 string.upper(str(clsid))[1:-1] + "x%sx%sx%s" % (lcid, major, minor)
-
- def SplitGeneratedFileName(fname):
- """Reverse of GetGeneratedFileName()
- """
- return tuple(string.split(fname,'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 demandGeneratedTypeLibraries.has_key(info):
- info = demandGeneratedTypeLibraries[info]
- 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 not mod.__dict__.has_key("_in_gencache_"):
- AddModuleToCache(typelibCLSID, lcid, major, minor)
- assert mod.__dict__.has_key("_in_gencache_")
- return mod
-
- def MakeModuleForTypelib(typelibCLSID, lcid, major, minor, progressInstance = None, bGUIProgress = 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.
- """
- if bGUIProgress is not None:
- print "The 'bGuiProgress' param to 'MakeModuleForTypelib' is obsolete."
-
- import makepy
- try:
- makepy.GenerateFromTypeLibSpec( (typelibCLSID, lcid, major, minor), progressInstance=progressInstance, bForDemand = bForDemand, bBuildHidden = bBuildHidden)
- except pywintypes.com_error:
- return None
- 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.
- """
- 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 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)
- 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.
- #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
- 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.
- 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)
- assert not mod.__dict__.has_key("_in_gencache_"), \
- "This module has already been processed by this process"
- mod._in_gencache_ = 1
- dict = mod.CLSIDToClassMap
- info = str(typelibclsid), lcid, major, minor
- for clsid, cls in dict.items():
- clsidToTypelib[clsid] = info
-
- dict = mod.CLSIDToPackageMap
- for clsid, name in dict.items():
- clsidToTypelib[clsid] = info
-
- dict = mod.VTablesToClassMap
- for clsid, cls in dict.items():
- clsidToTypelib[clsid] = info
-
- dict = mod.VTablesToPackageMap
- for clsid, cls in dict.items():
- clsidToTypelib[clsid] = info
-
- # If this lib was previously redirected, drop it
- if versionRedirectMap.has_key(info):
- del versionRedirectMap[info]
- if bFlushNow:
- _SaveDicts()
-
- def GetGeneratedInfos():
- zip_pos = win32com.__gen_path__.find(".zip\\")
- if zip_pos >= 0:
- import zipfile, cStringIO
- 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 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)==".py":
- continue
- name = os.path.splitext(os.path.split(file)[1])[0]
- try:
- iid, lcid, major, minor = string.split(name, "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" % (name, 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, 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
-