Skip to content

Commit d19ce57

Browse files
committed
use lookupSpecial in enter, exit, length_hint, round, bytes special methods
1 parent 47ab374 commit d19ce57

File tree

6 files changed

+106
-33
lines changed

6 files changed

+106
-33
lines changed

graalpython/com.oracle.graal.python.test/src/tests/test_bytes.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -722,6 +722,34 @@ def test_bytes_mod():
722722
raised = True
723723
assert raised
724724

725+
def test__bytes__():
726+
class C: pass
727+
setattr(C, "__bytes__", bytes)
728+
assert bytes(C()) == b''
729+
730+
class C(int): pass
731+
setattr(C, "__bytes__", bytes)
732+
assert bytes(C()) == b''
733+
assert bytes(C(1)) == b''
734+
735+
setattr(C, "__bytes__", complex)
736+
raised = False
737+
try:
738+
bytes(C(1))
739+
except(TypeError):
740+
raised = True
741+
assert raised
742+
743+
def b(o):
744+
return b'abc'
745+
746+
class BA(bytearray): pass
747+
setattr(BA, "__bytes__", b)
748+
assert bytes(BA(b'cde')) == b'abc'
749+
750+
class BAA(BA): pass
751+
assert bytes(BAA(b'cde')) == b'abc'
752+
725753
class BaseLikeBytes:
726754

727755
def test_maketrans(self):

graalpython/com.oracle.graal.python.test/src/tests/test_float.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,47 @@ def test___round__(self):
8585
pass
8686
else:
8787
assert False, "rounding with a float should have raised"
88+
89+
class F:
90+
pass
91+
92+
setattr(F, "__round__", round)
93+
try:
94+
round(F())
95+
except TypeError:
96+
pass
97+
else:
98+
assert False, "rounding with a non-float should have raised"
99+
100+
class F(float):
101+
pass
102+
103+
setattr(F, "__round__", round)
104+
try:
105+
round(F(4.2))
106+
except TypeError:
107+
pass
108+
else:
109+
assert False, "rounding with only 1 arg should have raised"
110+
111+
round(F(4.2), 1)
112+
113+
def r(o):
114+
return(42)
115+
116+
setattr(F, "__round__", r)
117+
assert round(F(4.2)) == 42
118+
119+
l = []
120+
def r(arg1, arg2):
121+
l.append(arg1)
122+
l.append(arg2)
123+
return(42)
124+
125+
setattr(F, "__round__", r)
126+
assert round(F(4.2), 2) == 42
127+
assert l[0] == 4.2
128+
assert l[1] == 2
88129

89130
def test_magic_rounding(self):
90131
class C():

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@
7474
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__SLOTS__;
7575
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__WEAKREF__;
7676
import static com.oracle.graal.python.nodes.SpecialMethodNames.DECODE;
77-
import static com.oracle.graal.python.nodes.SpecialMethodNames.__BYTES__;
7877
import static com.oracle.graal.python.nodes.SpecialMethodNames.__COMPLEX__;
7978
import static com.oracle.graal.python.nodes.SpecialMethodNames.__EQ__;
8079
import static com.oracle.graal.python.nodes.SpecialMethodNames.__FLOAT__;
@@ -185,6 +184,7 @@
185184
import com.oracle.graal.python.nodes.SpecialAttributeNames;
186185
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__QUALNAME__;
187186
import com.oracle.graal.python.nodes.SpecialMethodNames;
187+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__BYTES__;
188188
import com.oracle.graal.python.nodes.attributes.GetAttributeNode;
189189
import com.oracle.graal.python.nodes.attributes.GetAttributeNode.GetAnyAttributeNode;
190190
import com.oracle.graal.python.nodes.attributes.LookupAttributeInMRONode;
@@ -295,29 +295,30 @@ public PBytes byteDone(VirtualFrame frame, Object cls, PNone source, PNone encod
295295
return factory().createBytes(cls, PythonUtils.EMPTY_BYTE_ARRAY);
296296
}
297297

