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

pyo3(get, set) attribute not found when using cfg_attr #1003

Closed
Waelwindows opened this issue Jun 26, 2020 · 9 comments · Fixed by #2692
Closed

pyo3(get, set) attribute not found when using cfg_attr #1003

Waelwindows opened this issue Jun 26, 2020 · 9 comments · Fixed by #2692

Comments

@Waelwindows
Copy link

🐛 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

  • Your operating system and version: Arch Linux x86_64 5.7.4-arch1-1
  • Your python version: Python 3.8.3
  • How did you install python (e.g. apt or pyenv)? Did you use a virtualenv?: pacman
  • Your Rust version (rustc --version): rustc 1.46.0-nightly (6bb3dbfc6 2020-06-22)
  • Your PyO3 version: 0.10.1
  • Have you tried using latest PyO3 master (replace version = "0.x.y" with git = "https://github.com/PyO3/pyo3")?: No

💥 Reproducing

Please provide a minimal working example. This means both the Rust code and the Python.

This compiles

#[cfg_attr(feature="pyo3", pyclass)]
#[derive(Debug, Default)]
pub struct Foo {
    #[pyo3(get, set)]
    bar: bool,
}

However, this doesn't

#[cfg_attr(feature="pyo3", pyclass)]
#[derive(Debug, Default)]
pub struct Foo {
    #[cfg_attr(feature="pyo3", pyo3(get, set))]
    bar: bool,
}

Because it can't find the pyo3 attribute

error: cannot find attribute `pyo3` in this scope
  --> src/material/texture/mod.rs:45:32
   |
45 |     #[cfg_attr(feature="pyo3", pyo3(get, set))]
   |                                ^^^^

Please also write what exact flags are required to reproduce your results.

@birkenfeld
Copy link
Member

This is basically a duplicate of #780.

@davidhewitt
Copy link
Member

Based on #780 (comment) I wonder if we can resolve this by changing #[pyclass] expansion to (among other things) add a #[derive(PyClassImpl)] or something like that. Where the PyClassImpl derive macro would apparently be called with all cfg_attr attributes resolved.

This is kind of a hack, though, so I wonder if really we should be asking the compiler team if it's reasonable to expand all #[cfg_attr] clauses before calling custom attributes (as it already appears to do that for derive).

@davidhewitt
Copy link
Member

Looks like the compiler team may indeed be doing that rust-lang/rust#83824

@cgranade
Copy link

Is there a suggested workaround for this issue until that compiler feature lands? Thanks for the help!

@mejrs
Copy link
Member

mejrs commented May 19, 2021

Is there a suggested workaround for this issue until that compiler feature lands? Thanks for the help!

You can manually implement getters/setters, and guard that block with a cfg:

#[cfg_attr(feature = "pyo3", pyclass)]
struct Foo{
    bar: u8
}

#[cfg(feature = "pyo3")]
#[pymethods]
impl Foo{
    // not named "bar" because there might already a rust getter for it
    #[getter(bar)]
    fn py_bar(&self) -> u8{
        self.bar
    }
}

I've had to do this for structs with hundreds of fields - not fun. Note that you may need to apply .clone() for fields that are not Copy.

@Trolldemorted
Copy link

@mejrs get_all is awesome, thank you very much! If I hadn't scrolled until here, I would not have known. Maybe this should be documented somewhere more easy to find?

@mejrs
Copy link
Member

mejrs commented Apr 17, 2023

It is listed at https://pyo3.rs/v0.18.3/class.html#customizing-the-class I'm not sure where else this information should be. Where were you looking for it?

@Trolldemorted
Copy link

oh sorry, I thought the "pyo3(get,set) doesn't work with cfg_attr" problem was mentioned in the FAQs - if it is included in the future I'd recommend a sentence that suggests get_all as a workaround.

@hugohadfieldwayve
Copy link

For those stumbling upon this, here is a super explicit example with get_all and cfg_attr

#[cfg_attr(feature = "pyo3", pyclass(get_all))]
pub struct MyStruct {
    pub my_field_a: f32,
    pub my_field_b: f32
}

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.

7 participants