Skip to content

Commit 3ce52ce

Browse files
authored
Merge pull request #77 from kngwyu/py2
Python2 support
2 parents 733083c + c037c78 commit 3ce52ce

File tree

10 files changed

+110
-13
lines changed

10 files changed

+110
-13
lines changed

.travis.yml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,14 @@ cache:
99

1010
matrix:
1111
include:
12-
- python: "3.5"
13-
- python: "3.6"
12+
- python: "2.7"
13+
env: FEATURES=python2
14+
- python: "3.5"
15+
env: FEATURES=python3
16+
- python: "3.6"
17+
env: FEATURES=python3
18+
- python: "3.7-dev"
19+
env: FEATURES=python3
1420

1521
env:
1622
global:

Cargo.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,12 @@ num-complex = "0.2"
1616
num-traits = "0.2.6"
1717
ndarray = "0.12"
1818
pyo3 = "0.5.0-alpha.2"
19+
20+
[features]
21+
# In default setting, python version is automatically detected
22+
default = []
23+
# Use this feature when building python2 binding.
24+
python2 = ["pyo3/python2"]
25+
# Use this feature when building python3 binding.
26+
python3 = ["pyo3/python3"]
27+

README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,23 @@ https://github.com/PyO3/pyo3/blob/master/build.rs for minimum required version)
2626
Starting from 0.3, rust-numpy migrated from rust-cpython to pyo3.
2727
If you want to use rust-cpython, use version 0.2.1 from crates.io.
2828

29+
Supported python version
30+
-------------
31+
Currently 2.7, 3.5, 3.6, 3.7 are supported.
32+
33+
By default, python version is automatically by execute `python`.
34+
35+
If you need to use python version, please add a feature flag like
36+
37+
``` toml
38+
[dependencies.numpy]
39+
version = "0.4.0-alpha.1"
40+
features = ["python3"]
41+
```
42+
.
43+
44+
You can also specify version in [setup.py](examples/simple-extension/setup.py)
45+
2946

3047
Example
3148
---------

appveyor.yml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
environment:
22
TARGET: x86_64-pc-windows-msvc
33
matrix:
4+
- PYTHON: "C:/Python27-x64"
5+
FEATURES: python2
46
- PYTHON: "C:/Python35-x64"
7+
FEATURES: python3
58
- PYTHON: "C:/Python36-x64"
9+
FEATURES: python3
610

711
install:
812
- "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%"
@@ -17,10 +21,9 @@ install:
1721
- pip install setuptools-rust pytest pytest-benchmark tox numpy
1822

1923
build_script:
20-
- cargo build --verbose
24+
- cargo build --verbose --features %FEATURES%
2125

2226
test_script:
23-
- cargo build --verbose --all
24-
- cargo test --verbose --all
27+
- cargo test --verbose --features %FEATURES%
2528
- rustdoc --test README.md -L native="%PYTHON%\\libs" -L target/debug/deps/
2629
- cd examples/simple-extension && python setup.py install && python setup.py test

build.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
use std::process::{Command, Stdio};
2+
use std::str;
3+
fn is_python2() -> bool {
4+
let script = r"
5+
import sys
6+
print(sys.version_info[0])
7+
";
8+
let out = Command::new("python")
9+
.args(&["-c", script])
10+
.stderr(Stdio::inherit())
11+
.output()
12+
.expect("Failed to run the python interpreter");
13+
let version = str::from_utf8(&out.stdout).unwrap();
14+
version.starts_with("2")
15+
}
16+
17+
fn cfg(python2: bool) {
18+
if python2 {
19+
println!("cargo:rustc-cfg=Py_2");
20+
} else {
21+
println!("cargo:rustc-cfg=Py_3");
22+
}
23+
}
24+
25+
fn main() {
26+
if cfg!(feature = "python3") {
27+
cfg(false);
28+
} else if cfg!(feature = "python2") {
29+
cfg(true);
30+
} else {
31+
cfg(is_python2());
32+
}
33+
}

ci/travis/test.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
set -ex
44

