mirror of
https://github.com/boostorg/python.git
synced 2026-01-21 17:12:22 +00:00
Fix lots of bugs in the numeric interface and tests.
Tests: * Coerce a result to bool to deal with Python's new Bool type * Better reporting of mismatches in expected and received results * Remove bogus nullary y.astype() call * Fix all uses of trace and diagonal so they don't cause errors * Use appropriate typecodes * Use doctest detailed API to run just the relevant tests * Factor out error handling from macro API: * Added get_module_name() function to get current numeric module * new_(x) now returns an array instead of object * Fixed the signatures of the factory() family of functions * Updated docs accordingly. [SVN r35528]
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
#include <boost/python/tuple.hpp>
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/def.hpp>
|
||||
#include <boost/python/str.hpp>
|
||||
|
||||
using namespace boost::python;
|
||||
|
||||
@@ -39,19 +40,28 @@ void info(numeric::array const& z)
|
||||
z.info();
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
object handle_error()
|
||||
{
|
||||
PyObject* type, *value, *traceback;
|
||||
PyErr_Fetch(&type, &value, &traceback);
|
||||
handle<> ty(type), v(value), tr(traceback);
|
||||
return object("exception");
|
||||
str format("exception type: %sn");
|
||||
format += "exception value: %sn";
|
||||
format += "traceback:n%s" ;
|
||||
object ret = format % boost::python::make_tuple(ty, v, tr);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#define CHECK(expr) \
|
||||
{ \
|
||||
object result; \
|
||||
try { result = object(expr); } \
|
||||
catch(error_already_set) \
|
||||
{ \
|
||||
PyObject* type, *value, *traceback; \
|
||||
PyErr_Fetch(&type, &value, &traceback); \
|
||||
handle<> ty(type), v(value), tr(traceback); \
|
||||
str format("exception type: %s\n"); \
|
||||
format += "exception value: %s\n"; \
|
||||
format += "traceback:\n%s" ; \
|
||||
result = format % boost::python::make_tuple(ty, v, tr); \
|
||||
result = handle_error(); \
|
||||
} \
|
||||
check(result); \
|
||||
}
|
||||
@@ -73,7 +83,7 @@ void exercise(numeric::array& y, object check)
|
||||
// the results of corresponding python operations.
|
||||
void exercise_numarray(numeric::array& y, object check)
|
||||
{
|
||||
CHECK(y.astype());
|
||||
CHECK(str(y));
|
||||
|
||||
CHECK(y.argmax());
|
||||
CHECK(y.argmax(0));
|
||||
@@ -89,7 +99,7 @@ void exercise_numarray(numeric::array& y, object check)
|
||||
|
||||
CHECK(y.diagonal());
|
||||
CHECK(y.diagonal(1));
|
||||
CHECK(y.diagonal(0, 1));
|
||||
CHECK(y.diagonal(0, 0));
|
||||
CHECK(y.diagonal(0, 1, 0));
|
||||
|
||||
CHECK(y.is_c_array());
|
||||
@@ -97,19 +107,22 @@ void exercise_numarray(numeric::array& y, object check)
|
||||
|
||||
CHECK(y.trace());
|
||||
CHECK(y.trace(1));
|
||||
CHECK(y.trace(0, 1));
|
||||
CHECK(y.trace(0, 0));
|
||||
CHECK(y.trace(0, 1, 0));
|
||||
|
||||
CHECK(y.new_('D'));
|
||||
CHECK(y.new_("D").getshape());
|
||||
CHECK(y.new_("D").type());
|
||||
y.sort();
|
||||
CHECK(y);
|
||||
CHECK(y.type());
|
||||
|
||||
CHECK(y.factory(make_tuple(1.2, 3.4)));
|
||||
CHECK(y.factory(make_tuple(1.2, 3.4), "Double"));
|
||||
CHECK(y.factory(make_tuple(1.2, 3.4), "Double", make_tuple(1,2,1)));
|
||||
CHECK(y.factory(make_tuple(1.2, 3.4), "Double", make_tuple(2,1,1), false));
|
||||
CHECK(y.factory(make_tuple(1.2, 3.4), "Double", make_tuple(2), true, true));
|
||||
CHECK(y.factory(make_tuple(1.2, 3.4), "f8"));
|
||||
CHECK(y.factory(make_tuple(1.2, 3.4), "f8", true));
|
||||
CHECK(y.factory(make_tuple(1.2, 3.4), "f8", true, false));
|
||||
CHECK(y.factory(make_tuple(1.2, 3.4), "f8", true, false, object()));
|
||||
CHECK (y.factory(make_tuple(1.2, 3.4), "f8", true, false, object(), make_tuple(1,2,1)));
|
||||
|
||||
}
|
||||
|
||||
BOOST_PYTHON_MODULE(numpy_ext)
|
||||
@@ -119,6 +132,7 @@ BOOST_PYTHON_MODULE(numpy_ext)
|
||||
def("exercise", exercise);
|
||||
def("exercise_numarray", exercise_numarray);
|
||||
def("set_module_and_type", &numeric::array::set_module_and_type);
|
||||
def("get_module_name", &numeric::array::get_module_name);
|
||||
def("info", info);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
# tests based on the availability of Numeric and numarray, the corresponding
|
||||
# test functions are simply deleted below if necessary.
|
||||
|
||||
# So we can coerce portably across Python versions
|
||||
bool = type(1 == 1)
|
||||
|
||||
def numeric_tests():
|
||||
'''
|
||||
>>> from numpy_ext import *
|
||||
@@ -55,8 +58,8 @@ def _numarray_tests():
|
||||
>>> check = p.check
|
||||
>>> exercise_numarray(x, p)
|
||||
|
||||
>>> check(y.astype());
|
||||
|
||||
>>> check(str(y))
|
||||
|
||||
>>> check(y.argmax());
|
||||
>>> check(y.argmax(0));
|
||||
|
||||
@@ -68,30 +71,35 @@ def _numarray_tests():
|
||||
|
||||
>>> y.byteswap();
|
||||
>>> check(y);
|
||||
|
||||
|
||||
>>> check(y.diagonal());
|
||||
>>> check(y.diagonal(1));
|
||||
>>> check(y.diagonal(0, 1));
|
||||
>>> check(y.diagonal(0, 0));
|
||||
>>> check(y.diagonal(0, 1, 0));
|
||||
|
||||
>>> check(y.is_c_array());
|
||||
>>> check(y.isbyteswapped());
|
||||
|
||||
# coerce because numarray still returns an int and the C++ interface forces
|
||||
# the return type to bool
|
||||
>>> check( bool(y.isbyteswapped()) );
|
||||
|
||||
>>> check(y.trace());
|
||||
>>> check(y.trace(1));
|
||||
>>> check(y.trace(0, 1));
|
||||
>>> check(y.trace(0, 0));
|
||||
>>> check(y.trace(0, 1, 0));
|
||||
|
||||
>>> check(y.new('D'));
|
||||
>>> check(y.new('D').getshape());
|
||||
>>> check(y.new('D').type());
|
||||
>>> y.sort();
|
||||
>>> check(y);
|
||||
>>> check(y.type());
|
||||
|
||||
>>> check(y.factory((1.2, 3.4)));
|
||||
>>> check(y.factory((1.2, 3.4), "Double"));
|
||||
>>> check(y.factory((1.2, 3.4), "Double", (1,2,1)));
|
||||
>>> check(y.factory((1.2, 3.4), "Double", (2,1,1), false));
|
||||
>>> check(y.factory((1.2, 3.4), "Double", (2,), true, true));
|
||||
>>> check(y.factory((1.2, 3.4), "f8"))
|
||||
>>> check(y.factory((1.2, 3.4), "f8", true))
|
||||
>>> check(y.factory((1.2, 3.4), "f8", true, false))
|
||||
>>> check(y.factory((1.2, 3.4), "f8", true, false, None))
|
||||
>>> check(y.factory((1.2, 3.4), "f8", true, false, None, (1,2,1)))
|
||||
|
||||
>>> p.results
|
||||
[]
|
||||
@@ -105,12 +113,12 @@ class _printer(object):
|
||||
def __init__(self):
|
||||
self.results = [];
|
||||
def __call__(self, *stuff):
|
||||
self.results += [ str(x) for x in stuff ]
|
||||
for x in stuff:
|
||||
self.results.append(str(x))
|
||||
def check(self, x):
|
||||
if self.results[0] == str(x):
|
||||
del self.results[0]
|
||||
else:
|
||||
print ' Expected:\n %s\n but got:\n %s' % (x, self.results[0])
|
||||
if self.results[0] != str(x):
|
||||
print ' Expected:\n %s\n but the C++ interface gave:\n %s' % (x, self.results[0])
|
||||
del self.results[0]
|
||||
|
||||
def _run(args = None):
|
||||
import sys
|
||||
@@ -150,21 +158,29 @@ def _run(args = None):
|
||||
|
||||
failures = 0
|
||||
|
||||
find = doctest.DocTestFinder().find
|
||||
run = doctest.DocTestRunner().run
|
||||
|
||||
#
|
||||
# Run tests 4 different ways if both modules are installed, just
|
||||
# to show that set_module_and_type() is working properly
|
||||
#
|
||||
|
||||
# run all the tests with default module search
|
||||
print 'testing default extension module'
|
||||
failures += doctest.testmod(sys.modules.get(__name__))[0]
|
||||
print 'testing default extension module:', \
|
||||
numpy_ext.get_module_name() or '[numeric support not installed]'
|
||||
|
||||
for test in find(numeric_tests):
|
||||
failures += run(test)[0]
|
||||
|
||||
# test against Numeric if installed
|
||||
if has_numeric:
|
||||
print 'testing Numeric module explicitly'
|
||||
numpy_ext.set_module_and_type('Numeric', 'ArrayType')
|
||||
failures += doctest.testmod(sys.modules.get(__name__))[0]
|
||||
|
||||
|
||||
for test in find(numeric_tests):
|
||||
failures += run(test)[0]
|
||||
|
||||
global __test__
|
||||
if has_numarray:
|
||||
# Add the _numarray_tests to the list of things to test in
|
||||
@@ -173,13 +189,18 @@ def _run(args = None):
|
||||
'numeric_tests': numeric_tests }
|
||||
print 'testing numarray module explicitly'
|
||||
numpy_ext.set_module_and_type('numarray', 'NDArray')
|
||||
failures += doctest.testmod(sys.modules.get(__name__))[0]
|
||||
|
||||
for test in find(numeric_tests) + find(_numarray_tests):
|
||||
failures += run(test)[0]
|
||||
del __test__
|
||||
|
||||
# see that we can go back to the default
|
||||
print 'testing default module again'
|
||||
numpy_ext.set_module_and_type('', '')
|
||||
failures += doctest.testmod(sys.modules.get(__name__))[0]
|
||||
print 'testing default module again:', \
|
||||
numpy_ext.get_module_name() or '[numeric support not installed]'
|
||||
|
||||
for test in find(numeric_tests):
|
||||
failures += run(test)[0]
|
||||
|
||||
return failures
|
||||
|
||||
|
||||
Reference in New Issue
Block a user