mirror of
https://github.com/boostorg/python.git
synced 2026-01-24 06:02:14 +00:00
This commit was manufactured by cvs2svn to create branch 'RC_1_29_0'.
[SVN r15564]
This commit is contained in:
41
include/boost/python/args_fwd.hpp
Normal file
41
include/boost/python/args_fwd.hpp
Normal file
@@ -0,0 +1,41 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef ARGS_FWD_DWA2002927_HPP
|
||||
# define ARGS_FWD_DWA2002927_HPP
|
||||
|
||||
# include <boost/config.hpp>
|
||||
# include <cstddef>
|
||||
# include <utility>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct keyword;
|
||||
template <std::size_t nkeywords = 0> struct keywords;
|
||||
|
||||
typedef std::pair<keyword const*, keyword const*> keyword_range;
|
||||
|
||||
template <>
|
||||
struct keywords<0>
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(std::size_t, size = 0);
|
||||
static keyword_range range() { return keyword_range(); }
|
||||
};
|
||||
|
||||
namespace error
|
||||
{
|
||||
template <int keywords, int function_args>
|
||||
struct more_keywords_than_function_arguments
|
||||
{
|
||||
typedef char too_many_keywords[keywords > function_args ? -1 : 1];
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // ARGS_FWD_DWA2002927_HPP
|
||||
45
include/boost/python/detail/make_keyword_range_fn.hpp
Normal file
45
include/boost/python/detail/make_keyword_range_fn.hpp
Normal file
@@ -0,0 +1,45 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef MAKE_KEYWORD_RANGE_FN_DWA2002927_HPP
|
||||
# define MAKE_KEYWORD_RANGE_FN_DWA2002927_HPP
|
||||
|
||||
# include <boost/python/args_fwd.hpp>
|
||||
# include <boost/python/detail/caller.hpp>
|
||||
# include <boost/python/object/function_object.hpp>
|
||||
# include <boost/python/object/make_holder.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
template <class F, class Policies>
|
||||
object make_keyword_range_function(F f, Policies const& policies, keyword_range const& kw)
|
||||
{
|
||||
enum { n_arguments = detail::arg_tuple_size<F>::value };
|
||||
return objects::function_object(
|
||||
::boost::bind<PyObject*>(detail::caller(), f, _1, _2, policies)
|
||||
, n_arguments
|
||||
, kw);
|
||||
}
|
||||
|
||||
template <class ArgList, class HolderGenerator, class Policies>
|
||||
object make_keyword_range_constructor(
|
||||
Policies const& policies
|
||||
, detail::keyword_range const& kw
|
||||
, HolderGenerator* = 0
|
||||
, ArgList* = 0)
|
||||
{
|
||||
enum { nargs = mpl::size<ArgList>::value };
|
||||
|
||||
return objects::function_object(
|
||||
::boost::bind<PyObject*>(detail::caller(),
|
||||
objects::make_holder<nargs>
|
||||
::template apply<HolderGenerator,ArgList>::execute
|
||||
, _1, _2, policies)
|
||||
, nargs + 1, kw);
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif // MAKE_KEYWORD_RANGE_FN_DWA2002927_HPP
|
||||
15
include/boost/python/detail/scope.hpp
Normal file
15
include/boost/python/detail/scope.hpp
Normal file
@@ -0,0 +1,15 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef SCOPE_DWA2002927_HPP
|
||||
# define SCOPE_DWA2002927_HPP
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
void BOOST_PYTHON_DECL scope_setattr_doc(char const* name, object const& obj, char const* doc);
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif // SCOPE_DWA2002927_HPP
|
||||
231
include/boost/python/numeric.hpp
Normal file
231
include/boost/python/numeric.hpp
Normal file
@@ -0,0 +1,231 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef NUMARRAY_DWA2002922_HPP
|
||||
# define NUMARRAY_DWA2002922_HPP
|
||||
|
||||
# include <boost/python/tuple.hpp>
|
||||
# include <boost/python/str.hpp>
|
||||
# include <boost/preprocessor/iteration/local.hpp>
|
||||
# include <boost/preprocessor/cat.hpp>
|
||||
# include <boost/preprocessor/repetition/enum.hpp>
|
||||
# include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
# include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace numeric {
|
||||
|
||||
namespace aux
|
||||
{
|
||||
struct BOOST_PYTHON_DECL array_base : object
|
||||
{
|
||||
# define BOOST_PP_LOCAL_MACRO(n) \
|
||||
array_base(BOOST_PP_ENUM_PARAMS_Z(1, n, object const& x));
|
||||
# define BOOST_PP_LOCAL_LIMITS (1, 7)
|
||||
# include BOOST_PP_LOCAL_ITERATE()
|
||||
|
||||
object argmax(long axis=-1);
|
||||
object argmin(long axis=-1);
|
||||
object argsort(long axis=-1);
|
||||
object astype(object const& type = object());
|
||||
void byteswap();
|
||||
object copy() const;
|
||||
object diagonal(long offset = 0, long axis1 = 0, long axis2 = 1) const;
|
||||
void info() const;
|
||||
bool is_c_array() const;
|
||||
bool isbyteswapped() const;
|
||||
object 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 getflat() const;
|
||||
long getrank() const;
|
||||
object getshape() const;
|
||||
bool isaligned() const;
|
||||
bool iscontiguous() const;
|
||||
long itemsize() const;
|
||||
long nelements() const;
|
||||
object nonzero() const;
|
||||
|
||||
void put(object const& indices, object const& values);
|
||||
|
||||
void ravel();
|
||||
|
||||
object repeat(object const& repeats, long axis=0);
|
||||
|
||||
void resize(object const& shape);
|
||||
|
||||
void setflat(object const& flat);
|
||||
void setshape(object const& shape);
|
||||
|
||||
void swapaxes(long axis1, long axis2);
|
||||
|
||||
object take(object const& sequence, long axis = 0) const;
|
||||
|
||||
void tofile(object const& file) const;
|
||||
|
||||
str tostring() const;
|
||||
|
||||
void transpose(object const& axes = object());
|
||||
|
||||
object view() const;
|
||||
|
||||
public: // implementation detail - do not touch.
|
||||
BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(array_base, object);
|
||||
};
|
||||
|
||||
struct BOOST_PYTHON_DECL array_object_manager_traits
|
||||
{
|
||||
static bool check(PyObject* obj);
|
||||
static detail::new_non_null_reference adopt(PyObject* obj);
|
||||
};
|
||||
} // namespace aux
|
||||
|
||||
class array : public aux::array_base
|
||||
{
|
||||
typedef aux::array_base base;
|
||||
public:
|
||||
|
||||
object astype() { return base::astype(); }
|
||||
|
||||
template <class Type>
|
||||
object astype(Type const& type_)
|
||||
{
|
||||
return base::astype(object(type_));
|
||||
}
|
||||
|
||||
template <class Type>
|
||||
object new_(Type const& type_) const
|
||||
{
|
||||
return base::new_(object(type_));
|
||||
}
|
||||
|
||||
template <class Sequence>
|
||||
void resize(Sequence const& x)
|
||||
{
|
||||
base::resize(object(x));
|
||||
}
|
||||
|
||||
# define BOOST_PP_LOCAL_MACRO(n) \
|
||||
void resize(BOOST_PP_ENUM_PARAMS_Z(1, n, long x)) \
|
||||
{ \
|
||||
resize(make_tuple(BOOST_PP_ENUM_PARAMS_Z(1, n, x))); \
|
||||
}
|
||||
# define BOOST_PP_LOCAL_LIMITS (1, BOOST_PYTHON_MAX_ARITY)
|
||||
# include BOOST_PP_LOCAL_ITERATE()
|
||||
|
||||
template <class Sequence>
|
||||
void setshape(Sequence const& x)
|
||||
{
|
||||
base::setshape(object(x));
|
||||
}
|
||||
|
||||
# define BOOST_PP_LOCAL_MACRO(n) \
|
||||
void setshape(BOOST_PP_ENUM_PARAMS_Z(1, n, long x)) \
|
||||
{ \
|
||||
setshape(make_tuple(BOOST_PP_ENUM_PARAMS_Z(1, n, x))); \
|
||||
}
|
||||
# define BOOST_PP_LOCAL_LIMITS (1, BOOST_PYTHON_MAX_ARITY)
|
||||
# include BOOST_PP_LOCAL_ITERATE()
|
||||
|
||||
template <class Indices, class Values>
|
||||
void put(Indices const& indices, Values const& values)
|
||||
{
|
||||
base::put(object(indices), object(values));
|
||||
}
|
||||
|
||||
template <class Sequence>
|
||||
object take(Sequence const& sequence, long axis = 0)
|
||||
{
|
||||
return base::take(object(sequence), axis);
|
||||
}
|
||||
|
||||
template <class File>
|
||||
void tofile(File const& f) const
|
||||
{
|
||||
base::tofile(object(f));
|
||||
}
|
||||
|
||||
object factory()
|
||||
{
|
||||
return base::factory();
|
||||
}
|
||||
|
||||
template <class Buffer>
|
||||
object factory(Buffer const& buffer)
|
||||
{
|
||||
return base::factory(object(buffer));
|
||||
}
|
||||
|
||||
template <class Buffer, class Type>
|
||||
object factory(
|
||||
Buffer const& buffer
|
||||
, Type const& type_)
|
||||
{
|
||||
return base::factory(object(buffer), object(type_));
|
||||
}
|
||||
|
||||
template <class Buffer, class Type, class Shape>
|
||||
object factory(
|
||||
Buffer const& buffer
|
||||
, Type const& type_
|
||||
, Shape const& shape
|
||||
, bool copy = true
|
||||
, bool savespace = false)
|
||||
{
|
||||
return base::factory(object(buffer), object(type_), object(shape), copy, savespace);
|
||||
}
|
||||
|
||||
template <class Buffer, class Type, class Shape>
|
||||
object factory(
|
||||
Buffer const& buffer
|
||||
, Type const& type_
|
||||
, Shape const& shape
|
||||
, bool copy
|
||||
, bool savespace
|
||||
, char typecode)
|
||||
{
|
||||
return base::factory(object(buffer), object(type_), object(shape), copy, savespace, object(typecode));
|
||||
}
|
||||
|
||||
# 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)> \
|
||||
explicit array(BOOST_PP_ENUM_BINARY_PARAMS_Z(1, n, T, const& x)) \
|
||||
: base(BOOST_PP_ENUM_1(n, BOOST_PYTHON_ENUM_AS_OBJECT, x)) \
|
||||
{}
|
||||
# define BOOST_PP_LOCAL_LIMITS (1, 7)
|
||||
# include BOOST_PP_LOCAL_ITERATE()
|
||||
# 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);
|
||||
|
||||
public: // implementation detail -- for internal use only
|
||||
BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(array, base);
|
||||
};
|
||||
|
||||
} // namespace boost::python::numeric
|
||||
|
||||
namespace converter
|
||||
{
|
||||
template <>
|
||||
struct object_manager_traits< numeric::array >
|
||||
: numeric::aux::array_object_manager_traits
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(bool, is_specialized = true);
|
||||
};
|
||||
}
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // NUMARRAY_DWA2002922_HPP
|
||||
313
src/numeric.cpp
Normal file
313
src/numeric.cpp
Normal file
@@ -0,0 +1,313 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
#include <boost/python/numeric.hpp>
|
||||
#include <boost/python/handle.hpp>
|
||||
#include <boost/python/cast.hpp>
|
||||
#include <boost/python/tuple.hpp>
|
||||
#include <boost/python/detail/raw_pyobject.hpp>
|
||||
#include <boost/python/extract.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace numeric {
|
||||
|
||||
namespace
|
||||
{
|
||||
enum state_t { failed = -1, unknown, succeeded };
|
||||
state_t state = unknown;
|
||||
std::string module_name;
|
||||
std::string type_name;
|
||||
|
||||
handle<> array_module;
|
||||
handle<> array_type;
|
||||
handle<> array_function;
|
||||
|
||||
void throw_load_failure()
|
||||
{
|
||||
PyErr_Format(
|
||||
PyExc_ImportError
|
||||
, "No module named '%s' or its type '%s' did not follow the NumPy protocol"
|
||||
, module_name.c_str(), type_name.c_str());
|
||||
throw_error_already_set();
|
||||
|
||||
}
|
||||
|
||||
bool load(bool throw_on_error)
|
||||
{
|
||||
if (!state)
|
||||
{
|
||||
if (module_name.size() == 0)
|
||||
{
|
||||
module_name = "numarray";
|
||||
type_name = "NDArray";
|
||||
if (load(false))
|
||||
return true;
|
||||
module_name = "Numeric";
|
||||
type_name = "ArrayType";
|
||||
}
|
||||
|
||||
state = failed;
|
||||
PyObject* module = ::PyImport_Import(object(module_name).ptr());
|
||||
if (module)
|
||||
{
|
||||
PyObject* type = ::PyObject_GetAttrString(module, const_cast<char*>(type_name.c_str()));
|
||||
|
||||
if (type && PyType_Check(type))
|
||||
{
|
||||
array_type = handle<>(type);
|
||||
PyObject* function = ::PyObject_GetAttrString(module, const_cast<char*>("array"));
|
||||
|
||||
if (function && PyCallable_Check(function))
|
||||
{
|
||||
array_function = handle<>(function);
|
||||
state = succeeded;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (state == succeeded)
|
||||
return true;
|
||||
|
||||
if (throw_on_error)
|
||||
throw_load_failure();
|
||||
|
||||
PyErr_Clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
object demand_array_function()
|
||||
{
|
||||
load(true);
|
||||
return object(array_function);
|
||||
}
|
||||
}
|
||||
|
||||
void array::set_module_and_type(char const* package_name, char const* type_attribute_name)
|
||||
{
|
||||
state = unknown;
|
||||
module_name = package_name ? package_name : "" ;
|
||||
type_name = type_attribute_name ? type_attribute_name : "" ;
|
||||
}
|
||||
|
||||
|
||||
namespace aux
|
||||
{
|
||||
bool array_object_manager_traits::check(PyObject* obj)
|
||||
{
|
||||
if (!load(false))
|
||||
return false;
|
||||
return ::PyObject_IsInstance(obj, array_type.get());
|
||||
}
|
||||
|
||||
python::detail::new_non_null_reference
|
||||
array_object_manager_traits::adopt(PyObject* obj)
|
||||
{
|
||||
load(true);
|
||||
return detail::new_non_null_reference(
|
||||
pytype_check(downcast<PyTypeObject>(array_type.get()), obj));
|
||||
}
|
||||
|
||||
|
||||
# define BOOST_PYTHON_AS_OBJECT(z, n, _) object(x##n)
|
||||
# define BOOST_PP_LOCAL_MACRO(n) \
|
||||
array_base::array_base(BOOST_PP_ENUM_PARAMS(n, object const& x)) \
|
||||
: object(demand_array_function()(BOOST_PP_ENUM_PARAMS(n, x))) \
|
||||
{}
|
||||
# define BOOST_PP_LOCAL_LIMITS (1, 6)
|
||||
# include BOOST_PP_LOCAL_ITERATE()
|
||||
# undef BOOST_PYTHON_AS_OBJECT
|
||||
|
||||
array_base::array_base(BOOST_PP_ENUM_PARAMS(7, object const& x))
|
||||
: object(demand_array_function()(BOOST_PP_ENUM_PARAMS(7, x)))
|
||||
{}
|
||||
|
||||
object array_base::argmax(long axis)
|
||||
{
|
||||
return attr("argmax")(axis);
|
||||
}
|
||||
|
||||
object array_base::argmin(long axis)
|
||||
{
|
||||
return attr("argmin")(axis);
|
||||
}
|
||||
|
||||
object array_base::argsort(long axis)
|
||||
{
|
||||
return attr("argsort")(axis);
|
||||
}
|
||||
|
||||
object array_base::astype(object const& type)
|
||||
{
|
||||
return attr("astype")(type);
|
||||
}
|
||||
|
||||
void array_base::byteswap()
|
||||
{
|
||||
attr("byteswap")();
|
||||
}
|
||||
|
||||
object array_base::copy() const
|
||||
{
|
||||
return attr("copy")();
|
||||
}
|
||||
|
||||
object array_base::diagonal(long offset, long axis1, long axis2) const
|
||||
{
|
||||
return attr("diagonal")(offset, axis1, axis2);
|
||||
}
|
||||
|
||||
void array_base::info() const
|
||||
{
|
||||
attr("info")();
|
||||
}
|
||||
|
||||
bool array_base::is_c_array() const
|
||||
{
|
||||
return extract<bool>(attr("is_c_array")());
|
||||
}
|
||||
|
||||
bool array_base::isbyteswapped() const
|
||||
{
|
||||
return extract<bool>(attr("isbyteswapped")());
|
||||
}
|
||||
|
||||
object array_base::new_(object type) const
|
||||
{
|
||||
return attr("new")(type);
|
||||
}
|
||||
|
||||
void array_base::sort()
|
||||
{
|
||||
attr("sort")();
|
||||
}
|
||||
|
||||
object array_base::trace(long offset, long axis1, long axis2) const
|
||||
{
|
||||
return attr("trace")(offset, axis1, axis2);
|
||||
}
|
||||
|
||||
object array_base::type() const
|
||||
{
|
||||
return attr("type")();
|
||||
}
|
||||
|
||||
char array_base::typecode() const
|
||||
{
|
||||
return extract<char>(attr("typecode")());
|
||||
}
|
||||
|
||||
object array_base::factory(object const& buffer
|
||||
, object const& type
|
||||
, object const& shape
|
||||
, bool copy
|
||||
, bool savespace
|
||||
, object typecode)
|
||||
{
|
||||
return attr("array")(buffer, type, shape, copy, savespace, typecode);
|
||||
}
|
||||
|
||||
object array_base::getflat() const
|
||||
{
|
||||
return attr("getflat")();
|
||||
}
|
||||
|
||||
long array_base::getrank() const
|
||||
{
|
||||
return extract<long>(attr("getrank")());
|
||||
}
|
||||
|
||||
object array_base::getshape() const
|
||||
{
|
||||
return attr("getshape")();
|
||||
}
|
||||
|
||||
bool array_base::isaligned() const
|
||||
{
|
||||
return extract<bool>(attr("isaligned"));
|
||||
}
|
||||
|
||||
bool array_base::iscontiguous() const
|
||||
{
|
||||
return extract<bool>(attr("isaligned"));
|
||||
}
|
||||
|
||||
long array_base::itemsize() const
|
||||
{
|
||||
return extract<long>(attr("itemsize"));
|
||||
}
|
||||
|
||||
long array_base::nelements() const
|
||||
{
|
||||
return extract<long>(attr("nelements"));
|
||||
}
|
||||
|
||||
object array_base::nonzero() const
|
||||
{
|
||||
return attr("nonzero")();
|
||||
}
|
||||
|
||||
void array_base::put(object const& indices, object const& values)
|
||||
{
|
||||
attr("put")(indices, values);
|
||||
}
|
||||
|
||||
void array_base::ravel()
|
||||
{
|
||||
attr("ravel")();
|
||||
}
|
||||
|
||||
object array_base::repeat(object const& repeats, long axis)
|
||||
{
|
||||
return attr("repeat")(repeats, axis);
|
||||
}
|
||||
|
||||
void array_base::resize(object const& shape)
|
||||
{
|
||||
attr("resize")(shape);
|
||||
}
|
||||
|
||||
void array_base::setflat(object const& flat)
|
||||
{
|
||||
attr("setflat")(flat);
|
||||
}
|
||||
|
||||
void array_base::setshape(object const& shape)
|
||||
{
|
||||
attr("setshape")(shape);
|
||||
}
|
||||
|
||||
void array_base::swapaxes(long axis1, long axis2)
|
||||
{
|
||||
attr("swapaxes")(axis1, axis2);
|
||||
}
|
||||
|
||||
object array_base::take(object const& sequence, long axis) const
|
||||
{
|
||||
return attr("take")(sequence, axis);
|
||||
}
|
||||
|
||||
void array_base::tofile(object const& file) const
|
||||
{
|
||||
attr("tofile")(file);
|
||||
}
|
||||
|
||||
str array_base::tostring() const
|
||||
{
|
||||
return str(attr("tostring")());
|
||||
}
|
||||
|
||||
void array_base::transpose(object const& axes)
|
||||
{
|
||||
attr("transpose")(axes);
|
||||
}
|
||||
|
||||
object array_base::view() const
|
||||
{
|
||||
return attr("view")();
|
||||
}
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::numeric
|
||||
81
test/args.cpp
Normal file
81
test/args.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#include <boost/python/module_init.hpp>
|
||||
#include <boost/python/def.hpp>
|
||||
#include <boost/python/args.hpp>
|
||||
#include <boost/python/tuple.hpp>
|
||||
#include <boost/python/class.hpp>
|
||||
#include <boost/python/return_internal_reference.hpp>
|
||||
#include "test_class.hpp"
|
||||
|
||||
using namespace boost::python;
|
||||
|
||||
tuple f(int x = 1, double y = 4.25, char const* z = "wow")
|
||||
{
|
||||
return make_tuple(x, y, z);
|
||||
}
|
||||
|
||||
BOOST_PYTHON_FUNCTION_OVERLOADS(f_overloads, f, 0, 3)
|
||||
|
||||
typedef test_class<> Y;
|
||||
|
||||
struct X
|
||||
{
|
||||
X(int a0 = 0, int a1 = 1) : inner0(a0), inner1(a1) {}
|
||||
tuple f(int x = 1, double y = 4.25, char const* z = "wow")
|
||||
{
|
||||
return make_tuple(x, y, z);
|
||||
}
|
||||
|
||||
Y const& inner(bool n) const { return n ? inner1 : inner0; }
|
||||
|
||||
Y inner0;
|
||||
Y inner1;
|
||||
};
|
||||
|
||||
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(X_f_overloads, X::f, 0, 3)
|
||||
|
||||
BOOST_PYTHON_MODULE_INIT(args_ext)
|
||||
{
|
||||
def("f", f, args("x", "y", "z")
|
||||
, "This is f's docstring"
|
||||
);
|
||||
|
||||
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1200
|
||||
// MSVC6 gives a fatal error LNK1179: invalid or corrupt file:
|
||||
// duplicate comdat error if we try to re-use the exact type of f
|
||||
// here, so substitute long for int.
|
||||
tuple (*f)(long,double,char const*) = 0;
|
||||
#endif
|
||||
def("f1", f, f_overloads("f1's docstring", args("x", "y", "z")));
|
||||
def("f2", f, f_overloads(args("x", "y", "z")));
|
||||
def("f3", f, f_overloads(args("x", "y", "z"), "f3's docstring"));
|
||||
|
||||
class_<Y>("Y", init<int>(args("value"), "Y's docstring"))
|
||||
.def("value", &Y::value)
|
||||
;
|
||||
|
||||
class_<X>("X", "This is X's docstring")
|
||||
.def(init<int, optional<int> >(args("a0", "a1")))
|
||||
.def("f", &X::f
|
||||
, "This is X.f's docstring"
|
||||
, args("x", "y", "z"))
|
||||
|
||||
// Just to prove that all the different argument combinations work
|
||||
.def("inner0", &X::inner, return_internal_reference<>(), args("n"), "docstring")
|
||||
.def("inner1", &X::inner, return_internal_reference<>(), "docstring", args("n"))
|
||||
|
||||
.def("inner2", &X::inner, args("n"), return_internal_reference<>(), "docstring")
|
||||
.def("inner3", &X::inner, "docstring", return_internal_reference<>(), args("n"))
|
||||
|
||||
.def("inner4", &X::inner, args("n"), "docstring", return_internal_reference<>())
|
||||
.def("inner5", &X::inner, "docstring", args("n"), return_internal_reference<>())
|
||||
|
||||
.def("f1", &X::f, X_f_overloads(args("x", "y", "z")))
|
||||
;
|
||||
|
||||
def("inner", &X::inner, "docstring", args("self", "n"), return_internal_reference<>());
|
||||
}
|
||||
161
test/args.py
Normal file
161
test/args.py
Normal file
@@ -0,0 +1,161 @@
|
||||
"""
|
||||
>>> from args_ext import *
|
||||
|
||||
>>> f(x= 1, y = 3, z = 'hello')
|
||||
(1, 3.0, 'hello')
|
||||
|
||||
>>> f(z = 'hello', x = 3, y = 2.5)
|
||||
(3, 2.5, 'hello')
|
||||
|
||||
>>> f(1, z = 'hi', y = 3)
|
||||
(1, 3.0, 'hi')
|
||||
|
||||
>>> try: f(1, 2, 'hello', bar = 'baz')
|
||||
... except TypeError: pass
|
||||
... else: print 'expected an exception: unknown keyword'
|
||||
|
||||
|
||||
Exercise the functions using default stubs
|
||||
|
||||
>>> f1(z = 'nix', y = .125, x = 2)
|
||||
(2, 0.125, 'nix')
|
||||
>>> f1(y = .125, x = 2)
|
||||
(2, 0.125, 'wow')
|
||||
>>> f1(x = 2)
|
||||
(2, 4.25, 'wow')
|
||||
>>> f1()
|
||||
(1, 4.25, 'wow')
|
||||
|
||||
>>> f2(z = 'nix', y = .125, x = 2)
|
||||
(2, 0.125, 'nix')
|
||||
>>> f2(y = .125, x = 2)
|
||||
(2, 0.125, 'wow')
|
||||
>>> f2(x = 2)
|
||||
(2, 4.25, 'wow')
|
||||
>>> f2()
|
||||
(1, 4.25, 'wow')
|
||||
|
||||
>>> f3(z = 'nix', y = .125, x = 2)
|
||||
(2, 0.125, 'nix')
|
||||
>>> f3(y = .125, x = 2)
|
||||
(2, 0.125, 'wow')
|
||||
>>> f3(x = 2)
|
||||
(2, 4.25, 'wow')
|
||||
>>> f3()
|
||||
(1, 4.25, 'wow')
|
||||
|
||||
Member function tests
|
||||
|
||||
>>> q = X()
|
||||
>>> q.f(x= 1, y = 3, z = 'hello')
|
||||
(1, 3.0, 'hello')
|
||||
|
||||
>>> q.f(z = 'hello', x = 3, y = 2.5)
|
||||
(3, 2.5, 'hello')
|
||||
|
||||
>>> q.f(1, z = 'hi', y = 3)
|
||||
(1, 3.0, 'hi')
|
||||
|
||||
>>> try: q.f(1, 2, 'hello', bar = 'baz')
|
||||
... except TypeError: pass
|
||||
... else: print 'expected an exception: unknown keyword'
|
||||
|
||||
Exercise member functions using default stubs
|
||||
|
||||
>>> q.f1(z = 'nix', y = .125, x = 2)
|
||||
(2, 0.125, 'nix')
|
||||
>>> q.f1(y = .125, x = 2)
|
||||
(2, 0.125, 'wow')
|
||||
>>> q.f1(x = 2)
|
||||
(2, 4.25, 'wow')
|
||||
>>> q.f1()
|
||||
(1, 4.25, 'wow')
|
||||
|
||||
>>> X.f.__doc__
|
||||
"This is X.f's docstring"
|
||||
|
||||
>>> xfuncs = (X.inner0, X.inner1, X.inner2, X.inner3, X.inner4, X.inner5)
|
||||
>>> for f in xfuncs:
|
||||
... print f(q,1).value(),
|
||||
... print f(q, n = 1).value(),
|
||||
... print f(q, n = 0).value(),
|
||||
... print f.__doc__
|
||||
1 1 0 docstring
|
||||
1 1 0 docstring
|
||||
1 1 0 docstring
|
||||
1 1 0 docstring
|
||||
1 1 0 docstring
|
||||
1 1 0 docstring
|
||||
|
||||
>>> x = X(a1 = 44, a0 = 22)
|
||||
>>> x.inner0(0).value()
|
||||
22
|
||||
>>> x.inner0(1).value()
|
||||
44
|
||||
|
||||
>>> x = X(a0 = 7)
|
||||
>>> x.inner0(0).value()
|
||||
7
|
||||
>>> x.inner0(1).value()
|
||||
1
|
||||
|
||||
>>> inner(n = 1, self = q).value()
|
||||
1
|
||||
"""
|
||||
def run(args = None):
|
||||
import sys
|
||||
import doctest
|
||||
|
||||
if args is not None:
|
||||
sys.argv = args
|
||||
return doctest.testmod(sys.modules.get(__name__))
|
||||
|
||||
if __name__ == '__main__':
|
||||
print "running..."
|
||||
import sys
|
||||
sys.exit(run()[0])
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
105
test/numpy.cpp
Normal file
105
test/numpy.cpp
Normal file
@@ -0,0 +1,105 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
#include <boost/python/numeric.hpp>
|
||||
#include <boost/python/tuple.hpp>
|
||||
#include <boost/python/module_init.hpp>
|
||||
#include <boost/python/def.hpp>
|
||||
|
||||
using namespace boost::python;
|
||||
|
||||
// See if we can invoke array() from C++
|
||||
object new_array()
|
||||
{
|
||||
return numeric::array(
|
||||
make_tuple(
|
||||
make_tuple(1,2,3)
|
||||
, make_tuple(4,5,6)
|
||||
, make_tuple(7,8,9)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// test argument conversion
|
||||
void take_array(numeric::array x)
|
||||
{
|
||||
}
|
||||
|
||||
// A separate function to invoke the info() member. Must happen
|
||||
// outside any doctests since this prints directly to stdout and the
|
||||
// result text includes the address of the 'self' array.
|
||||
void info(numeric::array const& z)
|
||||
{
|
||||
z.info();
|
||||
}
|
||||
|
||||
// Tests which work on both Numeric and numarray array objects. Of
|
||||
// course all of the operators "just work" since numeric::array
|
||||
// inherits that behavior from object.
|
||||
void exercise(numeric::array& y, object check)
|
||||
{
|
||||
y[make_tuple(2,1)] = 3;
|
||||
check(y);
|
||||
check(y.astype('D'));
|
||||
check(y.copy());
|
||||
check(y.typecode());
|
||||
}
|
||||
|
||||
// numarray-specific tests. check is a callable object which we can
|
||||
// use to record intermediate results, which are later compared with
|
||||
// the results of corresponding python operations.
|
||||
void exercise_numarray(numeric::array& y, object check)
|
||||
{
|
||||
check(y.astype());
|
||||
|
||||
check(y.argmax());
|
||||
check(y.argmax(0));
|
||||
|
||||
check(y.argmin());
|
||||
check(y.argmin(0));
|
||||
|
||||
check(y.argsort());
|
||||
check(y.argsort(1));
|
||||
|
||||
y.byteswap();
|
||||
check(y);
|
||||
|
||||
check(y.diagonal());
|
||||
check(y.diagonal(1));
|
||||
check(y.diagonal(0, 1));
|
||||
check(y.diagonal(0, 1, 0));
|
||||
|
||||
check(y.is_c_array());
|
||||
check(y.isbyteswapped());
|
||||
|
||||
check(y.trace());
|
||||
check(y.trace(1));
|
||||
check(y.trace(0, 1));
|
||||
check(y.trace(0, 1, 0));
|
||||
|
||||
check(y.new_('D'));
|
||||
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));
|
||||
}
|
||||
|
||||
BOOST_PYTHON_MODULE_INIT(numpy_ext)
|
||||
{
|
||||
def("new_array", new_array);
|
||||
def("take_array", take_array);
|
||||
def("exercise", exercise);
|
||||
def("exercise_numarray", exercise_numarray);
|
||||
def("set_module_and_type", &numeric::array::set_module_and_type);
|
||||
def("info", info);
|
||||
}
|
||||
|
||||
#include "module_tail.cpp"
|
||||
175
test/numpy.py
Normal file
175
test/numpy.py
Normal file
@@ -0,0 +1,175 @@
|
||||
def numeric_tests():
|
||||
'''
|
||||
>>> from numpy_ext import *
|
||||
>>> x = new_array()
|
||||
>>> x[1,1] = 0.0
|
||||
|
||||
>>> try: take_array(3)
|
||||
... except TypeError: pass
|
||||
... else: print 'expected a TypeError'
|
||||
|
||||
>>> take_array(x)
|
||||
|
||||
>>> print x
|
||||
[[1 2 3]
|
||||
[4 0 6]
|
||||
[7 8 9]]
|
||||
|
||||
>>> y = x.copy()
|
||||
|
||||
|
||||
>>> p = _printer()
|
||||
>>> check = p.check
|
||||
>>> exercise(x, p)
|
||||
>>> y[2,1] = 3
|
||||
>>> check(y);
|
||||
|
||||
>>> check(y.astype('D'));
|
||||
|
||||
>>> check(y.copy());
|
||||
|
||||
>>> check(y.typecode());
|
||||
|
||||
>>> p.results
|
||||
[]
|
||||
>>> del p
|
||||
'''
|
||||
pass
|
||||
|
||||
def _numarray_tests():
|
||||
'''
|
||||
>>> from numpy_ext import *
|
||||
>>> x = new_array()
|
||||
>>> y = x.copy()
|
||||
>>> p = _printer()
|
||||
>>> check = p.check
|
||||
>>> exercise_numarray(x, p)
|
||||
|
||||
>>> check(y.astype());
|
||||
|
||||
>>> check(y.argmax());
|
||||
>>> check(y.argmax(0));
|
||||
|
||||
>>> check(y.argmin());
|
||||
>>> check(y.argmin(0));
|
||||
|
||||
>>> check(y.argsort());
|
||||
>>> check(y.argsort(1));
|
||||
|
||||
>>> y.byteswap();
|
||||
>>> check(y);
|
||||
|
||||
>>> check(y.diagonal());
|
||||
>>> check(y.diagonal(1));
|
||||
>>> check(y.diagonal(0, 1));
|
||||
>>> check(y.diagonal(0, 1, 0));
|
||||
|
||||
>>> check(y.is_c_array());
|
||||
>>> check(y.isbyteswapped());
|
||||
|
||||
>>> check(y.trace());
|
||||
>>> check(y.trace(1));
|
||||
>>> check(y.trace(0, 1));
|
||||
>>> check(y.trace(0, 1, 0));
|
||||
|
||||
>>> check(y.new('D'));
|
||||
>>> y.sort();
|
||||
>>> check(y);
|
||||
>>> check(y.type());
|
||||
|
||||
>>> check(y.array((1.2, 3.4)));
|
||||
>>> check(y.array((1.2, 3.4), "Double"));
|
||||
>>> check(y.array((1.2, 3.4), "Double", (1,2,1)));
|
||||
>>> check(y.array((1.2, 3.4), "Double", (2,1,1), false));
|
||||
>>> check(y.array((1.2, 3.4), "Double", (2,), true, true));
|
||||
|
||||
>>> p.results
|
||||
[]
|
||||
>>> del p
|
||||
'''
|
||||
pass
|
||||
|
||||
false = 0;
|
||||
true = 1;
|
||||
class _printer(object):
|
||||
def __init__(self):
|
||||
self.results = [];
|
||||
def __call__(self, *stuff):
|
||||
self.results += [ str(x) for x in stuff ]
|
||||
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])
|
||||
|
||||
def _run(args = None):
|
||||
import sys
|
||||
import doctest
|
||||
|
||||
if args is not None:
|
||||
sys.argv = args
|
||||
|
||||
# See which of the numeric modules are installed
|
||||
has_numeric = 0
|
||||
try:
|
||||
import Numeric
|
||||
m = Numeric
|
||||
has_numeric = 1
|
||||
except ImportError: pass
|
||||
|
||||
has_numarray = 0
|
||||
try:
|
||||
import numarray
|
||||
m = numarray
|
||||
has_numarray = 1
|
||||
except ImportError: pass
|
||||
|
||||
# Bail if neither one is installed
|
||||
if not (has_numeric or has_numarray):
|
||||
return 0
|
||||
|
||||
# test the info routine outside the doctest. See numpy.cpp for an
|
||||
# explanation
|
||||
import numpy_ext
|
||||
if (has_numarray):
|
||||
numpy_ext.info(m.array((1,2,3)))
|
||||
|
||||
failures = 0
|
||||
|
||||
#
|
||||
# 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]
|
||||
|
||||
# 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]
|
||||
|
||||
global __test__
|
||||
if has_numarray:
|
||||
# Add the _numarray_tests to the list of things to test in
|
||||
# this case.
|
||||
__test__ = { 'numarray_tests':_numarray_tests,
|
||||
'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]
|
||||
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]
|
||||
|
||||
return failures
|
||||
|
||||
if __name__ == '__main__':
|
||||
print "running..."
|
||||
import sys
|
||||
sys.exit(_run())
|
||||
Reference in New Issue
Block a user