Released: Python 2.6.8, 2.7.3, 3.1.5, and 3.2.3
mail.python.org
mail.python.org
Honestly, if the spec doesn't guarantee that iteration will be in order, no one has a right to complain if it actually isn't with this release.
In the C++ world I come from, the Spec is treated as being holy. You don't write code that invokes undefined behavior or relies on unspecified behavior. If you do, you're on your own and no one will touch your code with a ten foot pole if they can help it. (Unless, of course, there really is no other way due to your compiler, etc. etc. in which case you litter the comments with warnings)
In this particular case, it's a simple matter of choosing the right data structure to suit your needs, or sorting contents before accessing them if you truly require in-order iteration.
IIRC there were also larger concerns about poorly implemented systems that depended on hash() being stable for persistence reasons. I don't know the details of that, as I appreciate the nod to backwards compatibility and not breaking people on a bugfix release.
That's ridiculous.
>You don't write code that invokes undefined behavior or relies on unspecified behavior.
This happens all the time, and not only is code written that relies on unspecified behavior, vendors maintain backward compatibility for programs that do this.
http://www.joelonsoftware.com/articles/APIWar.html
> If you do, you're on your own and no one will touch your code with a ten foot pole if they can help it.
Not really. If you do this and you're a huge success, you're the center of the universe. If you do this and no one notices, you're fucked.
1: http://www.cs.rice.edu/~scrosby/hash/CrosbyWallach_UsenixSec...
[1] http://perldoc.perl.org/perlsec.html#Algorithmic-Complexity-...
And they are fixing it, so why say "it must be fixed"?
23.1 --- a/Modules/datetimemodule.c
23.2 +++ b/Modules/datetimemodule.c
23.3 @@ -2566,10 +2566,12 @@ generic_hash(unsigned char *data, int len)
23.4 register long x;
23.5
23.6 p = (unsigned char *) data;
23.7 - x = *p << 7;
23.8 + x = _Py_HashSecret.prefix;
23.9 + x ^= *p << 7;
23.10 while (--len >= 0)
23.11 x = (1000003*x) ^ *p++;
23.12 x ^= len;
23.13 + x ^= _Py_HashSecret.suffix;
23.14 if (x == -1)
23.15 x = -2;
The hash computation is initialized with a global random value, and a second one is xored in at the end. (-1 isn't allowed as a hash, since it's the sentinel value that indicates the hash hasn't been computed yet.)