Skip to content
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

#[classattr] functions should be able to take Python arguments #2383

Closed
davidhewitt opened this issue May 17, 2022 · 7 comments · Fixed by #2456
Closed

#[classattr] functions should be able to take Python arguments #2383

davidhewitt opened this issue May 17, 2022 · 7 comments · Fixed by #2456

Comments

@davidhewitt
Copy link
Member

davidhewitt commented May 17, 2022

Try to compile the following:

#[pyclass]
struct Singleton { }

#[pymethods]
impl Singleton {
    #[classattr]
    fn VALUE(py: Python<'_>) -> Py<Self> {
        Py::new(py, Singleton { }).unwrap()
    }
}

I expected this to compile, but instead the compiler emits:

error: class attribute methods cannot take arguments
  --> src/lib.rs:10:14
   |
10 |     fn VALUE(py: Python<'_>) -> Py<Self> {
   |              ^^

I think it'd be nice to change #[classattr] to allow Python argument (like #[getter], for example).

@mdaj06
Copy link

mdaj06 commented May 23, 2022

@davidhewitt i'd really like to implement this

@davidhewitt
Copy link
Member Author

@mdaj06 please do! Do you need any tips to get started?

@mdaj06
Copy link

mdaj06 commented May 23, 2022

@davidhewitt i'll look into it and if I get blocked I'll reach out,if that's okay?

@birkenfeld
Copy link
Member

Don't worry, we will try to help if you get stuck.

@mdaj06
Copy link

mdaj06 commented May 23, 2022

thanks!! @birkenfeld

@mdaj06
Copy link

mdaj06 commented Jun 8, 2022

i ran a few circles, trying to find out where to start. Could you point out the file i can start from?

@davidhewitt
Copy link
Member Author

Sure thing.

The call to the #[classattr] function is generated in macro code at

let mut ret = #cls::#name();

You will want to conditionally add py in there according to whether the #[classattr] function takes an argument. See the equivalent code for #[getter]:

let (py_arg, args) = split_off_python_arg(&spec.args);
ensure_spanned!(
args.is_empty(),
args[0].ty.span() => "getter function can only have one argument (of type pyo3::Python)"
);
let name = &spec.name;
let fncall = if py_arg.is_some() {
quote!(#cls::#name(_slf, _py))
} else {
quote!(#cls::#name(_slf))
};

Let me know if you need more detail than that :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants