[Python-Dev] Std test failures on WIndows: test_compare, test_minidom
Tim Peters
tim.one@home.com
Tue, 2 Jan 2001 19:30:26 -0500
[Neil]
> They do on my box:
>> Python 2.0 (#19, Nov 21 2000, 18:13:04)
> [GCC 2.95.2 20000220 (Debian GNU/Linux)] on linux2
> Type "copyright", "credits" or "license" for more information.
> >>> cmp(1, None)
> -78
Well, who cares about your silly box <wink>? Messier than I thought! Yes,
Windows strcmp is always in {-1, 0, 1}. Rather than run tests, here's the
tail end of MS's strcmp.c:
if ( ret < 0 )
ret = -1 ;
else if ( ret > 0 )
ret = 1 ;
return( ret );
Wasted cycles and stupid formatting <wink>.
> ...
> AFAICT, the problem is that instances without a comparison method can
> compare larger or smaller than numbers depending on where in memory
> the objects are stored.
If so, that's a bug ... OK, it *is* a bug, at least in current CVS. Did you
cause that, or was it always this way? I was able to provoke this badness:
>>> j < c < i
1
>>> j < i
0
>>>
i.e. it violates transitivity, and that's never supposed to happen in the
absence of user-supplied __cmp__. Here c is an instance of "class C: pass",
and i and j are ints.
>>> type(i), type(j), type(c)
(<type 'int'>, <type 'int'>, <type 'instance'>)
>>> i, j, c
(999999, 1000000, <__main__.C instance at 00791B7C>)
>>> id(i), id(j), id(c)
(7941572, 7744676, 7936892)
>>>
Guido thought he fixed this kind of stuff once (and I believed him <wink>)
by treating all numbers as if they had type name "" (i.e., yes, an empty
string) when compared to non-numbers. Then the usual "mixed-type
comparisons in the absence of __cmp__ compare via type name string" rule
ensured that numbers would always compare "less than" instances of any other
type. That's the intent of the tail end:
else if (vtp->tp_as_number != NULL)
vname = "";
else if (wtp->tp_as_number != NULL)
wname = "";
/* Numerical types compare smaller than all other types */
return strcmp(vname, wname);
of PyObject_Compare. So, in the example above, we *should* have
i < c == 1
j < c == 1
j < c < i == 0
Unfortunately, we actually have
i < c == 0
in that example. We're apparently not getting to the "number hack" code
because c is an instance, and I'll confess up front that my eyes always
glazed over long before I got to PyInstance_HalfBinOp <0.half wink>.
Whatever, there's at least one bug somewhere in that path! We should have
n < i == 1 for any numeric type n and any non-numeric type i (in the absence
of user-defined __cmp__).