@@ -1534,6 +1534,15 @@ Object fail(LazyPythonClass cls, Object arg, Object base) {
1534
1534
1535
1535
@ Specialization (guards = {"isNoValue(base)" , "!isNoValue(obj)" , "!isHandledType(obj)" })
1536
1536
Object createIntGeneric (VirtualFrame frame , LazyPythonClass cls , Object obj , @ SuppressWarnings ("unused" ) PNone base ) {
1537
+ // This method (together with callInt and callIndex) reflects the logic of PyNumber_Long
1538
+ // in CPython. We don't use PythonObjectLibrary here since the original CPython function
1539
+ // does not use any of the conversion functions (such as _PyLong_AsInt or
1540
+ // PyNumber_Index) either, but it reimplements the logic in a slightly different way
1541
+ // (e.g. trying __int__ before __index__ whereas _PyLong_AsInt does it the other way)
1542
+ // and also with specific exception messages which are expected by Python unittests.
1543
+ // This unfortunately means that this method relies on the internal logic of NO_VALUE
1544
+ // return values representing missing magic methods which should be ideally hidden
1545
+ // by PythonObjectLibrary.
1537
1546
Object result = callInt (frame , obj );
1538
1547
if (result == PNone .NO_VALUE ) {
1539
1548
result = callIndex (frame , obj );
@@ -1562,10 +1571,6 @@ protected static boolean isIntegerType(Object obj) {
1562
1571
return PGuards .isBoolean (obj ) || PGuards .isInteger (obj ) || PGuards .isPInt (obj );
1563
1572
}
1564
1573
1565
- protected static boolean isIntegerTypeOrNoValue (Object obj ) {
1566
- return obj == PNone .NO_VALUE || isIntegerType (obj );
1567
- }
1568
-
1569
1574
protected static boolean isHandledType (Object obj ) {
1570
1575
return PGuards .isInteger (obj ) || obj instanceof Double || obj instanceof Boolean || PGuards .isString (obj ) || PGuards .isBytes (obj ) || obj instanceof PythonNativeVoidPtr ;
1571
1576
}
@@ -1575,12 +1580,14 @@ protected static FloatBuiltins.IntNode createFloatInt() {
1575
1580
}
1576
1581
1577
1582
private Object callInt (VirtualFrame frame , Object obj ) {
1583
+ // The case when the result is NO_VALUE (i.e. the object does not provide __int__)
1584
+ // is handled in createIntGeneric
1578
1585
if (callIntNode == null ) {
1579
1586
CompilerDirectives .transferToInterpreterAndInvalidate ();
1580
1587
callIntNode = insert (LookupAndCallUnaryNode .create (__INT__ ));
1581
1588
}
1582
1589
Object result = callIntNode .executeObject (frame , obj );
1583
- if (! isIntegerTypeOrNoValue (result )) {
1590
+ if (result != PNone . NO_VALUE && ! isIntegerType (result )) {
1584
1591
throw raise (TypeError , ErrorMessages .RETURNED_NON_INT , "__int__" , result );
1585
1592
}
1586
1593
return result ;
@@ -1592,7 +1599,9 @@ private Object callIndex(VirtualFrame frame, Object obj) {
1592
1599
callIndexNode = insert (LookupAndCallUnaryNode .create (__INDEX__ ));
1593
1600
}
1594
1601
Object result = callIndexNode .executeObject (frame , obj );
1595
- if (!isIntegerTypeOrNoValue (result )) {
1602
+ // the case when the result is NO_VALUE (i.e. the object does not provide __index__)
1603
+ // is handled in createIntGeneric
1604
+ if (result != PNone .NO_VALUE && !isIntegerType (result )) {
1596
1605
throw raise (TypeError , ErrorMessages .RETURNED_NON_INT , "__index__" , result );
1597
1606
}
1598
1607
return result ;
0 commit comments