Format recently modified code example from the guide.

This commit is contained in:
Adam Reichold 2023-06-16 08:44:54 +02:00
parent 2996f92ade
commit 684002daf5
8 changed files with 63 additions and 42 deletions

View File

@ -17,6 +17,7 @@ This chapter will discuss the functionality and configuration these attributes o
- [`#[classattr]`](#class-attributes)
- [`#[args]`](#method-arguments)
- [Magic methods and slots](class/protocols.html)
- [Classes as function arguments](#classes-as-function-arguments)
## Defining a new class
@ -718,7 +719,7 @@ impl MyClass {
}
```
## Free functions
## Classes as function arguments
Free functions defined using `#[pyfunction]` interact with classes through the same mechanisms as the self parameters of instance methods, i.e. they can take GIL-bound references, GIL-bound reference wrappers or GIL-indepedent references:
@ -743,7 +744,7 @@ fn print_field(my_class: PyRef<'_, MyClass>) {
println!("{}", my_class.my_field);
}
// Take a GIL-bound reference to the underyling cell
// Take a GIL-bound reference to the underlying cell
// when borrowing needs to be managed manaually.
#[pyfunction]
fn increment_then_print_field(my_class: &PyCell<MyClass>) {

View File

@ -72,7 +72,12 @@ A [previous implementation] used a normal `u64`, which meant it required a `&mut
```rust,ignore
#[pyo3(signature = (*args, **kwargs))]
fn __call__(&mut self, py: Python<'_>, args: &PyTuple, kwargs: Option<&PyDict>) -> PyResult<Py<PyAny>> {
fn __call__(
&mut self,
py: Python<'_>,
args: &PyTuple,
kwargs: Option<&PyDict>,
) -> PyResult<Py<PyAny>> {
self.count += 1;
let name = self.wraps.getattr(py, "__name__")?;

View File

@ -266,16 +266,18 @@ use pyo3::prelude::*;
#[derive(FromPyObject)]
# #[derive(Debug)]
enum RustyEnum<'a> {
Int(usize), // input is a positive int
String(String), // input is a string
IntTuple(usize, usize), // input is a 2-tuple with positive ints
Int(usize), // input is a positive int
String(String), // input is a string
IntTuple(usize, usize), // input is a 2-tuple with positive ints
StringIntTuple(String, usize), // input is a 2-tuple with String and int
Coordinates3d { // needs to be in front of 2d
Coordinates3d {
// needs to be in front of 2d
x: usize,
y: usize,
z: usize,
},
Coordinates2d { // only gets checked if the input did not have `z`
Coordinates2d {
// only gets checked if the input did not have `z`
#[pyo3(attribute("x"))]
a: usize,
#[pyo3(attribute("y"))]

View File

@ -115,9 +115,7 @@ The `#[pyo3]` attribute can be used on individual arguments to modify properties
}
#[pyfunction]
fn object_length(
#[pyo3(from_py_with = "get_length")] argument: usize
) -> usize {
fn object_length(#[pyo3(from_py_with = "get_length")] argument: usize) -> usize {
argument
}

View File

@ -85,10 +85,7 @@ Arguments of type `Python` must not be part of the signature:
# use pyo3::prelude::*;
#[pyfunction]
#[pyo3(signature = (lambda))]
pub fn simple_python_bound_function(
py: Python<'_>,
lambda: PyObject,
) -> PyResult<()> {
pub fn simple_python_bound_function(py: Python<'_>, lambda: PyObject) -> PyResult<()> {
Ok(())
}
```

View File

@ -196,9 +196,8 @@ We can avoid the delay in releasing memory if we are careful to drop the
# use pyo3::prelude::*;
# use pyo3::types::PyString;
# fn main() -> PyResult<()> {
let hello: Py<PyString> = Python::with_gil(|py| {
py.eval("\"Hello World!\"", None, None)?.extract()
})?;
let hello: Py<PyString> =
Python::with_gil(|py| py.eval("\"Hello World!\"", None, None)?.extract())?;
// Do some stuff...
// Now sometime later in the program:
Python::with_gil(|py| {
@ -219,9 +218,8 @@ until the GIL is dropped.
# use pyo3::prelude::*;
# use pyo3::types::PyString;
# fn main() -> PyResult<()> {
let hello: Py<PyString> = Python::with_gil(|py| {
py.eval("\"Hello World!\"", None, None)?.extract()
})?;
let hello: Py<PyString> =
Python::with_gil(|py| py.eval("\"Hello World!\"", None, None)?.extract())?;
// Do some stuff...
// Now sometime later in the program:
Python::with_gil(|py| {

View File

@ -29,7 +29,7 @@ After:
# use pyo3::prelude::*;
#[pyfunction]
#[pyo3(signature = (x, y))] // both x and y have no defaults and are required
#[pyo3(signature = (x, y))] // both x and y have no defaults and are required
fn x_or_y(x: Option<u64>, y: u64) -> u64 {
x.unwrap_or(y)
}
@ -103,12 +103,16 @@ fn raise_err() -> anyhow::Result<()> {
fn main() {
Python::with_gil(|py| {
let rs_func = wrap_pyfunction!(raise_err, py).unwrap();
pyo3::py_run!(py, rs_func, r"
pyo3::py_run!(
py,
rs_func,
r"
try:
rs_func()
except Exception as e:
print(repr(e))
");
"
);
})
}
# }
@ -182,9 +186,7 @@ drop(second);
// Or it ensure releasing the inner lock before the outer one.
Python::with_gil(|py| {
let first = Object::new(py);
let second = Python::with_gil(|py| {
Object::new(py)
});
let second = Python::with_gil(|py| Object::new(py));
drop(first);
drop(second);
});
@ -207,7 +209,7 @@ Before, x in the below example would be required to be passed from Python code:
# use pyo3::prelude::*;
#[pyfunction]
fn required_argument_after_option(x: Option<i32>, y: i32) { }
fn required_argument_after_option(x: Option<i32>, y: i32) {}
```
After, specify the intended Python signature explicitly:
@ -218,11 +220,11 @@ After, specify the intended Python signature explicitly:
// If x really was intended to be required
#[pyfunction(signature = (x, y))]
fn required_argument_after_option_a(x: Option<i32>, y: i32) { }
fn required_argument_after_option_a(x: Option<i32>, y: i32) {}
// If x was intended to be optional, y needs a default too
#[pyfunction(signature = (x=None, y=0))]
fn required_argument_after_option_b(x: Option<i32>, y: i32) { }
fn required_argument_after_option_b(x: Option<i32>, y: i32) {}
```
### `__text_signature__` is now automatically generated for `#[pyfunction]` and `#[pymethods]`

View File

@ -218,18 +218,26 @@ can be used to generate a Python module which can then be used just as if it was
to this function!
```rust
use pyo3::{prelude::*, types::{IntoPyDict, PyModule}};
use pyo3::{
prelude::*,
types::{IntoPyDict, PyModule},
};
# fn main() -> PyResult<()> {
Python::with_gil(|py| {
let activators = PyModule::from_code(py, r#"
let activators = PyModule::from_code(
py,
r#"
def relu(x):
"""see https://en.wikipedia.org/wiki/Rectifier_(neural_networks)"""
return max(0.0, x)
def leaky_relu(x, slope=0.01):
return x if x >= 0 else x * slope
"#, "activators.py", "activators")?;
"#,
"activators.py",
"activators",
)?;
let relu_result: f64 = activators.getattr("relu")?.call1((-1.0,))?.extract()?;
assert_eq!(relu_result, 0.0);
@ -359,7 +367,10 @@ The example below shows:
use pyo3::prelude::*;
fn main() -> PyResult<()> {
let py_foo = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/python_app/utils/foo.py"));
let py_foo = include_str!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/python_app/utils/foo.py"
));
let py_app = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/python_app/app.py"));
let from_python = Python::with_gil(|py| -> PyResult<Py<PyAny>> {
PyModule::from_code(py, py_foo, "utils.foo", "utils.foo")?;
@ -422,7 +433,9 @@ use pyo3::types::PyModule;
fn main() {
Python::with_gil(|py| {
let custom_manager = PyModule::from_code(py, r#"
let custom_manager = PyModule::from_code(
py,
r#"
class House(object):
def __init__(self, address):
self.address = address
@ -434,7 +447,11 @@ class House(object):
else:
print(f"Thank you for visiting {self.address}, come again soon!")
"#, "house.py", "house").unwrap();
"#,
"house.py",
"house",
)
.unwrap();
let house_class = custom_manager.getattr("House").unwrap();
let house = house_class.call1(("123 Main Street",)).unwrap();
@ -448,13 +465,14 @@ class House(object):
match result {
Ok(_) => {
let none = py.None();
house.call_method1("__exit__", (&none, &none, &none)).unwrap();
},
house
.call_method1("__exit__", (&none, &none, &none))
.unwrap();
}
Err(e) => {
house.call_method1(
"__exit__",
(e.get_type(py), e.value(py), e.traceback(py))
).unwrap();
house
.call_method1("__exit__", (e.get_type(py), e.value(py), e.traceback(py)))
.unwrap();
}
}
})