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

Rename Py<T> to PyDetached<T> #3655

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions examples/decorator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub struct PyCounter {
count: Cell<u64>,

// This is the actual function being wrapped.
wraps: Py<PyAny>,
wraps: PyDetached<PyAny>,
}

#[pymethods]
Expand All @@ -24,7 +24,7 @@ impl PyCounter {
// 1. It doesn't guarantee the object can actually be called successfully
// 2. We still need to handle any exceptions that the function might raise
#[new]
fn __new__(wraps: Py<PyAny>) -> Self {
fn __new__(wraps: PyDetached<PyAny>) -> Self {
PyCounter {
count: Cell::new(0),
wraps,
Expand All @@ -42,7 +42,7 @@ impl PyCounter {
py: Python<'_>,
args: &PyTuple,
kwargs: Option<&PyDict>,
) -> PyResult<Py<PyAny>> {
) -> PyResult<PyDetached<PyAny>> {
let old_count = self.count.get();
let new_count = old_count + 1;
self.count.set(new_count);
Expand Down
32 changes: 16 additions & 16 deletions guide/src/class.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ Rust lifetimes are used by the Rust compiler to reason about a program's memory

As soon as Rust data is exposed to Python, there is no guarantee that the Rust compiler can make on how long the data will live. Python is a reference-counted language and those references can be held for an arbitrarily long time which is untraceable by the Rust compiler. The only possible way to express this correctly is to require that any `#[pyclass]` does not borrow data for any lifetime shorter than the `'static` lifetime, i.e. the `#[pyclass]` cannot have any lifetime parameters.

When you need to share ownership of data between Python and Rust, instead of using borrowed references with lifetimes consider using reference-counted smart pointers such as [`Arc`] or [`Py`].
When you need to share ownership of data between Python and Rust, instead of using borrowed references with lifetimes consider using reference-counted smart pointers such as [`Arc`] or [`PyDetached`].

#### No generic parameters

Expand Down Expand Up @@ -115,7 +115,7 @@ impl Nonzero {
```

If you want to return an existing object (for example, because your `new`
method caches the values it returns), `new` can return `pyo3::Py<Self>`.
method caches the values it returns), `new` can return `pyo3::PyDetached<Self>`.

As you can see, the Rust method name is not important here; this way you can
still, use `new()` for a Rust-level constructor.
Expand Down Expand Up @@ -202,14 +202,14 @@ struct MyClass {
num: i32,
}

fn return_myclass() -> Py<MyClass> {
Python::with_gil(|py| Py::new(py, MyClass { num: 1 }).unwrap())
fn return_myclass() -> PyDetached<MyClass> {
Python::with_gil(|py| PyDetached::new(py, MyClass { num: 1 }).unwrap())
}

let obj = return_myclass();

Python::with_gil(|py| {
let cell = obj.as_ref(py); // Py<MyClass>::as_ref returns &PyCell<MyClass>
let cell = obj.as_ref(py); // PyDetached<MyClass>::as_ref returns &PyCell<MyClass>
let obj_ref = cell.borrow(); // Get PyRef<T>
assert_eq!(obj_ref.num, 1);
});
Expand All @@ -230,12 +230,12 @@ struct FrozenCounter {
value: AtomicUsize,
}

let py_counter: Py<FrozenCounter> = Python::with_gil(|py| {
let py_counter: PyDetached<FrozenCounter> = Python::with_gil(|py| {
let counter = FrozenCounter {
value: AtomicUsize::new(0),
};

Py::new(py, counter).unwrap()
PyDetached::new(py, counter).unwrap()
});

py_counter.get().value.fetch_add(1, Ordering::Relaxed);
Expand Down Expand Up @@ -343,10 +343,10 @@ impl SubSubClass {
let base = PyClassInitializer::from(BaseClass::new());
let sub = base.add_subclass(SubClass { val2: val });
if val % 2 == 0 {
Ok(Py::new(py, sub)?.to_object(py))
Ok(PyDetached::new(py, sub)?.to_object(py))
} else {
let sub_sub = sub.add_subclass(SubSubClass { val3: val });
Ok(Py::new(py, sub_sub)?.to_object(py))
Ok(PyDetached::new(py, sub_sub)?.to_object(py))
}
}
}
Expand Down Expand Up @@ -778,7 +778,7 @@ fn increment_then_print_field(my_class: &PyCell<MyClass>) {

// Take a GIL-indepedent reference when you want to store the reference elsewhere.
#[pyfunction]
fn print_refcnt(my_class: Py<MyClass>, py: Python<'_>) {
fn print_refcnt(my_class: PyDetached<MyClass>, py: Python<'_>) {
println!("{}", my_class.get_refcnt(py));
}
```
Expand Down Expand Up @@ -971,8 +971,8 @@ enum MyEnum {
}

Python::with_gil(|py| {
let x = Py::new(py, MyEnum::Variant).unwrap();
let y = Py::new(py, MyEnum::OtherVariant).unwrap();
let x = PyDetached::new(py, MyEnum::Variant).unwrap();
let y = PyDetached::new(py, MyEnum::OtherVariant).unwrap();
let cls = py.get_type::<MyEnum>();
pyo3::py_run!(py, x y cls, r#"
assert x == cls.Variant
Expand Down Expand Up @@ -1016,7 +1016,7 @@ enum MyEnum{

Python::with_gil(|py| {
let cls = py.get_type::<MyEnum>();
let x = Py::new(py, MyEnum::Variant).unwrap();
let x = PyDetached::new(py, MyEnum::Variant).unwrap();
pyo3::py_run!(py, cls x, r#"
assert repr(x) == 'MyEnum.Variant'
assert repr(cls.OtherVariant) == 'MyEnum.OtherVariant'
Expand Down Expand Up @@ -1057,7 +1057,7 @@ enum MyEnum {
}

Python::with_gil(|py| {
let x = Py::new(py, MyEnum::Variant).unwrap();
let x = PyDetached::new(py, MyEnum::Variant).unwrap();
let cls = py.get_type::<MyEnum>();
pyo3::py_run!(py, x cls, r#"
assert repr(x) == 'RenamedEnum.UPPERCASE'
Expand Down Expand Up @@ -1148,7 +1148,7 @@ impl<'a, 'py> pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'py> for &'a

impl pyo3::IntoPy<PyObject> for MyClass {
fn into_py(self, py: pyo3::Python<'_>) -> pyo3::PyObject {
pyo3::IntoPy::into_py(pyo3::Py::new(py, self).unwrap(), py)
pyo3::IntoPy::into_py(pyo3::PyDetached::new(py, self).unwrap(), py)
}
}

Expand Down Expand Up @@ -1196,7 +1196,7 @@ impl pyo3::impl_::pyclass::PyClassImpl for MyClass {
[`GILGuard`]: {{#PYO3_DOCS_URL}}/pyo3/struct.GILGuard.html
[`PyTypeInfo`]: {{#PYO3_DOCS_URL}}/pyo3/type_object/trait.PyTypeInfo.html

[`Py`]: {{#PYO3_DOCS_URL}}/pyo3/struct.Py.html
[`PyDetached`]: {{#PYO3_DOCS_URL}}/pyo3/struct.PyDetached.html
[`PyCell`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyCell.html
[`PyClass`]: {{#PYO3_DOCS_URL}}/pyo3/pyclass/trait.PyClass.html
[`PyRef`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyRef.html
Expand Down
2 changes: 1 addition & 1 deletion guide/src/class/call.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ fn __call__(
py: Python<'_>,
args: &PyTuple,
kwargs: Option<&PyDict>,
) -> PyResult<Py<PyAny>> {
) -> PyResult<PyDetached<PyAny>> {
self.count += 1;
let name = self.wraps.getattr(py, "__name__")?;

Expand Down
2 changes: 1 addition & 1 deletion guide/src/class/object.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ impl Number {
> #[pymethods]
> impl NotHashable {
> #[classattr]
> const __hash__: Option<Py<PyAny>> = None;
> const __hash__: Option<PyDetached<PyAny>> = None;
> }
> ```

Expand Down
4 changes: 2 additions & 2 deletions guide/src/class/protocols.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,11 +197,11 @@ struct Container {

#[pymethods]
impl Container {
fn __iter__(slf: PyRef<'_, Self>) -> PyResult<Py<Iter>> {
fn __iter__(slf: PyRef<'_, Self>) -> PyResult<PyDetached<Iter>> {
let iter = Iter {
inner: slf.iter.clone().into_iter(),
};
Py::new(slf.py(), iter)
PyDetached::new(slf.py(), iter)
}
}

Expand Down
6 changes: 3 additions & 3 deletions guide/src/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,15 +131,15 @@ struct Inner {/* fields omitted */}
#[pyclass]
struct Outer {
#[pyo3(get)]
inner: Py<Inner>,
inner: PyDetached<Inner>,
}

#[pymethods]
impl Outer {
#[new]
fn __new__(py: Python<'_>) -> PyResult<Self> {
Ok(Self {
inner: Py::new(py, Inner {})?,
inner: PyDetached::new(py, Inner {})?,
})
}
}
Expand Down Expand Up @@ -183,7 +183,7 @@ struct MyClass;

## I'm trying to call Python from Rust but I get `STATUS_DLL_NOT_FOUND` or `STATUS_ENTRYPOINT_NOT_FOUND`!

This happens on Windows when linking to the python DLL fails or the wrong one is linked. The Python DLL on Windows will usually be called something like:
This happens on Windows when linking to the python DLL fails or the wrong one is linked. The Python DLL on Windows will usually be called something like:
- `python3X.dll` for Python 3.X, e.g. `python310.dll` for Python 3.10
- `python3.dll` when using PyO3's `abi3` feature

Expand Down
2 changes: 1 addition & 1 deletion guide/src/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ struct Permission {
#[derive(Serialize, Deserialize)]
struct User {
username: String,
permissions: Vec<Py<Permission>>,
permissions: Vec<PyDetached<Permission>>,
}
# }
```
Expand Down
8 changes: 4 additions & 4 deletions guide/src/memory.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ reference count reaches zero? It depends whether or not we are holding the GIL.
# use pyo3::types::PyString;
# fn main() -> PyResult<()> {
Python::with_gil(|py| -> PyResult<()> {
let hello: Py<PyString> = py.eval("\"Hello World!\"", None, None)?.extract()?;
let hello: PyDetached<PyString> = py.eval("\"Hello World!\"", None, None)?.extract()?;
println!("Python says: {}", hello.as_ref(py));
Ok(())
})?;
Expand All @@ -165,7 +165,7 @@ we are *not* holding the GIL?
# use pyo3::prelude::*;
# use pyo3::types::PyString;
# fn main() -> PyResult<()> {
let hello: Py<PyString> = Python::with_gil(|py| {
let hello: PyDetached<PyString> = Python::with_gil(|py| {
py.eval("\"Hello World!\"", None, None)?.extract()
})?;
// Do some stuff...
Expand Down Expand Up @@ -196,7 +196,7 @@ 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> =
let hello: PyDetached<PyString> =
Python::with_gil(|py| py.eval("\"Hello World!\"", None, None)?.extract())?;
// Do some stuff...
// Now sometime later in the program:
Expand All @@ -218,7 +218,7 @@ until the GIL is dropped.
# use pyo3::prelude::*;
# use pyo3::types::PyString;
# fn main() -> PyResult<()> {
let hello: Py<PyString> =
let hello: PyDetached<PyString> =
Python::with_gil(|py| py.eval("\"Hello World!\"", None, None)?.extract())?;
// Do some stuff...
// Now sometime later in the program:
Expand Down
8 changes: 4 additions & 4 deletions guide/src/migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ drop(second);

The replacement is [`Python::with_gil`]() which is more cumbersome but enforces the proper nesting by design, e.g.

```rust
```rust,ignore
# #![allow(dead_code)]
# use pyo3::prelude::*;

Expand Down Expand Up @@ -464,7 +464,7 @@ Python::with_gil(|py| {

After, some type annotations may be necessary:

```rust
```rust,ignore
# use pyo3::prelude::*;
#
# fn main() {
Expand Down Expand Up @@ -579,7 +579,7 @@ impl MyClass {

### Removed `PartialEq` for object wrappers

The Python object wrappers `Py` and `PyAny` had implementations of `PartialEq`
The Python object wrappers `PyDetached` and `PyAny` had implementations of `PartialEq`
so that `object_a == object_b` would compare the Python objects for pointer
equality, which corresponds to the `is` operator, not the `==` operator in
Python. This has been removed in favor of a new method: use
Expand Down Expand Up @@ -921,7 +921,7 @@ let list_ref: &PyList = list_py.as_ref(py);
```

After:
```rust
```rust,ignore
use pyo3::{Py, types::PyList};
# pyo3::Python::with_gil(|py| {
let list_py: Py<PyList> = PyList::empty(py).into();
Expand Down
4 changes: 2 additions & 2 deletions guide/src/performance.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ For example, instead of writing
# use pyo3::prelude::*;
# use pyo3::types::PyList;

struct Foo(Py<PyList>);
struct Foo(PyDetached<PyList>);

struct FooRef<'a>(&'a PyList);

Expand All @@ -81,7 +81,7 @@ use more efficient
# #![allow(dead_code)]
# use pyo3::prelude::*;
# use pyo3::types::PyList;
# struct Foo(Py<PyList>);
# struct Foo(PyDetached<PyList>);
# struct FooRef<'a>(&'a PyList);
#
impl PartialEq<Foo> for FooRef<'_> {
Expand Down
12 changes: 6 additions & 6 deletions guide/src/python_from_rust.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ fn main() -> PyResult<()> {
let arg3 = "arg3";

Python::with_gil(|py| {
let fun: Py<PyAny> = PyModule::from_code(
let fun: PyDetached<PyAny> = PyModule::from_code(
py,
"def example(*args, **kwargs):
if args != ():
Expand Down Expand Up @@ -78,7 +78,7 @@ fn main() -> PyResult<()> {
let val2 = 2;

Python::with_gil(|py| {
let fun: Py<PyAny> = PyModule::from_code(
let fun: PyDetached<PyAny> = PyModule::from_code(
py,
"def example(*args, **kwargs):
if args != ():
Expand Down Expand Up @@ -372,9 +372,9 @@ fn main() -> PyResult<()> {
"/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>> {
let from_python = Python::with_gil(|py| -> PyResult<PyDetached<PyAny>> {
PyModule::from_code(py, py_foo, "utils.foo", "utils.foo")?;
let app: Py<PyAny> = PyModule::from_code(py, py_app, "", "")?
let app: PyDetached<PyAny> = PyModule::from_code(py, py_app, "", "")?
.getattr("run")?
.into();
app.call0(py)
Expand Down Expand Up @@ -405,10 +405,10 @@ use std::path::Path;
fn main() -> PyResult<()> {
let path = Path::new("/usr/share/python_app");
let py_app = fs::read_to_string(path.join("app.py"))?;
let from_python = Python::with_gil(|py| -> PyResult<Py<PyAny>> {
let from_python = Python::with_gil(|py| -> PyResult<PyDetached<PyAny>> {
let syspath: &PyList = py.import("sys")?.getattr("path")?.downcast()?;
syspath.insert(0, &path)?;
let app: Py<PyAny> = PyModule::from_code(py, &py_app, "", "")?
let app: PyDetached<PyAny> = PyModule::from_code(py, &py_app, "", "")?
.getattr("run")?
.into();
app.call0(py)
Expand Down
Loading