298-
@Specialization(guards = "hasByteAttr(frame, source, lib)", limit = "3")
298+
@Specialization(guards = "hasByteAttr(source, lookupBytes, lib)", limit = "3")
299299
public PBytes hasBytesAttr(VirtualFrame frame, Object cls, Object source, @SuppressWarnings("unused") PNone encoding, @SuppressWarnings("unused") PNone errors,
300300
@Cached ConditionProfile errorProfile,
301301
@Cached BytesNodes.ToBytesNode toBytesNode,
302302
@Cached ConditionProfile isBytes,
303303
@Cached IsBuiltinClassProfile isClassProfile,
304+
@SuppressWarnings("unused") @Cached("create(__BYTES__)") LookupAttributeInMRONode lookupBytes,
305+
@SuppressWarnings("unused") @Cached("create(__BYTES__)") LookupSpecialMethodNode lookupSpecialBytes,
304306
@SuppressWarnings("unused") @CachedLibrary("source") PythonObjectLibrary lib) {
305-
Object b = lib.lookupAttribute(source, frame, __BYTES__);
306-
assert b != PNone.NO_VALUE;
307-
Object bytes = lib.lookupAndCallRegularMethod(source, frame, __BYTES__);
307+
Object bytes = lib.lookupAndCallSpecialMethod(source, frame, __BYTES__);
308+
308309
if (errorProfile.profile(!(bytes instanceof PBytesLike))) {
309-
throw raise(TypeError, ErrorMessages.RETURNED_NONBYTES, "__bytes__", b);
310+
throw raise(TypeError, ErrorMessages.RETURNED_NONBYTES, __BYTES__, bytes);
310311
}
311-
312312
if (isBytes.profile(bytes instanceof PBytes && isClassProfile.profileIsAnyBuiltinClass(cls))) {
313313
return (PBytes) bytes;
314314
}
315315
return factory().createBytes(cls, toBytesNode.execute(frame, bytes));
316316
}
317317

318-
@Specialization(guards = {"!isNone(source)", "!canUseByteAttr(frame, source, lib, encoding, errors)"}, limit = "3")
318+
@Specialization(guards = {"!isNone(source)", "!canUseByteAttr(source, lookupBytes, lib, encoding, errors)"}, limit = "3")
319319
public PBytes doInit(VirtualFrame frame, Object cls, Object source, Object encoding, Object errors,
320320
@Cached BytesNodes.BytesInitNode toBytesNode,
321+
@SuppressWarnings("unused") @Cached("create(__BYTES__)") LookupAttributeInMRONode lookupBytes,
321322
@SuppressWarnings("unused") @CachedLibrary("source") PythonObjectLibrary lib) {
322323
return factory().createBytes(cls, new ByteSequenceStorage(toBytesNode.execute(frame, source, encoding, errors)));
323324
}
@@ -327,12 +328,12 @@ public PBytes sourceNone(Object cls, Object source, @SuppressWarnings("unused")
327328
throw raise(TypeError, ErrorMessages.CANNOT_CONVERT_P_OBJ_TO_S, source, cls);
328329
}
329330

