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

documentation for IntoPy #1578

Merged
merged 2 commits into from
Apr 29, 2021
Merged

documentation for IntoPy #1578

merged 2 commits into from
Apr 29, 2021

Conversation

mejrs
Copy link
Member

@mejrs mejrs commented Apr 27, 2021

Added some documentation for IntoPy, but not the redirect I was planning on, I'll do that after #1128 lands.

Rendered

Defines a conversion from a Rust type to a Python object.

It functions similarly to std's Into trait,
but requires a GIL token as an argument.
Many functions and traits internal to PyO3 require this trait as a bound,
so a lack of this trait can manifest itself in different error messages.

Examples

With #[pyclass]

The easiest way to implement IntoPy is by exposing a struct as a native Python object
by annotating it with #[pyclass].

use pyo3::prelude::*;

#[pyclass]
struct Number {
	  #[pyo3(get, set)]
  value: i32,
}

Python code will see this as an instance of the Number class with a value attribute.

Conversion to a Python object

However, it may not be desirable to expose the existence of Number to Python code.
IntoPy allows us to define a conversion to an appropriate Python object.

use pyo3::prelude::*;

struct Number {
  value: i32,
}

impl IntoPy<PyObject> for Number {
    fn into_py(self, py: Python) -> PyObject {
        // delegates to i32's IntoPy implementation.
        self.value.into_py(py)
   }
}

Python code will see this as an int object.

Dynamic conversion into Python objects.

It is also possible to return a different Python object depending on some condition.
This is useful for types like enums that can carry different types.

use pyo3::prelude::*;

enum Value {
    Integer(i32),
    String(String),
    None
}

impl IntoPy<PyObject> for Value {
    fn into_py(self, py: Python) -> PyObject {
        match self {
            Self::Integer(val) => val.into_py(py),
            Self::String(val) => val.into_py(py),
            Self::None => py.None()
        }
   }
}

Python code will see this as any of the int, string or None objects.

Copy link
Member

@davidhewitt davidhewitt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️ 🚀 This is absolutely brilliant! Thank you so much for writing this!

No nits at all; it's just great 🚀

@davidhewitt davidhewitt merged commit fc6a20f into PyO3:main Apr 29, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants