From ad5f583b4d077fa6f7529bb71f3278f1a4fc255e Mon Sep 17 00:00:00 2001 From: Adam Reichold Date: Wed, 23 Feb 2022 08:52:41 +0100 Subject: [PATCH] Copy-edit the examples for consistency --- .github/workflows/ci.yml | 12 ++++----- README.md | 25 +++++++++++-------- examples/linalg/Cargo.toml | 2 +- examples/linalg/README.md | 7 +++--- examples/linalg/noxfile.py | 6 ++--- examples/linalg/src/lib.rs | 4 +-- examples/linalg/tests/test_linalg.py | 11 +++++--- examples/parallel/Cargo.toml | 2 +- examples/parallel/README.md | 8 +++--- examples/parallel/noxfile.py | 6 ++--- examples/parallel/src/lib.rs | 2 +- examples/simple-extension/README.md | 24 ------------------ examples/simple-extension/noxfile.py | 8 ------ .../{simple-extension => simple}/Cargo.toml | 2 +- examples/simple/README.md | 25 +++++++++++++++++++ examples/simple/noxfile.py | 8 ++++++ .../pyproject.toml | 0 .../{simple-extension => simple}/src/lib.rs | 8 +++--- .../tests/test_ext.py | 6 +---- 19 files changed, 83 insertions(+), 83 deletions(-) delete mode 100644 examples/simple-extension/README.md delete mode 100644 examples/simple-extension/noxfile.py rename examples/{simple-extension => simple}/Cargo.toml (93%) create mode 100644 examples/simple/README.md create mode 100644 examples/simple/noxfile.py rename examples/{simple-extension => simple}/pyproject.toml (100%) rename examples/{simple-extension => simple}/src/lib.rs (87%) rename examples/{simple-extension => simple}/tests/test_ext.py (75%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 23857656d..35422c397 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -77,7 +77,7 @@ jobs: - name: Test example run: | pip install nox - nox -f examples/simple-extension/noxfile.py + nox -f examples/simple/noxfile.py env: CARGO_TERM_VERBOSE: true CARGO_BUILD_TARGET: ${{ matrix.platform.rust-target }} @@ -99,7 +99,7 @@ jobs: default: true - uses: Swatinem/rust-cache@v1 with: - working-directory: examples/simple-extension + working-directory: examples/simple continue-on-error: true - name: Install toml run: pip install toml @@ -112,11 +112,11 @@ jobs: cargo_toml["workspace"] = {} with open("Cargo.toml", "w") as f: toml.dump(cargo_toml, f) - working-directory: examples/simple-extension + working-directory: examples/simple shell: python - name: Generate lockfile run: cargo generate-lockfile - working-directory: examples/simple-extension + working-directory: examples/simple - name: Unify dependencies on ndarray to 0.13.1 run: | import toml @@ -126,12 +126,12 @@ jobs: if pkg["name"] == "ndarray" and pkg["version"] != "0.13.1": pkg_id = pkg["name"] + ":" + pkg["version"] subprocess.run(["cargo", "update", "--package", pkg_id, "--precise", "0.13.1"], check=True) - working-directory: examples/simple-extension + working-directory: examples/simple shell: python - name: Test example run: | pip install nox - nox -f examples/simple-extension/noxfile.py + nox -f examples/simple/noxfile.py examples: runs-on: ubuntu-latest diff --git a/README.md b/README.md index 271c06335..5cb2b0694 100644 --- a/README.md +++ b/README.md @@ -28,10 +28,9 @@ Rust bindings for the NumPy C-API. ### Write a Python module in Rust -Please see the [simple-extension](https://github.com/PyO3/rust-numpy/tree/main/examples/simple-extension) -directory for the complete example. +Please see the [simple](examples/simple) example for how to get started. -Also, we have an example project with [ndarray-linalg](https://github.com/PyO3/rust-numpy/tree/main/examples/linalg). +There are also examples using [ndarray-linalg](examples/linalg) and [rayon](examples/parallel). ```toml [lib] @@ -46,22 +45,23 @@ numpy = "0.15" ```rust use numpy::ndarray::{ArrayD, ArrayViewD, ArrayViewMutD}; use numpy::{IntoPyArray, PyArrayDyn, PyReadonlyArrayDyn}; -use pyo3::prelude::{pymodule, PyModule, PyResult, Python}; +use pyo3::{pymodule, types::PyModule, PyResult, Python}; #[pymodule] fn rust_ext(_py: Python<'_>, m: &PyModule) -> PyResult<()> { - // immutable example + // example using immutable borrows producing a new array fn axpy(a: f64, x: ArrayViewD<'_, f64>, y: ArrayViewD<'_, f64>) -> ArrayD { a * &x + &y } - // mutable example (no return) + // example using a mutable borrow to modify an array in-place fn mult(a: f64, mut x: ArrayViewMutD<'_, f64>) { x *= a; } // wrapper of `axpy` - #[pyfn(m, "axpy")] + #[pyfn(m)] + #[pyo3(name = "axpy")] fn axpy_py<'py>( py: Python<'py>, a: f64, @@ -74,7 +74,8 @@ fn rust_ext(_py: Python<'_>, m: &PyModule) -> PyResult<()> { } // wrapper of `mult` - #[pyfn(m, "mult")] + #[pyfn(m)] + #[pyo3(name = "mult")] fn mult_py(_py: Python<'_>, a: f64, x: &PyArrayDyn) -> PyResult<()> { let x = unsafe { x.as_array_mut() }; mult(a, x); @@ -98,23 +99,24 @@ numpy = "0.15" ```rust use numpy::PyArray1; -use pyo3::prelude::{PyResult, Python}; -use pyo3::types::IntoPyDict; +use pyo3::{types::IntoPyDict, PyResult, Python}; fn main() -> PyResult<()> { Python::with_gil(|py| { let np = py.import("numpy")?; let locals = [("np", np)].into_py_dict(py); + let pyarray: &PyArray1 = py .eval("np.absolute(np.array([-1, -2, -3], dtype='int32'))", Some(locals), None)? .extract()?; + let readonly = pyarray.readonly(); let slice = readonly.as_slice()?; assert_eq!(slice, &[1, 2, 3]); + Ok(()) }) } - ``` ## Dependency on ndarray @@ -150,5 +152,6 @@ and [pull requests](https://github.com/PyO3/rust-numpy/pulls). PyO3's [Contributing.md](https://github.com/PyO3/pyo3/blob/main/Contributing.md) is a nice guide for starting. + Also, we have a [Gitter](https://gitter.im/PyO3/Lobby) channel for communicating. diff --git a/examples/linalg/Cargo.toml b/examples/linalg/Cargo.toml index da4c504b0..ddb422903 100644 --- a/examples/linalg/Cargo.toml +++ b/examples/linalg/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "numpy-linalg-example" +name = "rust-linalg" version = "0.1.0" authors = ["Yuji Kanagawa "] edition = "2018" diff --git a/examples/linalg/README.md b/examples/linalg/README.md index 9521648e0..1294fb5ae 100644 --- a/examples/linalg/README.md +++ b/examples/linalg/README.md @@ -1,8 +1,7 @@ -# rust-numpy example extension with linalg +# rust-numpy extension using ndarray-linalg -An example extension with [ndarray-linalg](https://github.com/rust-ndarray/ndarray-linalg). +An example extension using [ndarray-linalg](https://github.com/rust-ndarray/ndarray-linalg). Will link against a system-provided OpenBLAS. -See [simple-extension's README](https://github.com/PyO3/rust-numpy/blob/main/examples/simple-extension/README.md) -for an introduction. +See the [README](../simple/README.md) of the simple extension for more information. diff --git a/examples/linalg/noxfile.py b/examples/linalg/noxfile.py index cff23a4bb..6154c9517 100644 --- a/examples/linalg/noxfile.py +++ b/examples/linalg/noxfile.py @@ -3,6 +3,6 @@ @nox.session def tests(session): - session.install('pip', 'numpy', 'pytest') - session.run('pip', 'install', '.', '-v') - session.run('pytest') + session.install("pip", "numpy", "pytest") + session.run("pip", "install", ".", "-v") + session.run("pytest") diff --git a/examples/linalg/src/lib.rs b/examples/linalg/src/lib.rs index e648d3e4c..0ea9a635d 100755 --- a/examples/linalg/src/lib.rs +++ b/examples/linalg/src/lib.rs @@ -1,6 +1,6 @@ use ndarray_linalg::solve::Inverse; use numpy::{IntoPyArray, PyArray2, PyReadonlyArray2}; -use pyo3::{exceptions::PyRuntimeError, pymodule, types::PyModule, PyErr, PyResult, Python}; +use pyo3::{exceptions::PyRuntimeError, pymodule, types::PyModule, PyResult, Python}; #[pymodule] fn rust_linalg(_py: Python<'_>, m: &PyModule) -> PyResult<()> { @@ -9,7 +9,7 @@ fn rust_linalg(_py: Python<'_>, m: &PyModule) -> PyResult<()> { let x = x.as_array(); let y = x .inv() - .map_err(|e| PyErr::new::(format!("[rust_linalg] {}", e)))?; + .map_err(|e| PyRuntimeError::new_err(e.to_string()))?; Ok(y.into_pyarray(py)) } Ok(()) diff --git a/examples/linalg/tests/test_linalg.py b/examples/linalg/tests/test_linalg.py index 811e4ea85..a00a4d885 100644 --- a/examples/linalg/tests/test_linalg.py +++ b/examples/linalg/tests/test_linalg.py @@ -3,9 +3,12 @@ def test_inv(): - x = np.array([ - [1, 0], - [0, 2], - ], dtype=np.float64) + x = np.array( + [ + [1, 0], + [0, 2], + ], + dtype=np.float64, + ) y = rust_linalg.inv(x) np.testing.assert_array_almost_equal(y, np.linalg.inv(x)) diff --git a/examples/parallel/Cargo.toml b/examples/parallel/Cargo.toml index ec77988e0..ca5a2921a 100644 --- a/examples/parallel/Cargo.toml +++ b/examples/parallel/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "numpy-parallel-example" +name = "rust-parallel" version = "0.1.0" authors = ["Yuji Kanagawa "] edition = "2018" diff --git a/examples/parallel/README.md b/examples/parallel/README.md index 214b9922b..ac67bb936 100644 --- a/examples/parallel/README.md +++ b/examples/parallel/README.md @@ -1,7 +1,5 @@ -# rust-numpy example extension using optional ndarray features +# rust-numpy extension using optional ndarray features -An example extension using [optional ndarray features](https://docs.rs/ndarray/latest/ndarray/doc/crate_feature_flags/index.html), parallel execution using Rayon and optimized kernels using BLAS in this case. - -See [simple-extension's README](https://github.com/PyO3/rust-numpy/blob/main/examples/simple-extension/README.md) -for an introduction. +An example extension using [optional ndarray features](https://docs.rs/ndarray/latest/ndarray/doc/crate_feature_flags/index.html), in this case parallel execution using Rayon and optimized kernels using BLAS. +See the [README](../simple/README.md) of the simple extension for more information. diff --git a/examples/parallel/noxfile.py b/examples/parallel/noxfile.py index cff23a4bb..6154c9517 100644 --- a/examples/parallel/noxfile.py +++ b/examples/parallel/noxfile.py @@ -3,6 +3,6 @@ @nox.session def tests(session): - session.install('pip', 'numpy', 'pytest') - session.run('pip', 'install', '.', '-v') - session.run('pytest') + session.install("pip", "numpy", "pytest") + session.run("pip", "install", ".", "-v") + session.run("pytest") diff --git a/examples/parallel/src/lib.rs b/examples/parallel/src/lib.rs index cca4aa63a..5ed72b865 100755 --- a/examples/parallel/src/lib.rs +++ b/examples/parallel/src/lib.rs @@ -1,7 +1,7 @@ // We need to link `blas_src` directly, c.f. https://github.com/rust-ndarray/ndarray#how-to-enable-blas-integration extern crate blas_src; -use ndarray::Zip; +use numpy::ndarray::Zip; use numpy::{IntoPyArray, PyArray1, PyReadonlyArray1, PyReadonlyArray2}; use pyo3::{pymodule, types::PyModule, PyResult, Python}; diff --git a/examples/simple-extension/README.md b/examples/simple-extension/README.md deleted file mode 100644 index 02c4e7345..000000000 --- a/examples/simple-extension/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# rust-numpy example extension - -Here, we use [`maturin`][maturin] for building Python wheel and -[`poetry`][poetry] for managing Python dependencies and virtualenvs. -Following commands creates a virtualenv, install Python-side -dependencies, and install the extension to the virtualenv. - -```bash -poetry install -poetry run maturin develop -``` - -Once the extension installed, you can run the extension from -Python REPL started by `poetry run python`: - -```python ->>> import numpy as np ->>> import rust_ext ->>> rust_ext.axpy(2.0, np.array([0.0, 1.0]), np.array([2.0, 3.0])) -array([2., 5.]) -``` - -[maturin]: https://github.com/PyO3/maturin -[poetry]: https://python-poetry.org/ diff --git a/examples/simple-extension/noxfile.py b/examples/simple-extension/noxfile.py deleted file mode 100644 index cff23a4bb..000000000 --- a/examples/simple-extension/noxfile.py +++ /dev/null @@ -1,8 +0,0 @@ -import nox - - -@nox.session -def tests(session): - session.install('pip', 'numpy', 'pytest') - session.run('pip', 'install', '.', '-v') - session.run('pytest') diff --git a/examples/simple-extension/Cargo.toml b/examples/simple/Cargo.toml similarity index 93% rename from examples/simple-extension/Cargo.toml rename to examples/simple/Cargo.toml index acbfa36cd..0017f42e6 100644 --- a/examples/simple-extension/Cargo.toml +++ b/examples/simple/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "numpy-example" +name = "rust-ext" version = "0.1.0" authors = ["Toshiki Teramura ", "Yuji Kanagawa "] edition = "2018" diff --git a/examples/simple/README.md b/examples/simple/README.md new file mode 100644 index 000000000..d7e235873 --- /dev/null +++ b/examples/simple/README.md @@ -0,0 +1,25 @@ +# simple extension + +Here, we use [`maturin`][maturin] for building Python wheels and +[`nox`][nox] for managing Python dependencies and virtualenvs. + +Running `nox` inside this directory creates a virtualenv, +installs Python dependencies and the extension into it +and executes the tests from `tests/test_exp.py`. + +By running +```bash +maturin develop +``` +from inside a virtualenv, you can use the extension from +the Python REPL: + +```python +>>> import numpy as np +>>> import rust_ext +>>> rust_ext.axpy(2.0, np.array([0.0, 1.0]), np.array([2.0, 3.0])) +array([2., 5.]) +``` + +[maturin]: https://github.com/PyO3/maturin +[nox]: https://github.com/theacodes/nox diff --git a/examples/simple/noxfile.py b/examples/simple/noxfile.py new file mode 100644 index 000000000..6154c9517 --- /dev/null +++ b/examples/simple/noxfile.py @@ -0,0 +1,8 @@ +import nox + + +@nox.session +def tests(session): + session.install("pip", "numpy", "pytest") + session.run("pip", "install", ".", "-v") + session.run("pytest") diff --git a/examples/simple-extension/pyproject.toml b/examples/simple/pyproject.toml similarity index 100% rename from examples/simple-extension/pyproject.toml rename to examples/simple/pyproject.toml diff --git a/examples/simple-extension/src/lib.rs b/examples/simple/src/lib.rs similarity index 87% rename from examples/simple-extension/src/lib.rs rename to examples/simple/src/lib.rs index 2c1eceecd..2c1e2751d 100644 --- a/examples/simple-extension/src/lib.rs +++ b/examples/simple/src/lib.rs @@ -8,17 +8,17 @@ use pyo3::{ #[pymodule] fn rust_ext(_py: Python<'_>, m: &PyModule) -> PyResult<()> { - // immutable example + // example using immutable borrows producing a new array fn axpy(a: f64, x: ArrayViewD<'_, f64>, y: ArrayViewD<'_, f64>) -> ArrayD { a * &x + &y } - // mutable example (no return) + // example using a mutable borrow to modify an array in-place fn mult(a: f64, mut x: ArrayViewMutD<'_, f64>) { x *= a; } - // complex example + // example using complex numbers fn conj(x: ArrayViewD<'_, Complex64>) -> ArrayD { x.map(|c| c.conj()) } @@ -56,8 +56,8 @@ fn rust_ext(_py: Python<'_>, m: &PyModule) -> PyResult<()> { conj(x.as_array()).into_pyarray(py) } + // example of how to extract an array from a dictionary #[pyfn(m)] - #[pyo3(name = "extract")] fn extract(d: &PyDict) -> f64 { let x = d .get_item("x") diff --git a/examples/simple-extension/tests/test_ext.py b/examples/simple/tests/test_ext.py similarity index 75% rename from examples/simple-extension/tests/test_ext.py rename to examples/simple/tests/test_ext.py index c163f71a0..68703adf9 100644 --- a/examples/simple-extension/tests/test_ext.py +++ b/examples/simple/tests/test_ext.py @@ -7,10 +7,6 @@ def test_axpy(): y = np.array([3.0, 3.0, 3.0]) z = axpy(3.0, x, y) np.testing.assert_array_almost_equal(z, np.array([6.0, 9.0, 12.0])) - x = np.array([1.0, 2.0, 3.0, 4.0]) - y = np.array([3.0, 3.0, 3.0, 3.0]) - z = axpy(3.0, x, y) - np.testing.assert_array_almost_equal(z, np.array([6.0, 9.0, 12.0, 15.0])) def test_mult(): @@ -26,5 +22,5 @@ def test_conj(): def test_extract(): x = np.arange(5.0) - d = { "x": x } + d = {"x": x} np.testing.assert_almost_equal(extract(d), 10.0)