Apply suggestions from davidhewitt

Co-authored-by: David Hewitt <1939362+davidhewitt@users.noreply.github.com>
This commit is contained in:
Yuji Kanagawa 2021-03-07 23:26:45 +09:00 committed by GitHub
parent 7c1cc29612
commit cca560649e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 17 additions and 17 deletions

View File

@ -2,10 +2,10 @@
<!-- Please do not make descriptions too specific, so that we can easily -->
<!-- keep this file in sync with the codebase. -->
# PyO3: Architecture.md
# PyO3: Architecture
This document roughly describes the high-level architecture of PyO3.
If you want to become familiar with the codebase, you are in the right place!
If you want to become familiar with the codebase you are in the right place!
## Overview
@ -14,9 +14,9 @@ Thus, PyO3 has low-level bindings of these API as its core.
On top of that, we have higher-level bindings to operate Python objects safely.
Also, to define Python classes and functions in Rust code, we have `trait PyClass<T>` and a set of
protocol traits (e.g., `PyIterProtocol`) for supporting object protocols (i.e., `__dunder__` methods).
Since implementing `PyClass` requires lots of boilerplates, we have a proc-macro `#[pyclass]`.
Since implementing `PyClass` requires lots of boilerplate, we have a proc-macro `#[pyclass]`.
To summarize, we have mainly four parts in the PyO3 codebase.
To summarize, there are five main parts to the PyO3 codebase.
1. Low-level bindings of Python C/API.
- [`src/ffi`]
2. Bindings to Python objects.
@ -25,7 +25,7 @@ To summarize, we have mainly four parts in the PyO3 codebase.
- [`src/pycell.rs`], [`src/pyclass.rs`]
4. Protocol methods like `__getitem__`.
- [`src/class`]
5. Defining a Python class requires lots of glue code, so we provide proc-macros to simplify the procedure.
5. Procedural macros to simplify usage for users.
- [`src/derive_utils.rs`]
- [`pyo3-macros`], [`pyo3-macros-backend`]
@ -35,15 +35,15 @@ To summarize, we have mainly four parts in the PyO3 codebase.
We aim to provide straight-forward Rust wrappers resembling the file structure of
[`cpython/Include`](https://github.com/python/cpython/tree/v3.9.2/Include).
However, we still lack some API and continue to refactor the module to completely resemble
the CPython's file structure.
However, we still lack some APIs and are continuously updating the the module to match
the file contents upstream in CPython.
The tracking issue is [#1289](https://github.com/PyO3/pyo3/issues/1289), and contribution is welcome.
## Bindings to Python Objects
## Bindings to Python objects
[`src/types`] contains bindings to [built-in types](https://docs.python.org/3/library/stdtypes.html)
of Python, such as `dict` and `list`.
Due to historical reasons, Python's `object` is called `PyAny` and placed in [`src/types/any.rs`].
Currently, `PyAny` is a straight-forward wrapper of `ffi::PyObject`, like:
For historical reasons, Python's `object` is called `PyAny` in PyO3 and located in [`src/types/any.rs`].
Currently, `PyAny` is a straightforward wrapper of `ffi::PyObject`, defined as:
```rust
#[repr(transparent)]
pub struct PyAny(UnsafeCell<ffi::PyObject>);
@ -65,7 +65,7 @@ typedef struct {
```
However, we cannot access such a specific data structure with `#[cfg(Py_LIMITED_API)]` set.
Thus, all builtin objects are implemented as opaque types by wrapping `PyAny`, like:
Thus, all builtin objects are implemented as opaque types by wrapping `PyAny`, e.g.,:
```rust
#[repr(transparent)]
pub struct PyDict(PyAny);
@ -81,7 +81,7 @@ Since we need lots of boilerplate for implementing common traits for these types
[`src/types/mod.rs`].
## PyClass
[`src/pycell.rs`], [`src/pyclass.rs`], and [`src/type_object.rs`] contains types and
[`src/pycell.rs`], [`src/pyclass.rs`], and [`src/type_object.rs`] contain types and
traits to make `#[pyclass]` work.
Also, [`src/pyclass_init.rs`] and [`src/pyclass_slots.rs`] have related functionalities.
@ -106,10 +106,10 @@ pub struct PyCell<T: PyClass> {
}
```
Thus, when copying a Rust struct to a Python object, we first allocate `PyCell` on the Python heap and then
copy `T`.
move `T` into it.
Also, `PyCell` provides [RefCell](https://doc.rust-lang.org/std/cell/struct.RefCell.html)-like methods
to ensure Rust's borrow rules.
See [the document](https://docs.rs/pyo3/latest/pyo3/pycell/struct.PyCell.html) for more.
See [the documentation](https://docs.rs/pyo3/latest/pyo3/pycell/struct.PyCell.html) for more.
`PyCell<T>` requires that `T` implements `PyClass`.
This trait is somewhat complex and derives many traits, but the most important one is `PyTypeObject`
@ -135,11 +135,11 @@ sets `iter<T>` on the type object of `T`.
Also, [`src/class/methods.rs`] has utilities for `#[pyfunction]` and [`src/class/impl_.rs`] has
some internal tricks for making `#[pyproto]` flexible.
## Proc-macros
## Procedural macros
[`pyo3-macros`] provides six proc-macro APIs: `pymodule`, `pyproto`, `pyfunction`, `pyclass`,
`pymethods`, and `#[derive(FromPyObject)]`.
[`pyo3-macros-backend`] has the actual implementations of these APIs.
[`src/derive_utils.rs`] contains some utilities used in codes generated by these proc-macros,
[`src/derive_utils.rs`] contains some utilities used in code generated by these proc-macros,
such as parsing function arguments.
<!-- External Links -->

View File

@ -14,7 +14,7 @@
* Contributing Notes: [github](https://github.com/PyO3/pyo3/blob/master/Contributing.md)
* Brief Architecture Guide: [github](https://github.com/PyO3/pyo3/blob/master/Architecture.md)
* Architecture Guide: [github](https://github.com/PyO3/pyo3/blob/master/Architecture.md)
A comparison with rust-cpython can be found [in the guide](https://pyo3.rs/master/rust_cpython.html).