Skip to content

Commit

Permalink
examples: maturin and setuptools_rust examples
Browse files Browse the repository at this point in the history
  • Loading branch information
davidhewitt committed Apr 2, 2021
1 parent 4713b46 commit 23ba683
Show file tree
Hide file tree
Showing 67 changed files with 495 additions and 155 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
- run: pip install black==19.10b0
- run: pip install black==20.8b1
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
Expand Down Expand Up @@ -129,13 +129,13 @@ jobs:
- name: Install python test dependencies
run: |
python -m pip install -U pip setuptools
pip install setuptools-rust pytest pytest-benchmark tox tox-venv
pip install setuptools-rust pytest tox tox-venv
- name: Test example extension modules
shell: bash
run: |
for example_dir in examples/*; do
tox --discover $(which python) -c $example_dir -e py
tox -c $example_dir -e py
done
env:
TOX_TESTENV_PASSENV: "CARGO_BUILD_TARGET"
Expand Down
6 changes: 4 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ nightly = []
members = [
"pyo3-macros",
"pyo3-macros-backend",
"examples/pyo3_benchmarks",
"examples/rustapi_module",
"examples/pyo3-benchmarks",
"examples/pyo3-pytests",
"examples/maturin-starter",
"examples/setuptools-rust-starter",
"examples/word-count"
]
27 changes: 27 additions & 0 deletions examples/maturin-starter/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
[package]
authors = ["PyO3 Authors"]
name = "maturin-starter"
version = "0.1.0"
description = "An example project to get started using PyO3 with maturin"
edition = "2018"

[dependencies]

[dependencies.pyo3]
path = "../../"
features = ["extension-module"]

[lib]
name = "maturin_starter"
crate-type = ["cdylib"]

[package.metadata.maturin]
classifier=[
"License :: OSI Approved :: MIT License",
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"Programming Language :: Python",
"Programming Language :: Rust",
"Operating System :: POSIX",
"Operating System :: MacOS :: MacOS X",
]
File renamed without changes.
24 changes: 24 additions & 0 deletions examples/maturin-starter/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# maturin-starter

An example of a basic Python extension module built using PyO3 and `maturin`.

## Building and Testing

To build this package, first install `maturin`:

```shell
pip install maturin
```

To build and test use `maturin develop`:

```shell
pip install -r requirements-dev.txt
maturin develop && pytest
```

Alternatively, install tox and run the tests inside an isolated environment:

```shell
tox -e py
```
7 changes: 7 additions & 0 deletions examples/maturin-starter/maturin_starter/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# import the contents of the Rust library into the Python extension
from .maturin_starter import *


class PythonClass:
def __init__(self, value: int) -> None:
self.value = value
3 changes: 3 additions & 0 deletions examples/maturin-starter/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[build-system]
requires = ["maturin"]
build-backend = "maturin"
1 change: 1 addition & 0 deletions examples/maturin-starter/requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pytest>=3.5.0
35 changes: 35 additions & 0 deletions examples/maturin-starter/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use pyo3::prelude::*;
use pyo3::types::PyDict;
use pyo3::wrap_pymodule;

mod submodule;
use submodule::*;

#[pyclass]
struct ExampleClass {
#[pyo3(get, set)]
value: i32,
}

#[pymethods]
impl ExampleClass {
#[new]
pub fn new(value: i32) -> Self {
ExampleClass { value }
}
}

#[pymodule]
fn maturin_starter(py: Python, m: &PyModule) -> PyResult<()> {
m.add_class::<ExampleClass>()?;
m.add_wrapped(wrap_pymodule!(submodule))?;

// Inserting to sys.modules allows importing submodules nicely from Python
// e.g. from maturin_starter.submodule import SubmoduleClass

let sys = PyModule::import(py, "sys")?;
let sys_modules: &PyDict = sys.getattr("modules")?.downcast()?;
sys_modules.set_item("maturin_starter.submodule", m.getattr("submodule")?)?;

Ok(())
}
22 changes: 22 additions & 0 deletions examples/maturin-starter/src/submodule.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use pyo3::prelude::*;

#[pyclass]
struct SubmoduleClass {}

#[pymethods]
impl SubmoduleClass {
#[new]
pub fn __new__() -> Self {
SubmoduleClass {}
}

pub fn greeting(&self) -> &'static str {
"Hello, world!"
}
}

#[pymodule]
pub fn submodule(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_class::<SubmoduleClass>()?;
Ok(())
}
11 changes: 11 additions & 0 deletions examples/maturin-starter/tests/test_maturin_starter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from maturin_starter import PythonClass, ExampleClass


def test_python_class() -> None:
py_class = PythonClass(value=10)
assert py_class.value == 10


def test_example_class() -> None:
example = ExampleClass(value=11)
assert example.value == 11
6 changes: 6 additions & 0 deletions examples/maturin-starter/tests/test_submodule.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from maturin_starter.submodule import SubmoduleClass


def test_submodule_class() -> None:
submodule_class = SubmoduleClass()
assert submodule_class.greeting() == "Hello, world!"
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@ skipsdist = true
description = Run the unit tests under {basepython}
deps = -rrequirements-dev.txt
commands =
python setup.py install
# Use pip master with in-tree-build feature (to be released in pip 21.0)
python -m pip install --upgrade git+https://github.com/pypa/pip.git
python -m pip install . --use-feature=in-tree-build
pytest {posargs}
File renamed without changes.
3 changes: 3 additions & 0 deletions examples/pyo3-benchmarks/MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
include Cargo.toml
recursive-include src *
recursive-include tests
18 changes: 18 additions & 0 deletions examples/pyo3-benchmarks/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# pyo3-benchmarks

This extension module contains benchmarks for pieces of PyO3's API accessible from Python.

## Running the benchmarks

You can install the module in your Python environment and then run the benchmarks with pytest:

```shell
python setup.py develop
pytest
```

Or with tox:

```shell
tox -e py
```
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
pip>=19.1
hypothesis>=3.55
pytest>=3.5.0
setuptools-rust>=0.10.2
psutil>=5.6
pytest-benchmark~=3.2
Original file line number Diff line number Diff line change
@@ -1,24 +1,7 @@
import sys
import platform

from setuptools import setup
from setuptools_rust import RustExtension


def get_py_version_cfgs():
# For now each Cfg Py_3_X flag is interpreted as "at least 3.X"
version = sys.version_info[0:2]
py3_min = 6
out_cfg = []
for minor in range(py3_min, version[1] + 1):
out_cfg.append("--cfg=Py_3_%d" % minor)

if platform.python_implementation() == "PyPy":
out_cfg.append("--cfg=PyPy")

return out_cfg


setup(
name="pyo3-benchmarks",
version="0.1.0",
Expand All @@ -35,7 +18,6 @@ def get_py_version_cfgs():
rust_extensions=[
RustExtension(
"pyo3_benchmarks._pyo3_benchmarks",
rustc_flags=get_py_version_cfgs(),
debug=False,
),
],
Expand Down
File renamed without changes.
File renamed without changes.
27 changes: 27 additions & 0 deletions examples/pyo3-pytests/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
[package]
authors = ["PyO3 Authors"]
name = "pyo3-pytests"
version = "0.1.0"
description = "Python-based tests for PyO3"
edition = "2018"

[dependencies]

[dependencies.pyo3]
path = "../../"
features = ["extension-module"]

[lib]
name = "pyo3_pytests"
crate-type = ["cdylib"]

[package.metadata.maturin]
classifier=[
"License :: OSI Approved :: MIT License",
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"Programming Language :: Python",
"Programming Language :: Rust",
"Operating System :: POSIX",
"Operating System :: MacOS :: MacOS X",
]
File renamed without changes.
19 changes: 19 additions & 0 deletions examples/pyo3-pytests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# pyo3-pytests

An extension module built using PyO3, used to test PyO3 from Python.

## Testing

This package is intended to be built using `maturin`. Once built, you can run the tests using `pytest`:

```shell
pip install maturin
maturin develop
pytest
```

Alternatively, install tox and run the tests inside an isolated environment:

```shell
tox -e py
```
28 changes: 28 additions & 0 deletions examples/pyo3-pytests/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use std::process::Command;

fn main() {
let out = Command::new("python")
.args(&["-c", "import sys; import platform; print(sys.version_info[1]); print(platform.python_implementation())"])
.output()
.expect("python version did not print");

let output = String::from_utf8_lossy(&out.stdout);
let mut lines = output.trim().lines();

println!("{}", output);

let version: u8 = lines
.next()
.unwrap()
.parse()
.expect("python version was not parsed");
let implementation = lines.next().unwrap();

for each in 6..version {
println!("cargo:rustc-cfg=Py_3_{}", each);
}

if implementation == "PyPy" {
println!("cargo:rustc-cfg=PyPy");
}
}
1 change: 1 addition & 0 deletions examples/pyo3-pytests/pyo3_pytests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .pyo3_pytests import *
3 changes: 3 additions & 0 deletions examples/pyo3-pytests/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[build-system]
requires = ["maturin"]
build-backend = "maturin"
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
pip>=19.1
hypothesis>=3.55
pytest>=3.5.0
setuptools-rust>=0.10.2
psutil>=5.6
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use pyo3::prelude::*;
use pyo3::types::PyDict;

#[pymodule]
fn test_dict(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
fn dict_iter(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
m.add_class::<DictSize>()?;
Ok(())
}
Expand Down
Loading

0 comments on commit 23ba683

Please sign in to comment.