examples: maturin and setuptools_rust examples
This commit is contained in:
parent
1751a7fb19
commit
370652eba8
|
@ -15,7 +15,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-python@v2
|
- uses: actions/setup-python@v2
|
||||||
- run: pip install black==19.10b0
|
- run: pip install black==20.8b1
|
||||||
- uses: actions-rs/toolchain@v1
|
- uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: stable
|
toolchain: stable
|
||||||
|
@ -130,15 +130,13 @@ jobs:
|
||||||
run: cargo test --manifest-path=pyo3-macros-backend/Cargo.toml
|
run: cargo test --manifest-path=pyo3-macros-backend/Cargo.toml
|
||||||
|
|
||||||
- name: Install python test dependencies
|
- name: Install python test dependencies
|
||||||
run: |
|
run: python -m pip install -U pip tox
|
||||||
python -m pip install -U pip setuptools
|
|
||||||
pip install setuptools-rust pytest pytest-benchmark tox
|
|
||||||
|
|
||||||
- name: Test example extension modules
|
- name: Test example extension modules
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
for example_dir in examples/*; do
|
for example_dir in examples/*; do
|
||||||
tox --discover $(which python) -c $example_dir -e py
|
tox -c $example_dir -e py
|
||||||
done
|
done
|
||||||
env:
|
env:
|
||||||
TOX_TESTENV_PASSENV: "CARGO_BUILD_TARGET"
|
TOX_TESTENV_PASSENV: "CARGO_BUILD_TARGET"
|
||||||
|
|
|
@ -73,7 +73,9 @@ nightly = []
|
||||||
members = [
|
members = [
|
||||||
"pyo3-macros",
|
"pyo3-macros",
|
||||||
"pyo3-macros-backend",
|
"pyo3-macros-backend",
|
||||||
"examples/pyo3_benchmarks",
|
"examples/pyo3-benchmarks",
|
||||||
"examples/rustapi_module",
|
"examples/pyo3-pytests",
|
||||||
|
"examples/maturin-starter",
|
||||||
|
"examples/setuptools-rust-starter",
|
||||||
"examples/word-count"
|
"examples/word-count"
|
||||||
]
|
]
|
||||||
|
|
|
@ -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",
|
||||||
|
]
|
|
@ -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
|
||||||
|
```
|
|
@ -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
|
|
@ -0,0 +1,3 @@
|
||||||
|
[build-system]
|
||||||
|
requires = ["maturin>=0.10,<0.11"]
|
||||||
|
build-backend = "maturin"
|
|
@ -0,0 +1 @@
|
||||||
|
pytest>=3.5.0
|
|
@ -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(())
|
||||||
|
}
|
|
@ -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(())
|
||||||
|
}
|
|
@ -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
|
|
@ -0,0 +1,6 @@
|
||||||
|
from maturin_starter.submodule import SubmoduleClass
|
||||||
|
|
||||||
|
|
||||||
|
def test_submodule_class() -> None:
|
||||||
|
submodule_class = SubmoduleClass()
|
||||||
|
assert submodule_class.greeting() == "Hello, world!"
|
|
@ -6,5 +6,7 @@ skipsdist = true
|
||||||
description = Run the unit tests under {basepython}
|
description = Run the unit tests under {basepython}
|
||||||
deps = -rrequirements-dev.txt
|
deps = -rrequirements-dev.txt
|
||||||
commands =
|
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}
|
pytest {posargs}
|
|
@ -0,0 +1,3 @@
|
||||||
|
include Cargo.toml
|
||||||
|
recursive-include src *
|
||||||
|
recursive-include tests
|
|
@ -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
|
||||||
|
```
|
|
@ -1,6 +1,4 @@
|
||||||
pip>=19.1
|
pip>=19.1
|
||||||
hypothesis>=3.55
|
|
||||||
pytest>=3.5.0
|
pytest>=3.5.0
|
||||||
setuptools-rust>=0.10.2
|
setuptools-rust>=0.10.2
|
||||||
psutil>=5.6
|
|
||||||
pytest-benchmark~=3.2
|
pytest-benchmark~=3.2
|
|
@ -1,24 +1,7 @@
|
||||||
import sys
|
|
||||||
import platform
|
|
||||||
|
|
||||||
from setuptools import setup
|
from setuptools import setup
|
||||||
from setuptools_rust import RustExtension
|
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(
|
setup(
|
||||||
name="pyo3-benchmarks",
|
name="pyo3-benchmarks",
|
||||||
version="0.1.0",
|
version="0.1.0",
|
||||||
|
@ -35,7 +18,6 @@ setup(
|
||||||
rust_extensions=[
|
rust_extensions=[
|
||||||
RustExtension(
|
RustExtension(
|
||||||
"pyo3_benchmarks._pyo3_benchmarks",
|
"pyo3_benchmarks._pyo3_benchmarks",
|
||||||
rustc_flags=get_py_version_cfgs(),
|
|
||||||
debug=False,
|
debug=False,
|
||||||
),
|
),
|
||||||
],
|
],
|
|
@ -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",
|
||||||
|
]
|
|
@ -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
|
||||||
|
```
|
|
@ -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");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
from .pyo3_pytests import *
|
|
@ -0,0 +1,3 @@
|
||||||
|
[build-system]
|
||||||
|
requires = ["maturin>=0.10,<0.11"]
|
||||||
|
build-backend = "maturin"
|
|
@ -1,5 +1,4 @@
|
||||||
pip>=19.1
|
pip>=19.1
|
||||||
hypothesis>=3.55
|
hypothesis>=3.55
|
||||||
pytest>=3.5.0
|
pytest>=3.5.0
|
||||||
setuptools-rust>=0.10.2
|
|
||||||
psutil>=5.6
|
psutil>=5.6
|
|
@ -3,7 +3,7 @@ use pyo3::prelude::*;
|
||||||
use pyo3::types::PyDict;
|
use pyo3::types::PyDict;
|
||||||
|
|
||||||
#[pymodule]
|
#[pymodule]
|
||||||
fn test_dict(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
|
fn dict_iter(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
|
||||||
m.add_class::<DictSize>()?;
|
m.add_class::<DictSize>()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
|
@ -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(())
|
||||||
|
}
|
|
@ -4,7 +4,7 @@ import platform
|
||||||
|
|
||||||
import psutil
|
import psutil
|
||||||
import pytest
|
import pytest
|
||||||
from rustapi_module.buf_and_str import BytesExtractor
|
from pyo3_pytests.buf_and_str import BytesExtractor
|
||||||
|
|
||||||
PYPY = platform.python_implementation() == "PyPy"
|
PYPY = platform.python_implementation() == "PyPy"
|
||||||
|
|
|
@ -5,7 +5,7 @@ import re
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
import rustapi_module.datetime as rdt
|
import pyo3_pytests.datetime as rdt
|
||||||
from hypothesis import given, example
|
from hypothesis import given, example
|
||||||
from hypothesis import strategies as st
|
from hypothesis import strategies as st
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import pytest
|
import pytest
|
||||||
from rustapi_module.test_dict import DictSize
|
from pyo3_pytests.dict_iter import DictSize
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("size", [64, 128, 256])
|
@pytest.mark.parametrize("size", [64, 128, 256])
|
|
@ -0,0 +1,6 @@
|
||||||
|
import pyo3_pytests.misc
|
||||||
|
|
||||||
|
|
||||||
|
def test_issue_219():
|
||||||
|
# Should not deadlock
|
||||||
|
pyo3_pytests.misc.issue_219()
|
|
@ -4,7 +4,7 @@ import sys
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from rustapi_module.objstore import ObjStore
|
from pyo3_pytests.objstore import ObjStore
|
||||||
|
|
||||||
PYPY = platform.python_implementation() == "PyPy"
|
PYPY = platform.python_implementation() == "PyPy"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from hypothesis import given, assume
|
from hypothesis import given, assume
|
||||||
from hypothesis import strategies as st
|
from hypothesis import strategies as st
|
||||||
|
|
||||||
from rustapi_module import othermod
|
from pyo3_pytests import othermod
|
||||||
|
|
||||||
INTEGER32_ST = st.integers(min_value=(-(2 ** 31)), max_value=(2 ** 31 - 1))
|
INTEGER32_ST = st.integers(min_value=(-(2 ** 31)), max_value=(2 ** 31 - 1))
|
||||||
USIZE_ST = st.integers(min_value=othermod.USIZE_MIN, max_value=othermod.USIZE_MAX)
|
USIZE_ST = st.integers(min_value=othermod.USIZE_MIN, max_value=othermod.USIZE_MAX)
|
|
@ -1,5 +1,5 @@
|
||||||
import pytest
|
import pytest
|
||||||
from rustapi_module import pyclass_iter
|
from pyo3_pytests import pyclass_iter
|
||||||
|
|
||||||
|
|
||||||
def test_iter():
|
def test_iter():
|
|
@ -1,6 +1,6 @@
|
||||||
import platform
|
import platform
|
||||||
|
|
||||||
from rustapi_module.subclassing import Subclassable
|
from pyo3_pytests.subclassing import Subclassable
|
||||||
|
|
||||||
PYPY = platform.python_implementation() == "PyPy"
|
PYPY = platform.python_implementation() == "PyPy"
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
[tox]
|
||||||
|
# can't install from sdist because local pyo3 repo can't be included in the sdist
|
||||||
|
skipsdist = true
|
||||||
|
|
||||||
|
[testenv]
|
||||||
|
description = Run the unit tests under {basepython}
|
||||||
|
deps = -rrequirements-dev.txt
|
||||||
|
commands =
|
||||||
|
# Use pip master with in-tree-build feature (to be released in pip 21.1)
|
||||||
|
python -m pip install --upgrade git+https://github.com/pypa/pip.git
|
||||||
|
python -m pip install . --use-feature=in-tree-build
|
||||||
|
pytest {posargs}
|
|
@ -1,17 +0,0 @@
|
||||||
# rustapi_module
|
|
||||||
|
|
||||||
A simple extension module built using PyO3.
|
|
||||||
|
|
||||||
## Build
|
|
||||||
|
|
||||||
```shell
|
|
||||||
python setup.py install
|
|
||||||
```
|
|
||||||
|
|
||||||
## Testing
|
|
||||||
|
|
||||||
To test install tox globally and run
|
|
||||||
|
|
||||||
```shell
|
|
||||||
tox -e py
|
|
||||||
```
|
|
|
@ -1,16 +0,0 @@
|
||||||
[package]
|
|
||||||
authors = ["PyO3 Authors"]
|
|
||||||
name = "rustapi-module"
|
|
||||||
version = "0.1.0"
|
|
||||||
description = "A Python wrapper for the Rust API for purposes of testing"
|
|
||||||
edition = "2018"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
|
|
||||||
[dependencies.pyo3]
|
|
||||||
path = "../../"
|
|
||||||
features = ["extension-module"]
|
|
||||||
|
|
||||||
[lib]
|
|
||||||
name = "rustapi_module"
|
|
||||||
crate-type = ["cdylib"]
|
|
|
@ -1,17 +0,0 @@
|
||||||
# rustapi_module
|
|
||||||
|
|
||||||
A simple extension module built using PyO3.
|
|
||||||
|
|
||||||
## Build
|
|
||||||
|
|
||||||
```shell
|
|
||||||
python setup.py install
|
|
||||||
```
|
|
||||||
|
|
||||||
## Testing
|
|
||||||
|
|
||||||
To test install tox globally and run
|
|
||||||
|
|
||||||
```shell
|
|
||||||
tox -e py
|
|
||||||
```
|
|
|
@ -1,2 +0,0 @@
|
||||||
[build-system]
|
|
||||||
requires = ["setuptools>=41.0.0", "wheel", "setuptools_rust>=0.10.2"]
|
|
|
@ -1,53 +0,0 @@
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
def make_rust_extension(module_name):
|
|
||||||
return RustExtension(
|
|
||||||
module_name, "Cargo.toml", rustc_flags=get_py_version_cfgs(), debug=True
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
setup(
|
|
||||||
name="rustapi-module",
|
|
||||||
version="0.1.0",
|
|
||||||
classifiers=[
|
|
||||||
"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",
|
|
||||||
],
|
|
||||||
packages=["rustapi_module"],
|
|
||||||
rust_extensions=[
|
|
||||||
make_rust_extension("rustapi_module.buf_and_str"),
|
|
||||||
make_rust_extension("rustapi_module.datetime"),
|
|
||||||
make_rust_extension("rustapi_module.misc"),
|
|
||||||
make_rust_extension("rustapi_module.objstore"),
|
|
||||||
make_rust_extension("rustapi_module.othermod"),
|
|
||||||
make_rust_extension("rustapi_module.pyclass_iter"),
|
|
||||||
make_rust_extension("rustapi_module.subclassing"),
|
|
||||||
make_rust_extension("rustapi_module.test_dict"),
|
|
||||||
],
|
|
||||||
include_package_data=True,
|
|
||||||
zip_safe=False,
|
|
||||||
)
|
|
|
@ -1,8 +0,0 @@
|
||||||
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;
|
|
|
@ -1,6 +0,0 @@
|
||||||
import rustapi_module.misc
|
|
||||||
|
|
||||||
|
|
||||||
def test_issue_219():
|
|
||||||
# Should not deadlock
|
|
||||||
rustapi_module.misc.issue_219()
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
[package]
|
||||||
|
authors = ["PyO3 Authors"]
|
||||||
|
name = "setuptools-rust-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 = "setuptools_rust_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",
|
||||||
|
]
|
|
@ -0,0 +1,2 @@
|
||||||
|
include pyproject.toml Cargo.toml
|
||||||
|
recursive-include src *
|
|
@ -0,0 +1,24 @@
|
||||||
|
# setuptools-rust-starter
|
||||||
|
|
||||||
|
An example of a basic Python extension module built using PyO3 and `setuptools_rust`.
|
||||||
|
|
||||||
|
## Building and Testing
|
||||||
|
|
||||||
|
To build this package, first install `setuptools_rust`:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
pip install setuptools_rust
|
||||||
|
```
|
||||||
|
|
||||||
|
To build and test use `python setup.py develop`:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
pip install -r requirements-dev.txt
|
||||||
|
python setup.py develop && pytest
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternatively, install tox and run the tests inside an isolated environment:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
tox -e py
|
||||||
|
```
|
|
@ -0,0 +1,2 @@
|
||||||
|
pytest>=3.5.0
|
||||||
|
setuptools_rust~=0.11.0
|
|
@ -0,0 +1,26 @@
|
||||||
|
from setuptools import setup
|
||||||
|
from setuptools_rust import RustExtension
|
||||||
|
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name="setuptools-rust-starter",
|
||||||
|
version="0.1.0",
|
||||||
|
classifiers=[
|
||||||
|
"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",
|
||||||
|
],
|
||||||
|
packages=["setuptools_rust_starter"],
|
||||||
|
rust_extensions=[
|
||||||
|
RustExtension(
|
||||||
|
"setuptools_rust_starter._setuptools_rust_starter",
|
||||||
|
debug=False,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
include_package_data=True,
|
||||||
|
zip_safe=False,
|
||||||
|
)
|
|
@ -0,0 +1,7 @@
|
||||||
|
# import the contents of the Rust library into the Python extension
|
||||||
|
from ._setuptools_rust_starter import *
|
||||||
|
|
||||||
|
|
||||||
|
class PythonClass:
|
||||||
|
def __init__(self, value: int) -> None:
|
||||||
|
self.value = value
|
|
@ -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 _setuptools_rust_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 setuptools_rust_starter.submodule import SubmoduleClass
|
||||||
|
|
||||||
|
let sys = PyModule::import(py, "sys")?;
|
||||||
|
let sys_modules: &PyDict = sys.getattr("modules")?.downcast()?;
|
||||||
|
sys_modules.set_item("setuptools_rust_starter.submodule", m.getattr("submodule")?)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -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(())
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
from setuptools_rust_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
|
|
@ -0,0 +1,6 @@
|
||||||
|
from setuptools_rust_starter.submodule import SubmoduleClass
|
||||||
|
|
||||||
|
|
||||||
|
def test_submodule_class() -> None:
|
||||||
|
submodule_class = SubmoduleClass()
|
||||||
|
assert submodule_class.greeting() == "Hello, world!"
|
|
@ -0,0 +1,12 @@
|
||||||
|
[tox]
|
||||||
|
# can't install from sdist because local pyo3 repo can't be included in the sdist
|
||||||
|
skipsdist = true
|
||||||
|
|
||||||
|
[testenv]
|
||||||
|
description = Run the unit tests under {basepython}
|
||||||
|
deps = -rrequirements-dev.txt
|
||||||
|
commands =
|
||||||
|
# Use pip master with in-tree-build feature (to be released in pip 21.1)
|
||||||
|
python -m pip install --upgrade git+https://github.com/pypa/pip.git
|
||||||
|
python -m pip install . --use-feature=in-tree-build
|
||||||
|
pytest {posargs}
|
|
@ -41,7 +41,7 @@ use crate::{ffi, IntoPy, IntoPyPointer, PyClass, PyObject, Python};
|
||||||
/// # Python::with_gil(|py| {
|
/// # Python::with_gil(|py| {
|
||||||
/// # let inst = Py::new(py, Iter { count: 0 }).unwrap();
|
/// # let inst = Py::new(py, Iter { count: 0 }).unwrap();
|
||||||
/// # pyo3::py_run!(py, inst, "assert next(inst) == 1");
|
/// # pyo3::py_run!(py, inst, "assert next(inst) == 1");
|
||||||
/// # }); // test of StopIteration is done in examples/rustapi_module/pyclass_iter.rs
|
/// # }); // test of StopIteration is done in examples/pyo3-pytests/pyclass_iter.rs
|
||||||
/// ```
|
/// ```
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
pub trait PyIterProtocol<'p>: PyClass {
|
pub trait PyIterProtocol<'p>: PyClass {
|
||||||
|
|
Loading…
Reference in New Issue