diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
commit | 19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch) | |
tree | 42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/boost/libs/python/test | |
parent | Initial commit. (diff) | |
download | ceph-6d07fdb6bb33b1af39833b850bb6cf8af79fe293.tar.xz ceph-6d07fdb6bb33b1af39833b850bb6cf8af79fe293.zip |
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/python/test')
184 files changed, 13822 insertions, 0 deletions
diff --git a/src/boost/libs/python/test/Jamfile b/src/boost/libs/python/test/Jamfile new file mode 100644 index 000000000..9a5c75695 --- /dev/null +++ b/src/boost/libs/python/test/Jamfile @@ -0,0 +1,257 @@ +# 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) + +import python ; +import os ; +import ../../config/checks/config : requires ; + +lib socket ; + +use-project /boost/python : ../build ; +project /boost/python/test + : requirements + <toolset>gcc:<cxxflags>-Wextra + <target-os>qnxnto:<library>socket + ; + +local PY = ; +if [ python.configured ] +{ + PY = /python//python ; +} + +rule py-run ( sources * : input-file ? ) +{ + return [ run $(sources) /boost/python//boost_python $(PY) + : # args + : $(input-file) + : #requirements + <define>BOOST_PYTHON_SUPPRESS_REGISTRY_INITIALIZATION + + ] ; +} + +rule py-compile ( sources * ) +{ + return [ compile $(sources) /boost/python//boost_python ] ; +} + +rule py-compile-fail ( sources * ) +{ + return [ compile-fail $(sources) /boost/python//boost_python ] ; +} + +rule require-windows ( properties * ) +{ + if ! <target-os>windows in $(properties) + { + return <build>no ; + } +} + +if [ python.configured ] +{ +test-suite python + : + + [ + run exec.cpp /boost/python//boost_python/<link>static $(PY) + : # program args + : exec.py # input files + : # requirements + : # target-name + ] + + [ + run exec.cpp ../build//boost_python/<link>shared /python//python + : # program args + : exec.py + : # requirements + : exec-dynamic # target-name + ] + +# [ +# run import_.cpp ../build//boost_python /python//python +# : # program args +# : import_.py # input files +# : # requirements +# : # target-name +# ] + +[ +bpl-test crossmod_exception + : crossmod_exception.py crossmod_exception_a.cpp crossmod_exception_b.cpp +] + +[ bpl-test injected ] +[ bpl-test properties ] +[ bpl-test return_arg ] +[ bpl-test staticmethod ] +[ bpl-test boost_shared_ptr ] +[ bpl-test shared_ptr + : # sources + : [ requires cxx11_smart_ptr ] +] +[ bpl-test enable_shared_from_this ] +[ bpl-test andreas_beyer ] +[ bpl-test wrapper_held_type ] + +[ bpl-test polymorphism2_auto_ptr + : polymorphism2_auto_ptr.py polymorphism2.py polymorphism2_auto_ptr.cpp + : [ requires auto_ptr ] +] + +[ bpl-test polymorphism ] +[ bpl-test polymorphism2 ] + +[ bpl-test auto_ptr + : # files + : [ requires auto_ptr ] +] + +[ bpl-test minimal ] +[ bpl-test args ] +[ bpl-test raw_ctor ] +[ bpl-test enum : test_enum.py enum_ext.cpp ] +[ bpl-test exception_translator ] +[ bpl-test pearu1 : test_cltree.py cltree.cpp ] +[ bpl-test try : newtest.py m1.cpp m2.cpp ] +[ bpl-test const_argument ] +[ bpl-test keywords : keywords.cpp keywords_test.py ] + + +[ python-extension builtin_converters_ext : builtin_converters.cpp /boost/python//boost_python ] +[ bpl-test builtin_converters : test_builtin_converters.py builtin_converters_ext ] + + [ bpl-test test_pointer_adoption ] + [ bpl-test operators ] + [ bpl-test operators_wrapper ] + [ bpl-test callbacks ] + [ bpl-test defaults ] + +[ bpl-test object ] +[ bpl-test class ] +[ bpl-test list ] +[ bpl-test long ] +[ bpl-test dict ] +[ bpl-test tuple ] +[ bpl-test str ] +[ bpl-test slice ] + +[ bpl-test virtual_functions ] +[ bpl-test back_reference ] +[ bpl-test implicit ] +[ bpl-test data_members ] + +[ bpl-test ben_scott1 ] + +[ bpl-test bienstman1 ] +[ bpl-test bienstman2 ] +[ bpl-test bienstman3 ] + +[ bpl-test multi_arg_constructor + : # files + : # requirements + # A bug in the Win32 intel compilers causes compilation of one of our + # tests to take forever when debug symbols are enabled. This rule + # turns them off when added to the requirements section + <toolset>intel-win:<debug-symbols>off +] + +[ bpl-test iterator : iterator.py iterator.cpp input_iterator.cpp ] + +[ bpl-test stl_iterator : stl_iterator.py stl_iterator.cpp ] + +[ bpl-test extract ] + +[ +bpl-test crossmod_opaque + : crossmod_opaque.py crossmod_opaque_a.cpp crossmod_opaque_b.cpp +] +[ bpl-test opaque ] +[ bpl-test voidptr ] + +[ bpl-test pickle1 ] +[ bpl-test pickle2 ] +[ bpl-test pickle3 ] +[ bpl-test pickle4 ] + +[ bpl-test nested ] + +[ bpl-test docstring ] +[ bpl-test pytype_function ] + +[ bpl-test vector_indexing_suite ] + +[ bpl-test pointer_vector + : # files + : # requirements + # Turn off this test on HP CXX, as the test hangs when executing. + # Whenever the cause for the failure of the polymorphism test is found + # and fixed, this should be retested. + <toolset>hp_cxx:<build>no ] + +[ python-extension map_indexing_suite_ext + : map_indexing_suite.cpp int_map_indexing_suite.cpp a_map_indexing_suite.cpp + /boost/python//boost_python ] +[ bpl-test + map_indexing_suite : map_indexing_suite.py map_indexing_suite_ext ] + +[ run import_.cpp /boost/python//boost_python $(PY) : : import_.py ] + +# if $(TEST_BIENSTMAN_NON_BUGS) +# { +# bpl-test bienstman4 ; +# bpl-test bienstman5 ; +# } + +[ bpl-test calling_conventions : : <conditional>@require-windows ] +[ bpl-test calling_conventions_mf : : <conditional>@require-windows ] + +# --- unit tests of library components --- + +[ compile indirect_traits_test.cpp ] +[ run destroy_test.cpp ] +[ py-run pointer_type_id_test.cpp ] +[ py-run bases.cpp ] +[ run if_else.cpp ] +[ py-run pointee.cpp ] +[ run result.cpp ] + +[ compile string_literal.cpp ] +[ py-compile borrowed.cpp ] +[ py-compile object_manager.cpp ] +[ py-compile copy_ctor_mutates_rhs.cpp ] + +[ py-run upcast.cpp ] + +[ py-compile select_holder.cpp ] + +[ run select_from_python_test.cpp ../src/converter/type_id.cpp + : + : + : <define>BOOST_PYTHON_STATIC_LIB + <use>$(PY) + +] + + [ py-compile select_arg_to_python_test.cpp ] + +[ py-compile-fail ./raw_pyobject_fail1.cpp ] +[ py-compile-fail ./raw_pyobject_fail2.cpp ] +[ py-compile-fail ./as_to_python_function.cpp ] +[ py-compile-fail ./object_fail1.cpp ] + +# --- NumPy tests --- + +[ numpy-test numpy/dtype ] +[ numpy-test numpy/ufunc ] +[ numpy-test numpy/templates ] +[ numpy-test numpy/ndarray ] +[ numpy-test numpy/indexing ] +[ numpy-test numpy/shapes ] + + + ; +} diff --git a/src/boost/libs/python/test/a_map_indexing_suite.cpp b/src/boost/libs/python/test/a_map_indexing_suite.cpp new file mode 100644 index 000000000..07a0a6b97 --- /dev/null +++ b/src/boost/libs/python/test/a_map_indexing_suite.cpp @@ -0,0 +1,92 @@ +// Copyright Joel de Guzman 2004. 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) + +#include <boost/python/suite/indexing/map_indexing_suite.hpp> +#include <boost/python/module.hpp> +#include <boost/python/def.hpp> +#include <boost/python/implicit.hpp> + +using namespace boost::python; + +struct A +{ + int value; + A() : value(0){}; + A(int v) : value(v) {}; +}; + +bool operator==(const A& v1, const A& v2) +{ + return (v1.value == v2.value); +} + +struct B +{ + A a; +}; + +// Converter from A to python int +struct AToPython +{ + static PyObject* convert(const A& s) + { + return boost::python::incref(boost::python::object((int)s.value).ptr()); + } +}; + +// Conversion from python int to A +struct AFromPython +{ + AFromPython() + { + boost::python::converter::registry::push_back( + &convertible, + &construct, + boost::python::type_id< A >()); + } + + static void* convertible(PyObject* obj_ptr) + { +#if PY_VERSION_HEX >= 0x03000000 + if (!PyLong_Check(obj_ptr)) return 0; +#else + if (!PyInt_Check(obj_ptr)) return 0; +#endif + return obj_ptr; + } + + static void construct( + PyObject* obj_ptr, + boost::python::converter::rvalue_from_python_stage1_data* data) + { + void* storage = ( + (boost::python::converter::rvalue_from_python_storage< A >*) + data)-> storage.bytes; + +#if PY_VERSION_HEX >= 0x03000000 + new (storage) A((int)PyLong_AsLong(obj_ptr)); +#else + new (storage) A((int)PyInt_AsLong(obj_ptr)); +#endif + data->convertible = storage; + } +}; + +void a_map_indexing_suite() +{ + + to_python_converter< A , AToPython >(); + AFromPython(); + + class_< std::map<int, A> >("AMap") + .def(map_indexing_suite<std::map<int, A>, true >()) + ; + + class_< B >("B") + .add_property("a", make_getter(&B::a, return_value_policy<return_by_value>()), + make_setter(&B::a, return_value_policy<return_by_value>())) + ; +} + + diff --git a/src/boost/libs/python/test/andreas_beyer.cpp b/src/boost/libs/python/test/andreas_beyer.cpp new file mode 100644 index 000000000..b28b15660 --- /dev/null +++ b/src/boost/libs/python/test/andreas_beyer.cpp @@ -0,0 +1,61 @@ +// 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) +#include <boost/python.hpp> +#include <boost/enable_shared_from_this.hpp> +#include <boost/shared_ptr.hpp> + +using namespace boost; + +class A : public enable_shared_from_this<A> { + public: + A() : val(0) {}; + int val; + typedef shared_ptr<A> A_ptr; + A_ptr self() { + A_ptr self; + self = shared_from_this(); + return self; + } + +}; + +class B { + public: + B() { + a = A::A_ptr(new A()); + } + void set(A::A_ptr _a) { + this->a = _a; + } + A::A_ptr get() { + return a; + } + A::A_ptr a; +}; + +template <class T> +void hold_python(shared_ptr<T>& x) +{ + x = python::extract<shared_ptr<T> >( python::object(x) ); +} + +A::A_ptr get_b_a(shared_ptr<B> b) +{ + hold_python(b->a); + return b->get(); +} + +BOOST_PYTHON_MODULE(andreas_beyer_ext) { + python::class_<A, noncopyable> ("A") + .def("self", &A::self) + .def_readwrite("val", &A::val) + ; + python::register_ptr_to_python< A::A_ptr >(); + + python::class_<B>("B") + .def("set", &B::set) +// .def("get", &B::get) + .def("get", get_b_a) + ; +} diff --git a/src/boost/libs/python/test/andreas_beyer.py b/src/boost/libs/python/test/andreas_beyer.py new file mode 100644 index 000000000..0c24969bd --- /dev/null +++ b/src/boost/libs/python/test/andreas_beyer.py @@ -0,0 +1,24 @@ +# Copyright David Abrahams 2004. 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) +''' + >>> from andreas_beyer_ext import * + >>> b=B() + >>> a=b.get() # let b create an A + >>> a2=b.get() + >>> assert id(a) == id(a2) +''' +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/args.cpp b/src/boost/libs/python/test/args.cpp new file mode 100644 index 000000000..592a8e505 --- /dev/null +++ b/src/boost/libs/python/test/args.cpp @@ -0,0 +1,99 @@ +// Copyright David Abrahams 2002. +// 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) +#include <boost/python/module.hpp> +#include "test_class.hpp" +#include <boost/python/def.hpp> +#include <boost/python/args.hpp> +#include <boost/python/tuple.hpp> +#include <boost/python/class.hpp> +#include <boost/python/overloads.hpp> +#include <boost/python/raw_function.hpp> +#include <boost/python/return_internal_reference.hpp> + +using namespace boost::python; + +#if BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x580)) || BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500)) +# define make_tuple boost::python::make_tuple +#endif + +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) + + +tuple raw_func(tuple args, dict kw) +{ + return make_tuple(args, kw); +} + +BOOST_PYTHON_MODULE(args_ext) +{ + def("f", f, (arg("x")=1, arg("y")=4.25, arg("z")="wow") + , "This is f's docstring" + ); + + def("raw", raw_function(raw_func)); + +#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) + .def("raw", raw_function(raw_func)) + ; + + class_<X>("X", "This is X's docstring", init<>(args("self"))) + .def(init<int, optional<int> >(args("self", "a0", "a1"))) + .def("f", &X::f + , "This is X.f's docstring" + , args("self","x", "y", "z")) + + // Just to prove that all the different argument combinations work + .def("inner0", &X::inner, return_internal_reference<>(), args("self", "n"), "docstring") + .def("inner1", &X::inner, return_internal_reference<>(), "docstring", args("self", "n")) + + .def("inner2", &X::inner, args("self", "n"), return_internal_reference<>(), "docstring") + .def("inner3", &X::inner, "docstring", return_internal_reference<>(), args("self", "n")) + + .def("inner4", &X::inner, args("self", "n"), "docstring", return_internal_reference<>()) + .def("inner5", &X::inner, "docstring", args("self", "n"), return_internal_reference<>()) + + .def("f1", &X::f, X_f_overloads(args("self", "x", "y", "z"))) + .def("f2", &X::f, X_f_overloads(args("self", "x", "y", "z"), "f2's docstring")) + .def("f2", &X::f, X_f_overloads(args("x", "y", "z"), "f2's docstring")) + ; + + def("inner", &X::inner, "docstring", args("self", "n"), return_internal_reference<>()); +} + +#include "module_tail.cpp" diff --git a/src/boost/libs/python/test/args.py b/src/boost/libs/python/test/args.py new file mode 100644 index 000000000..e884c06be --- /dev/null +++ b/src/boost/libs/python/test/args.py @@ -0,0 +1,148 @@ +# Copyright David Abrahams 2004. 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) +from __future__ import print_function +""" +>>> from args_ext import * + +>>> raw(3, 4, foo = 'bar', baz = 42) +((3, 4), {'foo': 'bar', 'baz': 42}) + + Prove that we can handle empty keywords and non-keywords + +>>> raw(3, 4) +((3, 4), {}) + +>>> raw(foo = 'bar') +((), {'foo': 'bar'}) + +>>> 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') +>>> q.f2.__doc__.splitlines()[1] +'f2( (X)self [, (int)x [, (float)y [, (str)z]]]) -> tuple :' + +>>> q.f2.__doc__.splitlines()[2] +" f2's docstring" + +>>> X.f.__doc__.splitlines()[1:5] +['f( (X)self, (int)x, (float)y, (str)z) -> tuple :', " This is X.f's docstring", '', ' C++ signature :'] + +>>> xfuncs = (X.inner0, X.inner1, X.inner2, X.inner3, X.inner4, X.inner5) +>>> for f in xfuncs: +... print(f(q,1).value(), end=' ') +... print(f(q, n = 1).value(), end=' ') +... print(f(q, n = 0).value(), end=' ') +... print(f.__doc__.splitlines()[1:5]) +1 1 0 ['inner0( (X)self, (bool)n) -> Y :', ' docstring', '', ' C++ signature :'] +1 1 0 ['inner1( (X)self, (bool)n) -> Y :', ' docstring', '', ' C++ signature :'] +1 1 0 ['inner2( (X)self, (bool)n) -> Y :', ' docstring', '', ' C++ signature :'] +1 1 0 ['inner3( (X)self, (bool)n) -> Y :', ' docstring', '', ' C++ signature :'] +1 1 0 ['inner4( (X)self, (bool)n) -> Y :', ' docstring', '', ' C++ signature :'] +1 1 0 ['inner5( (X)self, (bool)n) -> Y :', ' docstring', '', ' C++ signature :'] + +>>> 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 + +>>> y = Y(value = 33) +>>> y.raw(this = 1, that = 'the other')[1] +{'this': 1, 'that': 'the other'} + +""" +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 + status = run()[0] + if (status == 0): print("Done.") + import args_ext + help(args_ext) + sys.exit(status) + + + diff --git a/src/boost/libs/python/test/as_to_python_function.cpp b/src/boost/libs/python/test/as_to_python_function.cpp new file mode 100644 index 000000000..cc083890a --- /dev/null +++ b/src/boost/libs/python/test/as_to_python_function.cpp @@ -0,0 +1,13 @@ +// Copyright David Abrahams 2002. +// 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) + +#include <boost/python/converter/as_to_python_function.hpp> + +struct hopefully_illegal +{ + static PyObject* convert(int&); +}; + +PyObject* x = boost::python::converter::as_to_python_function<int, hopefully_illegal>::convert(0); diff --git a/src/boost/libs/python/test/auto_ptr.cpp b/src/boost/libs/python/test/auto_ptr.cpp new file mode 100644 index 000000000..0f61e96dc --- /dev/null +++ b/src/boost/libs/python/test/auto_ptr.cpp @@ -0,0 +1,90 @@ +// Copyright David Abrahams 2002. +// 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) + +#include <boost/python/module.hpp> +#include "test_class.hpp" +#include <boost/python/class.hpp> +#include <boost/python/extract.hpp> +#include <boost/python/def.hpp> +#include <boost/python/implicit.hpp> + +#include <boost/detail/workaround.hpp> + +#include <memory> + +using namespace boost::python; + +typedef test_class<> X; + +struct Y : X +{ + Y(int n) : X(n) {}; +}; + +int look(std::auto_ptr<X> const& x) +{ + return (x.get()) ? x->value() : -1; +} + +int steal(std::auto_ptr<X> x) +{ + return x->value(); +} + +int maybe_steal(std::auto_ptr<X>& x, bool doit) +{ + int n = x->value(); + if (doit) + x.release(); + return n; +} + +std::auto_ptr<X> make() +{ + return std::auto_ptr<X>(new X(77)); +} + +std::auto_ptr<X> callback(object f) +{ + std::auto_ptr<X> x(new X(77)); + return call<std::auto_ptr<X> >(f.ptr(), x); +} + +std::auto_ptr<X> extract_(object o) +{ + return extract<std::auto_ptr<X>&>(o) +#if BOOST_MSVC <= 1300 + () +#endif + ; +} + +BOOST_PYTHON_MODULE(auto_ptr_ext) +{ + class_<X, std::auto_ptr<X>, boost::noncopyable>("X", init<int>()) + .def("value", &X::value) + ; + + class_<Y, std::auto_ptr<Y>, bases<X>, boost::noncopyable>("Y", init<int>()) + ; + + // VC6 auto_ptrs do not have converting constructors +#if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, < 306) + scope().attr("broken_auto_ptr") = 1; +#else + scope().attr("broken_auto_ptr") = 0; + implicitly_convertible<std::auto_ptr<Y>, std::auto_ptr<X> >(); +#endif + + def("look", look); + def("steal", steal); + def("maybe_steal", maybe_steal); + def("make", make); + def("callback", callback); + def("extract", extract_); +} + +#include "module_tail.cpp" + diff --git a/src/boost/libs/python/test/auto_ptr.py b/src/boost/libs/python/test/auto_ptr.py new file mode 100644 index 000000000..12e977d06 --- /dev/null +++ b/src/boost/libs/python/test/auto_ptr.py @@ -0,0 +1,100 @@ +# Copyright David Abrahams 2004. 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) +''' +>>> from auto_ptr_ext import * +>>> x = X(42) +>>> x.value() +42 +>>> look(x), look(x) +(42, 42) + +>>> maybe_steal(x, 0) +42 +>>> look(x) +42 + +>>> maybe_steal(x, 1) +42 +>>> broken_auto_ptr and -1 or look(x) +-1 + +>>> x = X(69) +>>> steal(x) +69 +>>> broken_auto_ptr and -1 or look(x) +-1 + +>>> if not broken_auto_ptr: +... try: x.value() +... except TypeError: pass +... else: print('expected a TypeError exception') + +>>> x = make() +>>> look(x) +77 + +>>> z = callback(lambda z: z) +>>> z.value() +77 + +>>> extract(x).value() +77 + +# +# Test derived to base conversions +# + +>>> y = Y(42) +>>> y.value() +42 + +>>> try: maybe_steal(y, 0) +... except TypeError: pass +... else: print('expected a TypeError exception') + +>>> y.value() +42 + +>>> broken_auto_ptr and 42 or steal(y) +42 + +>>> if not broken_auto_ptr: +... try: y.value() +... except TypeError: pass +... else: print('expected a TypeError exception') + +>>> print(look.__doc__.splitlines()[1]) +look( (X)arg1) -> int : + +>>> print(steal.__doc__.splitlines()[1]) +steal( (X)arg1) -> int : + +>>> print(maybe_steal.__doc__.splitlines()[1]) +maybe_steal( (X)arg1, (bool)arg2) -> int : + +>>> print(make.__doc__.splitlines()[1]) +make() -> X : + +>>> print(callback.__doc__.splitlines()[1]) +callback( (object)arg1) -> X : + +>>> print(extract.__doc__.splitlines()[1]) +extract( (object)arg1) -> X : + +''' + +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/back_reference.cpp b/src/boost/libs/python/test/back_reference.cpp new file mode 100644 index 000000000..266ed2912 --- /dev/null +++ b/src/boost/libs/python/test/back_reference.cpp @@ -0,0 +1,112 @@ +// Copyright David Abrahams 2002. +// 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) +#include <boost/python/class.hpp> +#include <boost/python/module.hpp> +#include <boost/python/def.hpp> +#include <boost/python/has_back_reference.hpp> +#include <boost/python/back_reference.hpp> +#include <boost/ref.hpp> +#include <boost/utility.hpp> +#include <memory> +#define BOOST_ENABLE_ASSERT_HANDLER +#include <boost/assert.hpp> +#include <boost/python/copy_const_reference.hpp> +#include <boost/python/return_value_policy.hpp> +#include <boost/mpl/bool.hpp> + +// This test shows that a class can be wrapped "as itself" but also +// acquire a back-reference iff has_back_reference<> is appropriately +// specialized. +using namespace boost::python; + +struct X +{ + explicit X(int x) : x(x), magic(7654321) { ++counter; } + X(X const& rhs) : x(rhs.x), magic(7654321) { ++counter; } + virtual ~X() { BOOST_ASSERT(magic == 7654321); magic = 6666666; x = 9999; --counter; } + + void set(int _x) { BOOST_ASSERT(magic == 7654321); this->x = _x; } + int value() const { BOOST_ASSERT(magic == 7654321); return x; } + static int count() { return counter; } + private: + void operator=(X const&); + private: + int x; + long magic; + static int counter; +}; + +int X::counter; + +struct Y : X +{ + Y(PyObject* self, int x) : X(x), self(self) {} + Y(PyObject* self, Y const& rhs) : X(rhs), self(self) {} + private: + Y(Y const&); + PyObject* self; +}; + +struct Z : X +{ + Z(PyObject* self, int x) : X(x), self(self) {} + Z(PyObject* self, Z const& rhs) : X(rhs), self(self) {} + private: + Z(Z const&); + PyObject* self; +}; + +Y const& copy_Y(Y const& y) { return y; } +Z const& copy_Z(Z const& z) { return z; } + +namespace boost { namespace python +{ + template <> + struct has_back_reference<Y> + : mpl::true_ + { + }; + + template <> + struct has_back_reference<Z> + : mpl::true_ + { + }; +}} + +// prove that back_references get initialized with the right PyObject* +object y_identity(back_reference<Y const&> y) +{ + return y.source(); +} + +// prove that back_references contain the right value +bool y_equality(back_reference<Y const&> y1, Y const& y2) +{ + return &y1.get() == &y2; +} + +BOOST_PYTHON_MODULE(back_reference_ext) +{ + def("copy_Y", copy_Y, return_value_policy<copy_const_reference>()); + def("copy_Z", copy_Z, return_value_policy<copy_const_reference>()); + def("x_instances", &X::count); + + class_<Y>("Y", init<int>()) + .def("value", &Y::value) + .def("set", &Y::set) + ; + + class_<Z,std::auto_ptr<Z> >("Z", init<int>()) + .def("value", &Z::value) + .def("set", &Z::set) + ; + + def("y_identity", y_identity); + def("y_equality", y_equality); + +} + +#include "module_tail.cpp" diff --git a/src/boost/libs/python/test/back_reference.py b/src/boost/libs/python/test/back_reference.py new file mode 100644 index 000000000..4a283a3e3 --- /dev/null +++ b/src/boost/libs/python/test/back_reference.py @@ -0,0 +1,37 @@ +# Copyright David Abrahams 2004. 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) +''' +>>> from back_reference_ext import * +>>> y = Y(3) +>>> z = Z(4) +>>> x_instances() +2 +>>> y2 = copy_Y(y) +>>> x_instances() +3 +>>> z2 = copy_Z(z) +>>> x_instances() +4 +>>> assert y_identity(y) is y +>>> y_equality(y, y) +1 + +>>> print(y_identity.__doc__.splitlines()[1]) +y_identity( (Y)arg1) -> object : +''' + +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/bases.cpp b/src/boost/libs/python/test/bases.cpp new file mode 100644 index 000000000..4e00f5448 --- /dev/null +++ b/src/boost/libs/python/test/bases.cpp @@ -0,0 +1,62 @@ +// Copyright David Abrahams 2002. +// 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) +#include <boost/python/bases.hpp> +#include <boost/static_assert.hpp> +#include <boost/python/detail/type_traits.hpp> + +struct A; +struct B; + +template <class X, class Y, class Z> +struct choose_bases + : boost::python::detail::select_bases< + X + , typename boost::python::detail::select_bases< + Y + , typename boost::python::detail::select_bases<Z>::type + >::type> +{ + +}; + +int main() +{ + BOOST_STATIC_ASSERT((boost::python::detail::specifies_bases< + boost::python::bases<A,B> >::value)); + + BOOST_STATIC_ASSERT((!boost::python::detail::specifies_bases< + boost::python::bases<A,B>& >::value)); + + BOOST_STATIC_ASSERT((!boost::python::detail::specifies_bases< + void* >::value)); + + BOOST_STATIC_ASSERT((!boost::python::detail::specifies_bases< + int >::value)); + + BOOST_STATIC_ASSERT((!boost::python::detail::specifies_bases< + int[5] >::value)); + + typedef boost::python::detail::select_bases< + int + , boost::python::detail::select_bases<char*>::type > collected1; + + BOOST_STATIC_ASSERT((boost::python::detail::is_same<collected1::type,boost::python::bases<> >::value)); + BOOST_STATIC_ASSERT((boost::python::detail::is_same<choose_bases<int,char*,long>::type,boost::python::bases<> >::value)); + + typedef boost::python::detail::select_bases< + int + , boost::python::detail::select_bases< + boost::python::bases<A,B> + , boost::python::detail::select_bases< + A + >::type + >::type + > collected2; + + BOOST_STATIC_ASSERT((boost::python::detail::is_same<collected2::type,boost::python::bases<A,B> >::value)); + BOOST_STATIC_ASSERT((boost::python::detail::is_same<choose_bases<int,boost::python::bases<A,B>,long>::type,boost::python::bases<A,B> >::value)); + + return 0; +} diff --git a/src/boost/libs/python/test/ben_scott1.cpp b/src/boost/libs/python/test/ben_scott1.cpp new file mode 100644 index 000000000..5a675e230 --- /dev/null +++ b/src/boost/libs/python/test/ben_scott1.cpp @@ -0,0 +1,54 @@ +// Copyright David Abrahams 2004. 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) +#include <boost/python.hpp> +#include <iostream> +using namespace boost::python; +using namespace boost; + +struct Product {}; +typedef shared_ptr<Product> ProductPtr; + + +struct Creator +{ + virtual ~Creator() {} + virtual ProductPtr create() = 0; +}; + + +struct Factory +{ + void reg(Creator* c) { mC = c; } + ProductPtr create() + { + std::cout << "Name: " << (typeid(*mC)).name() << std::endl; + return mC->create(); + } + +private: + Creator* mC; +}; + +struct CreatorWrap : public Creator +{ + CreatorWrap(PyObject* self) : mSelf(self) {} + ProductPtr create() { return call_method<ProductPtr>(mSelf, "create"); } + PyObject* mSelf; +}; + +BOOST_PYTHON_MODULE(ben_scott1_ext) +{ + class_<Product, ProductPtr>("Product"); + + class_<Creator, CreatorWrap, noncopyable>("Creator") + .def("create", &CreatorWrap::create) + ; + + class_<Factory>("Factory") + .def("reg", &Factory::reg, with_custodian_and_ward<1,2>()) + .def("create", &Factory::create) + ; +} + +#include "../test/module_tail.cpp" diff --git a/src/boost/libs/python/test/ben_scott1.py b/src/boost/libs/python/test/ben_scott1.py new file mode 100644 index 000000000..79130757a --- /dev/null +++ b/src/boost/libs/python/test/ben_scott1.py @@ -0,0 +1,17 @@ +# Copyright David Abrahams 2004. 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) +# This regression test checks that call_method<T>(...) where T is a +# non-reference, non-pointer type that happens to be held inside the +# result object (and thus is found as an lvalue) works. +from ben_scott1_ext import * + +class CreatorImpl(Creator): + def create(self): + return Product() + +factory = Factory() +c = CreatorImpl() +factory.reg(c) + +a = factory.create() diff --git a/src/boost/libs/python/test/bienstman1.cpp b/src/boost/libs/python/test/bienstman1.cpp new file mode 100644 index 000000000..dc0065784 --- /dev/null +++ b/src/boost/libs/python/test/bienstman1.cpp @@ -0,0 +1,40 @@ +// Copyright David Abrahams 2004. 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) +#include <boost/python/module.hpp> +#include <boost/python/def.hpp> +#include <boost/python/class.hpp> +#include <boost/python/reference_existing_object.hpp> +#include <boost/python/return_value_policy.hpp> + +struct A {}; + +struct V +{ + virtual ~V() {}; // silence compiler warningsa + virtual void f() = 0; + + const A* inside() {return &a;} + + A a; +}; + +const A* outside(const V& v) {return &v.a;} + +BOOST_PYTHON_MODULE(bienstman1_ext) +{ + using namespace boost::python; + using boost::shared_ptr; + using boost::python::return_value_policy; + using boost::python::reference_existing_object; + + class_<A>("A"); + + class_<V, boost::noncopyable>("V", no_init) + .def("inside", &V::inside, + return_value_policy<reference_existing_object>()) + .def("outside", outside, + return_value_policy<reference_existing_object>()) + ; +} + diff --git a/src/boost/libs/python/test/bienstman1.py b/src/boost/libs/python/test/bienstman1.py new file mode 100644 index 000000000..16dc47b2d --- /dev/null +++ b/src/boost/libs/python/test/bienstman1.py @@ -0,0 +1,23 @@ +# Copyright David Abrahams 2004. 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) +''' +# Try to reproduce a Numeric interaction bug if Numeric is installed. +>>> from bienstman1_ext import * +>>> try: from Numeric import * +... except: pass +''' +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/bienstman2.cpp b/src/boost/libs/python/test/bienstman2.cpp new file mode 100644 index 000000000..10f99923d --- /dev/null +++ b/src/boost/libs/python/test/bienstman2.cpp @@ -0,0 +1,28 @@ +// Copyright David Abrahams 2004. 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) +#include <boost/python/module.hpp> +#include <boost/python/def.hpp> +#include <boost/python/class.hpp> + +struct C {}; + +struct D {}; + +struct E +{ + const D fe (const C&) {return D();} + const D fe2(const C&, const C&) {return D();} +}; + +BOOST_PYTHON_MODULE(bienstman2_ext) +{ + using namespace boost::python; + + class_<C>("C"); + class_<D>("D"); + class_<E>("E") + .def("fe", &E::fe) // this compiles. + .def("fe2", &E::fe2) // this doesn't... well, now it does ;-) + ; +} diff --git a/src/boost/libs/python/test/bienstman2.py b/src/boost/libs/python/test/bienstman2.py new file mode 100644 index 000000000..931fae8f7 --- /dev/null +++ b/src/boost/libs/python/test/bienstman2.py @@ -0,0 +1,20 @@ +# Copyright David Abrahams 2004. 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) +''' +>>> import bienstman2_ext +''' +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/bienstman3.cpp b/src/boost/libs/python/test/bienstman3.cpp new file mode 100644 index 000000000..d765b303d --- /dev/null +++ b/src/boost/libs/python/test/bienstman3.cpp @@ -0,0 +1,26 @@ +// Copyright David Abrahams 2004. 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) +#include <boost/python/module.hpp> +#include <boost/python/def.hpp> +#include <boost/python/class.hpp> + +struct V +{ + virtual ~V() {}; // silence compiler warningsa + virtual void f() = 0; +}; + +struct B +{ + B(const V&) {} +}; + +BOOST_PYTHON_MODULE(bienstman3_ext) +{ + using namespace boost::python; + + class_<V, boost::noncopyable>("V", no_init); + class_<B>("B", init<const V&>()); + +} diff --git a/src/boost/libs/python/test/bienstman3.py b/src/boost/libs/python/test/bienstman3.py new file mode 100644 index 000000000..d0d250aea --- /dev/null +++ b/src/boost/libs/python/test/bienstman3.py @@ -0,0 +1,30 @@ +# Copyright David Abrahams 2004. 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) +''' +>>> from bienstman3_ext import * + +>>> try: +... V() +... except RuntimeError as x: +... print(x) +... else: +... print('expected an exception') +... +This class cannot be instantiated from Python + +''' +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/bienstman4.cpp b/src/boost/libs/python/test/bienstman4.cpp new file mode 100644 index 000000000..34b9e211f --- /dev/null +++ b/src/boost/libs/python/test/bienstman4.cpp @@ -0,0 +1,39 @@ +// Copyright David Abrahams 2002. +// 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) + +#include <boost/python/module.hpp> +#include <boost/python/def.hpp> +#include <boost/python/class.hpp> +#include <boost/python/implicit.hpp> +#include <boost/mpl/list.hpp> + +struct Type1 {}; + +struct Term {Term(Type1 const&) {} }; + +struct Expression {void add(Term const&) {} }; + +BOOST_PYTHON_MODULE(bienstman4_ext) +{ + using namespace boost::python; + using boost::mpl::list; + + implicitly_convertible<Type1,Term>(); + + class_<Expression>("Expression") + .def("add", &Expression::add) + ; + + class_<Type1>("T1") + ; + + class_<Term>("Term", init<Type1&>()) + ; + + Type1 t1; + Expression e; + e.add(t1); +} + diff --git a/src/boost/libs/python/test/bienstman4.py b/src/boost/libs/python/test/bienstman4.py new file mode 100644 index 000000000..eea33ba2a --- /dev/null +++ b/src/boost/libs/python/test/bienstman4.py @@ -0,0 +1,23 @@ +# Copyright David Abrahams 2004. 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) +''' +>>> from bienstman4_ext import * +>>> t1 = T1() +>>> e = Expression() +>>> e.add(t1) +''' +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/bienstman5.cpp b/src/boost/libs/python/test/bienstman5.cpp new file mode 100644 index 000000000..657dadd12 --- /dev/null +++ b/src/boost/libs/python/test/bienstman5.cpp @@ -0,0 +1,23 @@ +// Copyright David Abrahams 2002. +// 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) + +#include <boost/python/module.hpp> +#include <boost/python/def.hpp> +#include <boost/python/class.hpp> +#include <boost/mpl/list.hpp> + +#include <complex> + +struct M {M(const std::complex<double>&) {} }; + +BOOST_PYTHON_MODULE(bienstman5_ext) +{ + using namespace boost::python; + + class_<M>("M", init<std::complex<double> const&>()) + ; +} + + diff --git a/src/boost/libs/python/test/bienstman5.py b/src/boost/libs/python/test/bienstman5.py new file mode 100644 index 000000000..a6735d942 --- /dev/null +++ b/src/boost/libs/python/test/bienstman5.py @@ -0,0 +1,21 @@ +# Copyright David Abrahams 2004. 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) +''' +>>> from bienstman5_ext import * +>>> m = M(1j) +''' +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/boost_shared_ptr.cpp b/src/boost/libs/python/test/boost_shared_ptr.cpp new file mode 100644 index 000000000..57e50aa3c --- /dev/null +++ b/src/boost/libs/python/test/boost_shared_ptr.cpp @@ -0,0 +1,20 @@ +// Copyright David Abrahams 2002. +// Copyright Stefan Seefeld 2016. +// 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) + +#include <boost/python/module.hpp> +#include <boost/python/class.hpp> +#include <boost/python/call_method.hpp> +#include <boost/python/extract.hpp> +#include <boost/python/def.hpp> +#include <boost/shared_ptr.hpp> +#include <memory> + +using boost::shared_ptr; +#define MODULE boost_shared_ptr_ext + +#include "shared_ptr.hpp" +#include "module_tail.cpp" + diff --git a/src/boost/libs/python/test/boost_shared_ptr.py b/src/boost/libs/python/test/boost_shared_ptr.py new file mode 100644 index 000000000..31a2ad3d2 --- /dev/null +++ b/src/boost/libs/python/test/boost_shared_ptr.py @@ -0,0 +1,130 @@ +# Copyright David Abrahams 2004. 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) +''' +>>> from boost_shared_ptr_ext import * + + Test that shared_ptr<Derived> can be converted to shared_ptr<Base> + +>>> Y.store(YYY(42)) + +>>> x = X(17) +>>> null_x = null(x) +>>> null_x # should be None +>>> identity(null_x) # should also be None + +>>> a = New(1) +>>> A.call_f(a) +1 +>>> New(0) + +>>> type(factory(3)) +<class 'boost_shared_ptr_ext.Y'> +>>> type(factory(42)) +<class 'boost_shared_ptr_ext.YY'> + +>>> class P(Z): +... def v(self): +... return -Z.v(self); +... def __del__(self): +... print('bye') +... +>>> p = P(12) +>>> p.value() +12 +>>> p.v() +-12 +>>> look(p) +12 +>>> try: modify(p) +... except TypeError: pass +... else: 'print(expected a TypeError)' +>>> look(None) +-1 +>>> store(p) +>>> del p +>>> Z.get().v() +-12 +>>> Z.count() +1 +>>> Z.look_store() +12 +>>> Z.release() +bye +>>> Z.count() +0 + +>>> z = Z(13) +>>> z.value() +13 +>>> z.v() +13 +>>> try: modify(z) +... except TypeError: pass +... else: 'print(expected a TypeError)' + +>>> Z.get() # should be None +>>> store(z) +>>> assert Z.get() is z # show that deleter introspection works +>>> del z +>>> Z.get().value() +13 +>>> Z.count() +1 +>>> Z.look_store() +13 +>>> Z.release() +>>> Z.count() +0 + +>>> x = X(17) +>>> x.value() +17 +>>> look(x) +17 +>>> try: modify(x) +... except TypeError: pass +... else: 'print(expected a TypeError)' +>>> look(None) +-1 +>>> store(x) +>>> del x +>>> X.count() +1 +>>> X.look_store() +17 +>>> X.release() +>>> X.count() +0 + + +>>> y = Y(19) +>>> y.value() +19 +>>> modify(y) +>>> look(y) +-1 +>>> store(Y(23)) +>>> Y.count() +1 +>>> Y.look_store() +23 +>>> Y.release() +>>> Y.count() +0 +''' + +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/borrowed.cpp b/src/boost/libs/python/test/borrowed.cpp new file mode 100644 index 000000000..2c1bd1b7a --- /dev/null +++ b/src/boost/libs/python/test/borrowed.cpp @@ -0,0 +1,33 @@ +// Copyright David Abrahams 2002. +// 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) +#include <boost/python/detail/wrap_python.hpp> +#include <boost/python/borrowed.hpp> +#include <boost/static_assert.hpp> + +using namespace boost::python; + +template <class T> +void assert_borrowed_ptr(T const&) +{ + BOOST_STATIC_ASSERT(boost::python::detail::is_borrowed_ptr<T>::value); +} + +template <class T> +void assert_not_borrowed_ptr(T const&) +{ + BOOST_STATIC_ASSERT(!boost::python::detail::is_borrowed_ptr<T>::value); +} + +int main() +{ + assert_borrowed_ptr(borrowed((PyObject*)0)); + assert_borrowed_ptr(borrowed((PyTypeObject*)0)); + assert_borrowed_ptr((detail::borrowed<PyObject> const*)0); + assert_borrowed_ptr((detail::borrowed<PyObject> volatile*)0); + assert_borrowed_ptr((detail::borrowed<PyObject> const volatile*)0); + assert_not_borrowed_ptr((PyObject*)0); + assert_not_borrowed_ptr(0); + return 0; +} diff --git a/src/boost/libs/python/test/builtin_converters.cpp b/src/boost/libs/python/test/builtin_converters.cpp new file mode 100644 index 000000000..f66e61bd8 --- /dev/null +++ b/src/boost/libs/python/test/builtin_converters.cpp @@ -0,0 +1,152 @@ +// Copyright David Abrahams 2002. +// 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) +#include <boost/python/module.hpp> +#include <boost/python/def.hpp> +#include <complex> +#include <boost/python/handle.hpp> +#include <boost/python/cast.hpp> +#include <boost/python/object.hpp> +#include <boost/python/detail/wrap_python.hpp> + +template <class T> +struct by_value +{ + static T rewrap(T x) + { + return x; + } + static int size(void) + { + return sizeof(T); + } +}; + +template <class T> +struct by_const_reference +{ + static T rewrap(T const& x) + { + return x; + } +}; + +template <class T> +struct by_reference +{ + static T rewrap(T& x) + { + return x; + } +}; + +using boost::python::def; +using boost::python::handle; +using boost::python::object; +using boost::python::borrowed; + +// Used to test that arbitrary handle<>s can be returned +handle<PyTypeObject> get_type(handle<> x) +{ + return handle<PyTypeObject>(borrowed(x->ob_type)); +} + +handle<> return_null_handle() +{ + return handle<>(); +} + +char const* rewrap_value_mutable_cstring(char* x) { return x; } + +object identity_(object x) { return x; } + +BOOST_PYTHON_MODULE(builtin_converters_ext) +{ + def("get_type", get_type); + def("return_null_handle", return_null_handle); + +// These methods are used solely for getting some C++ type sizes + def("bool_size", by_value<bool>::size); + def("char_size", by_value<char>::size); + def("int_size", by_value<int>::size); + def("short_size", by_value<short>::size); + def("long_size", by_value<long>::size); +#ifdef HAVE_LONG_LONG + def("long_long_size", by_value<BOOST_PYTHON_LONG_LONG>::size); +#endif + + def("rewrap_value_bool", by_value<bool>::rewrap); + def("rewrap_value_char", by_value<char>::rewrap); + def("rewrap_value_signed_char", by_value<signed char>::rewrap); + def("rewrap_value_unsigned_char", by_value<unsigned char>::rewrap); + def("rewrap_value_int", by_value<int>::rewrap); + def("rewrap_value_unsigned_int", by_value<unsigned int>::rewrap); + def("rewrap_value_short", by_value<short>::rewrap); + def("rewrap_value_unsigned_short", by_value<unsigned short>::rewrap); + def("rewrap_value_long", by_value<long>::rewrap); + def("rewrap_value_unsigned_long", by_value<unsigned long>::rewrap); +// using Python's macro instead of Boost's - we don't seem to get the +// config right all the time. +#ifdef HAVE_LONG_LONG + def("rewrap_value_long_long", by_value<BOOST_PYTHON_LONG_LONG>::rewrap); + def("rewrap_value_unsigned_long_long", by_value<unsigned BOOST_PYTHON_LONG_LONG>::rewrap); +# endif + def("rewrap_value_float", by_value<float>::rewrap); + def("rewrap_value_double", by_value<double>::rewrap); + def("rewrap_value_long_double", by_value<long double>::rewrap); + def("rewrap_value_complex_float", by_value<std::complex<float> >::rewrap); + def("rewrap_value_complex_double", by_value<std::complex<double> >::rewrap); + def("rewrap_value_complex_long_double", by_value<std::complex<long double> >::rewrap); + def("rewrap_value_wstring", +# if defined(BOOST_NO_STD_WSTRING) || !defined(Py_USING_UNICODE) + identity_ +# else + by_value<std::wstring>::rewrap +# endif + ); + def("rewrap_value_string", +# if defined(BOOST_NO_STD_WSTRING) || !defined(Py_USING_UNICODE) + identity_ +# else + by_value<std::wstring>::rewrap +# endif + ); + def("rewrap_value_string", by_value<std::string>::rewrap); + def("rewrap_value_cstring", by_value<char const*>::rewrap); + def("rewrap_value_handle", by_value<handle<> >::rewrap); + def("rewrap_value_object", by_value<object>::rewrap); + + // Expose this to illustrate our failings ;-). See test_builtin_converters.py + def("rewrap_value_mutable_cstring", rewrap_value_mutable_cstring); + + + def("rewrap_const_reference_bool", by_const_reference<bool>::rewrap); + def("rewrap_const_reference_char", by_const_reference<char>::rewrap); + def("rewrap_const_reference_signed_char", by_const_reference<signed char>::rewrap); + def("rewrap_const_reference_unsigned_char", by_const_reference<unsigned char>::rewrap); + def("rewrap_const_reference_int", by_const_reference<int>::rewrap); + def("rewrap_const_reference_unsigned_int", by_const_reference<unsigned int>::rewrap); + def("rewrap_const_reference_short", by_const_reference<short>::rewrap); + def("rewrap_const_reference_unsigned_short", by_const_reference<unsigned short>::rewrap); + def("rewrap_const_reference_long", by_const_reference<long>::rewrap); + def("rewrap_const_reference_unsigned_long", by_const_reference<unsigned long>::rewrap); +// using Python's macro instead of Boost's - we don't seem to get the +// config right all the time. +# ifdef HAVE_LONG_LONG + def("rewrap_const_reference_long_long", by_const_reference<BOOST_PYTHON_LONG_LONG>::rewrap); + def("rewrap_const_reference_unsigned_long_long", by_const_reference<unsigned BOOST_PYTHON_LONG_LONG>::rewrap); +# endif + def("rewrap_const_reference_float", by_const_reference<float>::rewrap); + def("rewrap_const_reference_double", by_const_reference<double>::rewrap); + def("rewrap_const_reference_long_double", by_const_reference<long double>::rewrap); + def("rewrap_const_reference_complex_float", by_const_reference<std::complex<float> >::rewrap); + def("rewrap_const_reference_complex_double", by_const_reference<std::complex<double> >::rewrap); + def("rewrap_const_reference_complex_long_double", by_const_reference<std::complex<long double> >::rewrap); + def("rewrap_const_reference_string", by_const_reference<std::string>::rewrap); + def("rewrap_const_reference_cstring", by_const_reference<char const*>::rewrap); + def("rewrap_const_reference_handle", by_const_reference<handle<> >::rewrap); + def("rewrap_const_reference_object", by_const_reference<object>::rewrap); + def("rewrap_reference_object", by_reference<object>::rewrap); +} + diff --git a/src/boost/libs/python/test/callbacks.cpp b/src/boost/libs/python/test/callbacks.cpp new file mode 100644 index 000000000..66bd35240 --- /dev/null +++ b/src/boost/libs/python/test/callbacks.cpp @@ -0,0 +1,150 @@ +// Copyright David Abrahams 2002. +// 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) + +#include <boost/python/module.hpp> +#include <boost/python/def.hpp> +#include <boost/python/class.hpp> +#include <boost/ref.hpp> +#include <boost/python/ptr.hpp> +#include <boost/python/return_value_policy.hpp> +#include <boost/python/reference_existing_object.hpp> +#include <boost/python/call.hpp> +#include <boost/python/object.hpp> +#define BOOST_ENABLE_ASSERT_HANDLER +#include <boost/assert.hpp> + +using namespace boost::python; +BOOST_STATIC_ASSERT(converter::is_object_manager<handle<> >::value); + +int apply_int_int(PyObject* f, int x) +{ + return call<int>(f, x); +} + +void apply_void_int(PyObject* f, int x) +{ + call<void>(f, x); +} + +struct X +{ + explicit X(int x) : x(x), magic(7654321) { ++counter; } + X(X const& rhs) : x(rhs.x), magic(7654321) { ++counter; } + ~X() { BOOST_ASSERT(magic == 7654321); magic = 6666666; x = 9999; --counter; } + + void set(int _x) { BOOST_ASSERT(magic == 7654321); this->x = _x; } + int value() const { BOOST_ASSERT(magic == 7654321); return x; } + static int count() { return counter; } + private: + void operator=(X const&); + private: + int x; + long magic; + static int counter; +}; + +X apply_X_X(PyObject* f, X x) +{ + return call<X>(f, x); +} + +void apply_void_X_ref(PyObject* f, X& x) +{ + call<void>(f, boost::ref(x)); +} + +X& apply_X_ref_handle(PyObject* f, handle<> obj) +{ + return call<X&>(f, obj); +} + +X* apply_X_ptr_handle_cref(PyObject* f, handle<> const& obj) +{ + return call<X*>(f, obj); +} + +void apply_void_X_cref(PyObject* f, X const& x) +{ + call<void>(f, boost::cref(x)); +} + +void apply_void_X_ptr(PyObject* f, X* x) +{ + call<void>(f, ptr(x)); +} + +void apply_void_X_deep_ptr(PyObject* f, X* x) +{ + call<void>(f, x); +} + +char const* apply_cstring_cstring(PyObject* f, char const* s) +{ + return call<char const*>(f, s); +} + +char const* apply_cstring_pyobject(PyObject* f, PyObject* s) +{ + return call<char const*>(f, borrowed(s)); +} + +char apply_char_char(PyObject* f, char c) +{ + return call<char>(f, c); +} + +char const* apply_to_string_literal(PyObject* f) +{ + return call<char const*>(f, "hello, world"); +} + +handle<> apply_to_own_type(handle<> x) +{ + // Tests that we can return handle<> from a callback and that we + // can pass arbitrary handle<T>. + return call<handle<> >(x.get(), type_handle(borrowed(x->ob_type))); +} + +object apply_object_object(PyObject* f, object x) +{ + return call<object>(f, x); +} + +int X::counter; + +BOOST_PYTHON_MODULE(callbacks_ext) +{ + def("apply_object_object", apply_object_object); + def("apply_to_own_type", apply_to_own_type); + def("apply_int_int", apply_int_int); + def("apply_void_int", apply_void_int); + def("apply_X_X", apply_X_X); + def("apply_void_X_ref", apply_void_X_ref); + def("apply_void_X_cref", apply_void_X_cref); + def("apply_void_X_ptr", apply_void_X_ptr); + def("apply_void_X_deep_ptr", apply_void_X_deep_ptr); + + def("apply_X_ptr_handle_cref", apply_X_ptr_handle_cref + , return_value_policy<reference_existing_object>()); + + def("apply_X_ref_handle", apply_X_ref_handle + , return_value_policy<reference_existing_object>()); + + def("apply_cstring_cstring", apply_cstring_cstring); + def("apply_cstring_pyobject", apply_cstring_pyobject); + def("apply_char_char", apply_char_char); + def("apply_to_string_literal", apply_to_string_literal); + + + class_<X>("X", init<int>()) + .def(init<X const&>()) + .def("value", &X::value) + .def("set", &X::set) + ; + + def("x_count", &X::count); +} + +#include "module_tail.cpp" diff --git a/src/boost/libs/python/test/callbacks.py b/src/boost/libs/python/test/callbacks.py new file mode 100644 index 000000000..cf876a89d --- /dev/null +++ b/src/boost/libs/python/test/callbacks.py @@ -0,0 +1,147 @@ +# Copyright David Abrahams 2004. 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) +''' +>>> from callbacks_ext import * + +>>> def double(x): +... return x + x +... +>>> apply_int_int(double, 42) +84 +>>> apply_void_int(double, 42) + +>>> def identity(x): +... return x + +Once we have array conversion support, this test will fail. Er, +succeed<wink>: + +>>> try: apply_to_string_literal(identity) +... except ReferenceError: pass # expected +... else: print('expected an exception!') + +>>> try: apply_X_ref_handle(lambda ignored:X(42), None) +... except ReferenceError: pass # expected +... else: print('expected an exception!') + +>>> x = X(42) +>>> x.y = X(7) +>>> apply_X_ref_handle(lambda z:z.y, x).value() +7 + +>>> x = apply_X_X(identity, X(42)) +>>> x.value() +42 +>>> x_count() +1 +>>> del x +>>> x_count() +0 + +>>> def increment(x): +... x.set(x.value() + 1) +... +>>> x = X(42) +>>> apply_void_X_ref(increment, x) +>>> x.value() +43 + +>>> apply_void_X_cref(increment, x) +>>> x.value() # const-ness is not respected, sorry! +44 + +>>> last_x = 1 +>>> def decrement(x): +... global last_x +... last_x = x +... if x is not None: +... x.set(x.value() - 1) + +>>> apply_void_X_ptr(decrement, x) +>>> x.value() +43 +>>> last_x.value() +43 +>>> increment(last_x) +>>> x.value() +44 +>>> last_x.value() +44 + +>>> apply_void_X_ptr(decrement, None) +>>> assert last_x is None +>>> x.value() +44 + +>>> last_x = 1 +>>> apply_void_X_deep_ptr(decrement, None) +>>> assert last_x is None +>>> x.value() +44 + +>>> apply_void_X_deep_ptr(decrement, x) +>>> x.value() +44 +>>> last_x.value() +43 + +>>> y = apply_X_ref_handle(identity, x) +>>> assert y.value() == x.value() +>>> increment(x) +>>> assert y.value() == x.value() + +>>> y = apply_X_ptr_handle_cref(identity, x) +>>> assert y.value() == x.value() +>>> increment(x) +>>> assert y.value() == x.value() + +>>> y = apply_X_ptr_handle_cref(identity, None) +>>> y + +>>> def new_x(ignored): +... return X(666) +... +>>> try: apply_X_ref_handle(new_x, 1) +... except ReferenceError: pass +... else: print('no error') + +>>> try: apply_X_ptr_handle_cref(new_x, 1) +... except ReferenceError: pass +... else: print('no error') + +>>> try: apply_cstring_cstring(identity, 'hello') +... except ReferenceError: pass +... else: print('no error') + +>>> apply_char_char(identity, 'x') +'x' + +>>> apply_cstring_pyobject(identity, 'hello') +'hello' + +>>> apply_cstring_pyobject(identity, None) + + +>>> apply_char_char(identity, 'x') +'x' + +>>> assert apply_to_own_type(identity) is type(identity) + +>>> assert apply_object_object(identity, identity) is identity +''' + +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/calling_conventions.cpp b/src/boost/libs/python/test/calling_conventions.cpp new file mode 100644 index 000000000..c1c2b5a41 --- /dev/null +++ b/src/boost/libs/python/test/calling_conventions.cpp @@ -0,0 +1,160 @@ +// +// adapted from bind_stdcall_test.cpp - test for bind.hpp + __stdcall (free functions) +// The purpose of this simple test is to determine if a function can be +// called from Python with the various existing calling conventions +// +// Copyright (c) 2001 Peter Dimov and Multi Media Ltd. +// +// 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) +// + +#if !defined(TEST_INCLUDE_RECURSION) + +#define TEST_INCLUDE_RECURSION + +//------------------------------------------------------------------------------ +// this section is the main body of the test extension module + +#if defined(_WIN32) && !defined(_WIN64) +# define BOOST_PYTHON_ENABLE_CDECL +# define BOOST_PYTHON_ENABLE_STDCALL +# define BOOST_PYTHON_ENABLE_FASTCALL +#endif +#include <boost/preprocessor/cat.hpp> +#include <boost/preprocessor/stringize.hpp> +#include <boost/python.hpp> +using namespace boost::python; + +// first define test functions for every calling convention + +#define TEST_DECLARE_FUNCTIONS + +#define TESTED_CALLING_CONVENTION __cdecl +#include "calling_conventions.cpp" +#undef TESTED_CALLING_CONVENTION + +#define TESTED_CALLING_CONVENTION __stdcall +#include "calling_conventions.cpp" +#undef TESTED_CALLING_CONVENTION + +#define TESTED_CALLING_CONVENTION __fastcall +#include "calling_conventions.cpp" +#undef TESTED_CALLING_CONVENTION + +#undef TEST_DECLARE_FUNCTIONS + +// then create a module wrapping the defined functions for every calling convention + +BOOST_PYTHON_MODULE( calling_conventions_ext ) +{ + +#define TEST_WRAP_FUNCTIONS + +#define TESTED_CALLING_CONVENTION __cdecl +#include "calling_conventions.cpp" +#undef TESTED_CALLING_CONVENTION + +#define TESTED_CALLING_CONVENTION __stdcall +#include "calling_conventions.cpp" +#undef TESTED_CALLING_CONVENTION + +#define TESTED_CALLING_CONVENTION __fastcall +#include "calling_conventions.cpp" +#undef TESTED_CALLING_CONVENTION + +#undef TEST_WRAP_FUNCTIONS + +} + +#else // !defined(TEST_INCLUDE_RECURSION) + +//------------------------------------------------------------------------------ +// this section defines the functions to be wrapped + +# if defined(TEST_DECLARE_FUNCTIONS) + +# if !defined(TESTED_CALLING_CONVENTION) +# error "One calling convention must be defined" +# endif // !defined(TESTED_CALLING_CONVENTION) + +namespace BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION) { + + long TESTED_CALLING_CONVENTION f_0() + { + return 17041L; + } + + long TESTED_CALLING_CONVENTION f_1(long a) + { + return a; + } + + long TESTED_CALLING_CONVENTION f_2(long a, long b) + { + return a + 10 * b; + } + + long TESTED_CALLING_CONVENTION f_3(long a, long b, long c) + { + return a + 10 * b + 100 * c; + } + + long TESTED_CALLING_CONVENTION f_4(long a, long b, long c, long d) + { + return a + 10 * b + 100 * c + 1000 * d; + } + + long TESTED_CALLING_CONVENTION f_5(long a, long b, long c, long d, long e) + { + return a + 10 * b + 100 * c + 1000 * d + 10000 * e; + } + + long TESTED_CALLING_CONVENTION f_6(long a, long b, long c, long d, long e, long f) + { + return a + 10 * b + 100 * c + 1000 * d + 10000 * e + 100000 * f; + } + + long TESTED_CALLING_CONVENTION f_7(long a, long b, long c, long d, long e, long f, long g) + { + return a + 10 * b + 100 * c + 1000 * d + 10000 * e + 100000 * f + 1000000 * g; + } + + long TESTED_CALLING_CONVENTION f_8(long a, long b, long c, long d, long e, long f, long g, long h) + { + return a + 10 * b + 100 * c + 1000 * d + 10000 * e + 100000 * f + 1000000 * g + 10000000 * h; + } + + long TESTED_CALLING_CONVENTION f_9(long a, long b, long c, long d, long e, long f, long g, long h, long i) + { + return a + 10 * b + 100 * c + 1000 * d + 10000 * e + 100000 * f + 1000000 * g + 10000000 * h + 100000000 * i; + } + +} // namespace test##TESTED_CALLING_CONVENTION + +# endif // defined(TEST_DECLARE_FUNCTIONS) + +//------------------------------------------------------------------------------ +// this section wraps the functions + +# if defined(TEST_WRAP_FUNCTIONS) + +# if !defined(TESTED_CALLING_CONVENTION) +# error "One calling convention must be defined" +# endif // !defined(TESTED_CALLING_CONVENTION) + + def("f_0" BOOST_PP_STRINGIZE(TESTED_CALLING_CONVENTION), &BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION)::f_0); + def("f_1" BOOST_PP_STRINGIZE(TESTED_CALLING_CONVENTION), &BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION)::f_1); + def("f_2" BOOST_PP_STRINGIZE(TESTED_CALLING_CONVENTION), &BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION)::f_2); + def("f_3" BOOST_PP_STRINGIZE(TESTED_CALLING_CONVENTION), &BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION)::f_3); + def("f_4" BOOST_PP_STRINGIZE(TESTED_CALLING_CONVENTION), &BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION)::f_4); + def("f_5" BOOST_PP_STRINGIZE(TESTED_CALLING_CONVENTION), &BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION)::f_5); + def("f_6" BOOST_PP_STRINGIZE(TESTED_CALLING_CONVENTION), &BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION)::f_6); + def("f_7" BOOST_PP_STRINGIZE(TESTED_CALLING_CONVENTION), &BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION)::f_7); + def("f_8" BOOST_PP_STRINGIZE(TESTED_CALLING_CONVENTION), &BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION)::f_8); + def("f_9" BOOST_PP_STRINGIZE(TESTED_CALLING_CONVENTION), &BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION)::f_9); + +# endif // defined(TEST_WRAP_FUNCTIONS) + +#endif // !defined(TEST_INCLUDE_RECURSION) diff --git a/src/boost/libs/python/test/calling_conventions.py b/src/boost/libs/python/test/calling_conventions.py new file mode 100644 index 000000000..c57142448 --- /dev/null +++ b/src/boost/libs/python/test/calling_conventions.py @@ -0,0 +1,81 @@ +# Copyright Nicolas Lelong, 2010. 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) +""" +>>> from calling_conventions_ext import * +>>> f_0__cdecl() +17041 +>>> f_1__cdecl(1) +1 +>>> f_2__cdecl(1, 2) +21 +>>> f_3__cdecl(1, 2, 3) +321 +>>> f_4__cdecl(1, 2, 3, 4) +4321 +>>> f_5__cdecl(1, 2, 3, 4, 5) +54321 +>>> f_6__cdecl(1, 2, 3, 4, 5, 6) +654321 +>>> f_7__cdecl(1, 2, 3, 4, 5, 6, 7) +7654321 +>>> f_8__cdecl(1, 2, 3, 4, 5, 6, 7, 8) +87654321 +>>> f_9__cdecl(1, 2, 3, 4, 5, 6, 7, 8, 9) +987654321 +>>> f_0__stdcall() +17041 +>>> f_1__stdcall(1) +1 +>>> f_2__stdcall(1, 2) +21 +>>> f_3__stdcall(1, 2, 3) +321 +>>> f_4__stdcall(1, 2, 3, 4) +4321 +>>> f_5__stdcall(1, 2, 3, 4, 5) +54321 +>>> f_6__stdcall(1, 2, 3, 4, 5, 6) +654321 +>>> f_7__stdcall(1, 2, 3, 4, 5, 6, 7) +7654321 +>>> f_8__stdcall(1, 2, 3, 4, 5, 6, 7, 8) +87654321 +>>> f_9__stdcall(1, 2, 3, 4, 5, 6, 7, 8, 9) +987654321 +>>> f_0__fastcall() +17041 +>>> f_1__fastcall(1) +1 +>>> f_2__fastcall(1, 2) +21 +>>> f_3__fastcall(1, 2, 3) +321 +>>> f_4__fastcall(1, 2, 3, 4) +4321 +>>> f_5__fastcall(1, 2, 3, 4, 5) +54321 +>>> f_6__fastcall(1, 2, 3, 4, 5, 6) +654321 +>>> f_7__fastcall(1, 2, 3, 4, 5, 6, 7) +7654321 +>>> f_8__fastcall(1, 2, 3, 4, 5, 6, 7, 8) +87654321 +>>> f_9__fastcall(1, 2, 3, 4, 5, 6, 7, 8, 9) +987654321 +""" + +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/calling_conventions_mf.cpp b/src/boost/libs/python/test/calling_conventions_mf.cpp new file mode 100644 index 000000000..83a97acfe --- /dev/null +++ b/src/boost/libs/python/test/calling_conventions_mf.cpp @@ -0,0 +1,161 @@ +// +// adapted from bind_stdcall_mf_test.cpp - test for bind.hpp + __stdcall (free functions) +// The purpose of this simple test is to determine if a function can be +// called from Python with the various existing calling conventions +// +// Copyright (c) 2001 Peter Dimov and Multi Media Ltd. +// +// 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) +// + +#if !defined(TEST_INCLUDE_RECURSION) + +#define TEST_INCLUDE_RECURSION + +//------------------------------------------------------------------------------ +// this section is the main body of the test extension module + +#if defined(_WIN32) && !defined(_WIN64) +# define BOOST_PYTHON_ENABLE_CDECL +# define BOOST_PYTHON_ENABLE_STDCALL +# define BOOST_PYTHON_ENABLE_FASTCALL +#endif +#include <boost/preprocessor/cat.hpp> +#include <boost/preprocessor/stringize.hpp> +#include <boost/python.hpp> +using namespace boost::python; + +// first define test functions for every calling convention + +#define TEST_DECLARE_FUNCTIONS + +#define TESTED_CALLING_CONVENTION __cdecl +#include "calling_conventions_mf.cpp" +#undef TESTED_CALLING_CONVENTION + +#define TESTED_CALLING_CONVENTION __stdcall +#include "calling_conventions_mf.cpp" +#undef TESTED_CALLING_CONVENTION + +#define TESTED_CALLING_CONVENTION __fastcall +#include "calling_conventions_mf.cpp" +#undef TESTED_CALLING_CONVENTION + +#undef TEST_DECLARE_FUNCTIONS + +// then create a module wrapping the defined functions for every calling convention + +BOOST_PYTHON_MODULE( calling_conventions_mf_ext ) +{ + +#define TEST_WRAP_FUNCTIONS + +#define TESTED_CALLING_CONVENTION __cdecl +#include "calling_conventions_mf.cpp" +#undef TESTED_CALLING_CONVENTION + +#define TESTED_CALLING_CONVENTION __stdcall +#include "calling_conventions_mf.cpp" +#undef TESTED_CALLING_CONVENTION + +#define TESTED_CALLING_CONVENTION __fastcall +#include "calling_conventions_mf.cpp" +#undef TESTED_CALLING_CONVENTION + +#undef TEST_WRAP_FUNCTIONS + +} + +#else // !defined(TEST_INCLUDE_RECURSION) + +//------------------------------------------------------------------------------ +// this section defines the functions to be wrapped + +# if defined(TEST_DECLARE_FUNCTIONS) + +# if !defined(TESTED_CALLING_CONVENTION) +# error "One calling convention must be defined" +# endif // !defined(TESTED_CALLING_CONVENTION) + +namespace BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION) { + +struct X +{ + mutable unsigned int hash; + + X(): hash(0) {} + + void TESTED_CALLING_CONVENTION f0() { f1(17); } + void TESTED_CALLING_CONVENTION g0() const { g1(17); } + + void TESTED_CALLING_CONVENTION f1(int a1) { hash = (hash * 17041 + a1) % 32768; } + void TESTED_CALLING_CONVENTION g1(int a1) const { hash = (hash * 17041 + a1 * 2) % 32768; } + + void TESTED_CALLING_CONVENTION f2(int a1, int a2) { f1(a1); f1(a2); } + void TESTED_CALLING_CONVENTION g2(int a1, int a2) const { g1(a1); g1(a2); } + + void TESTED_CALLING_CONVENTION f3(int a1, int a2, int a3) { f2(a1, a2); f1(a3); } + void TESTED_CALLING_CONVENTION g3(int a1, int a2, int a3) const { g2(a1, a2); g1(a3); } + + void TESTED_CALLING_CONVENTION f4(int a1, int a2, int a3, int a4) { f3(a1, a2, a3); f1(a4); } + void TESTED_CALLING_CONVENTION g4(int a1, int a2, int a3, int a4) const { g3(a1, a2, a3); g1(a4); } + + void TESTED_CALLING_CONVENTION f5(int a1, int a2, int a3, int a4, int a5) { f4(a1, a2, a3, a4); f1(a5); } + void TESTED_CALLING_CONVENTION g5(int a1, int a2, int a3, int a4, int a5) const { g4(a1, a2, a3, a4); g1(a5); } + + void TESTED_CALLING_CONVENTION f6(int a1, int a2, int a3, int a4, int a5, int a6) { f5(a1, a2, a3, a4, a5); f1(a6); } + void TESTED_CALLING_CONVENTION g6(int a1, int a2, int a3, int a4, int a5, int a6) const { g5(a1, a2, a3, a4, a5); g1(a6); } + + void TESTED_CALLING_CONVENTION f7(int a1, int a2, int a3, int a4, int a5, int a6, int a7) { f6(a1, a2, a3, a4, a5, a6); f1(a7); } + void TESTED_CALLING_CONVENTION g7(int a1, int a2, int a3, int a4, int a5, int a6, int a7) const { g6(a1, a2, a3, a4, a5, a6); g1(a7); } + + void TESTED_CALLING_CONVENTION f8(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) { f7(a1, a2, a3, a4, a5, a6, a7); f1(a8); } + void TESTED_CALLING_CONVENTION g8(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) const { g7(a1, a2, a3, a4, a5, a6, a7); g1(a8); } +}; + +} // namespace BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION) + +# endif // defined(TEST_DECLARE_FUNCTIONS) + +//------------------------------------------------------------------------------ +// this section wraps the functions + +# if defined(TEST_WRAP_FUNCTIONS) + +# if !defined(TESTED_CALLING_CONVENTION) +# error "One calling convention must be defined" +# endif // !defined(TESTED_CALLING_CONVENTION) + +{ + + typedef BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION)::X X; + + class_<X>("X" BOOST_PP_STRINGIZE(TESTED_CALLING_CONVENTION)) + .def("f0", &X::f0) + .def("g0", &X::g0) + .def("f1", &X::f1) + .def("g1", &X::g1) + .def("f2", &X::f2) + .def("g2", &X::g2) + .def("f3", &X::f3) + .def("g3", &X::g3) + .def("f4", &X::f4) + .def("g4", &X::g4) + .def("f5", &X::f5) + .def("g5", &X::g5) + .def("f6", &X::f6) + .def("g6", &X::g6) + .def("f7", &X::f7) + .def("g7", &X::g7) + .def("f8", &X::f8) + .def("g8", &X::g8) + .def_readonly("hash", &X::hash) + ; + +} + +# endif // defined(TEST_WRAP_FUNCTIONS) + +#endif // !defined(TEST_INCLUDE_RECURSION) diff --git a/src/boost/libs/python/test/calling_conventions_mf.py b/src/boost/libs/python/test/calling_conventions_mf.py new file mode 100644 index 000000000..7e28484b9 --- /dev/null +++ b/src/boost/libs/python/test/calling_conventions_mf.py @@ -0,0 +1,84 @@ +# Copyright Nicolas Lelong, 2010. 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) +""" +>>> from calling_conventions_mf_ext import * +>>> x = X__cdecl() +>>> x.f0() +>>> x.g0() +>>> x.f1(1) +>>> x.g1(1) +>>> x.f2(1, 2) +>>> x.g2(1, 2) +>>> x.f3(1, 2, 3) +>>> x.g3(1, 2, 3) +>>> x.f4(1, 2, 3, 4) +>>> x.g4(1, 2, 3, 4) +>>> x.f5(1, 2, 3, 4, 5) +>>> x.g5(1, 2, 3, 4, 5) +>>> x.f6(1, 2, 3, 4, 5, 6) +>>> x.g6(1, 2, 3, 4, 5, 6) +>>> x.f7(1, 2, 3, 4, 5, 6, 7) +>>> x.g7(1, 2, 3, 4, 5, 6, 7) +>>> x.f8(1, 2, 3, 4, 5, 6, 7, 8) +>>> x.g8(1, 2, 3, 4, 5, 6, 7, 8) +>>> x.hash +2155 +>>> x = X__stdcall() +>>> x.f0() +>>> x.g0() +>>> x.f1(1) +>>> x.g1(1) +>>> x.f2(1, 2) +>>> x.g2(1, 2) +>>> x.f3(1, 2, 3) +>>> x.g3(1, 2, 3) +>>> x.f4(1, 2, 3, 4) +>>> x.g4(1, 2, 3, 4) +>>> x.f5(1, 2, 3, 4, 5) +>>> x.g5(1, 2, 3, 4, 5) +>>> x.f6(1, 2, 3, 4, 5, 6) +>>> x.g6(1, 2, 3, 4, 5, 6) +>>> x.f7(1, 2, 3, 4, 5, 6, 7) +>>> x.g7(1, 2, 3, 4, 5, 6, 7) +>>> x.f8(1, 2, 3, 4, 5, 6, 7, 8) +>>> x.g8(1, 2, 3, 4, 5, 6, 7, 8) +>>> x.hash +2155 +>>> x = X__fastcall() +>>> x.f0() +>>> x.g0() +>>> x.f1(1) +>>> x.g1(1) +>>> x.f2(1, 2) +>>> x.g2(1, 2) +>>> x.f3(1, 2, 3) +>>> x.g3(1, 2, 3) +>>> x.f4(1, 2, 3, 4) +>>> x.g4(1, 2, 3, 4) +>>> x.f5(1, 2, 3, 4, 5) +>>> x.g5(1, 2, 3, 4, 5) +>>> x.f6(1, 2, 3, 4, 5, 6) +>>> x.g6(1, 2, 3, 4, 5, 6) +>>> x.f7(1, 2, 3, 4, 5, 6, 7) +>>> x.g7(1, 2, 3, 4, 5, 6, 7) +>>> x.f8(1, 2, 3, 4, 5, 6, 7, 8) +>>> x.g8(1, 2, 3, 4, 5, 6, 7, 8) +>>> x.hash +2155 +""" + +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/class.cpp b/src/boost/libs/python/test/class.cpp new file mode 100644 index 000000000..078bebdf6 --- /dev/null +++ b/src/boost/libs/python/test/class.cpp @@ -0,0 +1,28 @@ +// 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) +#include <boost/python/module.hpp> +#include <boost/python/def.hpp> +#include <boost/python/object.hpp> +#include <boost/python/class.hpp> + +using namespace boost::python; + +struct X +{ + int x; + X(int n) : x(n) { } +}; + +int x_function(X& x) +{ return x.x; +} + + +BOOST_PYTHON_MODULE(class_ext) +{ + class_<X>("X", init<int>()); + def("x_function", x_function); +} + +#include "module_tail.cpp" diff --git a/src/boost/libs/python/test/class.py b/src/boost/libs/python/test/class.py new file mode 100644 index 000000000..15594a105 --- /dev/null +++ b/src/boost/libs/python/test/class.py @@ -0,0 +1,40 @@ +# 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) +''' +>>> from class_ext import * + +Ensure sanity: + + >>> x = X(42) + >>> x_function(x) + 42 + +Demonstrate extraction in the presence of metaclass changes: + + >>> class MetaX(X.__class__): + ... def __new__(cls, *args): + ... return super(MetaX, cls).__new__(cls, *args) + >>> class XPlusMetatype(X): + ... __metaclass__ = MetaX + >>> x = XPlusMetatype(42) + >>> x_function(x) + 42 + + +''' + +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/cltree.cpp b/src/boost/libs/python/test/cltree.cpp new file mode 100644 index 000000000..518ae37fe --- /dev/null +++ b/src/boost/libs/python/test/cltree.cpp @@ -0,0 +1,74 @@ +// Copyright David Abrahams 2005. 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) + +#include <boost/python/module.hpp> +#include <boost/python/def.hpp> +#include <boost/python/class.hpp> +#include <boost/utility.hpp> + +/* Non-modifiable definitions */ + +class basic { +public: + basic() { name = "cltree.basic"; } + std::string repr() { return name+"()"; } +protected: + std::string name; +}; + +class constant: public basic { +public: + constant() { name = "cltree.constant"; } +}; + +class symbol: public basic { +public: + symbol() { name = "cltree.symbol"; } +}; + +class variable: public basic { +public: + variable() { name = "cltree.variable"; } +}; + +/* EOF: Non-modifiable definitions */ + +class symbol_wrapper: public symbol { +public: + symbol_wrapper(PyObject* /*self*/): symbol() { + name = "cltree.wrapped_symbol"; + } +}; + +class variable_wrapper: public variable { +public: + variable_wrapper(PyObject* /*self*/): variable() { + name = "cltree.wrapped_variable"; + } + + // This constructor is introduced only because cannot use + // boost::noncopyable, see below. + variable_wrapper(PyObject* /*self*/,variable v): variable(v) {} + +}; + +BOOST_PYTHON_MODULE(cltree) +{ + boost::python::class_<basic>("basic") + .def("__repr__",&basic::repr) + ; + + boost::python::class_<constant, boost::python::bases<basic>, boost::noncopyable>("constant") + ; + + + boost::python::class_<symbol, symbol_wrapper, boost::noncopyable>("symbol") + ; + + boost::python::class_<variable, boost::python::bases<basic>, variable_wrapper>("variable") + ; +} + +#include "module_tail.cpp" + diff --git a/src/boost/libs/python/test/complicated.hpp b/src/boost/libs/python/test/complicated.hpp new file mode 100644 index 000000000..5ff19aea0 --- /dev/null +++ b/src/boost/libs/python/test/complicated.hpp @@ -0,0 +1,38 @@ +// Copyright David Abrahams 2001. +// 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) +#ifndef COMPLICATED_DWA20011215_HPP +# define COMPLICATED_DWA20011215_HPP +# include <iostream> + +# include "simple_type.hpp" + +struct complicated +{ + complicated(simple const&, int = 0); + ~complicated(); + + int get_n() const; + + char* s; + int n; +}; + +inline complicated::complicated(simple const&s, int _n) + : s(s.s), n(_n) +{ + std::cout << "constructing complicated: " << this->s << ", " << _n << std::endl; +} + +inline complicated::~complicated() +{ + std::cout << "destroying complicated: " << this->s << ", " << n << std::endl; +} + +inline int complicated::get_n() const +{ + return n; +} + +#endif // COMPLICATED_DWA20011215_HPP diff --git a/src/boost/libs/python/test/const_argument.cpp b/src/boost/libs/python/test/const_argument.cpp new file mode 100644 index 000000000..279c3dc1a --- /dev/null +++ b/src/boost/libs/python/test/const_argument.cpp @@ -0,0 +1,28 @@ +/* Copyright 2004 Jonathan Brandmeyer + * Use, modification and distribution are subject to 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) + * + * The purpose of this test is to determine if a function can be called from + * Python with a const value type as an argument, and whether or not the + * presence of a prototype without the cv-qualifier will work around the + * compiler's bug. + */ +#include <boost/python.hpp> +using namespace boost::python; + + +#if BOOST_WORKAROUND(BOOST_MSVC, == 1200) +bool accept_const_arg( object ); +#endif + +bool accept_const_arg( const object ) +{ + return true; +} + + +BOOST_PYTHON_MODULE( const_argument_ext ) +{ + def( "accept_const_arg", accept_const_arg ); +} diff --git a/src/boost/libs/python/test/const_argument.py b/src/boost/libs/python/test/const_argument.py new file mode 100644 index 000000000..1d241953b --- /dev/null +++ b/src/boost/libs/python/test/const_argument.py @@ -0,0 +1,23 @@ +# Copyright Jonathan Brandmeyer, 2004. 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) +""" +>>> from const_argument_ext import * +>>> accept_const_arg(1) +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/copy_ctor_mutates_rhs.cpp b/src/boost/libs/python/test/copy_ctor_mutates_rhs.cpp new file mode 100644 index 000000000..41eac495e --- /dev/null +++ b/src/boost/libs/python/test/copy_ctor_mutates_rhs.cpp @@ -0,0 +1,23 @@ +// Copyright David Abrahams 2003. +// 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) +#include <boost/python/detail/copy_ctor_mutates_rhs.hpp> +#include <boost/static_assert.hpp> +#include <memory> +#include <string> + +struct foo +{ + operator std::auto_ptr<int>&() const; +}; + +int main() +{ + using namespace boost::python::detail; + BOOST_STATIC_ASSERT(!copy_ctor_mutates_rhs<int>::value); + BOOST_STATIC_ASSERT(copy_ctor_mutates_rhs<std::auto_ptr<int> >::value); + BOOST_STATIC_ASSERT(!copy_ctor_mutates_rhs<std::string>::value); + BOOST_STATIC_ASSERT(!copy_ctor_mutates_rhs<foo>::value); + return 0; +} diff --git a/src/boost/libs/python/test/crossmod_exception.py b/src/boost/libs/python/test/crossmod_exception.py new file mode 100644 index 000000000..4820f29e9 --- /dev/null +++ b/src/boost/libs/python/test/crossmod_exception.py @@ -0,0 +1,19 @@ +# Copyright (C) 2003 Rational Discovery LLC. 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) + +print("running...") + +import crossmod_exception_a +import crossmod_exception_b + +try: + crossmod_exception_b.tossit() +except IndexError: + pass +try: + crossmod_exception_a.tossit() +except IndexError: + pass + +print("Done.") diff --git a/src/boost/libs/python/test/crossmod_exception_a.cpp b/src/boost/libs/python/test/crossmod_exception_a.cpp new file mode 100644 index 000000000..9526129af --- /dev/null +++ b/src/boost/libs/python/test/crossmod_exception_a.cpp @@ -0,0 +1,18 @@ +// Copyright (C) 2003 Rational Discovery LLC +// 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) + +#include <boost/python.hpp> + +namespace python = boost::python; + +void tossit(){ + PyErr_SetString(PyExc_IndexError,"a-blah!"); + throw python::error_already_set(); +} + +BOOST_PYTHON_MODULE(crossmod_exception_a) +{ + python::def("tossit",tossit); +} diff --git a/src/boost/libs/python/test/crossmod_exception_b.cpp b/src/boost/libs/python/test/crossmod_exception_b.cpp new file mode 100644 index 000000000..e2ea491ca --- /dev/null +++ b/src/boost/libs/python/test/crossmod_exception_b.cpp @@ -0,0 +1,18 @@ +// Copyright (C) 2003 Rational Discovery LLC +// 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) + +#include <boost/python.hpp> + +namespace python = boost::python; + +void tossit(){ + PyErr_SetString(PyExc_IndexError,"b-blah!"); + throw python::error_already_set(); +} + +BOOST_PYTHON_MODULE(crossmod_exception_b) +{ + python::def("tossit",tossit); +} diff --git a/src/boost/libs/python/test/crossmod_opaque.py b/src/boost/libs/python/test/crossmod_opaque.py new file mode 100644 index 000000000..533ac16fe --- /dev/null +++ b/src/boost/libs/python/test/crossmod_opaque.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +# Copyright Gottfried Ganßauge 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) + +if __name__ == '__main__': + print("running...") + + import crossmod_opaque_a + import crossmod_opaque_b + + crossmod_opaque_a.get() + crossmod_opaque_b.get() + + print("Done.") diff --git a/src/boost/libs/python/test/crossmod_opaque_a.cpp b/src/boost/libs/python/test/crossmod_opaque_a.cpp new file mode 100644 index 000000000..62ed43311 --- /dev/null +++ b/src/boost/libs/python/test/crossmod_opaque_a.cpp @@ -0,0 +1,26 @@ +// Copyright Gottfried Ganßauge 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) +# include <boost/python/return_opaque_pointer.hpp> +# include <boost/python/def.hpp> +# include <boost/python/module.hpp> +# include <boost/python/return_value_policy.hpp> + +typedef struct opaque_ *opaque; + +opaque the_op = ((opaque) 0x47110815); + +opaque get() { return the_op; } + +BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(opaque_) + +namespace bpl = boost::python; + +BOOST_PYTHON_MODULE(crossmod_opaque_a) +{ + bpl::def ( + "get", + &::get, + bpl::return_value_policy<bpl::return_opaque_pointer>()); +} diff --git a/src/boost/libs/python/test/crossmod_opaque_b.cpp b/src/boost/libs/python/test/crossmod_opaque_b.cpp new file mode 100644 index 000000000..3d661339c --- /dev/null +++ b/src/boost/libs/python/test/crossmod_opaque_b.cpp @@ -0,0 +1,26 @@ +// Copyright Gottfried Ganßauge 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) +# include <boost/python/return_opaque_pointer.hpp> +# include <boost/python/def.hpp> +# include <boost/python/module.hpp> +# include <boost/python/return_value_policy.hpp> + +typedef struct opaque_ *opaque; + +opaque the_op = ((opaque) 0x47110815); + +opaque get() { return the_op; } + +BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(opaque_) + +namespace bpl = boost::python; + +BOOST_PYTHON_MODULE(crossmod_opaque_b) +{ + bpl::def ( + "get", + &::get, + bpl::return_value_policy<bpl::return_opaque_pointer>()); +} diff --git a/src/boost/libs/python/test/data_members.cpp b/src/boost/libs/python/test/data_members.cpp new file mode 100644 index 000000000..6d2cc7bd4 --- /dev/null +++ b/src/boost/libs/python/test/data_members.cpp @@ -0,0 +1,132 @@ +// Copyright David Abrahams 2002. +// 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) +#include <boost/python/class.hpp> +#include <boost/python/module.hpp> +#include <boost/python/return_value_policy.hpp> +#include <boost/python/return_by_value.hpp> +#include "test_class.hpp" + +#if defined(_AIX) && defined(__EDG_VERSION__) && __EDG_VERSION__ < 245 +# include <iostream> // works around a KCC intermediate code generation bug +#endif + + +using namespace boost::python; + +typedef test_class<> X; + +struct Y : test_class<1> +{ + Y(int v) : test_class<1>(v) {} + Y& operator=(Y const& rhs) { x = rhs.x; return *this; } + bool q; +}; + +double get_fair_value(X const& x) { return x.value(); } + + +struct VarBase +{ + VarBase(std::string name_) : name(name_) {} + + std::string const name; + std::string get_name1() const { return name; } + +}; + +struct Var : VarBase +{ + Var(std::string name_) : VarBase(name_), value(), name2(name.c_str()), y(6) {} + std::string const& get_name2() const { return name; } + float value; + char const* name2; + Y y; + + static int static1; + static Y static2; +}; + +int Var::static1 = 0; +Y Var::static2(0); + +// Compilability regression tests +namespace boost_python_test +{ + struct trivial + { + trivial() : value(123) {} + double value; + }; + + struct Color3 + { + static const Color3 black; + }; + + const Color3 Color3::black +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + = {} +#endif + ; + + void compilability_test() + { + class_<trivial>("trivial") + .add_property("property", make_getter(&trivial::value, return_value_policy<return_by_value>())) + .def_readonly("readonly", &trivial::value) + ; + + class_< Color3 >("Color3", init< const Color3 & >()) + .def_readonly("BLACK", &Color3::black) // line 17 + ; + } +} + +BOOST_PYTHON_MODULE(data_members_ext) +{ + using namespace boost_python_test; + class_<X>("X", init<int>()) + .def("value", &X::value) + .def("set", &X::set) + .def_readonly("x", &X::x) + .add_property("fair_value", get_fair_value) + ; + + class_<Y>("Y", init<int>()) + .def("value", &Y::value) + .def("set", &Y::set) + .def_readwrite("x", &Y::x) + .def_readwrite("q", &Y::q) + ; + + class_<Var>("Var", init<std::string>()) + .def_readonly("name", &Var::name) + .def_readonly("name2", &Var::name2) + .def_readwrite("value", &Var::value) + .def_readonly("y", &Var::y) + + // Test return_by_value for plain values and for + // pointers... return_by_value was implemented as a + // side-effect of implementing data member support, so it made + // sense to add the test here. + .def("get_name1", &Var::get_name1, return_value_policy<return_by_value>()) + .def("get_name2", &Var::get_name2, return_value_policy<return_by_value>()) + + .add_property("name3", &Var::get_name1) + + // Test static data members + .def_readonly("ro1a", &Var::static1) + .def_readonly("ro1b", Var::static1) + .def_readwrite("rw1a", &Var::static1) + .def_readwrite("rw1b", Var::static1) + + .def_readonly("ro2a", &Var::static2) + .def_readonly("ro2b", Var::static2) + .def_readwrite("rw2a", &Var::static2) + .def_readwrite("rw2b", Var::static2) + ; +} + +#include "module_tail.cpp" diff --git a/src/boost/libs/python/test/data_members.py b/src/boost/libs/python/test/data_members.py new file mode 100644 index 000000000..74b655eb5 --- /dev/null +++ b/src/boost/libs/python/test/data_members.py @@ -0,0 +1,215 @@ +# Copyright David Abrahams 2004. 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) +''' +>>> from data_members_ext import * + + ---- Test static data members --- + +>>> v = Var('slim shady') + +>>> Var.ro2a.x +0 +>>> Var.ro2b.x +0 +>>> Var.rw2a.x +0 +>>> Var.rw2b.x +0 +>>> v.ro2a.x +0 +>>> v.ro2b.x +0 +>>> v.rw2a.x +0 +>>> v.rw2b.x +0 +>>> Var.rw2a.x = 777 +>>> Var.ro2a.x +777 +>>> Var.ro2b.x +777 +>>> Var.rw2a.x +777 +>>> Var.rw2b.x +777 +>>> v.ro2a.x +777 +>>> v.ro2b.x +777 +>>> v.rw2a.x +777 +>>> v.rw2b.x +777 +>>> Var.rw2b = Y(888) + +>>> y = Y(99) +>>> y.q = True +>>> y.q +True +>>> y.q = False +>>> y.q +False + +>>> Var.ro2a.x +888 +>>> Var.ro2b.x +888 +>>> Var.rw2a.x +888 +>>> Var.rw2b.x +888 +>>> v.ro2a.x +888 +>>> v.ro2b.x +888 +>>> v.rw2a.x +888 +>>> v.rw2b.x +888 +>>> v.rw2b.x = 999 +>>> Var.ro2a.x +999 +>>> Var.ro2b.x +999 +>>> Var.rw2a.x +999 +>>> Var.rw2b.x +999 +>>> v.ro2a.x +999 +>>> v.ro2b.x +999 +>>> v.rw2a.x +999 +>>> v.rw2b.x +999 + + +>>> Var.ro1a +0 +>>> Var.ro1b +0 +>>> Var.rw1a +0 +>>> Var.rw1b +0 +>>> v.ro1a +0 +>>> v.ro1b +0 +>>> v.rw1a +0 +>>> v.rw1b +0 +>>> Var.rw1a = 777 +>>> Var.ro1a +777 +>>> Var.ro1b +777 +>>> Var.rw1a +777 +>>> Var.rw1b +777 +>>> v.ro1a +777 +>>> v.ro1b +777 +>>> v.rw1a +777 +>>> v.rw1b +777 +>>> Var.rw1b = 888 +>>> Var.ro1a +888 +>>> Var.ro1b +888 +>>> Var.rw1a +888 +>>> Var.rw1b +888 +>>> v.ro1a +888 +>>> v.ro1b +888 +>>> v.rw1a +888 +>>> v.rw1b +888 +>>> v.rw1b = 999 +>>> Var.ro1a +999 +>>> Var.ro1b +999 +>>> Var.rw1a +999 +>>> Var.rw1b +999 +>>> v.ro1a +999 +>>> v.ro1b +999 +>>> v.rw1a +999 +>>> v.rw1b +999 + + + + ----------------- + +>>> x = X(42) +>>> x.x +42 +>>> try: x.x = 77 +... except AttributeError: pass +... else: print('no error') + +>>> x.fair_value +42.0 +>>> y = Y(69) +>>> y.x +69 +>>> y.x = 77 +>>> y.x +77 + +>>> v = Var("pi") +>>> v.value = 3.14 +>>> v.name +'pi' +>>> v.name2 +'pi' + +>>> v.get_name1() +'pi' + +>>> v.get_name2() +'pi' + +>>> v.y.x +6 +>>> v.y.x = -7 +>>> v.y.x +-7 + +>>> v.name3 +'pi' + + +''' + +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/defaults.cpp b/src/boost/libs/python/test/defaults.cpp new file mode 100644 index 000000000..6d87e5d6e --- /dev/null +++ b/src/boost/libs/python/test/defaults.cpp @@ -0,0 +1,173 @@ +// Copyright David Abrahams 2002. +// 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) + +#include <boost/python/def.hpp> +#include <boost/python/module.hpp> +#include <boost/python/class.hpp> +#include <boost/python/tuple.hpp> +#include <boost/python/list.hpp> +#include <boost/python/overloads.hpp> +#include <boost/python/return_internal_reference.hpp> + +#if defined(_AIX) && defined(__EDG_VERSION__) && __EDG_VERSION__ < 245 +# include <iostream> // works around a KCC intermediate code generation bug +#endif + +using namespace boost::python; +namespace bpl = boost::python; + +char const* const format = "int(%s); char(%s); string(%s); double(%s); "; + +/////////////////////////////////////////////////////////////////////////////// +// +// Overloaded functions +// +/////////////////////////////////////////////////////////////////////////////// +object +bar(int a, char b, std::string c, double d) +{ + return format % bpl::make_tuple(a, b, c, d); +} + +object +bar(int a, char b, std::string c) +{ + return format % bpl::make_tuple(a, b, c, 0.0); +} + +object +bar(int a, char b) +{ + return format % bpl::make_tuple(a, b, "default", 0.0); +} + +object +bar(int a) +{ + return format % bpl::make_tuple(a, 'D', "default", 0.0); +} + +BOOST_PYTHON_FUNCTION_OVERLOADS(bar_stubs, bar, 1, 4) + +/////////////////////////////////////////////////////////////////////////////// +// +// Functions with default arguments +// +/////////////////////////////////////////////////////////////////////////////// +object +foo(int a, char b = 'D', std::string c = "default", double d = 0.0) +{ + return format % bpl::make_tuple(a, b, c, d); +} + +BOOST_PYTHON_FUNCTION_OVERLOADS(foo_stubs, foo, 1, 4) + +/////////////////////////////////////////////////////////////////////////////// +// +// Overloaded member functions with default arguments +// +/////////////////////////////////////////////////////////////////////////////// +struct Y { + + Y() {} + + object + get_state() const + { + return format % bpl::make_tuple(a, b, c, d); + } + + int a; char b; std::string c; double d; +}; + + +struct X { + + X() {} + + X(int a, char b = 'D', std::string c = "constructor", double d = 0.0) + : state(format % bpl::make_tuple(a, b, c, d)) + {} + + X(std::string s, bool b) + : state("Got exactly two arguments from constructor: string(%s); bool(%s); " % bpl::make_tuple(s, b*1)) + {} + + object + bar(int a, char b = 'D', std::string c = "default", double d = 0.0) const + { + return format % bpl::make_tuple(a, b, c, d); + } + + Y const& + bar2(int a = 0, char b = 'D', std::string c = "default", double d = 0.0) + { + // tests zero arg member function and return_internal_reference policy + y.a = a; + y.b = b; + y.c = c; + y.d = d; + return y; + } + + object + foo(int a, bool b=false) const + { + return "int(%s); bool(%s); " % bpl::make_tuple(a, b*1); + } + + object + foo(std::string a, bool b=false) const + { + return "string(%s); bool(%s); " % bpl::make_tuple(a, b*1); + } + + object + foo(list a, list b, bool c=false) const + { + return "list(%s); list(%s); bool(%s); " % bpl::make_tuple(a, b, c*1); + } + + object + get_state() const + { + return state; + } + + Y y; + object state; +}; + +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(X_bar_stubs, bar, 1, 4) +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(X_bar_stubs2, bar2, 0, 4) +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(X_foo_2_stubs, foo, 1, 2) +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(X_foo_3_stubs, foo, 2, 3) + +/////////////////////////////////////////////////////////////////////////////// + +BOOST_PYTHON_MODULE(defaults_ext) +{ + def("foo", foo, foo_stubs()); + def("bar", (object(*)(int, char, std::string, double))0, bar_stubs()); + + class_<Y>("Y", init<>("doc of Y init")) // this should work + .def("get_state", &Y::get_state) + ; + + class_<X>("X",no_init) + + .def(init<optional<int, char, std::string, double> >("doc of init", args("self", "a", "b", "c", "d"))) + .def(init<std::string, bool>(args("self", "s", "b"))[default_call_policies()]) // what's a good policy here? + .def("get_state", &X::get_state) + .def("bar", &X::bar, X_bar_stubs()) + .def("bar2", &X::bar2, X_bar_stubs2("doc of X::bar2")[return_internal_reference<>()]) + .def("foo", (object(X::*)(std::string, bool) const)0, X_foo_2_stubs()) + .def("foo", (object(X::*)(int, bool) const)0, X_foo_2_stubs()) + .def("foo", (object(X::*)(list, list, bool) const)0, X_foo_3_stubs()) + ; +} + +#include "module_tail.cpp" + diff --git a/src/boost/libs/python/test/defaults.py b/src/boost/libs/python/test/defaults.py new file mode 100644 index 000000000..cf3cfd38f --- /dev/null +++ b/src/boost/libs/python/test/defaults.py @@ -0,0 +1,140 @@ +# Copyright David Abrahams 2004. 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) +""" +>>> from defaults_ext import * +>>> bar(1) +'int(1); char(D); string(default); double(0.0); ' + +>>> bar(2, 'X') +'int(2); char(X); string(default); double(0.0); ' + +>>> bar(3, 'Y', "Hello World") +'int(3); char(Y); string(Hello World); double(0.0); ' + +>>> bar(4, 'Z', "Hi There", 3.3) +'int(4); char(Z); string(Hi There); double(3.3); ' + +>>> foo(1) +'int(1); char(D); string(default); double(0.0); ' + +>>> foo(2, 'X') +'int(2); char(X); string(default); double(0.0); ' + +>>> foo(3, 'Y', "Hello World") +'int(3); char(Y); string(Hello World); double(0.0); ' + +>>> foo(4, 'Z', "Hi There", 3.3) +'int(4); char(Z); string(Hi There); double(3.3); ' + +>>> x = X() +>>> x.bar(1) +'int(1); char(D); string(default); double(0.0); ' + +>>> x.bar(2, 'X') +'int(2); char(X); string(default); double(0.0); ' + +>>> x.bar(3, 'Y', "Hello World") +'int(3); char(Y); string(Hello World); double(0.0); ' + +>>> x.bar(4, 'Z', "Hi There", 3.3) +'int(4); char(Z); string(Hi There); double(3.3); ' + +>>> x.foo(5) +'int(5); bool(0); ' + +>>> x.foo(6, 0) +'int(6); bool(0); ' + +>>> x.foo(7, 1) +'int(7); bool(1); ' + +>>> x.foo("A") +'string(A); bool(0); ' + +>>> x.foo("B", False) +'string(B); bool(0); ' + +>>> x.foo("C", True) +'string(C); bool(1); ' + +>>> x.foo([0,1,2], [2,3,4]) +'list([0, 1, 2]); list([2, 3, 4]); bool(0); ' + +>>> x.foo([0,1,2], [2,3,4], False) +'list([0, 1, 2]); list([2, 3, 4]); bool(0); ' + +>>> x.foo([0,1,2], [2,3,4], True) +'list([0, 1, 2]); list([2, 3, 4]); bool(1); ' + +>>> x = X(1) +>>> x.get_state() +'int(1); char(D); string(constructor); double(0.0); ' + +>>> x = X(1, 'X') +>>> x.get_state() +'int(1); char(X); string(constructor); double(0.0); ' + +>>> x = X(1, 'X', "Yabadabadoo") +>>> x.get_state() +'int(1); char(X); string(Yabadabadoo); double(0.0); ' + +>>> x = X(1, 'X', "Phoenix", 3.65) +>>> x.get_state() +'int(1); char(X); string(Phoenix); double(3.65); ' + +>>> x.bar2().get_state() +'int(0); char(D); string(default); double(0.0); ' + +>>> x.bar2(1).get_state() +'int(1); char(D); string(default); double(0.0); ' + +>>> x.bar2(1, 'K').get_state() +'int(1); char(K); string(default); double(0.0); ' + +>>> x.bar2(1, 'K', "Kim").get_state() +'int(1); char(K); string(Kim); double(0.0); ' + +>>> x.bar2(1, 'K', "Kim", 9.9).get_state() +'int(1); char(K); string(Kim); double(9.9); ' + +>>> x = X("Phoenix", 1) +>>> x.get_state() +'Got exactly two arguments from constructor: string(Phoenix); bool(1); ' + +>>> def selected_doc(obj, *args): +... doc = obj.__doc__.splitlines() +... return "\\n".join(["|"+doc[i] for i in args]) + +>>> print(selected_doc(X.__init__, 1, 2, 4, 7, 9)) +|__init__( (object)self [, (int)a [, (str)b [, (str)c [, (float)d]]]]) -> None : +| doc of init +| C++ signature : +|__init__( (object)self, (str)s, (bool)b) -> None : +| C++ signature : + +>>> print(selected_doc(Y.__init__, 1, 2, 4)) +|__init__( (object)arg1) -> None : +| doc of Y init +| C++ signature : + +>>> print(selected_doc(X.bar2, 1, 2, 4)) +|bar2( (X)arg1 [, (int)arg2 [, (str)arg3 [, (str)arg4 [, (float)arg5]]]]) -> Y : +| doc of X::bar2 +| C++ signature : + +""" +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/destroy_test.cpp b/src/boost/libs/python/test/destroy_test.cpp new file mode 100644 index 000000000..57501604b --- /dev/null +++ b/src/boost/libs/python/test/destroy_test.cpp @@ -0,0 +1,58 @@ +// Copyright David Abrahams 2004. 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) +#include <boost/python/detail/destroy.hpp> + +#include <boost/detail/lightweight_test.hpp> + +int count; +int marks[] = { + -1 + , -1, -1 + , -1, -1, -1, -1 + , -1 +}; +int* kills = marks; + +struct foo +{ + foo() : n(count++) {} + ~foo() + { + *kills++ = n; + } + int n; + + // This used to cause compiler errors with MSVC 9.0. + foo& operator~(); + foo& T(); +}; + +void assert_destructions(int n) +{ + for (int i = 0; i < n; ++i) + BOOST_TEST(marks[i] == i); + BOOST_TEST(marks[n] == -1); +} + +int main() +{ + assert_destructions(0); + + foo* f1 = new foo; + boost::python::detail::destroy_referent<foo const volatile&>(f1); + assert_destructions(1); + + foo* f2 = new foo[2]; + typedef foo x[2]; + + boost::python::detail::destroy_referent<x const&>(f2); + assert_destructions(3); + + typedef foo y[2][2]; + x* f3 = new y; + boost::python::detail::destroy_referent<y&>(f3); + assert_destructions(7); + + return boost::report_errors(); +} diff --git a/src/boost/libs/python/test/dict.cpp b/src/boost/libs/python/test/dict.cpp new file mode 100644 index 000000000..375905d69 --- /dev/null +++ b/src/boost/libs/python/test/dict.cpp @@ -0,0 +1,91 @@ +// Copyright David Abrahams 2004. 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) +#include <boost/python/module.hpp> +#define BOOST_ENABLE_ASSERT_HANDLER +#include <boost/assert.hpp> + +#include <boost/python/def.hpp> +#include <boost/python/class.hpp> +#include <boost/python/dict.hpp> +#include <exception> +#include <string> + +using namespace boost::python; + +object new_dict() +{ + return dict(); +} + +object data_dict() +{ + dict tmp1; + tmp1["key1"] = "value1"; + + dict tmp2; + tmp2["key2"] = "value2"; + tmp1[1] = tmp2; + return tmp1; +} + +object dict_from_sequence(object sequence) +{ + return dict(sequence); +} + +object dict_keys(dict data) +{ + return data.keys(); +} + +object dict_values(dict data) +{ + return data.values(); +} + +object dict_items(dict data) +{ + return data.items(); +} + +void work_with_dict(dict data1, dict data2) +{ + if (!data1.has_key("k1")) { + throw std::runtime_error("dict does not have key 'k1'"); + } + data1.update(data2); +} + +void test_templates(object print) +{ + std::string key = "key"; + + dict tmp; + tmp[1] = "a test string"; + print(tmp.get(1)); + //print(tmp[1]); + tmp[1.5] = 13; + print(tmp.get(1.5)); + print(tmp.get(44)); + print(tmp); + print(tmp.get(2,"default")); + print(tmp.setdefault(3,"default")); + + BOOST_ASSERT(!tmp.has_key(key)); + //print(tmp[3]); +} + +BOOST_PYTHON_MODULE(dict_ext) +{ + def("new_dict", new_dict); + def("data_dict", data_dict); + def("dict_keys", dict_keys); + def("dict_values", dict_values); + def("dict_items", dict_items); + def("dict_from_sequence", dict_from_sequence); + def("work_with_dict", work_with_dict); + def("test_templates", test_templates); +} + +#include "module_tail.cpp" diff --git a/src/boost/libs/python/test/dict.py b/src/boost/libs/python/test/dict.py new file mode 100644 index 000000000..72c37d99e --- /dev/null +++ b/src/boost/libs/python/test/dict.py @@ -0,0 +1,46 @@ +# Copyright David Abrahams 2004. 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) +from __future__ import print_function +""" +>>> from dict_ext import * +>>> def printer(*args): +... for x in args: print(x, end='') +... print('') +... +>>> print(new_dict()) +{} +>>> print(data_dict()) +{1: {'key2': 'value2'}, 'key1': 'value1'} +>>> tmp = data_dict() +>>> print(dict_keys(tmp)) +[1, 'key1'] +>>> print(dict_values(tmp)) +[{'key2': 'value2'}, 'value1'] +>>> print(dict_items(tmp)) +[(1, {'key2': 'value2'}), ('key1', 'value1')] +>>> print(dict_from_sequence([(1,1),(2,2),(3,3)])) +{1: 1, 2: 2, 3: 3} +>>> test_templates(printer) #doctest: +NORMALIZE_WHITESPACE +a test string +13 +None +{1.5: 13, 1: 'a test string'} +default +default +""" + +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/docstring.cpp b/src/boost/libs/python/test/docstring.cpp new file mode 100644 index 000000000..c6cc0252b --- /dev/null +++ b/src/boost/libs/python/test/docstring.cpp @@ -0,0 +1,116 @@ +// Copyright David Abrahams 2002. +// 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) +#include <boost/python/operators.hpp> +#include <boost/python/class.hpp> +#include <boost/python/module.hpp> +#include <boost/python/def.hpp> +#include <boost/python/docstring_options.hpp> +#include <boost/python/scope.hpp> +#include <boost/python/manage_new_object.hpp> +#include "test_class.hpp" + +// Just use math.h here; trying to use std::pow() causes too much +// trouble for non-conforming compilers and libraries. +#include <math.h> + +using namespace boost::python; + +typedef test_class<> X; + +X* create(int x) +{ + return new X(x); +} + +unsigned long fact(unsigned long n) +{ + return n <= 1 ? n : n * fact(n - 1); +} + +BOOST_PYTHON_MODULE(docstring_ext) +{ + scope().attr("__doc__") = + "A simple test module for documentation strings\n" + "Exercised by docstring.py" + ; + + class_<X>("X", + "A simple class wrapper around a C++ int\n" + "includes some error-checking" + + , init<int>( + "this is the __init__ function\n" + "its documentation has two lines." + , args("self", "value") + ) + + ) + .def("value", &X::value, + "gets the value of the object" + , args("self")) + .def( "value", &X::value, + "also gets the value of the object" + , args("self")) + ; + + def("create", create, return_value_policy<manage_new_object>(), + "creates a new X object", args("value")); + + def("fact", fact, "compute the factorial", args("n")); + + { + docstring_options doc_options; + doc_options.disable_user_defined(); + def("fact_usr_off_1", fact, "usr off 1", args("n")); + doc_options.enable_user_defined(); + def("fact_usr_on_1", fact, "usr on 1", args("n")); + doc_options.disable_user_defined(); + def("fact_usr_off_2", fact, "usr off 2", args("n")); + } + def("fact_usr_on_2", fact, "usr on 2", args("n")); + + { + docstring_options doc_options(true, false); + def("fact_sig_off_1", fact, "sig off 1", args("n")); + doc_options.enable_signatures(); + def("fact_sig_on_1", fact, "sig on 1", args("n")); + doc_options.disable_signatures(); + def("fact_sig_off_2", fact, "sig off 2", args("n")); + } + def("fact_sig_on_2", fact, "sig on 2", args("n")); + + { + docstring_options doc_options(false); + def("fact_usr_off_sig_off_1", fact, "usr off sig off 1", args("n")); + { + docstring_options nested_doc_options; + def("fact_usr_on_sig_on_1", fact, "usr on sig on 1", args("n")); + nested_doc_options.disable_all(); + nested_doc_options.enable_user_defined(); + def("fact_usr_on_sig_off_1", fact, "usr on sig off 1", args("n")); + nested_doc_options.enable_all(); + def("fact_usr_on_sig_on_2", fact, "usr on sig on 2", args("n")); + } + def("fact_usr_off_sig_off_2", fact, "usr off sig off 2", args("n")); + } + + { + docstring_options doc_options(true); + doc_options.disable_cpp_signatures(); + def("fact_usr_on_psig_on_csig_off_1", fact, "usr on psig on csig off 1", args("n")); + doc_options.enable_cpp_signatures(); + doc_options.disable_py_signatures(); + def("fact_usr_on_psig_off_csig_on_1", fact, "usr on psig off csig on 1", args("n")); + doc_options.enable_py_signatures(); + doc_options.disable_user_defined(); + doc_options.disable_cpp_signatures(); + def("fact_usr_off_psig_on_csig_off_1", fact, "usr off psig on csig off 1", args("n")); + doc_options.enable_cpp_signatures(); + doc_options.disable_py_signatures(); + def("fact_usr_off_psig_off_csig_on_1", fact, "usr off psig off csig on 1", args("n")); + } +} + +#include "module_tail.cpp" diff --git a/src/boost/libs/python/test/docstring.py b/src/boost/libs/python/test/docstring.py new file mode 100644 index 000000000..2727bd6d5 --- /dev/null +++ b/src/boost/libs/python/test/docstring.py @@ -0,0 +1,153 @@ +# Copyright David Abrahams & Ralf W. Grosse-Kunsteve 2004-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) +''' +>>> from docstring_ext import * + +>>> def selected_doc(obj, *args): +... doc = obj.__doc__.splitlines() +... return "\\n".join(["|"+doc[i] for i in args]) + +>>> print(selected_doc(X.__init__, 1, 2, 3, 4, 5)) +|__init__( (object)self, (int)value) -> None : +| this is the __init__ function +| its documentation has two lines. +| +| C++ signature : + +>>> print(selected_doc(X.value, 1, 2, 4, 7, 8, 10)) +|value( (X)self) -> int : +| gets the value of the object +| C++ signature : +|value( (X)self) -> int : +| also gets the value of the object +| C++ signature : + +>>> print(selected_doc(create, 1, 2, 3, 4)) +|create( (int)value) -> X : +| creates a new X object +| +| C++ signature : + +>>> print(selected_doc(fact, 1, 2, 3, 4)) +|fact( (int)n) -> int : +| compute the factorial +| +| C++ signature : + +>>> len(fact_usr_off_1.__doc__.splitlines()) +5 +>>> print(selected_doc(fact_usr_off_1, 1, 3)) +|fact_usr_off_1( (int)n) -> int : +| C++ signature : +>>> len(fact_usr_on_1.__doc__.splitlines()) +6 +>>> print(selected_doc(fact_usr_on_1, 1, 2, 4)) +|fact_usr_on_1( (int)n) -> int : +| usr on 1 +| C++ signature : +>>> len(fact_usr_off_2.__doc__.splitlines()) +5 +>>> print(selected_doc(fact_usr_off_2, 1, 3)) +|fact_usr_off_2( (int)n) -> int : +| C++ signature : +>>> len(fact_usr_on_2.__doc__.splitlines()) +6 +>>> print(selected_doc(fact_usr_on_2, 1, 2, 4)) +|fact_usr_on_2( (int)n) -> int : +| usr on 2 +| C++ signature : + + +>>> len(fact_sig_off_1.__doc__.splitlines()) +2 +>>> print(selected_doc(fact_sig_off_1, 1)) +|sig off 1 +>>> len(fact_sig_on_1.__doc__.splitlines()) +6 +>>> print(selected_doc(fact_sig_on_1, 1, 2, 4)) +|fact_sig_on_1( (int)n) -> int : +| sig on 1 +| C++ signature : + +>>> len(fact_sig_off_2.__doc__.splitlines()) +2 +>>> print(selected_doc(fact_sig_off_2, 1)) +|sig off 2 +>>> len(fact_sig_on_2.__doc__.splitlines()) +6 +>>> print(selected_doc(fact_sig_on_2, 1, 2, 4)) +|fact_sig_on_2( (int)n) -> int : +| sig on 2 +| C++ signature : + + +>>> print(fact_usr_off_sig_off_1.__doc__) +None +>>> len(fact_usr_on_sig_on_1.__doc__.splitlines()) +6 +>>> print(selected_doc(fact_usr_on_sig_on_1, 1, 2, 4)) +|fact_usr_on_sig_on_1( (int)n) -> int : +| usr on sig on 1 +| C++ signature : + +>>> len(fact_usr_on_sig_off_1.__doc__.splitlines()) +2 +>>> print(selected_doc(fact_usr_on_sig_off_1, 1)) +|usr on sig off 1 +>>> len(fact_usr_on_sig_on_2.__doc__.splitlines()) +6 +>>> print(selected_doc(fact_usr_on_sig_on_2, 1, 2, 4)) +|fact_usr_on_sig_on_2( (int)n) -> int : +| usr on sig on 2 +| C++ signature : + +>>> print(selected_doc(fact_usr_on_psig_on_csig_off_1, 1, 2)) +|fact_usr_on_psig_on_csig_off_1( (int)n) -> int : +| usr on psig on csig off 1 + +>>> print(selected_doc(fact_usr_on_psig_off_csig_on_1, 1, 3)) +|usr on psig off csig on 1 +|C++ signature : + +>>> print(fact_usr_off_psig_on_csig_off_1.__doc__.splitlines()[1]) +fact_usr_off_psig_on_csig_off_1( (int)n) -> int + +>>> print(selected_doc(fact_usr_off_psig_off_csig_on_1,1)) +|C++ signature : + + +''' + +def run(args = None): + import sys + import doctest + + if args is not None: + sys.argv = args + + import docstring_ext + + result = doctest.testmod(sys.modules.get(__name__)) + + import pydoc + import re + docmodule = lambda m: re.sub(".\10", "", pydoc.text.docmodule(m)) + try: + print('printing module help:') + print(docmodule(docstring_ext)) + except object as x: + print('********* failed **********') + print(x) + result = list(result) + result[0] += 1 + return tuple(result) + + return result + +if __name__ == '__main__': + print("running...") + import sys + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/enable_shared_from_this.cpp b/src/boost/libs/python/test/enable_shared_from_this.cpp new file mode 100644 index 000000000..c246284a1 --- /dev/null +++ b/src/boost/libs/python/test/enable_shared_from_this.cpp @@ -0,0 +1,48 @@ +// Copyright David Abrahams 2002. +// 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) + +#include <boost/python/module.hpp> +#include <boost/python/class.hpp> +#include <boost/python/call_method.hpp> +#include <boost/python/extract.hpp> +#include <boost/python/def.hpp> +#include <boost/enable_shared_from_this.hpp> +#include <boost/shared_ptr.hpp> +#include "test_class.hpp" + +#include <memory> + +using namespace boost::python; +using boost::shared_ptr; + +class Test; +typedef shared_ptr<Test> TestPtr; + +class Test : public boost::enable_shared_from_this<Test> { +public: + static TestPtr construct() { + return TestPtr(new Test); + } + + void act() { + TestPtr kungFuDeathGrip(shared_from_this()); + } + + void take(TestPtr t) { + } +}; + +BOOST_PYTHON_MODULE(enable_shared_from_this_ext) +{ + class_<Test, TestPtr, boost::noncopyable>("Test") + .def("construct", &Test::construct).staticmethod("construct") + .def("act", &Test::act) + .def("take", &Test::take) + ; +} + +#include "module_tail.cpp" + + diff --git a/src/boost/libs/python/test/enable_shared_from_this.py b/src/boost/libs/python/test/enable_shared_from_this.py new file mode 100644 index 000000000..d7ac7a999 --- /dev/null +++ b/src/boost/libs/python/test/enable_shared_from_this.py @@ -0,0 +1,26 @@ +# Copyright David Abrahams 2004. 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) +''' +>>> from enable_shared_from_this_ext import * + +>>> x = Test.construct() +>>> x.take(x) +>>> x.act() +''' + +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) + diff --git a/src/boost/libs/python/test/enum_ext.cpp b/src/boost/libs/python/test/enum_ext.cpp new file mode 100644 index 000000000..74224f1d7 --- /dev/null +++ b/src/boost/libs/python/test/enum_ext.cpp @@ -0,0 +1,55 @@ +// Copyright David Abrahams 2002. +// 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) +#include <boost/python/enum.hpp> +#include <boost/python/def.hpp> +#include <boost/python/module.hpp> +#include <boost/python/class.hpp> +#if BOOST_WORKAROUND(__MWERKS__, <= 0x2407) +#include <boost/python/detail/type_traits.hpp> +# include <boost/mpl/bool.hpp> +#endif +using namespace boost::python; + +enum color { red = 1, green = 2, blue = 4, blood = 1 }; + +#if BOOST_WORKAROUND(__MWERKS__, <= 0x2407) +namespace boost // Pro7 has a hard time detecting enums +{ + template <> struct boost::python::detail::is_enum<color> : boost::mpl::true_ {}; +} +#endif + +color identity_(color x) { return x; } + +struct colorized { + colorized() : x(red) {} + color x; +}; + +BOOST_PYTHON_MODULE(enum_ext) +{ + enum_<color>("color") + .value("red", red) + .value("green", green) + .value("blue", blue) + .value("blood", blood) + .export_values() + ; + + def("identity", identity_); + +#if BOOST_WORKAROUND(__MWERKS__, <=0x2407) + color colorized::*px = &colorized::x; + class_<colorized>("colorized") + .def_readwrite("x", px) + ; +#else + class_<colorized>("colorized") + .def_readwrite("x", &colorized::x) + ; +#endif +} + +#include "module_tail.cpp" diff --git a/src/boost/libs/python/test/exception_translator.cpp b/src/boost/libs/python/test/exception_translator.cpp new file mode 100644 index 000000000..1e91c9296 --- /dev/null +++ b/src/boost/libs/python/test/exception_translator.cpp @@ -0,0 +1,28 @@ +// Copyright David Abrahams 2004. 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) +#include <boost/python/module.hpp> +#include <boost/python/def.hpp> +#include <boost/python/exception_translator.hpp> + +struct error {}; + +void translate(error const& /*e*/) +{ + PyErr_SetString(PyExc_RuntimeError, "!!!error!!!"); +} + +void throw_error() +{ + throw error(); + +} + +BOOST_PYTHON_MODULE(exception_translator_ext) +{ + using namespace boost::python; + register_exception_translator<error>(&translate); + + def("throw_error", throw_error); +} + diff --git a/src/boost/libs/python/test/exception_translator.py b/src/boost/libs/python/test/exception_translator.py new file mode 100644 index 000000000..1d80aba3a --- /dev/null +++ b/src/boost/libs/python/test/exception_translator.py @@ -0,0 +1,27 @@ +# Copyright David Abrahams 2004. 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) +''' +>>> from exception_translator_ext import * +>>> try: +... throw_error(); +... except RuntimeError as x: +... print(x) +... else: +... print('Expected a RuntimeError!') +!!!error!!! +''' +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/exec.cpp b/src/boost/libs/python/test/exec.cpp new file mode 100644 index 000000000..72ff571bd --- /dev/null +++ b/src/boost/libs/python/test/exec.cpp @@ -0,0 +1,197 @@ +// Copyright Stefan Seefeld 2005. +// 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) + +#include <boost/python.hpp> + +#include <boost/detail/lightweight_test.hpp> +#include <iostream> + + +namespace python = boost::python; + +// An abstract base class +class Base : public boost::noncopyable +{ +public: + virtual ~Base() {}; + virtual std::string hello() = 0; +}; + +// C++ derived class +class CppDerived : public Base +{ +public: + virtual ~CppDerived() {} + virtual std::string hello() { return "Hello from C++!";} +}; + +// Familiar Boost.Python wrapper class for Base +struct BaseWrap : Base, python::wrapper<Base> +{ + virtual std::string hello() + { +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + // workaround for VC++ 6.x or 7.0, see + // http://boost.org/libs/python/doc/tutorial/doc/html/python/exposing.html#python.class_virtual_functions + return python::call<std::string>(this->get_override("hello").ptr()); +#else + return this->get_override("hello")(); +#endif + } +}; + +// Pack the Base class wrapper into a module +BOOST_PYTHON_MODULE(embedded_hello) +{ + python::class_<BaseWrap, boost::noncopyable> base("Base"); +} + + +void eval_test() +{ + python::object result = python::eval("'abcdefg'.upper()"); + std::string value = python::extract<std::string>(result) BOOST_EXTRACT_WORKAROUND; + BOOST_TEST(value == "ABCDEFG"); +} + +void exec_test() +{ + // Retrieve the main module + python::object main = python::import("__main__"); + + // Retrieve the main module's namespace + python::object global(main.attr("__dict__")); + + // Define the derived class in Python. + python::object result = python::exec( + "from embedded_hello import * \n" + "class PythonDerived(Base): \n" + " def hello(self): \n" + " return 'Hello from Python!' \n", + global, global); + + python::object PythonDerived = global["PythonDerived"]; + + // Creating and using instances of the C++ class is as easy as always. + CppDerived cpp; + BOOST_TEST(cpp.hello() == "Hello from C++!"); + + // But now creating and using instances of the Python class is almost + // as easy! + python::object py_base = PythonDerived(); + Base& py = python::extract<Base&>(py_base) BOOST_EXTRACT_WORKAROUND; + + // Make sure the right 'hello' method is called. + BOOST_TEST(py.hello() == "Hello from Python!"); +} + +void exec_file_test(std::string const &script) +{ + // Run a python script in an empty environment. + python::dict global; + python::object result = python::exec_file(script.c_str(), global, global); + + // Extract an object the script stored in the global dictionary. + BOOST_TEST(python::extract<int>(global["number"]) == 42); +} + +void exec_test_error() +{ + // Execute a statement that raises a python exception. + python::dict global; + python::object result = python::exec("print(unknown) \n", global, global); +} + +void exercise_embedding_html() +{ + using namespace boost::python; + /* code from: libs/python/doc/tutorial/doc/tutorial.qbk + (generates libs/python/doc/tutorial/doc/html/python/embedding.html) + */ + object main_module = import("__main__"); + object main_namespace = main_module.attr("__dict__"); + + object ignored = exec("hello = file('hello.txt', 'w')\n" + "hello.write('Hello world!')\n" + "hello.close()", + main_namespace); +} + +void check_pyerr(bool pyerr_expected=false) +{ + if (PyErr_Occurred()) + { + if (!pyerr_expected) { + BOOST_ERROR("Python Error detected"); + PyErr_Print(); + } + else { + PyErr_Clear(); + } + } + else + { + BOOST_ERROR("A C++ exception was thrown for which " + "there was no exception handler registered."); + } +} + +int main(int argc, char **argv) +{ + BOOST_TEST(argc == 2 || argc == 3); + std::string script = argv[1]; + + // Register the module with the interpreter + if (PyImport_AppendInittab(const_cast<char*>("embedded_hello"), +#if PY_VERSION_HEX >= 0x03000000 + PyInit_embedded_hello +#else + initembedded_hello +#endif + ) == -1) + { + BOOST_ERROR("Failed to add embedded_hello to the interpreter's " + "builtin modules"); + } + + // Initialize the interpreter + Py_Initialize(); + + if (python::handle_exception(eval_test)) { + check_pyerr(); + } + else if(python::handle_exception(exec_test)) { + check_pyerr(); + } + else if (python::handle_exception(boost::bind(exec_file_test, script))) { + check_pyerr(); + } + + if (python::handle_exception(exec_test_error)) + { + check_pyerr(/*pyerr_expected*/ true); + } + else + { + BOOST_ERROR("Python exception expected, but not seen."); + } + + if (argc > 2) { + // The main purpose is to test compilation. Since this test generates + // a file and I (rwgk) am uncertain about the side-effects, run it only + // if explicitly requested. + exercise_embedding_html(); + } + + // Boost.Python doesn't support Py_Finalize yet. + // Py_Finalize(); + return boost::report_errors(); +} + +// Including this file makes sure +// that on Windows, any crashes (e.g. null pointer dereferences) invoke +// the debugger immediately, rather than being translated into structured +// exceptions that can interfere with debugging. +#include "module_tail.cpp" diff --git a/src/boost/libs/python/test/exec.py b/src/boost/libs/python/test/exec.py new file mode 100644 index 000000000..c7bf28f35 --- /dev/null +++ b/src/boost/libs/python/test/exec.py @@ -0,0 +1,6 @@ +# Copyright Stefan Seefeld 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) + +if 1: + number = 42 diff --git a/src/boost/libs/python/test/extract.cpp b/src/boost/libs/python/test/extract.cpp new file mode 100644 index 000000000..40584a077 --- /dev/null +++ b/src/boost/libs/python/test/extract.cpp @@ -0,0 +1,143 @@ +// Copyright David Abrahams 2002. +// 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) + +#include <boost/python/extract.hpp> +#include <boost/python/list.hpp> +#include <boost/python/module.hpp> +#include <boost/python/def.hpp> +#include <boost/python/class.hpp> +#include <boost/python/reference_existing_object.hpp> +#include <boost/python/return_value_policy.hpp> +#include <boost/python/implicit.hpp> +#include <string> +#include <boost/lexical_cast.hpp> +#define BOOST_ENABLE_ASSERT_HANDLER +#include <boost/assert.hpp> +#include "test_class.hpp" + +using namespace boost::python; + +typedef test_class<> X; + +bool extract_bool(object x) { return extract<bool>(x); } + +boost::python::list extract_list(object x) +{ + extract<list> get_list((x)); + + // Make sure we always have the right idea about whether it's a list + bool is_list_1 = get_list.check(); + bool is_list_2 = PyObject_IsInstance(x.ptr(), (PyObject*)&PyList_Type); + if (is_list_1 != is_list_2) { + throw std::runtime_error("is_list_1 == is_list_2 failure."); + } + return get_list(); +} + +char const* extract_cstring(object x) +{ + return extract<char const*>(x); +} + +std::string extract_string(object x) +{ + std::string s = extract<std::string>(x); + return s; +} + +std::string const& extract_string_cref(object x) +{ +#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 +# pragma warning(push) +# pragma warning(disable:4172) // msvc lies about returning a reference to temporary +#elif defined(_MSC_VER) && defined(__ICL) && __ICL <= 900 +# pragma warning(push) +# pragma warning(disable:473) // intel/win32 does too +#endif + + return extract<std::string const&>(x); + +#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(_MSC_VER) && defined(__ICL) && __ICL <= 800 +# pragma warning(pop) +#endif +} + +X extract_X(object x) +{ + return extract<X>(x); +} + +X* extract_X_ptr(object x) { return extract<X*>(x); } + +X& extract_X_ref(object x) +{ + extract<X&> get_x(x); + return get_x; +} + +int double_X(object n) +{ + extract<X> x(n); + return x().value() + x().value(); +} + +bool check_bool(object x) { return extract<bool>(x).check(); } +bool check_list(object x) { return extract<list>(x).check(); } +bool check_cstring(object x) { return extract<char const*>(x).check(); } +bool check_string(object x) { return extract<std::string>(x).check(); } +bool check_string_cref(object x) { return extract<std::string const&>(x).check(); } +bool check_X(object x) { return extract<X>(x).check(); } +bool check_X_ptr(object x) { return extract<X*>(x).check(); } +bool check_X_ref(object x) { return extract<X&>(x).check(); } + +std::string x_rep(X const& x) +{ + return "X(" + boost::lexical_cast<std::string>(x.value()) + ")"; +} + +BOOST_PYTHON_MODULE(extract_ext) +{ + implicitly_convertible<int, X>(); + + def("extract_bool", extract_bool); + def("extract_list", extract_list); + def("extract_cstring", extract_cstring); + def("extract_string", extract_string); + def("extract_string_cref", extract_string_cref, return_value_policy<reference_existing_object>()); + def("extract_X", extract_X); + def("extract_X_ptr", extract_X_ptr, return_value_policy<reference_existing_object>()); + def("extract_X_ref", extract_X_ref, return_value_policy<reference_existing_object>()); + + def("check_bool", check_bool); + def("check_list", check_list); + def("check_cstring", check_cstring); + def("check_string", check_string); + def("check_string_cref", check_string_cref); + def("check_X", check_X); + def("check_X_ptr", check_X_ptr); + def("check_X_ref", check_X_ref); + + def("double_X", double_X); + + def("count_Xs", &X::count); + ; + + object x_class( + class_<X>("X", init<int>()) + .def( "__repr__", x_rep)); + + // Instantiate an X object through the Python interface + object x_obj = x_class(3); + + // Get the C++ object out of the Python object + X const& x = extract<X&>(x_obj); + if (x.value() != 3) { + throw std::runtime_error("x.value() == 3 failure."); + } +} + + +#include "module_tail.cpp" + diff --git a/src/boost/libs/python/test/extract.py b/src/boost/libs/python/test/extract.py new file mode 100644 index 000000000..feda93a1d --- /dev/null +++ b/src/boost/libs/python/test/extract.py @@ -0,0 +1,107 @@ +# Copyright David Abrahams 2004. 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) +''' + >>> from extract_ext import * + +Just about anything has a truth value in Python + + >>> assert check_bool(None) + >>> extract_bool(None) + 0 + + >>> assert check_bool(2) + >>> extract_bool(2) + 1 + + >>> assert not check_bool('') + +Check that object manager types work properly. These are a different +case because they wrap Python objects instead of being wrapped by them. + + >>> assert not check_list(2) + >>> try: x = extract_list(2) + ... except TypeError as x: + ... if str(x) != 'Expecting an object of type list; got an object of type int instead': + ... print(x) + ... else: + ... print('expected an exception, got', x, 'instead') + +Can't extract a list from a tuple. Use list(x) to convert a sequence +to a list: + + >>> assert not check_list((1, 2, 3)) + >>> assert check_list([1, 2, 3]) + >>> extract_list([1, 2, 3]) + [1, 2, 3] + +Can get a char const* from a Python string: + + >>> assert check_cstring('hello') + >>> extract_cstring('hello') + 'hello' + +Can't get a char const* from a Python int: + + >>> assert not check_cstring(1) + >>> try: x = extract_cstring(1) + ... except TypeError: pass + ... else: + ... print('expected an exception, got', x, 'instead') + +Extract an std::string (class) rvalue from a native Python type + + >>> assert check_string('hello') + >>> extract_string('hello') + 'hello' + +Constant references are not treated as rvalues for the purposes of +extract: + + >>> assert not check_string_cref('hello') + +We can extract lvalues where appropriate: + + >>> x = X(42) + >>> check_X(x) + 1 + >>> extract_X(x) + X(42) + + >>> check_X_ptr(x) + 1 + >>> extract_X_ptr(x) + X(42) + >>> extract_X_ref(x) + X(42) + +Demonstrate that double-extraction of an rvalue works, and all created +copies of the object are destroyed: + + >>> n = count_Xs() + >>> double_X(333) + 666 + >>> count_Xs() - n + 0 + +General check for cleanliness: + + >>> del x + >>> count_Xs() + 0 +''' + +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/fabscript b/src/boost/libs/python/test/fabscript new file mode 100644 index 000000000..1989cc0d1 --- /dev/null +++ b/src/boost/libs/python/test/fabscript @@ -0,0 +1,173 @@ +# -*- python -*- +# +# Copyright (c) 2016 Stefan Seefeld +# All rights reserved. +# +# 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) + +from faber import platform +from faber.feature import set +from faber.tools.compiler import runpath +from faber.tools.python import python, pythonpath +from faber.artefacts.object import object +from faber.artefacts.binary import binary +from faber.artefacts.python import extension +from faber.test import test, report, fail + +src = module('..src') + +python_libs=python.instance().libs +features |= runpath(src.bpl.path, base='') + +def extension_test(name, ext=[], script=None, np=False, + features=features, condition=None): + """Create a Python extension test `name`. + Arguments: + * name: the name of the test. + * ext: extensions to be compiled, <name> if none are given. + * script: the test script to execute, <name>.py if none is given. + * np: if true, add boost_numpy to sources + * features: pre-defined features + * condition: any condition under which to run the test + Return: + * the test artefact""" + + features=features.copy() + extensions = [] + libs = [src.bnl, src.bpl] if np else [src.bpl] + for e in ext or [name]: + if type(e) is str: # build from a single source file + n = e if e != name else e + '_ext' + s = [e + '.cpp'] + else: # build from a list of source files + n = e[0] if e[0] != name else e[0] + '_ext' + s = [n + '.cpp' for n in e] + e = extension(n, s + libs, features=features) + features |= pythonpath(e.path, base='') + extensions.append(e) + if not script: + script = name+'.py' + return test(name, script, run=python.run, dependencies=extensions, + features=features, condition=condition) + +tests = [] +for t in [('injected',), + ('properties',), + ('return_arg',), + ('staticmethod',), + ('boost_shared_ptr',), + ('enable_shared_from_this',), + ('andreas_beyer',), + ('polymorphism',), + ('polymorphism2',), + ('wrapper_held_type',), + ('minimal',), + ('args',), + ('raw_ctor',), + ('exception_translator',), + ('test_enum', ['enum_ext']), + ('test_cltree', ['cltree']), + ('newtest', ['m1', 'm2']), + ('const_argument',), + ('keywords_test', ['keywords']), + ('test_pointer_adoption',), + ('operators',), + ('operators_wrapper',), + ('callbacks',), + ('defaults',), + ('object',), + ('list',), + ('long',), + ('dict',), + ('tuple',), + ('str',), + ('slice',), + ('virtual_functions',), + ('back_reference',), + ('implicit',), + ('data_members',), + ('ben_scott1',), + ('bienstman1',), + ('bienstman2',), + ('bienstman3',), + ('multi_arg_constructor',), + ('iterator', ['iterator', 'input_iterator']), + ('stl_iterator',), + ('extract',), + ('crossmod_opaque', ['crossmod_opaque_a', 'crossmod_opaque_b']), + ('opaque',), + ('voidptr',), + ('pickle1',), + ('pickle2',), + ('pickle3',), + ('pickle4',), + ('nested',), + ('docstring',), + ('pytype_function',), + ('vector_indexing_suite',), + ('pointer_vector',), + ('builtin_converters', [], 'test_builtin_converters.py'), + ('map_indexing_suite', + [['map_indexing_suite', 'int_map_indexing_suite', 'a_map_indexing_suite']])]: + tests.append(extension_test(*t)) + +tests.append(extension_test('shared_ptr', + condition=set.define.contains('HAS_CXX11'))) +tests.append(extension_test('polymorphism2_auto_ptr', + condition=set.define.contains('HAS_CXX11').not_())) +tests.append(extension_test('auto_ptr', + condition=set.define.contains('HAS_CXX11'))) + +import_ = binary('import_', ['import_.cpp', src.bpl], features=features|python_libs) +if platform.os == 'Windows': + command = """set PATH=$(runpath);%PATH% +$(>[1]) $(>[2])""" +else: + command = 'LD_LIBRARY_PATH=$(runpath) $(>[1]) $(>[2])' + +tests.append(test('import', [import_, 'import_.py'], + run=action('run', command), + features=features)) + +tests.append(extension_test('calling_conventions', + condition=platform.os == 'Windows')) +tests.append(extension_test('calling_conventions_mf', + condition=platform.os == 'Windows')) + +for t in ['destroy_test', + 'pointer_type_id_test', + 'bases', + 'pointee', + 'if_else', + 'pointee', + 'result', + 'upcast', + 'select_from_python_test']: + tests.append(test(t, binary(t, [t + '.cpp', src.bpl], features=features), features=features, run=True)) +for t in ['indirect_traits_test', + 'string_literal', + 'borrowed', + 'object_manager', + 'copy_ctor_mutates_rhs', + 'select_holder', + 'select_arg_to_python_test']: + tests.append(test(t, object(t, [t + '.cpp'], features=features))) + +for t in ['raw_pyobject_fail1', + 'raw_pyobject_fail2', + 'as_to_python_function', + 'object_fail1']: + tests.append(test(t, object(t, [t + '.cpp'], features=features), expected=fail)) + +for t in ['numpy/dtype', + 'numpy/ufunc', + 'numpy/templates', + 'numpy/ndarray', + 'numpy/indexing', + 'numpy/shapes']: + tests.append(extension_test(t, np=True, + condition=set.define.contains('HAS_NUMPY'))) + +default = report('report', tests, fail_on_failures=True) diff --git a/src/boost/libs/python/test/if_else.cpp b/src/boost/libs/python/test/if_else.cpp new file mode 100644 index 000000000..60cc53192 --- /dev/null +++ b/src/boost/libs/python/test/if_else.cpp @@ -0,0 +1,44 @@ +// Copyright David Abrahams 2002. +// 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) +#include <boost/static_assert.hpp> +#include <boost/python/detail/if_else.hpp> +#include <boost/python/detail/type_traits.hpp> + + typedef char c1; + typedef char c2[2]; + typedef char c3[3]; + typedef char c4[4]; + +template <unsigned size> +struct choose +{ + typedef typename boost::python::detail::if_< + (sizeof(c1) == size) + >::template then< + c1 + >::template elif< + (sizeof(c2) == size) + >::template then< + c2 + >::template elif< + (sizeof(c3) == size) + >::template then< + c3 + >::template elif< + (sizeof(c4) == size) + >::template then< + c4 + >::template else_<void*>::type type; +}; + +int main() +{ + BOOST_STATIC_ASSERT((boost::python::detail::is_same<choose<1>::type,c1>::value)); + BOOST_STATIC_ASSERT((boost::python::detail::is_same<choose<2>::type,c2>::value)); + BOOST_STATIC_ASSERT((boost::python::detail::is_same<choose<3>::type,c3>::value)); + BOOST_STATIC_ASSERT((boost::python::detail::is_same<choose<4>::type,c4>::value)); + BOOST_STATIC_ASSERT((boost::python::detail::is_same<choose<5>::type,void*>::value)); + return 0; +} diff --git a/src/boost/libs/python/test/implicit.cpp b/src/boost/libs/python/test/implicit.cpp new file mode 100644 index 000000000..a1bae59e8 --- /dev/null +++ b/src/boost/libs/python/test/implicit.cpp @@ -0,0 +1,48 @@ +// Copyright David Abrahams 2002. +// 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) +#include <boost/python/class.hpp> +#include <boost/python/implicit.hpp> +#include <boost/python/module.hpp> +#include <boost/python/def.hpp> +#include "test_class.hpp" + +using namespace boost::python; + +typedef test_class<> X; + +int x_value(X const& x) +{ + return x.value(); +} + +X make_x(int n) { return X(n); } + + +// foo/bar -- a regression for a vc7 bug workaround +struct bar {}; +struct foo +{ + virtual ~foo() {}; // silence compiler warnings + virtual void f() = 0; + operator bar() const { return bar(); } +}; + +BOOST_PYTHON_MODULE(implicit_ext) +{ + implicitly_convertible<foo,bar>(); + implicitly_convertible<int,X>(); + + def("x_value", x_value); + def("make_x", make_x); + + class_<X>("X", init<int>()) + .def("value", &X::value) + .def("set", &X::set) + ; + + implicitly_convertible<X,int>(); +} + +#include "module_tail.cpp" diff --git a/src/boost/libs/python/test/implicit.py b/src/boost/libs/python/test/implicit.py new file mode 100644 index 000000000..f2aa3e1d3 --- /dev/null +++ b/src/boost/libs/python/test/implicit.py @@ -0,0 +1,44 @@ +# Copyright David Abrahams 2004. 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) +''' +>>> from implicit_ext import * +>>> x_value(X(42)) +42 +>>> x_value(42) +42 +>>> x = make_x(X(42)) +>>> x.value() +42 +>>> try: make_x('fool') +... except TypeError: pass +... else: print('no error') + +>>> print(x_value.__doc__.splitlines()[1]) +x_value( (X)arg1) -> int : + +>>> print(make_x.__doc__.splitlines()[1]) +make_x( (object)arg1) -> X : + +>>> print(X.value.__doc__.splitlines()[1]) +value( (X)arg1) -> int : + +>>> print(X.set.__doc__.splitlines()[1]) +set( (X)arg1, (object)arg2) -> None : + +''' + +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/import_.cpp b/src/boost/libs/python/test/import_.cpp new file mode 100644 index 000000000..3e21de0ba --- /dev/null +++ b/src/boost/libs/python/test/import_.cpp @@ -0,0 +1,70 @@ +// Copyright Stefan Seefeld 2007. +// 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) + +#include <boost/python.hpp> + +#include <boost/detail/lightweight_test.hpp> +#include <boost/bind.hpp> +#include <iostream> +#include <sstream> + +namespace bpl = boost::python; + +void import_test(char const *py_file_path) +{ + // Retrieve the main module + bpl::object main = bpl::import("__main__"); + + // Retrieve the main module's namespace + bpl::object global(main.attr("__dict__")); + + // Inject search path for import_ module + + bpl::str script( + "import sys, os.path\n" + "path = os.path.dirname(%r)\n" + "sys.path.insert(0, path)" + % bpl::str(py_file_path)); + + bpl::object result = bpl::exec(script, global, global); + + // Retrieve the main module + bpl::object import_ = bpl::import("import_"); + int value = bpl::extract<int>(import_.attr("value")) BOOST_EXTRACT_WORKAROUND; + std::cout << value << std::endl; + BOOST_TEST(value == 42); +} + +int main(int argc, char **argv) +{ + BOOST_TEST(argc == 2); + + // Initialize the interpreter + Py_Initialize(); + + if (bpl::handle_exception(boost::bind(import_test,argv[1]))) + { + if (PyErr_Occurred()) + { + BOOST_ERROR("Python Error detected"); + PyErr_Print(); + } + else + { + BOOST_ERROR("A C++ exception was thrown for which " + "there was no exception handler registered."); + } + } + + // Boost.Python doesn't support Py_Finalize yet. + // Py_Finalize(); + return boost::report_errors(); +} + +// Including this file makes sure +// that on Windows, any crashes (e.g. null pointer dereferences) invoke +// the debugger immediately, rather than being translated into structured +// exceptions that can interfere with debugging. +#include "module_tail.cpp" diff --git a/src/boost/libs/python/test/import_.py b/src/boost/libs/python/test/import_.py new file mode 100644 index 000000000..48de6e5ec --- /dev/null +++ b/src/boost/libs/python/test/import_.py @@ -0,0 +1,5 @@ +# Copyright Stefan Seefeld 2007. 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) + +value = 42 diff --git a/src/boost/libs/python/test/indirect_traits_test.cpp b/src/boost/libs/python/test/indirect_traits_test.cpp new file mode 100644 index 000000000..da4cc2456 --- /dev/null +++ b/src/boost/libs/python/test/indirect_traits_test.cpp @@ -0,0 +1,116 @@ +// Copyright David Abrahams 2004. 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) +//#include <stdio.h> +#define BOOST_ENABLE_ASSERT_HANDLER +#include <boost/assert.hpp> +#include <boost/mpl/assert.hpp> +#include <boost/python/detail/indirect_traits.hpp> +#include <boost/mpl/assert.hpp> + +//#define print(expr) printf("%s ==> %s\n", #expr, expr) + +// not all the compilers can handle an incomplete class type here. +struct X {}; + +using namespace boost::python::indirect_traits; + +typedef void (X::*pmf)(); + +BOOST_MPL_ASSERT((is_reference_to_function<int (&)()>)); +BOOST_MPL_ASSERT_NOT((is_reference_to_function<int (*)()>)); +BOOST_MPL_ASSERT_NOT((is_reference_to_function<int&>)); +BOOST_MPL_ASSERT_NOT((is_reference_to_function<pmf>)); + +BOOST_MPL_ASSERT_NOT((is_pointer_to_function<int (&)()>)); +BOOST_MPL_ASSERT((is_pointer_to_function<int (*)()>)); +BOOST_MPL_ASSERT_NOT((is_pointer_to_function<int (*&)()>)); +BOOST_MPL_ASSERT_NOT((is_pointer_to_function<int (*const&)()>)); +BOOST_MPL_ASSERT_NOT((is_pointer_to_function<pmf>)); + +BOOST_MPL_ASSERT_NOT((is_reference_to_function_pointer<int (&)()>)); +BOOST_MPL_ASSERT_NOT((is_reference_to_function_pointer<int (*)()>)); +BOOST_MPL_ASSERT_NOT((is_reference_to_function_pointer<int&>)); +BOOST_MPL_ASSERT((is_reference_to_function_pointer<int (*&)()>)); +BOOST_MPL_ASSERT((is_reference_to_function_pointer<int (*const&)()>)); +BOOST_MPL_ASSERT_NOT((is_reference_to_function_pointer<pmf>)); + +BOOST_MPL_ASSERT((is_reference_to_pointer<int*&>)); +BOOST_MPL_ASSERT((is_reference_to_pointer<int* const&>)); +BOOST_MPL_ASSERT((is_reference_to_pointer<int*volatile&>)); +BOOST_MPL_ASSERT((is_reference_to_pointer<int*const volatile&>)); +BOOST_MPL_ASSERT((is_reference_to_pointer<int const*&>)); +BOOST_MPL_ASSERT((is_reference_to_pointer<int const* const&>)); +BOOST_MPL_ASSERT((is_reference_to_pointer<int const*volatile&>)); +BOOST_MPL_ASSERT((is_reference_to_pointer<int const*const volatile&>)); +BOOST_MPL_ASSERT_NOT((is_reference_to_pointer<pmf>)); + +BOOST_MPL_ASSERT_NOT((is_reference_to_pointer<int const volatile>)); +BOOST_MPL_ASSERT_NOT((is_reference_to_pointer<int>)); +BOOST_MPL_ASSERT_NOT((is_reference_to_pointer<int*>)); + +BOOST_MPL_ASSERT_NOT((is_reference_to_const<int*&>)); +BOOST_MPL_ASSERT((is_reference_to_const<int* const&>)); +BOOST_MPL_ASSERT_NOT((is_reference_to_const<int*volatile&>)); +BOOST_MPL_ASSERT((is_reference_to_const<int*const volatile&>)); + +BOOST_MPL_ASSERT_NOT((is_reference_to_const<int const volatile>)); +BOOST_MPL_ASSERT_NOT((is_reference_to_const<int>)); +BOOST_MPL_ASSERT_NOT((is_reference_to_const<int*>)); + +BOOST_MPL_ASSERT((is_reference_to_non_const<int*&>)); +BOOST_MPL_ASSERT_NOT((is_reference_to_non_const<int* const&>)); +BOOST_MPL_ASSERT((is_reference_to_non_const<int*volatile&>)); +BOOST_MPL_ASSERT_NOT((is_reference_to_non_const<int*const volatile&>)); + +BOOST_MPL_ASSERT_NOT((is_reference_to_non_const<int const volatile>)); +BOOST_MPL_ASSERT_NOT((is_reference_to_non_const<int>)); +BOOST_MPL_ASSERT_NOT((is_reference_to_non_const<int*>)); + +BOOST_MPL_ASSERT_NOT((is_reference_to_volatile<int*&>)); +BOOST_MPL_ASSERT_NOT((is_reference_to_volatile<int* const&>)); +BOOST_MPL_ASSERT((is_reference_to_volatile<int*volatile&>)); +BOOST_MPL_ASSERT((is_reference_to_volatile<int*const volatile&>)); + +BOOST_MPL_ASSERT_NOT((is_reference_to_volatile<int const volatile>)); +BOOST_MPL_ASSERT_NOT((is_reference_to_volatile<int>)); +BOOST_MPL_ASSERT_NOT((is_reference_to_volatile<int*>)); + +namespace tt = boost::python::indirect_traits; + +BOOST_MPL_ASSERT_NOT((tt::is_reference_to_class<int>)); +BOOST_MPL_ASSERT_NOT((tt::is_reference_to_class<int&>)); +BOOST_MPL_ASSERT_NOT((tt::is_reference_to_class<int*>)); + + +BOOST_MPL_ASSERT_NOT((tt::is_reference_to_class<pmf>)); +BOOST_MPL_ASSERT_NOT((tt::is_reference_to_class<pmf const&>)); + +BOOST_MPL_ASSERT_NOT((tt::is_reference_to_class<X>)); + +BOOST_MPL_ASSERT((tt::is_reference_to_class<X&>)); +BOOST_MPL_ASSERT((tt::is_reference_to_class<X const&>)); +BOOST_MPL_ASSERT((tt::is_reference_to_class<X volatile&>)); +BOOST_MPL_ASSERT((tt::is_reference_to_class<X const volatile&>)); + +BOOST_MPL_ASSERT_NOT((is_pointer_to_class<int>)); +BOOST_MPL_ASSERT_NOT((is_pointer_to_class<int*>)); +BOOST_MPL_ASSERT_NOT((is_pointer_to_class<int&>)); + +BOOST_MPL_ASSERT_NOT((is_pointer_to_class<X>)); +BOOST_MPL_ASSERT_NOT((is_pointer_to_class<X&>)); +BOOST_MPL_ASSERT_NOT((is_pointer_to_class<pmf>)); +BOOST_MPL_ASSERT_NOT((is_pointer_to_class<pmf const>)); +BOOST_MPL_ASSERT((is_pointer_to_class<X*>)); +BOOST_MPL_ASSERT((is_pointer_to_class<X const*>)); +BOOST_MPL_ASSERT((is_pointer_to_class<X volatile*>)); +BOOST_MPL_ASSERT((is_pointer_to_class<X const volatile*>)); + +BOOST_MPL_ASSERT((tt::is_reference_to_member_function_pointer<pmf&>)); +BOOST_MPL_ASSERT((tt::is_reference_to_member_function_pointer<pmf const&>)); +BOOST_MPL_ASSERT((tt::is_reference_to_member_function_pointer<pmf volatile&>)); +BOOST_MPL_ASSERT((tt::is_reference_to_member_function_pointer<pmf const volatile&>)); +BOOST_MPL_ASSERT_NOT((tt::is_reference_to_member_function_pointer<pmf[2]>)); +BOOST_MPL_ASSERT_NOT((tt::is_reference_to_member_function_pointer<pmf(&)[2]>)); +BOOST_MPL_ASSERT_NOT((tt::is_reference_to_member_function_pointer<pmf>)); + diff --git a/src/boost/libs/python/test/injected.cpp b/src/boost/libs/python/test/injected.cpp new file mode 100644 index 000000000..73e1e14ba --- /dev/null +++ b/src/boost/libs/python/test/injected.cpp @@ -0,0 +1,39 @@ +// Copyright David Abrahams 2003. +// 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) + +#include <boost/python/module.hpp> +#include <boost/python/class.hpp> +#include "test_class.hpp" +#include <memory> +#include <boost/shared_ptr.hpp> +#include <boost/python/make_constructor.hpp> +#include <boost/python/args.hpp> + +using namespace boost::python; + +typedef test_class<> X; + +X* empty() { return new X(1000); } + +std::auto_ptr<X> sum(int a, int b) { return std::auto_ptr<X>(new X(a+b)); } + +boost::shared_ptr<X> product(int a, int b, int c) +{ + return boost::shared_ptr<X>(new X(a*b*c)); +} + +BOOST_PYTHON_MODULE(injected_ext) +{ + class_<X>("X", init<int>()) + .def("__init__", make_constructor(empty)) + .def("__init__", make_constructor(sum)) + .def("__init__", make_constructor(product + , default_call_policies() + , ( arg_("a"), arg_("b"), arg_("c")) + ), + "this is product's docstring") + .def("value", &X::value) + ; +} diff --git a/src/boost/libs/python/test/injected.py b/src/boost/libs/python/test/injected.py new file mode 100644 index 000000000..c50215048 --- /dev/null +++ b/src/boost/libs/python/test/injected.py @@ -0,0 +1,28 @@ +# Copyright David Abrahams 2004. 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) +''' +>>> from injected_ext import * +>>> X(3,5).value() - (3+5) +0 +>>> X(a=3,b=5,c=7).value() - (3*5*7) +0 +>>> X().value() +1000 +''' + +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) + diff --git a/src/boost/libs/python/test/input_iterator.cpp b/src/boost/libs/python/test/input_iterator.cpp new file mode 100644 index 000000000..70b994186 --- /dev/null +++ b/src/boost/libs/python/test/input_iterator.cpp @@ -0,0 +1,48 @@ +// Copyright David Abrahams 2002. +// 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) +#include <boost/python/module.hpp> +#include <boost/python/def.hpp> +#include <boost/python/class.hpp> +#include <boost/python/iterator.hpp> +#include <boost/iterator/transform_iterator.hpp> +#include <list> + +using namespace boost::python; + +typedef std::list<int> list_int; + +// Prove that we can handle InputIterators which return rvalues. +struct doubler +{ + typedef int result_type; + int operator()(int x) const { return x * 2; } +}; + +typedef boost::transform_iterator<doubler, list_int::iterator> doubling_iterator; +typedef std::pair<doubling_iterator,doubling_iterator> list_range2; + +list_range2 range2(list_int& x) +{ + return list_range2( + boost::make_transform_iterator<doubler>(x.begin(), doubler()) + , boost::make_transform_iterator<doubler>(x.end(), doubler())); +} + +// We do this in a separate module from iterators_ext (iterators.cpp) +// to work around an MSVC6 linker bug, which causes it to complain +// about a "duplicate comdat" if the input iterator is instantiated in +// the same module with the others. +BOOST_PYTHON_MODULE(input_iterator) +{ + def("range2", &::range2); + + class_<list_range2>("list_range2") + // We can wrap InputIterators which return by-value + .def("__iter__" + , range(&list_range2::first, &list_range2::second)) + ; +} + +#include "module_tail.cpp" diff --git a/src/boost/libs/python/test/int_map_indexing_suite.cpp b/src/boost/libs/python/test/int_map_indexing_suite.cpp new file mode 100644 index 000000000..397850131 --- /dev/null +++ b/src/boost/libs/python/test/int_map_indexing_suite.cpp @@ -0,0 +1,16 @@ +// Copyright David Abrahams 2004. 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) + +#include <boost/python/class.hpp> +#include <boost/python/suite/indexing/map_indexing_suite.hpp> + +void int_map_indexing_suite() +{ + using namespace boost::python; + + // Compile check only... + class_<std::map<int, int> >("IntMap") + .def(map_indexing_suite<std::map<int, int> >()) + ; +} diff --git a/src/boost/libs/python/test/iterator.cpp b/src/boost/libs/python/test/iterator.cpp new file mode 100644 index 000000000..458ba2926 --- /dev/null +++ b/src/boost/libs/python/test/iterator.cpp @@ -0,0 +1,137 @@ +// Copyright David Abrahams 2002. +// 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) +#include <boost/python/module.hpp> +#include <boost/python/def.hpp> +#include <boost/python/class.hpp> +#include <boost/python/return_internal_reference.hpp> +#include <boost/python/copy_non_const_reference.hpp> +#include <boost/python/return_value_policy.hpp> +#include <boost/python/iterator.hpp> +#include <list> +#include <utility> +#include <iterator> +#include <algorithm> + +using namespace boost::python; + +typedef std::list<int> list_int; +typedef std::list<list_int> list_list; + + +void push_back(list_int& x, int y) +{ + x.push_back(y); +} + +void push_list_back(list_list& x, list_int const& y) +{ + x.push_back(y); +} + +int back(list_int& x) +{ + return x.back(); +} + +typedef std::pair<list_int::iterator,list_int::iterator> list_range; + +struct list_range2 : list_range +{ + list_int::iterator& begin() { return this->first; } + list_int::iterator& end() { return this->second; } +}; + +list_range range(list_int& x) +{ + return list_range(x.begin(), x.end()); +} + +struct two_lists +{ + two_lists() + { + int primes[] = { 2, 3, 5, 7, 11, 13 }; + std::copy(primes, primes + sizeof(primes)/sizeof(*primes), std::back_inserter(one)); + int evens[] = { 2, 4, 6, 8, 10, 12 }; + std::copy(evens, evens + sizeof(evens)/sizeof(*evens), std::back_inserter(two)); + } + + struct two_start + { + typedef list_int::iterator result_type; + result_type operator()(two_lists& ll) const { return ll.two.begin(); } + }; + friend struct two_start; + + list_int::iterator one_begin() { return one.begin(); } + list_int::iterator two_begin() { return two.begin(); } + + list_int::iterator one_end() { return one.end(); } + list_int::iterator two_end() { return two.end(); } + +private: + list_int one; + list_int two; +}; + +BOOST_PYTHON_MODULE(iterator_ext) +{ + using boost::python::iterator; // gcc 2.96 bug workaround + def("range", &::range); + + class_<list_int>("list_int") + .def("push_back", push_back) + .def("back", back) + .def("__iter__", iterator<list_int>()) + ; + + class_<list_range>("list_range") + + // We can specify data members + .def("__iter__" + , range(&list_range::first, &list_range::second)) + ; + + // No runtime tests for this one yet + class_<list_range2>("list_range2") + + // We can specify member functions returning a non-const reference + .def("__iter__", range(&list_range2::begin, &list_range2::end)) + ; + + class_<two_lists>("two_lists") + + // We can spcify member functions + .add_property( + "primes" + , range(&two_lists::one_begin, &two_lists::one_end)) + + // Prove that we can explicitly specify call policies + .add_property( + "evens" + , range<return_value_policy<copy_non_const_reference> >( + &two_lists::two_begin, &two_lists::two_end)) + + // Prove that we can specify call policies and target + .add_property( + "twosies" + , range<return_value_policy<copy_non_const_reference>, two_lists>( + // And we can use adaptable function objects when + // partial specialization is available. +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + two_lists::two_start() +# else + &two_lists::two_begin +# endif + , &two_lists::two_end)) + ; + + class_<list_list>("list_list") + .def("push_back", push_list_back) + .def("__iter__", iterator<list_list,return_internal_reference<> >()) + ; +} + +#include "module_tail.cpp" diff --git a/src/boost/libs/python/test/iterator.py b/src/boost/libs/python/test/iterator.py new file mode 100644 index 000000000..314a35676 --- /dev/null +++ b/src/boost/libs/python/test/iterator.py @@ -0,0 +1,78 @@ +# Copyright David Abrahams 2004. 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) +from __future__ import print_function +''' +>>> from iterator_ext import * +>>> from input_iterator import * +>>> x = list_int() +>>> x.push_back(1) +>>> x.back() +1 +>>> x.push_back(3) +>>> x.push_back(5) +>>> for y in x: +... print(y) +1 +3 +5 +>>> z = range(x) +>>> for y in z: +... print(y) +1 +3 +5 + + Range2 wraps a transform_iterator which doubles the elements it + traverses. This proves we can wrap input iterators + +>>> z2 = range2(x) +>>> for y in z2: +... print(y) +2 +6 +10 + +>>> l2 = two_lists() +>>> for y in l2.primes: +... print(y) +2 +3 +5 +7 +11 +13 +>>> for y in l2.evens: +... print(y) +2 +4 +6 +8 +10 +12 +>>> ll = list_list() +>>> ll.push_back(x) +>>> x.push_back(7) +>>> ll.push_back(x) +>>> for a in ll: #doctest: +NORMALIZE_WHITESPACE +... for b in a: +... print(b, end='') +... print('') +... +1 3 5 +1 3 5 7 +''' +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/keywords.cpp b/src/boost/libs/python/test/keywords.cpp new file mode 100644 index 000000000..39bac0627 --- /dev/null +++ b/src/boost/libs/python/test/keywords.cpp @@ -0,0 +1,118 @@ +// Copyright David Abrahams 2002. +// 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) +#include <boost/python.hpp> +#include <string> + +struct Foo +{ + Foo( + int a = 0 + , double b = 0 + , const std::string &n = std::string() + ) : + a_(a) + , b_(b) + , n_(n) + {} + + void set(int a=0, double b=0, const std::string &n=std::string()) + { + a_ = a; + b_ = b; + n_ = n; + } + + int geta() const { return a_; } + + double getb() const { return b_; } + + std::string getn() const { return n_; } + +private: + int a_; + double b_; + std::string n_; +}; + +struct Bar +{ + Bar( + int a = 0 + , double b = 0 + , const std::string &n = std::string() + ) : + a_(a) + , b_(b) + , n_(n) + {} + + void set(int a=0, double b=0, const std::string &n=std::string()) + { + a_ = a; + b_ = b; + n_ = n; + } + + void seta(int a) + { + a_ = a; + } + + int geta() const { return a_; } + + double getb() const { return b_; } + + std::string getn() const { return n_; } + +private: + int a_; + double b_; + std::string n_; +}; + +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(bar_set, Bar::set, 0,3) + +using namespace boost::python; +BOOST_PYTHON_MODULE(keywords) +{ +#if BOOST_WORKAROUND(__GNUC__, == 2) + using boost::python::arg; +#endif + + class_<Foo>( + "Foo" + , init<int, double, const std::string&>( + ( arg("a") = 0 + , arg("b") = 0.0 + , arg("n") = std::string() + ) + )) + + .def("set", &Foo::set, (arg("a") = 0, arg("b") = 0.0, arg("n") = std::string()) ) + + .def("set2", &Foo::set, (arg("a"), "b", "n") ) + + .def("a", &Foo::geta) + .def("b", &Foo::getb) + .def("n", &Foo::getn) + ; + + class_<Bar>("Bar" + , init<optional<int, double, const std::string &> >() + ) + .def("set", &Bar::set, bar_set()) + .def("set2", &Bar::set, bar_set("set2's docstring")) + .def("seta", &Bar::seta, arg("a")) + + .def("a", &Bar::geta) + .def("b", &Bar::getb) + .def("n", &Bar::getn) + ; + +} + + + +#include "module_tail.cpp" diff --git a/src/boost/libs/python/test/keywords_test.py b/src/boost/libs/python/test/keywords_test.py new file mode 100644 index 000000000..bac7d17c1 --- /dev/null +++ b/src/boost/libs/python/test/keywords_test.py @@ -0,0 +1,106 @@ +# Copyright David Abrahams 2004. 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) +''' +>>> from keywords import * +>>> f = Foo() +>>> f.a(), f.b(), f.n() +(0, 0.0, '') +>>> f = Foo(1) +>>> f.a(), f.b(), f.n() +(1, 0.0, '') +>>> f = Foo(1,1.0) +>>> f.a(), f.b(), f.n() +(1, 1.0, '') +>>> f = Foo(1,1.0,"1") +>>> f.a(), f.b(), f.n() +(1, 1.0, '1') +>>> f = Foo(a=1) +>>> f.a(), f.b(), f.n() +(1, 0.0, '') +>>> f = Foo(b=1) +>>> f.a(), f.b(), f.n() +(0, 1.0, '') +>>> f = Foo(n="1") +>>> f.a(), f.b(), f.n() +(0, 0.0, '1') +>>> f = Foo(1,n="1") +>>> f.a(), f.b(), f.n() +(1, 0.0, '1') +>>> f.set() +>>> f.a(), f.b(), f.n() +(0, 0.0, '') +>>> f.set(1) +>>> f.a(), f.b(), f.n() +(1, 0.0, '') +>>> f.set(1,1.0) +>>> f.a(), f.b(), f.n() +(1, 1.0, '') +>>> f.set(1,1.0,"1") +>>> f.a(), f.b(), f.n() +(1, 1.0, '1') +>>> f.set(a=1) +>>> f.a(), f.b(), f.n() +(1, 0.0, '') +>>> f.set(b=1) +>>> f.a(), f.b(), f.n() +(0, 1.0, '') +>>> f.set(n="1") +>>> f.a(), f.b(), f.n() +(0, 0.0, '1') +>>> f.set(1,n="1") +>>> f.a(), f.b(), f.n() +(1, 0.0, '1') +>>> f.set2(b=2.0,n="2",a=2) +>>> f.a(), f.b(), f.n() +(2, 2.0, '2') + +# lets see how badly we've broken the 'regular' functions +>>> f = Bar() +>>> f.a(), f.b(), f.n() +(0, 0.0, '') +>>> f = Bar(1) +>>> f.a(), f.b(), f.n() +(1, 0.0, '') +>>> f = Bar(1,1.0) +>>> f.a(), f.b(), f.n() +(1, 1.0, '') +>>> f = Bar(1,1.0,"1") +>>> f.a(), f.b(), f.n() +(1, 1.0, '1') +>>> f.set() +>>> f.a(), f.b(), f.n() +(0, 0.0, '') +>>> f.set(1) +>>> f.a(), f.b(), f.n() +(1, 0.0, '') +>>> f.set(1,1.0) +>>> f.a(), f.b(), f.n() +(1, 1.0, '') +>>> f.set(1,1.0,"1") +>>> f.a(), f.b(), f.n() +(1, 1.0, '1') +>>> f.set2.__doc__.splitlines()[1] +'set2( (Bar)arg1 [, (int)arg2 [, (float)arg3 [, (str)arg4]]]) -> None :' +>>> f.set2.__doc__.splitlines()[2] +" set2's docstring" +''' + + + + +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) + diff --git a/src/boost/libs/python/test/list.cpp b/src/boost/libs/python/test/list.cpp new file mode 100644 index 000000000..3e9fcbe66 --- /dev/null +++ b/src/boost/libs/python/test/list.cpp @@ -0,0 +1,154 @@ +// Copyright David Abrahams 2002. +// 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) + +#include <boost/python/module.hpp> +#include <boost/python/def.hpp> +#include <boost/python/class.hpp> +#include <boost/python/list.hpp> +#include <boost/python/tuple.hpp> +#include <boost/python/dict.hpp> +#include <boost/python/make_function.hpp> +#include <boost/lexical_cast.hpp> +#define BOOST_ENABLE_ASSERT_HANDLER +#include <boost/assert.hpp> +#include "test_class.hpp" + +using namespace boost::python; + +object new_list() +{ + return list(); +} + +list listify(object x) +{ + return list(x); +} + +object listify_string(char const* s) +{ + return list(s); +} + +std::string x_rep(test_class<> const& x) +{ + return "X(" + boost::lexical_cast<std::string>(x.value()) + ")"; +} + +object apply_object_list(object f, list x) +{ + return f(x); +} + +list apply_list_list(object f, list x) +{ + return call<list>(f.ptr(), x); +} + +void append_object(list& x, object y) +{ + x.append(y); +} + +void append_list(list& x, list const& y) +{ + x.append(y); +} + +typedef test_class<> X; + +int notcmp(object const& x, object const& y) +{ + return y < x ? -1 : y > x ? 1 : 0; +} + +void exercise(list x, object y, object print) +{ + x.append(y); + x.append(5); + x.append(X(3)); + + print("after append:"); + print(x); + + print("number of", y, "instances:", x.count(y)); + + print("number of 5s:", x.count(5)); + + x.extend("xyz"); + print("after extend:"); + print(x); + print("index of", y, "is:", x.index(y)); + print("index of 'l' is:", x.index("l")); + + x.insert(4, 666); + print("after inserting 666:"); + print(x); + print("inserting with object as index:"); + x.insert(x[x.index(5)], "---"); + print(x); + + print("popping..."); + x.pop(); + print(x); + x.pop(x[x.index(5)]); + print(x); + x.pop(x.index(5)); + print(x); + + print("removing", y); + x.remove(y); + print(x); + print("removing", 666); + x.remove(666); + print(x); + + print("reversing..."); + x.reverse(); + print(x); + + print("sorted:"); + x.pop(2); // make sorting predictable + x.pop(2); // remove [1,2] so the list is sortable in py3k + x.sort(); + print(x); + + print("reverse sorted:"); +#if PY_VERSION_HEX >= 0x03000000 + x.sort(*tuple(), **dict(make_tuple(make_tuple("reverse", true)))); +#else + x.sort(¬cmp); +#endif + print(x); + + list w; + w.append(5); + w.append(6); + w += "hi"; + BOOST_ASSERT(w[0] == 5); + BOOST_ASSERT(w[1] == 6); + BOOST_ASSERT(w[2] == 'h'); + BOOST_ASSERT(w[3] == 'i'); +} + +BOOST_PYTHON_MODULE(list_ext) +{ + def("new_list", new_list); + def("listify", listify); + def("listify_string", listify_string); + def("apply_object_list", apply_object_list); + def("apply_list_list", apply_list_list); + + def("append_object", append_object); + def("append_list", append_list); + + def("exercise", exercise); + + class_<X>("X", init<int>()) + .def( "__repr__", x_rep) + ; +} + +#include "module_tail.cpp" diff --git a/src/boost/libs/python/test/list.py b/src/boost/libs/python/test/list.py new file mode 100644 index 000000000..913032db8 --- /dev/null +++ b/src/boost/libs/python/test/list.py @@ -0,0 +1,119 @@ +# Copyright David Abrahams 2004. 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) +from __future__ import print_function +''' +>>> from list_ext import * + +>>> new_list() +[] + +>>> listify((1,2,3)) +[1, 2, 3] + +>>> letters = listify_string('hello') +>>> letters +['h', 'e', 'l', 'l', 'o'] + +>>> X(22) +X(22) + +>>> def identity(x): +... return x +>>> assert apply_object_list(identity, letters) is letters + + 5 is not convertible to a list + +>>> try: result = apply_object_list(identity, 5) +... except TypeError: pass +... else: print('expected an exception, got', result, 'instead') + +>>> assert apply_list_list(identity, letters) is letters + + 5 is not convertible to a list as a return value + +>>> try: result = apply_list_list(len, letters) +... except TypeError: pass +... else: print('expected an exception, got', result, 'instead') + +>>> append_object(letters, '.') +>>> letters +['h', 'e', 'l', 'l', 'o', '.'] + + tuples do not automatically convert to lists when passed as arguments + +>>> try: append_list(letters, (1,2)) +... except TypeError: pass +... else: print('expected an exception') + +>>> append_list(letters, [1,2]) +>>> letters +['h', 'e', 'l', 'l', 'o', '.', [1, 2]] + + Check that subclass functions are properly called + +>>> class mylist(list): +... def append(self, o): +... list.append(self, o) +... if not hasattr(self, 'nappends'): +... self.nappends = 1 +... else: +... self.nappends += 1 +... +>>> l2 = mylist() +>>> append_object(l2, 'hello') +>>> append_object(l2, 'world') +>>> l2 +['hello', 'world'] +>>> l2.nappends +2 + +>>> def printer(*args): +... for x in args: print( x,) +... print('') +... + +>>> y = X(42) +>>> exercise(letters, y, printer) #doctest: +NORMALIZE_WHITESPACE +after append: +['h', 'e', 'l', 'l', 'o', '.', [1, 2], X(42), 5, X(3)] +number of X(42) instances: 1 +number of 5s: 1 +after extend: +['h', 'e', 'l', 'l', 'o', '.', [1, 2], X(42), 5, X(3), 'x', 'y', 'z'] +index of X(42) is: 7 +index of 'l' is: 2 +after inserting 666: +['h', 'e', 'l', 'l', 666, 'o', '.', [1, 2], X(42), 5, X(3), 'x', 'y', 'z'] +inserting with object as index: +['h', 'e', 'l', 'l', 666, '---', 'o', '.', [1, 2], X(42), 5, X(3), 'x', 'y', 'z'] +popping... +['h', 'e', 'l', 'l', 666, '---', 'o', '.', [1, 2], X(42), 5, X(3), 'x', 'y'] +['h', 'e', 'l', 'l', 666, 'o', '.', [1, 2], X(42), 5, X(3), 'x', 'y'] +['h', 'e', 'l', 'l', 666, 'o', '.', [1, 2], X(42), X(3), 'x', 'y'] +removing X(42) +['h', 'e', 'l', 'l', 666, 'o', '.', [1, 2], X(3), 'x', 'y'] +removing 666 +['h', 'e', 'l', 'l', 'o', '.', [1, 2], X(3), 'x', 'y'] +reversing... +['y', 'x', X(3), [1, 2], '.', 'o', 'l', 'l', 'e', 'h'] +sorted: +['.', 'e', 'h', 'l', 'l', 'o', 'x', 'y'] +reverse sorted: +['y', 'x', 'o', 'l', 'l', 'h', 'e', '.'] +''' + +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/long.cpp b/src/boost/libs/python/test/long.cpp new file mode 100644 index 000000000..61e4518ff --- /dev/null +++ b/src/boost/libs/python/test/long.cpp @@ -0,0 +1,63 @@ +// Copyright David Abrahams 2002. +// 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) + +#include <boost/python/module.hpp> +#include <boost/python/def.hpp> +#include <boost/python/long.hpp> +#include <boost/python/class.hpp> +#define BOOST_ENABLE_ASSERT_HANDLER +#include <boost/assert.hpp> + +using namespace boost::python; + +object new_long() +{ + return long_(); +} + +long_ longify(object x) +{ + return long_(x); +} + +object longify_string(char const* s) +{ + return long_(s); +} + +char const* is_long1(long_& x) +{ + long_ y = x; + x += 50; + BOOST_ASSERT(x == y + 50); + return "yes"; +} + +int is_long2(char const*) +{ + return 0; +} + +// tests for accepting objects (and derived classes) in constructors +// from "Milind Patil" <milind_patil-at-hotmail.com> + +struct Y +{ + Y(boost::python::long_) {} +}; + +BOOST_PYTHON_MODULE(long_ext) +{ + def("new_long", new_long); + def("longify", longify); + def("longify_string", longify_string); + def("is_long", is_long1); + def("is_long", is_long2); + + class_< Y >("Y", init< boost::python::long_ >()) + ; +} + +#include "module_tail.cpp" diff --git a/src/boost/libs/python/test/long.py b/src/boost/libs/python/test/long.py new file mode 100644 index 000000000..f63923632 --- /dev/null +++ b/src/boost/libs/python/test/long.py @@ -0,0 +1,36 @@ +# Copyright David Abrahams 2004. 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) +import sys +if (sys.version_info.major >= 3): + long = int +''' +>>> from long_ext import * +>>> print(new_long()) +0 +>>> print(longify(42)) +42 +>>> print(longify_string('300')) +300 +>>> is_long(long(20)) +'yes' +>>> is_long('20') +0 + +>>> x = Y(long(4294967295)) +''' + +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/m1.cpp b/src/boost/libs/python/test/m1.cpp new file mode 100644 index 000000000..a873bc35d --- /dev/null +++ b/src/boost/libs/python/test/m1.cpp @@ -0,0 +1,344 @@ +// Copyright David Abrahams 2001. +// 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) + + +#include <boost/python/def.hpp> +#include <boost/python/module.hpp> +#include <boost/python/class.hpp> +#include <boost/python/lvalue_from_pytype.hpp> +#include <boost/python/copy_const_reference.hpp> +#include <boost/python/return_value_policy.hpp> +#include <boost/python/to_python_converter.hpp> +#include <boost/python/errors.hpp> +#include <boost/python/manage_new_object.hpp> +#include <boost/python/converter/pytype_function.hpp> +#include <string.h> +#include "simple_type.hpp" +#include "complicated.hpp" + +// Declare some straightforward extension types +extern "C" void +dealloc(PyObject* self) +{ + PyObject_Del(self); +} + +// Noddy is a type we got from one of the Python sample files +struct NoddyObject : PyObject +{ + int x; +}; + +PyTypeObject NoddyType = { + PyVarObject_HEAD_INIT(NULL, 0) + const_cast<char*>("Noddy"), + sizeof(NoddyObject), + 0, + dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + 0, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ + 0, /* tp_mro */ + 0, /* tp_cache */ + 0, /* tp_subclasses */ + 0, /* tp_weaklist */ +#if PYTHON_API_VERSION >= 1012 + 0 /* tp_del */ +#endif +}; + +// Create a Noddy containing 42 +PyObject* new_noddy() +{ + NoddyObject* noddy = PyObject_New(NoddyObject, &NoddyType); + noddy->x = 42; + return (PyObject*)noddy; +} + +// Simple is a wrapper around a struct simple, which just contains a char* +struct SimpleObject +{ + PyObject_HEAD + simple x; +}; + +struct extract_simple_object +{ + static simple& execute(SimpleObject& o) { return o.x; } +}; + +PyTypeObject SimpleType = { + PyVarObject_HEAD_INIT(NULL, 0) + const_cast<char*>("Simple"), + sizeof(SimpleObject), + 0, + dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + 0, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ + 0, /* tp_mro */ + 0, /* tp_cache */ + 0, /* tp_subclasses */ + 0, /* tp_weaklist */ +#if PYTHON_API_VERSION >= 1012 + 0 /* tp_del */ +#endif +}; + +// Create a Simple containing "hello, world" +PyObject* new_simple() +{ + SimpleObject* simple = PyObject_New(SimpleObject, &SimpleType); + simple->x.s = const_cast<char*>("hello, world"); + return (PyObject*)simple; +} + +// +// Declare some wrappers/unwrappers to test the low-level conversion +// mechanism. +// +using boost::python::to_python_converter; + +// Wrap a simple by copying it into a Simple +struct simple_to_python + : to_python_converter<simple, simple_to_python, true> + //, boost::python::converter::wrap_pytype<&SimpleType> +{ + static PyObject* convert(simple const& x) + { + SimpleObject* p = PyObject_New(SimpleObject, &SimpleType); + p->x = x; + return (PyObject*)p; + } + static PyTypeObject const *get_pytype(){return &SimpleType; } +}; + +struct int_from_noddy +{ + static int& execute(NoddyObject& p) + { + return p.x; + } +}; + +// +// Some C++ functions to expose to Python +// + +// Returns the length of s's held string +int f(simple const& s) +{ + return strlen(s.s); +} + +int f_mutable_ref(simple& s) +{ + return strlen(s.s); +} + +int f_mutable_ptr(simple* s) +{ + return strlen(s->s); +} + +int f_const_ptr(simple const* s) +{ + return strlen(s->s); +} + +int f2(SimpleObject const& s) +{ + return strlen(s.x.s); +} + +// A trivial passthru function for simple objects +simple const& g(simple const& x) +{ + return x; +} + +struct A +{ + A() : x(0) {} + virtual ~A() {} + char const* name() { return "A"; } + int x; +}; + +struct B : A +{ + B() : x(1) {} + static char const* name(B*) { return "B"; } + int x; +}; + +struct C : A +{ + C() : x(2) {} + char const* name() { return "C"; } + virtual ~C() {} + int x; +}; + +struct D : B, C +{ + D() : x(3) {} + char const* name() { return "D"; } + int x; +}; + +A take_a(A const& a) { return a; } +B take_b(B& b) { return b; } +C take_c(C* c) { return *c; } +D take_d(D* const& d) { return *d; } + +D take_d_shared_ptr(boost::shared_ptr<D> d) { return *d; } + +boost::shared_ptr<A> d_factory() { return boost::shared_ptr<B>(new D); } + +struct Unregistered {}; +Unregistered make_unregistered(int) { return Unregistered(); } + +Unregistered* make_unregistered2(int) { return new Unregistered; } + +BOOST_PYTHON_MODULE(m1) +{ + using namespace boost::python; + using boost::shared_ptr; + + simple_to_python(); + + lvalue_from_pytype<int_from_noddy,&NoddyType>(); + + lvalue_from_pytype< +#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 // doesn't support non-type member pointer parameters + extract_member<SimpleObject, simple, &SimpleObject::x> +#else + extract_simple_object +#endif + , &SimpleType + >(); + + lvalue_from_pytype<extract_identity<SimpleObject>,&SimpleType>(); + + def("new_noddy", new_noddy); + def("new_simple", new_simple); + + def("make_unregistered", make_unregistered); + def("make_unregistered2", make_unregistered2, return_value_policy<manage_new_object>()); + + // Expose f() in all its variations + def("f", f); + def("f_mutable_ref", f_mutable_ref); + def("f_mutable_ptr", f_mutable_ptr); + def("f_const_ptr", f_const_ptr); + + def("f2", f2); + + // Expose g() + def("g", g , return_value_policy<copy_const_reference>() + ); + + def("take_a", take_a); + def("take_b", take_b); + def("take_c", take_c); + def("take_d", take_d); + + + def("take_d_shared_ptr", take_d_shared_ptr); + def("d_factory", d_factory); + + class_<A, shared_ptr<A> >("A") + .def("name", &A::name) + ; + + // sequence points don't ensure that "A" is constructed before "B" + // or "C" below if we make them part of the same chain + class_<B,bases<A> >("B") + .def("name", &B::name) + ; + + class_<C,bases<A> >("C") + .def("name", &C::name) + ; + + class_<D, bases<B,C> >("D") + .def("name", &D::name) + ; + + class_<complicated>("complicated", + init<simple const&,int>()) + .def(init<simple const&>()) + .def("get_n", &complicated::get_n) + ; +} + +#include "module_tail.cpp" diff --git a/src/boost/libs/python/test/m2.cpp b/src/boost/libs/python/test/m2.cpp new file mode 100644 index 000000000..5bcdea604 --- /dev/null +++ b/src/boost/libs/python/test/m2.cpp @@ -0,0 +1,108 @@ +// Copyright David Abrahams 2001. +// 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) + +// This module exercises the converters exposed in m1 at a low level +// by exposing raw Python extension functions that use wrap<> and +// unwrap<> objects. +#include <boost/python/module.hpp> +#include <boost/python/def.hpp> +#include <boost/python/copy_non_const_reference.hpp> +#include <boost/python/copy_const_reference.hpp> +#include <boost/python/return_value_policy.hpp> +#include "simple_type.hpp" + +#if PY_VERSION_HEX >= 0x03000000 +# define PyString_FromString PyUnicode_FromString +# define PyInt_FromLong PyLong_FromLong +#endif + +// Get a simple (by value) from the argument, and return the +// string it holds. +PyObject* unwrap_simple(simple x) +{ + return PyString_FromString(x.s); +} + +// Likewise, but demands that its possible to get a non-const +// reference to the simple. +PyObject* unwrap_simple_ref(simple& x) +{ + return PyString_FromString(x.s); +} + +// Likewise, with a const reference to the simple object. +PyObject* unwrap_simple_const_ref(simple const& x) +{ + return PyString_FromString(x.s); +} + +// Get an int (by value) from the argument, and convert it to a +// Python Int. +PyObject* unwrap_int(int x) +{ + return PyInt_FromLong(x); +} + +// Get a non-const reference to an int from the argument +PyObject* unwrap_int_ref(int& x) +{ + return PyInt_FromLong(x); +} + +// Get a const reference to an int from the argument. +PyObject* unwrap_int_const_ref(int const& x) +{ + return PyInt_FromLong(x); +} + +#if PY_VERSION_HEX >= 0x03000000 +# undef PyString_FromString +# undef PyInt_FromLong +#endif + +// rewrap<T> extracts a T from the argument, then converts the T back +// to a PyObject* and returns it. +template <class T> +struct rewrap +{ + static T f(T x) { return x; } +}; + +BOOST_PYTHON_MODULE(m2) +{ + using boost::python::return_value_policy; + using boost::python::copy_const_reference; + using boost::python::copy_non_const_reference; + using boost::python::def; + + def("unwrap_int", unwrap_int); + def("unwrap_int_ref", unwrap_int_ref); + def("unwrap_int_const_ref", unwrap_int_const_ref); + def("unwrap_simple", unwrap_simple); + def("unwrap_simple_ref", unwrap_simple_ref); + def("unwrap_simple_const_ref", unwrap_simple_const_ref); + + def("wrap_int", &rewrap<int>::f); + + def("wrap_int_ref", &rewrap<int&>::f + , return_value_policy<copy_non_const_reference>() + ); + + def("wrap_int_const_ref", &rewrap<int const&>::f + , return_value_policy<copy_const_reference>() + ); + + def("wrap_simple", &rewrap<simple>::f); + + def("wrap_simple_ref", &rewrap<simple&>::f + , return_value_policy<copy_non_const_reference>() + ); + + def("wrap_simple_const_ref", &rewrap<simple const&>::f + , return_value_policy<copy_const_reference>() + ); +} + +#include "module_tail.cpp" diff --git a/src/boost/libs/python/test/map_indexing_suite.cpp b/src/boost/libs/python/test/map_indexing_suite.cpp new file mode 100644 index 000000000..b8771cf41 --- /dev/null +++ b/src/boost/libs/python/test/map_indexing_suite.cpp @@ -0,0 +1,68 @@ +// Copyright Joel de Guzman 2004. 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) + +#include <boost/python/suite/indexing/map_indexing_suite.hpp> +#include <boost/python/module.hpp> +#include <boost/python/def.hpp> +#include <boost/python/implicit.hpp> + +using namespace boost::python; + +struct X // a container element +{ + std::string s; + X():s("default") {} + X(std::string s):s(s) {} + std::string repr() const { return s; } + void reset() { s = "reset"; } + void foo() { s = "foo"; } + bool operator==(X const& x) const { return s == x.s; } + bool operator!=(X const& x) const { return s != x.s; } +}; + +std::string x_value(X const& x) +{ + return "gotya " + x.s; +} + + +BOOST_PYTHON_MODULE(map_indexing_suite_ext) +{ + class_<X>("X") + .def(init<>()) + .def(init<X>()) + .def(init<std::string>()) + .def("__repr__", &X::repr) + .def("reset", &X::reset) + .def("foo", &X::foo) + ; + + def("x_value", x_value); + implicitly_convertible<std::string, X>(); + + class_<std::map<std::string, X> >("XMap") + .def(map_indexing_suite<std::map<std::string, X> >()) + ; + + void int_map_indexing_suite(); // moved to int_map_indexing_suite.cpp to + int_map_indexing_suite(); // avoid MSVC 6/7 internal structure overflow + +#if 0 + // Compile check only... + class_<std::map<int, int> >("IntMap") + .def(map_indexing_suite<std::map<int, int> >()) + ; +#endif + + // Some more.. + class_<std::map<std::string, boost::shared_ptr<X> > >("TestMap") + .def(map_indexing_suite<std::map<std::string, boost::shared_ptr<X> >, true>()) + ; + + void a_map_indexing_suite(); // moved to a_map_indexing_suite.cpp to + a_map_indexing_suite(); // avoid MSVC 6/7 internal structure overflow + +} + +#include "module_tail.cpp" diff --git a/src/boost/libs/python/test/map_indexing_suite.py b/src/boost/libs/python/test/map_indexing_suite.py new file mode 100644 index 000000000..a5750a833 --- /dev/null +++ b/src/boost/libs/python/test/map_indexing_suite.py @@ -0,0 +1,243 @@ +# Copyright Joel de Guzman 2004. 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) +from __future__ import print_function +''' + +##################################################################### +# Check an object that we will use as container element +##################################################################### + +>>> from map_indexing_suite_ext import * +>>> assert "map_indexing_suite_IntMap_entry" in dir() +>>> assert "map_indexing_suite_TestMap_entry" in dir() +>>> assert "map_indexing_suite_XMap_entry" in dir() +>>> assert "map_indexing_suite_AMap_entry" in dir() +>>> x = X('hi') +>>> x +hi +>>> x.reset() # a member function that modifies X +>>> x +reset +>>> x.foo() # another member function that modifies X +>>> x +foo + +# test that a string is implicitly convertible +# to an X +>>> x_value('bochi bochi') +'gotya bochi bochi' + +##################################################################### +# Iteration +##################################################################### +>>> def print_xmap(xmap): +... s = '[ ' +... for x in xmap: +... s += repr(x) +... s += ' ' +... s += ']' +... print(s) + +##################################################################### +# Setting (adding entries) +##################################################################### +>>> xm = XMap() +>>> xm['joel'] = 'apple' +>>> xm['tenji'] = 'orange' +>>> xm['mariel'] = 'grape' +>>> xm['tutit'] = 'banana' +>>> xm['kim'] = 'kiwi' + +>>> print_xmap(xm) +[ (joel, apple) (kim, kiwi) (mariel, grape) (tenji, orange) (tutit, banana) ] + +##################################################################### +# Changing an entry +##################################################################### +>>> xm['joel'] = 'pineapple' +>>> print_xmap(xm) +[ (joel, pineapple) (kim, kiwi) (mariel, grape) (tenji, orange) (tutit, banana) ] + +##################################################################### +# Deleting an entry +##################################################################### +>>> del xm['joel'] +>>> print_xmap(xm) +[ (kim, kiwi) (mariel, grape) (tenji, orange) (tutit, banana) ] + +##################################################################### +# adding an entry +##################################################################### +>>> xm['joel'] = 'apple' +>>> print_xmap(xm) +[ (joel, apple) (kim, kiwi) (mariel, grape) (tenji, orange) (tutit, banana) ] + +##################################################################### +# Indexing +##################################################################### +>>> len(xm) +5 +>>> xm['joel'] +apple +>>> xm['tenji'] +orange +>>> xm['mariel'] +grape +>>> xm['tutit'] +banana +>>> xm['kim'] +kiwi + +##################################################################### +# Calling a mutating function of a container element +##################################################################### +>>> xm['joel'].reset() +>>> xm['joel'] +reset + +##################################################################### +# Copying a container element +##################################################################### +>>> x = X(xm['mariel']) +>>> x +grape +>>> x.foo() +>>> x +foo +>>> xm['mariel'] # should not be changed to 'foo' +grape + +##################################################################### +# Referencing a container element +##################################################################### +>>> x = xm['mariel'] +>>> x +grape +>>> x.foo() +>>> x +foo +>>> xm['mariel'] # should be changed to 'foo' +foo + +>>> xm['mariel'] = 'grape' # take it back +>>> xm['joel'] = 'apple' # take it back + +##################################################################### +# Contains +##################################################################### +>>> assert 'joel' in xm +>>> assert 'mariel' in xm +>>> assert 'tenji' in xm +>>> assert 'tutit' in xm +>>> assert 'kim' in xm +>>> assert not 'X' in xm +>>> assert not 12345 in xm + +##################################################################### +# Some references to the container elements +##################################################################### + +>>> z0 = xm['joel'] +>>> z1 = xm['mariel'] +>>> z2 = xm['tenji'] +>>> z3 = xm['tutit'] +>>> z4 = xm['kim'] + +>>> z0 # proxy +apple +>>> z1 # proxy +grape +>>> z2 # proxy +orange +>>> z3 # proxy +banana +>>> z4 # proxy +kiwi + +##################################################################### +# Delete some container element +##################################################################### + +>>> del xm['tenji'] +>>> print_xmap(xm) +[ (joel, apple) (kim, kiwi) (mariel, grape) (tutit, banana) ] + +>>> del xm['tutit'] +>>> print_xmap(xm) +[ (joel, apple) (kim, kiwi) (mariel, grape) ] + +##################################################################### +# Show that the references are still valid +##################################################################### +>>> z0 # proxy +apple +>>> z1 # proxy +grape +>>> z2 # proxy detached +orange +>>> z3 # proxy detached +banana +>>> z4 # proxy +kiwi + +##################################################################### +# Show that iteration allows mutable access to the elements +##################################################################### +>>> for x in xm: +... x.data().reset() +>>> print_xmap(xm) +[ (joel, reset) (kim, reset) (mariel, reset) ] + +##################################################################### +# Some more... +##################################################################### + +>>> tm = TestMap() +>>> tm["joel"] = X("aaa") +>>> tm["kimpo"] = X("bbb") +>>> print_xmap(tm) +[ (joel, aaa) (kimpo, bbb) ] +>>> for el in tm: #doctest: +NORMALIZE_WHITESPACE +... print(el.key(), end='') +... dom = el.data() +joel kimpo + +##################################################################### +# Test custom converter... +##################################################################### + +>>> am = AMap() +>>> am[3] = 4 +>>> am[3] +4 +>>> for i in am: +... i.data() +4 + +##################################################################### +# END.... +##################################################################### + +''' + + +def run(args = None): + import sys + import doctest + + if args is not None: + sys.argxm = args + return doctest.testmod(sys.modules.get(__name__)) + +if __name__ == '__main__': + print('running...') + import sys + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) + + + + + diff --git a/src/boost/libs/python/test/minimal.cpp b/src/boost/libs/python/test/minimal.cpp new file mode 100644 index 000000000..5efee26bc --- /dev/null +++ b/src/boost/libs/python/test/minimal.cpp @@ -0,0 +1,16 @@ +// Copyright David Abrahams 2002. +// 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) +#include <boost/python/module.hpp> +#include <boost/python/def.hpp> + +#if defined(_AIX) && defined(__EDG_VERSION__) && __EDG_VERSION__ < 245 +# include <iostream> // works around a KCC intermediate code generation bug +#endif + +BOOST_PYTHON_MODULE(minimal_ext) +{ +} + +#include "module_tail.cpp" diff --git a/src/boost/libs/python/test/minimal.py b/src/boost/libs/python/test/minimal.py new file mode 100644 index 000000000..ee75e3705 --- /dev/null +++ b/src/boost/libs/python/test/minimal.py @@ -0,0 +1,7 @@ +# Copyright David Abrahams 2004. 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) +print("IMPORTING minimal_ext") +import minimal_ext +print("DONE IMPORTING minimal_ext") + diff --git a/src/boost/libs/python/test/module_tail.cpp b/src/boost/libs/python/test/module_tail.cpp new file mode 100644 index 000000000..f9cdca189 --- /dev/null +++ b/src/boost/libs/python/test/module_tail.cpp @@ -0,0 +1,58 @@ +// Copyright David Abrahams 2001. +// 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) + +#if defined(_WIN32) +# ifdef __MWERKS__ +# pragma ANSI_strict off +# endif +# include <windows.h> +# ifdef __MWERKS__ +# pragma ANSI_strict reset +# endif + +# ifdef _MSC_VER +# include <eh.h> // for _set_se_translator() +# pragma warning(push) +# pragma warning(disable:4297) +# pragma warning(disable:4535) +extern "C" void straight_to_debugger(unsigned int, EXCEPTION_POINTERS*) +{ + throw; +} +extern "C" void (*old_translator)(unsigned, EXCEPTION_POINTERS*) + = _set_se_translator(straight_to_debugger); +# pragma warning(pop) +# endif + +#endif // _WIN32 + +#include <exception> +#include <boost/python/extract.hpp> +#include <boost/python/str.hpp> +struct test_failure : std::exception +{ + test_failure(char const* expr, char const* /*function*/, char const* file, unsigned line) + : msg(file + boost::python::str(":%s:") % line + ": Boost.Python assertion failure: " + expr) + {} + + ~test_failure() throw() {} + + char const* what() const throw() + { + return boost::python::extract<char const*>(msg)(); + } + + boost::python::str msg; +}; + +namespace boost +{ + +void assertion_failed(char const * expr, char const * function, char const * file, long line) +{ + throw ::test_failure(expr,function, file, line); +} + +} // namespace boost diff --git a/src/boost/libs/python/test/multi_arg_constructor.cpp b/src/boost/libs/python/test/multi_arg_constructor.cpp new file mode 100644 index 000000000..7d49bb556 --- /dev/null +++ b/src/boost/libs/python/test/multi_arg_constructor.cpp @@ -0,0 +1,27 @@ +// Copyright David Abrahams 2004. 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) +#include <boost/python/module.hpp> +#include <boost/python/def.hpp> +#include <boost/python/class.hpp> + +struct A +{ + A(const double, const double, const double, const double, const double + , const double, const double + , const double, const double + ) {} +}; + +BOOST_PYTHON_MODULE(multi_arg_constructor_ext) +{ + using namespace boost::python; + + class_<A>( + "A" + , init<double, double, double, double, double, double, double, double, double>() + ) + ; + +} + diff --git a/src/boost/libs/python/test/multi_arg_constructor.py b/src/boost/libs/python/test/multi_arg_constructor.py new file mode 100644 index 000000000..5d8b4a516 --- /dev/null +++ b/src/boost/libs/python/test/multi_arg_constructor.py @@ -0,0 +1,21 @@ +# Copyright David Abrahams 2004. 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) +''' +>>> from multi_arg_constructor_ext import * +>>> a = A(1.0, 2, 3, 4, 5, 6, 7.0, 8.1, 9.3) +''' +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/nested.cpp b/src/boost/libs/python/test/nested.cpp new file mode 100644 index 000000000..de656d2b8 --- /dev/null +++ b/src/boost/libs/python/test/nested.cpp @@ -0,0 +1,51 @@ +// Copyright David Abrahams 2002. +// 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) +#include <boost/python/module.hpp> +#include <boost/python/class.hpp> +#include <boost/python/operators.hpp> +#include <boost/python/scope.hpp> +#include "test_class.hpp" +#if __GNUC__ != 2 +# include <ostream> +#else +# include <ostream.h> +#endif + +typedef test_class<> X; +typedef test_class<1> Y; + +std::ostream& operator<<(std::ostream& s, X const& x) +{ + return s << x.value(); +} + +std::ostream& operator<<(std::ostream& s, Y const& x) +{ + return s << x.value(); +} + + +BOOST_PYTHON_MODULE(nested_ext) +{ + using namespace boost::python; + + // Establish X as the current scope. + scope x_class + = class_<X>("X", init<int>()) + .def(str(self)) + ; + + + // Y will now be defined in the current scope + class_<Y>("Y", init<int>()) + .def(str(self)) + ; +} + + +#include "module_tail.cpp" + + + diff --git a/src/boost/libs/python/test/nested.py b/src/boost/libs/python/test/nested.py new file mode 100644 index 000000000..720790173 --- /dev/null +++ b/src/boost/libs/python/test/nested.py @@ -0,0 +1,40 @@ +# Copyright David Abrahams 2004. 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) +''' + >>> from nested_ext import * + + >>> X + <class 'nested_ext.X'> + + >>> X.__module__ + 'nested_ext' + + >>> X.__name__ + 'X' + + >>> X.Y + <class 'nested_ext.Y'> + + >>> X.Y.__module__ + 'nested_ext' + + >>> X.Y.__name__ + 'Y' + +''' + +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/newtest.py b/src/boost/libs/python/test/newtest.py new file mode 100644 index 000000000..b878d5192 --- /dev/null +++ b/src/boost/libs/python/test/newtest.py @@ -0,0 +1,206 @@ +# Copyright David Abrahams 2004. 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) +""" +>>> from m1 import * + +>>> from m2 import * + + Prove that we get an appropriate error from trying to return a type + for which we have no registered to_python converter + +>>> def check_unregistered(f, msgprefix): +... try: +... f(1) +... except TypeError as x: +... if not str(x).startswith(msgprefix): +... print(str(x)) +... else: +... print('expected a TypeError') +... +>>> check_unregistered(make_unregistered, 'No to_python (by-value) converter found for C++ type') +>>> check_unregistered(make_unregistered2, 'No Python class registered for C++ class') + +>>> n = new_noddy() +>>> s = new_simple() +>>> unwrap_int(n) +42 +>>> unwrap_int_ref(n) +42 +>>> unwrap_int_const_ref(n) +42 +>>> unwrap_simple(s) +'hello, world' +>>> unwrap_simple_ref(s) +'hello, world' +>>> unwrap_simple_const_ref(s) +'hello, world' +>>> unwrap_int(5) +5 + +Can't get a non-const reference to a built-in integer object +>>> try: +... unwrap_int_ref(7) +... except: pass +... else: print('no exception') + +>>> unwrap_int_const_ref(9) +9 + +>>> wrap_int(n) +42 + +try: wrap_int_ref(n) +... except: pass +... else: print('no exception') + +>>> wrap_int_const_ref(n) +42 + +>>> unwrap_simple_ref(wrap_simple(s)) +'hello, world' + +>>> unwrap_simple_ref(wrap_simple_ref(s)) +'hello, world' + +>>> unwrap_simple_ref(wrap_simple_const_ref(s)) +'hello, world' + +>>> f(s) +12 + +>>> unwrap_simple(g(s)) +'hello, world' + +>>> f(g(s)) +12 + +>>> f_mutable_ref(g(s)) +12 + +>>> f_const_ptr(g(s)) +12 + +>>> f_mutable_ptr(g(s)) +12 + +>>> f2(g(s)) +12 + +Create an extension class which wraps "complicated" (init1 and get_n) +are a complicated constructor and member function, respectively. + +>>> c1 = complicated(s, 99) +>>> c1.get_n() +99 +>>> c2 = complicated(s) +>>> c2.get_n() +0 + + a quick regression test for a bug where None could be converted + to the target of any member function. To see it, we need to + access the __dict__ directly, to bypass the type check supplied + by the Method property which wraps the method when accessed as an + attribute. + +>>> try: A.__dict__['name'](None) +... except TypeError: pass +... else: print('expected an exception!') + + +>>> a = A() +>>> b = B() +>>> c = C() +>>> d = D() + + +>>> take_a(a).name() +'A' + +>>> try: +... take_b(a) +... except: pass +... else: print('no exception') + +>>> try: +... take_c(a) +... except: pass +... else: print('no exception') + +>>> try: +... take_d(a) +... except: pass +... else: print('no exception') + +------ +>>> take_a(b).name() +'A' + +>>> take_b(b).name() +'B' + +>>> try: +... take_c(b) +... except: pass +... else: print('no exception') + +>>> try: +... take_d(b) +... except: pass +... else: print('no exception') + +------- +>>> take_a(c).name() +'A' + +>>> try: +... take_b(c) +... except: pass +... else: print('no exception') + +>>> take_c(c).name() +'C' + +>>> try: +... take_d(c) +... except: pass +... else: print('no exception') + +------- +>>> take_a(d).name() +'A' +>>> take_b(d).name() +'B' +>>> take_c(d).name() +'C' +>>> take_d(d).name() +'D' + +>>> take_d_shared_ptr(d).name() +'D' + +>>> d_as_a = d_factory() +>>> dd = take_d(d_as_a) +>>> dd.name() +'D' +>>> print(g.__doc__.splitlines()[1]) +g( (Simple)arg1) -> Simple : + +""" + +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/numpy/dtype.cpp b/src/boost/libs/python/test/numpy/dtype.cpp new file mode 100644 index 000000000..3a011a25e --- /dev/null +++ b/src/boost/libs/python/test/numpy/dtype.cpp @@ -0,0 +1,49 @@ +// Copyright Jim Bosch & Ankit Daftery 2010-2012. +// Copyright Stefan Seefeld 2016. +// 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) + +#include <boost/python/numpy.hpp> +#include <boost/cstdint.hpp> + +namespace p = boost::python; +namespace np = boost::python::numpy; + +template <typename T> +np::dtype accept(T) { + return np::dtype::get_builtin<T>(); +} + +BOOST_PYTHON_MODULE(dtype_ext) +{ + np::initialize(); + // wrap dtype equivalence test, since it isn't available in Python API. + p::def("equivalent", np::equivalent); + // integers, by number of bits + p::def("accept_int8", accept<boost::int8_t>); + p::def("accept_uint8", accept<boost::uint8_t>); + p::def("accept_int16", accept<boost::int16_t>); + p::def("accept_uint16", accept<boost::uint16_t>); + p::def("accept_int32", accept<boost::int32_t>); + p::def("accept_uint32", accept<boost::uint32_t>); + p::def("accept_int64", accept<boost::int64_t>); + p::def("accept_uint64", accept<boost::uint64_t>); + // integers, by C name according to NumPy + p::def("accept_bool_", accept<bool>); + p::def("accept_byte", accept<signed char>); + p::def("accept_ubyte", accept<unsigned char>); + p::def("accept_short", accept<short>); + p::def("accept_ushort", accept<unsigned short>); + p::def("accept_intc", accept<int>); + p::def("accept_uintc", accept<unsigned int>); + // floats and complex + p::def("accept_float32", accept<float>); + p::def("accept_complex64", accept< std::complex<float> >); + p::def("accept_float64", accept<double>); + p::def("accept_complex128", accept< std::complex<double> >); + if (sizeof(long double) > sizeof(double)) { + p::def("accept_longdouble", accept<long double>); + p::def("accept_clongdouble", accept< std::complex<long double> >); + } +} diff --git a/src/boost/libs/python/test/numpy/dtype.py b/src/boost/libs/python/test/numpy/dtype.py new file mode 100644 index 000000000..a27ee0f55 --- /dev/null +++ b/src/boost/libs/python/test/numpy/dtype.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python + +# Copyright Jim Bosch & Ankit Daftery 2010-2012. +# 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) + +import dtype_ext +import unittest +import numpy +import sys +if (sys.version_info.major >= 3): + long = int + +class DtypeTestCase(unittest.TestCase): + + def assertEquivalent(self, a, b): + return self.assert_(dtype_ext.equivalent(a, b), "%r is not equivalent to %r") + + def testIntegers(self): + for bits in (8, 16, 32, 64): + s = getattr(numpy, "int%d" % bits) + u = getattr(numpy, "uint%d" % bits) + fs = getattr(dtype_ext, "accept_int%d" % bits) + fu = getattr(dtype_ext, "accept_uint%d" % bits) + self.assertEquivalent(fs(s(1)), numpy.dtype(s)) + self.assertEquivalent(fu(u(1)), numpy.dtype(u)) + # these should just use the regular Boost.Python converters + self.assertEquivalent(fs(True), numpy.dtype(s)) + self.assertEquivalent(fu(True), numpy.dtype(u)) + self.assertEquivalent(fs(int(1)), numpy.dtype(s)) + self.assertEquivalent(fu(int(1)), numpy.dtype(u)) + self.assertEquivalent(fs(long(1)), numpy.dtype(s)) + self.assertEquivalent(fu(long(1)), numpy.dtype(u)) + for name in ("bool_", "byte", "ubyte", "short", "ushort", "intc", "uintc"): + t = getattr(numpy, name) + ft = getattr(dtype_ext, "accept_%s" % name) + self.assertEquivalent(ft(t(1)), numpy.dtype(t)) + # these should just use the regular Boost.Python converters + self.assertEquivalent(ft(True), numpy.dtype(t)) + if name != "bool_": + self.assertEquivalent(ft(int(1)), numpy.dtype(t)) + self.assertEquivalent(ft(long(1)), numpy.dtype(t)) + + + def testFloats(self): + f = numpy.float32 + c = numpy.complex64 + self.assertEquivalent(dtype_ext.accept_float32(f(numpy.pi)), numpy.dtype(f)) + self.assertEquivalent(dtype_ext.accept_complex64(c(1+2j)), numpy.dtype(c)) + f = numpy.float64 + c = numpy.complex128 + self.assertEquivalent(dtype_ext.accept_float64(f(numpy.pi)), numpy.dtype(f)) + self.assertEquivalent(dtype_ext.accept_complex128(c(1+2j)), numpy.dtype(c)) + if hasattr(numpy, "longdouble") and hasattr(dtype_ext, "accept_longdouble"): + f = numpy.longdouble + c = numpy.clongdouble + self.assertEquivalent(dtype_ext.accept_longdouble(f(numpy.pi)), numpy.dtype(f)) + self.assertEquivalent(dtype_ext.accept_clongdouble(c(1+2j)), numpy.dtype(c)) + + +if __name__=="__main__": + unittest.main() diff --git a/src/boost/libs/python/test/numpy/indexing.cpp b/src/boost/libs/python/test/numpy/indexing.cpp new file mode 100644 index 000000000..f3cc45717 --- /dev/null +++ b/src/boost/libs/python/test/numpy/indexing.cpp @@ -0,0 +1,28 @@ +// Copyright Jim Bosch & Ankit Daftery 2010-2012. +// Copyright Stefan Seefeld 2016. +// 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) + +#include <boost/python/numpy.hpp> +#include <boost/python/slice.hpp> + +namespace p = boost::python; +namespace np = boost::python::numpy; + +p::object single(np::ndarray ndarr, int i) { return ndarr[i];} +p::object slice(np::ndarray ndarr, p::slice sl) { return ndarr[sl];} +p::object indexarray(np::ndarray ndarr, np::ndarray d1) { return ndarr[d1];} +p::object indexarray_2d(np::ndarray ndarr, np::ndarray d1,np::ndarray d2) { return ndarr[p::make_tuple(d1,d2)];} +p::object indexslice(np::ndarray ndarr, np::ndarray d1, p::slice sl) { return ndarr[p::make_tuple(d1, sl)];} + +BOOST_PYTHON_MODULE(indexing_ext) +{ + np::initialize(); + p::def("single", single); + p::def("slice", slice); + p::def("indexarray", indexarray); + p::def("indexarray", indexarray_2d); + p::def("indexslice", indexslice); + +} diff --git a/src/boost/libs/python/test/numpy/indexing.py b/src/boost/libs/python/test/numpy/indexing.py new file mode 100644 index 000000000..ebd9dcbab --- /dev/null +++ b/src/boost/libs/python/test/numpy/indexing.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python + +# Copyright Jim Bosch & Ankit Daftery 2010-2012. +# 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) + +import unittest +import numpy +import indexing_ext + +class TestIndexing(unittest.TestCase): + + def testSingle(self): + x = numpy.arange(0,10) + for i in range(0,10): + numpy.testing.assert_equal(indexing_ext.single(x,i), i) + for i in range(-10,0): + numpy.testing.assert_equal(indexing_ext.single(x,i),10+i) + + def testSlice(self): + x = numpy.arange(0,10) + sl = slice(3,8) + b = [3,4,5,6,7] + numpy.testing.assert_equal(indexing_ext.slice(x,sl), b) + + def testStepSlice(self): + x = numpy.arange(0,10) + sl = slice(3,8,2) + b = [3,5,7] + numpy.testing.assert_equal(indexing_ext.slice(x,sl), b) + + def testIndex(self): + x = numpy.arange(0,10) + chk = numpy.array([3,4,5,6]) + numpy.testing.assert_equal(indexing_ext.indexarray(x,chk),chk) + chk = numpy.array([[0,1],[2,3]]) + numpy.testing.assert_equal(indexing_ext.indexarray(x,chk),chk) + x = numpy.arange(9).reshape(3,3) + y = numpy.array([0,1]) + z = numpy.array([0,2]) + chk = numpy.array([0,5]) + numpy.testing.assert_equal(indexing_ext.indexarray(x,y,z),chk) + x = numpy.arange(0,10) + b = x>4 + chk = numpy.array([5,6,7,8,9]) + numpy.testing.assert_equal(indexing_ext.indexarray(x,b),chk) + x = numpy.arange(9).reshape(3,3) + b = numpy.array([0,2]) + sl = slice(0,3) + chk = numpy.array([[0,1,2],[6,7,8]]) + numpy.testing.assert_equal(indexing_ext.indexslice(x,b,sl),chk) + +if __name__=="__main__": + unittest.main() diff --git a/src/boost/libs/python/test/numpy/ndarray.cpp b/src/boost/libs/python/test/numpy/ndarray.cpp new file mode 100644 index 000000000..75a101043 --- /dev/null +++ b/src/boost/libs/python/test/numpy/ndarray.cpp @@ -0,0 +1,51 @@ +// Copyright Jim Bosch & Ankit Daftery 2010-2012. +// Copyright Stefan Seefeld 2016. +// 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) + +#include <boost/python/numpy.hpp> + +namespace p = boost::python; +namespace np = boost::python::numpy; + +np::ndarray zeros(p::tuple shape, np::dtype dt) { return np::zeros(shape, dt);} +np::ndarray array2(p::object obj, np::dtype dt) { return np::array(obj,dt);} +np::ndarray array1(p::object obj) { return np::array(obj);} +np::ndarray empty1(p::tuple shape, np::dtype dt) { return np::empty(shape,dt);} + +np::ndarray c_empty(p::tuple shape, np::dtype dt) +{ + // convert 'shape' to a C array so we can test the corresponding + // version of the constructor + unsigned len = p::len(shape); + Py_intptr_t *c_shape = new Py_intptr_t[len]; + for (unsigned i = 0; i != len; ++i) + c_shape[i] = p::extract<Py_intptr_t>(shape[i]); + np::ndarray result = np::empty(len, c_shape, dt); + delete [] c_shape; + return result; +} + +np::ndarray transpose(np::ndarray arr) { return arr.transpose();} +np::ndarray squeeze(np::ndarray arr) { return arr.squeeze();} +np::ndarray reshape(np::ndarray arr,p::tuple tup) { return arr.reshape(tup);} + +Py_intptr_t shape_index(np::ndarray arr,int k) { return arr.shape(k); } +Py_intptr_t strides_index(np::ndarray arr,int k) { return arr.strides(k); } + +BOOST_PYTHON_MODULE(ndarray_ext) +{ + np::initialize(); + p::def("zeros", zeros); + p::def("zeros_matrix", zeros, np::as_matrix<>()); + p::def("array", array2); + p::def("array", array1); + p::def("empty", empty1); + p::def("c_empty", c_empty); + p::def("transpose", transpose); + p::def("squeeze", squeeze); + p::def("reshape", reshape); + p::def("shape_index", shape_index); + p::def("strides_index", strides_index); +} diff --git a/src/boost/libs/python/test/numpy/ndarray.py b/src/boost/libs/python/test/numpy/ndarray.py new file mode 100644 index 000000000..2acc384a5 --- /dev/null +++ b/src/boost/libs/python/test/numpy/ndarray.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python + +# Copyright Jim Bosch & Ankit Daftery 2010-2012. +# 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) + +import ndarray_ext +import unittest +import numpy + +class TestNdarray(unittest.TestCase): + + def testNdzeros(self): + for dtp in (numpy.int16, numpy.int32, numpy.float32, numpy.complex128): + v = numpy.zeros(60, dtype=dtp) + dt = numpy.dtype(dtp) + for shape in ((60,),(6,10),(4,3,5),(2,2,3,5)): + a1 = ndarray_ext.zeros(shape,dt) + a2 = v.reshape(a1.shape) + self.assertEqual(shape,a1.shape) + self.assert_((a1 == a2).all()) + + def testNdzeros_matrix(self): + for dtp in (numpy.int16, numpy.int32, numpy.float32, numpy.complex128): + dt = numpy.dtype(dtp) + shape = (6, 10) + a1 = ndarray_ext.zeros_matrix(shape, dt) + a2 = numpy.matrix(numpy.zeros(shape, dtype=dtp)) + self.assertEqual(shape,a1.shape) + self.assert_((a1 == a2).all()) + self.assertEqual(type(a1), type(a2)) + + def testNdarray(self): + a = range(0,60) + for dtp in (numpy.int16, numpy.int32, numpy.float32, numpy.complex128): + v = numpy.array(a, dtype=dtp) + dt = numpy.dtype(dtp) + a1 = ndarray_ext.array(a) + a2 = ndarray_ext.array(a,dt) + self.assert_((a1 == v).all()) + self.assert_((a2 == v).all()) + for shape in ((60,),(6,10),(4,3,5),(2,2,3,5)): + a1 = a1.reshape(shape) + self.assertEqual(shape,a1.shape) + a2 = a2.reshape(shape) + self.assertEqual(shape,a2.shape) + + def testNdempty(self): + for dtp in (numpy.int16, numpy.int32, numpy.float32, numpy.complex128): + dt = numpy.dtype(dtp) + for shape in ((60,),(6,10),(4,3,5),(2,2,3,5)): + a1 = ndarray_ext.empty(shape,dt) + a2 = ndarray_ext.c_empty(shape,dt) + self.assertEqual(shape,a1.shape) + self.assertEqual(shape,a2.shape) + + def testTranspose(self): + for dtp in (numpy.int16, numpy.int32, numpy.float32, numpy.complex128): + dt = numpy.dtype(dtp) + for shape in ((6,10),(4,3,5),(2,2,3,5)): + a1 = numpy.empty(shape,dt) + a2 = a1.transpose() + a1 = ndarray_ext.transpose(a1) + self.assertEqual(a1.shape,a2.shape) + + def testSqueeze(self): + a1 = numpy.array([[[3,4,5]]]) + a2 = a1.squeeze() + a1 = ndarray_ext.squeeze(a1) + self.assertEqual(a1.shape,a2.shape) + + def testReshape(self): + a1 = numpy.empty((2,2)) + a2 = ndarray_ext.reshape(a1,(1,4)) + self.assertEqual(a2.shape,(1,4)) + + def testShapeIndex(self): + a = numpy.arange(24) + a.shape = (1,2,3,4) + def shape_check(i): + print(i) + self.assertEqual(ndarray_ext.shape_index(a,i) ,a.shape[i] ) + for i in range(4): + shape_check(i) + for i in range(-1,-5,-1): + shape_check(i) + try: + ndarray_ext.shape_index(a,4) # out of bounds -- should raise IndexError + self.assertTrue(False) + except IndexError: + pass + + def testStridesIndex(self): + a = numpy.arange(24) + a.shape = (1,2,3,4) + def strides_check(i): + print(i) + self.assertEqual(ndarray_ext.strides_index(a,i) ,a.strides[i] ) + for i in range(4): + strides_check(i) + for i in range(-1,-5,-1): + strides_check(i) + try: + ndarray_ext.strides_index(a,4) # out of bounds -- should raise IndexError + self.assertTrue(False) + except IndexError: + pass + + +if __name__=="__main__": + unittest.main() diff --git a/src/boost/libs/python/test/numpy/shapes.cpp b/src/boost/libs/python/test/numpy/shapes.cpp new file mode 100644 index 000000000..a245df155 --- /dev/null +++ b/src/boost/libs/python/test/numpy/shapes.cpp @@ -0,0 +1,22 @@ +// Copyright Jim Bosch & Ankit Daftery 2010-2012. +// Copyright Stefan Seefeld 2016. +// 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) + +#include <boost/python/numpy.hpp> + +namespace p = boost::python; +namespace np = boost::python::numpy; + +np::ndarray reshape(np::ndarray old_array, p::tuple shape) +{ + np::ndarray local_shape = old_array.reshape(shape); + return local_shape; +} + +BOOST_PYTHON_MODULE(shapes_ext) +{ + np::initialize(); + p::def("reshape", reshape); +} diff --git a/src/boost/libs/python/test/numpy/shapes.py b/src/boost/libs/python/test/numpy/shapes.py new file mode 100644 index 000000000..d0a0099ca --- /dev/null +++ b/src/boost/libs/python/test/numpy/shapes.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python + +# Copyright Jim Bosch & Ankit Daftery 2010-2012. +# 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) + +import shapes_ext +import unittest +import numpy + +class TestShapes(unittest.TestCase): + + def testShapes(self): + a1 = numpy.array([(0,1),(2,3)]) + a1_shape = (1,4) + a1 = shapes_ext.reshape(a1,a1_shape) + self.assertEqual(a1_shape,a1.shape) + +if __name__=="__main__": + unittest.main() diff --git a/src/boost/libs/python/test/numpy/templates.cpp b/src/boost/libs/python/test/numpy/templates.cpp new file mode 100644 index 000000000..83de6bd2f --- /dev/null +++ b/src/boost/libs/python/test/numpy/templates.cpp @@ -0,0 +1,63 @@ +// Copyright Jim Bosch & Ankit Daftery 2010-2012. +// Copyright Stefan Seefeld 2016. +// 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) + +#include <boost/python/numpy.hpp> +#include <boost/mpl/vector.hpp> +#include <boost/mpl/vector_c.hpp> + +namespace p = boost::python; +namespace np = boost::python::numpy; + +struct ArrayFiller +{ + + typedef boost::mpl::vector< short, int, float, std::complex<double> > TypeSequence; + typedef boost::mpl::vector_c< int, 1, 2 > DimSequence; + + explicit ArrayFiller(np::ndarray const & arg) : argument(arg) {} + + template <typename T, int N> + void apply() const + { + if (N == 1) + { + char * p = argument.get_data(); + int stride = argument.strides(0); + int size = argument.shape(0); + for (int n = 0; n != size; ++n, p += stride) + *reinterpret_cast<T*>(p) = static_cast<T>(n); + } + else + { + char * row_p = argument.get_data(); + int row_stride = argument.strides(0); + int col_stride = argument.strides(1); + int rows = argument.shape(0); + int cols = argument.shape(1); + int i = 0; + for (int n = 0; n != rows; ++n, row_p += row_stride) + { + char * col_p = row_p; + for (int m = 0; m != cols; ++i, ++m, col_p += col_stride) + *reinterpret_cast<T*>(col_p) = static_cast<T>(i); + } + } + } + + np::ndarray argument; +}; + +void fill(np::ndarray const & arg) +{ + ArrayFiller filler(arg); + np::invoke_matching_array<ArrayFiller::TypeSequence, ArrayFiller::DimSequence >(arg, filler); +} + +BOOST_PYTHON_MODULE(templates_ext) +{ + np::initialize(); + p::def("fill", fill); +} diff --git a/src/boost/libs/python/test/numpy/templates.py b/src/boost/libs/python/test/numpy/templates.py new file mode 100755 index 000000000..8290b13a0 --- /dev/null +++ b/src/boost/libs/python/test/numpy/templates.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python + +# Copyright Jim Bosch & Ankit Daftery 2010-2012. +# 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) + +import templates_ext +import unittest +import numpy + +class TestTemplates(unittest.TestCase): + + def testTemplates(self): + for dtype in (numpy.int16, numpy.int32, numpy.float32, numpy.complex128): + v = numpy.arange(12, dtype=dtype) + for shape in ((12,), (4, 3), (2, 6)): + a1 = numpy.zeros(shape, dtype=dtype) + a2 = v.reshape(a1.shape) + templates_ext.fill(a1) + self.assert_((a1 == a2).all()) + a1 = numpy.zeros((12,), dtype=numpy.float64) + self.assertRaises(TypeError, templates_ext.fill, a1) + a1 = numpy.zeros((12,2,3), dtype=numpy.float32) + self.assertRaises(TypeError, templates_ext.fill, a1) + +if __name__=="__main__": + unittest.main() diff --git a/src/boost/libs/python/test/numpy/ufunc.cpp b/src/boost/libs/python/test/numpy/ufunc.cpp new file mode 100644 index 000000000..3a9d43cbb --- /dev/null +++ b/src/boost/libs/python/test/numpy/ufunc.cpp @@ -0,0 +1,36 @@ +// Copyright Jim Bosch & Ankit Daftery 2010-2012. +// Copyright Stefan Seefeld 2016. +// 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) + +#include <boost/python/numpy.hpp> + +namespace p = boost::python; +namespace np = boost::python::numpy; + +struct UnaryCallable +{ + typedef double argument_type; + typedef double result_type; + + double operator()(double r) const { return r * 2;} +}; + +struct BinaryCallable +{ + typedef double first_argument_type; + typedef double second_argument_type; + typedef double result_type; + + double operator()(double a, double b) const { return a * 2 + b * 3;} +}; + +BOOST_PYTHON_MODULE(ufunc_ext) +{ + np::initialize(); + p::class_<UnaryCallable>("UnaryCallable") + .def("__call__", np::unary_ufunc<UnaryCallable>::make()); + p::class_< BinaryCallable>("BinaryCallable") + .def("__call__", np::binary_ufunc<BinaryCallable>::make()); +} diff --git a/src/boost/libs/python/test/numpy/ufunc.py b/src/boost/libs/python/test/numpy/ufunc.py new file mode 100755 index 000000000..e820121ee --- /dev/null +++ b/src/boost/libs/python/test/numpy/ufunc.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python + +# Copyright Jim Bosch & Ankit Daftery 2010-2012. +# 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) + +import ufunc_ext +import unittest +import numpy +from numpy.testing.utils import assert_array_almost_equal + +class TestUnary(unittest.TestCase): + + def testScalar(self): + f = ufunc_ext.UnaryCallable() + assert_array_almost_equal(f(1.0), 2.0) + assert_array_almost_equal(f(3.0), 6.0) + + def testArray(self): + f = ufunc_ext.UnaryCallable() + a = numpy.arange(5, dtype=float) + b = f(a) + assert_array_almost_equal(b, a*2.0) + c = numpy.zeros(5, dtype=float) + d = f(a,output=c) + self.assert_(c is d) + assert_array_almost_equal(d, a*2.0) + + def testList(self): + f = ufunc_ext.UnaryCallable() + a = range(5) + b = f(a) + assert_array_almost_equal(b/2.0, a) + +class TestBinary(unittest.TestCase): + + def testScalar(self): + f = ufunc_ext.BinaryCallable() + assert_array_almost_equal(f(1.0, 3.0), 11.0) + assert_array_almost_equal(f(3.0, 2.0), 12.0) + + def testArray(self): + f = ufunc_ext.BinaryCallable() + a = numpy.random.randn(5) + b = numpy.random.randn(5) + assert_array_almost_equal(f(a,b), (a*2+b*3)) + c = numpy.zeros(5, dtype=float) + d = f(a,b,output=c) + self.assert_(c is d) + assert_array_almost_equal(d, a*2 + b*3) + assert_array_almost_equal(f(a, 2.0), a*2 + 6.0) + assert_array_almost_equal(f(1.0, b), 2.0 + b*3) + + +if __name__=="__main__": + unittest.main() diff --git a/src/boost/libs/python/test/object.cpp b/src/boost/libs/python/test/object.cpp new file mode 100644 index 000000000..b1f015187 --- /dev/null +++ b/src/boost/libs/python/test/object.cpp @@ -0,0 +1,392 @@ +// Copyright David Abrahams 2002. +// 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) +#include <boost/python/module.hpp> +#include <boost/python/def.hpp> +#include <boost/python/object.hpp> +#include <boost/python/class.hpp> + +using namespace boost::python; + +class NotCopyable +{ +} not_copyable; + +object ref_to_noncopyable() +{ + return object(boost::ref(not_copyable)); +} + +object call_object_3(object f) +{ + return f(3); +} + +object message() +{ + return object("hello, world!"); +} + +object number() +{ + return object(42); +} + +object obj_getattr(object x, char const* name) +{ + return x.attr(name); +} + +object obj_objgetattr(object x, object const& name) +{ + return x.attr(name); +} + +object obj_const_getattr(object const& x, char const* name) +{ + return x.attr(name); +} + +object obj_const_objgetattr(object const& x, object const& name) +{ + return x.attr(name); +} + +void obj_setattr(object x, char const* name, object value) +{ + x.attr(name) = value; +} + +void obj_objsetattr(object x, object const& name, object value) +{ + x.attr(name) = value; +} + +void obj_setattr42(object x, char const* name) +{ + x.attr(name) = 42; +} + +void obj_objsetattr42(object x, object const& name) +{ + x.attr(name) = 42; +} + +void obj_moveattr(object& x, char const* src, char const* dst) +{ + x.attr(dst) = x.attr(src); +} + +void obj_objmoveattr(object& x, object const& src, object const& dst) +{ + x.attr(dst) = x.attr(src); +} + +void obj_delattr(object x, char const* name) +{ + x.attr(name).del(); +} + +void obj_objdelattr(object x, object const& name) +{ + x.attr(name).del(); +} + +object obj_getitem(object x, object key) +{ + return x[key]; +} + +object obj_getitem3(object x) +{ + return x[3]; +} + +object obj_const_getitem(object const& x, object key) +{ + return x[key]; +} + +void obj_setitem(object x, object key, object value) +{ + x[key] = value; +} + +void obj_setitem42(object x, object key) +{ + x[key] = 42; +} + +void obj_moveitem(object& x, object src, object dst) +{ + x[dst] = x[src]; +} + +void obj_moveitem2(object const& x_src, object k_src, object& x_dst, object k_dst) +{ + x_dst[k_dst] = x_src[k_src]; +} + +bool test(object y) +{ + return y; +} + +bool test_not(object y) +{ + return !y; +} + +bool test_attr(object y, char* name) +{ + return y.attr(name); +} + +bool test_objattr(object y, object& name) +{ + return y.attr(name); +} + +bool test_not_attr(object y, char* name) +{ + return !y.attr(name); +} + +bool test_not_objattr(object y, object& name) +{ + return !y.attr(name); +} + +bool test_item(object y, object key) +{ + return y[key]; +} + +bool test_not_item(object y, object key) +{ + return !y[key]; +} + +bool check_string_slice() +{ + object s("hello, world"); + + if (s.slice(_,-3) != "hello, wo") + return false; + + if (s.slice(-3,_) != "rld") + return false; + + if (s.slice(_,_) != s) + return false; + + if (", " != s.slice(5,7)) + return false; + + return s.slice(2,-1).slice(1,-1) == "lo, wor"; +} + +object test_call(object c, object args, object kwds) +{ + return c(*args, **kwds); +} + +bool check_binary_operators() +{ + int y; + + object x(3); + +#define TEST_BINARY(op) \ + for (y = 1; y < 6; ++y) \ + { \ + if ((x op y) != (3 op y)) \ + return false; \ + } \ + for (y = 1; y < 6; ++y) \ + { \ + if ((y op x) != (y op 3)) \ + return false; \ + } \ + for (y = 1; y < 6; ++y) \ + { \ + object oy(y); \ + if ((oy op x) != (oy op 3)) \ + return false; \ + } + TEST_BINARY(>) + TEST_BINARY(>=) + TEST_BINARY(<) + TEST_BINARY(<=) + TEST_BINARY(==) + TEST_BINARY(!=) + + TEST_BINARY(+) + TEST_BINARY(-) + TEST_BINARY(*) + TEST_BINARY(/) + TEST_BINARY(%) + TEST_BINARY(<<) + TEST_BINARY(>>) + TEST_BINARY(&) + TEST_BINARY(^) + TEST_BINARY(|) + return true; +} + +bool check_inplace(object l, object o) +{ + int y; +#define TEST_INPLACE(op) \ + for (y = 1; y < 6; ++y) \ + { \ + object x(666); \ + x op##= y; \ + if (x != (666 op y)) \ + return false; \ + } \ + for (y = 1; y < 6; ++y) \ + { \ + object x(666); \ + x op##= object(y); \ + if (!(x == (666 op y))) \ + return false; \ + } + TEST_INPLACE(+) + TEST_INPLACE(-) + TEST_INPLACE(*) + TEST_INPLACE(/) + TEST_INPLACE(%) + TEST_INPLACE(<<) + TEST_INPLACE(>>) + TEST_INPLACE(&) + TEST_INPLACE(^) + TEST_INPLACE(|) + + l += l; + for (y = 0; y < 6; ++y) + { + if (l[y] != y % 3) + return false; + } + +#define TEST_ITEM_INPLACE(index, op, n, r1, r2) \ + l[index] op##= n; \ + if (l[index] != r1) \ + return false; \ + l[index] op##= object(n); \ + if (!(l[index] == r2)) \ + return false; + + TEST_ITEM_INPLACE(0,+,7,7,14) + TEST_ITEM_INPLACE(1,-,2,-1,-3) + TEST_ITEM_INPLACE(2,*,3,6,18) + TEST_ITEM_INPLACE(2,/,2,9,4) + TEST_ITEM_INPLACE(0,%,4,2,2) + l[0] += 1; + TEST_ITEM_INPLACE(0,<<,2,12,48) + TEST_ITEM_INPLACE(0,>>,1,24,12) + l[4] = 15; + TEST_ITEM_INPLACE(4,&,(16+4+1),5,5) + TEST_ITEM_INPLACE(0,^,1,13,12) + TEST_ITEM_INPLACE(0,|,1,13,13) + + o.attr("x0") = 0; + o.attr("x1") = 1; + o.attr("x2") = 2; + o.attr("x3") = 0; + o.attr("x4") = 1; + +#define TEST_ATTR_INPLACE(index, op, n, r1, r2) \ + o.attr("x" #index) op##= n; \ + if (o.attr("x" #index) != r1) \ + return false; \ + o.attr("x" #index) op##= object(n); \ + if (o.attr("x" #index) != r2) \ + return false; + + TEST_ATTR_INPLACE(0,+,7,7,14) + TEST_ATTR_INPLACE(1,-,2,-1,-3) + TEST_ATTR_INPLACE(2,*,3,6,18) + TEST_ATTR_INPLACE(2,/,2,9,4) + TEST_ATTR_INPLACE(0,%,4,2,2) + o.attr("x0") += 1; + TEST_ATTR_INPLACE(0,<<,2,12,48) + TEST_ATTR_INPLACE(0,>>,1,24,12) + o.attr("x4") = 15; + TEST_ATTR_INPLACE(4,&,(16+4+1),5,5) + TEST_ATTR_INPLACE(0,^,1,13,12) + TEST_ATTR_INPLACE(0,|,1,13,13) + + if (l[0] != o.attr("x0")) + return false; + if (l[1] != o.attr("x1")) + return false; + if (l[2] != o.attr("x2")) + return false; + if (l[3] != o.attr("x3")) + return false; + if (l[4] != o.attr("x4")) + return false; + + // set item 5 to be a list, by calling l.__class__ + l[5] = l.attr("__class__")(); + // append an element + l[5].attr("append")(2); + // Check its value + if (l[5][0] != 2) + return false; + + return true; +} + +BOOST_PYTHON_MODULE(object_ext) +{ + class_<NotCopyable, boost::noncopyable>("NotCopyable", no_init); + + def("ref_to_noncopyable", ref_to_noncopyable); + def("call_object_3", call_object_3); + def("message", message); + def("number", number); + + def("obj_getattr", obj_getattr); + def("obj_objgetattr", obj_objgetattr); + def("obj_const_getattr", obj_const_getattr); + def("obj_const_objgetattr", obj_const_objgetattr); + def("obj_setattr", obj_setattr); + def("obj_objsetattr", obj_objsetattr); + def("obj_setattr42", obj_setattr42); + def("obj_objsetattr42", obj_objsetattr42); + def("obj_moveattr", obj_moveattr); + def("obj_objmoveattr", obj_objmoveattr); + def("obj_delattr", obj_delattr); + def("obj_objdelattr", obj_objdelattr); + + def("obj_getitem", obj_getitem); + def("obj_getitem3", obj_getitem); + def("obj_const_getitem", obj_const_getitem); + def("obj_setitem", obj_setitem); + def("obj_setitem42", obj_setitem42); + def("obj_moveitem", obj_moveitem); + def("obj_moveitem2", obj_moveitem2); + + def("test", test); + def("test_not", test_not); + + def("test_attr", test_attr); + def("test_objattr", test_objattr); + def("test_not_attr", test_not_attr); + def("test_not_objattr", test_not_objattr); + + def("test_item", test_item); + def("test_not_item", test_not_item); + + def("test_call", test_call); + def("check_binary_operators", check_binary_operators); + def("check_inplace", check_inplace); + def("check_string_slice", check_string_slice); + ; +} + +#include "module_tail.cpp" diff --git a/src/boost/libs/python/test/object.py b/src/boost/libs/python/test/object.py new file mode 100644 index 000000000..67a46d936 --- /dev/null +++ b/src/boost/libs/python/test/object.py @@ -0,0 +1,180 @@ +# Copyright David Abrahams 2004. 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) +from __future__ import print_function +''' +>>> from object_ext import * + +>>> type(ref_to_noncopyable()) +<class 'object_ext.NotCopyable'> + +>>> def print1(x): +... print(x) +>>> call_object_3(print1) +3 +>>> message() +'hello, world!' +>>> number() +42 + +>>> test('hi') +1 +>>> test(None) +0 +>>> test_not('hi') +0 +>>> test_not(0) +1 + + Attributes + +>>> class X: pass +... +>>> x = X() + +>>> try: obj_getattr(x, 'foo') +... except AttributeError: pass +... else: print('expected an exception') +>>> try: obj_objgetattr(x, 'objfoo') +... except AttributeError: pass +... else: print('expected an exception') + +>>> obj_setattr(x, 'foo', 1) +>>> x.foo +1 +>>> obj_objsetattr(x, 'objfoo', 1) +>>> try:obj_objsetattr(x, 1) +... except TypeError: pass +... else: print('expected an exception') +>>> x.objfoo +1 +>>> obj_getattr(x, 'foo') +1 +>>> obj_objgetattr(x, 'objfoo') +1 +>>> try:obj_objgetattr(x, 1) +... except TypeError: pass +... else: print('expected an exception') +>>> obj_const_getattr(x, 'foo') +1 +>>> obj_const_objgetattr(x, 'objfoo') +1 +>>> obj_setattr42(x, 'foo') +>>> x.foo +42 +>>> obj_objsetattr42(x, 'objfoo') +>>> x.objfoo +42 +>>> obj_moveattr(x, 'foo', 'bar') +>>> x.bar +42 +>>> obj_objmoveattr(x, 'objfoo', 'objbar') +>>> x.objbar +42 +>>> test_attr(x, 'foo') +1 +>>> test_objattr(x, 'objfoo') +1 +>>> test_not_attr(x, 'foo') +0 +>>> test_not_objattr(x, 'objfoo') +0 +>>> x.foo = None +>>> test_attr(x, 'foo') +0 +>>> x.objfoo = None +>>> test_objattr(x, 'objfoo') +0 +>>> test_not_attr(x, 'foo') +1 +>>> test_not_objattr(x, 'objfoo') +1 +>>> obj_delattr(x, 'foo') +>>> obj_objdelattr(x, 'objfoo') +>>> try:obj_delattr(x, 'foo') +... except AttributeError: pass +... else: print('expected an exception') +>>> try:obj_objdelattr(x, 'objfoo') +... except AttributeError: pass +... else: print('expected an exception') + + Items + +>>> d = {} +>>> obj_setitem(d, 'foo', 1) +>>> d['foo'] +1 +>>> obj_getitem(d, 'foo') +1 +>>> obj_const_getitem(d, 'foo') +1 +>>> obj_setitem42(d, 'foo') +>>> obj_getitem(d, 'foo') +42 +>>> d['foo'] +42 +>>> obj_moveitem(d, 'foo', 'bar') +>>> d['bar'] +42 +>>> obj_moveitem2(d, 'bar', d, 'baz') +>>> d['baz'] +42 +>>> test_item(d, 'foo') +1 +>>> test_not_item(d, 'foo') +0 +>>> d['foo'] = None +>>> test_item(d, 'foo') +0 +>>> test_not_item(d, 'foo') +1 + + Slices + +>>> assert check_string_slice() + + Operators + +>>> def print_args(*args, **kwds): +... print(args, kwds) +>>> test_call(print_args, (0, 1, 2, 3), {'a':'A'}) +(0, 1, 2, 3) {'a': 'A'} + + +>>> assert check_binary_operators() + +>>> class X: pass +... +>>> assert check_inplace(list(range(3)), X()) + + + Now make sure that object is actually managing reference counts + +>>> import weakref +>>> class Z: pass +... +>>> z = Z() +>>> def death(r): print('death') +... +>>> r = weakref.ref(z, death) +>>> z.foo = 1 +>>> obj_getattr(z, 'foo') +1 +>>> del z +death +''' + +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/object_fail1.cpp b/src/boost/libs/python/test/object_fail1.cpp new file mode 100644 index 000000000..6bb2eda5c --- /dev/null +++ b/src/boost/libs/python/test/object_fail1.cpp @@ -0,0 +1,11 @@ +// Copyright David Abrahams 2002. +// 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) +#include <boost/python/object.hpp> + +int f(boost::python::object const& x) +{ + x._("hello") = 1; + return 0; +} diff --git a/src/boost/libs/python/test/object_manager.cpp b/src/boost/libs/python/test/object_manager.cpp new file mode 100644 index 000000000..e3608c1f1 --- /dev/null +++ b/src/boost/libs/python/test/object_manager.cpp @@ -0,0 +1,33 @@ +// Copyright David Abrahams 2002. +// 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) +#include <boost/python/converter/object_manager.hpp> +#include <boost/python/borrowed.hpp> +#include <boost/static_assert.hpp> +#include <boost/python/handle.hpp> + +using namespace boost::python; +using namespace boost::python::converter; + +struct X {}; + +int main() +{ + BOOST_STATIC_ASSERT(is_object_manager<handle<> >::value); + BOOST_STATIC_ASSERT(!is_object_manager<int>::value); + BOOST_STATIC_ASSERT(!is_object_manager<X>::value); + + BOOST_STATIC_ASSERT(is_reference_to_object_manager<handle<>&>::value); + BOOST_STATIC_ASSERT(is_reference_to_object_manager<handle<> const&>::value); + BOOST_STATIC_ASSERT(is_reference_to_object_manager<handle<> volatile&>::value); + BOOST_STATIC_ASSERT(is_reference_to_object_manager<handle<> const volatile&>::value); + + BOOST_STATIC_ASSERT(!is_reference_to_object_manager<handle<> >::value); + BOOST_STATIC_ASSERT(!is_reference_to_object_manager<X>::value); + BOOST_STATIC_ASSERT(!is_reference_to_object_manager<X&>::value); + BOOST_STATIC_ASSERT(!is_reference_to_object_manager<X const&>::value); + + return 0; +} + diff --git a/src/boost/libs/python/test/opaque.cpp b/src/boost/libs/python/test/opaque.cpp new file mode 100644 index 000000000..f15e9458f --- /dev/null +++ b/src/boost/libs/python/test/opaque.cpp @@ -0,0 +1,76 @@ +// Copyright David Abrahams and Gottfried Ganssauge 2003. +// 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) +# include <boost/python/return_opaque_pointer.hpp> +# include <boost/python/def.hpp> +# include <boost/python/module.hpp> +# include <boost/python/return_value_policy.hpp> + +typedef struct opaque_ *opaque; +typedef struct opaque2_ *opaque2; + +opaque the_op = ((opaque) 0x47110815); +opaque2 the_op2 = ((opaque2) 0x08154711); + +opaque get() { return the_op; } + +void use(opaque op) +{ + if (op != the_op) + throw std::runtime_error (std::string ("failed")); +} + +int useany(opaque op) +{ + return op ? 1 : 0; +} + +opaque getnull() +{ + return 0; +} + +void failuse (opaque op) +{ + if (op == the_op) + throw std::runtime_error (std::string ("success")); +} + +opaque2 get2 () { return the_op2; } + +void use2 (opaque2 op) +{ + if (op != the_op2) + throw std::runtime_error (std::string ("failed")); +} + +void failuse2 (opaque2 op) +{ + if (op == the_op2) + throw std::runtime_error (std::string ("success")); +} + +BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(opaque_) +BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(opaque2_) + +namespace bpl = boost::python; + +BOOST_PYTHON_MODULE(opaque_ext) +{ + bpl::def ( + "get", &::get, bpl::return_value_policy<bpl::return_opaque_pointer>()); + bpl::def ("use", &::use); + bpl::def ("useany", &::useany); + bpl::def ("getnull", &::getnull, bpl::return_value_policy<bpl::return_opaque_pointer>()); + bpl::def ("failuse", &::failuse); + + bpl::def ( + "get2", + &::get2, + bpl::return_value_policy<bpl::return_opaque_pointer>()); + bpl::def ("use2", &::use2); + bpl::def ("failuse2", &::failuse2); +} + +# include "module_tail.cpp" diff --git a/src/boost/libs/python/test/opaque.py b/src/boost/libs/python/test/opaque.py new file mode 100644 index 000000000..9f5663723 --- /dev/null +++ b/src/boost/libs/python/test/opaque.py @@ -0,0 +1,87 @@ +# -*- coding: utf-8 -*- +# Copyright Gottfried Ganßauge 2003..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) + + +""" +>>> from opaque_ext import * + + + Check for correct conversion + +>>> use(get()) + + Check that None is converted to a NULL opaque pointer + +>>> useany(get()) +1 +>>> useany(None) +0 + + Check that we don't lose type information by converting NULL + opaque pointers to None + +>>> assert getnull() is None +>>> useany(getnull()) +0 + +>>> failuse(get()) +Traceback (most recent call last): + ... +RuntimeError: success + + Check that there is no conversion from integers ... + +>>> try: use(0) +... except TypeError: pass +... else: print('expected a TypeError') + + ... and from strings to opaque objects + +>>> try: use("") +... except TypeError: pass +... else: print('expected a TypeError') + + Now check the same for another opaque pointer type + +>>> use2(get2()) +>>> failuse2(get2()) +Traceback (most recent call last): + ... +RuntimeError: success +>>> try: use2(0) +... except TypeError: pass +... else: print('expected a TypeError') +>>> try: use2("") +... except TypeError: pass +... else: print('expected a TypeError') + + Check that opaque types are distinct + +>>> try: use(get2()) +... except TypeError: pass +... else: print('expected a TypeError') +>>> try: use2(get()) +... except TypeError: pass +... else: print('expected a TypeError') + + This used to result in a segmentation violation + +>>> type(get()) != type (get2()) +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/operators.cpp b/src/boost/libs/python/test/operators.cpp new file mode 100644 index 000000000..c58f2b005 --- /dev/null +++ b/src/boost/libs/python/test/operators.cpp @@ -0,0 +1,175 @@ +// Copyright David Abrahams 2002. +// 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) +#include <boost/python/operators.hpp> +#include <boost/python/class.hpp> +#include <boost/python/module.hpp> +#include <boost/python/def.hpp> +#include "test_class.hpp" +#include <boost/python/module.hpp> +#include <boost/python/class.hpp> +#include <boost/python/operators.hpp> +#include <boost/operators.hpp> +//#include <boost/python/str.hpp> +// Just use math.h here; trying to use std::pow() causes too much +// trouble for non-conforming compilers and libraries. +#include <math.h> + +#if __GNUC__ != 2 +# include <ostream> +#else +# include <ostream.h> +#endif + +using namespace boost::python; + + +using namespace boost::python; + +struct X : test_class<> +{ + typedef test_class<> base_t; + + X(int x) : base_t(x) {} + X const operator+(X const& r) const { return X(value() + r.value()); } + +// typedef int (X::*safe_bool)() const; +// operator safe_bool() const { return value() != 0 ? &X::value : 0; } +}; + +X operator-(X const& l, X const& r) { return X(l.value() - r.value()); } +X operator-(int l, X const& r) { return X(l - r.value()); } +X operator-(X const& l, int r) { return X(l.value() - r); } + +X operator-(X const& x) { return X(-x.value()); } + +X& operator-=(X& l, X const& r) { l.set(l.value() - r.value()); return l; } + +bool operator<(X const& x, X const& y) { return x.value() < y.value(); } +bool operator<(X const& x, int y) { return x.value() < y; } +bool operator<(int x, X const& y) { return x < y.value(); } + +X abs(X x) { return X(x.value() < 0 ? -x.value() : x.value()); } + +X pow(X x, int y) +{ + return X(int(pow(double(x.value()), double(y)))); +} + +X pow(X x, X y) +{ + return X(int(pow(double(x.value()), double(y.value())))); +} + +int pow(int x, X y) +{ + return int(pow(double(x), double(y.value()))); +} + +std::ostream& operator<<(std::ostream& s, X const& x) +{ + return s << x.value(); +} + +struct number + : boost::integer_arithmetic<number> +{ + explicit number(long x_) : x(x_) {} + operator long() const { return x; } + + template <class T> + number& operator+=(T const& rhs) + { x += rhs; return *this; } + + template <class T> + number& operator-=(T const& rhs) + { x -= rhs; return *this; } + + template <class T> + number& operator*=(T const& rhs) + { x *= rhs; return *this; } + + template <class T> + number& operator/=(T const& rhs) + { x /= rhs; return *this; } + + template <class T> + number& operator%=(T const& rhs) + { x %= rhs; return *this; } + + long x; +}; + +BOOST_PYTHON_MODULE(operators_ext) +{ + class_<X>("X", init<int>()) + .def("value", &X::value) + .def(self + self) + .def(self - self) + .def(self - int()) + .def(other<int>() - self) + .def(-self) + .def(self < other<int>()) + .def(self < self) + .def(1 < self) + .def(self -= self) + + .def(abs(self)) + .def(str(self)) + + .def(pow(self,self)) + .def(pow(self,int())) + .def(pow(int(),self)) + .def( + !self + // "not self" is legal here but causes friction on a few + // nonconforming compilers; it's cute because it looks + // like python, but doing it here doesn't prove much and + // just causes tests to fail or complicated workarounds to + // be enacted. + ) + ; + + class_<number>("number", init<long>()) + // interoperate with self + .def(self += self) + .def(self + self) + .def(self -= self) + .def(self - self) + .def(self *= self) + .def(self * self) + .def(self /= self) + .def(self / self) + .def(self %= self) + .def(self % self) + + // Convert to Python int + .def(int_(self)) + + // interoperate with long + .def(self += long()) + .def(self + long()) + .def(long() + self) + .def(self -= long()) + .def(self - long()) + .def(long() - self) + .def(self *= long()) + .def(self * long()) + .def(long() * self) + .def(self /= long()) + .def(self / long()) + .def(long() / self) + .def(self %= long()) + .def(self % long()) + .def(long() % self) + ; + + class_<test_class<1> >("Z", init<int>()) + .def(int_(self)) + .def(float_(self)) + .def(complex_(self)) + ; +} + +#include "module_tail.cpp" diff --git a/src/boost/libs/python/test/operators.py b/src/boost/libs/python/test/operators.py new file mode 100644 index 000000000..5b369803c --- /dev/null +++ b/src/boost/libs/python/test/operators.py @@ -0,0 +1,102 @@ +# Copyright David Abrahams 2004. 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) +''' +>>> from operators_ext import * + + Check __nonzero__ support + +>>> assert X(2) +>>> assert not X(0) + + ---- + +>>> x = X(42) +>>> x.value() +42 +>>> y = x - X(5) +>>> y.value() +37 +>>> y = x - 4 +>>> y.value() +38 +>>> y = 3 - x +>>> y.value() +-39 +>>> (-y).value() +39 + +>>> (x + y).value() +3 + +>>> abs(y).value() +39 + +>>> x < 10 +0 +>>> x < 43 +1 + +>>> 10 < x +1 +>>> 43 < x +0 + +>>> x < y +0 +>>> y < x +1 + + ------ +>>> x > 10 +1 +>>> x > 43 +0 + +>>> 10 > x +0 +>>> 43 > x +1 + +>>> x > y +1 +>>> y > x +0 + +>>> y = x - 5 +>>> x -= y +>>> x.value() +5 +>>> str(x) +'5' + +>>> z = Z(10) +>>> int(z) +10 +>>> float(z) +10.0 +>>> complex(z) +(10+0j) + +>>> pow(2,x) +32 +>>> pow(x,2).value() +25 +>>> pow(X(2),x).value() +32 +''' + +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/operators_wrapper.cpp b/src/boost/libs/python/test/operators_wrapper.cpp new file mode 100644 index 000000000..12f30048d --- /dev/null +++ b/src/boost/libs/python/test/operators_wrapper.cpp @@ -0,0 +1,42 @@ +#include "boost/python.hpp" +#include <memory> + +struct vector +{ + virtual ~vector() {} + + vector operator+( const vector& ) const + { return vector(); } + + vector& operator+=( const vector& ) + { return *this; } + + vector operator-() const + { return *this; } +}; + +struct dvector : vector +{}; + +using namespace boost::python; + +struct vector_wrapper + : vector, wrapper< vector > +{ + vector_wrapper(vector const&) {} + vector_wrapper() {} +}; + +BOOST_PYTHON_MODULE( operators_wrapper_ext ) +{ + class_< vector_wrapper >( "vector" ) + .def( self + self ) + .def( self += self ) + .def( -self ) + ; + + scope().attr("v") = vector(); + std::auto_ptr<vector> dp(new dvector); + register_ptr_to_python< std::auto_ptr<vector> >(); + scope().attr("d") = dp; +} diff --git a/src/boost/libs/python/test/operators_wrapper.py b/src/boost/libs/python/test/operators_wrapper.py new file mode 100644 index 000000000..6c889b0a3 --- /dev/null +++ b/src/boost/libs/python/test/operators_wrapper.py @@ -0,0 +1,11 @@ +from operators_wrapper_ext import * + +class D2(vector): pass +d2 = D2() + +for lhs in (v,d,d2): + -lhs + for rhs in (v,d,d2): + lhs + rhs + lhs += rhs + diff --git a/src/boost/libs/python/test/pickle1.cpp b/src/boost/libs/python/test/pickle1.cpp new file mode 100644 index 000000000..cc4ad6795 --- /dev/null +++ b/src/boost/libs/python/test/pickle1.cpp @@ -0,0 +1,62 @@ +// Copyright Ralf W. Grosse-Kunstleve 2002-2004. 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) + +/* + This example shows how to make an Extension Class "pickleable". + + The world class below can be fully restored by passing the + appropriate argument to the constructor. Therefore it is sufficient + to define the pickle interface method __getinitargs__. + + For more information refer to boost/libs/python/doc/pickle.html. + */ + +#include <boost/python/module.hpp> +#include <boost/python/def.hpp> +#include <boost/python/class.hpp> +#include <boost/python/tuple.hpp> + +#include <string> + +namespace boost_python_test { + + // A friendly class. + class world + { + private: + std::string country; + public: + world(const std::string& _country) { + this->country = _country; + } + std::string greet() const { return "Hello from " + country + "!"; } + std::string get_country() const { return country; } + }; + + struct world_pickle_suite : boost::python::pickle_suite + { + static + boost::python::tuple + getinitargs(const world& w) + { + return boost::python::make_tuple(w.get_country()); + } + }; + + // To support test of "pickling not enabled" error message. + struct noop {}; +} + +BOOST_PYTHON_MODULE(pickle1_ext) +{ + using namespace boost::python; + using namespace boost_python_test; + class_<world>("world", init<const std::string&>()) + .def("greet", &world::greet) + .def_pickle(world_pickle_suite()) + ; + + // To support test of "pickling not enabled" error message. + class_<noop>("noop"); +} diff --git a/src/boost/libs/python/test/pickle1.py b/src/boost/libs/python/test/pickle1.py new file mode 100644 index 000000000..b8f4efd9b --- /dev/null +++ b/src/boost/libs/python/test/pickle1.py @@ -0,0 +1,41 @@ +# Copyright David Abrahams 2004. 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) +r'''>>> import pickle1_ext + >>> import pickle + >>> pickle1_ext.world.__module__ + 'pickle1_ext' + >>> pickle1_ext.world.__safe_for_unpickling__ + 1 + >>> pickle1_ext.world.__name__ + 'world' + >>> pickle1_ext.world('Hello').__reduce__() + (<class 'pickle1_ext.world'>, ('Hello',)) + >>> wd = pickle1_ext.world('California') + >>> pstr = pickle.dumps(wd) + >>> wl = pickle.loads(pstr) + >>> print(wd.greet()) + Hello from California! + >>> print(wl.greet()) + Hello from California! + + >>> noop = pickle1_ext.noop() + >>> try: pickle.dumps(noop) + ... except RuntimeError as e: print(str(e)[:55]) + Pickling of "pickle1_ext.noop" instances is not enabled +''' + +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/pickle2.cpp b/src/boost/libs/python/test/pickle2.cpp new file mode 100644 index 000000000..c9610946e --- /dev/null +++ b/src/boost/libs/python/test/pickle2.cpp @@ -0,0 +1,97 @@ +// Copyright Ralf W. Grosse-Kunstleve 2002-2004. 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) + +/* + This example shows how to make an Extension Class "pickleable". + + The world class below contains member data (secret_number) that + cannot be restored by any of the constructors. Therefore it is + necessary to provide the __getstate__/__setstate__ pair of pickle + interface methods. + + For simplicity, the __dict__ is not included in the result of + __getstate__. This is not generally recommended, but a valid + approach if it is anticipated that the object's __dict__ will + always be empty. Note that safety guards are provided to catch + the cases where this assumption is not true. + + pickle3.cpp shows how to include the object's __dict__ in the + result of __getstate__. + + For more information refer to boost/libs/python/doc/pickle.html. + */ + +#include <boost/python/module.hpp> +#include <boost/python/def.hpp> +#include <boost/python/class.hpp> +#include <boost/python/tuple.hpp> +#include <boost/python/extract.hpp> + +namespace boost_python_test { + + // A friendly class. + class world + { + public: + world(const std::string& _country) : secret_number(0) { + this->country = _country; + } + std::string greet() const { return "Hello from " + country + "!"; } + std::string get_country() const { return country; } + void set_secret_number(int number) { secret_number = number; } + int get_secret_number() const { return secret_number; } + private: + std::string country; + int secret_number; + }; + + struct world_pickle_suite : boost::python::pickle_suite + { + static + boost::python::tuple + getinitargs(const world& w) + { + return boost::python::make_tuple(w.get_country()); + } + + static + boost::python::tuple + getstate(const world& w) + { + return boost::python::make_tuple(w.get_secret_number()); + } + + static + void + setstate(world& w, boost::python::tuple state) + { + using namespace boost::python; + if (len(state) != 1) + { + PyErr_SetObject(PyExc_ValueError, + ("expected 1-item tuple in call to __setstate__; got %s" + % state).ptr() + ); + throw_error_already_set(); + } + + long number = extract<long>(state[0]); + if (number != 42) + w.set_secret_number(number); + } + }; + +} + +BOOST_PYTHON_MODULE(pickle2_ext) +{ + using namespace boost_python_test; + boost::python::class_<world>( + "world", boost::python::init<const std::string&>()) + .def("greet", &world::greet) + .def("get_secret_number", &world::get_secret_number) + .def("set_secret_number", &world::set_secret_number) + .def_pickle(world_pickle_suite()) + ; +} diff --git a/src/boost/libs/python/test/pickle2.py b/src/boost/libs/python/test/pickle2.py new file mode 100644 index 000000000..f4788d3b8 --- /dev/null +++ b/src/boost/libs/python/test/pickle2.py @@ -0,0 +1,51 @@ +# Copyright David Abrahams 2004. 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) +from __future__ import print_function +r'''>>> import pickle2_ext + >>> import pickle + >>> pickle2_ext.world.__module__ + 'pickle2_ext' + >>> pickle2_ext.world.__safe_for_unpickling__ + 1 + >>> pickle2_ext.world.__name__ + 'world' + >>> pickle2_ext.world('Hello').__reduce__() + (<class 'pickle2_ext.world'>, ('Hello',), (0,)) + >>> for number in (24, 42): + ... wd = pickle2_ext.world('California') + ... wd.set_secret_number(number) + ... pstr = pickle.dumps(wd) + ... wl = pickle.loads(pstr) + ... print(wd.greet(), wd.get_secret_number()) + ... print(wl.greet(), wl.get_secret_number()) + Hello from California! 24 + Hello from California! 24 + Hello from California! 42 + Hello from California! 0 + +# Now show that the __dict__ is not taken care of. + >>> wd = pickle2_ext.world('California') + >>> wd.x = 1 + >>> wd.__dict__ + {'x': 1} + >>> try: pstr = pickle.dumps(wd) + ... except RuntimeError as err: print(err) + ... + Incomplete pickle support (__getstate_manages_dict__ not set) +''' + +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/pickle3.cpp b/src/boost/libs/python/test/pickle3.cpp new file mode 100644 index 000000000..7afe2dbfa --- /dev/null +++ b/src/boost/libs/python/test/pickle3.cpp @@ -0,0 +1,107 @@ +// Copyright Ralf W. Grosse-Kunstleve 2002-2004. 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) + +/* + This example shows how to make an Extension Class "pickleable". + + The world class below contains member data (secret_number) that + cannot be restored by any of the constructors. Therefore it is + necessary to provide the __getstate__/__setstate__ pair of pickle + interface methods. + + The object's __dict__ is included in the result of __getstate__. + This requires more code (compare with pickle2.cpp), but is + unavoidable if the object's __dict__ is not always empty. + + For more information refer to boost/libs/python/doc/pickle.html. + */ + +#include <boost/python/module.hpp> +#include <boost/python/def.hpp> +#include <boost/python/class.hpp> +#include <boost/python/tuple.hpp> +#include <boost/python/dict.hpp> +#include <boost/python/extract.hpp> +#include <boost/python/back_reference.hpp> + +namespace boost_python_test { + + // A friendly class. + class world + { + public: + world(const std::string& _country) : secret_number(0) { + this->country = _country; + } + std::string greet() const { return "Hello from " + country + "!"; } + std::string get_country() const { return country; } + void set_secret_number(int number) { secret_number = number; } + int get_secret_number() const { return secret_number; } + private: + std::string country; + int secret_number; + }; + + struct world_pickle_suite : boost::python::pickle_suite + { + static + boost::python::tuple + getinitargs(const world& w) + { + return boost::python::make_tuple(w.get_country()); + } + + static + boost::python::tuple + getstate(boost::python::object w_obj) + { + world const& w = boost::python::extract<world const&>(w_obj)(); + + return boost::python::make_tuple( + w_obj.attr("__dict__"), + w.get_secret_number()); + } + + static + void + setstate(boost::python::object w_obj, boost::python::tuple state) + { + using namespace boost::python; + world& w = extract<world&>(w_obj)(); + + if (len(state) != 2) + { + PyErr_SetObject(PyExc_ValueError, + ("expected 2-item tuple in call to __setstate__; got %s" + % state).ptr() + ); + throw_error_already_set(); + } + + // restore the object's __dict__ + dict d = extract<dict>(w_obj.attr("__dict__"))(); + d.update(state[0]); + + // restore the internal state of the C++ object + long number = extract<long>(state[1]); + if (number != 42) + w.set_secret_number(number); + } + + static bool getstate_manages_dict() { return true; } + }; + +} + +BOOST_PYTHON_MODULE(pickle3_ext) +{ + using namespace boost_python_test; + boost::python::class_<world>( + "world", boost::python::init<const std::string&>()) + .def("greet", &world::greet) + .def("get_secret_number", &world::get_secret_number) + .def("set_secret_number", &world::set_secret_number) + .def_pickle(world_pickle_suite()) + ; +} diff --git a/src/boost/libs/python/test/pickle3.py b/src/boost/libs/python/test/pickle3.py new file mode 100644 index 000000000..932e30f3c --- /dev/null +++ b/src/boost/libs/python/test/pickle3.py @@ -0,0 +1,46 @@ +# Copyright David Abrahams 2004. 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) +from __future__ import print_function +r'''>>> import pickle3_ext + >>> import pickle + >>> pickle3_ext.world.__module__ + 'pickle3_ext' + >>> pickle3_ext.world.__safe_for_unpickling__ + 1 + >>> pickle3_ext.world.__getstate_manages_dict__ + 1 + >>> pickle3_ext.world.__name__ + 'world' + >>> pickle3_ext.world('Hello').__reduce__() + (<class 'pickle3_ext.world'>, ('Hello',), ({}, 0)) + >>> for number in (24, 42): + ... wd = pickle3_ext.world('California') + ... wd.set_secret_number(number) + ... wd.x = 2 * number + ... wd.y = 'y' * number + ... wd.z = 3. * number + ... pstr = pickle.dumps(wd) + ... wl = pickle.loads(pstr) + ... print(wd.greet(), wd.get_secret_number(), wd.x, wd.y, wd.z) + ... print(wl.greet(), wl.get_secret_number(), wl.x, wl.y, wl.z) + Hello from California! 24 48 yyyyyyyyyyyyyyyyyyyyyyyy 72.0 + Hello from California! 24 48 yyyyyyyyyyyyyyyyyyyyyyyy 72.0 + Hello from California! 42 84 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy 126.0 + Hello from California! 0 84 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy 126.0 +''' + +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/pickle4.cpp b/src/boost/libs/python/test/pickle4.cpp new file mode 100644 index 000000000..1374cc7dc --- /dev/null +++ b/src/boost/libs/python/test/pickle4.cpp @@ -0,0 +1,44 @@ +// Copyright Ralf W. Grosse-Kunstleve 2004. 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) + +/* + This example shows how to enable pickling without using the + pickle_suite. The pickling interface (__getinitargs__) is + implemented in Python. + + For more information refer to boost/libs/python/doc/pickle.html. + */ + +#include <boost/python/module.hpp> +#include <boost/python/class.hpp> + +#include <string> + +namespace boost_python_test { + + // A friendly class. + class world + { + private: + std::string country; + public: + world(const std::string& _country) { + this->country = _country; + } + std::string greet() const { return "Hello from " + country + "!"; } + std::string get_country() const { return country; } + }; + +} + +BOOST_PYTHON_MODULE(pickle4_ext) +{ + using namespace boost::python; + using namespace boost_python_test; + class_<world>("world", init<const std::string&>()) + .enable_pickling() + .def("greet", &world::greet) + .def("get_country", &world::get_country) + ; +} diff --git a/src/boost/libs/python/test/pickle4.py b/src/boost/libs/python/test/pickle4.py new file mode 100644 index 000000000..be813bbb1 --- /dev/null +++ b/src/boost/libs/python/test/pickle4.py @@ -0,0 +1,39 @@ +# Copyright David Abrahams 2004. 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) +r'''>>> import pickle4_ext + >>> import pickle + >>> def world_getinitargs(self): + ... return (self.get_country(),) + >>> pickle4_ext.world.__getinitargs__ = world_getinitargs + >>> pickle4_ext.world.__module__ + 'pickle4_ext' + >>> pickle4_ext.world.__safe_for_unpickling__ + 1 + >>> pickle4_ext.world.__name__ + 'world' + >>> pickle4_ext.world('Hello').__reduce__() + (<class 'pickle4_ext.world'>, ('Hello',)) + >>> wd = pickle4_ext.world('California') + >>> pstr = pickle.dumps(wd) + >>> wl = pickle.loads(pstr) + >>> print(wd.greet()) + Hello from California! + >>> print(wl.greet()) + Hello from California! +''' + +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/pointee.cpp b/src/boost/libs/python/test/pointee.cpp new file mode 100644 index 000000000..2aa5dc3d8 --- /dev/null +++ b/src/boost/libs/python/test/pointee.cpp @@ -0,0 +1,34 @@ +// Copyright David Abrahams 2002. +// 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) +#include <boost/python/pointee.hpp> +#include <boost/python/detail/type_traits.hpp> +#include <memory> +#include <boost/shared_ptr.hpp> +#include <boost/static_assert.hpp> + +struct A; + +int main() +{ + BOOST_STATIC_ASSERT( + (boost::python::detail::is_same< + boost::python::pointee<std::auto_ptr<char**> >::type + , char** + >::value)); + + BOOST_STATIC_ASSERT( + (boost::python::detail::is_same< + boost::python::pointee<boost::shared_ptr<A> >::type + , A>::value)); + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + BOOST_STATIC_ASSERT( + (boost::python::detail::is_same< + boost::python::pointee<char*>::type + , char + >::value)); +#endif + return 0; +} diff --git a/src/boost/libs/python/test/pointer_type_id_test.cpp b/src/boost/libs/python/test/pointer_type_id_test.cpp new file mode 100644 index 000000000..02e168c7e --- /dev/null +++ b/src/boost/libs/python/test/pointer_type_id_test.cpp @@ -0,0 +1,43 @@ +// Copyright David Abrahams 2004. 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) +#include <boost/python/type_id.hpp> + +#include <boost/detail/lightweight_test.hpp> +#include <boost/python/converter/pointer_type_id.hpp> + +int main() +{ + using namespace boost::python::converter; + + boost::python::type_info x + = boost::python::type_id<int>(); + + + BOOST_TEST(pointer_type_id<int*>() == x); + BOOST_TEST(pointer_type_id<int const*>() == x); + BOOST_TEST(pointer_type_id<int volatile*>() == x); + BOOST_TEST(pointer_type_id<int const volatile*>() == x); + + BOOST_TEST(pointer_type_id<int*&>() == x); + BOOST_TEST(pointer_type_id<int const*&>() == x); + BOOST_TEST(pointer_type_id<int volatile*&>() == x); + BOOST_TEST(pointer_type_id<int const volatile*&>() == x); + + BOOST_TEST(pointer_type_id<int*const&>() == x); + BOOST_TEST(pointer_type_id<int const*const&>() == x); + BOOST_TEST(pointer_type_id<int volatile*const&>() == x); + BOOST_TEST(pointer_type_id<int const volatile*const&>() == x); + + BOOST_TEST(pointer_type_id<int*volatile&>() == x); + BOOST_TEST(pointer_type_id<int const*volatile&>() == x); + BOOST_TEST(pointer_type_id<int volatile*volatile&>() == x); + BOOST_TEST(pointer_type_id<int const volatile*volatile&>() == x); + + BOOST_TEST(pointer_type_id<int*const volatile&>() == x); + BOOST_TEST(pointer_type_id<int const*const volatile&>() == x); + BOOST_TEST(pointer_type_id<int volatile*const volatile&>() == x); + BOOST_TEST(pointer_type_id<int const volatile*const volatile&>() == x); + + return boost::report_errors(); +} diff --git a/src/boost/libs/python/test/pointer_vector.cpp b/src/boost/libs/python/test/pointer_vector.cpp new file mode 100644 index 000000000..08cd48619 --- /dev/null +++ b/src/boost/libs/python/test/pointer_vector.cpp @@ -0,0 +1,52 @@ +// Copyright Joel de Guzman 2005-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) +#include <boost/python.hpp> +#include <boost/python/suite/indexing/vector_indexing_suite.hpp> +#include <vector> + +using namespace boost::python; + +class Abstract +{ +public: + virtual ~Abstract() {}; // silence compiler warningsa + virtual std::string f() =0; +}; + +class Concrete1 : public Abstract +{ +public: + virtual std::string f() { return "harru"; } +}; + +typedef std::vector<Abstract*> ListOfObjects; + +class DoesSomething +{ +public: + DoesSomething() {} + + ListOfObjects returnList() + { + ListOfObjects lst; + lst.push_back(new Concrete1()); return lst; + } +}; + +BOOST_PYTHON_MODULE(pointer_vector_ext) +{ +class_<Abstract, boost::noncopyable>("Abstract", no_init) + .def("f", &Abstract::f) + ; + +class_<ListOfObjects>("ListOfObjects") + .def( vector_indexing_suite<ListOfObjects>() ) + ; + +class_<DoesSomething>("DoesSomething") + .def("returnList", &DoesSomething::returnList) + ; +} + + diff --git a/src/boost/libs/python/test/pointer_vector.py b/src/boost/libs/python/test/pointer_vector.py new file mode 100644 index 000000000..234eff2c0 --- /dev/null +++ b/src/boost/libs/python/test/pointer_vector.py @@ -0,0 +1,31 @@ +# Copyright Joel de Guzman 2004. 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) +''' + +>>> import pointer_vector_ext +>>> d = pointer_vector_ext.DoesSomething() +>>> lst = d.returnList() +>>> lst[0].f(); +'harru' + +''' + + +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) + + + diff --git a/src/boost/libs/python/test/polymorphism.cpp b/src/boost/libs/python/test/polymorphism.cpp new file mode 100644 index 000000000..02713ae26 --- /dev/null +++ b/src/boost/libs/python/test/polymorphism.cpp @@ -0,0 +1,162 @@ +// Copyright David Abrahams 2002. +// 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) +#include <boost/python/module.hpp> +#include <boost/python/class.hpp> +#include <boost/python/return_value_policy.hpp> +#include <boost/python/manage_new_object.hpp> +#include <boost/python/reference_existing_object.hpp> +#include <boost/python/call_method.hpp> +#include <boost/python/pure_virtual.hpp> +#include <boost/python/def.hpp> +#include <boost/utility.hpp> + +using namespace boost::python; + +struct Callback +{ + Callback(PyObject* o) : mSelf(o) {} + PyObject* mSelf; +}; + +struct P +{ + virtual ~P(){} + virtual std::string f() = 0; + std::string g() { return "P::g()"; } +}; + +struct PCallback : P, Callback +{ + PCallback (PyObject* self) : Callback(self) {} + + std::string f() + { + return call_method<std::string>(mSelf, "f"); + } +}; + +struct Q : virtual P +{ + std::string f() { return "Q::f()"; } +}; + +struct A +{ + virtual ~A(){} + virtual std::string f() { return "A::f()"; } +}; + +struct ACallback : A, Callback +{ + ACallback (PyObject* self) : Callback(self) {} + + + std::string f() + { + return call_method<std::string>(mSelf, "f"); + } + + std::string default_f() + { + return A::f(); + } +}; + +struct B : A +{ + virtual std::string f() { return "B::f()"; } +}; + +struct C : A +{ + virtual std::string f() { return "C::f()"; } +}; + +struct D : A +{ + virtual std::string f() { return "D::f()"; } + std::string g() { return "D::g()"; } +}; + +struct DCallback : D, Callback +{ + DCallback (PyObject* self) : Callback(self) {} + + std::string f() + { + return call_method<std::string>(mSelf, "f"); + } + + std::string default_f() + { + return A::f(); + } +}; + + +A& getBCppObj () +{ + static B b; + return b; +} + +std::string call_f(A& a) { return a.f(); } + +A* factory(unsigned choice) +{ + switch (choice % 3) + { + case 0: return new A; + break; + case 1: return new B; + break; + default: return new C; + break; + } +} + +C& getCCppObj () +{ + static C c; + return c; +} + +A* pass_a(A* x) { return x; } + +BOOST_PYTHON_MODULE_INIT(polymorphism_ext) +{ + class_<A,boost::noncopyable,ACallback>("A") + .def("f", &A::f, &ACallback::default_f) + ; + + def("getBCppObj", getBCppObj, return_value_policy<reference_existing_object>()); + + class_<C,bases<A>,boost::noncopyable>("C") + .def("f", &C::f) + ; + + class_<D,bases<A>,DCallback,boost::noncopyable>("D") + .def("f", &D::f, &DCallback::default_f) + .def("g", &D::g) + ; + + def("pass_a", &pass_a, return_internal_reference<>()); + + def("getCCppObj", getCCppObj, return_value_policy<reference_existing_object>()); + + def("factory", factory, return_value_policy<manage_new_object>()); + + def("call_f", call_f); + + class_<P,boost::noncopyable,PCallback>("P") + .def("f", pure_virtual(&P::f)) + ; + + class_<Q, bases<P> >("Q") + .def("g", &P::g) // make sure virtual inheritance doesn't interfere + ; +} + +//#include "module_tail.cpp" diff --git a/src/boost/libs/python/test/polymorphism.py b/src/boost/libs/python/test/polymorphism.py new file mode 100644 index 000000000..e3c66ea27 --- /dev/null +++ b/src/boost/libs/python/test/polymorphism.py @@ -0,0 +1,74 @@ +# Copyright David Abrahams 2004. 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) +import unittest +from polymorphism_ext import * + +class PolymorphTest(unittest.TestCase): + + def testReturnCpp(self): + + # Python Created Object With Same Id As + # Cpp Created B Object + # b = B(872) + + # Get Reference To Cpp Created B Object + a = getBCppObj() + + # Python Created B Object and Cpp B Object + # Should have same result by calling f() + self.assertEqual ('B::f()', a.f()) + self.assertEqual ('B::f()', call_f(a)) + self.assertEqual ('A::f()', call_f(A())) + + def test_references(self): + # B is not exposed to Python + a = getBCppObj() + self.assertEqual(type(a), A) + + # C is exposed to Python + c = getCCppObj() + self.assertEqual(type(c), C) + + def test_factory(self): + self.assertEqual(type(factory(0)), A) + self.assertEqual(type(factory(1)), A) + self.assertEqual(type(factory(2)), C) + + def test_return_py(self): + + class X(A): + def f(self): + return 'X.f' + + x = X() + + self.assertEqual ('X.f', x.f()) + self.assertEqual ('X.f', call_f(x)) + + def test_wrapper_downcast(self): + a = pass_a(D()) + self.assertEqual('D::g()', a.g()) + + def test_pure_virtual(self): + p = P() + self.assertRaises(RuntimeError, p.f) + + q = Q() + self.assertEqual ('Q::f()', q.f()) + + class R(P): + def f(self): + return 'R.f' + + r = R() + self.assertEqual ('R.f', r.f()) + + +if __name__ == "__main__": + + # remove the option which upsets unittest + import sys + sys.argv = [ x for x in sys.argv if x != '--broken-auto-ptr' ] + + unittest.main() diff --git a/src/boost/libs/python/test/polymorphism2.cpp b/src/boost/libs/python/test/polymorphism2.cpp new file mode 100644 index 000000000..8aefbc3af --- /dev/null +++ b/src/boost/libs/python/test/polymorphism2.cpp @@ -0,0 +1,172 @@ +// Copyright David Abrahams 2002. +// 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) +#include <boost/python/module.hpp> +#include <boost/python/class.hpp> +#include <boost/python/return_value_policy.hpp> +#include <boost/python/manage_new_object.hpp> +#include <boost/python/reference_existing_object.hpp> +#include <boost/python/pure_virtual.hpp> +#include <boost/python/wrapper.hpp> +#include <boost/python/def.hpp> +#include <boost/python/call.hpp> +#include <boost/utility.hpp> + +#include <memory> + +#ifdef HELD_BY_AUTO_PTR +# define HELD_PTR(X) , std::auto_ptr< X > +#else +# define HELD_PTR(X) +#endif + +using namespace boost::python; + +struct P +{ + virtual ~P(){} + virtual char const* f() = 0; + char const* g() { return "P::g()"; } +}; + +struct PCallback : P, wrapper<P> +{ + char const* f() + { +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + return call<char const*>(this->get_override("f").ptr()); +#else + return this->get_override("f")(); +#endif + } +}; + +struct Q : virtual P +{ + char const* f() { return "Q::f()"; } +}; + +struct A +{ + virtual ~A(){} + virtual char const* f() { return "A::f()"; } +}; + +struct ACallback : A, wrapper<A> +{ + char const* f() + { + if (override f = this->get_override("f")) +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + return call<char const*>(f.ptr()); +#else + return f(); +#endif + + return A::f(); + } + + char const* default_f() { return this->A::f(); } +}; + +struct B : A +{ + virtual char const* f() { return "B::f()"; } +}; + +struct C : A +{ + virtual char const* f() { return "C::f()"; } +}; + +struct D : A +{ + virtual char const* f() { return "D::f()"; } + char const* g() { return "D::g()"; } +}; + +struct DCallback : D, wrapper<D> +{ + char const* f() + { + if (override f = this->get_override("f")) +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + return call<char const*>(f.ptr()); +#else + return f(); +#endif + //else + return D::f(); + } +}; + + +A& getBCppObj () +{ + static B b; + return b; +} + +char const* call_f(A& a) { return a.f(); } + +A* factory(unsigned choice) +{ + switch (choice % 3) + { + case 0: return new A; + break; + case 1: return new B; + break; + default: return new C; + break; + } +} + +C& getCCppObj () +{ + static C c; + return c; +} + +A* pass_a(A* x) { return x; } + +#ifdef HELD_BY_AUTO_PTR +BOOST_PYTHON_MODULE_INIT(polymorphism2_auto_ptr_ext) +#else +BOOST_PYTHON_MODULE_INIT(polymorphism2_ext) +#endif +{ + class_<ACallback HELD_PTR(A),boost::noncopyable>("A") + .def("f", &A::f, &ACallback::default_f) + ; + + def("getBCppObj", getBCppObj, return_value_policy<reference_existing_object>()); + + class_<C HELD_PTR(C),bases<A>,boost::noncopyable>("C") + .def("f", &C::f) + ; + + class_<DCallback HELD_PTR(D),bases<A>,boost::noncopyable>("D") + .def("f", &D::f) + .def("g", &D::g) + ; + + def("pass_a", &pass_a, return_internal_reference<>()); + + def("getCCppObj", getCCppObj, return_value_policy<reference_existing_object>()); + + def("factory", factory, return_value_policy<manage_new_object>()); + + def("call_f", call_f); + + class_<PCallback,boost::noncopyable>("P") + .def("f", pure_virtual(&P::f)) + ; + + class_<Q HELD_PTR(Q), bases<P> >("Q") + .def("g", &P::g) // make sure virtual inheritance doesn't interfere + ; +} + +//#include "module_tail.cpp" diff --git a/src/boost/libs/python/test/polymorphism2.py b/src/boost/libs/python/test/polymorphism2.py new file mode 100644 index 000000000..cf7384fab --- /dev/null +++ b/src/boost/libs/python/test/polymorphism2.py @@ -0,0 +1,94 @@ +# Copyright David Abrahams 2004. 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) +import unittest +import sys + +class PolymorphTest(unittest.TestCase): + + def testReturnCpp(self): + + # Python Created Object With Same Id As + # Cpp Created B Object + # b = B(872) + + # Get Reference To Cpp Created B Object + a = getBCppObj() + + # Python Created B Object and Cpp B Object + # Should have same result by calling f() + self.assertEqual ('B::f()', a.f()) + self.assertEqual ('B::f()', call_f(a)) + self.assertEqual ('A::f()', call_f(A())) + + def test_references(self): + # B is not exposed to Python + a = getBCppObj() + self.assertEqual(type(a), A) + + # C is exposed to Python + c = getCCppObj() + self.assertEqual(type(c), C) + + def test_factory(self): + self.assertEqual(type(factory(0)), A) + self.assertEqual(type(factory(1)), A) + self.assertEqual(type(factory(2)), C) + + def test_return_py(self): + + class X(A): + def f(self): + return 'X.f' + + x = X() + + self.assertEqual ('X.f', x.f()) + self.assertEqual ('X.f', call_f(x)) + + def test_self_default(self): + + class X(A): + def f(self): + return 'X.f() -> ' + A.f(self) + + x = X() + + self.assertEqual ('X.f() -> A::f()', x.f()) + + # This one properly raises the "dangling reference" exception + # self.failUnlessEqual ('X.f() -> A::f()', call_f(x)) + + def test_wrapper_downcast(self): + a = pass_a(D()) + self.assertEqual('D::g()', a.g()) + + def test_pure_virtual(self): + p = P() + self.assertRaises(RuntimeError, p.f) + + q = Q() + self.assertEqual ('Q::f()', q.f()) + + class R(P): + def f(self): + return 'R.f' + + r = R() + self.assertEqual ('R.f', r.f()) + + +def test(): + # remove the option that upsets unittest + import sys + sys.argv = [ x for x in sys.argv if x != '--broken-auto-ptr' ] + unittest.main() + +# This nasty hack basically says that if we're loaded by another module, we'll +# be testing polymorphism2_auto_ptr_ext instead of polymorphism2_ext. +if __name__ == "__main__": + from polymorphism2_ext import * + test() +else: + from polymorphism2_auto_ptr_ext import * + diff --git a/src/boost/libs/python/test/polymorphism2_auto_ptr.cpp b/src/boost/libs/python/test/polymorphism2_auto_ptr.cpp new file mode 100644 index 000000000..8cd5ef247 --- /dev/null +++ b/src/boost/libs/python/test/polymorphism2_auto_ptr.cpp @@ -0,0 +1,6 @@ +// Copyright David Abrahams 2005. 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) + +#define HELD_BY_AUTO_PTR +#include "polymorphism2.cpp" diff --git a/src/boost/libs/python/test/polymorphism2_auto_ptr.py b/src/boost/libs/python/test/polymorphism2_auto_ptr.py new file mode 100644 index 000000000..88cf664ab --- /dev/null +++ b/src/boost/libs/python/test/polymorphism2_auto_ptr.py @@ -0,0 +1,5 @@ +# Copyright David Abrahams 2005. 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) +import polymorphism2 +polymorphism2.test() diff --git a/src/boost/libs/python/test/properties.cpp b/src/boost/libs/python/test/properties.cpp new file mode 100644 index 000000000..d338beb91 --- /dev/null +++ b/src/boost/libs/python/test/properties.cpp @@ -0,0 +1,100 @@ +// Copyright David Abrahams 2004. 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) +#include <boost/python.hpp> + +using namespace boost::python; + +namespace test { + +// Hmm. return_internal_reference<>() wants to wrap a real class. +class ret_type +{ + public: + ret_type() : i(42.5) {} + double i; +}; + +class crash_me +{ + private: + ret_type i; + public: + ret_type& get_i() { return i; } +}; + +} + +struct X +{ + X( int value ) : m_value( value ) + { ++s_count; } + + X( const X &other ) : m_value( other.m_value ) + { ++s_count; } + + ~X() + { --s_count; } + + int get_value() const + { return m_value; } + + void set_value(int new_value) + { m_value = new_value; } + + static int get_instance_count() + { return s_count; } + + int m_value; + + static int s_count; +}; + +int X::s_count = 0; + +int get_X_instance_count() +{ return X::get_instance_count(); } + + + +BOOST_PYTHON_MODULE(properties_ext) +{ + typedef return_value_policy<return_by_value> return_by_value_t; + typedef return_internal_reference<> return_by_internal_reference_t; + class_<X>("X", init<int>() ) + //defining read only property + .add_property( "value_r", &X::get_value ) + .add_property( "value_r_ds", &X::get_value, "value_r_ds is read-only") + //defining read \ write property + .add_property( "value_rw", &X::get_value, &X::set_value ) + .add_property( "value_rw_ds", &X::get_value, &X::set_value, + "value_rw_ds is read-write") + //defining read \ write property using make_getter and make_setter + .add_property( "value_direct", + make_getter( &X::m_value, return_by_value_t() ), + make_setter( &X::m_value, return_by_internal_reference_t() ) ) + //defining read only property for static member + .add_static_property( "instance_count", &X::get_instance_count ) + //defining read \ write property for static member using make_getter and make_setter + .add_static_property( "instance_count_direct", + make_getter( &X::s_count, return_by_value_t() ), + make_setter( &X::s_count, return_by_internal_reference_t() ) ) + //defining class property using a global function + .add_static_property( "instance_count_injected", &get_X_instance_count ); + + + class_< test::ret_type>( "ret_type") + .add_property( "i", &test::ret_type::i, &test::ret_type::i) + ; + + class_< test::crash_me> crash_me_wrapper( "crash_me"); + + crash_me_wrapper + .def( "get_i", &test::crash_me::get_i , return_internal_reference<>()) + ; + + crash_me_wrapper.add_property( "i", crash_me_wrapper.attr("get_i")); + +} + +#include "module_tail.cpp" diff --git a/src/boost/libs/python/test/properties.py b/src/boost/libs/python/test/properties.py new file mode 100644 index 000000000..1bc7a624b --- /dev/null +++ b/src/boost/libs/python/test/properties.py @@ -0,0 +1,106 @@ +# Copyright David Abrahams 2004. 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) +""" +This is test module for properties. + +>>> r = properties.ret_type() +>>> r.i = 22.5 +>>> r.i +22.5 +>>> c = properties.crash_me() +>>> c.i.i +42.5 + +>>> X = properties.X + +>>> x1 = X(1) + +value read only +>>> x1.value_r +1 + +value read - write +>>> x1.value_rw +1 + +value direct access +>>> x1.value_direct +1 + +class instance count read - only +>>> X.instance_count +1 + +class instance count direct +>>> X.instance_count_direct +1 + +class instance count injected +>>> X.instance_count_injected +1 + +class instance count from object +>>> x1.instance_count +1 + +class instance count from object +>>> x1.instance_count_direct +1 + +class instance count from object: +>>> x1.instance_count_injected +1 + +as expected you can't assign new value to read only property +>>> x1.value_r = 2 +Traceback (most recent call last): + File "properties.py", line 49, in ? + x1.value_r = 2 +AttributeError: can't set attribute + +setting value_rw to 2. value_direct: +>>> x1.value_rw = 2 +>>> x1.value_rw +2 + +setting value_direct to 3. value_direct: +>>> x1.value_direct = 3 +>>> x1.value_direct +3 + +>>> assert x1.value_r == 3 + +>>> x2 = X(2) + +after creating second intstance of X instances count is 2 +>>> x2.instance_count +2 + +>>> del x2 +>>> assert x1.instance_count == 1 + +>>> assert properties.X.value_r_ds.__doc__ == "value_r_ds is read-only" + +>>> assert properties.X.value_rw_ds.__doc__ == "value_rw_ds is read-write" + +""" + +#import sys; sys.path.append(r'P:\Actimize4.0\smart_const\py_smart_const___Win32_Debug') +import properties_ext as properties + + +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/pyrun.py b/src/boost/libs/python/test/pyrun.py new file mode 100644 index 000000000..d330773ea --- /dev/null +++ b/src/boost/libs/python/test/pyrun.py @@ -0,0 +1,7 @@ +import sys + +pythonpath = sys.argv[1] +scriptfile = sys.argv[2] +sys.argv = sys.argv[2:] +sys.path.append(pythonpath) +exec(compile(open(scriptfile).read(), scriptfile, 'exec')) diff --git a/src/boost/libs/python/test/pytype_function.cpp b/src/boost/libs/python/test/pytype_function.cpp new file mode 100644 index 000000000..46cce19e6 --- /dev/null +++ b/src/boost/libs/python/test/pytype_function.cpp @@ -0,0 +1,85 @@ +// Copyright Joel de Guzman 2004. 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) + +#include <boost/python/module.hpp> +#include <boost/python/def.hpp> +#include <boost/python/extract.hpp> +#include <boost/python/to_python_converter.hpp> +#include <boost/python/class.hpp> + +using namespace boost::python; + +struct A +{ +}; + +struct B +{ + A a; + B(const A& a_):a(a_){} +}; + +// Converter from A to python int +struct BToPython +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + : converter::to_python_target_type<A> //inherits get_pytype +#endif +{ + static PyObject* convert(const B& b) + { + return boost::python::incref(boost::python::object(b.a).ptr()); + } +}; + +// Conversion from python int to A +struct BFromPython +{ + BFromPython() + { + boost::python::converter::registry::push_back( + &convertible, + &construct, + boost::python::type_id< B >() +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + , &converter::expected_from_python_type<A>::get_pytype//convertible to A can be converted to B +#endif + ); + } + + static void* convertible(PyObject* obj_ptr) + { + extract<const A&> ex(obj_ptr); + if (!ex.check()) return 0; + return obj_ptr; + } + + static void construct( + PyObject* obj_ptr, + boost::python::converter::rvalue_from_python_stage1_data* data) + { + void* storage = ( + (boost::python::converter::rvalue_from_python_storage< B >*)data)-> storage.bytes; + + extract<const A&> ex(obj_ptr); + new (storage) B(ex()); + data->convertible = storage; + } +}; + + +B func(const B& b) { return b ; } + + +BOOST_PYTHON_MODULE(pytype_function_ext) +{ + to_python_converter< B , BToPython,true >(); //has get_pytype + BFromPython(); + + class_<A>("A") ; + + def("func", &func); + +} + +#include "module_tail.cpp" diff --git a/src/boost/libs/python/test/pytype_function.py b/src/boost/libs/python/test/pytype_function.py new file mode 100644 index 000000000..a7101fb99 --- /dev/null +++ b/src/boost/libs/python/test/pytype_function.py @@ -0,0 +1,32 @@ +# Copyright David Abrahams 2004. 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) +""" +>>> from pytype_function_ext import * + +>>> print(func.__doc__.splitlines()[1]) +func( (A)arg1) -> A : + +>>> print(func.__module__) +pytype_function_ext + +>>> print(func.__name__) +func +""" +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) + + + diff --git a/src/boost/libs/python/test/raw_ctor.cpp b/src/boost/libs/python/test/raw_ctor.cpp new file mode 100644 index 000000000..a825ae019 --- /dev/null +++ b/src/boost/libs/python/test/raw_ctor.cpp @@ -0,0 +1,43 @@ +// Copyright David Abrahams 2004. 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) + +#include <boost/python/class.hpp> +#include <boost/python/raw_function.hpp> +#include <boost/python/make_constructor.hpp> +#include <boost/python/dict.hpp> +#include <boost/python/tuple.hpp> +#include <boost/python/module.hpp> + +using namespace boost::python; + +class Foo +{ + public: + Foo(tuple args, dict kw) + : args(args), kw(kw) {} + + tuple args; + dict kw; +}; + +object init_foo(tuple args, dict kw) +{ + tuple rest(args.slice(1,_)); + return args[0].attr("__init__")(rest, kw); +} + +BOOST_PYTHON_MODULE(raw_ctor_ext) +{ + // using no_init postpones defining __init__ function until after + // raw_function for proper overload resolution order, since later + // defs get higher priority. + class_<Foo>("Foo", no_init) + .def("__init__", raw_function(&init_foo)) + .def(init<tuple, dict>()) + .def_readwrite("args", &Foo::args) + .def_readwrite("kw", &Foo::kw) + ; +} + +#include "module_tail.cpp" diff --git a/src/boost/libs/python/test/raw_ctor.py b/src/boost/libs/python/test/raw_ctor.py new file mode 100644 index 000000000..1e9a9192a --- /dev/null +++ b/src/boost/libs/python/test/raw_ctor.py @@ -0,0 +1,76 @@ +# Copyright David Abrahams 2004. 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) +""" +>>> 'importing' +'importing' +>>> from raw_ctor_ext import * +>>> 'imported' +'imported' +>>> import sys +>>> sys.stdout.flush() +>>> f = Foo(1, 2, 'a', bar = 3, baz = 4) +>>> f.args +(1, 2, 'a') +>>> sorted(f.kw.items()) +[('bar', 3), ('baz', 4)] +""" +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/boost/libs/python/test/raw_pyobject_fail1.cpp b/src/boost/libs/python/test/raw_pyobject_fail1.cpp new file mode 100644 index 000000000..f9dd54bc3 --- /dev/null +++ b/src/boost/libs/python/test/raw_pyobject_fail1.cpp @@ -0,0 +1,11 @@ +// Copyright David Abrahams 2002. +// 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) +#include <boost/python/converter/arg_to_python.hpp> + +int main() +{ + boost::python::converter::arg_to_python<PyTypeObject*> x(0); + return 0; +} diff --git a/src/boost/libs/python/test/raw_pyobject_fail2.cpp b/src/boost/libs/python/test/raw_pyobject_fail2.cpp new file mode 100644 index 000000000..62c57ae74 --- /dev/null +++ b/src/boost/libs/python/test/raw_pyobject_fail2.cpp @@ -0,0 +1,13 @@ +// Copyright David Abrahams 2002. +// 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) +#include <boost/python/converter/arg_to_python.hpp> + +struct X : PyObject {}; + +int main() +{ + boost::python::converter::arg_to_python<X*> x(0); + return 0; +} diff --git a/src/boost/libs/python/test/register_ptr.cpp b/src/boost/libs/python/test/register_ptr.cpp new file mode 100644 index 000000000..6cd4d7856 --- /dev/null +++ b/src/boost/libs/python/test/register_ptr.cpp @@ -0,0 +1,55 @@ +// Copyright David Abrahams 2004. 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) + +#include <boost/python.hpp> +#include <boost/shared_ptr.hpp> + +using namespace boost; +using namespace python; + +struct A +{ + virtual int f() { return 0; } +}; + +shared_ptr<A> New() { return shared_ptr<A>( new A() ); } + +int Call( const shared_ptr<A> & a ) +{ + return a->f(); +} + +int Fail( shared_ptr<A> & a ) +{ + return a->f(); +} + +struct A_Wrapper: A +{ + A_Wrapper(PyObject* self_): self(self_) {} + A_Wrapper(PyObject* self_, const A& a): self(self_), A(a) {} + + int f() + { + return call_method<int>(self, "f"); + } + + int default_f() + { + return A::f(); + } + + PyObject* self; +}; + +BOOST_PYTHON_MODULE(register_ptr) +{ + class_<A, A_Wrapper>("A") + .def("f", &A::f, &A_Wrapper::default_f) + ; + register_ptr_to_python< shared_ptr<A> >(); + def("New", &New); + def("Call", &Call); + def("Fail", &Fail); +} diff --git a/src/boost/libs/python/test/register_ptr_test.py b/src/boost/libs/python/test/register_ptr_test.py new file mode 100644 index 000000000..674e5572f --- /dev/null +++ b/src/boost/libs/python/test/register_ptr_test.py @@ -0,0 +1,25 @@ +# Copyright David Abrahams 2004. 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) +import unittest +from register_ptr import * + +class RegisterPtrTest(unittest.TestCase): + + def testIt(self): + + class B(A): + def f(self): + return 10 + + a = New() # this must work + b = B() + self.assertEqual(Call(a), 0) + self.assertEqual(Call(b), 10) + def fails(): + Fail(A()) + self.assertRaises(TypeError, fails) + self.assertEqual(Fail(a), 0) # ok, since a is held by shared_ptr + +if __name__ == '__main__': + unittest.main() diff --git a/src/boost/libs/python/test/result.cpp b/src/boost/libs/python/test/result.cpp new file mode 100644 index 000000000..d5f43cc3d --- /dev/null +++ b/src/boost/libs/python/test/result.cpp @@ -0,0 +1,111 @@ +// Copyright David Abrahams 2002. +// 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) +#include <boost/python/detail/result.hpp> +#include <boost/type.hpp> +#include <functional> + +using boost::python::detail::result; +using boost::type; + +void expect_int(type<int>*) {} +void expect_string(type<char*>*) {} + +struct X {}; + +int main() +{ + // Test the usage which works for functions, member functions, and data members + expect_int( + result((int(*)())0) + ); + + expect_int( + result((int(*)(char))0) + ); + + expect_int( + result((int(X::*)())0) + ); + + expect_int( + result((int(X::*)(char))0) + ); + + expect_int( + result((int(X::*))0) + ); + + expect_string( + result((char*(*)())0) + ); + + expect_string( + result((char*(*)(char))0) + ); + + expect_string( + result((char*(X::*)())0) + ); + + expect_string( + result((char*(X::*)(char))0) + ); + + expect_string( + result((char*(X::*))0) + ); + + // Show that we can use the general version that works for + // AdaptableFunctions + expect_int( + result((int(*)())0,0) + ); + + expect_int( + result((int(*)(char))0,0) + ); + + expect_int( + result((int(X::*)())0,0) + ); + + expect_int( + result((int(X::*)(char))0,0) + ); + + expect_int( + result((int(X::*))0,0) + ); + + expect_int( + result(std::plus<int>(),0) + ); + + expect_string( + result((char*(*)())0,0) + ); + + expect_string( + result((char*(*)(char))0,0) + ); + + expect_string( + result((char*(X::*)())0,0) + ); + + expect_string( + result((char*(X::*)(char))0,0) + ); + + expect_string( + result((char*(X::*))0,0) + ); + + expect_string( + result(std::plus<char*>(),0) + ); + + return 0; +} diff --git a/src/boost/libs/python/test/return_arg.cpp b/src/boost/libs/python/test/return_arg.cpp new file mode 100644 index 000000000..d8d3c1ddb --- /dev/null +++ b/src/boost/libs/python/test/return_arg.cpp @@ -0,0 +1,67 @@ +// Copyright David Abrahams and Nikolay Mladenov 2003. +// 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) + +#include <boost/python/module.hpp> +#include <boost/python/class.hpp> +#include <boost/python/def.hpp> +#include <boost/python/return_arg.hpp> + +struct Widget +{ + Widget() + : sensitive_(true) + {} + + bool get_sensitive() const + { + return sensitive_; + } + + void set_sensitive(bool s) + { + this->sensitive_ = s; + } + + private: + bool sensitive_; +}; + +struct Label : Widget +{ + Label() {} + + std::string get_label() const + { + return label_; + } + + void set_label(const std::string &l) + { + label_ = l; + } + + private: + std::string label_; +}; + +void return_arg_f(boost::python::object) {} + +using namespace boost::python; +BOOST_PYTHON_MODULE(return_arg_ext) +{ + class_<Widget>("Widget") + .def("sensitive", &Widget::get_sensitive) + .def("sensitive", &Widget::set_sensitive, return_self<>()) + ; + + class_<Label, bases<Widget> >("Label") + .def("label", &Label::get_label)//,return_arg<0>()) //error(s) + .def("label", &Label::set_label, return_self<>()) + ; + + def("return_arg", return_arg_f, return_arg<1>()); +} + +#include "module_tail.cpp" diff --git a/src/boost/libs/python/test/return_arg.py b/src/boost/libs/python/test/return_arg.py new file mode 100644 index 000000000..e66a0b8d9 --- /dev/null +++ b/src/boost/libs/python/test/return_arg.py @@ -0,0 +1,27 @@ +# Copyright David Abrahams 2004. 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) +''' +>>> from return_arg_ext import * +>>> l1=Label() +>>> assert l1 is l1.label("bar") +>>> assert l1 is l1.label("bar").sensitive(0) +>>> assert l1.label("foo").sensitive(0) is l1.sensitive(1).label("bar") +>>> assert return_arg is return_arg(return_arg) + +''' + +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/select_arg_to_python_test.cpp b/src/boost/libs/python/test/select_arg_to_python_test.cpp new file mode 100644 index 000000000..c5faace36 --- /dev/null +++ b/src/boost/libs/python/test/select_arg_to_python_test.cpp @@ -0,0 +1,70 @@ +// Copyright David Abrahams 2004. 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) +#include <boost/python/converter/arg_to_python.hpp> +#include <boost/python/type_id.hpp> +#include <boost/python/handle.hpp> +#include <boost/python/object.hpp> +#include <iostream> + +// gcc 2.95.x and MIPSpro 7.3.1.3 linker seem to demand this definition +#if ((defined(__GNUC__) && __GNUC__ < 3)) \ + || (defined(__sgi) && defined(__EDG_VERSION__) && (__EDG_VERSION__ == 238)) +namespace boost { namespace python { +BOOST_PYTHON_DECL bool handle_exception_impl(function0<void>) +{ + return true; +} +}} +#endif + +int result; + +#define ASSERT_SAME(T1,T2) assert_same< T1,T2 >() + +template <class T, class U> +void assert_same(U* = 0, T* = 0) +{ + BOOST_STATIC_ASSERT((boost::is_same<T,U>::value)); + +} + + +int main() +{ + using namespace boost::python::converter::detail; + using namespace boost::python::converter; + using namespace boost::python; + using namespace boost; + + + ASSERT_SAME( + select_arg_to_python<int>::type, value_arg_to_python<int> + ); + + ASSERT_SAME( + select_arg_to_python<reference_wrapper<int> >::type, reference_arg_to_python<int> + ); + + ASSERT_SAME( + select_arg_to_python<pointer_wrapper<int> >::type, pointer_shallow_arg_to_python<int> + ); + + ASSERT_SAME( + select_arg_to_python<int*>::type, pointer_deep_arg_to_python<int*> + ); + + ASSERT_SAME( + select_arg_to_python<handle<> >::type, object_manager_arg_to_python<handle<> > + ); + + ASSERT_SAME( + select_arg_to_python<object>::type, object_manager_arg_to_python<object> + ); + + ASSERT_SAME( + select_arg_to_python<char[20]>::type, arg_to_python<char const*> + ); + + return result; +} diff --git a/src/boost/libs/python/test/select_from_python_test.cpp b/src/boost/libs/python/test/select_from_python_test.cpp new file mode 100644 index 000000000..bb60962a3 --- /dev/null +++ b/src/boost/libs/python/test/select_from_python_test.cpp @@ -0,0 +1,161 @@ +// Copyright David Abrahams 2004. 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) +#include <boost/python/converter/arg_from_python.hpp> +#include <boost/python/type_id.hpp> +#include <iostream> + +// gcc 2.95.x, MIPSpro 7.3.1.3 and IBM XL for Linux linker seem to demand this definition +#if (defined(__GNUC__) && (__GNUC__ < 3)) \ + || (defined(__sgi) && defined(__EDG_VERSION__) && (__EDG_VERSION__ == 238)) \ + || (defined(__IBMCPP__) && defined(__linux__)) +namespace boost { namespace python { +BOOST_PYTHON_DECL bool handle_exception_impl(function0<void>) +{ + return true; +} +}} +#endif + +int result; + +#define ASSERT_SAME(T1,T2) \ + if (!is_same< T1, T2 >::value) { \ + std::cout << "*********************\n"; \ + std::cout << python::type_id< T1 >() << " != " << python::type_id< T2 >() << "\n"; \ + std::cout << "*********************\n"; \ + result = 1; \ + } + +int main() +{ + using namespace boost::python::converter; + using namespace boost; + + + ASSERT_SAME( + select_arg_from_python<int>::type, arg_rvalue_from_python<int> + ); + + ASSERT_SAME( + select_arg_from_python<int const>::type, arg_rvalue_from_python<int const> + ); + + ASSERT_SAME( + select_arg_from_python<int volatile>::type, arg_rvalue_from_python<int volatile> + ); + + ASSERT_SAME( + select_arg_from_python<int const volatile>::type, arg_rvalue_from_python<int const volatile> + ); + + + + ASSERT_SAME( + select_arg_from_python<int*>::type, pointer_arg_from_python<int*> + ); + + ASSERT_SAME( + select_arg_from_python<int const*>::type, pointer_arg_from_python<int const*> + ); + + ASSERT_SAME( + select_arg_from_python<int volatile*>::type, pointer_arg_from_python<int volatile*> + ); + + ASSERT_SAME( + select_arg_from_python<int const volatile*>::type, pointer_arg_from_python<int const volatile*> + ); + + + + + ASSERT_SAME( + select_arg_from_python<int&>::type, reference_arg_from_python<int&> + ); + + ASSERT_SAME( + select_arg_from_python<int const&>::type, arg_rvalue_from_python<int const&> + ); + + ASSERT_SAME( + select_arg_from_python<int volatile&>::type, reference_arg_from_python<int volatile&> + ); + + ASSERT_SAME( + select_arg_from_python<int const volatile&>::type, reference_arg_from_python<int const volatile&> + ); + + + + ASSERT_SAME( + select_arg_from_python<int*&>::type, reference_arg_from_python<int*&> + ); + + ASSERT_SAME( + select_arg_from_python<int const*&>::type, reference_arg_from_python<int const*&> + ); + + ASSERT_SAME( + select_arg_from_python<int volatile*&>::type, reference_arg_from_python<int volatile*&> + ); + + ASSERT_SAME( + select_arg_from_python<int const volatile*&>::type, reference_arg_from_python<int const volatile*&> + ); + + + + ASSERT_SAME( + select_arg_from_python<int* const&>::type, pointer_cref_arg_from_python<int*const&> + ); + + ASSERT_SAME( + select_arg_from_python<int const* const&>::type, pointer_cref_arg_from_python<int const*const&> + ); + + ASSERT_SAME( + select_arg_from_python<int volatile* const&>::type, pointer_cref_arg_from_python<int volatile*const&> + ); + + ASSERT_SAME( + select_arg_from_python<int const volatile* const&>::type, pointer_cref_arg_from_python<int const volatile*const&> + ); + + + + ASSERT_SAME( + select_arg_from_python<int*volatile&>::type, reference_arg_from_python<int*volatile&> + ); + + ASSERT_SAME( + select_arg_from_python<int const*volatile&>::type, reference_arg_from_python<int const*volatile&> + ); + + ASSERT_SAME( + select_arg_from_python<int volatile*volatile&>::type, reference_arg_from_python<int volatile*volatile&> + ); + + ASSERT_SAME( + select_arg_from_python<int const volatile*volatile&>::type, reference_arg_from_python<int const volatile*volatile&> + ); + + + + ASSERT_SAME( + select_arg_from_python<int*const volatile&>::type, reference_arg_from_python<int*const volatile&> + ); + + ASSERT_SAME( + select_arg_from_python<int const*const volatile&>::type, reference_arg_from_python<int const*const volatile&> + ); + + ASSERT_SAME( + select_arg_from_python<int volatile*const volatile&>::type, reference_arg_from_python<int volatile*const volatile&> + ); + + ASSERT_SAME( + select_arg_from_python<int const volatile*const volatile&>::type, reference_arg_from_python<int const volatile*const volatile&> + ); + return result; +} diff --git a/src/boost/libs/python/test/select_holder.cpp b/src/boost/libs/python/test/select_holder.cpp new file mode 100644 index 000000000..8650bd06a --- /dev/null +++ b/src/boost/libs/python/test/select_holder.cpp @@ -0,0 +1,76 @@ +// Copyright David Abrahams 2002. +// 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) +#include <boost/python/object/class_metadata.hpp> +#include <boost/python/has_back_reference.hpp> +#include <boost/python/detail/not_specified.hpp> +#include <boost/static_assert.hpp> +#include <boost/python/detail/type_traits.hpp> +#include <boost/function/function0.hpp> +#include <boost/mpl/bool.hpp> +#include <memory> + +struct BR {}; + +struct Base {}; +struct Derived : Base {}; + +namespace boost { namespace python +{ + // specialization + template <> + struct has_back_reference<BR> + : mpl::true_ + { + }; +}} // namespace boost::python + +template <class T, class U> +void assert_same(U* = 0, T* = 0) +{ + BOOST_STATIC_ASSERT((boost::python::detail::is_same<T,U>::value)); + +} + +template <class T, class Held, class Holder> +void assert_holder(T* = 0, Held* = 0, Holder* = 0) +{ + using namespace boost::python::detail; + using namespace boost::python::objects; + + typedef typename class_metadata< + T,Held,not_specified,not_specified + >::holder h; + + assert_same<Holder>( + (h*)0 + ); +} + +int test_main(int, char * []) +{ + using namespace boost::python::detail; + using namespace boost::python::objects; + + assert_holder<Base,not_specified,value_holder<Base> >(); + + assert_holder<BR,not_specified,value_holder_back_reference<BR,BR> >(); + assert_holder<Base,Base,value_holder_back_reference<Base,Base> >(); + assert_holder<BR,BR,value_holder_back_reference<BR,BR> >(); + + assert_holder<Base,Derived + ,value_holder_back_reference<Base,Derived> >(); + + assert_holder<Base,std::auto_ptr<Base> + ,pointer_holder<std::auto_ptr<Base>,Base> >(); + + assert_holder<Base,std::auto_ptr<Derived> + ,pointer_holder_back_reference<std::auto_ptr<Derived>,Base> >(); + + assert_holder<BR,std::auto_ptr<BR> + ,pointer_holder_back_reference<std::auto_ptr<BR>,BR> > (); + + return 0; +} + diff --git a/src/boost/libs/python/test/shared_ptr.cpp b/src/boost/libs/python/test/shared_ptr.cpp new file mode 100644 index 000000000..f72e6f029 --- /dev/null +++ b/src/boost/libs/python/test/shared_ptr.cpp @@ -0,0 +1,19 @@ +// Copyright David Abrahams 2002. +// Copyright Stefan Seefeld 2016. +// 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) + +#include <boost/python/module.hpp> +#include <boost/python/class.hpp> +#include <boost/python/call_method.hpp> +#include <boost/python/extract.hpp> +#include <boost/python/def.hpp> +#include <memory> + +using std::shared_ptr; +#define MODULE shared_ptr_ext + +#include "shared_ptr.hpp" +#include "module_tail.cpp" + diff --git a/src/boost/libs/python/test/shared_ptr.hpp b/src/boost/libs/python/test/shared_ptr.hpp new file mode 100644 index 000000000..9f9a4b69e --- /dev/null +++ b/src/boost/libs/python/test/shared_ptr.hpp @@ -0,0 +1,206 @@ +// Copyright David Abrahams 2002. +// Copyright Stefan Seefeld 2016. +// 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) + +#include "test_class.hpp" + +using namespace boost::python; + +typedef test_class<> X; +typedef test_class<1> Y; + +template <class T> +struct functions +{ + static int look(shared_ptr<T> const& x) + { + return (x.get()) ? x->value() : -1; + } + + static void store(shared_ptr<T> x) + { + storage = x; + } + + static void release_store() + { + store(shared_ptr<T>()); + } + + static void modify(shared_ptr<T>& x) + { + x.reset(); + } + + static shared_ptr<T> get() { return storage; } + static shared_ptr<T> &get1() { return storage; } + + static int look_store() + { + return look(get()); + } + + template <class C> + static void expose(C const& c) + { + def("look", &look); + def("store", &store); + def("modify", &modify); + def("identity", &identity); + def("null", &null); + + const_cast<C&>(c) + .def("look", &look) + .staticmethod("look") + .def("store", &store) + .staticmethod("store") + .def("modify", &modify) + .staticmethod("modify") + .def("look_store", &look_store) + .staticmethod("look_store") + .def("identity", &identity) + .staticmethod("identity") + .def("null", &null) + .staticmethod("null") + .def("get1", &get1, return_internal_reference<>()) + .staticmethod("get1") + .def("get", &get) + .staticmethod("get") + .def("count", &T::count) + .staticmethod("count") + .def("release", &release_store) + .staticmethod("release") + ; + } + + static shared_ptr<T> identity(shared_ptr<T> x) { return x; } + static shared_ptr<T> null(T const&) { return shared_ptr<T>(); } + + + static shared_ptr<T> storage; +}; + +template <class T> shared_ptr<T> functions<T>::storage; + +struct Z : test_class<2> +{ + Z(int x) : test_class<2>(x) {} + virtual int v() { return this->value(); } +}; + +struct ZWrap : Z +{ + ZWrap(PyObject* self, int x) + : Z(x), m_self(self) {} + + + virtual int v() { return call_method<int>(m_self, "v"); } + int default_v() { return Z::v(); } + + + PyObject* m_self; +}; + +struct YY : Y +{ + YY(int n) : Y(n) {} +}; + +struct YYY : Y +{ + YYY(int n) : Y(n) {} +}; + +shared_ptr<Y> factory(int n) +{ + return shared_ptr<Y>(n < 42 ? new Y(n) : new YY(n)); +} + +// regressions from Nicodemus + struct A + { + virtual ~A() {}; // silence compiler warnings + virtual int f() = 0; + static int call_f(shared_ptr<A>& a) { return a->f(); } + }; + + struct B: A + { + int f() { return 1; } + }; + + shared_ptr<A> New(bool make) + { + return shared_ptr<A>( make ? new B() : 0 ); + } + + struct A_Wrapper: A + { + A_Wrapper(PyObject* self_): + A(), self(self_) {} + + int f() { + return call_method< int >(self, "f"); + } + + PyObject* self; + }; + +// ------ + +// from Neal Becker + +struct Test { + shared_ptr<X> x; +}; +// ------ + + +BOOST_PYTHON_MODULE(MODULE) +{ + class_<A, shared_ptr<A_Wrapper>, boost::noncopyable>("A") + .def("call_f", &A::call_f) + .staticmethod("call_f") + ; + + // This is the ugliness required to register a to-python converter + // for shared_ptr<A>. + objects::class_value_wrapper< + shared_ptr<A> + , objects::make_ptr_instance<A, objects::pointer_holder<shared_ptr<A>,A> > + >(); + + def("New", &New); + + def("factory", factory); + + functions<X>::expose( + class_<X, boost::noncopyable>("X", init<int>()) + .def("value", &X::value) + ); + + functions<Y>::expose( + class_<Y, shared_ptr<Y> >("Y", init<int>()) + .def("value", &Y::value) + ); + + class_<YY, bases<Y>, boost::noncopyable>("YY", init<int>()) + ; + + class_<YYY, shared_ptr<YYY>, bases<Y> >("YYY", init<int>()) + ; + + functions<Z>::expose( + class_<Z, ZWrap>("Z", init<int>()) + .def("value", &Z::value) + .def("v", &Z::v, &ZWrap::default_v) + ); + +// from Neal Becker + class_<Test> ("Test") + .def_readonly ("x", &Test::x, "x") + ; +// ------ +} diff --git a/src/boost/libs/python/test/shared_ptr.py b/src/boost/libs/python/test/shared_ptr.py new file mode 100644 index 000000000..d250ae7ec --- /dev/null +++ b/src/boost/libs/python/test/shared_ptr.py @@ -0,0 +1,130 @@ +# Copyright David Abrahams 2004. 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) +''' +>>> from shared_ptr_ext import * + + Test that shared_ptr<Derived> can be converted to shared_ptr<Base> + +>>> Y.store(YYY(42)) + +>>> x = X(17) +>>> null_x = null(x) +>>> null_x # should be None +>>> identity(null_x) # should also be None + +>>> a = New(1) +>>> A.call_f(a) +1 +>>> New(0) + +>>> type(factory(3)) +<class 'shared_ptr_ext.Y'> +>>> type(factory(42)) +<class 'shared_ptr_ext.YY'> + +>>> class P(Z): +... def v(self): +... return -Z.v(self); +... def __del__(self): +... print('bye') +... +>>> p = P(12) +>>> p.value() +12 +>>> p.v() +-12 +>>> look(p) +12 +>>> try: modify(p) +... except TypeError: pass +... else: 'print(expected a TypeError)' +>>> look(None) +-1 +>>> store(p) +>>> del p +>>> Z.get().v() +-12 +>>> Z.count() +1 +>>> Z.look_store() +12 +>>> Z.release() +bye +>>> Z.count() +0 + +>>> z = Z(13) +>>> z.value() +13 +>>> z.v() +13 +>>> try: modify(z) +... except TypeError: pass +... else: 'print(expected a TypeError)' + +>>> Z.get() # should be None +>>> store(z) +>>> assert Z.get() is z # show that deleter introspection works +>>> del z +>>> Z.get().value() +13 +>>> Z.count() +1 +>>> Z.look_store() +13 +>>> Z.release() +>>> Z.count() +0 + +>>> x = X(17) +>>> x.value() +17 +>>> look(x) +17 +>>> try: modify(x) +... except TypeError: pass +... else: 'print(expected a TypeError)' +>>> look(None) +-1 +>>> store(x) +>>> del x +>>> X.count() +1 +>>> X.look_store() +17 +>>> X.release() +>>> X.count() +0 + + +>>> y = Y(19) +>>> y.value() +19 +>>> modify(y) +>>> look(y) +-1 +>>> store(Y(23)) +>>> Y.count() +1 +>>> Y.look_store() +23 +>>> Y.release() +>>> Y.count() +0 +''' + +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/simple_type.hpp b/src/boost/libs/python/test/simple_type.hpp new file mode 100644 index 000000000..d1314ff97 --- /dev/null +++ b/src/boost/libs/python/test/simple_type.hpp @@ -0,0 +1,13 @@ +// Copyright David Abrahams 2001. +// 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) +#ifndef SIMPLE_TYPE_DWA2001128_HPP +# define SIMPLE_TYPE_DWA2001128_HPP + +struct simple +{ + char* s; +}; + +#endif // SIMPLE_TYPE_DWA2001128_HPP diff --git a/src/boost/libs/python/test/slice.cpp b/src/boost/libs/python/test/slice.cpp new file mode 100644 index 000000000..b1b965fa1 --- /dev/null +++ b/src/boost/libs/python/test/slice.cpp @@ -0,0 +1,98 @@ +#include <boost/python.hpp> +#include <boost/python/slice.hpp> +#include <boost/python/str.hpp> +#include <vector> + +// Copyright (c) 2004 Jonathan Brandmeyer +// Use, modification and distribution are subject to 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) + +using namespace boost::python; + +#if BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x580)) || BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500)) +# define make_tuple boost::python::make_tuple +#endif + +// These checks are only valid under Python 2.3 +// (rich slicing wasn't supported for builtins under Python 2.2) +bool check_string_rich_slice() +{ + object s("hello, world"); + + // default slice + if (s[slice()] != "hello, world") + return false; + + // simple reverse + if (s[slice(_,_,-1)] != "dlrow ,olleh") + return false; + + // reverse with mixed-sign offsets + if (s[slice(-6,1,-1)] != " ,oll") + return false; + + // all of the object.cpp check_string_slice() checks should work + // with the form that omits the step argument. + if (s[slice(_,-3)] != "hello, wo") + return false; + if (s[slice(-3,_)] != "rld") + return false; + if (", " != s[slice(5,7)]) + return false; + + return s[slice(2,-1)][slice(1,-1)] == "lo, wor"; +} + +// Tried to get more info into the error message (actual array +// contents) but Numeric complains that treating an array as a boolean +// value doesn't make any sense. +#define ASSERT_EQUAL( e1, e2 ) \ + if (!all((e1) == (e2))) \ + return "assertion failed: " #e1 " == " #e2 "\nLHS:\n%s\nRHS:\n%s" % make_tuple(e1,e2); \ +else + +// Verify functions accepting a slice argument can be called +bool accept_slice( slice) { return true; } + +#if BOOST_WORKAROUND( BOOST_MSVC, BOOST_TESTED_AT(1400)) \ + || BOOST_WORKAROUND( BOOST_INTEL_WIN, == 710) +int check_slice_get_indices(slice index); +#endif +int check_slice_get_indices( +#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) + const +#endif + slice index) +{ + // A vector of integers from [-5, 5]. + std::vector<int> coll(11); + typedef std::vector<int>::iterator coll_iterator; + + for (coll_iterator i = coll.begin(); i != coll.end(); ++i) { + *i = i - coll.begin() - 5; + } + + slice::range<std::vector<int>::iterator> bounds; + try { + bounds = index.get_indices(coll.begin(), coll.end()); + } + catch (std::invalid_argument) { + return 0; + } + int sum = 0; + while (bounds.start != bounds.stop) { + sum += *bounds.start; + std::advance( bounds.start, bounds.step); + } + sum += *bounds.start; + return sum; +} + + +BOOST_PYTHON_MODULE(slice_ext) +{ + def( "accept_slice", accept_slice); + def( "check_string_rich_slice", check_string_rich_slice); + def( "check_slice_get_indices", check_slice_get_indices); +} diff --git a/src/boost/libs/python/test/slice.py b/src/boost/libs/python/test/slice.py new file mode 100644 index 000000000..c58bbc029 --- /dev/null +++ b/src/boost/libs/python/test/slice.py @@ -0,0 +1,54 @@ +# Copyright David Abrahams 2004. 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) +""" +>>> from slice_ext import * +>>> accept_slice(slice(1, None, (1,2))) +1 +>>> try: +... accept_slice(list((1,2))) +... print("test failed") +... except: +... print("test passed") +... +test passed +>>> import sys +>>> if sys.version_info[0] == 2 and sys.version_info[1] >= 3: +... check_string_rich_slice() +... elif sys.version_info[0] > 2: +... check_string_rich_slice() +... else: +... print(1) +... +1 +>>> check_slice_get_indices( slice(None)) +0 +>>> check_slice_get_indices( slice(2,-2)) +0 +>>> check_slice_get_indices( slice(2, None, 2)) +5 +>>> check_slice_get_indices( slice(2, None, -1)) +-12 +>>> check_slice_get_indices( slice( 20, None)) +0 +>>> check_slice_get_indices( slice( -2, -5, -2)) +6 +""" + +# Performs an affirmative and negative argument resolution check. +# checks the operation of extended slicing in new strings (Python 2.3 only). + +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/staticmethod.cpp b/src/boost/libs/python/test/staticmethod.cpp new file mode 100644 index 000000000..dcd75ca82 --- /dev/null +++ b/src/boost/libs/python/test/staticmethod.cpp @@ -0,0 +1,48 @@ +// Copyright David Abrahams 2002. +// 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) + +#include <boost/python/class.hpp> +#include <boost/python/module.hpp> +#include <boost/python/def.hpp> +#include <boost/python/call_method.hpp> +#include <boost/ref.hpp> +#include <boost/utility.hpp> +#define BOOST_ENABLE_ASSERT_HANDLER +#include <boost/assert.hpp> + +using namespace boost::python; + +struct X +{ + explicit X(int x) : x(x), magic(7654321) { ++counter; } + X(X const& rhs) : x(rhs.x), magic(7654321) { ++counter; } + virtual ~X() { BOOST_ASSERT(magic == 7654321); magic = 6666666; x = 9999; --counter; } + + void set(int _x) { BOOST_ASSERT(magic == 7654321); this->x = _x; } + int value() const { BOOST_ASSERT(magic == 7654321); return x; } + static int count() { return counter; } + private: + void operator=(X const&); + private: + int x; + long magic; + static int counter; +}; +int X::counter; +int getXmagic(){return 7654321;} + +BOOST_PYTHON_MODULE(staticmethod_ext) +{ + class_<X>("X", init<int>()) + .def("value", &X::value) + .def("set", &X::set) + .def("count", &X::count) + .staticmethod("count") + .def("magic", &getXmagic) + .staticmethod("magic") + ; +} + +#include "module_tail.cpp" diff --git a/src/boost/libs/python/test/staticmethod.py b/src/boost/libs/python/test/staticmethod.py new file mode 100644 index 000000000..3dd355b13 --- /dev/null +++ b/src/boost/libs/python/test/staticmethod.py @@ -0,0 +1,57 @@ +# Copyright David Abrahams 2004. 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) +''' +>>> from staticmethod_ext import * + +>>> class X1(X): +... pass + + +>>> x = X(16) +>>> x1 = X1(17) + + + +>>> x1.count() +2 + +>>> x.count() +2 + +>>> X1.count() +2 + +>>> X.count() +2 + + +>>> x1.magic() +7654321 + +>>> x.magic() +7654321 + +>>> X1.magic() +7654321 + +>>> X.magic() +7654321 + + +''' + +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/stl_iterator.cpp b/src/boost/libs/python/test/stl_iterator.cpp new file mode 100644 index 000000000..409e0da84 --- /dev/null +++ b/src/boost/libs/python/test/stl_iterator.cpp @@ -0,0 +1,33 @@ +// Copyright Eric Niebler 2005. +// 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) +#include <boost/python/module.hpp> +#include <boost/python/def.hpp> +#include <boost/python/iterator.hpp> +#include <boost/python/stl_iterator.hpp> +#include <list> + +using namespace boost::python; + +typedef std::list<int> list_int; + +void assign(list_int& x, object const& y) +{ + stl_input_iterator<int> begin(y), end; + x.clear(); + for( ; begin != end; ++begin) + x.push_back(*begin); +} + +BOOST_PYTHON_MODULE(stl_iterator_ext) +{ + using boost::python::iterator; // gcc 2.96 bug workaround + + class_<list_int>("list_int") + .def("assign", assign) + .def("__iter__", iterator<list_int>()) + ; +} + +#include "module_tail.cpp" diff --git a/src/boost/libs/python/test/stl_iterator.py b/src/boost/libs/python/test/stl_iterator.py new file mode 100644 index 000000000..4743ed632 --- /dev/null +++ b/src/boost/libs/python/test/stl_iterator.py @@ -0,0 +1,39 @@ +# Copyright Eric Niebler 2005. 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) +''' +>>> from stl_iterator_ext import * +>>> x = list_int() +>>> x.assign(iter([1,2,3,4,5])) +>>> for y in x: +... print(y) +1 +2 +3 +4 +5 +>>> def generator(): +... yield 1 +... yield 2 +... raise RuntimeError("oops") +>>> try: +... x.assign(iter(generator())) +... print("NOT OK") +... except RuntimeError: +... print("OK") +OK +''' +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/str.cpp b/src/boost/libs/python/test/str.cpp new file mode 100644 index 000000000..0505b250a --- /dev/null +++ b/src/boost/libs/python/test/str.cpp @@ -0,0 +1,84 @@ +// Copyright David Abrahams 2004. 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) +#include <boost/python/module.hpp> +#include <boost/assert.hpp> + +#include <boost/python/def.hpp> +#include <boost/python/class.hpp> +#include <boost/python/str.hpp> +#define BOOST_ENABLE_ASSERT_HANDLER +#include <boost/assert.hpp> + +using namespace boost::python; + +object convert_to_string(object data) +{ + return str(data); +} + +void work_with_string(object print) +{ + str data("this is a demo string"); + print(data.split(" ")); + print(data.split(" ",3)); + print(str("<->").join(data.split(" "))); + print(data.capitalize()); + print('[' + data.center(30) + ']'); + print(data.count("t")); +#if PY_VERSION_HEX < 0x03000000 + print(data.encode("utf-8")); + print(data.decode("utf-8")); +#else + print(data.encode("utf-8").attr("decode")("utf-8")); + print(data.encode("utf-8").attr("decode")("utf-8")); +#endif + + BOOST_ASSERT(!data.endswith("xx")); + BOOST_ASSERT(!data.startswith("test")); + + print(data.splitlines()); + print(data.strip()); + print(data.swapcase()); + print(data.title()); + + print("find"); + print(data.find("demo")); + print(data.find("demo"),3,5); + print(data.find(std::string("demo"))); + print(data.find(std::string("demo"),9)); + + print("expandtabs"); + str tabstr("\t\ttab\tdemo\t!"); + print(tabstr.expandtabs()); + print(tabstr.expandtabs(4)); + print(tabstr.expandtabs(7L)); + + print("operators"); + print( str("part1") + str("part2") ); +// print( str("a test string").slice(3,_) ); +// print( str("another test")[5] ); + + print(data.replace("demo",std::string("blabla"))); + print(data.rfind("i",5)); + print(data.rindex("i",5)); + + BOOST_ASSERT(!data.startswith("asdf")); + BOOST_ASSERT(!data.endswith("asdf")); + + print(data.translate(str('a')*256)); + + + bool tmp = data.isalnum() || data.isalpha() || data.isdigit() || data.islower() || + data.isspace() || data.istitle() || data.isupper(); + (void)tmp; // ignored. +} + + +BOOST_PYTHON_MODULE(str_ext) +{ + def("convert_to_string",convert_to_string); + def("work_with_string",work_with_string); +} + +#include "module_tail.cpp" diff --git a/src/boost/libs/python/test/str.py b/src/boost/libs/python/test/str.py new file mode 100644 index 000000000..4eba0e876 --- /dev/null +++ b/src/boost/libs/python/test/str.py @@ -0,0 +1,54 @@ +# Copyright David Abrahams 2004. 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) +from __future__ import print_function +""" +>>> from str_ext import * +>>> def printer(*args): +... for x in args: print(x, end='') +... print('') +... +>>> work_with_string(printer) #doctest: +NORMALIZE_WHITESPACE +['this', 'is', 'a', 'demo', 'string'] +['this', 'is', 'a', 'demo string'] +this<->is<->a<->demo<->string +This is a demo string +[ this is a demo string ] +2 +this is a demo string +this is a demo string +['this is a demo string'] +this is a demo string +THIS IS A DEMO STRING +This Is A Demo String +find +10 +10 3 5 +10 +10 +expandtabs + tab demo ! + tab demo ! + tab demo ! +operators +part1part2 +this is a blabla string +18 +18 +aaaaaaaaaaaaaaaaaaaaa +""" + +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/string_literal.cpp b/src/boost/libs/python/test/string_literal.cpp new file mode 100644 index 000000000..7a349d6c2 --- /dev/null +++ b/src/boost/libs/python/test/string_literal.cpp @@ -0,0 +1,42 @@ +// Copyright David Abrahams 2004. 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) +#include <boost/python/detail/string_literal.hpp> +//#include <stdio.h> + +#include <boost/detail/lightweight_test.hpp> +#include <boost/static_assert.hpp> + +using namespace boost::python::detail; + + +template <class T> +void expect_string_literal(T const&) +{ + BOOST_STATIC_ASSERT(is_string_literal<T const>::value); +} + +int main() +{ + expect_string_literal("hello"); + BOOST_STATIC_ASSERT(!is_string_literal<int*&>::value); + BOOST_STATIC_ASSERT(!is_string_literal<int* const&>::value); + BOOST_STATIC_ASSERT(!is_string_literal<int*volatile&>::value); + BOOST_STATIC_ASSERT(!is_string_literal<int*const volatile&>::value); + + BOOST_STATIC_ASSERT(!is_string_literal<char const*>::value); + BOOST_STATIC_ASSERT(!is_string_literal<char*>::value); + BOOST_STATIC_ASSERT(!is_string_literal<char*&>::value); + BOOST_STATIC_ASSERT(!is_string_literal<char* const&>::value); + BOOST_STATIC_ASSERT(!is_string_literal<char*volatile&>::value); + BOOST_STATIC_ASSERT(!is_string_literal<char*const volatile&>::value); + + BOOST_STATIC_ASSERT(!is_string_literal<char[20]>::value); + BOOST_STATIC_ASSERT(is_string_literal<char const[20]>::value); + BOOST_STATIC_ASSERT(is_string_literal<char const[3]>::value); + + BOOST_STATIC_ASSERT(!is_string_literal<int[20]>::value); + BOOST_STATIC_ASSERT(!is_string_literal<int const[20]>::value); + BOOST_STATIC_ASSERT(!is_string_literal<int const[3]>::value); + return boost::report_errors(); +} diff --git a/src/boost/libs/python/test/test_builtin_converters.py b/src/boost/libs/python/test/test_builtin_converters.py new file mode 100644 index 000000000..e612ed23d --- /dev/null +++ b/src/boost/libs/python/test/test_builtin_converters.py @@ -0,0 +1,312 @@ +# Copyright David Abrahams 2004. 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) +import sys +if (sys.version_info.major >= 3): + long = int +r""" +>>> from builtin_converters_ext import * + +# Provide values for integer converter tests +>>> def _signed_values(s): +... base = 2 ** (8 * s - 1) +... return [[-base, -1, 1, base - 1], [-base - 1, base]] +>>> def _unsigned_values(s): +... base = 2 ** (8 * s) +... return [[1, base - 1], [long(-1), -1, base]] + +# Wrappers to simplify tests +>>> def should_pass(method, values): +... result = map(method, values[0]) +... if result != values[0]: +... print("Got %s but expected %s" % (result, values[0])) +>>> def test_overflow(method, values): +... for v in values[1]: +... try: method(v) +... except OverflowError: pass +... else: print("OverflowError expected") + +# Synthesize idendity functions in case long long not supported +>>> if not 'rewrap_value_long_long' in dir(): +... def rewrap_value_long_long(x): return long(x) +... def rewrap_value_unsigned_long_long(x): return long(x) +... def rewrap_const_reference_long_long(x): return long(x) +... def rewrap_const_reference_unsigned_long_long(x): return long(x) +>>> if not 'long_long_size' in dir(): +... def long_long_size(): return long_size() + +>>> try: bool_exists = bool +... except: pass +... else: +... rewrap_value_bool(True) +... rewrap_value_bool(False) +True +False + +>>> rewrap_value_bool(None) +0 +>>> rewrap_value_bool(0) +0 +>>> rewrap_value_bool(33) +1 +>>> rewrap_value_char('x') +'x' + + Note that there's currently silent truncation of strings passed to + char arguments. + +>>> rewrap_value_char('xy') +'x' +>>> rewrap_value_signed_char(42) +42 +>>> rewrap_value_unsigned_char(42) +42 +>>> rewrap_value_int(42) +42 +>>> rewrap_value_unsigned_int(42) +42 +>>> rewrap_value_short(42) +42 +>>> rewrap_value_unsigned_short(42) +42 +>>> rewrap_value_long(42) +42 +>>> rewrap_value_unsigned_long(42) +42 + + test unsigned long values which don't fit in a signed long. + strip any 'L' characters in case the platform has > 32 bit longs + +>>> hex(rewrap_value_unsigned_long(long(0x80000001))).replace('L','') +'0x80000001' + +>>> rewrap_value_long_long(42) == 42 +True +>>> rewrap_value_unsigned_long_long(42) == 42 +True + + show that we have range checking. + +>>> should_pass(rewrap_value_signed_char, _signed_values(char_size())) +>>> should_pass(rewrap_value_short, _signed_values(short_size())) +>>> should_pass(rewrap_value_int, _signed_values(int_size())) +>>> should_pass(rewrap_value_long, _signed_values(long_size())) +>>> should_pass(rewrap_value_long_long, _signed_values(long_long_size())) + +>>> should_pass(rewrap_value_unsigned_char, _unsigned_values(char_size())) +>>> should_pass(rewrap_value_unsigned_short, _unsigned_values(short_size())) +>>> should_pass(rewrap_value_unsigned_int, _unsigned_values(int_size())) +>>> should_pass(rewrap_value_unsigned_long, _unsigned_values(long_size())) +>>> should_pass(rewrap_value_unsigned_long_long, +... _unsigned_values(long_long_size())) + +>>> test_overflow(rewrap_value_signed_char, _signed_values(char_size())) +>>> test_overflow(rewrap_value_short, _signed_values(short_size())) +>>> test_overflow(rewrap_value_int, _signed_values(int_size())) +>>> test_overflow(rewrap_value_long, _signed_values(long_size())) +>>> test_overflow(rewrap_value_long_long, _signed_values(long_long_size())) + +>>> test_overflow(rewrap_value_unsigned_char, _unsigned_values(char_size())) +>>> test_overflow(rewrap_value_unsigned_short, _unsigned_values(short_size())) +>>> test_overflow(rewrap_value_unsigned_int, _unsigned_values(int_size())) +>>> test_overflow(rewrap_value_unsigned_long, _unsigned_values(long_size())) + +# Exceptionally for PyLong_AsUnsignedLongLong(), a negative value raises +# TypeError on Python versions prior to 2.7 +>>> for v in _unsigned_values(long_long_size())[1]: +... try: rewrap_value_unsigned_long_long(v) +... except (OverflowError, TypeError): pass +... else: print("OverflowError or TypeError expected") + +>>> assert abs(rewrap_value_float(4.2) - 4.2) < .000001 +>>> rewrap_value_double(4.2) - 4.2 +0.0 +>>> rewrap_value_long_double(4.2) - 4.2 +0.0 + +>>> assert abs(rewrap_value_complex_float(4+.2j) - (4+.2j)) < .000001 +>>> assert abs(rewrap_value_complex_double(4+.2j) - (4+.2j)) < .000001 +>>> assert abs(rewrap_value_complex_long_double(4+.2j) - (4+.2j)) < .000001 + +>>> rewrap_value_cstring('hello, world') +'hello, world' +>>> rewrap_value_string('yo, wassup?') +'yo, wassup?' + +>>> print(rewrap_value_wstring(u'yo, wassup?')) +yo, wassup? + +>>> print(rewrap_value_wstring(u'\U0001f4a9')) +\U0001f4a9 + + test that overloading on unicode works: + +>>> print(rewrap_value_string(u'yo, wassup?')) +yo, wassup? + + wrap strings with embedded nulls: + +>>> rewrap_value_string('yo,\0wassup?') +'yo,\x00wassup?' + +>>> rewrap_value_handle(1) +1 +>>> x = 'hi' +>>> assert rewrap_value_handle(x) is x +>>> assert rewrap_value_object(x) is x + + Note that we can currently get a mutable pointer into an immutable + Python string: + +>>> rewrap_value_mutable_cstring('hello, world') +'hello, world' + +>>> rewrap_const_reference_bool(None) +0 +>>> rewrap_const_reference_bool(0) +0 + +>>> try: rewrap_const_reference_bool('yes') +... except TypeError: pass +... else: print('expected a TypeError exception') + +>>> rewrap_const_reference_char('x') +'x' + + Note that there's currently silent truncation of strings passed to + char arguments. + +>>> rewrap_const_reference_char('xy') +'x' +>>> rewrap_const_reference_signed_char(42) +42 +>>> rewrap_const_reference_unsigned_char(42) +42 +>>> rewrap_const_reference_int(42) +42 +>>> rewrap_const_reference_unsigned_int(42) +42 +>>> rewrap_const_reference_short(42) +42 +>>> rewrap_const_reference_unsigned_short(42) +42 +>>> rewrap_const_reference_long(42) +42 +>>> rewrap_const_reference_unsigned_long(42) +42 +>>> rewrap_const_reference_long_long(42) == 42 +True +>>> rewrap_const_reference_unsigned_long_long(42) == 42 +True + + +>>> assert abs(rewrap_const_reference_float(4.2) - 4.2) < .000001 +>>> rewrap_const_reference_double(4.2) - 4.2 +0.0 +>>> rewrap_const_reference_long_double(4.2) - 4.2 +0.0 + +>>> assert abs(rewrap_const_reference_complex_float(4+.2j) - (4+.2j)) < .000001 +>>> assert abs(rewrap_const_reference_complex_double(4+.2j) - (4+.2j)) < .000001 +>>> assert abs(rewrap_const_reference_complex_long_double(4+.2j) - (4+.2j)) < .000001 + +>>> rewrap_const_reference_cstring('hello, world') +'hello, world' +>>> rewrap_const_reference_string('yo, wassup?') +'yo, wassup?' + +>>> rewrap_const_reference_handle(1) +1 +>>> x = 'hi' +>>> assert rewrap_const_reference_handle(x) is x +>>> assert rewrap_const_reference_object(x) is x +>>> assert rewrap_reference_object(x) is x + + +Check that None <==> NULL + +>>> rewrap_const_reference_cstring(None) + +But None cannot be converted to a string object: + +>>> try: rewrap_const_reference_string(None) +... except TypeError: pass +... else: print('expected a TypeError exception') + +Now check implicit conversions between floating/integer types + +>>> rewrap_const_reference_float(42) +42.0 + +>>> rewrap_const_reference_float(long(42)) +42.0 + +>>> try: rewrap_const_reference_int(42.0) +... except TypeError: pass +... else: print('expected a TypeError exception') + +>>> rewrap_value_float(42) +42.0 + +>>> try: rewrap_value_int(42.0) +... except TypeError: pass +... else: print('expected a TypeError exception') + +Check that classic classes also work + +>>> class FortyTwo: +... def __int__(self): +... return 42 +... def __float__(self): +... return 42.0 +... def __complex__(self): +... return complex(4+.2j) +... def __str__(self): +... return '42' + +>>> try: rewrap_const_reference_float(FortyTwo()) +... except TypeError: pass +... else: print('expected a TypeError exception') + +>>> try: rewrap_value_int(FortyTwo()) +... except TypeError: pass +... else: print('expected a TypeError exception') + +>>> try: rewrap_const_reference_string(FortyTwo()) +... except TypeError: pass +... else: print('expected a TypeError exception') + +>>> try: rewrap_value_complex_double(FortyTwo()) +... except TypeError: pass +... else: print('expected a TypeError exception') + +# show that arbitrary handle<T> instantiations can be returned +>>> assert get_type(1) is type(1) + +>>> assert return_null_handle() is None +""" + +import sys +if (sys.version_info.major >= 3): + long = int + +def run(args = None): + import sys + import doctest + import builtin_converters_ext + + if 'rewrap_value_long_long' in dir(builtin_converters_ext): + print('LONG_LONG supported, testing...') + else: + print('LONG_LONG not supported, skipping those tests...') + + if args is not None: + sys.argv = args + return doctest.testmod(sys.modules.get(__name__)) + +if __name__ == '__main__': + print("running...") + import sys + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/test_class.hpp b/src/boost/libs/python/test/test_class.hpp new file mode 100644 index 000000000..5404fdba2 --- /dev/null +++ b/src/boost/libs/python/test/test_class.hpp @@ -0,0 +1,32 @@ +// Copyright David Abrahams 2002. +// 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) +#ifndef TEST_CLASS_DWA2002326_HPP +# define TEST_CLASS_DWA2002326_HPP +# include <boost/detail/lightweight_test.hpp> + +template <int n = 0> +struct test_class +{ + explicit test_class(int x) : x(x), magic(7654321 + n) { ++counter; } + test_class(test_class const& rhs) : x(rhs.x), magic(7654321 + n) { ++counter; } + virtual ~test_class() { BOOST_TEST(magic == 7654321 + n); magic = 6666666; x = 9999; --counter; } + + void set(int _x) { BOOST_TEST(magic == 7654321 + n); this->x = _x; } + int value() const { BOOST_TEST(magic == 7654321 + n); return x; } + operator int() const { return x; } + static int count() { return counter; } + + int x; + long magic; + static int counter; + + private: + void operator=(test_class const&); +}; + +template <int n> +int test_class<n>::counter; + +#endif // TEST_CLASS_DWA2002326_HPP diff --git a/src/boost/libs/python/test/test_cltree.py b/src/boost/libs/python/test/test_cltree.py new file mode 100644 index 000000000..2127b7cdb --- /dev/null +++ b/src/boost/libs/python/test/test_cltree.py @@ -0,0 +1,43 @@ +# Copyright David Abrahams 2004. 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) +#!/usr/bin/env python + +from cltree import basic,symbol,constant,variable + +b = basic() +c = constant() +s = symbol() +v = variable() + +assert isinstance(b,basic) +assert not isinstance(b,symbol) +assert not isinstance(b,constant) +assert not isinstance(b,variable) + +assert isinstance(c,basic) +assert isinstance(c,constant) +assert not isinstance(c,symbol) +assert not isinstance(c,variable) + +assert not isinstance(s,basic) +assert isinstance(s,symbol) +assert not isinstance(s,constant) +assert not isinstance(s,variable) + +assert isinstance(v,basic) +assert not isinstance(v,symbol) +assert not isinstance(v,constant) +assert isinstance(v,variable) + +print('b=',b) +assert repr(b)=='cltree.basic()' +print('s=',s) +assert repr(s)!='cltree.wrapped_symbol()' # because not isinstance(s,basic) +print('c=',c) +assert repr(c)=='cltree.constant()' +print('v=',v) +assert repr(v)=='cltree.wrapped_variable()' + + +print('ok') diff --git a/src/boost/libs/python/test/test_enum.py b/src/boost/libs/python/test/test_enum.py new file mode 100644 index 000000000..e4ad70bd5 --- /dev/null +++ b/src/boost/libs/python/test/test_enum.py @@ -0,0 +1,85 @@ +# Copyright David Abrahams 2004. 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) +''' +>>> from enum_ext import * + +>>> identity(color.red) # in case of duplicated enums it always take the last enum +enum_ext.color.blood + +>>> identity(color.green) +enum_ext.color.green + +>>> identity(color.blue) +enum_ext.color.blue + +>>> identity(color(1)) # in case of duplicated enums it always take the last enum +enum_ext.color.blood + +>>> identity(color(2)) +enum_ext.color.green + +>>> identity(color(3)) +enum_ext.color(3) + +>>> identity(color(4)) +enum_ext.color.blue + + --- check export to scope --- + +>>> identity(red) +enum_ext.color.blood + +>>> identity(green) +enum_ext.color.green + +>>> identity(blue) +enum_ext.color.blue + +>>> try: identity(1) +... except TypeError: pass +... else: print('expected a TypeError') + +>>> c = colorized() +>>> c.x +enum_ext.color.blood +>>> c.x = green +>>> c.x +enum_ext.color.green +>>> red == blood +True +>>> red == green +False +>>> hash(red) == hash(blood) +True +>>> hash(red) == hash(green) +False +''' + +# pickling of enums only works with Python 2.3 or higher +exercise_pickling = ''' +>>> import pickle +>>> p = pickle.dumps(color.green, pickle.HIGHEST_PROTOCOL) +>>> l = pickle.loads(p) +>>> identity(l) +enum_ext.color.green +''' + +def run(args = None): + import sys + import doctest + import pickle + + if args is not None: + sys.argv = args + self = sys.modules.get(__name__) + if (hasattr(pickle, "HIGHEST_PROTOCOL")): + self.__doc__ += exercise_pickling + return doctest.testmod(self) + +if __name__ == '__main__': + print("running...") + import sys + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/test_overload_resolution.cpp b/src/boost/libs/python/test/test_overload_resolution.cpp new file mode 100644 index 000000000..e15bcc6a7 --- /dev/null +++ b/src/boost/libs/python/test/test_overload_resolution.cpp @@ -0,0 +1,53 @@ +// Copyright Troy D. Straszheim 2009 +// 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) +// +// +// example that shows problems with overloading and automatic conversion. +// if you call one of the below functions from python with bool/int/double, +// you'll see that the overload called is first match, not best match. +// See overload matching in luabind for an example of how to do this better. +// +// see this mail: +// http://mail.python.org/pipermail/cplusplus-sig/2009-March/014362.html +// +// This test isn't called by the cmake/jamfiles. For future use. +// +#include <boost/python/module.hpp> +#include <boost/python/def.hpp> +#include <complex> +#include <boost/python/handle.hpp> +#include <boost/python/cast.hpp> +#include <boost/python/object.hpp> +#include <boost/python/detail/wrap_python.hpp> + +using boost::python::def; +using boost::python::handle; +using boost::python::object; +using boost::python::borrowed; + +std::string takes_bool(bool b) { return "bool"; } +std::string takes_int(int b) { return "int"; } +std::string takes_double(double b) { return "double"; } + + +BOOST_PYTHON_MODULE(overload_resolution) +{ + def("bid", takes_bool); + def("bid", takes_int); + def("bid", takes_double); + + def("dib", takes_double); + def("dib", takes_int); + def("dib", takes_bool); + + def("idb", takes_int); + def("idb", takes_double); + def("idb", takes_bool); + + def("bdi", takes_bool); + def("bdi", takes_double); + def("bdi", takes_int); +} + diff --git a/src/boost/libs/python/test/test_pointer_adoption.cpp b/src/boost/libs/python/test/test_pointer_adoption.cpp new file mode 100644 index 000000000..a4e14af5d --- /dev/null +++ b/src/boost/libs/python/test/test_pointer_adoption.cpp @@ -0,0 +1,125 @@ +// Copyright David Abrahams 2002. +// 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) +#include <boost/python/module.hpp> +#include <boost/python/def.hpp> +#include <boost/python/return_value_policy.hpp> +#include <boost/python/manage_new_object.hpp> +#include <boost/python/return_internal_reference.hpp> +#include <boost/python/class.hpp> + +using namespace boost::python; + +int a_instances = 0; + +int num_a_instances() { return a_instances; } + +struct inner +{ + inner(std::string const& s) + : s(s) + {} + + void change(std::string const& new_s) + { + this->s = new_s; + } + + std::string s; +}; + +struct Base +{ + virtual ~Base() {} +}; + +struct A : Base +{ + A(std::string const& s) + : x(s) + { + ++a_instances; + } + + ~A() + { + --a_instances; + } + + std::string content() const + { + return x.s; + } + + inner& get_inner() + { + return x; + } + + inner x; +}; + +struct B +{ + B() : x(0) {} + B(A* x_) : x(x_) {} + + inner const* adopt(A* _x) { this->x = _x; return &_x->get_inner(); } + + std::string a_content() + { + return x ? x->content() : std::string("empty"); + } + + A* x; +}; + + +A* create(std::string const& s) +{ + return new A(s); +} + +A* as_A(Base* b) +{ + return dynamic_cast<A*>(b); +} + +BOOST_PYTHON_MODULE(test_pointer_adoption_ext) +{ + def("num_a_instances", num_a_instances); + + // Specify the manage_new_object return policy to take + // ownership of create's result + def("create", create, return_value_policy<manage_new_object>()); + + def("as_A", as_A, return_internal_reference<>()); + + class_<Base>("Base") + ; + + class_<A, bases<Base> >("A", no_init) + .def("content", &A::content) + .def("get_inner", &A::get_inner, return_internal_reference<>()) + ; + + class_<inner>("inner", no_init) + .def("change", &inner::change) + ; + + class_<B>("B") + .def(init<A*>()[with_custodian_and_ward_postcall<1,2>()]) + + .def("adopt", &B::adopt + // Adopt returns a pointer referring to a subobject of its 2nd argument (1st being "self") + , return_internal_reference<2 + // Meanwhile, self holds a reference to the 2nd argument. + , with_custodian_and_ward<1,2> >() + ) + + .def("a_content", &B::a_content) + ; +} + +#include "module_tail.cpp" diff --git a/src/boost/libs/python/test/test_pointer_adoption.py b/src/boost/libs/python/test/test_pointer_adoption.py new file mode 100644 index 000000000..0fdf3b98e --- /dev/null +++ b/src/boost/libs/python/test/test_pointer_adoption.py @@ -0,0 +1,93 @@ +# Copyright David Abrahams 2004. 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) +""" +>>> from test_pointer_adoption_ext import * + +>>> num_a_instances() +0 + +>>> a = create('dynamically allocated') +>>> num_a_instances() +1 + +>>> a.content() +'dynamically allocated' + +>>> innards = a.get_inner() +>>> innards.change('with an exposed reference') +>>> a.content() +'with an exposed reference' + +# The a instance should be kept alive... +>>> a = None +>>> num_a_instances() +1 + +# ...until we're done with its innards +>>> innards = None +>>> num_a_instances() +0 + +>>> b = B() +>>> a = create('another') +>>> b.a_content() +'empty' +>>> innards = b.adopt(a); +>>> b.a_content() +'another' +>>> num_a_instances() +1 +>>> del a # innards and b are both holding a reference +>>> num_a_instances() +1 +>>> innards.change('yet another') +>>> b.a_content() +'yet another' + +>>> del innards +>>> num_a_instances() # b still owns a reference to a +1 +>>> del b +>>> num_a_instances() +0 + +Test call policies for constructors here + +>>> a = create('second a') +>>> num_a_instances() +1 +>>> b = B(a) +>>> num_a_instances() +1 +>>> a.content() +'second a' + +>>> del a +>>> num_a_instances() +1 +>>> b.a_content() +'second a' + +>>> del b +>>> num_a_instances() +0 + +>>> assert as_A(create('dynalloc')) is not None +>>> base = Base() +>>> assert as_A(base) is None +""" +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/tuple.cpp b/src/boost/libs/python/test/tuple.cpp new file mode 100644 index 000000000..d48e91d88 --- /dev/null +++ b/src/boost/libs/python/test/tuple.cpp @@ -0,0 +1,33 @@ +// Copyright David Abrahams 2005. 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) + +#include <boost/python/module.hpp> +#include <boost/python/def.hpp> +#include <boost/python/class.hpp> +#include <boost/python/tuple.hpp> + +using namespace boost::python; + +object convert_to_tuple(object data) +{ + return tuple(data); +} + +void test_operators(tuple t1, tuple t2, object print) +{ + print(t1 + t2); +} + +tuple mktuple0() { return make_tuple(); } +tuple mktuple1(int x) { return make_tuple(x); } +tuple mktuple2(char const* a1, int x) { return make_tuple(a1, x); } + +BOOST_PYTHON_MODULE(tuple_ext) +{ + def("convert_to_tuple",convert_to_tuple); + def("test_operators",test_operators); + def("make_tuple", mktuple0); + def("make_tuple", mktuple1); + def("make_tuple", mktuple2); +} diff --git a/src/boost/libs/python/test/tuple.py b/src/boost/libs/python/test/tuple.py new file mode 100644 index 000000000..1aec5fded --- /dev/null +++ b/src/boost/libs/python/test/tuple.py @@ -0,0 +1,38 @@ +# Copyright David Abrahams 2004. 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) +from __future__ import print_function +""" +>>> from tuple_ext import * +>>> def printer(*args): +... for x in args: print(x,) +... print('') +... +>>> print(convert_to_tuple("this is a test string")) +('t', 'h', 'i', 's', ' ', 'i', 's', ' ', 'a', ' ', 't', 'e', 's', 't', ' ', 's', 't', 'r', 'i', 'n', 'g') +>>> t1 = convert_to_tuple("this is") +>>> t2 = (1,2,3,4) +>>> test_operators(t1,t2,printer) #doctest: +NORMALIZE_WHITESPACE +('t', 'h', 'i', 's', ' ', 'i', 's', 1, 2, 3, 4) +>>> make_tuple() +() +>>> make_tuple(42) +(42,) +>>> make_tuple('hello', 42) +('hello', 42) +""" + +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/upcast.cpp b/src/boost/libs/python/test/upcast.cpp new file mode 100644 index 000000000..255429f16 --- /dev/null +++ b/src/boost/libs/python/test/upcast.cpp @@ -0,0 +1,19 @@ +// Copyright David Abrahams 2002. +// 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) + +#include <boost/python/cast.hpp> +#include <boost/detail/lightweight_test.hpp> + +struct X { long x; }; +struct Y : X, PyObject {}; + +int main() +{ + PyTypeObject o; + Y y; + BOOST_TEST(&Py_REFCNT(boost::python::upcast<PyObject>(&o)) == &Py_REFCNT(&o)); + BOOST_TEST(&Py_REFCNT(boost::python::upcast<PyObject>(&y)) == &Py_REFCNT(&y)); + return boost::report_errors(); +} diff --git a/src/boost/libs/python/test/vector_indexing_suite.cpp b/src/boost/libs/python/test/vector_indexing_suite.cpp new file mode 100644 index 000000000..0f9cd74ca --- /dev/null +++ b/src/boost/libs/python/test/vector_indexing_suite.cpp @@ -0,0 +1,62 @@ +// Copyright Joel de Guzman 2004. 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) + +#include <boost/python/suite/indexing/vector_indexing_suite.hpp> +#include <boost/python/module.hpp> +#include <boost/python/def.hpp> +#include <boost/python/implicit.hpp> + +using namespace boost::python; + +struct X // a container element +{ + std::string s; + X():s("default") {} + X(std::string s):s(s) {} + std::string repr() const { return s; } + void reset() { s = "reset"; } + void foo() { s = "foo"; } + bool operator==(X const& x) const { return s == x.s; } + bool operator!=(X const& x) const { return s != x.s; } +}; + +std::string x_value(X const& x) +{ + return "gotya " + x.s; +} + +BOOST_PYTHON_MODULE(vector_indexing_suite_ext) +{ + class_<X>("X") + .def(init<>()) + .def(init<X>()) + .def(init<std::string>()) + .def("__repr__", &X::repr) + .def("reset", &X::reset) + .def("foo", &X::foo) + ; + + def("x_value", x_value); + implicitly_convertible<std::string, X>(); + + class_<std::vector<X> >("XVec") + .def(vector_indexing_suite<std::vector<X> >()) + ; + + // Compile check only... + class_<std::vector<float> >("FloatVec") + .def(vector_indexing_suite<std::vector<float> >()) + ; + + // Compile check only... + class_<std::vector<bool> >("BoolVec") + .def(vector_indexing_suite<std::vector<bool> >()) + ; + + // vector of strings + class_<std::vector<std::string> >("StringVec") + .def(vector_indexing_suite<std::vector<std::string> >()) + ; +} + diff --git a/src/boost/libs/python/test/vector_indexing_suite.py b/src/boost/libs/python/test/vector_indexing_suite.py new file mode 100644 index 000000000..478cd0151 --- /dev/null +++ b/src/boost/libs/python/test/vector_indexing_suite.py @@ -0,0 +1,370 @@ +# Copyright Joel de Guzman 2004. 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) +''' + +##################################################################### +# Check an object that we will use as container element +##################################################################### + +>>> from vector_indexing_suite_ext import * +>>> x = X('hi') +>>> x +hi +>>> x.reset() # a member function that modifies X +>>> x +reset +>>> x.foo() # another member function that modifies X +>>> x +foo + +# test that a string is implicitly convertible +# to an X +>>> x_value('bochi bochi') +'gotya bochi bochi' + +##################################################################### +# Iteration +##################################################################### +>>> def print_xvec(xvec): +... s = '[ ' +... for x in xvec: +... s += repr(x) +... s += ' ' +... s += ']' +... print(s) + +##################################################################### +# Replace all the contents using slice syntax +##################################################################### + +>>> v = XVec() +>>> v[:] = [X('a'),X('b'),X('c'),X('d'),X('e')] +>>> print_xvec(v) +[ a b c d e ] + +##################################################################### +# Indexing +##################################################################### +>>> len(v) +5 +>>> v[0] +a +>>> v[1] +b +>>> v[2] +c +>>> v[3] +d +>>> v[4] +e +>>> v[-1] +e +>>> v[-2] +d +>>> v[-3] +c +>>> v[-4] +b +>>> v[-5] +a + +##################################################################### +# Deleting an element +##################################################################### + +>>> del v[0] +>>> v[0] = 'yaba' # must do implicit conversion +>>> print_xvec(v) +[ yaba c d e ] + +##################################################################### +# Calling a mutating function of a container element +##################################################################### +>>> v[3].reset() +>>> v[3] +reset + +##################################################################### +# Copying a container element +##################################################################### +>>> x = X(v[3]) +>>> x +reset +>>> x.foo() +>>> x +foo +>>> v[3] # should not be changed to 'foo' +reset + +##################################################################### +# Referencing a container element +##################################################################### +>>> x = v[3] +>>> x +reset +>>> x.foo() +>>> x +foo +>>> v[3] # should be changed to 'foo' +foo + +##################################################################### +# Slice +##################################################################### + +>>> sl = v[0:2] +>>> print_xvec(sl) +[ yaba c ] +>>> sl[0].reset() +>>> sl[0] +reset + +##################################################################### +# Reset the container again +##################################################################### +>>> v[:] = ['a','b','c','d','e'] # perform implicit conversion to X +>>> print_xvec(v) +[ a b c d e ] + +##################################################################### +# Slice: replace [1:3] with an element +##################################################################### +>>> v[1:3] = X('z') +>>> print_xvec(v) +[ a z d e ] + +##################################################################### +# Slice: replace [0:2] with a list +##################################################################### +>>> v[0:2] = ['1','2','3','4'] # perform implicit conversion to X +>>> print_xvec(v) +[ 1 2 3 4 d e ] + +##################################################################### +# Slice: delete [3:4] +##################################################################### +>>> del v[3:4] +>>> print_xvec(v) +[ 1 2 3 d e ] + +##################################################################### +# Slice: set [3:] to a list +##################################################################### +>>> v[3:] = [X('trailing'), X('stuff')] # a list +>>> print_xvec(v) +[ 1 2 3 trailing stuff ] + +##################################################################### +# Slice: delete [:3] +##################################################################### +>>> del v[:3] +>>> print_xvec(v) +[ trailing stuff ] + +##################################################################### +# Slice: insert a tuple to [0:0] +##################################################################### +>>> v[0:0] = ('leading','stuff') # can also be a tuple +>>> print_xvec(v) +[ leading stuff trailing stuff ] + +##################################################################### +# Reset the container again +##################################################################### +>>> v[:] = ['a','b','c','d','e'] + +##################################################################### +# Some references to the container elements +##################################################################### +>>> z0 = v[0] +>>> z1 = v[1] +>>> z2 = v[2] +>>> z3 = v[3] +>>> z4 = v[4] + +>>> z0 # proxy +a +>>> z1 # proxy +b +>>> z2 # proxy +c +>>> z3 # proxy +d +>>> z4 # proxy +e + +##################################################################### +# Delete a container element +##################################################################### + +>>> del v[2] +>>> print_xvec(v) +[ a b d e ] + +##################################################################### +# Show that the references are still valid +##################################################################### +>>> z0 # proxy +a +>>> z1 # proxy +b +>>> z2 # proxy detached +c +>>> z3 # proxy index adjusted +d +>>> z4 # proxy index adjusted +e + +##################################################################### +# Delete all container elements +##################################################################### +>>> del v[:] +>>> print_xvec(v) +[ ] + +##################################################################### +# Show that the references are still valid +##################################################################### +>>> z0 # proxy detached +a +>>> z1 # proxy detached +b +>>> z2 # proxy detached +c +>>> z3 # proxy detached +d +>>> z4 # proxy detached +e + +##################################################################### +# Reset the container again +##################################################################### +>>> v[:] = ['a','b','c','d','e'] + +##################################################################### +# renew the references to the container elements +##################################################################### +>>> z0 = v[0] +>>> z1 = v[1] +>>> z2 = v[2] +>>> z3 = v[3] +>>> z4 = v[4] + +>>> z0 # proxy +a +>>> z1 # proxy +b +>>> z2 # proxy +c +>>> z3 # proxy +d +>>> z4 # proxy +e + +##################################################################### +# Set [2:4] to a list such that there will be more elements +##################################################################### +>>> v[2:4] = ['x','y','v'] +>>> print_xvec(v) +[ a b x y v e ] + +##################################################################### +# Show that the references are still valid +##################################################################### +>>> z0 # proxy +a +>>> z1 # proxy +b +>>> z2 # proxy detached +c +>>> z3 # proxy detached +d +>>> z4 # proxy index adjusted +e + +##################################################################### +# Contains +##################################################################### +>>> v[:] = ['a','b','c','d','e'] # reset again + +>>> assert 'a' in v +>>> assert 'b' in v +>>> assert 'c' in v +>>> assert 'd' in v +>>> assert 'e' in v +>>> assert not 'X' in v +>>> assert not 12345 in v + +##################################################################### +# Show that iteration allows mutable access to the elements +##################################################################### +>>> v[:] = ['a','b','c','d','e'] # reset again +>>> for x in v: +... x.reset() +>>> print_xvec(v) +[ reset reset reset reset reset ] + +##################################################################### +# append +##################################################################### +>>> v[:] = ['a','b','c','d','e'] # reset again +>>> v.append('f') +>>> print_xvec(v) +[ a b c d e f ] + +##################################################################### +# extend +##################################################################### +>>> v[:] = ['a','b','c','d','e'] # reset again +>>> v.extend(['f','g','h','i','j']) +>>> print_xvec(v) +[ a b c d e f g h i j ] + +##################################################################### +# extend using a generator expression +##################################################################### +>>> v[:] = ['a','b','c','d','e'] # reset again +>>> def generator(): +... addlist = ['f','g','h','i','j'] +... for i in addlist: +... if i != 'g': +... yield i +>>> v.extend(generator()) +>>> print_xvec(v) +[ a b c d e f h i j ] + +##################################################################### +# vector of strings +##################################################################### +>>> sv = StringVec() +>>> sv.append('a') +>>> print(sv[0]) +a + +##################################################################### +# END.... +##################################################################### + +''' + + +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) + + + + + diff --git a/src/boost/libs/python/test/virtual_functions.cpp b/src/boost/libs/python/test/virtual_functions.cpp new file mode 100644 index 000000000..774b11b12 --- /dev/null +++ b/src/boost/libs/python/test/virtual_functions.cpp @@ -0,0 +1,125 @@ +// Copyright David Abrahams 2002. +// 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) + +#include <boost/python/class.hpp> +#include <boost/python/module.hpp> +#include <boost/python/def.hpp> +#include <boost/python/return_internal_reference.hpp> +#include <boost/python/call_method.hpp> +#include <boost/ref.hpp> +#include <boost/utility.hpp> + +#define BOOST_ENABLE_ASSERT_HANDLER +#include <boost/assert.hpp> + +using namespace boost::python; + +struct X +{ + explicit X(int x) : x(x), magic(7654321) { ++counter; } + X(X const& rhs) : x(rhs.x), magic(7654321) { ++counter; } + virtual ~X() { BOOST_ASSERT(magic == 7654321); magic = 6666666; x = 9999; --counter; } + + void set(int _x) { BOOST_ASSERT(magic == 7654321); this->x = _x; } + int value() const { BOOST_ASSERT(magic == 7654321); return x; } + static int count() { return counter; } + private: + void operator=(X const&); + private: + int x; + long magic; + static int counter; +}; + +struct Y : X +{ + Y(int x) : X(x) {}; +}; + +struct abstract : X +{ + abstract(int x) : X(x) {}; + int call_f(Y const& y) { return f(y); } + virtual int f(Y const& y) = 0; + abstract& call_g(Y const& y) { return g(y); } + virtual abstract& g(Y const& y) = 0; +}; + +struct concrete : X +{ + concrete(int x) : X(x) {}; + int call_f(Y const& y) { return f(y); } + virtual int f(Y const& y) { set(y.value()); return y.value(); } +}; + +struct abstract_callback : abstract +{ + abstract_callback(PyObject* p, int x) + : abstract(x), self(p) + {} + + int f(Y const& y) + { + return call_method<int>(self, "f", boost::ref(y)); + } + + abstract& g(Y const& y) + { + return call_method<abstract&>(self, "g", boost::ref(y)); + } + + PyObject* self; +}; + +struct concrete_callback : concrete +{ + concrete_callback(PyObject* p, int x) + : concrete(x), self(p) + {} + + concrete_callback(PyObject* p, concrete const& x) + : concrete(x), self(p) + {} + + int f(Y const& y) + { + return call_method<int>(self, "f", boost::ref(y)); + } + + int f_impl(Y const& y) + { + return this->concrete::f(y); + } + + PyObject* self; +}; + +int X::counter; + +BOOST_PYTHON_MODULE(virtual_functions_ext) +{ + class_<concrete, concrete_callback>("concrete", init<int>()) + .def("value", &concrete::value) + .def("set", &concrete::set) + .def("call_f", &concrete::call_f) + .def("f", &concrete_callback::f_impl) + ; + + class_<abstract, boost::noncopyable, abstract_callback + >("abstract", init<int>()) + + .def("value", &abstract::value) + .def("call_f", &abstract::call_f) + .def("call_g", &abstract::call_g, return_internal_reference<>()) + .def("set", &abstract::set) + ; + + class_<Y>("Y", init<int>()) + .def("value", &Y::value) + .def("set", &Y::set) + ; +} + +#include "module_tail.cpp" diff --git a/src/boost/libs/python/test/virtual_functions.py b/src/boost/libs/python/test/virtual_functions.py new file mode 100644 index 000000000..cba21edd6 --- /dev/null +++ b/src/boost/libs/python/test/virtual_functions.py @@ -0,0 +1,110 @@ +# Copyright David Abrahams 2004. 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) +''' +>>> from virtual_functions_ext import * + +>>> class C1(concrete): +... def f(self, y): +... return concrete.f(self, Y(-y.value())) + +>>> class C2(concrete): +... pass + +>>> class A1(abstract): +... def f(self, y): +... return y.value() * 2 +... def g(self, y): +... return self + +>>> class A2(abstract): +... pass + + +>>> y1 = Y(16) +>>> y2 = Y(17) + + + +# +# Test abstract with f,g overridden +# +>>> a1 = A1(42) +>>> a1.value() +42 + +# Call f,g indirectly from C++ +>>> a1.call_f(y1) +32 +>>> assert type(a1.call_g(y1)) is abstract + +# Call f directly from Python +>>> a1.f(y2) +34 + +# +# Test abstract with f not overridden +# +>>> a2 = A2(42) +>>> a2.value() +42 + +# Call f indirectly from C++ +>>> try: a2.call_f(y1) +... except AttributeError: pass +... else: print('no exception') + +# Call f directly from Python +>>> try: a2.call_f(y2) +... except AttributeError: pass +... else: print('no exception') + +############# Concrete Tests ############ + +# +# Test concrete with f overridden +# +>>> c1 = C1(42) +>>> c1.value() +42 + +# Call f indirectly from C++ +>>> c1.call_f(y1) +-16 + +# Call f directly from Python +>>> c1.f(y2) +-17 + +# +# Test concrete with f not overridden +# +>>> c2 = C2(42) +>>> c2.value() +42 + +# Call f indirectly from C++ +>>> c2.call_f(y1) +16 + +# Call f directly from Python +>>> c2.f(y2) +17 + + +''' + +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/voidptr.cpp b/src/boost/libs/python/test/voidptr.cpp new file mode 100644 index 000000000..82e412bea --- /dev/null +++ b/src/boost/libs/python/test/voidptr.cpp @@ -0,0 +1,43 @@ +// Copyright Niall Douglas 2005. +// 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) + +# include <boost/python/return_opaque_pointer.hpp> +# include <boost/python/def.hpp> +# include <boost/python/module.hpp> +# include <boost/python/return_value_policy.hpp> + +static void *test=(void *) 78; + +void *get() +{ + return test; +} + +void *getnull() +{ + return 0; +} + +void use(void *a) +{ + if(a!=test) + throw std::runtime_error(std::string("failed")); +} + +int useany(void *a) +{ + return a ? 1 : 0; +} + + +namespace bpl = boost::python; + +BOOST_PYTHON_MODULE(voidptr_ext) +{ + bpl::def("get", &::get, bpl::return_value_policy<bpl::return_opaque_pointer>()); + bpl::def("getnull", &::getnull, bpl::return_value_policy<bpl::return_opaque_pointer>()); + bpl::def("use", &::use); + bpl::def("useany", &::useany); +} diff --git a/src/boost/libs/python/test/voidptr.py b/src/boost/libs/python/test/voidptr.py new file mode 100644 index 000000000..0e189c965 --- /dev/null +++ b/src/boost/libs/python/test/voidptr.py @@ -0,0 +1,54 @@ +# Copyright Niall Douglas 2005. +# 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) + + +""" +>>> from voidptr_ext import * + + + Check for correct conversion + +>>> use(get()) + + Check that None is converted to a NULL void pointer + +>>> useany(get()) +1 +>>> useany(None) +0 + + Check that we don't lose type information by converting NULL + opaque pointers to None + +>>> assert getnull() is None +>>> useany(getnull()) +0 + + Check that there is no conversion from integers ... + +>>> try: use(0) +... except TypeError: pass +... else: print('expected a TypeError') + + ... and from strings to opaque objects + +>>> try: use("") +... except TypeError: pass +... else: print('expected a TypeError') +""" +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/src/boost/libs/python/test/wrapper_held_type.cpp b/src/boost/libs/python/test/wrapper_held_type.cpp new file mode 100644 index 000000000..e99422796 --- /dev/null +++ b/src/boost/libs/python/test/wrapper_held_type.cpp @@ -0,0 +1,69 @@ +// Copyright David Abrahams 2005. 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) + +#include <boost/python/register_ptr_to_python.hpp> +#include <boost/python/def.hpp> +#include <boost/python/class.hpp> +#include <boost/python/wrapper.hpp> +#include <boost/python/module.hpp> +#include <boost/python/implicit.hpp> + +#include <memory> + +struct data +{ + virtual ~data() {}; // silence compiler warnings + virtual int id() const + { + return 42; + } +}; + +std::auto_ptr<data> create_data() +{ + return std::auto_ptr<data>( new data ); +} + +void do_nothing( std::auto_ptr<data>& ){} + + +namespace bp = boost::python; + +struct data_wrapper : data, bp::wrapper< data > +{ + data_wrapper(data const & arg ) + : data( arg ) + , bp::wrapper< data >() + {} + + data_wrapper() + : data() + , bp::wrapper< data >() + {} + + virtual int id() const + { + if( bp::override id = this->get_override( "id" ) ) + return bp::call<int>(id.ptr()); // id(); + else + return data::id( ); + } + + virtual int default_id( ) const + { + return this->data::id( ); + } + +}; + +BOOST_PYTHON_MODULE(wrapper_held_type_ext) +{ + bp::class_< data_wrapper, std::auto_ptr< data > >( "data" ) + .def( "id", &data::id, &::data_wrapper::default_id ); + + bp::def( "do_nothing", &do_nothing ); + bp::def( "create_data", &create_data ); +} + +#include "module_tail.cpp" diff --git a/src/boost/libs/python/test/wrapper_held_type.py b/src/boost/libs/python/test/wrapper_held_type.py new file mode 100644 index 000000000..ff1bd1d24 --- /dev/null +++ b/src/boost/libs/python/test/wrapper_held_type.py @@ -0,0 +1,34 @@ +# Copyright David Abrahams 2005. 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) +''' +>>> from wrapper_held_type_ext import * +>>> d = data() +>>> print(d.id()) +42 +>>> do_nothing( d ) +>>> print(d.id()) +42 +>>> d = create_data() +>>> print(d.id()) +42 +>>> do_nothing( d ) +>>> print(d.id()) +42 +''' + +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 + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) + |