330-
protected static boolean canUseByteAttr(VirtualFrame frame, Object object, PythonObjectLibrary lib, Object encoding, Object errors) {
331-
return PGuards.isNoValue(encoding) && PGuards.isNoValue(errors) && hasByteAttr(frame, object, lib);
331+
protected static boolean canUseByteAttr(Object object, LookupAttributeInMRONode lookupBytes, PythonObjectLibrary lib, Object encoding, Object errors) {
332+
return PGuards.isNoValue(encoding) && PGuards.isNoValue(errors) && hasByteAttr(object, lookupBytes, lib);
332333
}
333334

334-
protected static boolean hasByteAttr(VirtualFrame frame, Object object, PythonObjectLibrary lib) {
335-
return lib.lookupAttribute(object, frame, __BYTES__) != PNone.NO_VALUE;
335+
protected static boolean hasByteAttr(Object object, LookupAttributeInMRONode lookupBytes, PythonObjectLibrary lib) {
336+
return lookupBytes.execute(lib.getLazyPythonClass(object)) != PNone.NO_VALUE;
336337
}
337338
}
338339

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@
119119
import com.oracle.graal.python.nodes.PGuards;
120120
import com.oracle.graal.python.nodes.PRaiseNode;
121121
import com.oracle.graal.python.nodes.SpecialMethodNames;
122+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__ROUND__;
122123
import com.oracle.graal.python.nodes.argument.ReadArgumentNode;
123124
import com.oracle.graal.python.nodes.attributes.DeleteAttributeNode;
124125
import com.oracle.graal.python.nodes.attributes.GetAttributeNode.GetAnyAttributeNode;
@@ -1729,16 +1730,16 @@ private static String newString(byte[] bytes) {
17291730
@Builtin(name = ROUND, minNumOfPositionalArgs = 1, parameterNames = {"number", "ndigits"})
17301731
@GenerateNodeFactory
17311732
public abstract static class RoundNode extends PythonBuiltinNode {
1732-
@Specialization
1733+
@Specialization(limit = "1")
17331734
Object round(VirtualFrame frame, Object x, @SuppressWarnings("unused") PNone n,
1734-
@Shared("callNode") @Cached("create(__ROUND__)") LookupAndCallBinaryNode callNode) {
1735-
return callNode.executeObject(frame, x, PNone.NONE);
1735+
@SuppressWarnings("unused") @CachedLibrary("x") PythonObjectLibrary lib) {
1736+
return lib.lookupAndCallSpecialMethod(x, frame, __ROUND__);
17361737
}
17371738

1738-
@Specialization(guards = "!isNoValue(n)")
1739+
@Specialization(guards = "!isNoValue(n)", limit = "1")
17391740
Object round(VirtualFrame frame, Object x, Object n,
1740-
@Shared("callNode") @Cached("create(__ROUND__)") LookupAndCallBinaryNode callNode) {
1741-
return callNode.executeObject(frame, x, n);
1741+
@SuppressWarnings("unused") @CachedLibrary("x") PythonObjectLibrary lib) {
1742+
return lib.lookupAndCallSpecialMethod(x, frame, __ROUND__, n);
17421743
}
17431744
}
17441745

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/iterator/IteratorNodes.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
import com.oracle.graal.python.nodes.attributes.LookupAttributeInMRONode;
5656
import com.oracle.graal.python.nodes.attributes.LookupInheritedAttributeNode;
5757
import com.oracle.graal.python.nodes.call.special.CallUnaryMethodNode;
58+
import com.oracle.graal.python.nodes.call.special.LookupSpecialMethodNode;
5859
import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile;
5960
import com.oracle.graal.python.runtime.exception.PException;
6061
import com.oracle.truffle.api.dsl.Cached;
@@ -96,7 +97,7 @@ int length(VirtualFrame frame, Object iterable,
9697
@CachedLibrary("iterable") PythonObjectLibrary plib,
9798
@CachedLibrary(limit = "3") PythonObjectLibrary toInt,
9899
@Cached("create(__LEN__)") LookupAttributeInMRONode lenNode,
99-
@Cached("create(__LENGTH_HINT__)") LookupAttributeInMRONode lenHintNode,
100+
@Cached("create(__LENGTH_HINT__)") LookupSpecialMethodNode lenHintNode,
100101
@Cached CallUnaryMethodNode dispatchGetattribute,
101102
@Cached IsBuiltinClassProfile errorProfile,
102103
@Cached ConditionProfile hasLenProfile,
@@ -123,7 +124,7 @@ int length(VirtualFrame frame, Object iterable,
123124
}
124125
}
125126
}
126-
Object attrLenHintObj = lenHintNode.execute(clazz);
127+
Object attrLenHintObj = lenHintNode.execute(frame, clazz, iterable);
127128
if (hasLenghtHintProfile.profile(attrLenHintObj != PNone.NO_VALUE)) {
128129
Object len = null;
129130
try {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/WithNode.java

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,15 @@
3131
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
3232
import com.oracle.graal.python.builtins.objects.PNone;
3333
import com.oracle.graal.python.builtins.objects.exception.PBaseException;
34-
import com.oracle.graal.python.builtins.objects.function.PKeyword;
34+
import com.oracle.graal.python.builtins.objects.object.PythonObjectLibrary;
3535
import com.oracle.graal.python.builtins.objects.traceback.GetTracebackNode;
3636
import com.oracle.graal.python.builtins.objects.traceback.LazyTraceback;
3737
import com.oracle.graal.python.builtins.objects.traceback.PTraceback;
3838
import com.oracle.graal.python.nodes.ErrorMessages;
3939
import com.oracle.graal.python.nodes.PRaiseNode;
40-
import com.oracle.graal.python.nodes.attributes.LookupInheritedAttributeNode;
41-
import com.oracle.graal.python.nodes.call.CallNode;
40+
import com.oracle.graal.python.nodes.call.special.CallQuaternaryMethodNode;
41+
import com.oracle.graal.python.nodes.call.special.CallUnaryMethodNode;
42+
import com.oracle.graal.python.nodes.call.special.LookupSpecialMethodNode;
4243
import com.oracle.graal.python.nodes.expression.CoerceToBooleanNode;
4344
import com.oracle.graal.python.nodes.expression.ExpressionNode;
4445
import com.oracle.graal.python.nodes.frame.WriteNode;
@@ -55,10 +56,11 @@ public class WithNode extends ExceptionHandlingStatementNode {
5556
@Child private StatementNode body;
5657
@Child private WriteNode targetNode;
5758
@Child private ExpressionNode withContext;
58-
@Child private LookupInheritedAttributeNode enterGetter = LookupInheritedAttributeNode.create(__ENTER__);
59-
@Child private LookupInheritedAttributeNode exitGetter = LookupInheritedAttributeNode.create(__EXIT__);
60-
@Child private CallNode enterDispatch = CallNode.create();
61-
@Child private CallNode exitDispatch = CallNode.create();
59+
@Child private LookupSpecialMethodNode enterSpecialGetter = LookupSpecialMethodNode.create(__ENTER__);
60+
@Child private LookupSpecialMethodNode exitSpecialGetter = LookupSpecialMethodNode.create(__EXIT__);
61+
@Child private PythonObjectLibrary objectLibrary = PythonObjectLibrary.getFactory().createDispatched(1);
62+
@Child private CallUnaryMethodNode enterDispatch = CallUnaryMethodNode.create();
63+
@Child private CallQuaternaryMethodNode exitDispatch = CallQuaternaryMethodNode.create();
6264
@Child private CoerceToBooleanNode toBooleanNode = CoerceToBooleanNode.createIfTrueNode();
6365
@Child private GetClassNode getClassNode = GetClassNode.create();
6466
@Child private PRaiseNode raiseNode;
@@ -105,12 +107,12 @@ private PRaiseNode getRaiseNode() {
105107
@Override
106108
public void executeVoid(VirtualFrame frame) {
107109
Object withObject = getWithObject(frame);
108-
Object enterCallable = enterGetter.execute(withObject);
110+
Object enterCallable = enterSpecialGetter.execute(frame, objectLibrary.getLazyPythonClass(withObject), withObject);
109111
if (enterCallable == PNone.NO_VALUE) {
110112
noEnter.enter();
111113
throw getRaiseNode().raise(PythonBuiltinClassType.AttributeError, ErrorMessages.OBJ_P_HAS_NO_ATTR_S, withObject, __ENTER__);
112114
}
113-
Object exitCallable = exitGetter.execute(withObject);
115+
Object exitCallable = exitSpecialGetter.execute(frame, objectLibrary.getLazyPythonClass(withObject), withObject);
114116
if (exitCallable == PNone.NO_VALUE) {
115117
noExit.enter();
116118
throw getRaiseNode().raise(PythonBuiltinClassType.AttributeError, ErrorMessages.OBJ_P_HAS_NO_ATTR_S, withObject, __EXIT__);
@@ -154,14 +156,14 @@ protected void doBody(VirtualFrame frame) {
154156
* reset the exception state.
155157
*/
156158
protected void doLeave(VirtualFrame frame, Object withObject, Object exitCallable) {
157-
exitDispatch.execute(frame, exitCallable, new Object[]{withObject, PNone.NONE, PNone.NONE, PNone.NONE}, PKeyword.EMPTY_KEYWORDS);
159+
exitDispatch.execute(frame, exitCallable, withObject, PNone.NONE, PNone.NONE, PNone.NONE);
158160
}
159161

160162
/**
161163
* Call the __enter__ method
162164
*/
163165
protected void doEnter(VirtualFrame frame, Object withObject, Object enterCallable) {
164-
applyValues(frame, enterDispatch.execute(frame, enterCallable, new Object[]{withObject}, PKeyword.EMPTY_KEYWORDS));
166+
applyValues(frame, enterDispatch.executeObject(frame, enterCallable, withObject));
165167
}
166168

167169
/**
@@ -178,8 +180,7 @@ protected void handleException(VirtualFrame frame, Object withObject, Object exi
178180
// If exit handler returns 'true', suppress
179181
boolean handled;
180182
try {
181-
Object returnValue = exitDispatch.execute(frame, exitCallable,
182-
new Object[]{withObject, type, caughtException, tb != null ? tb : PNone.NONE}, PKeyword.EMPTY_KEYWORDS);
183+
Object returnValue = exitDispatch.execute(frame, exitCallable, withObject, type, caughtException, tb != null ? tb : PNone.NONE);
183184
handled = toBooleanNode.executeBoolean(frame, returnValue);
184185
} catch (PException handlerException) {
185186
tryChainExceptionFromHandler(handlerException, pException);

0 commit comments

Comments
 (0)