Welcome, guest | Sign In | My Account | Store | Cart

Based on RawConfigParser, the usage and implementation is almost the same, however this is not a subclass of it because it doesn't need to.

Python, 268 lines
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
#!/usr/bin/env python

# regconfig.py
import _winreg
import os.path as path

class RegConfig:
    """ Class that encapsulates a registry (path) as a configuration store.

        section = registry key
        option = registry valuename
        value = registry value

        Storage model = dictionary

    """

    def __init__(self, reg_path=None, autowrite=False):
        
        self._regpath = reg_path
        self._autowrite = autowrite
        self._store = {}

        # Autowrite is available only if a registry path is provided.
        if not self._regpath: self._autowrite = False

        # read the registry and store values if path given.
        if self._regpath: self.read(self._regpath)


    def add_section(self, section):
        """ Add a section named section to the instance. If a section by the
            given name already exists, ValueError is raised. """
        if not self.has_section(section):
            self._store[section] = {}
        else:
            raise ValueError("Section already exists")
        
    def get(self, section, option):
        """ Get an option value for the named section. """
        if self.has_option(section, option):
            return self._store[section][option][0]

                
    def _get_default_regkey(self, regpath=None, forwriting=False):
        """ Get the registry key handle for registry operations. provided the
            registry path. """ 
        if regpath:
            key = regpath
            subkey = ''
            while path.split(key)[0]:
                key, tmp = path.split(key)
                subkey = '\\'.join([tmp, subkey])              
            if key == 'HKEY_CLASSES_ROOT':
                key = _winreg.HKEY_CLASSES_ROOT
            elif key == 'HKEY_CURRENT_CONFIG':
                key = _winreg.HKEY_CURRENT_CONFIG
            elif key == 'HKEY_CURRENT_USER':
                key = _winreg.HKEY_CURRENT_USER
            elif key == 'HKEY_DYN_DATA':
                key = _winreg.HKEY_DYN_DATA
            elif key == 'HKEY_LOCAL_MACHINE':
                key = _winreg.HKEY_LOCAL_MACHINE
            elif key == 'HKEY_PERFORMANCE_DATA':
                key = _winreg.HKEY_PERFORMANCE_DATA
            elif key == 'HKEY_USERS':
                key = _winreg.HKEY_USERS
            else:
                raise TypeError('Invalid registry key (HKEY_)')
            try:
                if forwriting:
                    hkey = _winreg.CreateKey(key, subkey)
                else:
                    hkey = _winreg.OpenKey(key, subkey)
            except:
                raise WindowsError('Cannot open registry path')
            else:
                return hkey
        
                    
    def items(self, section):
        """ Return a list of (name, value) pairs for each option in the given
            section. """
        if self.has_section(section):
            sectiondict = self._store[section]
            ret = []
            for option in sectiondict.keys():
                value, type = sectiondict[option]
                ret.append((option, value))
            return ret
        
        
    def has_option(self, section, option):
        """ If the given section exists, and contains the given option. """
        if self._store.has_key(section):
            sectiondict = self._store[section]
            return sectiondict.has_key(option)
    
    
    def has_section(self, section):
        """ Indicates whether the named section is present in the
            configuration. """
        return self._store.has_key(section)
        
        
    def options(self, section):
        """ Returns a list of options available in the specified section. """
        if self._store.has_key(section):
            sectiondict = self._store[section]
            if sectiondict:
                return sectiondict.keys()
            
            
    def read(self, regpath=None):
        """ Can be a single or a list of registry paths. When multiple registry
            keys are read, options and values are overwritten in a FIFO
            fashion ordered from the list. """
        if regpath:
            try:
                if isinstance(regpath, list):
                    for rp in regpath:
                        self._read(self._get_default_regkey(rp))
                else:
                    self._read(self._get_default_regkey(regpath))
            except Exception, e:
                if not self._autowrite: raise e
                
    def _read(self, regkey=None):
        """ Parses a registry path into sections, options and values. """
        if regkey:
            index = 0
            while 1:
                try:
                    section = _winreg.EnumKey(regkey, index)
                except: 
                    break
                else:
                    try:
                        self.add_section(section)
                    except:
                        pass
                    index += 1
                    
            for section in self.sections():
                index = 0
                while 1:
                    try:
                        hkey = _winreg.OpenKey(regkey, section)   
                        valuename, data, type = _winreg.EnumValue(hkey, index)
                    except:
                        break
                    else:
                        self.set(section, valuename, (data, type), readop=True)
                        index += 1
                        if hkey: _winreg.CloseKey(hkey)
            if regkey: _winreg.CloseKey(regkey)
                        
                        
    def remove_option(self, section, option):
        if self.has_option(section, option):
            del self._store[section][option]
            
                     
    def remove_section(self, section):
        if self.has_section(section):
            del self._store[section]     


    def sections(self):
        """ Return a list of the sections available. """
        return self._store.keys()
    

    def set(self, section, option, value, check=True, readop=False):
        """ If the given section exists, set the given option to the specified
            value; if check=True ValueError is raised if it nonexistent
            otherwise the section is written. """
        if not self.has_section(section):
            if check and not self._autowrite:
                raise ValueError('Section does not exist')
            self.add_section(section)
            
        sectiondict = self._store[section]
        
        if isinstance(value, tuple):
            pass
        else:
            value = self._valueregform(value)
            
        # Automatically write to rgistry if specified.
        if self._autowrite and not readop:
            self._write_reg(self._regpath, section, option, value)
                    
        
        sectiondict[option] = value
        

    def _valueregform(self, value):
        """ Converts values set by the user to a from to be stored in the
            registry. """
        if isinstance(value, str) or isinstance(value, unicode):
            value = (value, _winreg.REG_SZ)
        elif isinstance(value, int):
            value = (value, _winreg.REG_DWORD)
        elif isinstance(value, list):
            for s in value:
                if not isinstance(s, str) or isinstance(s, unicode):
                    raise TypeError(
                        "Values in list must be of type str or unicode.")
            value = (value, _winreg.REG_MULTI_SZ)
        else:
            raise TypeError('Invalid value')
    
        return value
    
    def write(self, regpath=None):
        """ Writes configuration to the registry path. """
        if not regpath:
            regpath = self._regpath
        if regpath:
            for section in self.sections():
                sectiondict = self._store[section]
                for option in sectiondict.keys():
                    apply(self._write_reg, (regpath, section, option,
                                            sectiondict[option]))
        
        
    def _write_reg(self, regpath, section, option, value):
        """ Writes to the registry path. """
        hkey = _winreg.CreateKey(self._get_default_regkey(regpath, True),
                                 section)
        _winreg.SetValueEx(hkey, option, 0, value[1], value[0])
        if hkey: _winreg.CloseKey(hkey)


