From 31c8b7f1b49bd5b9acb88f8e837bf217e2b62035 Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Mon, 31 Jul 2017 11:37:52 -0400 Subject: [PATCH 01/16] Remove 'numeric' documentation. --- doc/reference/numeric.qbk | 153 -------------------------------------- doc/reference/objects.qbk | 1 - doc/reference/slice.qbk | 8 -- 3 files changed, 162 deletions(-) delete mode 100644 doc/reference/numeric.qbk diff --git a/doc/reference/numeric.qbk b/doc/reference/numeric.qbk deleted file mode 100644 index 4ccb0d38..00000000 --- a/doc/reference/numeric.qbk +++ /dev/null @@ -1,153 +0,0 @@ -[section boost/python/numeric.hpp] -[section Introduction] -Exposes a [link concepts.objectwrapper.typewrapper_concept_requirements TypeWrapper] for the Python [@http://www.python.org/dev/doc/devel/lib/typesmapping.html array] type. -[endsect] -[section Class `array`] -Provides access to the array types of [@http://www.pfdubois.com/numpy/ Numerical Python]\ 's [@http://www.pfdubois.com/numpy/#Numeric Numeric] and [@http://stsdas.stsci.edu/numarray/index.html NumArray] modules. With the exception of the functions documented below, the semantics of the constructors and member functions defined below can be fully understood by reading the [link concepts.objectwrapper.typewrapper_concept_requirements TypeWrapper] concept definition. Since array is publicly derived from object, the public object interface applies to array instances as well. - -The default behavior is to use numarray.NDArray as the associated Python type if the numarray module is installed in the default location. Otherwise it falls back to use Numeric.ArrayType. If neither extension module is installed, overloads of wrapped C++ functions with numeric::array parameters will never be matched, and other attempted uses of numeric::array will raise an appropriate Python exception. The associated Python type can be set manually using the set_module_and_type(...) static function. -`` -namespace boost { namespace python { namespace numeric -{ - class array : public object - { - public: - object astype(); - template - object astype(Type const& type_); - - template - array new_(Type const& type_) const; - - template - void resize(Sequence const& x); - void resize(long x1); - void resize(long x1, long x2); - ... - void resize(long x1, long x2,...long xn); - - template - void setshape(Sequence const& x); - void setshape(long x1); - void setshape(long x1, long x2); - ... - void setshape(long x1, long x2,...long xn); - - template - void put(Indices const& indices, Values const& values); - - template - object take(Sequence const& sequence, long axis = 0); - - template - void tofile(File const& f) const; - - object factory(); - template - object factory(Sequence const&); - template - object factory(Sequence const&, Typecode const&, bool copy = true, bool savespace = false); - template - object factory(Sequence const&, Typecode const&, bool copy, bool savespace, Type const&); - template - object factory(Sequence const&, Typecode const&, bool copy, bool savespace, Type const&, Shape const&); - - template - explicit array(T1 const& x1); - template - explicit array(T1 const& x1, T2 const& x2); - ... - template - explicit array(T1 const& x1, T2 const& x2,...Tn const& xn); - - static void set_module_and_type(); - static void set_module_and_type(char const* package_path = 0, char const* type_name = 0); - static void get_module_name(); - - object argmax(long axis=-1); - - object argmin(long axis=-1); - - object argsort(long axis=-1); - - void byteswap(); - - object copy() const; - - object diagonal(long offset = 0, long axis1 = 0, long axis2 = 1) const; - - void info() const; - - bool is_c_array() const; - bool isbyteswapped() const; - void sort(); - object trace(long offset = 0, long axis1 = 0, long axis2 = 1) const; - object type() const; - char typecode() const; - - object getflat() const; - long getrank() const; - object getshape() const; - bool isaligned() const; - bool iscontiguous() const; - long itemsize() const; - long nelements() const; - object nonzero() const; - - void ravel(); - object repeat(object const& repeats, long axis=0); - void setflat(object const& flat); - void swapaxes(long axis1, long axis2); - str tostring() const; - void transpose(object const& axes = object()); - object view() const; - }; -}}} -`` -[endsect] -[section Class `array` observer functions] -`` -object factory(); -template -object factory(Sequence const&); -template -object factory(Sequence const&, Typecode const&, bool copy = true, bool savespace = false); -template -object factory(Sequence const&, Typecode const&, bool copy, bool savespace, Type const&); -template -object factory(Sequence const&, Typecode const&, bool copy, bool savespace, Type const&, Shape const&); -`` -These functions map to the underlying array type's array() function family. They are not called "array" because of the C++ limitation that you can't define a member function with the same name as its enclosing class. -`` -template -array new_(Type const&) const; -`` -This function maps to the underlying array type's new() function. It is not called "new" because that is a keyword in C++. -[endsect] -[section Class `array` static functions] -`` -static void set_module_and_type(char const* package_path, char const* type_name); -static void set_module_and_type(); -`` -[variablelist -[[Requires][package_path and type_name, if supplied, is an [link ntbs].]] -[[Effects][The first form sets the package path of the module that supplies the type named by type_name to package_path. The second form restores the default search behavior. The associated Python type will be searched for only the first time it is needed, and thereafter the first time it is needed after an invocation of set_module_and_type.]] -] -``static std::string get_module_name()`` -[variablelist -[[Effects][Returns the name of the module containing the class that will be held by new `numeric::array` instances.]] -] -[endsect] -[section Example] -`` -#include -#include - -// sets the first element in a 2d numeric array -void set_first_element(numeric::array& y, double value) -{ - y[make_tuple(0,0)] = value; -} -`` -[endsect] -[endsect] diff --git a/doc/reference/objects.qbk b/doc/reference/objects.qbk index 80ce257c..c57b02d0 100644 --- a/doc/reference/objects.qbk +++ b/doc/reference/objects.qbk @@ -5,7 +5,6 @@ [include dict.qbk] [include list.qbk] [include long.qbk] -[include numeric.qbk] [include object.qbk] [include str.qbk] [include slice.qbk] diff --git a/doc/reference/slice.qbk b/doc/reference/slice.qbk index 32e3363f..19dbe4d9 100644 --- a/doc/reference/slice.qbk +++ b/doc/reference/slice.qbk @@ -105,14 +105,6 @@ list odd_elements(list l) return l[slice(_,_,2)]; } -// Perform a multidimensional extended slice of a Numeric.array -numeric::array even_columns(numeric::array arr) -{ - // select every other column, starting with the second, of a 2-D array. - // Equivalent to "return arr[:, 1::2]" in Python. - return arr[make_tuple( slice(), slice(1,_,2))]; -} - // Perform a summation over a slice of a std::vector. double partial_sum(std::vector const& Foo, const slice index) { From b3b67273b0751ccfe650cbaebc053bcd323ad12c Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Sun, 13 Aug 2017 20:44:52 -0400 Subject: [PATCH 02/16] Fix traits qualification. --- include/boost/python/object/inheritance.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/python/object/inheritance.hpp b/include/boost/python/object/inheritance.hpp index eb7fca28..90e56f0c 100644 --- a/include/boost/python/object/inheritance.hpp +++ b/include/boost/python/object/inheritance.hpp @@ -103,7 +103,7 @@ struct implicit_cast_generator template struct cast_generator : mpl::if_< - detail::is_base_and_derived + boost::python::detail::is_base_and_derived , implicit_cast_generator , dynamic_cast_generator > From c2424bcc8f0ed16008394c6a4e326e954bae7702 Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Sun, 13 Aug 2017 20:45:13 -0400 Subject: [PATCH 03/16] Fix version number. --- SConstruct | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SConstruct b/SConstruct index 6edd7cd4..848172f9 100644 --- a/SConstruct +++ b/SConstruct @@ -85,7 +85,7 @@ if not GetOption('verbose'): config.ui.pretty_output(env) # build -env['BPL_VERSION'] = '1.62' +env['BPL_VERSION'] = '1.65' for e in config.variants(env): variant_dir=e.subst("$BOOST_CURRENT_VARIANT_DIR") e.SConscript('src/SConscript', variant_dir=variant_dir + '/src', From 00b7ed03a7df3f013bfe7c6e1ce708bd514169e2 Mon Sep 17 00:00:00 2001 From: Edward Diener Date: Sun, 17 Sep 2017 16:34:40 -0400 Subject: [PATCH 04/16] Remove executable attribute for files. --- doc/html/images/python_cpp_mix.png | Bin doc/internals.html | 0 doc/internals.rst | 0 include/boost/python/arg_from_python.hpp | 0 include/boost/python/base_type_traits.hpp | 0 include/boost/python/borrowed.hpp | 0 include/boost/python/cast.hpp | 0 include/boost/python/converter/arg_to_python.hpp | 0 .../python/converter/context_result_converter.hpp | 0 include/boost/python/converter/pytype_function.hpp | 0 .../boost/python/converter/return_from_python.hpp | 0 include/boost/python/def_visitor.hpp | 0 include/boost/python/detail/convertible.hpp | 0 .../boost/python/detail/copy_ctor_mutates_rhs.hpp | 0 include/boost/python/detail/def_helper_fwd.hpp | 0 include/boost/python/detail/is_shared_ptr.hpp | 0 include/boost/python/detail/is_wrapper.hpp | 0 .../python/detail/nullary_function_adaptor.hpp | 0 include/boost/python/detail/prefix.hpp | 0 include/boost/python/detail/python_type.hpp | 0 include/boost/python/detail/sfinae.hpp | 0 include/boost/python/detail/unwind_type.hpp | 0 include/boost/python/detail/unwrap_type_id.hpp | 0 include/boost/python/detail/unwrap_wrapper.hpp | 0 include/boost/python/detail/value_arg.hpp | 0 include/boost/python/docstring_options.hpp | 0 include/boost/python/handle_fwd.hpp | 0 include/boost/python/object.hpp | 0 .../boost/python/object/function_doc_signature.hpp | 0 include/boost/python/object/inheritance_query.hpp | 0 include/boost/python/object/stl_iterator_core.hpp | 0 include/boost/python/object_protocol_core.hpp | 0 include/boost/python/raw_function.hpp | 0 include/boost/python/refcount.hpp | 0 include/boost/python/self.hpp | 0 include/boost/python/stl_iterator.hpp | 0 include/boost/python/wrapper.hpp | 0 src/numpy/dtype.cpp | 0 src/wrapper.cpp | 0 test/borrowed.cpp | 0 test/class.py | 0 test/cltree.cpp | 0 test/copy_ctor_mutates_rhs.cpp | 0 test/crossmod_exception_a.cpp | 0 test/crossmod_exception_b.cpp | 0 test/enable_shared_from_this.py | 0 test/injected.cpp | 0 test/int_map_indexing_suite.cpp | 0 test/keywords.cpp | 0 test/object_fail1.cpp | 0 test/object_manager.cpp | 0 test/operators.cpp | 0 test/polymorphism2.cpp | 0 test/polymorphism2_auto_ptr.cpp | 0 test/properties.cpp | 0 test/pytype_function.py | 0 test/raw_ctor.cpp | 0 test/raw_pyobject_fail1.cpp | 0 test/raw_pyobject_fail2.cpp | 0 test/result.cpp | 0 test/return_arg.cpp | 0 test/stl_iterator.cpp | 0 test/voidptr.cpp | 0 test/wrapper_held_type.cpp | 0 64 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 doc/html/images/python_cpp_mix.png mode change 100755 => 100644 doc/internals.html mode change 100755 => 100644 doc/internals.rst mode change 100755 => 100644 include/boost/python/arg_from_python.hpp mode change 100755 => 100644 include/boost/python/base_type_traits.hpp mode change 100755 => 100644 include/boost/python/borrowed.hpp mode change 100755 => 100644 include/boost/python/cast.hpp mode change 100755 => 100644 include/boost/python/converter/arg_to_python.hpp mode change 100755 => 100644 include/boost/python/converter/context_result_converter.hpp mode change 100755 => 100644 include/boost/python/converter/pytype_function.hpp mode change 100755 => 100644 include/boost/python/converter/return_from_python.hpp mode change 100755 => 100644 include/boost/python/def_visitor.hpp mode change 100755 => 100644 include/boost/python/detail/convertible.hpp mode change 100755 => 100644 include/boost/python/detail/copy_ctor_mutates_rhs.hpp mode change 100755 => 100644 include/boost/python/detail/def_helper_fwd.hpp mode change 100755 => 100644 include/boost/python/detail/is_shared_ptr.hpp mode change 100755 => 100644 include/boost/python/detail/is_wrapper.hpp mode change 100755 => 100644 include/boost/python/detail/nullary_function_adaptor.hpp mode change 100755 => 100644 include/boost/python/detail/prefix.hpp mode change 100755 => 100644 include/boost/python/detail/python_type.hpp mode change 100755 => 100644 include/boost/python/detail/sfinae.hpp mode change 100755 => 100644 include/boost/python/detail/unwind_type.hpp mode change 100755 => 100644 include/boost/python/detail/unwrap_type_id.hpp mode change 100755 => 100644 include/boost/python/detail/unwrap_wrapper.hpp mode change 100755 => 100644 include/boost/python/detail/value_arg.hpp mode change 100755 => 100644 include/boost/python/docstring_options.hpp mode change 100755 => 100644 include/boost/python/handle_fwd.hpp mode change 100755 => 100644 include/boost/python/object.hpp mode change 100755 => 100644 include/boost/python/object/function_doc_signature.hpp mode change 100755 => 100644 include/boost/python/object/inheritance_query.hpp mode change 100755 => 100644 include/boost/python/object/stl_iterator_core.hpp mode change 100755 => 100644 include/boost/python/object_protocol_core.hpp mode change 100755 => 100644 include/boost/python/raw_function.hpp mode change 100755 => 100644 include/boost/python/refcount.hpp mode change 100755 => 100644 include/boost/python/self.hpp mode change 100755 => 100644 include/boost/python/stl_iterator.hpp mode change 100755 => 100644 include/boost/python/wrapper.hpp mode change 100755 => 100644 src/numpy/dtype.cpp mode change 100755 => 100644 src/wrapper.cpp mode change 100755 => 100644 test/borrowed.cpp mode change 100755 => 100644 test/class.py mode change 100755 => 100644 test/cltree.cpp mode change 100755 => 100644 test/copy_ctor_mutates_rhs.cpp mode change 100755 => 100644 test/crossmod_exception_a.cpp mode change 100755 => 100644 test/crossmod_exception_b.cpp mode change 100755 => 100644 test/enable_shared_from_this.py mode change 100755 => 100644 test/injected.cpp mode change 100755 => 100644 test/int_map_indexing_suite.cpp mode change 100755 => 100644 test/keywords.cpp mode change 100755 => 100644 test/object_fail1.cpp mode change 100755 => 100644 test/object_manager.cpp mode change 100755 => 100644 test/operators.cpp mode change 100755 => 100644 test/polymorphism2.cpp mode change 100755 => 100644 test/polymorphism2_auto_ptr.cpp mode change 100755 => 100644 test/properties.cpp mode change 100755 => 100644 test/pytype_function.py mode change 100755 => 100644 test/raw_ctor.cpp mode change 100755 => 100644 test/raw_pyobject_fail1.cpp mode change 100755 => 100644 test/raw_pyobject_fail2.cpp mode change 100755 => 100644 test/result.cpp mode change 100755 => 100644 test/return_arg.cpp mode change 100755 => 100644 test/stl_iterator.cpp mode change 100755 => 100644 test/voidptr.cpp mode change 100755 => 100644 test/wrapper_held_type.cpp diff --git a/doc/html/images/python_cpp_mix.png b/doc/html/images/python_cpp_mix.png old mode 100755 new mode 100644 diff --git a/doc/internals.html b/doc/internals.html old mode 100755 new mode 100644 diff --git a/doc/internals.rst b/doc/internals.rst old mode 100755 new mode 100644 diff --git a/include/boost/python/arg_from_python.hpp b/include/boost/python/arg_from_python.hpp old mode 100755 new mode 100644 diff --git a/include/boost/python/base_type_traits.hpp b/include/boost/python/base_type_traits.hpp old mode 100755 new mode 100644 diff --git a/include/boost/python/borrowed.hpp b/include/boost/python/borrowed.hpp old mode 100755 new mode 100644 diff --git a/include/boost/python/cast.hpp b/include/boost/python/cast.hpp old mode 100755 new mode 100644 diff --git a/include/boost/python/converter/arg_to_python.hpp b/include/boost/python/converter/arg_to_python.hpp old mode 100755 new mode 100644 diff --git a/include/boost/python/converter/context_result_converter.hpp b/include/boost/python/converter/context_result_converter.hpp old mode 100755 new mode 100644 diff --git a/include/boost/python/converter/pytype_function.hpp b/include/boost/python/converter/pytype_function.hpp old mode 100755 new mode 100644 diff --git a/include/boost/python/converter/return_from_python.hpp b/include/boost/python/converter/return_from_python.hpp old mode 100755 new mode 100644 diff --git a/include/boost/python/def_visitor.hpp b/include/boost/python/def_visitor.hpp old mode 100755 new mode 100644 diff --git a/include/boost/python/detail/convertible.hpp b/include/boost/python/detail/convertible.hpp old mode 100755 new mode 100644 diff --git a/include/boost/python/detail/copy_ctor_mutates_rhs.hpp b/include/boost/python/detail/copy_ctor_mutates_rhs.hpp old mode 100755 new mode 100644 diff --git a/include/boost/python/detail/def_helper_fwd.hpp b/include/boost/python/detail/def_helper_fwd.hpp old mode 100755 new mode 100644 diff --git a/include/boost/python/detail/is_shared_ptr.hpp b/include/boost/python/detail/is_shared_ptr.hpp old mode 100755 new mode 100644 diff --git a/include/boost/python/detail/is_wrapper.hpp b/include/boost/python/detail/is_wrapper.hpp old mode 100755 new mode 100644 diff --git a/include/boost/python/detail/nullary_function_adaptor.hpp b/include/boost/python/detail/nullary_function_adaptor.hpp old mode 100755 new mode 100644 diff --git a/include/boost/python/detail/prefix.hpp b/include/boost/python/detail/prefix.hpp old mode 100755 new mode 100644 diff --git a/include/boost/python/detail/python_type.hpp b/include/boost/python/detail/python_type.hpp old mode 100755 new mode 100644 diff --git a/include/boost/python/detail/sfinae.hpp b/include/boost/python/detail/sfinae.hpp old mode 100755 new mode 100644 diff --git a/include/boost/python/detail/unwind_type.hpp b/include/boost/python/detail/unwind_type.hpp old mode 100755 new mode 100644 diff --git a/include/boost/python/detail/unwrap_type_id.hpp b/include/boost/python/detail/unwrap_type_id.hpp old mode 100755 new mode 100644 diff --git a/include/boost/python/detail/unwrap_wrapper.hpp b/include/boost/python/detail/unwrap_wrapper.hpp old mode 100755 new mode 100644 diff --git a/include/boost/python/detail/value_arg.hpp b/include/boost/python/detail/value_arg.hpp old mode 100755 new mode 100644 diff --git a/include/boost/python/docstring_options.hpp b/include/boost/python/docstring_options.hpp old mode 100755 new mode 100644 diff --git a/include/boost/python/handle_fwd.hpp b/include/boost/python/handle_fwd.hpp old mode 100755 new mode 100644 diff --git a/include/boost/python/object.hpp b/include/boost/python/object.hpp old mode 100755 new mode 100644 diff --git a/include/boost/python/object/function_doc_signature.hpp b/include/boost/python/object/function_doc_signature.hpp old mode 100755 new mode 100644 diff --git a/include/boost/python/object/inheritance_query.hpp b/include/boost/python/object/inheritance_query.hpp old mode 100755 new mode 100644 diff --git a/include/boost/python/object/stl_iterator_core.hpp b/include/boost/python/object/stl_iterator_core.hpp old mode 100755 new mode 100644 diff --git a/include/boost/python/object_protocol_core.hpp b/include/boost/python/object_protocol_core.hpp old mode 100755 new mode 100644 diff --git a/include/boost/python/raw_function.hpp b/include/boost/python/raw_function.hpp old mode 100755 new mode 100644 diff --git a/include/boost/python/refcount.hpp b/include/boost/python/refcount.hpp old mode 100755 new mode 100644 diff --git a/include/boost/python/self.hpp b/include/boost/python/self.hpp old mode 100755 new mode 100644 diff --git a/include/boost/python/stl_iterator.hpp b/include/boost/python/stl_iterator.hpp old mode 100755 new mode 100644 diff --git a/include/boost/python/wrapper.hpp b/include/boost/python/wrapper.hpp old mode 100755 new mode 100644 diff --git a/src/numpy/dtype.cpp b/src/numpy/dtype.cpp old mode 100755 new mode 100644 diff --git a/src/wrapper.cpp b/src/wrapper.cpp old mode 100755 new mode 100644 diff --git a/test/borrowed.cpp b/test/borrowed.cpp old mode 100755 new mode 100644 diff --git a/test/class.py b/test/class.py old mode 100755 new mode 100644 diff --git a/test/cltree.cpp b/test/cltree.cpp old mode 100755 new mode 100644 diff --git a/test/copy_ctor_mutates_rhs.cpp b/test/copy_ctor_mutates_rhs.cpp old mode 100755 new mode 100644 diff --git a/test/crossmod_exception_a.cpp b/test/crossmod_exception_a.cpp old mode 100755 new mode 100644 diff --git a/test/crossmod_exception_b.cpp b/test/crossmod_exception_b.cpp old mode 100755 new mode 100644 diff --git a/test/enable_shared_from_this.py b/test/enable_shared_from_this.py old mode 100755 new mode 100644 diff --git a/test/injected.cpp b/test/injected.cpp old mode 100755 new mode 100644 diff --git a/test/int_map_indexing_suite.cpp b/test/int_map_indexing_suite.cpp old mode 100755 new mode 100644 diff --git a/test/keywords.cpp b/test/keywords.cpp old mode 100755 new mode 100644 diff --git a/test/object_fail1.cpp b/test/object_fail1.cpp old mode 100755 new mode 100644 diff --git a/test/object_manager.cpp b/test/object_manager.cpp old mode 100755 new mode 100644 diff --git a/test/operators.cpp b/test/operators.cpp old mode 100755 new mode 100644 diff --git a/test/polymorphism2.cpp b/test/polymorphism2.cpp old mode 100755 new mode 100644 diff --git a/test/polymorphism2_auto_ptr.cpp b/test/polymorphism2_auto_ptr.cpp old mode 100755 new mode 100644 diff --git a/test/properties.cpp b/test/properties.cpp old mode 100755 new mode 100644 diff --git a/test/pytype_function.py b/test/pytype_function.py old mode 100755 new mode 100644 diff --git a/test/raw_ctor.cpp b/test/raw_ctor.cpp old mode 100755 new mode 100644 diff --git a/test/raw_pyobject_fail1.cpp b/test/raw_pyobject_fail1.cpp old mode 100755 new mode 100644 diff --git a/test/raw_pyobject_fail2.cpp b/test/raw_pyobject_fail2.cpp old mode 100755 new mode 100644 diff --git a/test/result.cpp b/test/result.cpp old mode 100755 new mode 100644 diff --git a/test/return_arg.cpp b/test/return_arg.cpp old mode 100755 new mode 100644 diff --git a/test/stl_iterator.cpp b/test/stl_iterator.cpp old mode 100755 new mode 100644 diff --git a/test/voidptr.cpp b/test/voidptr.cpp old mode 100755 new mode 100644 diff --git a/test/wrapper_held_type.cpp b/test/wrapper_held_type.cpp old mode 100755 new mode 100644 From ecf05c4a90b05b031634b7c793a9e25d4e4fe611 Mon Sep 17 00:00:00 2001 From: Mark Borgerding Date: Wed, 20 Sep 2017 09:39:46 -0400 Subject: [PATCH 05/16] ndarray.shape(k),strides(k) act more like their python counterparts (negative indexing, bounds checking) (issue #157) --- include/boost/python/numpy/ndarray.hpp | 8 +++---- src/numpy/ndarray.cpp | 24 +++++++++++++++++++ test/numpy/ndarray.cpp | 5 ++++ test/numpy/ndarray.py | 33 ++++++++++++++++++++++++++ 4 files changed, 66 insertions(+), 4 deletions(-) diff --git a/include/boost/python/numpy/ndarray.hpp b/include/boost/python/numpy/ndarray.hpp index 98a4cb15..2cb3b509 100644 --- a/include/boost/python/numpy/ndarray.hpp +++ b/include/boost/python/numpy/ndarray.hpp @@ -86,11 +86,11 @@ public: /// @brief Copy the scalar (deep for all non-object fields). ndarray copy() const; - /// @brief Return the size of the nth dimension. - Py_intptr_t shape(int n) const { return get_shape()[n]; } + /// @brief Return the size of the nth dimension. raises IndexError if k not in [-get_nd() : get_nd()-1 ] + Py_intptr_t shape(int n) const; - /// @brief Return the stride of the nth dimension. - Py_intptr_t strides(int n) const { return get_strides()[n]; } + /// @brief Return the stride of the nth dimension. raises IndexError if k not in [-get_nd() : get_nd()-1] + Py_intptr_t strides(int n) const; /** * @brief Return the array's raw data pointer. diff --git a/src/numpy/ndarray.cpp b/src/numpy/ndarray.cpp index 8ae67b89..625c43b3 100644 --- a/src/numpy/ndarray.cpp +++ b/src/numpy/ndarray.cpp @@ -138,6 +138,30 @@ ndarray from_data_impl(void * data, } // namespace detail +namespace { + int normalize_index(int n,int nlim) // wraps [-nlim:nlim) into [0:nlim), throw IndexError otherwise + { + if (n<0) + n += nlim; // negative indices work backwards from end + if (n < 0 || n >= nlim) + { + PyErr_SetObject(PyExc_IndexError, Py_None); + throw_error_already_set(); + } + return n; + } +} + +Py_intptr_t ndarray::shape(int n) const +{ + return get_shape()[normalize_index(n,get_nd())]; +} + +Py_intptr_t ndarray::strides(int n) const +{ + return get_strides()[normalize_index(n,get_nd())]; +} + ndarray ndarray::view(dtype const & dt) const { return ndarray(python::detail::new_reference diff --git a/test/numpy/ndarray.cpp b/test/numpy/ndarray.cpp index 808872e8..75a10104 100644 --- a/test/numpy/ndarray.cpp +++ b/test/numpy/ndarray.cpp @@ -31,6 +31,9 @@ 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(); @@ -43,4 +46,6 @@ BOOST_PYTHON_MODULE(ndarray_ext) 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/test/numpy/ndarray.py b/test/numpy/ndarray.py index fb92a2a2..2acc384a 100644 --- a/test/numpy/ndarray.py +++ b/test/numpy/ndarray.py @@ -75,5 +75,38 @@ class TestNdarray(unittest.TestCase): 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() From 135c02548431e86d4b169fae07e9f1ceee188211 Mon Sep 17 00:00:00 2001 From: Mark Borgerding Date: Wed, 20 Sep 2017 16:47:48 -0400 Subject: [PATCH 06/16] fixed nuisance warning when calling from_data(...,bob) with an ndarray bob, "FutureWarning: comparison to None will result in an elementwise object comparison in the future." --- src/numpy/ndarray.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/numpy/ndarray.cpp b/src/numpy/ndarray.cpp index 625c43b3..af09ecc3 100644 --- a/src/numpy/ndarray.cpp +++ b/src/numpy/ndarray.cpp @@ -194,7 +194,7 @@ python::object ndarray::get_base() const void ndarray::set_base(object const & base) { Py_XDECREF(get_struct()->base); - if (base != object()) + if (base.ptr()) { Py_INCREF(base.ptr()); get_struct()->base = base.ptr(); From b09d80a93e299bdaba29b652010b668b87f1306c Mon Sep 17 00:00:00 2001 From: Frank Richter Date: Wed, 18 Oct 2017 11:43:28 +0200 Subject: [PATCH 07/16] Fix exec(), eval() not passing through arguments --- src/exec.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/exec.cpp b/src/exec.cpp index 603a6f01..171c6f41 100644 --- a/src/exec.cpp +++ b/src/exec.cpp @@ -16,7 +16,7 @@ namespace python object BOOST_PYTHON_DECL eval(str string, object global, object local) { - return eval(python::extract(string)); + return eval(python::extract(string), global, local); } object BOOST_PYTHON_DECL eval(char const *string, object global, object local) @@ -39,7 +39,7 @@ object BOOST_PYTHON_DECL eval(char const *string, object global, object local) object BOOST_PYTHON_DECL exec(str string, object global, object local) { - return exec(python::extract(string)); + return exec(python::extract(string), global, local); } object BOOST_PYTHON_DECL exec(char const *string, object global, object local) From 9d2903cd5ef6588f20b58cc993dd4336fa72d80c Mon Sep 17 00:00:00 2001 From: Marvin Schmidt Date: Mon, 4 Sep 2017 07:43:43 +0200 Subject: [PATCH 08/16] Fix symbol visibility of init method This was properly an oversight when switching to the BOOST_SYMBOL_* symbols from Boost.Config in commit 0224f54a (see #1) Since Boost.Config is already doing the differentiation between different platforms and compilers we can simplify this bit and just use BOOST_SYMBOL_EXPORT --- include/boost/python/module_init.hpp | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/include/boost/python/module_init.hpp b/include/boost/python/module_init.hpp index a9536c88..7fe5a1c8 100644 --- a/include/boost/python/module_init.hpp +++ b/include/boost/python/module_init.hpp @@ -66,25 +66,9 @@ BOOST_PYTHON_DECL PyObject* init_module(char const* name, void(*)()); # endif -# if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(BOOST_PYTHON_STATIC_MODULE) - -# define BOOST_PYTHON_MODULE_INIT(name) \ - void BOOST_PP_CAT(init_module_,name)(); \ -extern "C" __declspec(dllexport) _BOOST_PYTHON_MODULE_INIT(name) - -# elif BOOST_PYTHON_USE_GCC_SYMBOL_VISIBILITY - -# define BOOST_PYTHON_MODULE_INIT(name) \ - void BOOST_PP_CAT(init_module_,name)(); \ -extern "C" __attribute__ ((__visibility__("default"))) _BOOST_PYTHON_MODULE_INIT(name) - -# else - -# define BOOST_PYTHON_MODULE_INIT(name) \ - void BOOST_PP_CAT(init_module_,name)(); \ -extern "C" _BOOST_PYTHON_MODULE_INIT(name) - -# endif +# define BOOST_PYTHON_MODULE_INIT(name) \ + void BOOST_PP_CAT(init_module_,name)(); \ +extern "C" BOOST_SYMBOL_EXPORT _BOOST_PYTHON_MODULE_INIT(name) # endif From 8d37630cc8c8eb252010f3ab51cad7e149c42beb Mon Sep 17 00:00:00 2001 From: Raffi Enficiaud Date: Tue, 15 Aug 2017 21:32:15 +0200 Subject: [PATCH 09/16] Fix warning: returning the proper type for object sizes --- include/boost/python/detail/caller.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/python/detail/caller.hpp b/include/boost/python/detail/caller.hpp index c572d35a..1bd30bfb 100644 --- a/include/boost/python/detail/caller.hpp +++ b/include/boost/python/detail/caller.hpp @@ -48,7 +48,7 @@ inline PyObject* get(mpl::int_, PyObject* const& args_) return PyTuple_GET_ITEM(args_,N); } -inline unsigned arity(PyObject* const& args_) +inline Py_ssize_t arity(PyObject* const& args_) { return PyTuple_GET_SIZE(args_); } From 2b7842a39f023e2aa2b401089dfeac0172844574 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Trzci=C5=84ski?= Date: Tue, 24 Oct 2017 11:09:23 +0100 Subject: [PATCH 10/16] Fix memory leaks in enum.cpp Unfortunately due to optimised build of Python3 libraries and executable I got only partial stack from [http://clang.llvm.org/docs/AddressSanitizer.html], however digging into and reducing my code I tracked it down to be issue with `boost/libs/python/src/object/enum.cpp`. It has to bits that leak (and comment mentioning there is one): PyObject *mod = PyObject_GetAttrString( self_, "__module__"); Leaks reference, as it never decreases it. It also stores a new string object under object's `name` that ref count never gets decremented. That commit fixes both issues. --- src/object/enum.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/object/enum.cpp b/src/object/enum.cpp index 3063320c..4d73ee23 100644 --- a/src/object/enum.cpp +++ b/src/object/enum.cpp @@ -34,11 +34,17 @@ static PyMemberDef enum_members[] = { extern "C" { + static void + enum_dealloc(enum_object* self) + { + Py_XDECREF(self->name); + Py_TYPE(self)->tp_free((PyObject*)self); + } + static PyObject* enum_repr(PyObject* self_) { - // XXX(bhy) Potentional memory leak here since PyObject_GetAttrString returns a new reference - // const char *mod = PyString_AsString(PyObject_GetAttrString( self_, const_cast("__module__"))); PyObject *mod = PyObject_GetAttrString( self_, "__module__"); + object auto_free(handle<>(mod)); enum_object* self = downcast(self_); if (!self->name) { @@ -88,7 +94,7 @@ static PyTypeObject enum_type_object = { const_cast("Boost.Python.enum"), sizeof(enum_object), /* tp_basicsize */ 0, /* tp_itemsize */ - 0, /* tp_dealloc */ + (destructor) enum_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ From 7c5e478432e99f304e0ea9c03ef16f289592a5e9 Mon Sep 17 00:00:00 2001 From: Gary Furnish Date: Sun, 20 Aug 2017 21:56:52 -0600 Subject: [PATCH 11/16] Fix autoptr/unique_ptr ifdef for VS2017. --- include/boost/python/make_constructor.hpp | 4 ++-- include/boost/python/object/make_ptr_instance.hpp | 2 +- include/boost/python/object/pointer_holder.hpp | 4 ++-- include/boost/python/object/py_function.hpp | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/boost/python/make_constructor.hpp b/include/boost/python/make_constructor.hpp index 053d050c..3ec9ad5f 100644 --- a/include/boost/python/make_constructor.hpp +++ b/include/boost/python/make_constructor.hpp @@ -45,7 +45,7 @@ namespace detail template void dispatch(U* x, detail::true_) const { -#if __cplusplus < 201103L +#if defined(BOOST_NO_CXX11_SMART_PTR) std::auto_ptr owner(x); dispatch(owner, detail::false_()); #else @@ -63,7 +63,7 @@ namespace detail void* memory = holder::allocate(this->m_self, offsetof(instance_t, storage), sizeof(holder)); try { -#if __cplusplus < 201103L +#if defined(BOOST_NO_CXX11_SMART_PTR) (new (memory) holder(x))->install(this->m_self); #else (new (memory) holder(std::move(x)))->install(this->m_self); diff --git a/include/boost/python/object/make_ptr_instance.hpp b/include/boost/python/object/make_ptr_instance.hpp index 21089c6b..66a8bebe 100644 --- a/include/boost/python/object/make_ptr_instance.hpp +++ b/include/boost/python/object/make_ptr_instance.hpp @@ -21,7 +21,7 @@ struct make_ptr_instance template static inline Holder* construct(void* storage, PyObject*, Arg& x) { -#if __cplusplus < 201103L +#if defined(BOOST_NO_CXX11_SMART_PTR) return new (storage) Holder(x); #else return new (storage) Holder(std::move(x)); diff --git a/include/boost/python/object/pointer_holder.hpp b/include/boost/python/object/pointer_holder.hpp index c5caefe6..c3b57e83 100644 --- a/include/boost/python/object/pointer_holder.hpp +++ b/include/boost/python/object/pointer_holder.hpp @@ -106,7 +106,7 @@ struct pointer_holder_back_reference : instance_holder template inline pointer_holder::pointer_holder(Pointer p) -#if __cplusplus < 201103L +#if defined(BOOST_NO_CXX11_SMART_PTR) : m_p(p) #else : m_p(std::move(p)) @@ -116,7 +116,7 @@ inline pointer_holder::pointer_holder(Pointer p) template inline pointer_holder_back_reference::pointer_holder_back_reference(Pointer p) -#if __cplusplus < 201103L +#if defined(BOOST_NO_CXX11_SMART_PTR) : m_p(p) #else : m_p(std::move(p)) diff --git a/include/boost/python/object/py_function.hpp b/include/boost/python/object/py_function.hpp index 05cedfa0..df2fb44a 100644 --- a/include/boost/python/object/py_function.hpp +++ b/include/boost/python/object/py_function.hpp @@ -135,7 +135,7 @@ struct py_function {} py_function(py_function const& rhs) -#if __cplusplus < 201103L +#if defined(BOOST_NO_CXX11_SMART_PTR) : m_impl(rhs.m_impl) #else : m_impl(std::move(rhs.m_impl)) @@ -168,7 +168,7 @@ struct py_function } private: -#if __cplusplus < 201103L +#if defined(BOOST_NO_CXX11_SMART_PTR) mutable std::auto_ptr m_impl; #else mutable std::unique_ptr m_impl; From 30c9eb1fb6f0525541e4b6dd33ed01de455b0b53 Mon Sep 17 00:00:00 2001 From: Gary Furnish Date: Mon, 21 Aug 2017 09:19:20 -0600 Subject: [PATCH 12/16] Fix c++11 detection. --- config/cxx.py | 2 +- include/boost/python/converter/registered.hpp | 2 +- include/boost/python/converter/shared_ptr_to_python.hpp | 2 +- include/boost/python/detail/is_shared_ptr.hpp | 2 +- include/boost/python/detail/type_traits.hpp | 5 +++-- include/boost/python/object/class_metadata.hpp | 2 +- include/boost/python/to_python_indirect.hpp | 2 +- include/boost/python/to_python_value.hpp | 2 +- 8 files changed, 10 insertions(+), 9 deletions(-) diff --git a/config/cxx.py b/config/cxx.py index ae34beb0..deb7be73 100644 --- a/config/cxx.py +++ b/config/cxx.py @@ -15,7 +15,7 @@ def add_options(vars): def check(context): - source = r"""#if __cplusplus < 201103L + source = r"""#if __cplusplus < 201103L && (!defined(_MSC_VER) || _MSC_VER < 1800) #error no C++11 #endif""" diff --git a/include/boost/python/converter/registered.hpp b/include/boost/python/converter/registered.hpp index 73f4d984..98013052 100644 --- a/include/boost/python/converter/registered.hpp +++ b/include/boost/python/converter/registered.hpp @@ -76,7 +76,7 @@ namespace detail registry::lookup_shared_ptr(type_id >()); } -#if __cplusplus >= 201103L +#if !defined(BOOST_NO_CXX11_SMART_PTR) template inline void register_shared_ptr0(std::shared_ptr*) diff --git a/include/boost/python/converter/shared_ptr_to_python.hpp b/include/boost/python/converter/shared_ptr_to_python.hpp index cc686461..02649d40 100644 --- a/include/boost/python/converter/shared_ptr_to_python.hpp +++ b/include/boost/python/converter/shared_ptr_to_python.hpp @@ -25,7 +25,7 @@ PyObject* shared_ptr_to_python(shared_ptr const& x) return converter::registered const&>::converters.to_python(&x); } -#if __cplusplus >= 201103L +#if !defined(BOOST_NO_CXX11_SMART_PTR) template PyObject* shared_ptr_to_python(std::shared_ptr const& x) { diff --git a/include/boost/python/detail/is_shared_ptr.hpp b/include/boost/python/detail/is_shared_ptr.hpp index bef0e05a..383383bc 100644 --- a/include/boost/python/detail/is_shared_ptr.hpp +++ b/include/boost/python/detail/is_shared_ptr.hpp @@ -13,7 +13,7 @@ namespace boost { namespace python { namespace detail { BOOST_PYTHON_IS_XXX_DEF(shared_ptr, shared_ptr, 1) -#if __cplusplus >= 201103L +#if !defined(BOOST_NO_CXX11_SMART_PTR) template struct is_shared_ptr > : std::true_type {}; #endif diff --git a/include/boost/python/detail/type_traits.hpp b/include/boost/python/detail/type_traits.hpp index df940c7e..381132ee 100644 --- a/include/boost/python/detail/type_traits.hpp +++ b/include/boost/python/detail/type_traits.hpp @@ -7,7 +7,8 @@ # define BOOST_PYTHON_DETAIL_TYPE_TRAITS_HPP -#if __cplusplus < 201103L +#if __cplusplus < 201103L && (!defined(BOOST_MSVC) || BOOST_MSVC<=1600) +#define BOOST_PYTHON_USE_BOOST_TYPES # include # include # include @@ -34,7 +35,7 @@ namespace boost { namespace python { namespace detail { -#if __cplusplus < 201103L +#if defined(BOOST_PYTHON_USE_BOOST_TYPES) using boost::alignment_of; using boost::add_const; using boost::add_cv; diff --git a/include/boost/python/object/class_metadata.hpp b/include/boost/python/object/class_metadata.hpp index 93303ecb..06d3f8ef 100644 --- a/include/boost/python/object/class_metadata.hpp +++ b/include/boost/python/object/class_metadata.hpp @@ -83,7 +83,7 @@ inline void register_shared_ptr_from_python_and_casts(T*, Bases) { // Constructor performs registration python::detail::force_instantiate(converter::shared_ptr_from_python()); -#if __cplusplus >= 201103L +#if !defined(BOOST_NO_CXX11_SMART_PTR) python::detail::force_instantiate(converter::shared_ptr_from_python()); #endif diff --git a/include/boost/python/to_python_indirect.hpp b/include/boost/python/to_python_indirect.hpp index 212e1db3..0a19aca5 100644 --- a/include/boost/python/to_python_indirect.hpp +++ b/include/boost/python/to_python_indirect.hpp @@ -83,7 +83,7 @@ namespace detail // copy constructor. # if defined(__ICL) && __ICL < 600 typedef boost::shared_ptr smart_pointer; -# elif __cplusplus < 201103L +# elif defined(BOOST_NO_CXX11_SMART_PTR) typedef std::auto_ptr smart_pointer; # else typedef std::unique_ptr smart_pointer; diff --git a/include/boost/python/to_python_value.hpp b/include/boost/python/to_python_value.hpp index 2066d3a2..b6ec0135 100644 --- a/include/boost/python/to_python_value.hpp +++ b/include/boost/python/to_python_value.hpp @@ -118,7 +118,7 @@ struct object_manager_get_pytype PyTypeObject const* get_pytype(boost::type &> *) const {return converter::registered::converters.to_python_target_type();} template PyTypeObject const* get_pytype(boost::type &> *) const {return converter::registered::converters.to_python_target_type();} -# if __cplusplus >= 201103L +# if !defined(BOOST_NO_CXX11_SMART_PTR) template PyTypeObject const* get_pytype(boost::type &> *) const {return converter::registered::converters.to_python_target_type();} template From 2d9871fc5ad78b3fca8766778e7ecb54af461474 Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Fri, 27 Oct 2017 13:03:24 -0400 Subject: [PATCH 13/16] Fix unresolved symbol error with MSVC. --- include/boost/python/object/make_ptr_instance.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/python/object/make_ptr_instance.hpp b/include/boost/python/object/make_ptr_instance.hpp index 66a8bebe..92412b31 100644 --- a/include/boost/python/object/make_ptr_instance.hpp +++ b/include/boost/python/object/make_ptr_instance.hpp @@ -58,7 +58,7 @@ struct make_ptr_instance static inline PyTypeObject* get_derived_class_object(boost::python::detail::true_, U const volatile* x) { converter::registration const* r = converter::registry::query( - type_info(typeid(*get_pointer(x))) + type_info(typeid(*x)) ); return r ? r->m_class_object : 0; } From bf9a03399b84d1ea2b62de027c8fafe5a27e4b2f Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Mon, 30 Oct 2017 08:04:01 -0400 Subject: [PATCH 14/16] Revert "Avoid multiple template instances of boost::python::details::get_signature when multiple calling conventions are enabled" This reverts commit b49a186b6fc4b4ecf84aa920149426a1d2385b19. --- include/boost/python/signature.hpp | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/include/boost/python/signature.hpp b/include/boost/python/signature.hpp index 9b323a28..ab4bca39 100644 --- a/include/boost/python/signature.hpp +++ b/include/boost/python/signature.hpp @@ -111,7 +111,6 @@ struct most_derived // 'default' calling convention # define BOOST_PYTHON_FN_CC -# define BOOST_PYTHON_FN_CC_IS_DEFAULT # define BOOST_PP_ITERATION_PARAMS_1 \ (3, (0, BOOST_PYTHON_MAX_ARITY, )) @@ -119,7 +118,6 @@ struct most_derived # include BOOST_PP_ITERATE() # undef BOOST_PYTHON_FN_CC -# undef BOOST_PYTHON_FN_CC_IS_DEFAULT // __cdecl calling convention @@ -143,7 +141,6 @@ struct most_derived # if defined(BOOST_PYTHON_ENABLE_STDCALL) # define BOOST_PYTHON_FN_CC __stdcall -# define BOOST_PYTHON_FN_CC_IS_STDCALL # define BOOST_PP_ITERATION_PARAMS_1 \ (3, (0, BOOST_PYTHON_MAX_ARITY, )) @@ -151,7 +148,6 @@ struct most_derived # include BOOST_PP_ITERATE() # undef BOOST_PYTHON_FN_CC -# undef BOOST_PYTHON_FN_CC_IS_STDCALL # endif // defined(BOOST_PYTHON_ENABLE_STDCALL) @@ -160,14 +156,12 @@ struct most_derived # if defined(BOOST_PYTHON_ENABLE_FASTCALL) # define BOOST_PYTHON_FN_CC __fastcall -# define BOOST_PYTHON_FN_CC_IS_FASTCALL # define BOOST_PP_ITERATION_PARAMS_1 \ (3, (0, BOOST_PYTHON_MAX_ARITY, )) # include BOOST_PP_ITERATE() -# undef BOOST_PYTHON_FN_CC_IS_FASTCALL # undef BOOST_PYTHON_FN_CC # endif // defined(BOOST_PYTHON_ENABLE_FASTCALL) @@ -190,8 +184,8 @@ struct most_derived // as 'get_signature(RT(*)(T0...TN), void* = 0)' is the same // function as 'get_signature(RT(__cdecl *)(T0...TN), void* = 0)', - // we don't define it multiple times (i.e. for __cdecl, __stdcall ...) -# if defined(BOOST_PYTHON_FN_CC_IS_DEFAULT) + // we don't define it twice +# if !defined(BOOST_PYTHON_FN_CC_IS_CDECL) template < class RT BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class T)> @@ -204,7 +198,7 @@ get_signature(RT(BOOST_PYTHON_FN_CC *)(BOOST_PP_ENUM_PARAMS_Z(1, N, T)), void* = >(); } -# endif // BOOST_PYTHON_FN_CC_IS_DEFAULT +# endif // !defined(BOOST_PYTHON_FN_CC_IS_CDECL) # undef N @@ -212,13 +206,11 @@ get_signature(RT(BOOST_PYTHON_FN_CC *)(BOOST_PP_ENUM_PARAMS_Z(1, N, T)), void* = (3, (0, 3, )) # include BOOST_PP_ITERATE() -#else // BOOST_PP_ITERATION_DEPTH() != 1 +#else # define N BOOST_PP_RELATIVE_ITERATION(1) # define Q BOOST_PYTHON_CV_QUALIFIER(BOOST_PP_ITERATION()) -# if defined(BOOST_PYTHON_FN_CC_IS_DEFAULT) - template < class RT, class ClassT BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class T)> inline BOOST_PYTHON_LIST_INC(BOOST_PP_INC(N))< @@ -253,8 +245,6 @@ get_signature( >(); } -# endif // BOOST_PYTHON_FN_CC_IS_DEFAULT - # undef Q # undef N From 9ad3313d1f788a1498553bbbf6634af715589d4c Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Tue, 7 Nov 2017 19:43:16 -0500 Subject: [PATCH 15/16] Fix deprecated elementwise comparison warning / error. --- include/boost/python/numpy/ufunc.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/python/numpy/ufunc.hpp b/include/boost/python/numpy/ufunc.hpp index 7e249238..79d7d262 100644 --- a/include/boost/python/numpy/ufunc.hpp +++ b/include/boost/python/numpy/ufunc.hpp @@ -106,7 +106,7 @@ struct unary_ufunc dtype in_dtype = dtype::get_builtin(); dtype out_dtype = dtype::get_builtin(); ndarray in_array = from_object(input, in_dtype, ndarray::ALIGNED); - ndarray out_array = (output != object()) ? + ndarray out_array = ! output.is_none() ? from_object(output, out_dtype, ndarray::ALIGNED | ndarray::WRITEABLE) : zeros(in_array.get_nd(), in_array.get_shape(), out_dtype); multi_iter iter = make_multi_iter(in_array, out_array); @@ -171,7 +171,7 @@ struct binary_ufunc ndarray in1_array = from_object(input1, in1_dtype, ndarray::ALIGNED); ndarray in2_array = from_object(input2, in2_dtype, ndarray::ALIGNED); multi_iter iter = make_multi_iter(in1_array, in2_array); - ndarray out_array = (output != object()) + ndarray out_array = !output.is_none() ? from_object(output, out_dtype, ndarray::ALIGNED | ndarray::WRITEABLE) : zeros(iter.get_nd(), iter.get_shape(), out_dtype); iter = make_multi_iter(in1_array, in2_array, out_array); From ebba009a9fd150bd07f6557948e139b62536a99b Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Fri, 10 Nov 2017 02:08:40 -0500 Subject: [PATCH 16/16] First attempt at faber-based build system. --- appveyor.yml => .appveyor.yml | 34 ++++--- .ci/faber | 3 + .travis.yml | 26 +++-- fabscript | 80 ++++++++++++++++ src/fabscript | 58 ++++++++++++ test/fabscript | 173 ++++++++++++++++++++++++++++++++++ 6 files changed, 351 insertions(+), 23 deletions(-) rename appveyor.yml => .appveyor.yml (83%) create mode 100644 .ci/faber create mode 100644 fabscript create mode 100644 src/fabscript create mode 100644 test/fabscript diff --git a/appveyor.yml b/.appveyor.yml similarity index 83% rename from appveyor.yml rename to .appveyor.yml index bc11c5b8..714a51bd 100644 --- a/appveyor.yml +++ b/.appveyor.yml @@ -4,7 +4,7 @@ environment: # /E:ON and /V:ON options are not enabled in the batch script intepreter # See: http://stackoverflow.com/a/13751649/163740 CMD_IN_ENV: "cmd /E:ON /V:ON /C .\\ci\\run_with_env.cmd" - BOOST_PREFIX: C:\Libraries\boost_1_60_0 + BOOST_PREFIX: C:\Libraries\boost_1_63_0 matrix: @@ -15,7 +15,8 @@ environment: - PYTHON: "C:\\Python27" PYTHON_VERSION: "2.7.x" # currently 2.7.9 PYTHON_ARCH: "32" - ARCH: "x86" + MSVC: "14.0" + ARCH: x86 #- PYTHON: "C:\\Python27-x64" # PYTHON_VERSION: "2.7.x" # currently 2.7.9 @@ -26,9 +27,11 @@ environment: # PYTHON_VERSION: "3.5.x" # currently 3.4.3 # PYTHON_ARCH: "32" - #- PYTHON: "C:\\Python35-x64" - # PYTHON_VERSION: "3.5.x" # currently 3.4.3 - # PYTHON_ARCH: "64" + - PYTHON: "C:\\Python36-x64" + PYTHON_VERSION: "3.6.x" + PYTHON_ARCH: "64" + MSVC: "12.0" + ARCH: x86_64 install: # If there is a newer build queued for the same PR, cancel this one. @@ -68,21 +71,22 @@ install: # compiled extensions and are not provided as pre-built wheel packages, # pip will build them from source using the MSVC compiler matching the # target Python version and architecture - - easy_install scons + - | + curl -LfsS -o faber.tar.gz https://github.com/stefanseefeld/faber/archive/release/0.2.tar.gz + tar xf faber.tar.gz + CD faber-release-0.2 + python setup.py install + CD .. + # report the available MSVC compilers + - python -m faber.tools.msvc - easy_install sphinx - pip install numpy - #- "%CMD_IN_ENV% pip install -r dev-requirements.txt" build_script: - # Build the compiled extension - #- "%CMD_IN_ENV% python setup.py build" - - scons config arch=%ARCH% --boost-include=%BOOST_PREFIX% - - scons arch=%ARCH% --verbose + - faber --with-boost-include=%BOOST_PREFIX% target.arch=%ARCH% msvc.version=%MSVC% test_script: - # Run the project tests - #- "%CMD_IN_ENV% python setup.py nosetests" - - scons test arch=%ARCH% --verbose + - faber --with-boost-include=%BOOST_PREFIX% test.report target.arch=%ARCH% msvc.version=%MSVC% after_test: # If tests are successful, create binary packages for the project. @@ -97,4 +101,4 @@ after_test: #on_success: # - TODO: upload the content of dist/*.whl to a public wheelhouse -# \ No newline at end of file +# diff --git a/.ci/faber b/.ci/faber new file mode 100644 index 00000000..b23e8a18 --- /dev/null +++ b/.ci/faber @@ -0,0 +1,3 @@ +from faber.tools.python import python + +p = python(command='$PYTHON') diff --git a/.travis.yml b/.travis.yml index 97a4fc8a..e9342193 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,12 +26,10 @@ matrix: - compiler: gcc env: CXX=g++ PYTHON=python3 CXXFLAGS=-std=c++11 - compiler: clang - # clang generates an 'illegal instruction' error in the NumPy check. - # Perhaps we need to upgrade clang to a newer version ? - env: CXX=clang++ PYTHON=python3 CXXFLAGS=-std=c++98 OPTIONS=--no-numpy + env: CXX=clang++ PYTHON=python3 CXXFLAGS=-std=c++98 - compiler: clang - env: CXX=clang++ PYTHON=python3 CXXFLAGS=-std=c++11 OPTIONS=--no-numpy - - env: PYTHON=python DOC=1 + env: CXX=clang++ PYTHON=python3 CXXFLAGS=-std=c++11 + #- env: PYTHON=python DOC=1 addons: @@ -77,16 +75,28 @@ install: ./bootstrap.sh ./b2 tools/bcp mkdir -p $HOME/Boost + # Install Boost.Python prerequisites, but not Boost.Python itself. dist/bin/bcp python tools/boostbook tools/quickbook $HOME/Boost &> /dev/null + rm -rf $HOME/Boost/boost/python* + popd + # Install Faber, the build tool. + date=2017-11-09 + #wget https://github.com/stefanseefeld/faber/archive/snapshot/$date.tar.gz + wget https://github.com/stefanseefeld/faber/archive/release/0.2.tar.gz + tar xf 0.2.tar.gz + pushd faber-release-0.2 + sudo python setup.py install popd fi before_script: -- scons --version +- sed -e "s/\$PYTHON/$PYTHON/g" .ci/faber > ~/.faber +- $PYTHON --version +- faber -h script: -- scons config --python=$PYTHON --boost-include=$HOME/Boost $OPTIONS -- if [ "$DOC" ]; then scons doc; else scons && scons test; fi +- faber --with-boost-include=$HOME/Boost test.report cxx.name=$CXX cxxflags=$CXXFLAGS +#- if [ "$DOC" ]; then scons doc; else scons && scons test; fi after_success: # Upload docs only when building upstream. diff --git a/fabscript b/fabscript new file mode 100644 index 00000000..59be9e18 --- /dev/null +++ b/fabscript @@ -0,0 +1,80 @@ +# -*- 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.feature import set +from faber.types import cxx +from faber.tools.compiler import cxxflags, define, include +from faber.tools.python import python +from faber.config import report, cxx_checks +from faber.config.try_run import try_run + +features += include('include') +features += define('BOOST_ALL_NO_LIB') # disable auto-linking +boost_include = options.get_with('boost-include') +if boost_include: + features += include(boost_include) +python = python.instance() +features |= set(python.include, python.linkpath, python.libs) + +class has_numpy(try_run): + + src = r""" +// If defined, enforces linking against PythonXXd.lib, which +// is usually not included in Python environments. +#undef _DEBUG +#include "Python.h" +#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION +#include "numpy/arrayobject.h" + +#if PY_VERSION_HEX >= 0x03000000 +void *initialize() { import_array();} +#else +void initialize() { import_array();} +#endif + +int main() +{ + int result = 0; + Py_Initialize(); + initialize(); + if (PyErr_Occurred()) + { + result = 1; + } + else + { + npy_intp dims = 2; + PyObject * a = PyArray_SimpleNew(1, &dims, NPY_INT); + if (!a) result = 1; + Py_DECREF(a); + } + Py_Finalize(); + return result; +} +""" + def __init__(self, features=()): + + inc = '' + try: + inc = python.check_python('import numpy; print(numpy.get_include())') + features |= include(inc) + except Exception: + # ignore errors, the check will fail during compilation... + pass + try_run.__init__(self, 'has_numpy', has_numpy.src, cxx, features, + if_=(include(inc), define('HAS_NUMPY'))) + +checks = [cxx_checks.has_cxx11(features, define('HAS_CXX11')), + has_numpy(features)] +config = report('config', checks) + +src = module('src', features=config.use) +test = module('test', features=config.use) + +default = src.default diff --git a/src/fabscript b/src/fabscript new file mode 100644 index 00000000..d5dbf603 --- /dev/null +++ b/src/fabscript @@ -0,0 +1,58 @@ +# -*- 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.feature import set +from faber.artefacts.library import library +from faber.tools.compiler import define + +root = module('..') + +bpl = library('boost_python', + ['list.cpp', + 'long.cpp', + 'dict.cpp', + 'tuple.cpp', + 'str.cpp', + 'slice.cpp', + 'converter/from_python.cpp', + 'converter/registry.cpp', + 'converter/type_id.cpp', + 'object/enum.cpp', + 'object/class.cpp', + 'object/function.cpp', + 'object/inheritance.cpp', + 'object/life_support.cpp', + 'object/pickle_support.cpp', + 'errors.cpp', + 'module.cpp', + 'converter/builtin_converters.cpp', + 'converter/arg_to_python_base.cpp', + 'object/iterator.cpp', + 'object/stl_iterator.cpp', + 'object_protocol.cpp', + 'object_operators.cpp', + 'wrapper.cpp', + 'import.cpp', + 'exec.cpp', + 'object/function_doc_signature.cpp'], + dependencies=root.config, + features=features + define('BOOST_PYTHON_SOURCE')) + +bnl = library('boost_numpy', + ['numpy/dtype.cpp', + 'numpy/matrix.cpp', + 'numpy/ndarray.cpp', + 'numpy/numpy.cpp', + 'numpy/scalars.cpp', + 'numpy/ufunc.cpp', + bpl], + dependencies=root.config, + features=features + define('BOOST_NUMPY_SOURCE'), + condition=set.define.contains('HAS_NUMPY')) +default = [bpl, bnl] diff --git a/test/fabscript b/test/fabscript new file mode 100644 index 00000000..1989cc0d --- /dev/null +++ b/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, if none are given. + * script: the test script to execute, .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)