From 314a4a2b3e4f0789d9de0beb70017583a380f763 Mon Sep 17 00:00:00 2001 From: konstin Date: Sat, 19 May 2018 17:27:26 +0200 Subject: [PATCH] Some more documentation work --- README.md | 6 +-- ci/travis/guide.sh | 5 +- guide/src/SUMMARY.md | 5 +- guide/src/module.md | 22 +------- guide/src/overview.md | 88 +++++++------------------------ pyo3-derive-backend/src/lib.rs | 1 + pyo3-derive-backend/src/module.rs | 1 + pyo3cls/src/lib.rs | 2 + src/objects/floatob.rs | 1 + src/objects/mod.rs | 11 ++-- src/objects/num3.rs | 2 +- 11 files changed, 37 insertions(+), 107 deletions(-) diff --git a/README.md b/README.md index 99b4ad28..c318485c 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ * [User Guide](https://pyo3.github.io/pyo3/guide/) * [API Documentation](http://pyo3.github.io/pyo3/pyo3/) -A comparison with pyo3, the base for this project, can be found [in the guide](https://pyo3.github.io/pyo3/guide/rust-cpython.html). +A comparison with rust-cpython can be found [in the guide](https://pyo3.github.io/pyo3/guide/rust-cpython.html). ## Usage @@ -80,8 +80,8 @@ use pyo3::py::modinit as pymodinit; fn init_mod(py: Python, m: &PyModule) -> PyResult<()> { #[pyfn(m, "sum_as_string")] - // ``#[pyfn()]` converts the arguments from Python objects to Rust values and the Rust return - // value back into a Python object. + // ``#[pyfn()]` converts the arguments from Python objects to Rust values + // and the Rust return value back into a Python object. fn sum_as_string_py(a:i64, b:i64) -> PyResult { let out = sum_as_string(a, b); Ok(out) diff --git a/ci/travis/guide.sh b/ci/travis/guide.sh index c2934ac1..5c83be9b 100755 --- a/ci/travis/guide.sh +++ b/ci/travis/guide.sh @@ -14,13 +14,14 @@ fi ### Build API reference ######################################################## -cargo doc --no-deps -p pyo3 -p pyo3cls +cargo doc --no-deps -p pyo3 -p pyo3cls -p pyo3-derive-backend echo "" > target/doc/index.html ### Build guide ################################################################ -mdbook build -d target/doc/guide guide +# This builds the book in target/doc/guide. See https://github.com/rust-lang-nursery/mdBook/issues/698 +mdbook build -d ../target/doc/guide guide git clone https://github.com/davisp/ghp-import.git ./ghp-import/ghp_import.py -n -p -f -m "Documentation upload" -r https://"$GH_TOKEN"@github.com/"$TRAVIS_REPO_SLUG.git" target/doc diff --git a/guide/src/SUMMARY.md b/guide/src/SUMMARY.md index 2f95d72d..d486d4a8 100644 --- a/guide/src/SUMMARY.md +++ b/guide/src/SUMMARY.md @@ -1,8 +1,7 @@ # Summary -[Overview](./overview.md) - -link-arg=-undefi- [Type Conversions](./conversions.md) +- [Get Started](./overview.md) +- [Type Conversions](./conversions.md) - [Python Exception](./exception.md) - [Python Module](./module.md) - [Python Function](./function.md) diff --git a/guide/src/module.md b/guide/src/module.md index 9bc95a6b..8b93da58 100644 --- a/guide/src/module.md +++ b/guide/src/module.md @@ -1,26 +1,6 @@ # Python Module -Python module generation is powered by unstable [Procedural Macros](https://doc.rust-lang.org/book/first-edition/procedural-macros.html) feature, so you need to turn on `proc_macro` feature: - -```rust -#![feature(proc_macro)] - -extern crate pyo3; -# fn main() {} -``` - -You need to change your `crate-type` to `cdylib` to produce a Python compatible library: - -```toml -[lib] -name = "rust2py" -crate-type = ["cdylib"] - -[dependencies] -pyo3 = { version = "0.2", features = ["extension-module"] } -``` - -Now you can write your module, for example +As shown in the Getting Started chapter, you can create a module as follows: ```rust #![feature(proc_macro)] diff --git a/guide/src/overview.md b/guide/src/overview.md index d45c84b0..c1e84cf4 100644 --- a/guide/src/overview.md +++ b/guide/src/overview.md @@ -1,22 +1,13 @@ -# Overview +# PyO3 -[![Build Status](https://travis-ci.org/PyO3/pyo3.svg?branch=master)](https://travis-ci.org/PyO3/pyo3) -[![Latest Version](https://img.shields.io/crates/v/pyo3.svg)](https://crates.io/crates/pyo3) -[![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](http://pyo3.github.io/pyo3/pyo3/) - -PyO3 is a [Rust](http://www.rust-lang.org/) bindings for the [Python](https://www.python.org/) interpreter. - -Supported Python versions: - -* Python2.7, Python 3.5 and up - -Supported Rust version: - -* Rust 1.20.0-nightly or later -* On Windows, we require rustc 1.20.0-nightly +[Rust](http://www.rust-lang.org/) bindings for the [Python](https://www.python.org/) interpreter. This includes running and interacting with python code from a rust binaries as well as writing native python modules. ## Usage +Pyo3 supports python 2.7 as well as python 3.5 and up. The minimum required rust version is 1.27.0-nightly 2018-05-01. + +### From a rust binary + To use `pyo3`, add this to your `Cargo.toml`: ```toml @@ -31,12 +22,9 @@ extern crate pyo3; use pyo3::prelude::*; -fn main() { +fn main() -> PyResult<()> { let gil = Python::acquire_gil(); - hello(gil.python()).unwrap(); -} - -fn hello(py: Python) -> PyResult<()> { + let py = gil.python(); let sys = py.import("sys")?; let version: String = sys.get("version")?.extract()?; @@ -49,14 +37,12 @@ fn hello(py: Python) -> PyResult<()> { } ``` -Example library with python bindings: +### As native module -The following two files will build with `cargo build`, and will generate a python-compatible library. -For MacOS, `-C link-arg=-undefined -C link-arg=dynamic_lookup` is required to build the library. -`setuptools-rust` includes this by default. -See [examples/word-count](https://github.com/PyO3/pyo3/tree/master/examples/word-count). -Also on macOS, you will need to rename the output from \*.dylib to \*.so. -On Windows, you will need to rename the output from \*.dll to \*.pyd. +Pyo3 can be used to write native python module. The example will generate a python-compatible library. + +For MacOS, "-C link-arg=-undefined -C link-arg=dynamic_lookup" is required to build the library. +`setuptools-rust` includes this by default. See [examples/word-count](examples/word-count) and the associated setup.py. Also on macOS, you will need to rename the output from \*.dylib to \*.so. On Windows, you will need to rename the output from \*.dll to \*.pyd. **`Cargo.toml`:** @@ -80,17 +66,16 @@ use pyo3::prelude::*; use pyo3::py::modinit as pymodinit; -// add bindings to the generated python module +// Add bindings to the generated python module // N.B: names: "librust2py" must be the name of the `.so` or `.pyd` file /// This module is implemented in Rust. #[pymodinit(rust2py)] fn init_mod(py: Python, m: &PyModule) -> PyResult<()> { #[pyfn(m, "sum_as_string")] - // pyo3 aware function. All of our python interface could be declared in a separate module. - // Note that the `#[pyfn()]` annotation automatically converts the arguments from - // Python objects to Rust values; and the Rust return value back into a Python object. - fn sum_as_string_py(_py: Python, a:i64, b:i64) -> PyResult { + // ``#[pyfn()]` converts the arguments from Python objects to Rust values + // and the Rust return value back into a Python object. + fn sum_as_string_py(a:i64, b:i64) -> PyResult { let out = sum_as_string(a, b); Ok(out) } @@ -98,48 +83,11 @@ fn init_mod(py: Python, m: &PyModule) -> PyResult<()> { Ok(()) } -// logic implemented as a normal Rust function +// The logic can be implemented as a normal rust function fn sum_as_string(a:i64, b:i64) -> String { format!("{}", a + b).to_string() } -# fn main() {} ``` For `setup.py` integration, see [setuptools-rust](https://github.com/PyO3/setuptools-rust) - -## Ownership and Lifetimes - -In Python, all objects are implicitly reference counted. -In Rust, we will use the [`PyObject`](https://pyo3.github.io/pyo3/pyo3/struct.PyObject.html) type -to represent a reference to a Python object. - -Because all Python objects potentially have multiple owners, the -concept of Rust mutability does not apply to Python objects. -As a result, this API will **allow mutating Python objects even if they are not stored -in a mutable Rust variable**. - -The Python interpreter uses a global interpreter lock (GIL) to ensure thread-safety. -This API uses a zero-sized [`struct Python<'p>`](https://pyo3.github.io/pyo3/pyo3/struct.Python.html) as a token to indicate -that a function can assume that the GIL is held. - -You obtain a [`Python`](https://pyo3.github.io/pyo3/pyo3/struct.Python.html) instance -by acquiring the GIL, and have to pass it into some operations that call into the Python runtime. - -PyO3 library provides wrappers for python native objects. Ownership of python objects are -disallowed because any access to python runtime has to be protected by GIL. -All APIs are available through references. Lifetimes of python object's references are -bound to GIL lifetime. - -There are two types of pointers that could be stored on Rust structs. -Both implements `Send` and `Sync` traits and maintain python object's reference count. - -* [`PyObject`](https://pyo3.github.io/pyo3/pyo3/struct.PyObject.html) is general purpose -type. It does not maintain type of the referenced object. It provides helper methods -for extracting Rust values and casting to specific python object type. - -* [`Py`](https://pyo3.github.io/pyo3/pyo3/struct.Py.html) represents a reference to a -concrete python object `T`. - -To upgrade to a reference [`AsPyRef`](https://pyo3.github.io/pyo3/pyo3/trait.AsPyRef.html) -trait can be used. diff --git a/pyo3-derive-backend/src/lib.rs b/pyo3-derive-backend/src/lib.rs index 95d1d8f0..94c183b2 100644 --- a/pyo3-derive-backend/src/lib.rs +++ b/pyo3-derive-backend/src/lib.rs @@ -1,4 +1,5 @@ // Copyright (c) 2017-present PyO3 Project and Contributors +//! This crate contains the implementation of the proc macro attributes #![recursion_limit = "1024"] diff --git a/pyo3-derive-backend/src/module.rs b/pyo3-derive-backend/src/module.rs index 008faf8c..6631d37a 100644 --- a/pyo3-derive-backend/src/module.rs +++ b/pyo3-derive-backend/src/module.rs @@ -1,4 +1,5 @@ // Copyright (c) 2017-present PyO3 Project and Contributors +//! Code generation for the function that initializes a python module and adds classes and function. use args; use method; diff --git a/pyo3cls/src/lib.rs b/pyo3cls/src/lib.rs index be9a6d57..a89cf303 100644 --- a/pyo3cls/src/lib.rs +++ b/pyo3cls/src/lib.rs @@ -1,4 +1,6 @@ // Copyright (c) 2017-present PyO3 Project and Contributors +//! This crate declares only the proc macro attributes, as a crate defining proc macro attributes +//! must not contain any other public items #![recursion_limit = "1024"] #![feature(proc_macro)] diff --git a/src/objects/floatob.rs b/src/objects/floatob.rs index 55c0623c..dfc8c55b 100644 --- a/src/objects/floatob.rs +++ b/src/objects/floatob.rs @@ -10,6 +10,7 @@ use python::{ToPyPointer, Python}; use err::PyErr; use instance::{Py, PyObjectWithToken}; use conversion::{ToPyObject, IntoPyObject}; +use objectprotocol::ObjectProtocol; /// Represents a Python `float` object. /// diff --git a/src/objects/mod.rs b/src/objects/mod.rs index fd14a1c4..ae8ecf7c 100644 --- a/src/objects/mod.rs +++ b/src/objects/mod.rs @@ -31,7 +31,7 @@ pub use self::num3::PyLong as PyInt; pub use self::num2::{PyInt, PyLong}; -/// Implements typesafe conversions from a PyObjectRef, given a typecheck function as second +/// Implements a typesafe conversions throught [FromPyObject], given a typecheck function as second /// parameter #[macro_export] macro_rules! pyobject_downcast( @@ -178,6 +178,9 @@ macro_rules! pyobject_native_type_convert( }; ); +/// Implements [FromPyObject] and (currently deactivated until it's stabillized) a +/// [TryFrom](std::convert::TryFrom) implementation, given a function body that performs the actual +/// conversion #[macro_export] macro_rules! pyobject_extract( ($obj:ident to $t:ty => $body: block) => { @@ -185,9 +188,6 @@ macro_rules! pyobject_extract( { fn extract($obj: &'source $crate::PyObjectRef) -> $crate::PyResult { - #[allow(unused_imports)] - use objectprotocol::ObjectProtocol; - $body } } @@ -199,9 +199,6 @@ macro_rules! pyobject_extract( fn try_from($obj: &$crate::PyObjectRef) -> Result { - #[allow(unused_imports)] - use $crate::ObjectProtocol; - $body } } diff --git a/src/objects/num3.rs b/src/objects/num3.rs index 325b68ba..21119c00 100644 --- a/src/objects/num3.rs +++ b/src/objects/num3.rs @@ -79,7 +79,7 @@ macro_rules! int_fits_larger_int( } } pyobject_extract!(obj to $rust_type => { - let val = try!(obj.extract::<$larger_type>()); + let val = try!($crate::objectprotocol::ObjectProtocol::extract::<$larger_type>(obj)); match cast::<$larger_type, $rust_type>(val) { Some(v) => Ok(v), None => Err(exc::OverflowError.into())