| """ | 
 | Windows registry support. | 
 |  | 
 | openKey( keyname )  | 
 |     open existing key object | 
 |  | 
 | >>> key=openKey( r"HKLM\HARDWARE\DESCRIPTION\System" ) | 
 |  | 
 | createKey( keyname )  | 
 |     create a key if it doesn't already exist | 
 |  | 
 | >>> key=createKey( r"HKLM\SOFTWARE\Python\Test" ) | 
 |  | 
 | deleteKey( keyname )  | 
 |     delete a key if it exists | 
 |     Note: deleteKey may not be recursive on all platforms. | 
 |  | 
 | >>> key=deleteKey( r"HKLM\SOFTWARE\Python\Test" ) | 
 |  | 
 | RemoteKey( machine, top_level_key ):  | 
 |     open a key on another machine. | 
 |     You can use the returned key as a basis for opens, creates and deletes | 
 |     on the other machine. | 
 |  | 
 | >>> key=RemoteKey( "somemachine", "HKLM" ) | 
 |  | 
 | For information on the key API, open a key and look at its docstring. | 
 |  | 
 |  | 
 | """ | 
 |  | 
 | import _winreg | 
 | import sys | 
 | import exceptions | 
 | import array | 
 | from types import * | 
 | import string | 
 |  | 
 | class RegType: | 
 |     "Represents one of the types that can go into the registry" | 
 |     def __init__( self, msname, friendlyname ): | 
 |         self.msname=msname | 
 |         self.friendlyname=friendlyname | 
 |         self.intval=getattr( _winreg, msname ) | 
 |  | 
 |     def __repr__( self ): | 
 |         "Return a useful representation of the type object" | 
 |         return "<RegType %d: %s %s>" % \ | 
 |                         (self.intval, self.msname, self.friendlyname ) | 
 |  | 
 | _typeConstants={  | 
 |     _winreg.REG_NONE:  | 
 |         RegType( "REG_NONE", "None" ), | 
 |     _winreg.REG_SZ:  | 
 |         RegType( "REG_SZ", "String" ), | 
 |     _winreg.REG_EXPAND_SZ:  | 
 |         RegType("REG_EXPAND_SZ", "Expandable Template String" ), | 
 |     _winreg.REG_BINARY:  | 
 |         RegType("REG_BINARY", "Binary Data"), | 
 |     _winreg.REG_DWORD :  | 
 |         RegType("REG_DWORD", "Integer" ), | 
 | #    _winreg.REG_DWORD_LITTLE_ENDIAN :  | 
 | #        RegType("REG_DWORD_LITTLE_ENDIAN", "Integer"), | 
 |     _winreg.REG_DWORD_BIG_ENDIAN :  | 
 |         RegType("REG_DWORD_BIG_ENDIAN", "Big Endian Integer"), | 
 |     _winreg.REG_LINK :  | 
 |         RegType("REG_LINK", "Link"), | 
 |     _winreg.REG_MULTI_SZ :  | 
 |         RegType("REG_MULTI_SZ", "List of Strings"), | 
 |     _winreg.REG_RESOURCE_LIST :  | 
 |         RegType("REG_RESOURCE_LIST", "Resource List"), | 
 |     _winreg.REG_FULL_RESOURCE_DESCRIPTOR :  | 
 |         RegType( "REG_FULL_RESOURCE_DESCRIPTOR",  | 
 |                                             "Full Resource Descriptor" ), | 
 |     _winreg.REG_RESOURCE_REQUIREMENTS_LIST:  | 
 |         RegType( "REG_RESOURCE_REQUIREMENTS_LIST",  | 
 |                                             "Resource Requirements List" ) | 
 | } | 
 |  | 
 | regtypes={} | 
 | for constant in _typeConstants.values(): | 
 |     regtypes[constant.msname]=constant | 
 |  | 
 | class _DictBase: | 
 |     "Base class for dictionary-type objects" | 
 |     def __init__( self, key ): | 
 |         self.key=key | 
 |  | 
 |     def clear( self ): | 
 |         "Clear the list of keys/data values, as in dictionaries" | 
 |         keys=list( self.keys() ) | 
 |         map( self.__delitem__, keys ) | 
 |  | 
 |     def get( self, item, defaultVal=None ): | 
 |         "Get a key/value by name or index" | 
 |         try: | 
 |             return self.__getitem__( item ) | 
 |         except (IndexError, EnvironmentError, WindowsError): | 
 |             return defaultVal | 
 |  | 
 |     def has_key( self, item ): | 
 |         "Check if a key/data value with a particular name exists" | 
 |         try: | 
 |             self.__getitem__( item ) | 
 |             return 1 | 
 |         except (IndexError, EnvironmentError, WindowsError): | 
 |             return 0 | 
 |  | 
 |     def keys( self ): | 
 |         "Get a list of key/data value names" | 
 |         keys=[]  | 
 |         try: | 
 |             for i in xrange( 0, sys.maxint ): | 
 |                 keyname = self._nameFromNum( i  ) | 
 |                 keys.append( keyname ) | 
 |         except (IndexError, EnvironmentError, WindowsError): | 
 |             pass | 
 |         return keys | 
 |  | 
 |     def values( self ): | 
 |         "Get a list of key objects or data values" | 
 |         values=[]  # map() doesn't use the IndexError semantics... | 
 |         for i in self: | 
 |             values.append( i ) | 
 |         return values | 
 |  | 
 |     def items( self ): | 
 |         "Get pairs of keyname/key object or valuename/value data" | 
 |         return map( None, self.keys(), self.values() ) | 
 |  | 
 |     def __len__( self ): | 
 |         return len( self.keys() ) | 
 |  | 
 | def _getName( item, nameFromNum ): | 
 |     "Helper function -- don't use it directly" | 
 |     if type( item ) == IntType: | 
 |         try: | 
 |             keyname = nameFromNum( item ) | 
 |         except (WindowsError, EnvironmentError): | 
 |             raise IndexError, item | 
 |  | 
 |     elif type( item ) in [StringType, UnicodeType]:  | 
 |         keyname=item | 
 |     else: | 
 |         raise exceptions.TypeError, \ | 
 |                 "Requires integer index or string key name"  | 
 |     return keyname | 
 |  | 
 |  | 
 | class RegValuesDict( _DictBase ): | 
 |     "A dictionary of registry data values" | 
 |     def _nameFromNum( self, i ): | 
 |         return self.key._nameFromNum( i ) | 
 |  | 
 |     def __getitem__( self, item ): | 
 |         return self.key.getValueNameDataAndType( item ) | 
 |  | 
 |     def __setitem__( self, name, val): | 
 |         if type( val )==TupleType: | 
 |             data, datatype=val | 
 |             assert isinstance( datatype, RegType ) | 
 |             self.key.setValue( name, data, datatype ) | 
 |         else: | 
 |             self.key.setValue( name, val ) | 
 |  | 
 |     def __delitem__( self, item ): | 
 |         valname=_getName( item, self._nameFromNum ) | 
 |         self.key.deleteValue( valname ) | 
 |      | 
 | class RegKeysDict( _DictBase ): | 
 |     "A dictionary of registry keys" | 
 |     def _nameFromNum( self, item ): | 
 |         return _winreg.EnumKey( self.key.handle, item ) | 
 |  | 
 |     def __getitem__( self, item ): | 
 |         keyname=_getName( item, self._nameFromNum ) | 
 |         return self.key.openSubkey( keyname ) | 
 |  | 
 |     def __delitem__( self, item ): | 
 |         keyname=_getName( item, self._nameFromNum ) | 
 |         self.key.deleteSubkey( keyname ) | 
 |  | 
 | def openKey( keyname, samFlags=None ): | 
 |     "Open a key by name" | 
 |     lst=string.split( keyname, "\\", 1 ) | 
 |     if len( lst )==2: | 
 |         hivename,path=lst | 
 |         return hives[hivename].openSubkey( path ) | 
 |     else: | 
 |         hivename=lst[0] | 
 |         return hives[hivename] | 
 |  | 
 | def createKey( keyname ): | 
 |     lst=string.split( keyname, "\\", 1 ) | 
 |     assert len( lst )==2 | 
 |     hivename,path=lst | 
 |     return hives[hivename].createSubkey( path ) | 
 |  | 
 | def deleteKey( keyname ): | 
 |     lst=string.split( keyname, "\\", 1 ) | 
 |     assert len( lst )==2 | 
 |     hivename,path=lst | 
 |     return hives[hivename].deleteSubkey( path ) | 
 |  | 
 |  | 
 | class RegKey: | 
 |     "A registry key object" | 
 |  | 
 |     def __init__( self, name, handle=None ): | 
 |         self.name=name | 
 |         self.handle=handle | 
 |  | 
 |     def _nameFromNum( self, item ): | 
 |         "internal" | 
 |         (name,data,datatype)=_winreg.EnumValue( self.handle, item ) | 
 |         return name | 
 |  | 
 |     def __nonzero__(self): | 
 |         "Is the key open?" | 
 |         if self.handle: | 
 |             return 1 | 
 |         else: | 
 |             return 0 | 
 |  | 
 |     def __cmp__ (self, other ): | 
 |         "Compare two keys for equality" | 
 |         if hasattr( other, "handle" ) and hasattr( other, "name" ): | 
 |             return cmp( self.name, other.name ) | 
 |         else: | 
 |             return cmp( self.handle, other ) | 
 |  | 
 |     def __repr__( self ): | 
 |         return "<Windows RegKey: %s>"% self.name | 
 |  | 
 |     def close(self ): | 
 |         "Close the key" | 
 |         return _winreg.CloseKey( self.handle ) | 
 |  | 
 |     def getSubkeyNames( self ): | 
 |         "Get a list of subkey names" | 
 |         return self.getSubkeys().keys() | 
 |  | 
 |     def getValueNames( self ): | 
 |         "Get a list of value names" | 
 |         return self.getValues().keys() | 
 |  | 
 |     def deleteSubkey( self, subkey ): | 
 |         "Delete a subkey by name" | 
 |         return _winreg.DeleteKey( self.handle, subkey ) | 
 |          | 
 |     def deleteValue( self, valname ): | 
 |         "Delete a value by name" | 
 |         return _winreg.DeleteValue( self.handle, valname ) | 
 |  | 
 |     def createSubkey( self, keyname ): | 
 |         "Create a subkey by name" | 
 |         handle=_winreg.CreateKey( self.handle, keyname ) | 
 |         return RegKey( self.name+"\\"+keyname, handle) | 
 |  | 
 |     def openSubkey( self, keyname, samFlags=None ): | 
 |         "Open a named subkey" | 
 |         if samFlags: | 
 |             handle=_winreg.OpenKey( self.handle, keyname, 0, samFlags ) | 
 |         else: | 
 |             handle=_winreg.OpenKey( self.handle, keyname, 0 ) | 
 |         return RegKey( self.name+"\\"+keyname, handle ) | 
 |  | 
 |     def getSubkeys( self ): | 
 |         "Get a dictionary-like mapping of subkeys" | 
 |         return RegKeysDict( self ) | 
 |  | 
 |     def getValues( self ): | 
 |         "Get a dictionary-like mapping of data values" | 
 |         return RegValuesDict( self ) | 
 |  | 
 |     def getValueNameDataAndType( self, valname ): | 
 |         "Get a data value's name, data and type all at one time" | 
 |         try: | 
 |             if type( valname )==IntType: | 
 |                 (valname,data,datatype)=_winreg.EnumValue( self.handle, valname ) | 
 |             else: | 
 |                 keyname=_getName( valname, self._nameFromNum ) | 
 |                 (data,datatype)=_winreg.QueryValueEx( self.handle, keyname ) | 
 |         except (WindowsError, EnvironmentError): | 
 |             raise IndexError, valname | 
 |  | 
 |         if datatype==_winreg.REG_BINARY: | 
 |             # use arrays for binary data | 
 |             data=array.array( 'c', data ) | 
 |  | 
 |         return (valname, data, _typeConstants[datatype] ) | 
 |  | 
 |     def getValueData( self, valname ): | 
 |         "Get a data value's data." | 
 |         name, data, type=self.getValueNameDataAndType( valname ) | 
 |         return data | 
 |  | 
 |     def setValue( self, valname, data, regtype=None ): | 
 |         "Set a data value's data (and optionally type)" | 
 |         if regtype: | 
 |             typeint=regtype.intval | 
 |         else: | 
 |             if type( data ) in [StringType, UnicodeType]: | 
 |                 typeint=_winreg.REG_SZ | 
 |             elif type( data )==ListType: | 
 |                  # XXX - _winreg currently only supports lists | 
 |                  # Also, probably should check each element is | 
 |                  # string/unicode. | 
 |                  typeint = _winreg.REG_MULTI_SZ | 
 |             elif type( data )==IntType: | 
 |                 typeint=_winreg.REG_DWORD | 
 |             elif type( data )==array.ArrayType: | 
 |                 typeint=_winreg.REG_BINARY | 
 |         _winreg.SetValueEx( self.handle, valname, 0, typeint, data ) | 
 |  | 
 |     def flush(self ): | 
 |         "Make sure that all changes are written to the registry. " | 
 |         "Only use this if you know what you are doing. " | 
 |         "It isn't usually needed." | 
 |         _winreg.FlushKey( self.keyobbj ) | 
 |  | 
 |     def save( self, filename ): | 
 |         "Save a key to a filename" | 
 |         _winreg.SaveKey( self.keyobj, filename ) | 
 |  | 
 |     def load( self, subkey, filename ): | 
 |         "Load a key from a filename" | 
 |         return _winreg.RegLoadKey( self.handle, subkey, filename ) | 
 |  | 
 |  | 
 | class RemoteKey( RegKey ): | 
 |     "Open a key on a remote machine" | 
 |     def __init__( self, machine, topLevelKey ): | 
 |         assert topLevelKey in _hivenames  | 
 |         self.handle =  _winreg.ConnectRegistry( machine, parentKey ) | 
 |         self.name=r"\\%s\%s" % (machine, topLevelKey ) | 
 |  | 
 | _hivenames = ["HKEY_CLASSES_ROOT","HKEY_CURRENT_USER","HKEY_LOCAL_MACHINE", | 
 |                 "HKEY_USERS","HKEY_CURRENT_CONFIG","HKEY_DYN_DATA", | 
 |                 "HKEY_PERFORMANCE_DATA"] | 
 | hives={} | 
 | for name in _hivenames: | 
 |     hives[name]=RegKey( name, getattr( _winreg, name ) ) | 
 | hives["HKLM"]=hives["HKEY_LOCAL_MACHINE"] | 
 | hives["HKCR"]=hives["HKEY_CLASSES_ROOT"] | 
 | hives["HKCU"]=hives["HKEY_CURRENT_USER"] | 
 |  | 
 | _flagnames = ["KEY_ALL_ACCESS","KEY_CREATE_LINK", "KEY_CREATE_SUB_KEY", | 
 |              "KEY_ENUMERATE_SUB_KEYS", "KEY_EXECUTE", "KEY_NOTIFY",  | 
 |              "KEY_QUERY_VALUE", "KEY_READ", "KEY_SET_VALUE"] | 
 | flags={} | 
 | for name in _flagnames: | 
 |     flags[name]=getattr( _winreg, name ) | 
 |  | 
 | _RegNotifyChangeKeyValueOptions=[ "REG_NOTIFY_CHANGE_ATTRIBUTES", | 
 |             "REG_NOTIFY_CHANGE_SECURITY", "REG_NOTIFY_CHANGE_LAST_SET", | 
 |             "REG_NOTIFY_CHANGE_NAME", "REG_LEGAL_CHANGE_FILTER" ] | 
 |  | 
 | _RegRestoreKeyOptions=["REG_WHOLE_HIVE_VOLATILE",  | 
 |     "REG_NO_LAZY_FLUSH", | 
 |     "REG_OPTION_VOLATILE", | 
 |     "REG_REFRESH_HIVE", | 
 |     "REG_OPTION_NON_VOLATILE", | 
 |     "REG_OPTION_BACKUP_RESTORE" ] | 
 |  | 
 | _RegCreateKeyExOptions=[ | 
 |     "REG_LEGAL_OPTION", | 
 |     "REG_OPTION_RESERVED", | 
 |     "REG_OPTION_VOLATILE", | 
 |     "REG_OPTION_NON_VOLATILE", | 
 |     "REG_OPTION_BACKUP_RESTORE", | 
 |     "REG_CREATED_NEW_KEY", | 
 |     "REG_OPENED_EXISTING_KEY", | 
 |     "REG_OPTION_CREATE_LINK"] | 
 |  | 
 |  | 
 | #unusednames=_RegNotifyChangeKeyValueOptions+_RegRestoreKeyOptions+_RegCreateKeyExOptions | 
 |  | 
 | #typeConstantNames=map( lambda x: x.msname, typeConstants.values() ) | 
 |  | 
 | #allnames=_hivenames+_flagnames+typeConstantNames+unusednames | 
 | #winregnames=_winreg.__dict__.keys() | 
 | #for name in winregnames: | 
 | #    if name not in allnames: | 
 | #        print name | 
 |  |