Merge pull request #1540 from davidhewitt/guide-auto-versions

guide: automatically set pyo3 version in links and cargo toml
This commit is contained in:
Yuji Kanagawa 2021-04-03 18:18:25 +09:00 committed by GitHub
commit 6c577962bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 128 additions and 72 deletions

View File

@ -21,11 +21,19 @@ jobs:
- name: Setup mdBook
uses: peaceiris/actions-mdbook@v1
with:
mdbook-version: '0.4.5'
mdbook-version: '0.4.9'
- name: Prepare tag
id: prepare_tag
run: |
TAG_NAME="${GITHUB_REF##*/}"
echo "::set-output name=tag_name::${TAG_NAME}"
# This builds the book in gh-pages-build. See https://github.com/rust-lang-nursery/mdBook/issues/698
- name: Build the guide
run: mdbook build -d ../gh-pages-build guide
env:
PYO3_VERSION_TAG: ${{ steps.prepare_tag.outputs.tag_name }}
# This adds the docs to gh-pages-build/doc
- name: Build the doc
@ -34,12 +42,6 @@ jobs:
cp -r target/doc gh-pages-build/doc
echo "<meta http-equiv=refresh content=0;url=pyo3/index.html>" > gh-pages-build/doc/index.html
- name: Prepare tag
id: prepare_tag
run: |
TAG_NAME="${GITHUB_REF##*/}"
echo "::set-output name=tag_name::${TAG_NAME}"
- name: Deploy
uses: peaceiris/actions-gh-pages@v3.7.0-8
with:

View File

@ -2,3 +2,6 @@
title = "PyO3 user guide"
description = "PyO3 user guide"
author = "PyO3 Project and Contributors"
[preprocessor.pyo3_version]
command = "python guide/pyo3_version.py"

50
guide/pyo3_version.py Normal file
View File

@ -0,0 +1,50 @@
"""Simple mdbook preprocessor to inject pyo3 version into the guide.
It will replace:
- {{#PYO3_VERSION_TAG}} with the contents of the PYO3_VERSION_TAG environment var
- {{#PYO3_DOCS_URL}} with the location of docs (e.g. https://docs.rs/pyo3/0.13.2)
- {{#PYO3_CRATE_VERSION}} with a relevant toml snippet (e.g. version = "0.13.2")
Tested against mdbook 0.4.9.
"""
import json
import os
import sys
# Set PYO3_VERSION in CI to build the correct version into links
PYO3_VERSION_TAG = os.environ.get("PYO3_VERSION_TAG", "main")
if PYO3_VERSION_TAG == "main":
PYO3_DOCS_URL = "https://pyo3.rs/main/doc"
PYO3_CRATE_VERSION = 'git = "https://github.com/pyo3/pyo3"'
else:
# v0.13.2 -> 0.13.2
version = PYO3_VERSION_TAG.lstrip("v")
PYO3_DOCS_URL = f"https://docs.rs/pyo3/{version}"
PYO3_CRATE_VERSION = f'version = "{version}"'
def replace_section_content(section):
if not isinstance(section, dict) or "Chapter" not in section:
return
# Replace raw and url-encoded forms
section["Chapter"]["content"] = (
section["Chapter"]["content"]
.replace("{{#PYO3_VERSION_TAG}}", PYO3_VERSION_TAG)
.replace("{{#PYO3_DOCS_URL}}", PYO3_DOCS_URL)
.replace("{{#PYO3_CRATE_VERSION}}", PYO3_CRATE_VERSION)
)
for sub_item in section["Chapter"]["sub_items"]:
replace_section_content(sub_item)
for line in sys.stdin:
if line:
[context, book] = json.loads(line)
for section in book["sections"]:
replace_section_content(section)
json.dump(book, fp=sys.stdout)

View File

