Skip to content

Copy-edit the examples for consistency #278

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 6 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }}
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down
25 changes: 14 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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<f64> {
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,
Expand All @@ -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<f64>) -> PyResult<()> {
let x = unsafe { x.as_array_mut() };
mult(a, x);
Expand All @@ -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<i32> = 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
Expand Down Expand Up @@ -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.

2 changes: 1 addition & 1 deletion examples/linalg/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "numpy-linalg-example"
name = "rust-linalg"
version = "0.1.0"
authors = ["Yuji Kanagawa <[email protected]>"]
edition = "2018"
Expand Down
7 changes: 3 additions & 4 deletions examples/linalg/README.md
Original file line number Diff line number Diff line change
@@ -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.
6 changes: 3 additions & 3 deletions examples/linalg/noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
4 changes: 2 additions & 2 deletions examples/linalg/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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<()> {
Expand All @@ -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::<PyRuntimeError, _>(format!("[rust_linalg] {}", e)))?;
.map_err(|e| PyRuntimeError::new_err(e.to_string()))?;
Ok(y.into_pyarray(py))
}
Ok(())
Expand Down
11 changes: 7 additions & 4 deletions examples/linalg/tests/test_linalg.py
Original file line number Diff line number Diff line change
Expand Up @@ -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))
2 changes: 1 addition & 1 deletion examples/parallel/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "numpy-parallel-example"
name = "rust-parallel"
version = "0.1.0"
authors = ["Yuji Kanagawa <[email protected]>"]
edition = "2018"
Expand Down
8 changes: 3 additions & 5 deletions examples/parallel/README.md
Original file line number Diff line number Diff line change
@@ -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.
6 changes: 3 additions & 3 deletions examples/parallel/noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
2 changes: 1 addition & 1 deletion examples/parallel/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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};

Expand Down
24 changes: 0 additions & 24 deletions examples/simple-extension/README.md

This file was deleted.

8 changes: 0 additions & 8 deletions examples/simple-extension/noxfile.py

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "numpy-example"
name = "rust-ext"
version = "0.1.0"
authors = ["Toshiki Teramura <[email protected]>", "Yuji Kanagawa <[email protected]>"]
edition = "2018"
Expand Down
25 changes: 25 additions & 0 deletions examples/simple/README.md
Original file line number Diff line number Diff line change
@@ -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
8 changes: 8 additions & 0 deletions examples/simple/noxfile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import nox


@nox.session
def tests(session):
session.install("pip", "numpy", "pytest")
session.run("pip", "install", ".", "-v")
session.run("pytest")
Original file line number Diff line number Diff line change
Expand Up @@ -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<f64> {
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<Complex64> {
x.map(|c| c.conj())
}
Expand Down Expand Up @@ -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")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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():
Expand All @@ -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)