[Ironpython-users] Why does this happen?

Slide slide.o.mix at gmail.com
Sat Mar 31 06:00:41 CEST 2012


The types that are being compared are as follows:

class CmpErr:
    "Dummy element that always raises an error during comparison"
    def __cmp__(self, other):
        raise ZeroDivisionError

And an Int32. The bisect test creates a list of the CmpErr objects and
then tries to insert the number 10, so a CmpErr instance (OldInstance)
is being compared to an Int32.

The DebugView IS much easier and explains a lot about what is being
generated. I need to review the semantics for the rich comparison in
the CPython code, I was looking at it earlier today on my phone (which
ends up not being a very good way to view code). I'll compare it to
what the IronPython code is doing.

Here is some code that reproduces the issue. On CPython this code
prints "Pass" and on IronPython it prints "Fail"


import bisect

class CmpErr:
    "Dummy element that always raises an error during comparison"
    def __cmp__(self, other):
        raise ZeroDivisionError
		
seq = [CmpErr(), CmpErr(), CmpErr()]

try:
    bisect.bisect_left(seq, 10)
except ZeroDivisionError:
	print "Pass"
else:
	print "Fail"

I'm going to file an issue on this, because its looks like a
compatibility problem.

Thanks,

slide

On Fri, Mar 30, 2012 at 5:26 PM, Dino Viehland <dinov at microsoft.com> wrote:
> First off just to make your life easier in the future the DebugView
> property on the expression is much better than the other view - it produces
> something that looks like C#.
>
> Ok, I think the types are actually different and the LHS is succeeding on
> one of ==, <, or >.  I say that because in MakeSortComparisonRule we do:
>
> if (xType == yType && cTarget != SlotOrFunction.Empty) {
>
> And if they were both old instances we'd do the ShouldCoerce check (which
> would be true) and we'd generate the code which looks like the list.sort()
> case.  You can check xType and yType in the debugger.  Better yet you can
> drill into the meta objects in the types array and see the actual values the
> rule is being created for.
>
> The problem type I think is xType and it's probably some IronPython runtime
> type (because it defines __eq__ as well as op_LessThan and op_GreaterThan).
> But I have no guesses as to what it is - every type I tried still went down the
> __cmp__ path.
>
> So look at xType and those methods...  If it somehow is really an OldInstance
> then something really strange is going on and it'd be interesting to see if xType
> and yType are somehow different when they should be the same.
>
>> -----Original Message-----
>> From: ironpython-users-bounces+dinov=microsoft.com at python.org
>> [mailto:ironpython-users-bounces+dinov=microsoft.com at python.org] On
>> Behalf Of Slide
>> Sent: Friday, March 30, 2012 5:08 AM
>> To: ironpython-users at python.org
>> Subject: Re: [Ironpython-users] Why does this happen?
>>
>> Here's the expression for my case
>>
>> {IIF(CallSiteBinder(Convert($arg0).__eq__(Convert(Unbox($arg1)))), 0,
>> IIF(CallSiteBinder(op_LessThan(Convert($arg0),
>> Convert(Unbox($arg1)))), -1,
>> IIF(CallSiteBinder(op_GreaterThan(Convert($arg0),
>> Convert(Unbox($arg1)))), 1, IIF((Not(((coerceResult =
>> Convert($arg0).__coerce__(value(IronPython.Runtime.CodeContext),
>> Convert(Unbox($arg1)))) Is OldInstance)) AndAlso ((coerceTuple =
>> ValidateCoerceResult(coerceResult)) != null)), {var callres; ... },
>> Convert(Convert($arg0).__cmp__(value(IronPython.Runtime.CodeContext),
>> Convert(Unbox($arg1))))))))}
>>
>> Here is the expression for the List.sort case
>>
>> {IIF((Not(((coerceResult =
>> Convert($arg0).__coerce__(value(IronPython.Runtime.CodeContext),
>> Convert($arg1))) Is OldInstance)) AndAlso ((coerceTuple =
>> ValidateCoerceResult(coerceResult)) != null)), {var callres; ... },
>> Convert(Convert($arg0).__cmp__(value(IronPython.Runtime.CodeContext),
>> Convert($arg1))))}
>>
>> Is there more information from the DynamicMetaObject that would be helpful?
>>
>> Thanks for your time, I appreciate you helping out those like me who don't know
>> much about the internals of IronPython.
>>
>> slide
>>
>>
>> On Thu, Mar 29, 2012 at 10:07 PM, Dino Viehland <dinov at microsoft.com>
>> wrote:
>> > I'm actually not sure why it would happen.  The only thought I have is
>> > if you're only doing one comparison, and comparing the same instance,
>> > there's an object identity test which would prevent the __cmp__ call
>> > from happening.  But I'm guessing that's not what's happening...
>> >
>> > Can you put a breakpoint in PythonProtocol.Operations.cs in
>> > MakeSortComparisonRule and see what's returned from the call to
>> > bodybuilder.GetMetaObject?  That'll give you the full expression tree
>> > of the rule for doing the comparison.  There's supposed to be some
>> > calls to __cmp__ in there - if they're not there maybe what is will provide some
>> enlightenment.
>> >
>> >> -----Original Message-----
>> >> From: ironpython-users-bounces+dinov=microsoft.com at python.org
>> >> [mailto:ironpython-users-bounces+dinov=microsoft.com at python.org] On
>> >> Behalf Of Slide
>> >> Sent: Thursday, March 29, 2012 8:49 PM
>> >> To: ironpython-users at python.org
>> >> Subject: Re: [Ironpython-users] Why does this happen?
>> >>
>> >> Is Dino on vacation? He usually has good answers for these sorts of
>> >> things :-) I still can't get the callsite to end up calling __cmp__
>> >> like List.sort does. I'm not sure why that is the case. It looks like
>> >> even the Python version of bisect has a similar issue though (it
>> >> never calls __cmp__ either), so I think there is a bug somewhere.
>> >>
>> >> On Sat, Mar 24, 2012 at 8:51 PM, Slide <slide.o.mix at gmail.com> wrote:
>> >> >
>> >> > I am implementing a module in C#. This module does some comparison
>> >> operations. One of the tests for this module has something like the following:
>> >> >
>> >> > class CmpErr:
>> >> >     def __cmp__(self, other):
>> >> >         raise ZeroDivisionError
>> >> >
>> >> > x = [CmpErr(), CmpErr(), CmpErr()]
>> >> > cSharpMethod(x)
>> >> >
>> >> > Inside cSharpMethod is when I do the comparison. The way I am doing
>> >> > the comparison is taken from how its done in List.cs
>> >> >
>> >> > IComparer comparer =
>> >> > PythonContext.GetContext(context).GetComparer(null,
>> >> > GetComparisonType(context, list));
>> >> >
>> >> > Then I call comparer.Compare on the two items. In List.sort, this
>> >> > eventually
>> >> calls the __cmp__ method if I try adding a call to x.sort() instead
>> >> of cSharpMethod, but from inside cSharpMethod, __cmp__ is never
>> >> called and I can't figure out why.
>> >> >
>> >> > Any ideas on why this might be occuring?
>> >> >
>> >> > Thanks,
>> >> >
>> >> > slide
>> >> >
>> >> > --
>> >> > Website: http://earl-of-code.com
>> >>
>> >>
>> >>
>> >>
>> >> --
>> >> Website: http://earl-of-code.com
>> >> _______________________________________________
>> >> Ironpython-users mailing list
>> >> Ironpython-users at python.org
>> >> http://mail.python.org/mailman/listinfo/ironpython-users
>> >
>> >
>>
>>
>>
>> --
>> Website: http://earl-of-code.com
>> _______________________________________________
>> Ironpython-users mailing list
>> Ironpython-users at python.org
>> http://mail.python.org/mailman/listinfo/ironpython-users
>>
>>
>
>
>



-- 
Website: http://earl-of-code.com


More information about the Ironpython-users mailing list