@ -14,7 +14,8 @@ If you have e.g. a library crate and a profiling crate alongside, you need to us
```toml
[dependencies]
pyo3 = "0.6"
pyo3 = { {{#PYO3_CRATE_VERSION}} }
[lib]
name = "hyperjson"
@ -29,7 +30,7 @@ And this in the profiling crate:
```toml
[dependencies]
my_main_crate = { path = "..", default-features = false }
pyo3 = "0.6"
pyo3 = { {{#PYO3_CRATE_VERSION}} }
```
On Linux/macOS you might have to change `LD_LIBRARY_PATH` to include libpython, while on windows you might need to set `LIB` to include `pythonxy.lib` (where x and y are major and minor version), which is normally either in the `libs` or `Lib` folder of a Python installation.
@ -51,7 +52,7 @@ There are three steps involved in making use of `abi3` when building Python pack
```toml
[dependencies]
pyo3 = { version = "...", features = ["abi3"]}
pyo3 = { {{#PYO3_CRATE_VERSION}}, features = ["abi3"] }
```
2. Ensure that the built shared objects are correctly marked as `abi3`. This is accomplished by telling your build system that you're using the limited API.

View File

@ -137,7 +137,7 @@ The `#[pyclass]` macro accepts the following parameters:
The performance improvement applies to types that are often created and deleted in a row,
so that they can benefit from a freelist. `XXX` is a number of items for the free list.
* `gc` - Classes with the `gc` parameter participate in Python garbage collection.
If a custom class contains references to other Python objects that can be collected, the [`PyGCProtocol`](https://docs.rs/pyo3/latest/pyo3/class/gc/trait.PyGCProtocol.html) trait has to be implemented.
If a custom class contains references to other Python objects that can be collected, the [`PyGCProtocol`]({{#PYO3_DOCS_URL}}/pyo3/class/gc/trait.PyGCProtocol.html) trait has to be implemented.
* `weakref` - Adds support for Python weak references.
* `extends=BaseType` - Use a custom base class. The base `BaseType` must implement `PyTypeInfo`.
* `subclass` - Allows Python classes to inherit from this class.
@ -267,7 +267,7 @@ impl SubSubClass {
```
You can also inherit native types such as `PyDict`, if they implement
[`PySizedLayout`](https://docs.rs/pyo3/latest/pyo3/type_object/trait.PySizedLayout.html). However, this is not supported when building for the Python limited API (aka the `abi3` feature of PyO3).
[`PySizedLayout`]({{#PYO3_DOCS_URL}}/pyo3/type_object/trait.PySizedLayout.html). However, this is not supported when building for the Python limited API (aka the `abi3` feature of PyO3).
However, because of some technical problems, we don't currently provide safe upcasting methods for types
that inherit native types. Even in such cases, you can unsafely get a base class by raw pointer conversion.
@ -813,15 +813,15 @@ impl pyo3::class::impl_::PyClassImpl for MyClass {
```
[`GILGuard`]: https://docs.rs/pyo3/latest/pyo3/struct.GILGuard.html
[`PyTypeInfo`]: https://docs.rs/pyo3/latest/pyo3/type_object/trait.PyTypeInfo.html
[`PyTypeObject`]: https://docs.rs/pyo3/latest/pyo3/type_object/trait.PyTypeObject.html
[`GILGuard`]: {{#PYO3_DOCS_URL}}/pyo3/struct.GILGuard.html
[`PyTypeInfo`]: {{#PYO3_DOCS_URL}}/pyo3/type_object/trait.PyTypeInfo.html
[`PyTypeObject`]: {{#PYO3_DOCS_URL}}/pyo3/type_object/trait.PyTypeObject.html
[`PyCell`]: https://docs.rs/pyo3/latest/pyo3/pycell/struct.PyCell.html
[`PyClass`]: https://docs.rs/pyo3/latest/pyo3/pyclass/trait.PyClass.html
[`PyRef`]: https://docs.rs/pyo3/latest/pyo3/pycell/struct.PyRef.html
[`PyRefMut`]: https://docs.rs/pyo3/latest/pyo3/pycell/struct.PyRefMut.html
[`PyClassInitializer<T>`]: https://docs.rs/pyo3/latest/pyo3/pyclass_init/struct.PyClassInitializer.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
[`PyRefMut`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyRefMut.html
[`PyClassInitializer<T>`]: {{#PYO3_DOCS_URL}}/pyo3/pyclass_init/struct.PyClassInitializer.html
[`RefCell`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html

View File

@ -204,7 +204,7 @@ struct GCTracked {} // Fails because it does not implement PyGCProtocol
### Iterator Types
Iterators can be defined using the
[`PyIterProtocol`](https://docs.rs/pyo3/latest/pyo3/class/iter/trait.PyIterProtocol.html) trait.
[`PyIterProtocol`]({{#PYO3_DOCS_URL}}/pyo3/class/iter/trait.PyIterProtocol.html) trait.
It includes two methods `__iter__` and `__next__`:
* `fn __iter__(slf: PyRefMut<Self>) -> PyResult<impl IntoPy<PyObject>>`
* `fn __next__(slf: PyRefMut<Self>) -> PyResult<Option<impl IntoPy<PyObject>>>`
@ -290,9 +290,9 @@ documentation](https://docs.python.org/3/library/stdtypes.html#iterator-types).
This guide has so far shown how to use `Option<T>` to implement yielding values during iteration.
In Python a generator can also return a value. To express this in Rust, PyO3 provides the
[`IterNextOutput`](https://docs.rs/pyo3/latest/pyo3/class/iter/enum.IterNextOutput.html) enum to
[`IterNextOutput`]({{#PYO3_DOCS_URL}}/pyo3/class/iter/enum.IterNextOutput.html) enum to
both `Yield` values and `Return` a final value - see its docs for further details and an example.
[`PyGCProtocol`]: https://docs.rs/pyo3/latest/pyo3/class/gc/trait.PyGCProtocol.html
[`PyNumberProtocol`]: https://docs.rs/pyo3/latest/pyo3/class/number/trait.PyNumberProtocol.html
[`PyObjectProtocol`]: https://docs.rs/pyo3/latest/pyo3/class/basic/trait.PyObjectProtocol.html
[`PyGCProtocol`]: {{#PYO3_DOCS_URL}}/pyo3/class/gc/trait.PyGCProtocol.html
[`PyNumberProtocol`]: {{#PYO3_DOCS_URL}}/pyo3/class/number/trait.PyNumberProtocol.html
[`PyObjectProtocol`]: {{#PYO3_DOCS_URL}}/pyo3/class/basic/trait.PyObjectProtocol.html

View File

@ -221,10 +221,10 @@ impl IntoPy<PyObject> for MyPyObjectWrapper {
converted into [`PyObject`]. `IntoPy<PyObject>` serves the
same purpose, except that it consumes `self`.
[`IntoPy`]: https://docs.rs/pyo3/latest/pyo3/conversion/trait.IntoPy.html
[`FromPyObject`]: https://docs.rs/pyo3/latest/pyo3/conversion/trait.FromPyObject.html
[`ToPyObject`]: https://docs.rs/pyo3/latest/pyo3/conversion/trait.ToPyObject.html
[`PyObject`]: https://docs.rs/pyo3/latest/pyo3/type.PyObject.html
[`IntoPy`]: {{#PYO3_DOCS_URL}}/pyo3/conversion/trait.IntoPy.html
[`FromPyObject`]: {{#PYO3_DOCS_URL}}/pyo3/conversion/trait.FromPyObject.html
[`ToPyObject`]: {{#PYO3_DOCS_URL}}/pyo3/conversion/trait.ToPyObject.html
[`PyObject`]: {{#PYO3_DOCS_URL}}/pyo3/type.PyObject.html
[`PyRef`]: https://docs.rs/pyo3/latest/pyo3/pycell/struct.PyRef.html
[`PyRefMut`]: https://docs.rs/pyo3/latest/pyo3/pycell/struct.PyRefMut.html
[`PyRef`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyRef.html
[`PyRefMut`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyRefMut.html

View File

@ -49,7 +49,7 @@ fn mymodule(py: Python, m: &PyModule) -> PyResult<()> {
## Raising an exception
To raise an exception, first you need to obtain an exception type and construct a new [`PyErr`], then call the [`PyErr::restore`](https://docs.rs/pyo3/latest/pyo3/struct.PyErr.html#method.restore) method to write the exception back to the Python interpreter's global state.
To raise an exception, first you need to obtain an exception type and construct a new [`PyErr`], then call the [`PyErr::restore`]({{#PYO3_DOCS_URL}}/pyo3/struct.PyErr.html#method.restore) method to write the exception back to the Python interpreter's global state.
```rust
use pyo3::{Python, PyErr};
@ -105,7 +105,7 @@ Python::with_gil(|py| {
assert!(list.is_instance::<PyList>().unwrap());
});
```
[`PyAny::is_instance`] calls the underlying [`PyType::is_instance`](https://docs.rs/pyo3/latest/pyo3/types/struct.PyType.html#method.is_instance)
[`PyAny::is_instance`] calls the underlying [`PyType::is_instance`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyType.html#method.is_instance)
method to do the actual work.
To check the type of an exception, you can similarly do:
@ -122,7 +122,7 @@ err.is_instance::<PyTypeError>(py);
## Handling Rust errors
The vast majority of operations in this library will return
[`PyResult<T>`](https://docs.rs/pyo3/latest/pyo3/prelude/type.PyResult.html),
[`PyResult<T>`]({{#PYO3_DOCS_URL}}/pyo3/prelude/type.PyResult.html),
which is an alias for the type `Result<T, PyErr>`.
A [`PyErr`] represents a Python exception. Errors within the PyO3 library are also exposed as
@ -181,7 +181,7 @@ fn parse_int(s: String) -> PyResult<usize> {
The code snippet above will raise a `ValueError` in Python if `String::parse()` returns an error.
If lazy construction of the Python exception instance is desired, the
[`PyErrArguments`](https://docs.rs/pyo3/latest/pyo3/trait.PyErrArguments.html)
[`PyErrArguments`]({{#PYO3_DOCS_URL}}/pyo3/trait.PyErrArguments.html)
trait can be implemented. In that case, actual exception argument creation is delayed
until the `PyErr` is needed.
@ -209,13 +209,13 @@ fn tell(file: &PyAny) -> PyResult<u64> {
```
[`pyo3::exceptions`](https://docs.rs/pyo3/latest/pyo3/exceptions/index.html)
[`pyo3::exceptions`]({{#PYO3_DOCS_URL}}/pyo3/exceptions/index.html)
defines exceptions for several standard library modules.
[`create_exception!`]: https://docs.rs/pyo3/latest/pyo3/macro.create_exception.html
[`import_exception!`]: https://docs.rs/pyo3/latest/pyo3/macro.import_exception.html
[`create_exception!`]: {{#PYO3_DOCS_URL}}/pyo3/macro.create_exception.html
[`import_exception!`]: {{#PYO3_DOCS_URL}}/pyo3/macro.import_exception.html
[`PyErr`]: https://docs.rs/pyo3/latest/pyo3/struct.PyErr.html
[`PyErr::from_instance`]: https://docs.rs/pyo3/latest/pyo3/struct.PyErr.html#method.from_instance
[`Python::is_instance`]: https://docs.rs/pyo3/latest/pyo3/struct.Python.html#method.is_instance
[`PyAny::is_instance`]: https://docs.rs/pyo3/latest/pyo3/struct.PyAny.html#method.is_instance
[`PyErr`]: {{#PYO3_DOCS_URL}}/pyo3/struct.PyErr.html
[`PyErr::from_instance`]: {{#PYO3_DOCS_URL}}/pyo3/struct.PyErr.html#method.from_instance
[`Python::is_instance`]: {{#PYO3_DOCS_URL}}/pyo3/struct.Python.html#method.is_instance
[`PyAny::is_instance`]: {{#PYO3_DOCS_URL}}/pyo3/struct.PyAny.html#method.is_instance

View File

@ -13,7 +13,7 @@
PyO3 provides a struct [`GILOnceCell`] which works equivalently to `OnceCell` but relies solely on the Python GIL for thread safety. This means it can be used in place of `lazy_static` or `once_cell` where you are experiencing the deadlock described above. See the documentation for [`GILOnceCell`] for an example how to use it.
[`GILOnceCell`]: https://docs.rs/pyo3/latest/pyo3/once_cell/struct.GILOnceCell.html
[`GILOnceCell`]: {{#PYO3_DOCS_URL}}/pyo3/once_cell/struct.GILOnceCell.html
## I can't run `cargo test`: I'm having linker issues like "Symbol not found" or "Undefined reference to _PyExc_SystemError"!
@ -21,7 +21,7 @@ Currently, [#341](https://github.com/PyO3/pyo3/issues/341) causes `cargo test` t
```toml
[dependencies.pyo3]
version = "*"
version = "{{#PYO3_VERSION}}"
[features]
extension-module = ["pyo3/extension-module"]

View File

@ -32,7 +32,7 @@ See the [building and distribution](building_and_distribution.md#minimum-python-
### `auto-initalize`
This feature changes [`Python::with_gil`](https://docs.rs/pyo3/latest/pyo3/struct.Python.html#method.with_gil) and [`Python::acquire_gil`](https://docs.rs/pyo3/latest/pyo3/struct.Python.html#method.acquire_gil) to automatically initialize a Python interpreter (by calling [`prepare_freethreaded_python`](https://docs.rs/pyo3/latest/pyo3/fn.prepare_freethreaded_python.html)) if needed.
This feature changes [`Python::with_gil`]({{#PYO3_DOCS_URL}}/pyo3/struct.Python.html#method.with_gil) and [`Python::acquire_gil`]({{#PYO3_DOCS_URL}}/pyo3/struct.Python.html#method.acquire_gil) to automatically initialize a Python interpreter (by calling [`prepare_freethreaded_python`]({{#PYO3_DOCS_URL}}/pyo3/fn.prepare_freethreaded_python.html)) if needed.
If you do not enable this feature, you should call `pyo3::prepare_freethreaded_python()` before attempting to call any other Python APIs.

View File

@ -202,14 +202,14 @@ then use a `#[pyclass]` struct with that container as a field as a way to pass t
the FFI barrier. You can even make that class callable with `__call__` so it looks like a function
in Python code.
[`PyAny::is_callable`]: https://docs.rs/pyo3/latest/pyo3/struct.PyAny.html#tymethod.is_callable
[`PyAny::call`]: https://docs.rs/pyo3/latest/pyo3/struct.PyAny.html#tymethod.call
[`PyAny::call0`]: https://docs.rs/pyo3/latest/pyo3/struct.PyAny.html#tymethod.call0
[`PyAny::call1`]: https://docs.rs/pyo3/latest/pyo3/struct.PyAny.html#tymethod.call1
[`PyObject`]: https://docs.rs/pyo3/latest/pyo3/type.PyObject.html
[`wrap_pyfunction!`]: https://docs.rs/pyo3/latest/pyo3/macro.wrap_pyfunction.html
[`PyFunction`]: https://docs.rs/pyo3/latest/pyo3/types/struct.PyFunction.html
[`PyCFunction`]: https://docs.rs/pyo3/latest/pyo3/types/struct.PyCFunction.html
[`PyAny::is_callable`]: {{#PYO3_DOCS_URL}}/pyo3/struct.PyAny.html#tymethod.is_callable
[`PyAny::call`]: {{#PYO3_DOCS_URL}}/pyo3/struct.PyAny.html#tymethod.call
[`PyAny::call0`]: {{#PYO3_DOCS_URL}}/pyo3/struct.PyAny.html#tymethod.call0
[`PyAny::call1`]: {{#PYO3_DOCS_URL}}/pyo3/struct.PyAny.html#tymethod.call1
[`PyObject`]: {{#PYO3_DOCS_URL}}/pyo3/type.PyObject.html
[`wrap_pyfunction!`]: {{#PYO3_DOCS_URL}}/pyo3/macro.wrap_pyfunction.html
[`PyFunction`]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PyFunction.html
[`PyCFunction`]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PyCFunction.html
### Accessing the module of a function

View File

@ -397,7 +397,7 @@ However, for `#[pyproto]` and some functions, you need to manually fix the code.
In 0.8 object creation was done with `PyRef::new` and `PyRefMut::new`.
In 0.9 these have both been removed.
To upgrade code, please use
[`PyCell::new`](https://docs.rs/pyo3/latest/pyo3/pycell/struct.PyCell.html#method.new) instead.
[`PyCell::new`]({{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyCell.html#method.new) instead.
If you need [`PyRef`] or [`PyRefMut`], just call `.borrow()` or `.borrow_mut()`
on the newly-created `PyCell`.
@ -499,11 +499,11 @@ impl PySequenceProtocol for ByteSequence {
}
```
[`FromPyObject`]: https://docs.rs/pyo3/latest/pyo3/conversion/trait.FromPyObject.html
[`PyAny`]: https://docs.rs/pyo3/latest/pyo3/types/struct.PyAny.html
[`PyCell`]: https://docs.rs/pyo3/latest/pyo3/pycell/struct.PyCell.html
[`PyBorrowMutError`]: https://docs.rs/pyo3/latest/pyo3/pycell/struct.PyBorrowMutError.html
[`PyRef`]: https://docs.rs/pyo3/latest/pyo3/pycell/struct.PyRef.html
[`PyRefMut`]: https://docs.rs/pyo3/latest/pyo3/pycell/struct.PyRef.html
[`FromPyObject`]: {{#PYO3_DOCS_URL}}/pyo3/conversion/trait.FromPyObject.html
[`PyAny`]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PyAny.html
[`PyCell`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyCell.html
[`PyBorrowMutError`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyBorrowMutError.html
[`PyRef`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyRef.html
[`PyRefMut`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyRef.html
[`RefCell`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html

View File

@ -72,4 +72,4 @@ test_word_count_python_sequential 27.3985 (15.82) 45.452
You can see that the Python threaded version is not much slower than the Rust sequential version, which means compared to an execution on a single CPU core the speed has doubled.
[`Python::allow_threads`]: https://docs.rs/pyo3/latest/pyo3/struct.Python.html#method.allow_threads
[`Python::allow_threads`]: {{#PYO3_DOCS_URL}}/pyo3/struct.Python.html#method.allow_threads

View File

@ -57,7 +57,7 @@ fn main() {
### Creating keyword arguments
For the `call` and `call_method` APIs, `kwargs` can be `None` or `Some(&PyDict)`. You can use the [`IntoPyDict`](https://docs.rs/pyo3/latest/pyo3/types/trait.IntoPyDict.html) trait to convert other dict-like containers, e.g. `HashMap` or `BTreeMap`, as well as tuples with up to 10 elements and `Vec`s where each element is a two-element tuple.
For the `call` and `call_method` APIs, `kwargs` can be `None` or `Some(&PyDict)`. You can use the [`IntoPyDict`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.IntoPyDict.html) trait to convert other dict-like containers, e.g. `HashMap` or `BTreeMap`, as well as tuples with up to 10 elements and `Vec`s where each element is a two-element tuple.
```rust
use pyo3::prelude::*;
@ -103,7 +103,7 @@ If you already have some existing Python code that you need to execute from Rust
### Want to access Python APIs? Then use `PyModule::import`.
[`Pymodule::import`](https://docs.rs/pyo3/latest/pyo3/types/struct.PyModule.html#method.import) can
[`Pymodule::import`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyModule.html#method.import) can
be used to get handle to a Python module from Rust. You can use this to import and use any Python
module available in your environment.
@ -122,7 +122,7 @@ fn main() -> PyResult<()> {
### Want to run just an expression? Then use `eval`.
[`Python::eval`](https://docs.rs/pyo3/latest/pyo3/struct.Python.html#method.eval) is
[`Python::eval`]({{#PYO3_DOCS_URL}}/pyo3/struct.Python.html#method.eval) is
a method to execute a [Python expression](https://docs.python.org/3.7/reference/expressions.html)
and return the evaluated value as a `&PyAny` object.
@ -195,7 +195,7 @@ assert userdata.as_tuple() == userdata_as_tuple
## You have a Python file or code snippet? Then use `PyModule::from_code`.
[PyModule::from_code](https://docs.rs/pyo3/latest/pyo3/types/struct.PyModule.html#method.from_code)
[PyModule::from_code]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyModule.html#method.from_code)
can be used to generate a Python module which can then be used just as if it was imported with
`PyModule::import`.
@ -226,8 +226,8 @@ def leaky_relu(x, slope=0.01):
# }
```
[`Python::run`]: https://docs.rs/pyo3/latest/pyo3/struct.Python.html#method.run
[`py_run!`]: https://docs.rs/pyo3/latest/pyo3/macro.py_run.html
[`Python::run`]: {{#PYO3_DOCS_URL}}/pyo3/struct.Python.html#method.run
[`py_run!`]: {{#PYO3_DOCS_URL}}/pyo3/macro.py_run.html
## Need to use a context manager from Rust?

View File

@ -295,9 +295,9 @@ usually defined using the `#[pyclass]` macro.
This trait marks structs that mirror native Python types, such as `PyList`.
[eval]: https://docs.rs/pyo3/latest/pyo3/struct.Python.html#method.eval
[clone_ref]: https://docs.rs/pyo3/latest/pyo3/struct.Py.html#method.clone_ref
[pyo3::types]: https://docs.rs/pyo3/latest/pyo3/types/index.html
[PyAny]: https://docs.rs/pyo3/latest/pyo3/types/struct.PyAny.html
[PyList_append]: https://docs.rs/pyo3/latest/pyo3/types/struct.PyList.html#method.append
[eval]: {{#PYO3_DOCS_URL}}/pyo3/struct.Python.html#method.eval
[clone_ref]: {{#PYO3_DOCS_URL}}/pyo3/struct.Py.html#method.clone_ref
[pyo3::types]: {{#PYO3_DOCS_URL}}/pyo3/types/index.html
[PyAny]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PyAny.html
[PyList_append]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PyList.html#method.append
[RefCell]: https://doc.rust-lang.org/std/cell/struct.RefCell.html