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 1, 2021
1 parent 4713b46 commit 555c7ab
Show file tree
Hide file tree
Showing 65 changed files with 488 additions and 154 deletions.
2 changes: 1 addition & 1 deletion .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
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.
File renamed without changes.
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",
]
2 changes: 2 additions & 0 deletions examples/pyo3-pytests/MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
include pyproject.toml Cargo.toml
recursive-include src *
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");
}
}
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
49 changes: 49 additions & 0 deletions examples/pyo3-pytests/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use pyo3::prelude::*;
use pyo3::types::PyDict;
use pyo3::wrap_pymodule;

pub mod buf_and_str;
pub mod datetime;
pub mod dict_iter;
pub mod misc;
pub mod objstore;
pub mod othermod;
pub mod pyclass_iter;
pub mod subclassing;

use buf_and_str::*;
use datetime::*;
use dict_iter::*;
use misc::*;
use objstore::*;
use othermod::*;
use pyclass_iter::*;
use subclassing::*;

#[pymodule]
fn pyo3_pytests(py: Python, m: &PyModule) -> PyResult<()> {
m.add_wrapped(wrap_pymodule!(buf_and_str))?;
m.add_wrapped(wrap_pymodule!(datetime))?;
m.add_wrapped(wrap_pymodule!(dict_iter))?;
m.add_wrapped(wrap_pymodule!(misc))?;
m.add_wrapped(wrap_pymodule!(objstore))?;
m.add_wrapped(wrap_pymodule!(othermod))?;
m.add_wrapped(wrap_pymodule!(pyclass_iter))?;
m.add_wrapped(wrap_pymodule!(subclassing))?;

// Inserting to sys.modules allows importing submodules nicely from Python
// e.g. import pyo3_pytests.buf_and_str as bas

let sys = PyModule::import(py, "sys")?;
let sys_modules: &PyDict = sys.getattr("modules")?.downcast()?;
sys_modules.set_item("pyo3_pytests.buf_and_str", m.getattr("buf_and_str")?)?;
sys_modules.set_item("pyo3_pytests.datetime", m.getattr("datetime")?)?;
sys_modules.set_item("pyo3_pytests.dict_iter", m.getattr("dict_iter")?)?;
sys_modules.set_item("pyo3_pytests.misc", m.getattr("misc")?)?;
sys_modules.set_item("pyo3_pytests.objstore", m.getattr("objstore")?)?;
sys_modules.set_item("pyo3_pytests.othermod", m.getattr("othermod")?)?;
sys_modules.set_item("pyo3_pytests.pyclass_iter", m.getattr("pyclass_iter")?)?;
sys_modules.set_item("pyo3_pytests.subclassing", m.getattr("subclassing")?)?;

Ok(())
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import psutil
import pytest
from rustapi_module.buf_and_str import BytesExtractor
from pyo3_pytests.buf_and_str import BytesExtractor

PYPY = platform.python_implementation() == "PyPy"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import sys

import pytest
import rustapi_module.datetime as rdt
import pyo3_pytests.datetime as rdt
from hypothesis import given, example
from hypothesis import strategies as st

Expand Down
Loading

0 comments on commit 555c7ab

Please sign in to comment.