Skip to content

Commit 78a89f0

Browse files
committed
implement __init_subclass__ call after creating a new type as per PEP 487
1 parent 372fc3d commit 78a89f0

File tree

3 files changed

+32
-11
lines changed

3 files changed

+32
-11
lines changed

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

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -184,15 +184,15 @@ class D(C): ...
184184
self.assertEqual(D[int], 'D[int]')
185185
self.assertEqual(D[D], 'D[D]')
186186

187-
# def test_class_getitem_patched(self):
188-
# class C:
189-
# def __init_subclass__(cls):
190-
# def __class_getitem__(cls, item):
191-
# return '{0}[{1}]'.format(cls.__name__, item.__name__)
192-
# cls.__class_getitem__ = classmethod(__class_getitem__)
193-
# class D(C): ...
194-
# self.assertEqual(D[int], 'D[int]')
195-
# self.assertEqual(D[D], 'D[D]')
187+
def test_class_getitem_patched(self):
188+
class C:
189+
def __init_subclass__(cls):
190+
def __class_getitem__(cls, item):
191+
return '{0}[{1}]'.format(cls.__name__, item.__name__)
192+
cls.__class_getitem__ = classmethod(__class_getitem__)
193+
class D(C): ...
194+
self.assertEqual(D[int], 'D[int]')
195+
self.assertEqual(D[D], 'D[D]')
196196

197197
def test_class_getitem_with_builtins(self):
198198
class A(dict):

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

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@
119119
import com.oracle.graal.python.builtins.objects.set.PSet;
120120
import com.oracle.graal.python.builtins.objects.set.SetNodes;
121121
import com.oracle.graal.python.builtins.objects.str.PString;
122+
import com.oracle.graal.python.builtins.objects.superobject.SuperObject;
122123
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
123124
import com.oracle.graal.python.builtins.objects.type.LazyPythonClass;
124125
import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass;
@@ -130,6 +131,7 @@
130131
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetNameNode;
131132
import com.oracle.graal.python.nodes.PGuards;
132133
import com.oracle.graal.python.nodes.SpecialMethodNames;
134+
import com.oracle.graal.python.nodes.attributes.GetAttributeNode;
133135
import com.oracle.graal.python.nodes.attributes.GetAttributeNode.GetAnyAttributeNode;
134136
import com.oracle.graal.python.nodes.attributes.LookupAttributeInMRONode;
135137
import com.oracle.graal.python.nodes.attributes.LookupInheritedAttributeNode;
@@ -1813,6 +1815,8 @@ public Object type(Object cls, Object obj, PNone bases, PNone dict, PKeyword[] k
18131815
public Object type(VirtualFrame frame, PythonAbstractClass cls, String name, PTuple bases, PDict namespace, PKeyword[] kwds,
18141816
@Cached("create()") GetClassNode getMetaclassNode,
18151817
@Cached("create(__NEW__)") LookupInheritedAttributeNode getNewFuncNode,
1818+
@Cached("create(__INIT_SUBCLASS__)") GetAttributeNode getInitSubclassNode,
1819+
@Cached("create()") CallNode callInitSubclassNode,
18161820
@Cached("create()") CallNode callNewFuncNode) {
18171821
// Determine the proper metatype to deal with this
18181822
PythonAbstractClass metaclass = calculate_metaclass(cls, bases, getMetaclassNode);
@@ -1827,7 +1831,14 @@ public Object type(VirtualFrame frame, PythonAbstractClass cls, String name, PTu
18271831
}
18281832

18291833
try {
1830-
Object newType = typeMetaclass(name, bases, namespace, metaclass);
1834+
PythonClass newType = typeMetaclass(name, bases, namespace, metaclass);
1835+
1836+
// TODO: Call __set_name__ on all descriptors in a newly generated type
1837+
1838+
// Call __init_subclass__ on the parent of a newly generated type
1839+
SuperObject superObject = factory().createSuperObject(PythonBuiltinClassType.Super);
1840+
superObject.init(newType, newType, newType);
1841+
callInitSubclassNode.execute(frame, getInitSubclassNode.executeObject(superObject), new Object[0], kwds);
18311842

18321843
// set '__module__' attribute
18331844
Object moduleAttr = ensureReadAttrNode().execute(newType, __MODULE__);
@@ -1863,7 +1874,7 @@ private String getModuleNameFromGlobals(PythonObject globals) {
18631874
}
18641875

18651876
@TruffleBoundary
1866-
private Object typeMetaclass(String name, PTuple bases, PDict namespace, PythonAbstractClass metaclass) {
1877+
private PythonClass typeMetaclass(String name, PTuple bases, PDict namespace, PythonAbstractClass metaclass) {
18671878

18681879
Object[] array = bases.getArray();
18691880

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectBuiltins.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import static com.oracle.graal.python.nodes.SpecialMethodNames.__GETATTR__;
4040
import static com.oracle.graal.python.nodes.SpecialMethodNames.__GET__;
4141
import static com.oracle.graal.python.nodes.SpecialMethodNames.__HASH__;
42+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__INIT_SUBCLASS__;
4243
import static com.oracle.graal.python.nodes.SpecialMethodNames.__INIT__;
4344
import static com.oracle.graal.python.nodes.SpecialMethodNames.__LEN__;
4445
import static com.oracle.graal.python.nodes.SpecialMethodNames.__NE__;
@@ -631,4 +632,13 @@ boolean richcmp(Object left, Object right, @SuppressWarnings("unused") String op
631632
return node.executeBool(left, right);
632633
}
633634
}
635+
636+
@Builtin(name = __INIT_SUBCLASS__, minNumOfPositionalArgs = 1)
637+
@GenerateNodeFactory
638+
abstract static class InitSubclass extends PythonUnaryBuiltinNode {
639+
@Specialization
640+
PNone initSubclass(@SuppressWarnings("unused") Object self) {
641+
return PNone.NONE;
642+
}
643+
}
634644
}

0 commit comments

Comments
 (0)