if __name__ == '__main__':

    rc = RegConfig(r"HKEY_LOCAL_MACHINE\SOFTWARE\mysoftware", autowrite=True)
    rc.set('configuration', 'configparser', 0)
    rc.set('configuration', 'regconfig', 'it works')
    rc.set('settings', 'users', ['jack', 'john', 'who else?'])
    
    # Can u store a pickle? yes...however...
    """ Quote - Value lengths are limited by available memory. Long values
        (more than 2048 bytes) should be stored as files with the filenames
        stored in the configuration registry. This helps the registry perform
        efficiently."""
    import pickle
    x = {'hi': 'im going to be pickled...' }
    pick = pickle.dumps(x, pickle.HIGHEST_PROTOCOL)
    rc.set('pickle', 'pickleobject', (pick, _winreg.REG_BINARY))
    rc.write()
    
    #get sections and items
    for section in rc.sections():
        print section
        for item in rc.items(section):
            print '\t', item
            
    # Call this to write to registry path use it to configure different users..
    rc.write(r"HKEY_LOCAL_MACHINE\SOFTWARE\mysoftwareagain")
    
    # let's try reading the data only
    rc = RegConfig(r"HKEY_LOCAL_MACHINE\SOFTWARE\mysoftware")
    
    # let unpickle the pickle
    pick = rc.get('pickle', 'pickleobject')
    print pickle.loads(pick)

Ever wanted to use the registry for you application configurations. Use this class, it's very easy to use and is modelled after RawConfigParser.

1 comment

a 13 years, 11 months ago  # | flag

apply() is deprecated. apply(self._write_reg, (regpath, section, option, sectiondict[option])) should be changed to self._write_reg(regpath, section, option, sectiondict[option])