Format recently modified code example from the guide.
This commit is contained in:
parent
2996f92ade
commit
684002daf5
|
@ -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>) {
|
||||
|
|
|
@ -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__")?;
|
||||
|
||||
|
|
|
@ -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"))]
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
```
|
||||
|
|
|
@ -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| {
|
||||
|
|
|
@ -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]`
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue