Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
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
39 changes: 39 additions & 0 deletions .github/workflows/doc-cn-sync.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Sync Translations on Doc Changes

on:
push:
branches: [main]
paths:
- 'guide/**/*.md' # 监控guide下所有.md变化

jobs:
detect-changes:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2 # 获取前一个commit以便diff

- name: Find changed English docs
id: changes
run: |
# git diff找出变化的文件,排除zh-CN
CHANGED_FILES=$(git diff --name-only HEAD^ HEAD -- guide/**/*.md | grep -v '/zh-CN/' || true)
if [ -n "$CHANGED_FILES" ]; then
echo "changed=true" >> $GITHUB_OUTPUT
echo "files<<EOF" >> $GITHUB_OUTPUT
echo "$CHANGED_FILES" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
else
echo "changed=false" >> $GITHUB_OUTPUT
fi

- name: Create issue for translation update
if: steps.changes.outputs.changed == 'true'
uses: peter-evans/create-issue-from-file@v5 # 这个action创建Issue,更灵活(GitHub会自动安装)
with:
title: "英文文档更新:需要同步中文翻译"
content: |
以下英文文件有变化,请检查并更新对应中文版本(在guide/zh-CN/下):

${{ steps.changes.outputs.files }}
18 changes: 18 additions & 0 deletions guide/cn/book.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[book]
title = "PyO3 user guide"
description = "PyO3 user guide"
author = "PyO3 Project and Contributors"
language = "cn"
src = "../src/zh-CN"

[preprocessor.pyo3_version]
command = "python3 guide/pyo3_version.py"

[preprocessor.tabs]

[output.html]
git-repository-url = "https://github.com/PyO3/pyo3/tree/main/guide"
edit-url-template = "https://github.com/PyO3/pyo3/edit/main/guide/{path}"
playground.runnable = false
additional-css = ["../theme/tabs.css"]
additional-js = ["../theme/tabs.js"]
6 changes: 4 additions & 2 deletions guide/book.toml → guide/en/book.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
title = "PyO3 user guide"
description = "PyO3 user guide"
author = "PyO3 Project and Contributors"
language = "en"
src = "../src"

[preprocessor.pyo3_version]
command = "python3 guide/pyo3_version.py"
Expand All @@ -12,5 +14,5 @@ command = "python3 guide/pyo3_version.py"
git-repository-url = "https://github.com/PyO3/pyo3/tree/main/guide"
edit-url-template = "https://github.com/PyO3/pyo3/edit/main/guide/{path}"
playground.runnable = false
additional-css = ["theme/tabs.css"]
additional-js = ["theme/tabs.js"]
additional-css = ["../theme/tabs.css"]
additional-js = ["../theme/tabs.js"]
2 changes: 1 addition & 1 deletion guide/src/async-await.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use pyo3::prelude::*;

#[pyfunction]
#[pyo3(signature=(seconds, result=None))]
async fn sleep(seconds: f64, result: Option<PyObject>) -> Option<PyObject> {
async fn sleep(seconds: f64, result: Option<Py<PyAny>>) -> Option<Py<PyAny>> {
let (tx, rx) = oneshot::channel();
thread::spawn(move || {
thread::sleep(Duration::from_secs_f64(seconds));
Expand Down
11 changes: 8 additions & 3 deletions guide/src/class.md
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ impl SubSubClass {
}

#[staticmethod]
fn factory_method(py: Python<'_>, val: usize) -> PyResult<PyObject> {
fn factory_method(py: Python<'_>, val: usize) -> PyResult<Py<PyAny>> {
let base = PyClassInitializer::from(BaseClass::new());
let sub = base.add_subclass(SubClass { val2: val });
if val % 2 == 0 {
Expand Down Expand Up @@ -748,7 +748,7 @@ To create a constructor which takes a positional class argument, you can combine
# use pyo3::prelude::*;
# use pyo3::types::PyType;
# #[pyclass]
# struct BaseClass(PyObject);
# struct BaseClass(Py<PyAny>);
#
#[pymethods]
impl BaseClass {
Expand Down Expand Up @@ -1385,7 +1385,12 @@ unsafe impl pyo3::type_object::PyTypeInfo for MyClass {
#[inline]
fn type_object_raw(py: pyo3::Python<'_>) -> *mut pyo3::ffi::PyTypeObject {
<Self as pyo3::impl_::pyclass::PyClassImpl>::lazy_type_object()
.get_or_init(py)
.get_or_try_init(py)
.unwrap_or_else(|e| pyo3::impl_::pyclass::type_object_init_failed(
py,
e,
<Self as pyo3::type_object::PyTypeInfo>::NAME
))
.as_type_ptr()
}
}
Expand Down
10 changes: 5 additions & 5 deletions guide/src/class/protocols.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ given signatures should be interpreted as follows:
#[pymethods]
impl NotHashable {
#[classattr]
const __hash__: Option<PyObject> = None;
const __hash__: Option<Py<PyAny>> = None;
}
```
</details>
Expand Down Expand Up @@ -162,15 +162,15 @@ use std::sync::Mutex;

#[pyclass]
struct MyIterator {
iter: Mutex<Box<dyn Iterator<Item = PyObject> + Send>>,
iter: Mutex<Box<dyn Iterator<Item = Py<PyAny>> + Send>>,
}

#[pymethods]
impl MyIterator {
fn __iter__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> {
slf
}
fn __next__(slf: PyRefMut<'_, Self>) -> Option<PyObject> {
fn __next__(slf: PyRefMut<'_, Self>) -> Option<Py<PyAny>> {
slf.iter.lock().unwrap().next()
}
}
Expand Down Expand Up @@ -283,7 +283,7 @@ Use the `#[pyclass(sequence)]` annotation to instruct PyO3 to fill the `sq_lengt
#[pymethods]
impl NoContains {
#[classattr]
const __contains__: Option<PyObject> = None;
const __contains__: Option<Py<PyAny>> = None;
}
```
</details>
Expand Down Expand Up @@ -439,7 +439,7 @@ use pyo3::gc::PyVisit;

#[pyclass]
struct ClassWithGCSupport {
obj: Option<PyObject>,
obj: Option<Py<PyAny>>,
}

#[pymethods]
Expand Down
3 changes: 1 addition & 2 deletions guide/src/conversions/tables.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## Mapping of Rust types to Python types

When writing functions callable from Python (such as a `#[pyfunction]` or in a `#[pymethods]` block), the trait `FromPyObject` is required for function arguments, and `IntoPy<PyObject>` is required for function return values.
When writing functions callable from Python (such as a `#[pyfunction]` or in a `#[pymethods]` block), the trait `FromPyObject` is required for function arguments, and `IntoPyObject` is required for function return values.

Consult the tables in the following section to find the Rust types provided by PyO3 which implement these traits.

Expand Down Expand Up @@ -54,7 +54,6 @@ It is also worth remembering the following special types:
| `Python<'py>` | A GIL token, used to pass to PyO3 constructors to prove ownership of the GIL. |
| `Bound<'py, T>` | A Python object connected to the GIL lifetime. This provides access to most of PyO3's APIs. |
| `Py<T>` | A Python object isolated from the GIL lifetime. This can be sent to other threads. |
| `PyObject` | An alias for `Py<PyAny>` |
| `PyRef<T>` | A `#[pyclass]` borrowed immutably. |
| `PyRefMut<T>` | A `#[pyclass]` borrowed mutably. |

Expand Down
7 changes: 3 additions & 4 deletions guide/src/conversions/traits.md
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,7 @@ forward the implementation to the inner type.

// newtype tuple structs are implicitly `transparent`
#[derive(IntoPyObject)]
struct TransparentTuple(PyObject);
struct TransparentTuple(Py<PyAny>);

#[derive(IntoPyObject)]
#[pyo3(transparent)]
Expand All @@ -599,7 +599,7 @@ For `enum`s each variant is converted according to the rules for `struct`s above

#[derive(IntoPyObject)]
enum Enum<'a, 'py, K: Hash + Eq, V> { // enums are supported and convert using the same
TransparentTuple(PyObject), // rules on the variants as the structs above
TransparentTuple(Py<PyAny>), // rules on the variants as the structs above
#[pyo3(transparent)]
TransparentStruct { inner: Bound<'py, PyAny> },
Tuple(&'a str, HashMap<K, V>),
Expand Down Expand Up @@ -645,7 +645,7 @@ demonstrated below.
```rust,no_run
# use pyo3::prelude::*;
# #[allow(dead_code)]
struct MyPyObjectWrapper(PyObject);
struct MyPyObjectWrapper(Py<PyAny>);

impl<'py> IntoPyObject<'py> for MyPyObjectWrapper {
type Target = PyAny; // the Python type
Expand Down Expand Up @@ -741,7 +741,6 @@ In the example above we used `BoundObject::into_any` and `BoundObject::unbind` t
[`FromPyObject`]: {{#PYO3_DOCS_URL}}/pyo3/conversion/trait.FromPyObject.html
[`IntoPyObject`]: {{#PYO3_DOCS_URL}}/pyo3/conversion/trait.IntoPyObject.html
[`IntoPyObjectExt`]: {{#PYO3_DOCS_URL}}/pyo3/conversion/trait.IntoPyObjectExt.html
[`PyObject`]: {{#PYO3_DOCS_URL}}/pyo3/type.PyObject.html

[`PyRef`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyRef.html
[`PyRefMut`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyRefMut.html
Expand Down
2 changes: 1 addition & 1 deletion guide/src/free-threading.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ simultaneously interacting with the interpreter.
You still need to obtain a `'py` lifetime is to interact with Python
objects or call into the CPython C API. If you are not yet attached to the
Python runtime, you can register a thread using the [`Python::attach`]
function. Threads created via the Python [`threading`] module do not not need to
function. Threads created via the Python [`threading`] module do not need to
do this, and pyo3 will handle setting up the [`Python<'py>`] token when CPython
calls into your extension.

Expand Down
2 changes: 1 addition & 1 deletion guide/src/function/signature.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,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: Py<PyAny>) -> PyResult<()> {
Ok(())
}
```
Expand Down
9 changes: 9 additions & 0 deletions guide/src/migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ For this reason we chose to rename these to more modern terminology introduced i
- `pyo3::prepare_freethreaded_python` is now called `Python::initialize`.
</details>

### Deprecation of `PyObject` type alias
<details open>
<summary><small>Click to expand</small></summary>

The type alias `PyObject` (aka `Py<PyAny>`) is often confused with the identically named FFI definition `pyo3::ffi::PyObject`. For this reason we are deprecating its usage. To migrate simply replace its usage by the target type `Py<PyAny>`.

</details>

### Deprecation of `GILProtected`
<details open>
<summary><small>Click to expand</small></summary>
Expand Down Expand Up @@ -186,6 +194,7 @@ impl ToPyObject for MyPyObjectWrapper {

After:
```rust,no_run
# #![allow(deprecated)]
# use pyo3::prelude::*;
# #[allow(dead_code)]
# struct MyPyObjectWrapper(PyObject);
Expand Down
4 changes: 2 additions & 2 deletions guide/src/python-from-rust/function-calls.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ Both of these APIs take `args` and `kwargs` arguments (for positional and keywor
* [`call1`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.call1) and [`call_method1`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.call_method1) to call only with positional `args`.
* [`call0`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.call0) and [`call_method0`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.call_method0) to call with no arguments.

For convenience the [`Py<T>`](../types.md#pyt-and-pyobject) smart pointer also exposes these same six API methods, but needs a `Python` token as an additional first argument to prove the GIL is held.
For convenience the [`Py<T>`](../types.md#pyt) smart pointer also exposes these same six API methods, but needs a `Python` token as an additional first argument to prove the GIL is held.

The example below calls a Python function behind a `PyObject` (aka `Py<PyAny>`) reference:
The example below calls a Python function behind a `Py<PyAny>` reference:

```rust
use pyo3::prelude::*;
Expand Down
2 changes: 1 addition & 1 deletion guide/src/python-typing-hints.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ impl MyClass {
pub fn __class_getitem__(
cls: &Bound<'_, PyType>,
key: &Bound<'_, PyAny>,
) -> PyResult<PyObject> {
) -> PyResult<Py<PyAny>> {
/* implementation details */
}
}
Expand Down
2 changes: 1 addition & 1 deletion guide/src/trait-bounds.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ How could we expose this solver to Python thanks to PyO3 ?
## Implementation of the trait bounds for the Python class

If a Python class implements the same three methods as the `Model` trait, it seems logical it could be adapted to use the solver.
However, it is not possible to pass a `PyObject` to it as it does not implement the Rust trait (even if the Python model has the required methods).
However, it is not possible to pass a `Py<PyAny>` to it as it does not implement the Rust trait (even if the Python model has the required methods).

In order to implement the trait, we must write a wrapper around the calls in Rust to the Python model.
The method signatures must be the same as the trait, keeping in mind that the Rust trait cannot be changed for the purpose of making the code available in Python.
Expand Down
8 changes: 4 additions & 4 deletions guide/src/types.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ The recommendation of when to use each of these smart pointers is as follows:

The sections below also explain these smart pointers in a little more detail.

### `Py<T>` (and `PyObject`)
### `Py<T>`

[`Py<T>`][Py] is the foundational smart pointer in PyO3's API. The type parameter `T` denotes the type of the Python object. Very frequently this is `PyAny`, meaning any Python object. This is so common that `Py<PyAny>` has a type alias `PyObject`.
[`Py<T>`][Py] is the foundational smart pointer in PyO3's API. The type parameter `T` denotes the type of the Python object. Very frequently this is `PyAny`, meaning any Python object.

Because `Py<T>` is not bound to [the `'py` lifetime](./python-from-rust.md#the-py-lifetime), it is the type to use when storing a Python object inside a Rust `struct` or `enum` which do not want to have a lifetime parameter. In particular, [`#[pyclass]`][pyclass] types are not permitted to have a lifetime, so `Py<T>` is the correct type to store Python objects inside them.

Expand Down Expand Up @@ -117,11 +117,11 @@ fn add<'py>(
# })
```

If naming the `'py` lifetime adds unwanted complexity to the function signature, it is also acceptable to return `PyObject` (aka `Py<PyAny>`), which has no lifetime. The cost is instead paid by a slight increase in implementation complexity, as seen by the introduction of a call to [`Bound::unbind`]:
If naming the `'py` lifetime adds unwanted complexity to the function signature, it is also acceptable to return `Py<PyAny>`, which has no lifetime. The cost is instead paid by a slight increase in implementation complexity, as seen by the introduction of a call to [`Bound::unbind`]:

```rust
# use pyo3::prelude::*;
fn add(left: &Bound<'_, PyAny>, right: &Bound<'_, PyAny>) -> PyResult<PyObject> {
fn add(left: &Bound<'_, PyAny>, right: &Bound<'_, PyAny>) -> PyResult<Py<PyAny>> {
let output: Bound<'_, PyAny> = left.add(right)?;
Ok(output.unbind())
}
Expand Down
52 changes: 52 additions & 0 deletions guide/src/zh-CN/SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# 摘要

[介绍](index.md)

---

- [入门指南](getting-started.md)
- [在 Python 调用 Rust](rust-from-python.md)
- [Python 模块](module.md)
- [Python 函数](function.md)
- [函数签名](function/signature.md)
- [错误处理](function/error-handling.md)
- [Python 类](class.md)
- [类自定义](class/protocols.md)
- [基本对象自定义](class/object.md)
- [模拟数值类型](class/numeric.md)
- [模拟可调用对象](class/call.md)
- [线程安全](class/thread-safety.md)
- [在 Rust 调用 Python](python-from-rust.md)
- [Python 对象类型](types.md)
- [Python 异常](exception.md)
- [调用 Python 函数](python-from-rust/function-calls.md)
- [执行现有的 Python 代码](python-from-rust/calling-existing-code.md)
- [类型转换](conversions.md)
- [Rust 类型到 Python 类型的映射](conversions/tables.md)
- [转换 trait](conversions/traits.md)
- [使用 `async` 和 `await`](async-await.md)
- [并行性](parallelism.md)
- [支持自由线程的 CPython](free-threading.md)
- [调试](debugging.md)
- [功能参考](features.md)
- [性能](performance.md)
- [类型存根生成和内省](type-stub.md)
- [高级主题](advanced.md)
- [构建和分发](building-and-distribution.md)
- [支持多个 Python 版本](building-and-distribution/multiple-python-versions.md)
- [实用的 crate](ecosystem.md)
- [日志记录](ecosystem/logging.md)
- [跟踪](ecosystem/tracing.md)
- [使用 `async` 和 `await`](ecosystem/async-await.md)
- [常见问题和故障排除](faq.md)

---

[附录 A: 迁移指南](migration.md)
[附录 B: Trait 边界](trait-bounds.md)
[附录 C: Python 类型提示](python-typing-hints.md)
[变更日志](changelog.md)

---

[贡献](contributing.md)
5 changes: 5 additions & 0 deletions guide/src/zh-CN/advanced.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# 高级主题

**翻译即将到来。请参阅英文版本:(https://pyo3.rs/main/advanced.html)**

<!-- 即将补充翻译内容 -->
5 changes: 5 additions & 0 deletions guide/src/zh-CN/async-await.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# 使用 `async` 和 `await`

**翻译即将到来。请参阅英文版本:(https://pyo3.rs/main/async-await.html)**

<!-- 即将补充翻译内容 -->
5 changes: 5 additions & 0 deletions guide/src/zh-CN/building-and-distribution.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# 构建和分发

**翻译即将到来。请参阅英文版本:(https://pyo3.rs/main/building-and-distribution.html)**

<!-- 即将补充翻译内容 -->
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# 支持多个 Python 版本

**翻译即将到来。请参阅英文版本:(https://pyo3.rs/main/building-and-distribution/multiple-python-versions.html)**

<!-- 即将补充翻译内容 -->
5 changes: 5 additions & 0 deletions guide/src/zh-CN/changelog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# 变更日志

**翻译即将到来。请参阅英文版本:(https://pyo3.rs/main/changelog.html)**

<!-- 鉴于日志更新频率较高,我们暂未对其进行同步翻译 -->
Loading
Loading