Skip to content

Commit

Permalink
[WIP, not ready for review] PyCell document
Browse files Browse the repository at this point in the history
  • Loading branch information
kngwyu committed Feb 21, 2020
1 parent 3d0ee2a commit b0b8245
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 7 deletions.
4 changes: 2 additions & 2 deletions guide/src/class.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,10 @@ like [std::cell::RefCell](https://doc.rust-lang.org/std/cell/struct.RefCell.html

Users who are familiar with `RefCell` can use `PyCell` just like `RefCell`.

For users who doesn't know `RefCell` well, we repeat the Rust's borrowing rule here:
For users who doesn't know `RefCell` well, here we repeat the Rust's borrowing rule:
- At any given time, you can have either (but not both of) one mutable reference or any number of immutable references.
- References must always be valid.
`PyCell` ensures these borrowing rules by managing a reference counter.
`PyCell` ensures these borrowing rules by tracking references at runtime.

TODO: link to the API document

Expand Down
24 changes: 19 additions & 5 deletions src/pycell.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! Traits and structs for `#[pyclass]`.
//! Includes `PyCell` implementation.
use crate::conversion::{AsPyPointer, FromPyPointer, ToPyObject};
use crate::pyclass_init::PyClassInitializer;
use crate::pyclass_slots::{PyClassDict, PyClassWeakRef};
Expand Down Expand Up @@ -90,12 +90,19 @@ impl<T: PyClass> PyCellInner<T> {
}
}

// TODO(kngwyu): Mutability example
/// `PyCell` represents the concrete layout of `T: PyClass` when it is converted
/// to a Python class.
/// `PyCell` is the container type for [`PyClass`](trait.PyClass.html).
///
/// You can use it to test your `#[pyclass]` correctly works.
/// From Python side, `PyCell<T>` is the concrete layout of `T: PyClass` in the Python heap,
/// which means we can convert `*const PyClass<T>` to `*mut ffi::PyObject`.
///
/// From Rust side, `PyCell<T>` is the mutable container of `T`.
/// Since `PyCell<T: PyClass>` is always on the Python heap, we don't have the ownership of it.
/// Thus, to mutate the data behind `&PyCell<T>` safely, we employ the
/// [Interior Mutability Pattern](https://doc.rust-lang.org/book/ch15-05-interior-mutability.html)
/// like [std::cell::RefCell](https://doc.rust-lang.org/std/cell/struct.RefCell.html).
///
/// In most cases, `PyCell` is hidden behind `#[pymethods]`.
/// However, you can construct `&PyCell` directly to test your pyclass in Rust code.
/// ```
/// # use pyo3::prelude::*;
/// # use pyo3::{py_run, PyCell};
Expand All @@ -112,6 +119,7 @@ impl<T: PyClass> PyCellInner<T> {
/// author: "Philip Kindred Dick",
/// };
/// let book_cell = PyCell::new(py, book).unwrap();
/// // you can expose PyCell to Python snippets
/// py_run!(py, book_cell, "assert book_cell.name[-6:] == 'Castle'");
/// ```
#[repr(C)]
Expand Down Expand Up @@ -254,6 +262,9 @@ impl<T: PyClass + fmt::Debug> fmt::Debug for PyCell<T> {
}
}

/// Wraps a borrowed reference to a value in a `PyCell<T>`.
///
/// See the [`PyCell`](struct.PyCell.html) documentation for more.
pub struct PyRef<'p, T: PyClass> {
inner: &'p PyCellInner<T>,
}
Expand Down Expand Up @@ -319,6 +330,9 @@ impl<T: PyClass + fmt::Debug> fmt::Debug for PyRef<'_, T> {
}
}

/// Wraps a mutable borrowed reference to a value in a `PyCell<T>`.
///
/// See the [`PyCell`](struct.PyCell.html) documentation for more.
pub struct PyRefMut<'p, T: PyClass> {
inner: &'p PyCellInner<T>,
}
Expand Down

0 comments on commit b0b8245

Please sign in to comment.