Patch for PyDO2
Jeroen van Dongen <[email protected]>
| Newsgroups | gmane.comp.web.skunkweb |
|---|---|
| Message-ID | <1069541156.1141.23.camel@localhost> |
Hi, I think I just found a bug in PyDO2. In the __new__ method of _metapydo, we iterate over the namespace to find any class_ or static_ members. When found, the prefix is stripped and the new name is added to the namespace while the old one is removed. Problem seems to be the line: for k, v in namespace.iteritems() ... some code ... del namespace[k] We change namespace, which is a dictionary, which is implemented as a hashtable. Under rare circumstances it apparently can so happen that upon deletion of an entry, a not-yet processed key is rehashed to end up BEFORE the currently processed key and hence is never processed. I bumped into this with a specific class where one of my class_ methods was not converted (it kept the class_ prefix). Any other name would do, even changing the case of one of the characters in the name would do it, except that specific one name. Drove me insane I can tell you that much :) Dumping namespace.keys() at each round of the for-loop showed that at some point the troubled key moved to position 2 in the list produced by keys(). That one was already processed, and hence my class_ method disappeared, never to be seen again in that loop. I've not been able to find any Python docs explaining this or warning against it, but apparently it can happen. Neither have I been able to reproduce it with any other combination of method/attribute names. I think it's a rare treat as it probably requires a collision of hashed keys for it to occur. Anyway, attached you'll find a patch against current cvs. Simple enough solution, but interesting 'feature' imo. Rgds, Jeroen
pydo.diff
(text/x-patch, 526 B)
--- ../PyDO2.py 2003-11-22 23:16:38.000000000 +0100
+++ PyDO2.py 2003-11-22 23:18:15.000000000 +0100
@@ -29,7 +29,8 @@
def __new__(self, cl_name, bases, namespace):
prefix_descriptor_pairs=(('static_', staticmethod),
('class_', classmethod))
- for k, v in namespace.iteritems():
+ ns = namespace.items()
+ for k, v in ns:
for prefix, descriptor in prefix_descriptor_pairs:
lenpre=len(prefix)
if k.startswith(prefix):