Skip to content

Commit 3d95901

Browse files
committed
add missing foreign_object.__getattr__ and fix calling well-known Python methods directly on a foreign object
1 parent e374961 commit 3d95901

File tree

3 files changed

+32
-9
lines changed

3 files changed

+32
-9
lines changed

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
1+
# Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
22
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
33
#
44
# The Universal Permissive License (UPL), Version 1.0
@@ -268,3 +268,13 @@ def test_non_index_array_access():
268268
assert False, "using __getitem__ to access keys of an array-like foreign object should work"
269269
except NotImplementedError as e:
270270
assert "host lookup is not allowed" in str(e)
271+
272+
def test_direct_call_of_truffle_object_methods():
273+
import java
274+
try:
275+
al = java.type("java.util.ArrayList")()
276+
assert al.__len__() == al.size() == len(al)
277+
except IndexError:
278+
assert False, "calling the python equivalents for well-known functions directly should work"
279+
except NotImplementedError as e:
280+
assert "host lookup is not allowed" in str(e)

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/TruffleObjectBuiltins.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2018, Oracle and/or its affiliates.
2+
* Copyright (c) 2017, 2019, Oracle and/or its affiliates.
33
* Copyright (c) 2014, Regents of the University of California
44
*
55
* All rights reserved.
@@ -34,6 +34,7 @@
3434
import static com.oracle.graal.python.nodes.SpecialMethodNames.__DIR__;
3535
import static com.oracle.graal.python.nodes.SpecialMethodNames.__EQ__;
3636
import static com.oracle.graal.python.nodes.SpecialMethodNames.__FLOORDIV__;
37+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__GETATTR__;
3738
import static com.oracle.graal.python.nodes.SpecialMethodNames.__GETITEM__;
3839
import static com.oracle.graal.python.nodes.SpecialMethodNames.__GE__;
3940
import static com.oracle.graal.python.nodes.SpecialMethodNames.__GT__;
@@ -875,6 +876,22 @@ Object doit(TruffleObject object, Object key) {
875876
}
876877
}
877878

879+
@Builtin(name = __GETATTR__, fixedNumOfPositionalArgs = 2)
880+
@GenerateNodeFactory
881+
abstract static class GetattrNode extends PythonBinaryBuiltinNode {
882+
@Child Node readNode = Message.READ.createNode();
883+
@Child PForeignToPTypeNode toPythonNode = PForeignToPTypeNode.create();
884+
885+
@Specialization
886+
protected Object doIt(TruffleObject object, Object key) {
887+
try {
888+
return toPythonNode.executeConvert(ForeignAccess.sendRead(readNode, object, key));
889+
} catch (UnknownIdentifierException | UnsupportedMessageException e) {
890+
throw raise(PythonErrorType.AttributeError, "foreign object %s has no attribute %s", object, key);
891+
}
892+
}
893+
}
894+
878895
@Builtin(name = __SETATTR__, fixedNumOfPositionalArgs = 3)
879896
@GenerateNodeFactory
880897
abstract static class SetattrNode extends UnboxNode {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/call/PythonCallNode.java

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,11 @@
3131
import com.oracle.graal.python.nodes.argument.keywords.KeywordArgumentsNode;
3232
import com.oracle.graal.python.nodes.argument.positional.PositionalArgumentsNode;
3333
import com.oracle.graal.python.nodes.attributes.GetAttributeNode;
34+
import com.oracle.graal.python.nodes.attributes.GetAttributeNode.GetAnyAttributeNode;
3435
import com.oracle.graal.python.nodes.call.PythonCallNodeGen.GetCallAttributeNodeGen;
3536
import com.oracle.graal.python.nodes.call.special.CallBinaryMethodNode;
3637
import com.oracle.graal.python.nodes.call.special.CallTernaryMethodNode;
3738
import com.oracle.graal.python.nodes.call.special.CallUnaryMethodNode;
38-
import com.oracle.graal.python.nodes.call.special.LookupAndCallBinaryNode;
3939
import com.oracle.graal.python.nodes.expression.ExpressionNode;
4040
import com.oracle.graal.python.nodes.frame.ReadGlobalOrBuiltinNode;
4141
import com.oracle.graal.python.nodes.frame.ReadNameNode;
@@ -232,10 +232,9 @@ protected static Node createInvoke() {
232232
Object call(VirtualFrame frame, ForeignInvoke callable,
233233
@Cached("create()") PForeignToPTypeNode fromForeign,
234234
@Cached("create()") BranchProfile keywordsError,
235-
@Cached("create()") BranchProfile nameError,
236235
@Cached("create()") BranchProfile typeError,
237236
@Cached("create()") BranchProfile invokeError,
238-
@Cached("create(__GETATTRIBUTE__)") LookupAndCallBinaryNode getAttrNode,
237+
@Cached("create()") GetAnyAttributeNode getAttrNode,
239238
@Cached("createInvoke()") Node invokeNode) {
240239
Object[] arguments = evaluateArguments(frame);
241240
PKeyword[] keywords = evaluateKeywords(frame);
@@ -245,13 +244,10 @@ Object call(VirtualFrame frame, ForeignInvoke callable,
245244
}
246245
try {
247246
return fromForeign.executeConvert(ForeignAccess.sendInvoke(invokeNode, callable.receiver, callable.identifier, arguments));
248-
} catch (UnknownIdentifierException e) {
249-
nameError.enter();
250-
throw raise(PythonErrorType.NameError, e);
251247
} catch (ArityException | UnsupportedTypeException e) {
252248
typeError.enter();
253249
throw raise(PythonErrorType.TypeError, e);
254-
} catch (UnsupportedMessageException e) {
250+
} catch (UnknownIdentifierException | UnsupportedMessageException e) {
255251
invokeError.enter();
256252
// the interop contract is to revert to READ and then EXECUTE
257253
Object member = getAttrNode.executeObject(callable.receiver, callable.identifier);

0 commit comments

Comments
 (0)