examples: maturin and setuptools_rust examples
This commit is contained in:
parent
1751a7fb19
commit
370652eba8
|
@ -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
|
||||
|
@ -130,15 +130,13 @@ jobs:
|
|||
run: cargo test --manifest-path=pyo3-macros-backend/Cargo.toml
|
||||
|
||||
- name: Install python test dependencies
|
||||
run: |
|
||||
python -m pip install -U pip setuptools
|
||||
pip install setuptools-rust pytest pytest-benchmark tox
|
||||
run: python -m pip install -U pip tox
|
||||
|
||||
- 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"
|
||||
|
|
|
@ -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"
|
||||
]
|
||||
|
|
|
@ -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}
|
||||
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}
|
|
@ -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
|
||||
hypothesis>=3.55
|
||||
pytest>=3.5.0
|
||||
setuptools-rust>=0.10.2
|
||||
psutil>=5.6
|
||||
pytest-benchmark~=3.2
|
|
@ -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",
|
||||
|
@ -35,7 +18,6 @@ setup(
|
|||
rust_extensions=[
|
||||
RustExtension(
|
||||
"pyo3_benchmarks._pyo3_benchmarks",
|
||||
rustc_flags=get_py_version_cfgs(),
|
||||
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
|
||||
hypothesis>=3.55
|
||||
pytest>=3.5.0
|
||||
setuptools-rust>=0.10.2
|
||||
psutil>=5.6
|
|
@ -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(())
|
||||
}
|
|
@ -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 pytest
|
||||
from rustapi_module.buf_and_str import BytesExtractor
|
||||
from pyo3_pytests.buf_and_str import BytesExtractor
|
||||
|
||||
PYPY = platform.python_implementation() == "PyPy"
|
||||
|
|
@ -5,7 +5,7 @@ import re
|
|||
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
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import pytest
|
||||
from rustapi_module.test_dict import DictSize
|
||||
from pyo3_pytests.dict_iter import DictSize
|
||||
|
||||
|
||||
@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
|
||||
|
||||
from rustapi_module.objstore import ObjStore
|
||||
from pyo3_pytests.objstore import ObjStore
|
||||
|
||||
PYPY = platform.python_implementation() == "PyPy"
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
from hypothesis import given, assume
|
||||
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))
|
||||
USIZE_ST = st.integers(min_value=othermod.USIZE_MIN, max_value=othermod.USIZE_MAX)
|
|
@ -1,5 +1,5 @@
|
|||
import pytest
|
||||
from rustapi_module import pyclass_iter
|
||||
from pyo3_pytests import pyclass_iter
|
||||
|
||||
|
||||
def test_iter():
|
|
@ -1,6 +1,6 @@
|
|||
import platform
|
||||
|
||||
from rustapi_module.subclassing import Subclassable
|
||||
from pyo3_pytests.subclassing import Subclassable
|
||||
|
||||
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| {
|
||||
/// # let inst = Py::new(py, Iter { count: 0 }).unwrap();
|
||||
/// # 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)]
|
||||
pub trait PyIterProtocol<'p>: PyClass {
|
||||
|
|
Loading…
Reference in New Issue