-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Implement __init_subclass__ #1357
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Thanks for your contribution. Adding a test about this feature In |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMHO doing this calls on builtins.__build_class__
doesn't cover all cases.
(general) batuhan@x200-trisquel:~/cpython$ python
Python 3.9.0a0 (heads/master:b607d99, Jul 4 2019, 11:03:12)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> class X:
... def __init_subclass__(cls):
... print(f"initalizing {cls!r}")
...
>>> Y = type("Y", (X,), {})
initalizing <class '__main__.Y'>
(general) batuhan@x200-trisquel:~/RustPython$ git checkout dvt/init_subclasses
(general) batuhan@x200-trisquel:~/RustPython$ cargo run
Compiling rustpython-vm v0.1.0 (/home/batuhan/RustPython/vm)
Compiling rustpython v0.1.0 (/home/batuhan/RustPython)
Finished dev [unoptimized + debuginfo] target(s) in 55.62s
Running `target/debug/rustpython`
Welcome to the magnificent Rust Python 0.1.0 interpreter 😱 🖖
>>>>> class X:
..... def __init_subclass__(cls):
..... print(f"initalizing {cls!r}")
.....
>>>>> Y = type("Y", (X,), {})
>>>>>
CPython does this notify operation on type object constructor (__new__
). The reason
@dvtkrlbs used __build_class__
instead of __new__
is unlike cpython rustpython's __build_class__
doesn't pass it's keyword arguments (class A(kw1=some_value, ..., metaclass=Z)
) to type constructor.
Also there is another thing that might be a problem with cpython compatibility.
/* Special-case __init_subclass__ and __class_getitem__:
if they are plain functions, make them classmethods */
tmp = _PyDict_GetItemIdWithError(dict, &PyId___init_subclass__);
if (tmp != NULL && PyFunction_Check(tmp)) {
tmp = PyClassMethod_New(tmp);
if (tmp == NULL)
goto error;
if (_PyDict_SetItemId(dict, &PyId___init_subclass__, tmp) < 0) {
Py_DECREF(tmp);
goto error;
}
Py_DECREF(tmp);
}
else if (tmp == NULL && PyErr_Occurred()) {
goto error;
}
CPython;
>>> class X:
... def __init_subclass__(cls):
... pass
...
>>> assert isinstance(X.__dict__["__init_subclass__"], classmethod)
>>>
RustPython;
>>>>> class X:
..... def __init_subclass__(cls):
..... pass
.....
>>>>> assert isinstance(X.__dict__["__init_subclass__"], classmethod)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError
This is a special case like #1230
Also probably an error in my side but with this edit the parent class cant alter the subclass even though i pass the class as reference class X:
def __init_subclass__(cls):
cls.initialized = True
class Y:
pass
assert Y.initialized this does not work even though it should work |
I am not familiar with rust (not even a little bit) so just asking. let args: Args = Args::new(vec![class.clone()]); is this type = (PyTypeObject *)metatype->tp_alloc(metatype, nslots);
...
if (init_subclass(type, kwds) < 0)
goto error; |
Python objects in rustpython lives in Rc (reference counting) and they customize the behaviour. Clone just increments the counter. (Unlike normal objects). So all the reference counting of the python objects is automatic. |
oh, i see. |
Hmm you can access args from type_new function it actually passes them i will move the implementation to there |
This is probably caused because |
Could you add the python examples now mentioned as comments into the |
Oh i completely forgot about this |
This pull request implements a portion of the PEP 487 this pep also defines
__set_name__
dunder method but it is not implemented in this pr.__init_subclass__
method allows a superclass to initialize al subclasses it takes the subclass and any number of arguments