Skip to content

Commit 20014e8

Browse files
committed
[GR-10018] Missing functionality: towards py4j (0.10.7)
PullRequest: graalpython/181
2 parents 0fe6726 + bd132cf commit 20014e8

File tree

14 files changed

+208
-41
lines changed

14 files changed

+208
-41
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
This changelog summarizes major changes between GraalVM versions of the Python
44
language runtime. The main focus is on user-observable behavior of the engine.
55

6+
## Version 1.0.0 RC7
7+
8+
* Enhance the `java` interop builtin module with introspection utility methods
9+
610
## Version 1.0.0 RC6
711

812
* Support regular expression patterns built from bytes by using CPython's sre module as a fallback engine to our own

doc/INTEROP.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,28 @@ byteArray = myBigInt.toByteArray()
6262
print(list(byteArray)) # Java arrays can act like Python lists
6363
```
6464

65+
In addition to the `type` builtin method, the `java` module, exposes the following
66+
methods as well:
67+
68+
Builtin | Specification
69+
--- | ---
70+
`instanceof(obj, class)` | returns `True` if `obj` is an instance of `class` (`class` must be a foreign object class)
71+
`is_function(obj)` | returns `True` if `obj` is a Java host language function wrapped using Truffle interop
72+
`is_object(obj)` | returns `True` if `obj` if the argument is Java host language object wrapped using Truffle interop
73+
`is_symbol(obj)` | returns `True` if `obj` if the argument is a Java host symbol, representing the constructor and static members of a Java class, as obtained by `java.type`
74+
75+
```python
76+
import java
77+
ArrayList = java.type('java.util.ArrayList')
78+
my_list = ArrayList()
79+
print(java.is_symbol(ArrayList)) # prints True
80+
print(java.is_symbol(my_list)) # prints False, my_list is not a Java host symbol
81+
print(java.is_object(ArrayList)) # prints True, symbols are also host objects
82+
print(java.is_function(my_list.add))# prints True, the add method of ArrayList
83+
print(java.instanceof(my_list, ArrayList)) # prints True
84+
```
85+
86+
6587
#### Python responses to Truffle interop messages
6688

6789
###### READ

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
import com.oracle.graal.python.builtins.modules.PosixModuleBuiltins;
6565
import com.oracle.graal.python.builtins.modules.RandomModuleBuiltins;
6666
import com.oracle.graal.python.builtins.modules.SREModuleBuiltins;
67+
import com.oracle.graal.python.builtins.modules.SelectModuleBuiltins;
6768
import com.oracle.graal.python.builtins.modules.SignalModuleBuiltins;
6869
import com.oracle.graal.python.builtins.modules.StringModuleBuiltins;
6970
import com.oracle.graal.python.builtins.modules.SysModuleBuiltins;
@@ -253,6 +254,7 @@ public final class Python3Core implements PythonCore {
253254
new JavaModuleBuiltins(),
254255
new SREModuleBuiltins(),
255256
new AstModuleBuiltins(),
257+
new SelectModuleBuiltins(),
256258
new SignalModuleBuiltins(),
257259
new TracebackBuiltins(),
258260
new GcModuleBuiltins(),

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

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,17 @@
4545
import com.oracle.graal.python.builtins.Builtin;
4646
import com.oracle.graal.python.builtins.CoreFunctions;
4747
import com.oracle.graal.python.builtins.PythonBuiltins;
48+
import com.oracle.graal.python.builtins.objects.str.PString;
4849
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
50+
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
4951
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
5052
import com.oracle.graal.python.runtime.exception.PythonErrorType;
5153
import com.oracle.truffle.api.TruffleLanguage.Env;
54+
import com.oracle.truffle.api.dsl.Fallback;
5255
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
5356
import com.oracle.truffle.api.dsl.NodeFactory;
5457
import com.oracle.truffle.api.dsl.Specialization;
58+
import com.oracle.truffle.api.interop.TruffleObject;
5559

5660
@CoreFunctions(defineModule = "java")
5761
public class JavaModuleBuiltins extends PythonBuiltins {
@@ -63,8 +67,7 @@ protected List<? extends NodeFactory<? extends PythonBuiltinBaseNode>> getNodeFa
6367
@Builtin(name = "type", fixedNumOfPositionalArgs = 1)
6468
@GenerateNodeFactory
6569
abstract static class TypeNode extends PythonUnaryBuiltinNode {
66-
@Specialization
67-
Object type(String name) {
70+
private Object get(String name) {
6871
Env env = getContext().getEnv();
6972
if (!env.isHostLookupAllowed()) {
7073
throw raise(PythonErrorType.NotImplementedError, "host lookup is not allowed");
@@ -81,5 +84,75 @@ Object type(String name) {
8184
return hostValue;
8285
}
8386
}
87+
88+
@Specialization
89+
Object type(String name) {
90+
return get(name);
91+
}
92+
93+
@Specialization
94+
Object type(PString name) {
95+
return get(name.getValue());
96+
}
97+
}
98+
99+
@Builtin(name = "is_function", fixedNumOfPositionalArgs = 1)
100+
@GenerateNodeFactory
101+
abstract static class IsFunctionNode extends PythonUnaryBuiltinNode {
102+
@Specialization
103+
boolean check(Object object) {
104+
Env env = getContext().getEnv();
105+
return env.isHostFunction(object);
106+
}
107+
}
108+
109+
@Builtin(name = "is_object", fixedNumOfPositionalArgs = 1)
110+
@GenerateNodeFactory
111+
abstract static class IsObjectNode extends PythonUnaryBuiltinNode {
112+
@Specialization
113+
boolean check(Object object) {
114+
Env env = getContext().getEnv();
115+
return env.isHostObject(object);
116+
}
117+
}
118+
119+
@Builtin(name = "is_symbol", fixedNumOfPositionalArgs = 1)
120+
@GenerateNodeFactory
121+
abstract static class IsSymbolNode extends PythonUnaryBuiltinNode {
122+
@Specialization
123+
boolean check(Object object) {
124+
Env env = getContext().getEnv();
125+
return env.isHostSymbol(object);
126+
}
127+
}
128+
129+
@Builtin(name = "instanceof", fixedNumOfPositionalArgs = 2)
130+
@GenerateNodeFactory
131+
abstract static class InstanceOfNode extends PythonBinaryBuiltinNode {
132+
@Specialization(guards = {"!isForeignObject(object)", "isForeignObject(klass)"})
133+
boolean check(Object object, TruffleObject klass) {
134+
Env env = getContext().getEnv();
135+
Object hostKlass = env.asHostObject(klass);
136+
if (hostKlass instanceof Class<?>) {
137+
return ((Class<?>) hostKlass).isInstance(object);
138+
}
139+
return false;
140+
}
141+
142+
@Specialization(guards = {"isForeignObject(object)", "isForeignObject(klass)"})
143+
boolean checkForeign(Object object, TruffleObject klass) {
144+
Env env = getContext().getEnv();
145+
Object hostObject = env.asHostObject(object);
146+
Object hostKlass = env.asHostObject(klass);
147+
if (hostKlass instanceof Class<?>) {
148+
return ((Class<?>) hostKlass).isInstance(hostObject);
149+
}
150+
return false;
151+
}
152+
153+
@Fallback
154+
boolean fallback(Object object, Object klass) {
155+
throw raise(PythonErrorType.TypeError, "unsupported instanceof(%p, %p)", object, klass);
156+
}
84157
}
85158
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* The Universal Permissive License (UPL), Version 1.0
6+
*
7+
* Subject to the condition set forth below, permission is hereby granted to any
8+
* person obtaining a copy of this software, associated documentation and/or
9+
* data (collectively the "Software"), free of charge and under any and all
10+
* copyright rights in the Software, and any and all patent rights owned or
11+
* freely licensable by each licensor hereunder covering either (i) the
12+
* unmodified Software as contributed to or provided by such licensor, or (ii)
13+
* the Larger Works (as defined below), to deal in both
14+
*
15+
* (a) the Software, and
16+
*
17+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
18+
* one is included with the Software each a "Larger Work" to which the Software
19+
* is contributed by such licensors),
20+
*
21+
* without restriction, including without limitation the rights to copy, create
22+
* derivative works of, display, perform, and distribute the Software and make,
23+
* use, sell, offer for sale, import, export, have made, and have sold the
24+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
25+
* either these or other terms.
26+
*
27+
* This license is subject to the following condition:
28+
*
29+
* The above copyright notice and either this complete permission notice or at a
30+
* minimum a reference to the UPL must be included in all copies or substantial
31+
* portions of the Software.
32+
*
33+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39+
* SOFTWARE.
40+
*/
41+
package com.oracle.graal.python.builtins.modules;
42+
43+
import java.util.ArrayList;
44+
import java.util.List;
45+
46+
import com.oracle.graal.python.builtins.CoreFunctions;
47+
import com.oracle.graal.python.builtins.PythonBuiltins;
48+
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
49+
import com.oracle.truffle.api.dsl.NodeFactory;
50+
51+
@CoreFunctions(defineModule = "select")
52+
public class SelectModuleBuiltins extends PythonBuiltins {
53+
@Override
54+
protected List<? extends NodeFactory<? extends PythonBuiltinBaseNode>> getNodeFactories() {
55+
return new ArrayList<>();
56+
}
57+
}

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,22 +1248,22 @@ abstract static class PyTruffleSlice_GetIndicesEx extends NativeBuiltin {
12481248
@Specialization
12491249
Object doUnpack(int start, int stop, int step, int length) {
12501250
PSlice tmpSlice = factory().createSlice(start, stop, step);
1251-
SliceInfo actualIndices = tmpSlice.computeActualIndices(length);
1251+
SliceInfo actualIndices = tmpSlice.computeIndices(length);
12521252
return factory().createTuple(new Object[]{actualIndices.start, actualIndices.stop, actualIndices.step, actualIndices.length});
12531253
}
12541254

12551255
@Specialization(rewriteOn = ArithmeticException.class)
12561256
Object doUnpackLong(long start, long stop, long step, long length) {
12571257
PSlice tmpSlice = factory().createSlice(PInt.intValueExact(start), PInt.intValueExact(stop), PInt.intValueExact(step));
1258-
SliceInfo actualIndices = tmpSlice.computeActualIndices(PInt.intValueExact(length));
1258+
SliceInfo actualIndices = tmpSlice.computeIndices(PInt.intValueExact(length));
12591259
return factory().createTuple(new Object[]{actualIndices.start, actualIndices.stop, actualIndices.step, actualIndices.length});
12601260
}
12611261

12621262
@Specialization(replaces = {"doUnpackLong", "doUnpack"})
12631263
Object doUnpackLongOvf(long start, long stop, long step, long length) {
12641264
try {
12651265
PSlice tmpSlice = factory().createSlice(PInt.intValueExact(start), PInt.intValueExact(stop), PInt.intValueExact(step));
1266-
SliceInfo actualIndices = tmpSlice.computeActualIndices(length > Integer.MAX_VALUE ? Integer.MAX_VALUE : PInt.intValueExact(length));
1266+
SliceInfo actualIndices = tmpSlice.computeIndices(length > Integer.MAX_VALUE ? Integer.MAX_VALUE : PInt.intValueExact(length));
12671267
return factory().createTuple(new Object[]{actualIndices.start, actualIndices.stop, actualIndices.step, actualIndices.length});
12681268
} catch (ArithmeticException e) {
12691269
throw raiseIndexError();

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/SequenceStorageNodes.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ protected Object doScalarGeneric(SequenceStorage storage, Object idx) {
396396

397397
@Specialization
398398
protected Object doSlice(SequenceStorage storage, PSlice slice) {
399-
SliceInfo info = slice.computeActualIndices(storage.length());
399+
SliceInfo info = slice.computeIndices(storage.length());
400400
if (factoryMethod != null) {
401401
return factoryMethod.apply(getGetItemSliceNode().execute(storage, info.start, info.stop, info.step, info.length), factory());
402402
}
@@ -749,7 +749,7 @@ protected SequenceStorage doScalarGeneric(SequenceStorage storage, Object idx, O
749749

750750
@Specialization
751751
protected SequenceStorage doSlice(SequenceStorage storage, PSlice slice, Object iterable) {
752-
SliceInfo info = slice.computeActualIndices(storage.length());
752+
SliceInfo info = slice.computeIndices(storage.length());
753753
try {
754754
getSetItemSliceNode().execute(storage, info, iterable);
755755
return storage;
@@ -2727,7 +2727,7 @@ protected void doScalarGeneric(SequenceStorage storage, Object idx) {
27272727

27282728
@Specialization
27292729
protected void doSlice(SequenceStorage storage, PSlice slice) {
2730-
SliceInfo info = slice.computeActualIndices(storage.length());
2730+
SliceInfo info = slice.computeIndices(storage.length());
27312731
try {
27322732
getGetItemSliceNode().execute(storage, info);
27332733
} catch (SequenceStoreException e) {

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

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -95,27 +95,8 @@ protected int getForeignSize(TruffleObject object, Node getSizeNode, PForeignToP
9595
}
9696

9797
protected SliceInfo materializeSlice(PSlice idxSlice, TruffleObject object, Node getSizeNode, PForeignToPTypeNode foreign2PTypeNode) throws UnsupportedMessageException {
98-
99-
// determine start
100-
boolean isStartMissing = false;
101-
int start = idxSlice.getStart();
102-
if (start == PSlice.MISSING_INDEX) {
103-
start = 0;
104-
isStartMissing = true;
105-
}
106-
107-
// determine stop
108-
int end = idxSlice.getStop();
109-
int foreignSize = -1;
110-
if (end == PSlice.MISSING_INDEX) {
111-
foreignSize = getForeignSize(object, getSizeNode, foreign2PTypeNode);
112-
end = foreignSize;
113-
} else if (isStartMissing) {
114-
foreignSize = getForeignSize(object, getSizeNode, foreign2PTypeNode);
115-
}
116-
117-
// determine length (foreignSize is only required if start or stop is missing)
118-
return idxSlice.computeActualIndices(foreignSize);
98+
int foreignSize = getForeignSize(object, getSizeNode, foreign2PTypeNode);
99+
return idxSlice.computeIndices(foreignSize);
119100
}
120101
}
121102

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import static com.oracle.graal.python.nodes.SpecialMethodNames.__DELATTR__;
3333
import static com.oracle.graal.python.nodes.SpecialMethodNames.__DELITEM__;
3434
import static com.oracle.graal.python.nodes.SpecialMethodNames.__DIR__;
35+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__EQ__;
3536
import static com.oracle.graal.python.nodes.SpecialMethodNames.__FLOORDIV__;
3637
import static com.oracle.graal.python.nodes.SpecialMethodNames.__GETITEM__;
3738
import static com.oracle.graal.python.nodes.SpecialMethodNames.__GE__;
@@ -43,6 +44,7 @@
4344
import static com.oracle.graal.python.nodes.SpecialMethodNames.__LT__;
4445
import static com.oracle.graal.python.nodes.SpecialMethodNames.__MUL__;
4546
import static com.oracle.graal.python.nodes.SpecialMethodNames.__NEW__;
47+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__NE__;
4648
import static com.oracle.graal.python.nodes.SpecialMethodNames.__RADD__;
4749
import static com.oracle.graal.python.nodes.SpecialMethodNames.__REPR__;
4850
import static com.oracle.graal.python.nodes.SpecialMethodNames.__RFLOORDIV__;
@@ -716,6 +718,14 @@ protected GeNode() {
716718
}
717719
}
718720

721+
@Builtin(name = __EQ__, fixedNumOfPositionalArgs = 2)
722+
@GenerateNodeFactory
723+
public abstract static class EqNode extends ForeignBinaryComparisonNode {
724+
protected EqNode() {
725+
super(BinaryComparisonNode.create(__EQ__, __NE__, "=="));
726+
}
727+
}
728+
719729
@Builtin(name = __ITER__, fixedNumOfPositionalArgs = 1)
720730
@GenerateNodeFactory
721731
public abstract static class IterNode extends UnboxNode {
@@ -769,7 +779,7 @@ Object doForeignMapping(TruffleObject mapping,
769779

770780
@Fallback
771781
Object doGeneric(@SuppressWarnings("unused") Object o) {
772-
return PNone.NO_VALUE;
782+
return PNone.NONE;
773783
}
774784

775785
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/range/RangeBuiltins.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ Object doPRange(PRange primary, PInt idx) {
207207

208208
@Specialization
209209
Object doPRange(PRange range, PSlice slice) {
210-
SliceInfo info = slice.computeActualIndices(range.len());
210+
SliceInfo info = slice.computeIndices(range.len());
211211
int newStep = range.getStep() * info.step;
212212
int newStart = info.start == PSlice.MISSING_INDEX ? range.getStart() : range.getStart() + info.start * range.getStep();
213213
int newStop = info.stop == PSlice.MISSING_INDEX ? range.getStop() : Math.min(range.getStop(), newStart + info.length * newStep);

0 commit comments

Comments
 (0)