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 | """Slightly magical Win32api Registry -> Dictionary-like-object wrapper"""
from __future__ import generators
import win32api, win32con, cPickle
class RegistryDict(object):
def __init__(self, keyhandle = win32con.HKEY_LOCAL_MACHINE, keypath = [], flags = None):
"""If flags=None, then it will create the key.. otherwise pass a win32con.KEY_* sam"""
keyhandle = None
self.open(keyhandle, keypath, flags)
def massageIncomingRegistryValue((obj, objtype)):
if objtype == win32con.REG_BINARY and obj[:8]=='PyPickle':
obj = obj[8:]
return cPickle.loads(obj)
elif objtype == win32con.REG_NONE:
return None
elif objtype in (win32con.REG_SZ, win32con.REG_EXPAND_SZ, win32con.REG_RESOURCE_LIST, win32con.REG_LINK, win32con.REG_BINARY, win32con.REG_DWORD, win32con.REG_DWORD_LITTLE_ENDIAN, win32con.REG_DWORD_BIG_ENDIAN, win32con.REG_MULTI_SZ):
return obj
raise NotImplementedError, "Registry type 0x%08X not supported" % (objtype,)
massageIncomingRegistryValue = staticmethod(massageIncomingRegistryValue)
def __getitem__(self, item):
item = str(item)
# is it data?
try:
return self.massageIncomingRegistryValue(win32api.RegQueryValueEx(self.keyhandle, item))
except:
pass
# it's probably a key then
try:
return RegistryDict(self.keyhandle, item, win32con.KEY_ALL_ACCESS)
except:
pass
# must not be there
raise KeyError, item
def has_key(self, key):
return self.__contains__(key)
def __contains__(self, key):
try:
self.__getitem__(key)
return 1
except KeyError:
return 0
def copy(self):
return dict(self.iteritems())
def __repr__(self):
return repr(self.copy())
def __str__(self):
return self.__repr__()
def __cmp__(self, other):
return cmp(self.copy(), other)
def __hash__(self):
raise TypeError, "RegistryDict objects are unhashable"
def clear(self):
for k in self.iterkeys():
del self[k]
def iteritems_data(self):
i = 0
# yield data
try:
while 1:
s, obj, objtype = win32api.RegEnumValue(self.keyhandle, i)
yield s, massageRegistryValue((obj, objtype))
i += 1
except:
pass
def iteritems_children(self, access=win32con.KEY_ALL_ACCESS):
i = 0
try:
while 1:
s, obj, objtype = win32api.RegEnumKey(self.keyhandle, i)
yield s, RegistryDict(self.keyhandle, [s], access)
i += 1
except:
pass
def iteritems(self, access=win32con.KEY_ALL_ACCESS):
# yield children
for item in self.iteritems_data():
yield item
for item in self.iteritems_children(access):
yield item
def iterkeys_data(self):
for key, value in self.iteritems_data():
yield key
def iterkeys_children(self, access=win32con.KEY_ALL_ACCESS):
for key, value in self.iteritems_children(access):
yield key
def iterkeys(self):
for key, value in self.iteritems():
yield key
def itervalues_data(self):
for key, value in self.iteritems_data():
yield value
def itervalues_children(self, access=win32con.KEY_ALL_ACCESS):
for key, value in self.iteritems_children(access):
yield value
def itervalues(self, access=win32con.KEY_ALL_ACCESS):
for key, value in self.iteritems(access):
yield value
def items(self, access=win32con.KEY_ALL_ACCESS):
return list(self.iteritems())
def keys(self):
return list(self.iterkeys())
def values(self, access=win32con.KEY_ALL_ACCESS):
return list(self.itervalues(access))
def __delitem__(self, item):
win32api.RegDeleteValue(self.keyhandle, str(item))
def __len__(self):
return len(self.items())
def __iter__(self):
return self.iterkeys()
def popitem(self):
try:
k, v = self.iteritems().next()
del self[k]
return k, v
except StopIteration:
raise KeyError, "RegistryDict is empty"
def get(self,key,default=None):
try:
return self.__getitem__(key)
except:
return default
def setdefault(self,key,default=None):
try:
return self.__getitem__(key)
except:
self.__setitem__(key)
return default
def update(self,d):
for k,v in d.items():
self.__setitem__(k, v)
def __setitem__(self, item, value):
item = str(item)
pyvalue = type(value)
if pyvalue is dict or isinstance(value, RegistryDict):
d = RegistryDict(self.keyhandle, item)
d.clear()
d.update(value)
return
if pyvalue is str:
valuetype = win32con.REG_SZ
elif pyvalue is int:
valuetype = win32con.REG_DWORD
else:
valuetype = win32con.REG_BINARY
value = 'PyPickle' + cPickle.dumps(value)
win32api.RegSetValueEx(self.keyhandle, item, 0, valuetype, value)
def open(self, keyhandle, keypath, flags = None):
if self.keyhandle:
self.close()
if type(keypath) is str:
keypath = keypath.split('\\')
if flags is None:
for subkey in keypath:
keyhandle = win32api.RegCreateKey(keyhandle, subkey)
else:
for subkey in keypath:
keyhandle = win32api.RegOpenKeyEx(keyhandle, subkey, 0, flags)
self.keyhandle = keyhandle
def close(self):
try:
win32api.RegCloseKey(self.keyhandle)
except:
pass
def __del__(self):
self.close()
|
self. missing. class RegistryDict(object): def __init__(self, keyhandle = win32con.HKEY_LOCAL_MACHINE, keypath = [], flags = None): """If flags=None, then it will create the key.. otherwise pass a win32con.KEY_* sam""" self.keyhandle = None # THIS should be this way, should it not? self.open(keyhandle, keypath, flags)
otherwise self.open leads to "... has no attribut "keyhandle")
Updates and fixes. I've had occasion to use this class, and have found it quite nice. There are a few changes I've had to make, though:
The previous comment's correction, adding "self." to the first line of __init__ to make keyhandle an ivar, is correct.
Changed the definition of __cmp__ to the following:
Changed the definition of clear to the following:
In iteritems_data, the call to "massage..." should be:
In iteritems_children, changed the RegEnumKey line to read:
The __delitem__ method only deletes string values. I changed it to the following:
Note the use of .clear() to delete the whole tree under the subkey. A more cautious approach would be to require the client code to manage that.
In the "open" method, the "else" clause is one level too deep. The "else" should be paired with "if flags is None:"
If desired, I can put a patch or the whole file somewhere around here.
Oops! one more fix. I just ran across another subtle bug: the dictionary key '' (the empty string) must mean the "default value" of a registry key, but it was returning a copy of "self" if there was no default value. The following updated __getitem__ fixes this:
Requests. This looks like a very cool recipe. It would help though to have the updated/fixed version of this recipe posted in it's entirety. Cutting and pasting the fixes from the comments is somewhat error prone. It'd also be nice if some simple test cases were constructed to act as a demonstration of the usage of this module.
I second that. I agree with the previous post. Before or after applying the mentioned bug fixes, I've never gotten this to work. Without clear examples and tests in a main function like many other recipes, I wouldn't be sure if I were using it properly anyway. This looks like a very useful and promising recipe, but it definitely could be improved with unit tests and some refactoring.
Fixed script, downloadable. You can download the entire script with the fixes above from:
http://mikebabcock.ca/code/registrydict.py
You're welcome :)
PS, I'll update this with any other patches/fixes I notice from here. I made one change myself as well, by removing an unnecessary temporary variable in one of the other patches.
Still not quite right. This script at http://mikebabcock.ca/code/registrydict.py also needs a wee fix (I've emailed the author about it):
Line26: def __getitem__(self, item):
should be (I think):
def __getitem__(self, key)
Now, I wish someone could show me how it works!
-ross
Save unicode as REG_SZ. May be worth putting
</pre>
__delitem__ rewrite. I've rewritten __delitem__ as it just plain didn't work...
It's got slightly different behaviour: the old version looked like it was attempting to silently fail if you deleted a key that didn't exist.
This version will raise a keyerror, which is more consistent with the behaviour of standard dictionaries, i.e.
Will raise a keyerror, not fail silently.
Updated my hosted copy. http://mikebabcock.ca/code/registrydict.py has been updated appropriately as per the updates above.
doesnt work. I try to run this script with no success. Is this right?: Should be printed subkeys this way? Neither of these is working :-(
Moreover, here: http://mikebabcock.ca/code/registrydict.py is just part of updated script, so I am not sure, if I collect the right script of last version.
Thank you very much
Updated version available in a new recipe. I've just submitted a new recipe, number 551761, with all the corrections applied; it's awaiting approval.
what will this call return, if the keyPath in the below method call doesnt exist, then what would be return value of function call? rd = RegistryDict(win32con.HKEY_LOCAL_MACHINE, KeyPath)
so basically i first want to find if key path exists. if yes, then want to find the value of some key at this key path.
thanks, Rahul