Skip to content

Commit dc35ecd

Browse files
committed
Adding tests for xtensor-python
1 parent 8cca223 commit dc35ecd

File tree

5 files changed

+172
-1
lines changed

5 files changed

+172
-1
lines changed

.gitignore

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Python Artefacts
2+
3+
*.py[cod]
4+
5+
# C extensions
6+
7+
*.so
8+
9+
# Packages
10+
11+
*.egg
12+
*.egg-info
13+
dist
14+
build
15+
eggs
16+
parts
17+
bin
18+
var
19+
sdist
20+
develop-eggs
21+
.installed.cfg
22+
lib
23+
lib64
24+
__pycache__
25+
tmp/
26+
27+
# Jupyter Artefacts
28+
.ipynb_checkpoints/

README.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,10 @@
1313

1414
# Testing
1515

16-
- Checkout and pip install the `xtensor-python-test` project.
16+
Testing `xtensor-python` requires `nosetests`
17+
18+
``` bash
19+
nosetests .
20+
```
21+
22+
To pick up changes in `xtensor-python` while rebuilding, delete the `build/` directory.

test/main.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#include <pybind11/pybind11.h>
2+
#include "xtensor/xarray.hpp"
3+
#include "xtensor-python/pyarray.hpp"
4+
5+
namespace py = pybind11;
6+
7+
int test0(xt::pyarray<double> &m)
8+
{
9+
return m(0);
10+
}
11+
12+
PYBIND11_PLUGIN(xtensor_python_test)
13+
{
14+
py::module m("xtensor_python_test", "Test module for xtensor python bindings");
15+
16+
m.def("test0", test0, "");
17+
18+
return m.ptr();
19+
}

test/setup.py

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
from setuptools import setup, Extension
2+
from setuptools.command.build_ext import build_ext
3+
import sys
4+
import os
5+
import setuptools
6+
7+
__version__ = '0.0.1'
8+
9+
10+
class get_pybind_include(object):
11+
"""Helper class to determine the pybind11 include path
12+
13+
The purpose of this class is to postpone importing pybind11
14+
until it is actually installed, so that the ``get_include()``
15+
method can be invoked. """
16+
17+
def __init__(self, user=False):
18+
self.user = user
19+
20+
def __str__(self):
21+
import pybind11
22+
return pybind11.get_include(self.user)
23+
24+
25+
ext_modules = [
26+
Extension(
27+
'xtensor_python_test',
28+
['main.cpp'],
29+
include_dirs=[
30+
# Path to pybind11 headers
31+
get_pybind_include(),
32+
get_pybind_include(user=True),
33+
os.path.join(sys.prefix, 'include')
34+
],
35+
language='c++'
36+
),
37+
]
38+
39+
40+
def has_flag(compiler, flagname):
41+
"""Return a boolean indicating whether a flag name is supported on
42+
the specified compiler.
43+
"""
44+
import tempfile
45+
with tempfile.NamedTemporaryFile('w', suffix='.cpp') as f:
46+
f.write('int main (int argc, char **argv) { return 0; }')
47+
try:
48+
compiler.compile([f.name], extra_postargs=[flagname])
49+
except setuptools.distutils.errors.CompileError:
50+
return False
51+
return True
52+
53+
54+
def cpp_flag(compiler):
55+
"""Return the -std=c++14 compiler flag and errors when the flag is
56+
no available.
57+
"""
58+
if has_flag(compiler, '-std=c++14'):
59+
return '-std=c++14'
60+
else:
61+
raise RuntimeError('C++14 support is required by xtensor!')
62+
63+
64+
class BuildExt(build_ext):
65+
"""A custom build extension for adding compiler-specific options."""
66+
c_opts = {
67+
'msvc': ['/EHsc'],
68+
'unix': [],
69+
}
70+
71+
if sys.platform == 'darwin':
72+
c_opts['unix'] += ['-stdlib=libc++', '-mmacosx-version-min=10.7']
73+
74+
def build_extensions(self):
75+
ct = self.compiler.compiler_type
76+
opts = self.c_opts.get(ct, [])
77+
if ct == 'unix':
78+
opts.append('-DVERSION_INFO="%s"' % self.distribution.get_version())
79+
opts.append(cpp_flag(self.compiler))
80+
if has_flag(self.compiler, '-fvisibility=hidden'):
81+
opts.append('-fvisibility=hidden')
82+
elif ct == 'msvc':
83+
opts.append('/DVERSION_INFO=\\"%s\\"' % self.distribution.get_version())
84+
for ext in self.extensions:
85+
ext.extra_compile_args = opts
86+
build_ext.build_extensions(self)
87+
88+
setup(
89+
name='xtensor_python_test',
90+
version=__version__,
91+
author='Sylvain Corlay',
92+
author_email='sylvain.corlay@gmail.com',
93+
url='https://github.com/pybind/python_example',
94+
description='An example project using xtensor-python',
95+
long_description='',
96+
ext_modules=ext_modules,
97+
install_requires=['pybind11>=1.8.1'],
98+
cmdclass={'build_ext': BuildExt},
99+
zip_safe=False,
100+
)

test/test_pyarray.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import os
2+
import sys
3+
import subprocess
4+
5+
# Build the test extension
6+
7+
here = os.path.abspath(os.path.dirname(__file__))
8+
subprocess.check_call([sys.executable, os.path.join(here, 'setup.py'), 'build_ext', '--inplace'], cwd=here)
9+
10+
# Test it!
11+
12+
from unittest import TestCase
13+
import xtensor_python_test as xt
14+
15+
class ExampleTest(TestCase):
16+
17+
def test_example(self):
18+
self.assertEqual(4, xt.test0([4, 5, 6]))

0 commit comments

Comments
 (0)