Skip to content

Commit a834670

Browse files
committed
Support basic usage of foreign meta-objects that are not instantiable with typing
1 parent 9565645 commit a834670

File tree

3 files changed

+97
-1
lines changed

3 files changed

+97
-1
lines changed

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,19 @@ def test_java_import_star(self):
575575
assert "getGlobal" in d
576576
assert d["getGlobal"]().getName() == d["GLOBAL_LOGGER_NAME"]
577577

578+
def test_java_typing_support(self):
579+
import typing
580+
import java.lang.Integer as Integer
581+
import java.util.List as List
582+
assert List.__name__ == "List"
583+
assert List.__qualname__ == "java.util.List"
584+
assert List.__module__ == "polyglot"
585+
assert List.__type_params__ == ()
586+
assert List.__annotations__ == {}
587+
assert isinstance(List[Integer], typing.GenericAlias)
588+
assert List[Integer].__origin__ == List
589+
assert List[Integer].__args__ == (Integer,)
590+
578591
def test_java_null_is_none(self):
579592
import java.lang.Integer as Integer
580593
x = Integer.getInteger("something_that_does_not_exists")

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@
174174
import com.oracle.graal.python.builtins.objects.exception.UnicodeTranslateErrorBuiltins;
175175
import com.oracle.graal.python.builtins.objects.filter.FilterBuiltins;
176176
import com.oracle.graal.python.builtins.objects.floats.FloatBuiltins;
177+
import com.oracle.graal.python.builtins.objects.foreign.ForeignAbstractClassBuiltins;
177178
import com.oracle.graal.python.builtins.objects.foreign.ForeignBooleanBuiltins;
178179
import com.oracle.graal.python.builtins.objects.foreign.ForeignExecutableBuiltins;
179180
import com.oracle.graal.python.builtins.objects.foreign.ForeignInstantiableBuiltins;
@@ -829,7 +830,7 @@ It can be called either on the class (e.g. C.f()) or on an instance
829830
"ForeignBoolean",
830831
ForeignNumber,
831832
newBuilder().publishInModule(J_POLYGLOT).basetype().addDict().disallowInstantiation().slots(ForeignBooleanBuiltins.SLOTS)),
832-
ForeignAbstractClass("ForeignAbstractClass", ForeignObject, newBuilder().publishInModule(J_POLYGLOT).basetype().addDict().disallowInstantiation()),
833+
ForeignAbstractClass("ForeignAbstractClass", ForeignObject, newBuilder().publishInModule(J_POLYGLOT).basetype().addDict().disallowInstantiation().slots(ForeignAbstractClassBuiltins.SLOTS)),
833834
ForeignExecutable("ForeignExecutable", ForeignObject, newBuilder().publishInModule(J_POLYGLOT).basetype().addDict().disallowInstantiation().slots(ForeignExecutableBuiltins.SLOTS)),
834835
ForeignInstantiable("ForeignInstantiable", ForeignObject, newBuilder().publishInModule(J_POLYGLOT).basetype().addDict().slots(ForeignInstantiableBuiltins.SLOTS)),
835836
ForeignIterable("ForeignIterable", ForeignObject, newBuilder().publishInModule(J_POLYGLOT).basetype().addDict().disallowInstantiation().slots(ForeignIterableBuiltins.SLOTS)),

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

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,21 +26,32 @@
2626

2727
package com.oracle.graal.python.builtins.objects.foreign;
2828

29+
import static com.oracle.graal.python.nodes.BuiltinNames.T_POLYGLOT;
30+
import static com.oracle.graal.python.nodes.SpecialAttributeNames.J___ANNOTATIONS__;
2931
import static com.oracle.graal.python.nodes.SpecialAttributeNames.J___BASES__;
32+
import static com.oracle.graal.python.nodes.SpecialAttributeNames.J___MODULE__;
33+
import static com.oracle.graal.python.nodes.SpecialAttributeNames.J___NAME__;
34+
import static com.oracle.graal.python.nodes.SpecialAttributeNames.J___QUALNAME__;
35+
import static com.oracle.graal.python.nodes.SpecialAttributeNames.J___TYPE_PARAMS__;
3036
import static com.oracle.graal.python.nodes.SpecialMethodNames.J___INSTANCECHECK__;
3137

3238
import java.util.List;
3339

