Repository navigation
Conversation
|
Thanks for your contribution. Adding a test about this feature In |
isidentical
left a comment
There was a problem hiding this comment.
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>
AssertionErrorThis 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.initializedthis 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