Support for __init_subclass__

This commit is contained in:
K. Lange 2023-01-26 20:01:12 +09:00
parent 5d1b73b3a2
commit 1e044c140d
11 changed files with 75 additions and 9 deletions

View File

@ -199,6 +199,11 @@ KRK_Method(object,__init__) {
return NONE_VAL();
}
KRK_StaticMethod(object,__init_subclass__) {
if (!krk_parseArgs(".", (const char*[]){NULL}, NULL)) return NONE_VAL();
return NONE_VAL();
}
/**
* object.__str__() / object.__repr__()
@ -1345,6 +1350,7 @@ void _createAndBind_builtins(void) {
BIND_STATICMETHOD(object,__setattr__);
BIND_STATICMETHOD(object,__new__);
BIND_METHOD(object,__init__);
BIND_CLASSMETHOD(object,__init_subclass__);
krk_defineNative(&object->methods, "__repr__", FUNC_NAME(object,__str__));
krk_finalizeClass(object);
KRK_DOC(object,

View File

@ -100,7 +100,7 @@ static inline KrkNative * krk_defineNativeStaticMethod(KrkTable * table, const c
}
#define BIND_STATICMETHOD(klass,method) krk_defineNativeStaticMethod(&klass->methods, #method, _ ## klass ## _ ## method)
static inline KrkNative * krk_deifneNativeClassMethod(KrkTable * table, const char * name, NativeFn function) {
static inline KrkNative * krk_defineNativeClassMethod(KrkTable * table, const char * name, NativeFn function) {
KrkNative * out = krk_defineNative(table,name,function);
out->obj.flags |= KRK_OBJ_FLAGS_FUNCTION_IS_CLASS_METHOD;
return out;

View File

@ -58,7 +58,7 @@ KRK_StaticMethod(type,__new__) {
KrkClass * base;
KrkDict * nspace;
if (!krk_parseArgs("O!O!O!O!",
if (!krk_parseArgs("O!O!O!O!~",
(const char*[]){"cls","name","base","namespace"},
vm.baseClasses->typeClass, &metaclass,
vm.baseClasses->strClass, &name,
@ -96,6 +96,22 @@ KRK_StaticMethod(type,__new__) {
krk_finalizeClass(_class);
_callSetName(_class);
/* Call super().__init_subclass__ */
extern int krk_bindMethodSuper(KrkClass * originalClass, KrkString * name, KrkClass * realClass);
krk_push(NONE_VAL());
if (!krk_bindMethodSuper(base,S("__init_subclass__"),_class)) {
krk_pop(); /* none */
} else {
if (hasKw) {
krk_push(KWARGS_VAL(KWARGS_DICT));
krk_push(argv[argc]);
krk_push(KWARGS_VAL(1));
krk_callStack(3);
} else {
krk_callStack(0);
}
}
return krk_pop();
}

View File

@ -1,4 +1,4 @@
['__class__', '__dir__', '__doc__', '__eq__', '__format__', '__hash__', '__init__', '__new__', '__repr__', '__setattr__', '__str__', 'longList', 'ofAttributes', 'onThatObject', 'thatWeWantToSet']
['__class__', '__dir__', '__doc__', '__eq__', '__format__', '__hash__', '__init__', '__init_subclass__', '__new__', '__repr__', '__setattr__', '__str__', 'longList', 'ofAttributes', 'onThatObject', 'thatWeWantToSet']
1
2
3

View File

@ -0,0 +1,19 @@
class Foo():
@classmethod
def cm(cls):
print(f"{cls=}")
class Bar(Foo):
pass
class Baz(Foo):
@classmethod
def cm(cls):
print("(Baz)")
super().cm()
Bar.cm()
Bar().cm()
Baz.cm()
Baz().cm()

View File

@ -0,0 +1,6 @@
cls=<class '__main__.Bar'>
cls=<class '__main__.Bar'>
(Baz)
cls=<class '__main__.Baz'>
(Baz)
cls=<class '__main__.Baz'>

View File

@ -7,10 +7,10 @@ False
[1, 3, 4, 5]
[1, 3, 4]
list index out of range: 3
['__class__', '__dir__', '__doc__', '__eq__', '__format__', '__hash__', '__init__', '__new__', '__repr__', '__setattr__', '__str__', 'baz', 'qux']
['__class__', '__dir__', '__doc__', '__eq__', '__format__', '__hash__', '__init__', '__init_subclass__', '__new__', '__repr__', '__setattr__', '__str__', 'baz', 'qux']
42
['__class__', '__dir__', '__doc__', '__eq__', '__format__', '__hash__', '__init__', '__new__', '__repr__', '__setattr__', '__str__', 'qux']
['__class__', '__dir__', '__doc__', '__eq__', '__format__', '__hash__', '__init__', '__init_subclass__', '__new__', '__repr__', '__setattr__', '__str__', 'qux']
hi
'object' object has no attribute 'baz'
['__class__', '__dir__', '__doc__', '__eq__', '__format__', '__hash__', '__init__', '__new__', '__repr__', '__setattr__', '__str__']
['__class__', '__dir__', '__doc__', '__eq__', '__format__', '__hash__', '__init__', '__init_subclass__', '__new__', '__repr__', '__setattr__', '__str__']
'object' object has no attribute 'bar'

View File

@ -1,3 +1,3 @@
['__class__', '__dir__', '__doc__', '__eq__', '__format__', '__getattr__', '__hash__', '__init__', '__module__', '__new__', '__qualname__', '__repr__', '__setattr__', '__str__', '_dict']
['__class__', '__dir__', '__doc__', '__eq__', '__format__', '__getattr__', '__hash__', '__init__', '__init_subclass__', '__module__', '__new__', '__qualname__', '__repr__', '__setattr__', '__str__', '_dict']
1
['__class__', '__dir__', '__doc__', '__eq__', '__format__', '__hash__', '__init__', '__module__', '__new__', '__qualname__', '__repr__', '__setattr__', '__str__', 'butts']
['__class__', '__dir__', '__doc__', '__eq__', '__format__', '__hash__', '__init__', '__init_subclass__', '__module__', '__new__', '__qualname__', '__repr__', '__setattr__', '__str__', 'butts']

View File

@ -0,0 +1,15 @@
class Foo:
def __init_subclass__(cls,**kwds):
print('Foo subclass',cls,'with args',kwds)
class Bar(Foo):
pass
class Baz(Foo,foo=42):
pass
class Qux(Bar):
pass
class Florp(Bar,abc=123):
pass

View File

@ -0,0 +1,4 @@
Foo subclass <class '__main__.Bar'> with args {}
Foo subclass <class '__main__.Baz'> with args {'foo': 42}
Foo subclass <class '__main__.Qux'> with args {}
Foo subclass <class '__main__.Florp'> with args {'abc': 123}

View File

@ -1,6 +1,6 @@
True
True
['__class__', '__dir__', '__doc__', '__eq__', '__format__', '__get__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__repr__', '__set__', '__setattr__', '__str__', 'fget', 'setter']
['__class__', '__dir__', '__doc__', '__eq__', '__format__', '__get__', '__hash__', '__init__', '__init_subclass__', '__module__', '__name__', '__new__', '__repr__', '__set__', '__setattr__', '__str__', 'fget', 'setter']
p retrieved from A
{'a': 45}
calling property from subclass