3440
import com.oracle.graal.python.PythonLanguage;
3541
import com.oracle.graal.python.annotations.Builtin;
42+
import com.oracle.graal.python.annotations.Slot;
43+
import com.oracle.graal.python.annotations.Slot.SlotKind;
3644
import com.oracle.graal.python.builtins.CoreFunctions;
3745
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
3846
import com.oracle.graal.python.builtins.PythonBuiltins;
3947
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes;
48+
import com.oracle.graal.python.builtins.objects.type.TpSlots;
49+
import com.oracle.graal.python.builtins.objects.type.slots.TpSlotBinaryFunc.MpSubscriptBuiltinNode;
4050
import com.oracle.graal.python.lib.PyObjectGetIter;
4151
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
4252
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
4353
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
54+
import com.oracle.graal.python.nodes.interop.PForeignToPTypeNode;
4455
import com.oracle.graal.python.runtime.GilNode;
4556
import com.oracle.graal.python.runtime.object.PFactory;
4657
import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage;
@@ -64,6 +75,8 @@
6475
*/
6576
@CoreFunctions(extendClasses = PythonBuiltinClassType.ForeignAbstractClass)
6677
public final class ForeignAbstractClassBuiltins extends PythonBuiltins {
78+
public static TpSlots SLOTS = ForeignAbstractClassBuiltinsSlotsGen.SLOTS;
79+
6780
@Override
6881
protected List<? extends NodeFactory<? extends PythonBuiltinBaseNode>> getNodeFactories() {
6982
return ForeignAbstractClassBuiltinsFactory.getFactories();
@@ -94,6 +107,66 @@ static Object getBases(VirtualFrame frame, Object self,
94107
}
95108
}
96109

110+
@Builtin(name = J___NAME__, minNumOfPositionalArgs = 1, isGetter = true, isSetter = false)
111+
@GenerateNodeFactory
112+
abstract static class ForeignNameNode extends PythonUnaryBuiltinNode {
113+
@Specialization(limit = "2")
114+
static Object foreignName(Object self,
115+
@CachedLibrary("self") InteropLibrary lib,
116+
@Cached PForeignToPTypeNode castStr) {
117+
try {
118+
return castStr.executeConvert(lib.getMetaSimpleName(self));
119+
} catch (UnsupportedMessageException e) {
120+
throw CompilerDirectives.shouldNotReachHere(e);
121+
}
122+
}
123+
}
124+
125+
@Builtin(name = J___QUALNAME__, minNumOfPositionalArgs = 1, isGetter = true, isSetter = false)
126+
@GenerateNodeFactory
127+
abstract static class ForeignQualnameNode extends PythonUnaryBuiltinNode {
128+
@Specialization(limit = "2")
129+
static Object foreignName(Object self,
130+
@CachedLibrary("self") InteropLibrary lib,
131+
@Cached PForeignToPTypeNode castStr) {
132+
try {
133+
return castStr.executeConvert(lib.getMetaQualifiedName(self));
134+
} catch (UnsupportedMessageException e) {
135+
throw CompilerDirectives.shouldNotReachHere(e);
136+
}
137+
}
138+
}
139+
140+
@Builtin(name = J___MODULE__, minNumOfPositionalArgs = 1, isGetter = true, isSetter = false)
141+
@GenerateNodeFactory
142+
abstract static class ForeignModuleNode extends PythonUnaryBuiltinNode {
143+
@Specialization
144+
static Object foreignModule(@SuppressWarnings("unused") Object self) {
145+
return T_POLYGLOT;
146+
}
147+
}
148+
149+
@Builtin(name = J___TYPE_PARAMS__, minNumOfPositionalArgs = 1, isGetter = true, isSetter = false)
150+
@GenerateNodeFactory
151+
abstract static class ForeignTypeParams extends PythonUnaryBuiltinNode {
152+
@Specialization
153+
static Object foreignTypeParams(@SuppressWarnings("unused") Object self,
154+
@Bind PythonLanguage lang) {
155+
return PFactory.createEmptyTuple(lang);
156+
}
157+
}
158+
159+
@Builtin(name = J___ANNOTATIONS__, minNumOfPositionalArgs = 1, isGetter = true, isSetter = false)
160+
@GenerateNodeFactory
161+
abstract static class ForeignAnnotations extends PythonUnaryBuiltinNode {
162+
@Specialization
163+
static Object foreignAnnotations(@SuppressWarnings("unused") Object self,
164+
@Bind PythonLanguage lang) {
165+
// TODO: use the declared members interop API to return annotations
166+
return PFactory.createDict(lang);
167+
}
168+
}
169+
97170
@Builtin(name = J___INSTANCECHECK__, minNumOfPositionalArgs = 2)
98171
@GenerateNodeFactory
99172
abstract static class InstancecheckNode extends PythonBinaryBuiltinNode {
@@ -112,4 +185,13 @@ static Object check(Object self, Object instance,
112185
}
113186
}
114187

188+
@Slot(value = SlotKind.mp_subscript, isComplex = true)
189+
@GenerateNodeFactory
190+
abstract static class ForeignClassGetItemNode extends MpSubscriptBuiltinNode {
191+
@Specialization
192+
static Object classGetItem(Object cls, Object key,
193+
@Bind PythonLanguage language) {
194+
return PFactory.createGenericAlias(language, cls, key);
195+
}
196+
}
115197
}

0 commit comments

Comments
 (0)