5-
cargo build --verbose --all
6-
cargo test --verbose --all
5+
cargo build --verbose --features $FEATURES
6+
cargo test --verbose --features $FEATURES
77
rustdoc -L target/debug/deps/ --test README.md
88

99
for example in examples/*; do

examples/simple-extension/setup.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,20 @@ def run(self):
1414
raise SystemExit(errno)
1515

1616

17+
def get_cfg_flags():
18+
version = sys.version_info[0:2]
19+
if version[0] == 2:
20+
return ['--cfg=Py_2']
21+
else:
22+
return ['--cfg=Py_3']
23+
24+
def get_features():
25+
version = sys.version_info[0:2]
26+
if version[0] == 2:
27+
return ['numpy/python2']
28+
else:
29+
return ['numpy/python3']
30+
1731
setup_requires = ['setuptools-rust>=0.6.0']
1832
install_requires = ['numpy']
1933
test_requires = install_requires + ['pytest']
@@ -22,7 +36,12 @@ def run(self):
2236
name='rust_ext',
2337
version='0.1.0',
2438
description='Example of python-extension using rust-numpy',
25-
rust_extensions=[RustExtension('rust_ext.rust_ext', './Cargo.toml')],
39+
rust_extensions=[RustExtension(
40+
'rust_ext.rust_ext',
41+
'./Cargo.toml',
42+
rustc_flags=get_cfg_flags(),
43+
features=get_features(),
44+
)],
2645
install_requires=install_requires,
2746
setup_requires=setup_requires,
2847
test_requires=test_requires,

examples/simple-extension/tests/test_ext.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ def test_axpy():
77
y = np.array([3.0, 3.0, 3.0])
88
z = axpy(3.0, x, y)
99
np.testing.assert_array_almost_equal(z, np.array([6.0, 9.0, 12.0]))
10-
x = np.array([*x, 4.0])
11-
y = np.array([*y, 3.0])
10+
x = np.array([1.0, 2.0, 3.0, 4.0])
11+
y = np.array([3.0, 3.0, 3.0, 3.0])
1212
z = axpy(3.0, x, y)
1313
np.testing.assert_array_almost_equal(z, np.array([6.0, 9.0, 12.0, 15.0]))
1414

examples/simple-extension/tox.ini

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
[tox]
2-
envlist = py35,
2+
envlist = py27,
3+
py35,
34
py36,
45
py37,
56
minversion = 2.9.0

src/npyffi/mod.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,19 @@
1212
use pyo3::ffi;
1313
use std::ffi::CString;
1414
use std::os::raw::c_void;
15-
use std::ptr::null_mut;
1615

1716
fn get_numpy_api(module: &str, capsule: &str) -> *const *const c_void {
1817
let module = CString::new(module).unwrap();
1918
let capsule = CString::new(capsule).unwrap();
19+
#[cfg(not(Py_3))]
20+
unsafe fn get_capsule(capsule: *mut ffi::PyObject) -> *const *const c_void {
21+
ffi::PyCObject_AsVoidPtr(capsule) as *const *const c_void
22+
}
23+
#[cfg(Py_3)]
24+
unsafe fn get_capsule(capsule: *mut ffi::PyObject) -> *const *const c_void {
25+
use std::ptr::null_mut;
26+
ffi::PyCapsule_GetPointer(capsule, null_mut()) as *const *const c_void
27+
}
2028
unsafe {
2129
assert_ne!(
2230
ffi::Py_IsInitialized(),
@@ -27,7 +35,8 @@ Please make sure that you get gil, by `let gil = Python::acquire_gil();`"
2735
let numpy = ffi::PyImport_ImportModule(module.as_ptr());
2836
assert!(!numpy.is_null(), "Failed to import numpy module");
2937
let capsule = ffi::PyObject_GetAttrString(numpy as *mut ffi::PyObject, capsule.as_ptr());
30-
ffi::PyCapsule_GetPointer(capsule, null_mut()) as *const *const c_void
38+
assert!(!capsule.is_null(), "Failed to import numpy module");
39+
get_capsule(capsule)
3140
}
3241
}
3342

0 commit comments

Comments
 (0)