2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-19 16:32:16 +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:
Dave Abrahams
2006-10-09 04:05:25 +00:00
parent 545be29ad3
commit 49d4aac8ec
5 changed files with 267 additions and 210 deletions

View File

@@ -1,105 +1,105 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<html>
<head>
<meta name="generator" content=
"HTML Tidy for Windows (vers 1st August 2002), see www.w3.org">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../boost.css">
<head>
<meta name="generator" content=
"HTML Tidy for Linux/x86 (vers 1 September 2005), see www.w3.org">
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<link rel="stylesheet" type="text/css" href="../boost.css">
<title>Boost.Python - &lt;boost/python/numeric.hpp&gt;</title>
</head>
<title>Boost.Python - &lt;boost/python/numeric.hpp&gt;</title>
</head>
<body>
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../../index.htm"><img height="86" width="277"
alt="C++ Boost" src="../../../../boost.png" border="0"></a></h3>
</td>
<body>
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../../index.htm"><img height="86" width="277" alt=
"C++ Boost" src="../../../../boost.png" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
<td valign="top">
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
<h2 align="center">Header &lt;boost/python/numeric.hpp&gt;</h2>
</td>
</tr>
</table>
<hr>
<h2 align="center">Header &lt;boost/python/numeric.hpp&gt;</h2>
</td>
</tr>
</table>
<hr>
<h2>Contents</h2>
<h2>Contents</h2>
<dl class="page-index">
<dt><a href="#introduction">Introduction</a></dt>
<dl class="page-index">
<dt><a href="#introduction">Introduction</a></dt>
<dt><a href="#classes">Classes</a></dt>
<dt><a href="#classes">Classes</a></dt>
<dd>
<dl class="page-index">
<dt><a href="#array-spec">Class <code>array</code></a></dt>
<dd>
<dl class="page-index">
<dt><a href="#array-spec">Class <code>array</code></a></dt>
<dd>
<dl class="page-index">
<dt><a href="#array-spec-synopsis">Class <code>array</code>
synopsis</a></dt>
<dd>
<dl class="page-index">
<dt><a href="#array-spec-synopsis">Class <code>array</code>
synopsis</a></dt>
<dt><a href="#array-spec-observers">Class <code>array</code>
observer functions</a></dt>
<dt><a href="#array-spec-observers">Class <code>array</code>
observer functions</a></dt>
<dt><a href="#array-spec-statics">Class <code>array</code>
static functions</a></dt>
</dl>
</dd>
</dl>
</dd>
<dt><a href="#array-spec-statics">Class <code>array</code> static
functions</a></dt>
</dl>
</dd>
</dl>
</dd>
<dt><a href="#examples">Example(s)</a></dt>
</dl>
<hr>
<dt><a href="#examples">Example(s)</a></dt>
</dl>
<hr>
<h2><a name="introduction"></a>Introduction</h2>
<h2><a name="introduction" id="introduction"></a>Introduction</h2>
<p>Exposes a <a href=
"ObjectWrapper.html#TypeWrapper-concept">TypeWrapper</a> for the Python
<a href=
"http://www.python.org/dev/doc/devel/lib/typesmapping.html">array</a>
type.</p>
<p>Exposes a <a href=
"ObjectWrapper.html#TypeWrapper-concept">TypeWrapper</a> for the Python
<a href=
"http://www.python.org/dev/doc/devel/lib/typesmapping.html">array</a>
type.</p>
<h2><a name="classes"></a>Classes</h2>
<h2><a name="classes" id="classes"></a>Classes</h2>
<h3><a name="array-spec"></a>Class <code>array</code></h3>
<h3><a name="array-spec" id="array-spec"></a>Class <code>array</code></h3>
<p>Provides access to the array types of <a href=
"http://www.pfdubois.com/numpy/">Numerical Python</a>'s <a href=
"http://www.pfdubois.com/numpy/#Numeric">Numeric</a> and <a href=
"http://stsdas.stsci.edu/numarray/index.html">NumArray</a> modules. With
the exception of the functions documented <a href=
"#array-spec-observers">below</a>, the semantics of the constructors and
member functions defined below can be fully understood by reading the <a
href="ObjectWrapper.html#TypeWrapper-concept">TypeWrapper</a> concept
definition. Since <code>array</code> is publicly derived from <code><a
href="object.html#object-spec">object</a></code>, the public object
interface applies to <code>array</code> instances as well.</p>
<p>Provides access to the array types of <a href=
"http://www.pfdubois.com/numpy/">Numerical Python</a>'s <a href=
"http://www.pfdubois.com/numpy/#Numeric">Numeric</a> and <a href=
"http://stsdas.stsci.edu/numarray/index.html">NumArray</a> modules. With
the exception of the functions documented <a href=
"#array-spec-observers">below</a>, the semantics of the constructors and
member functions defined below can be fully understood by reading the
<a href="ObjectWrapper.html#TypeWrapper-concept">TypeWrapper</a> concept
definition. Since <code>array</code> is publicly derived from
<code><a href="object.html#object-spec">object</a></code>, the public
object interface applies to <code>array</code> instances as well.</p>
<p><a name="default_search"></a>The default behavior is to use
<code>numarray.NDArray</code> as the associated Python type if the
<code>numarray</code> module is installed in the default location.
Otherwise it falls back to use <code>Numeric.ArrayType</code>. If neither
extension module is installed, conversions to arguments of type
<code>numeric::array</code> will cause overload resolution to reject the
overload, and other attempted uses of <code>numeric::array</code> will <a
href="definitions.html#raise">raise</a> an appropriate Python exception.
The associated Python type can be set manually using the <code><a href=
"#array-spec-statics">set_module_and_type</a>(...)</code> static
function.</p>
<p><a name="default_search" id="default_search"></a>The default behavior is
to use <code>numarray.NDArray</code> as the associated Python type if the
<code>numarray</code> module is installed in the default location.
Otherwise it falls back to use <code>Numeric.ArrayType</code>. If neither
extension module is installed, overloads of wrapped C++ functions with
<code>numeric::array</code> parameters will never be matched, and other
attempted uses of <code>numeric::array</code> will <a href=
"definitions.html#raise">raise</a> an appropriate Python exception. The
associated Python type can be set manually using the <code><a href=
"#array-spec-statics">set_module_and_type</a>(...)</code> static
function.</p>
<h4><a name="array-spec-synopsis"></a>Class <code>array</code>
synopsis</h4>
<pre>
<h4><a name="array-spec-synopsis" id="array-spec-synopsis"></a>Class
<code>array</code> synopsis</h4>
<pre>
namespace boost { namespace python { namespace numeric
{
class array : public object
@@ -110,7 +110,7 @@ namespace boost { namespace python { namespace numeric
object astype(Type const&amp; type_);
template &lt;class Type&gt;
object new_(Type const&amp; type_) const;
array new_(Type const&amp; type_) const;
template &lt;class Sequence&gt;
void resize(Sequence const&amp; x);
@@ -136,14 +136,14 @@ namespace boost { namespace python { namespace numeric
void tofile(File const&amp; f) const;
object factory();
template &lt;class Buffer&gt;
object factory(Buffer const&amp;);
template &lt;class Buffer, class Type&gt;
object factory(Buffer const&amp;, Type const&amp;);
template &lt;class Buffer, class Type, class Shape&gt;
object factory(Buffer const&amp;, Type const&amp;, Shape const&amp;, bool copy = true, bool savespace = false);
template &lt;class Buffer, class Type, class Shape&gt;
object factory(Buffer const&amp;, Type const&amp;, Shape const&amp;, bool copy, bool savespace, char typecode);
template &lt;class Sequence&gt;
object factory(Sequence const&amp;);
template &lt;class Sequence, class Typecode&gt;
object factory(Sequence const&amp;, Typecode const&amp;, bool copy = true, bool savespace = false);
template &lt;class Sequence, class Typecode, class Type&gt;
object factory(Sequence const&amp;, Typecode const&amp;, bool copy, bool savespace, Type const&amp;);
template &lt;class Sequence, class Typecode, class Type, class Shape&gt;
object factory(Sequence const&amp;, Typecode const&amp;, bool copy, bool savespace, Type const&amp;, Shape const&amp;);
template &lt;class T1&gt;
explicit array(T1 const&amp; x1);
@@ -155,6 +155,7 @@ namespace boost { namespace python { namespace numeric
static void set_module_and_type();
static void set_module_and_type(char const* package_path = 0, char const* type_name = 0);
static void get_module_name();
object argmax(long axis=-1);
@@ -203,54 +204,60 @@ namespace boost { namespace python { namespace numeric
}}}
</pre>
<h4><a name="array-spec-observers"></a>Class <code>array</code> observer
functions</h4>
<pre>
<h4><a name="array-spec-observers" id="array-spec-observers"></a>Class
<code>array</code> observer functions</h4>
<pre>
object factory();
template &lt;class Buffer&gt;
object factory(Buffer const&amp;);
template &lt;class Buffer, class Type&gt;
object factory(Buffer const&amp;, Type const&amp;);
template &lt;class Buffer, class Type, class Shape&gt;
object factory(Buffer const&amp;, Type const&amp;, Shape const&amp;, bool copy = true, bool savespace = false);
template &lt;class Buffer, class Type, class Shape&gt;
object factory(Buffer const&amp;, Type const&amp;, Shape const&amp;, bool copy, bool savespace, char typecode);
</pre>
These functions map to the underlying array type's <code>array()</code>
function family. They are not called "<code>array</code>" because of the
C++ limitation that you can't define a member function with the same name
as its enclosing class.
<pre>
template &lt;class Sequence&gt;
object factory(Sequence const&amp;);
template &lt;class Sequence, class Typecode&gt;
object factory(Sequence const&amp;, Typecode const&amp;, bool copy = true, bool savespace = false);
template &lt;class Sequence, class Typecode, class Type&gt;
object factory(Sequence const&amp;, Typecode const&amp;, bool copy, bool savespace, Type const&amp;);
template &lt;class Sequence, class Typecode, class Type, class Shape&gt;
object factory(Sequence const&amp;, Typecode const&amp;, bool copy, bool savespace, Type const&amp;, Shape const&amp;);
</pre>These functions map to the underlying array type's <code>array()</code>
function family. They are not called "<code>array</code>" because of the C++
limitation that you can't define a member function with the same name as its
enclosing class.
<pre>
template &lt;class Type&gt;
object new_(Type const&amp;) const;
</pre>
This function maps to the underlying array type's <code>new()</code>
function. It is not called "<code>new</code>" because that is a keyword
in C++.
array new_(Type const&amp;) const;
</pre>This function maps to the underlying array type's <code>new()</code>
function. It is not called "<code>new</code>" because that is a keyword in
C++.
<h4><a name="array-spec-statics"></a>Class <code>array</code> static
functions</h4>
<pre>
<h4><a name="array-spec-statics" id="array-spec-statics"></a>Class
<code>array</code> static functions</h4>
<pre>
static void set_module_and_type(char const* package_path, char const* type_name);
static void set_module_and_type();
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> <code>package_path</code> and
<code>type_name</code>, if supplied, is an <a href=
"definitions.html#ntbs">ntbs</a>.</dt>
<dl class="function-semantics">
<dt><b>Requires:</b> <code>package_path</code> and
<code>type_name</code>, if supplied, is an <a href=
"definitions.html#ntbs">ntbs</a>.</dt>
<dt><b>Effects:</b> The first form sets the package path of the module
which supplies the type named by <code>type_name</code> to
<code>package_path</code>. The second form restores the <a href=
"#default_search">default search behavior</a>. The associated Python
type will be searched for only the first time it is needed, and
thereafter the first time it is needed after an invocation of
<code>set_module_and_type</code>.</dt>
</dl>
<dt><b>Effects:</b> The first form sets the package path of the module
that supplies the type named by <code>type_name</code> to
<code>package_path</code>. The second form restores the <a href=
"#default_search">default search behavior</a>. The associated Python type
will be searched for only the first time it is needed, and thereafter the
first time it is needed after an invocation of
<code>set_module_and_type</code>.</dt>
</dl>
<pre>
static std::string get_module_name()
</pre>
<h2><a name="examples"></a>Example</h2>
<pre>
<dl class="function-semantics">
<dt><b>Effects:</b> Returns the name of the module containing the class
that will be held by new <code>numeric::array</code> instances.</dt>
</dl>
<h2><a name="examples" id="examples"></a>Example</h2>
<pre>
#include &lt;boost/python/numeric.hpp&gt;
#include &lt;boost/python/tuple.hpp&gt;
@@ -261,10 +268,9 @@ void set_first_element(numeric::array&amp; y, double value)
}
</pre>
<p>Revised 03 October, 2002</p>
<p>Revised 07 October, 2006</p>
<p><i>&copy; Copyright <a href=
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
</body>
<p><i>&copy; Copyright <a href="../../../../people/dave_abrahams.htm">Dave
Abrahams</a> 2002-2006.</i></p>
</body>
</html>

View File

@@ -17,6 +17,8 @@
namespace boost { namespace python { namespace numeric {
struct array;
namespace aux
{
struct BOOST_PYTHON_DECL array_base : object
@@ -36,18 +38,19 @@ namespace aux
void info() const;
bool is_c_array() const;
bool isbyteswapped() const;
object new_(object type) const;
array new_(object type) const;
void sort();
object trace(long offset = 0, long axis1 = 0, long axis2 = 1) const;
object type() const;
char typecode() const;
object factory(object const& buffer=object()
, object const& type=object()
, object const& shape=object()
, bool copy = true
, bool savespace = false
, object typecode = object());
object factory(
object const& sequence = object()
, object const& typecode = object()
, bool copy = true
, bool savespace = false
, object type = object()
, object shape = object());
object getflat() const;
long getrank() const;
@@ -106,7 +109,7 @@ class array : public aux::array_base
}
template <class Type>
object new_(Type const& type_) const
array new_(Type const& type_) const
{
return base::new_(object(type_));
}
@@ -162,43 +165,48 @@ class array : public aux::array_base
return base::factory();
}
template <class Buffer>
object factory(Buffer const& buffer)
template <class Sequence>
object factory(Sequence const& sequence)
{
return base::factory(object(buffer));
return base::factory(object(sequence));
}
template <class Buffer, class Type>
template <class Sequence, class Typecode>
object factory(
Buffer const& buffer
, Type const& type_)
Sequence const& sequence
, Typecode const& typecode_
, bool copy = true
, bool savespace = false
)
{
return base::factory(object(buffer), object(type_));
return base::factory(object(sequence), object(typecode_), copy, savespace);
}
template <class Buffer, class Type, class Shape>
template <class Sequence, class Typecode, class Type>
object factory(
Buffer const& buffer
, Type const& type_
, Shape const& shape
, bool copy = true
, bool savespace = false)
Sequence const& sequence
, Typecode const& typecode_
, bool copy
, bool savespace
, Type const& type
)
{
return base::factory(object(buffer), object(type_), object(shape), copy, savespace);
return base::factory(object(sequence), object(typecode_), copy, savespace, object(type));
}
template <class Buffer, class Type, class Shape>
template <class Sequence, class Typecode, class Type, class Shape>
object factory(
Buffer const& buffer
, Type const& type_
, Shape const& shape
, bool copy
, bool savespace
, char typecode)
Sequence const& sequence
, Typecode const& typecode_
, bool copy
, bool savespace
, Type const& type
, Shape const& shape
)
{
return base::factory(object(buffer), object(type_), object(shape), copy, savespace, object(typecode));
return base::factory(object(sequence), object(typecode_), copy, savespace, object(type), object(shape));
}
# define BOOST_PYTHON_ENUM_AS_OBJECT(z, n, x) object(BOOST_PP_CAT(x,n))
# define BOOST_PP_LOCAL_MACRO(n) \
template <BOOST_PP_ENUM_PARAMS_Z(1, n, class T)> \
@@ -210,6 +218,7 @@ class array : public aux::array_base
# undef BOOST_PYTHON_AS_OBJECT
static BOOST_PYTHON_DECL void set_module_and_type(char const* package_name = 0, char const* type_attribute_name = 0);
static BOOST_PYTHON_DECL std::string get_module_name();
public: // implementation detail -- for internal use only
BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(array, base);

View File

@@ -90,7 +90,12 @@ void array::set_module_and_type(char const* package_name, char const* type_attri
module_name = package_name ? package_name : "" ;
type_name = type_attribute_name ? type_attribute_name : "" ;
}
std::string array::get_module_name()
{
load(false);
return module_name;
}
namespace aux
{
@@ -173,9 +178,9 @@ namespace aux
return extract<bool>(attr("isbyteswapped")());
}
object array_base::new_(object type) const
array array_base::new_(object type) const
{
return attr("new")(type);
return extract<array>(attr("new")(type))();
}
void array_base::sort()
@@ -197,15 +202,17 @@ namespace aux
{
return extract<char>(attr("typecode")());
}
object array_base::factory(object const& buffer
, object const& type
, object const& shape
object array_base::factory(
object const& sequence
, object const& typecode
, bool copy
, bool savespace
, object typecode)
, object type
, object shape
)
{
return attr("factory")(buffer, type, shape, copy, savespace, typecode);
return attr("factory")(sequence, typecode, copy, savespace, type, shape);
}
object array_base::getflat() const

View File

@@ -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);
}

View File

@@ -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