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:
@@ -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 - <boost/python/numeric.hpp></title>
|
||||
</head>
|
||||
<title>Boost.Python - <boost/python/numeric.hpp></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 <boost/python/numeric.hpp></h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
<h2 align="center">Header <boost/python/numeric.hpp></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& type_);
|
||||
|
||||
template <class Type>
|
||||
object new_(Type const& type_) const;
|
||||
array new_(Type const& type_) const;
|
||||
|
||||
template <class Sequence>
|
||||
void resize(Sequence const& x);
|
||||
@@ -136,14 +136,14 @@ namespace boost { namespace python { namespace numeric
|
||||
void tofile(File const& f) const;
|
||||
|
||||
object factory();
|
||||
template <class Buffer>
|
||||
object factory(Buffer const&);
|
||||
template <class Buffer, class Type>
|
||||
object factory(Buffer const&, Type const&);
|
||||
template <class Buffer, class Type, class Shape>
|
||||
object factory(Buffer const&, Type const&, Shape const&, bool copy = true, bool savespace = false);
|
||||
template <class Buffer, class Type, class Shape>
|
||||
object factory(Buffer const&, Type const&, Shape const&, bool copy, bool savespace, char typecode);
|
||||
template <class Sequence>
|
||||
object factory(Sequence const&);
|
||||
template <class Sequence, class Typecode>
|
||||
object factory(Sequence const&, Typecode const&, bool copy = true, bool savespace = false);
|
||||
template <class Sequence, class Typecode, class Type>
|
||||
object factory(Sequence const&, Typecode const&, bool copy, bool savespace, Type const&);
|
||||
template <class Sequence, class Typecode, class Type, class Shape>
|
||||
object factory(Sequence const&, Typecode const&, bool copy, bool savespace, Type const&, Shape const&);
|
||||
|
||||
template <class T1>
|
||||
explicit array(T1 const& 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 <class Buffer>
|
||||
object factory(Buffer const&);
|
||||
template <class Buffer, class Type>
|
||||
object factory(Buffer const&, Type const&);
|
||||
template <class Buffer, class Type, class Shape>
|
||||
object factory(Buffer const&, Type const&, Shape const&, bool copy = true, bool savespace = false);
|
||||
template <class Buffer, class Type, class Shape>
|
||||
object factory(Buffer const&, Type const&, Shape const&, 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 <class Sequence>
|
||||
object factory(Sequence const&);
|
||||
template <class Sequence, class Typecode>
|
||||
object factory(Sequence const&, Typecode const&, bool copy = true, bool savespace = false);
|
||||
template <class Sequence, class Typecode, class Type>
|
||||
object factory(Sequence const&, Typecode const&, bool copy, bool savespace, Type const&);
|
||||
template <class Sequence, class Typecode, class Type, class Shape>
|
||||
object factory(Sequence const&, Typecode const&, bool copy, bool savespace, Type const&, Shape const&);
|
||||
</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 <class Type>
|
||||
object new_(Type const&) 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&) 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 <boost/python/numeric.hpp>
|
||||
#include <boost/python/tuple.hpp>
|
||||
|
||||
@@ -261,10 +268,9 @@ void set_first_element(numeric::array& y, double value)
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Revised 03 October, 2002</p>
|
||||
<p>Revised 07 October, 2006</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||
</body>
|
||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002-2006.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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