-
Notifications
You must be signed in to change notification settings - Fork 769
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
using subclass, args on new, and overriding __init__ fails #1644
Comments
@davidhewitt if you could point me in the right direction I could try to fix this. |
I think if you try overriding I agree that this is both suprising and undocumented. We should add some information to the guide about this. I'd also be happy to discuss whether this should be changed. |
The problem with overriding __new__ instead of __init__ is that I'm trying
to replace an existing python implementation, where there is existing code
that does just this - inherits and uses a different signature of __init__.
…On Tue, Jun 1, 2021 at 9:08 PM David Hewitt ***@***.***> wrote:
I think if you try overriding __new__ instead of __init__, things should
just work?
I agree that this is both suprising and undocumented. We should add some
information to the guide about this. I'd also be happy to discuss whether
this should be changed.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#1644 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/ASHRLMOBGGJFDN47G7DKXR3TQUOZDANCNFSM452MSZZQ>
.
|
Note that you can override both (with the same arguments): class SubclassWithExtraInitArguments(SubclassableWithParameter):
def __new__(cls, bar):
print("before super new")
return super().__new__(cls, foo=bool(bar))
def __init__(self, bar):
print("before super init")
super().__init__() The above passes the "test" for me. I appreciate that it's perhaps not ideal for your use case. To explain the current situation, I think quoting from the Python docs is helpful: https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_new
In our case, at the moment initializing the Rust pyclass object is part of the "initialization which is absolutely necessary". When we create the I'm not saying that this is how it must stay; I'm aware it has drawbacks (and it existed before I was maintaining the project). I'd be happy to discuss alternative designs if we can come up with something better / more flexible. Ideally we'd be able to allow users to choose whether to use |
I have similar problem with self-referenceable class: # Cython code to be rewritten
cdef class ConstExpr:
def __init__(self, baseobj, offset=0):
self.baseobj = baseobj
self.offset = offset
def __add__(self, other):
return ConstExpr(self.baseobj, self.offset + offset) // Rewrite Cython code in Rust
use pyo3::prelude::*;
use pyo3::types::PyNone;
use std::sync::Arc;
pub(crate) struct ConstExpr {
baseobj: Option<Arc<Self>>,
offset: i32,
}
#[derive(Clone)]
#[pyclass(frozen, subclass, name = "ConstExpr")]
pub struct PyConstExpr(Arc<ConstExpr>);
#[pymethods]
impl PyConstExpr {
#[new]
#[pyo3(signature = (baseobj, offset=0))]
fn new(baseobj: &PyAny, offset: i32) -> PyResult<Self> {
let expr = if let Ok(expr) = baseobj.extract::<PyConstExpr>() {
ConstExpr::new(Some(expr.0.clone()), offset)
} else if baseobj.is(PyNone::get(baseobj.py())) {
ConstExpr::new(None, offset)
} else {
return Err(PyTypeError::new_err(format!("{baseobj} is not a ConstExpr")));
};
Ok(Self(Arc::new(expr)))
}
fn __add__(&self, rhs: i32) -> Self {
Self(Arc::new(ConstExpr {
baseobj: self.0.baseobj.clone(),
offset: self.0.offset + rhs,
}))
}
} # test code
import _rust as rs
class Subclass(rs.ConstExpr):
def __init__(self):
super().__init__(self) # TypeError: object.__init__() takes exactly one argument (the instance to initialize)
s = Subclass() # TypeError: ConstExpr.__new__() missing 1 required positional argument: 'baseobj'
print(s) # should be Subclass
print(s + 1) # should be ConstExpr { baseobj: s, offset: 1 }
print(s + 2) # should be ConstExpr { baseobj: s, offset: 2 } I can't rewrite code as it is because in PyO3 only Python's It's low-level advanced API so making breaking change by requiring (1) overriding both |
This issue is about sub classing with overridden init ; This bug prevents it. Details below.
🐛 Bug Reports
When reporting a bug, please provide the following information. If this is not a bug report you can just discard this template.
🌍 Environment
rustc --version
): rustc 1.54.0-nightly (b663c0f4f 2021-05-29)version = "0.x.y"
withgit = "https://github.com/PyO3/pyo3")?
yes.💥 Reproducing
I have a branch with the augmented test (examples/pyo3-pytests/src/subclassing.rs & examples/pyo3-pytests/tests/test_subclassing.py), at https://github.com/alonblade/pyo3/tree/add-test-for-inheritance-with-init ; Here is the change:
And the output
The text was updated successfully, but these errors were encountered: