PyO3 / pyo3

Rust bindings for the Python interpreter
https://pyo3.rs
Other
11.44k stars 693 forks source link

'Deprecation of implicit default for trailing optional arguments' Causing issues with erasable setters #4292

Open SuperJappie08 opened 6 days ago

SuperJappie08 commented 6 days ago

Bug Description

As a result of the (upcoming) changes in 0.22 and 0.23 with Option<T> arguments requiring a #[pyo3(signature=...)] link to migration guide.

This causes a problem for setters of a pyclass, which can be erased by setting None, since you're not allowed to specify a signature on a setter.

This is caused by #2935. In this case, I do not need a default argument. However, it will be required in version 0.23.

Steps to Reproduce

use pyo3::prelude::*;

#[pyclass]
struct SimpleClass {
    field: Option<u32>
}

#[pymethods]
impl SimpleClass {
    #[new]
    #[pyo3(signature = (value=None))]
    fn new(field: Option<u32>) -> Self {
        Self { field }
    }

    #[getter]
    fn get_field(&self) -> Option<u32> {
        self.field
    }

    /// This causes issues
    #[setter]
    fn set_field((&mut self, field: Option<u32>) {
        self.field = field;
    }
}

Backtrace

No response

Your operating system and version

Windows/Linux (All effected)

Your Python version (python --version)

Python 3.10.12

Your Rust version (rustc --version)

rustc 1.79.0 (129f3b996 2024-06-10)

Your PyO3 version

0.22+

How did you install python? Did you use a virtualenv?

apt + venv

Additional Info

This currently causes non-removable warnings, however in the future this will break code.

EDIT: Added more information

SuperJappie08 commented 5 days ago

After some digging, I found a possible solution, which is to check the function type to not be a setter method here. https://github.com/PyO3/pyo3/blob/8f7450e33d9edcab790d5b2ad303cbb81a86536e/pyo3-macros-backend/src/deprecations.rs#L53-L60

This can probably be done by adding && !matches!(spec.tp, FnType::Setter(_)).

But I am not sure if an error will occur in 0.23 as a result of something somewhere else.