From 77ee91d5c58661323188412fc47ae2fab9bd9abb Mon Sep 17 00:00:00 2001 From: al3xst Date: Thu, 17 Nov 2016 14:54:10 +0100 Subject: [PATCH 1/9] Updated python library reference url Due to changes on the python website, the url to the pickle library reference page was invalid. --- doc/reference/pickle.qbk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/reference/pickle.qbk b/doc/reference/pickle.qbk index 7f89c2d1..23d25ede 100644 --- a/doc/reference/pickle.qbk +++ b/doc/reference/pickle.qbk @@ -4,7 +4,7 @@ Pickle is a Python module for object serialization, also known as persistence, m It is often necessary to save and restore the contents of an object to a file. One approach to this problem is to write a pair of functions that read and write data from a file in a special format. A powerful alternative approach is to use Python's pickle module. Exploiting Python's ability for introspection, the pickle module recursively converts nearly arbitrary Python objects into a stream of bytes that can be written to a file. -The Boost Python Library supports the pickle module through the interface as described in detail in the [@http://www.python.org/doc/current/lib/module-pickle.html Python Library Reference for pickle]. This interface involves the special methods `__getinitargs__`, `__getstate__` and `__setstate__` as described in the following. Note that `Boost.Python` is also fully compatible with Python's cPickle module. +The Boost Python Library supports the pickle module through the interface as described in detail in the [@https://docs.python.org/2/library/pickle.html Python Library Reference for pickle]. This interface involves the special methods `__getinitargs__`, `__getstate__` and `__setstate__` as described in the following. Note that `Boost.Python` is also fully compatible with Python's cPickle module. [endsect] [section The Pickle Interface] At the user level, the Boost.Python pickle interface involves three special methods: From 1e315242ce66dc4c826d9dcf1f9509178bb82818 Mon Sep 17 00:00:00 2001 From: Rene Rivera Date: Fri, 3 Mar 2017 22:28:22 -0600 Subject: [PATCH 2/9] Fix libs from referencing BPL when there is no python configured. --- build/Jamfile | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/build/Jamfile b/build/Jamfile index aedeed67..4a766ac2 100644 --- a/build/Jamfile +++ b/build/Jamfile @@ -42,8 +42,11 @@ rule cond ( test ? : yes * : no * ) { if $(test) { return $(yes) ; } else { retu rule unless ( test ? : yes * : no * ) { if ! $(test) { return $(yes) ; } else { return $(no) ; } } local rule eq ( a : b ) { if $(a) = $(b) { return 1 ; } } -lib_boost_python($(py2-version)) = boost_python ; -lib_boost_python($(py3-version)) = boost_python3 ; +lib_boost_python(2) = boost_python ; +lib_boost_python(3) = boost_python3 ; + +lib_boost_python($(py2-version)) = $(lib_boost_python(2)) ; +lib_boost_python($(py3-version)) = $(lib_boost_python(3)) ; rule lib_boost_python ( version ) { @@ -169,6 +172,10 @@ for local N in 2 3 libraries += $(lib_boost_numpy($(py$(N)-version))) ; } } + else + { + alias $(lib_boost_python($(N))) ; + } } boost-install $(libraries) ; From 398e7f02b8636b1ff8cce28bb2922584c457728e Mon Sep 17 00:00:00 2001 From: Rene Rivera Date: Sun, 5 Mar 2017 08:56:57 -0600 Subject: [PATCH 3/9] Fix no pynumpy target when no numpy configured. --- build/Jamfile | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/build/Jamfile b/build/Jamfile index 4a766ac2..f585953d 100644 --- a/build/Jamfile +++ b/build/Jamfile @@ -121,8 +121,11 @@ rule lib_boost_python ( version ) ; } -lib_boost_numpy($(py2-version)) = boost_numpy ; -lib_boost_numpy($(py3-version)) = boost_numpy3 ; +lib_boost_numpy(2) = boost_numpy ; +lib_boost_numpy(3) = boost_numpy3 ; + +lib_boost_numpy($(py2-version)) = $(lib_boost_python(2)) ; +lib_boost_numpy($(py3-version)) = $(lib_boost_python(3)) ; rule lib_boost_numpy ( version ) { @@ -175,6 +178,7 @@ for local N in 2 3 else { alias $(lib_boost_python($(N))) ; + alias $(lib_boost_numpy($(N))) ; } } From 471e6181b228036d5a16864f6338ab2947e09e81 Mon Sep 17 00:00:00 2001 From: Rene Rivera Date: Sun, 5 Mar 2017 15:16:36 -0600 Subject: [PATCH 4/9] BPL builds targets need to always be defined. --- build/Jamfile | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/build/Jamfile b/build/Jamfile index f585953d..8c37ec6d 100644 --- a/build/Jamfile +++ b/build/Jamfile @@ -169,15 +169,18 @@ for local N in 2 3 { lib_boost_python $(py$(N)-version) ; libraries += $(lib_boost_python($(py$(N)-version))) ; - if [ python.numpy ] - { - lib_boost_numpy $(py$(N)-version) ; - libraries += $(lib_boost_numpy($(py$(N)-version))) ; - } } else { alias $(lib_boost_python($(N))) ; + } + if [ python.numpy ] + { + lib_boost_numpy $(py$(N)-version) ; + libraries += $(lib_boost_numpy($(py$(N)-version))) ; + } + else + { alias $(lib_boost_numpy($(N))) ; } } From 5121fc11f9d97a0f79a2f37ad01f26bc3f40564f Mon Sep 17 00:00:00 2001 From: Rene Rivera Date: Mon, 6 Mar 2017 10:30:41 -0600 Subject: [PATCH 5/9] Don't build numpy if there's no python version to target. --- build/Jamfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/Jamfile b/build/Jamfile index 8c37ec6d..f14dc113 100644 --- a/build/Jamfile +++ b/build/Jamfile @@ -174,7 +174,7 @@ for local N in 2 3 { alias $(lib_boost_python($(N))) ; } - if [ python.numpy ] + if $(py$(N)-version) && [ python.numpy ] { lib_boost_numpy $(py$(N)-version) ; libraries += $(lib_boost_numpy($(py$(N)-version))) ; From 47faef65ee3cf6b58f4a70f788c76db9aa011d54 Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Thu, 16 Mar 2017 11:35:26 -0400 Subject: [PATCH 6/9] Fix documentation links. --- doc/reference/indexing.qbk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/reference/indexing.qbk b/doc/reference/indexing.qbk index 0cfc7c7f..4f3a55cb 100644 --- a/doc/reference/indexing.qbk +++ b/doc/reference/indexing.qbk @@ -38,7 +38,7 @@ The `indexing_suite` class is the base class for the management of C++ container [[__iter__(self)] [This method is called when an iterator is required for a container. This method should return a new iterator object that can iterate over all the objects in the container. For mappings, it should iterate over the keys of the container, and should also be made available as the method iterkeys(). -Iterator objects also need to implement this method; they are required to return themselves. For more information on iterator objects, see [@http://www.python.org/doc/current/lib/typeiter.html Iterator Types] in the [@http://www.python.org/doc/current/lib/lib.html Python Library Reference].]] +Iterator objects also need to implement this method; they are required to return themselves. For more information on iterator objects, see [@https://docs.python.org/3/library/stdtypes.html#iterator-types Iterator Types] in the [@https://docs.python.org/3/library/index.html Python Library Reference].]] [[__contains__(self, item)] [Called to implement membership test operators. Should return true if item is in self, false otherwise. For mapping objects, this should consider the keys of the mapping rather than the values or the key-item pairs.]] From 352792c90a36ee8d6a520c7602b2dbd03ab19c3f Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Thu, 16 Mar 2017 20:14:39 -0400 Subject: [PATCH 7/9] Add more export symbols. --- include/boost/python/numpy/dtype.hpp | 2 +- .../boost/python/numpy/invoke_matching.hpp | 6 +- include/boost/python/numpy/matrix.hpp | 2 +- include/boost/python/numpy/ndarray.hpp | 72 +++++++++++-------- .../python/numpy/numpy_object_mgr_traits.hpp | 4 +- include/boost/python/numpy/scalars.hpp | 2 +- include/boost/python/numpy/ufunc.hpp | 6 +- 7 files changed, 55 insertions(+), 39 deletions(-) diff --git a/include/boost/python/numpy/dtype.hpp b/include/boost/python/numpy/dtype.hpp index 32bb3d4a..9633d37d 100644 --- a/include/boost/python/numpy/dtype.hpp +++ b/include/boost/python/numpy/dtype.hpp @@ -70,7 +70,7 @@ public: }; -bool equivalent(dtype const & a, dtype const & b); +BOOST_NUMPY_DECL bool equivalent(dtype const & a, dtype const & b); namespace detail { diff --git a/include/boost/python/numpy/invoke_matching.hpp b/include/boost/python/numpy/invoke_matching.hpp index 90ec8ae2..095ca3a8 100644 --- a/include/boost/python/numpy/invoke_matching.hpp +++ b/include/boost/python/numpy/invoke_matching.hpp @@ -19,7 +19,7 @@ namespace boost { namespace python { namespace numpy { namespace detail { -struct add_pointer_meta +struct BOOST_NUMPY_DECL add_pointer_meta { template struct apply @@ -29,8 +29,8 @@ struct add_pointer_meta }; -struct dtype_template_match_found {}; -struct nd_template_match_found {}; +struct BOOST_NUMPY_DECL dtype_template_match_found {}; +struct BOOST_NUMPY_DECL nd_template_match_found {}; template struct dtype_template_invoker diff --git a/include/boost/python/numpy/matrix.hpp b/include/boost/python/numpy/matrix.hpp index 43335e1f..829f544a 100644 --- a/include/boost/python/numpy/matrix.hpp +++ b/include/boost/python/numpy/matrix.hpp @@ -61,7 +61,7 @@ public: * return a numpy.matrix instead. */ template -struct BOOST_NUMPY_DECL as_matrix : Base +struct as_matrix : Base { static PyObject * postcall(PyObject *, PyObject * result) { diff --git a/include/boost/python/numpy/ndarray.hpp b/include/boost/python/numpy/ndarray.hpp index 9ad0f20e..e5b6a9e9 100644 --- a/include/boost/python/numpy/ndarray.hpp +++ b/include/boost/python/numpy/ndarray.hpp @@ -142,32 +142,32 @@ public: /** * @brief Construct a new array with the given shape and data type, with data initialized to zero. */ -ndarray zeros(python::tuple const & shape, dtype const & dt); -ndarray zeros(int nd, Py_intptr_t const * shape, dtype const & dt); +BOOST_NUMPY_DECL ndarray zeros(python::tuple const & shape, dtype const & dt); +BOOST_NUMPY_DECL ndarray zeros(int nd, Py_intptr_t const * shape, dtype const & dt); /** * @brief Construct a new array with the given shape and data type, with data left uninitialized. */ -ndarray empty(python::tuple const & shape, dtype const & dt); -ndarray empty(int nd, Py_intptr_t const * shape, dtype const & dt); +BOOST_NUMPY_DECL ndarray empty(python::tuple const & shape, dtype const & dt); +BOOST_NUMPY_DECL ndarray empty(int nd, Py_intptr_t const * shape, dtype const & dt); /** * @brief Construct a new array from an arbitrary Python sequence. * * @todo This does't seem to handle ndarray subtypes the same way that "numpy.array" does in Python. */ -ndarray array(object const & obj); -ndarray array(object const & obj, dtype const & dt); +BOOST_NUMPY_DECL ndarray array(object const & obj); +BOOST_NUMPY_DECL ndarray array(object const & obj, dtype const & dt); namespace detail { -ndarray from_data_impl(void * data, - dtype const & dt, - std::vector const & shape, - std::vector const & strides, - object const & owner, - bool writeable); +BOOST_NUMPY_DECL ndarray from_data_impl(void * data, + dtype const & dt, + std::vector const & shape, + std::vector const & strides, + object const & owner, + bool writeable); template ndarray from_data_impl(void * data, @@ -183,12 +183,12 @@ ndarray from_data_impl(void * data, return from_data_impl(data, dt, shape_, strides_, owner, writeable); } -ndarray from_data_impl(void * data, - dtype const & dt, - object const & shape, - object const & strides, - object const & owner, - bool writeable); +BOOST_NUMPY_DECL ndarray from_data_impl(void * data, + dtype const & dt, + object const & shape, + object const & strides, + object const & owner, + bool writeable); } // namespace boost::python::numpy::detail @@ -250,39 +250,53 @@ inline ndarray from_data(void const * data, * @param[in] nd_max Maximum number of dimensions. * @param[in] flags Bitwise OR of flags specifying additional requirements. */ -ndarray from_object(object const & obj, dtype const & dt, - int nd_min, int nd_max, ndarray::bitflag flags=ndarray::NONE); +BOOST_NUMPY_DECL ndarray from_object(object const & obj, + dtype const & dt, + int nd_min, + int nd_max, + ndarray::bitflag flags=ndarray::NONE); -inline ndarray from_object(object const & obj, dtype const & dt, - int nd, ndarray::bitflag flags=ndarray::NONE) +BOOST_NUMPY_DECL inline ndarray from_object(object const & obj, + dtype const & dt, + int nd, + ndarray::bitflag flags=ndarray::NONE) { return from_object(obj, dt, nd, nd, flags); } -inline ndarray from_object(object const & obj, dtype const & dt, ndarray::bitflag flags=ndarray::NONE) +BOOST_NUMPY_DECL inline ndarray from_object(object const & obj, + dtype const & dt, + ndarray::bitflag flags=ndarray::NONE) { return from_object(obj, dt, 0, 0, flags); } -ndarray from_object(object const & obj, int nd_min, int nd_max, - ndarray::bitflag flags=ndarray::NONE); +BOOST_NUMPY_DECL ndarray from_object(object const & obj, + int nd_min, + int nd_max, + ndarray::bitflag flags=ndarray::NONE); -inline ndarray from_object(object const & obj, int nd, ndarray::bitflag flags=ndarray::NONE) +BOOST_NUMPY_DECL inline ndarray from_object(object const & obj, + int nd, + ndarray::bitflag flags=ndarray::NONE) { return from_object(obj, nd, nd, flags); } -inline ndarray from_object(object const & obj, ndarray::bitflag flags=ndarray::NONE) +BOOST_NUMPY_DECL inline ndarray from_object(object const & obj, + ndarray::bitflag flags=ndarray::NONE) { return from_object(obj, 0, 0, flags); } -inline ndarray::bitflag operator|(ndarray::bitflag a, ndarray::bitflag b) +BOOST_NUMPY_DECL inline ndarray::bitflag operator|(ndarray::bitflag a, + ndarray::bitflag b) { return ndarray::bitflag(int(a) | int(b)); } -inline ndarray::bitflag operator&(ndarray::bitflag a, ndarray::bitflag b) +BOOST_NUMPY_DECL inline ndarray::bitflag operator&(ndarray::bitflag a, + ndarray::bitflag b) { return ndarray::bitflag(int(a) & int(b)); } diff --git a/include/boost/python/numpy/numpy_object_mgr_traits.hpp b/include/boost/python/numpy/numpy_object_mgr_traits.hpp index 8f9f4440..a138f4cd 100644 --- a/include/boost/python/numpy/numpy_object_mgr_traits.hpp +++ b/include/boost/python/numpy/numpy_object_mgr_traits.hpp @@ -7,6 +7,8 @@ #ifndef boost_python_numpy_numpy_object_mgr_traits_hpp_ #define boost_python_numpy_numpy_object_mgr_traits_hpp_ +#include + /** * @brief Macro that specializes object_manager_traits by requiring a * source-file implementation of get_pytype(). @@ -14,7 +16,7 @@ #define NUMPY_OBJECT_MANAGER_TRAITS(manager) \ template <> \ -struct object_manager_traits \ +struct BOOST_NUMPY_DECL object_manager_traits \ { \ BOOST_STATIC_CONSTANT(bool, is_specialized = true); \ static inline python::detail::new_reference adopt(PyObject* x) \ diff --git a/include/boost/python/numpy/scalars.hpp b/include/boost/python/numpy/scalars.hpp index 0ba23c41..c2a83d82 100644 --- a/include/boost/python/numpy/scalars.hpp +++ b/include/boost/python/numpy/scalars.hpp @@ -22,7 +22,7 @@ namespace boost { namespace python { namespace numpy { * * @todo This could have a lot more functionality. */ -class void_ : public object +class BOOST_NUMPY_DECL void_ : public object { static python::detail::new_reference convert(object_cref arg, bool align); public: diff --git a/include/boost/python/numpy/ufunc.hpp b/include/boost/python/numpy/ufunc.hpp index 4c2331c9..7e249238 100644 --- a/include/boost/python/numpy/ufunc.hpp +++ b/include/boost/python/numpy/ufunc.hpp @@ -62,13 +62,13 @@ public: }; /// @brief Construct a multi_iter over a single sequence or scalar object. -multi_iter make_multi_iter(object const & a1); +BOOST_NUMPY_DECL multi_iter make_multi_iter(object const & a1); /// @brief Construct a multi_iter by broadcasting two objects. -multi_iter make_multi_iter(object const & a1, object const & a2); +BOOST_NUMPY_DECL multi_iter make_multi_iter(object const & a1, object const & a2); /// @brief Construct a multi_iter by broadcasting three objects. -multi_iter make_multi_iter(object const & a1, object const & a2, object const & a3); +BOOST_NUMPY_DECL multi_iter make_multi_iter(object const & a1, object const & a2, object const & a3); /** * @brief Helps wrap a C++ functor taking a single scalar argument as a broadcasting ufunc-like From edd890bd2bdb89ac0d9fbcf5b6ba1dcc0bb66717 Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Mon, 20 Mar 2017 08:29:15 -0400 Subject: [PATCH 8/9] More dllexport fixes --- include/boost/python/converter/pyobject_type.hpp | 7 +++++-- include/boost/python/numpy/dtype.hpp | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/include/boost/python/converter/pyobject_type.hpp b/include/boost/python/converter/pyobject_type.hpp index 526f9f9d..bde39e80 100644 --- a/include/boost/python/converter/pyobject_type.hpp +++ b/include/boost/python/converter/pyobject_type.hpp @@ -9,8 +9,11 @@ namespace boost { namespace python { namespace converter { -BOOST_PYTHON_DECL PyObject* checked_downcast_impl(PyObject*, PyTypeObject*); - +BOOST_PYTHON_DECL inline +PyObject* checked_downcast_impl(PyObject *obj, PyTypeObject *type) +{ + return (PyType_IsSubtype(Py_TYPE(obj), type) ? obj : NULL); +} // Used as a base class for specializations which need to provide // Python type checking capability. template diff --git a/include/boost/python/numpy/dtype.hpp b/include/boost/python/numpy/dtype.hpp index 9633d37d..b9e95f9b 100644 --- a/include/boost/python/numpy/dtype.hpp +++ b/include/boost/python/numpy/dtype.hpp @@ -56,7 +56,7 @@ public: * This is more permissive than equality tests. For instance, if long and int are the same * size, the dtypes corresponding to each will be equivalent, but not equal. */ - friend bool equivalent(dtype const & a, dtype const & b); + friend BOOST_NUMPY_DECL bool equivalent(dtype const & a, dtype const & b); /** * @brief Register from-Python converters for NumPy's built-in array scalar types. From 3066c73c093dace63d49ddc9aec7783715c3e96a Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Wed, 15 Feb 2017 15:36:01 -0500 Subject: [PATCH 9/9] Fix Windows builds. --- SConstruct | 1 + appveyor.yml | 4 +++- src/SConscript | 14 +++++++++++--- test/SConscript | 9 +++++++++ 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/SConstruct b/SConstruct index 3f3dbfd4..6edd7cd4 100644 --- a/SConstruct +++ b/SConstruct @@ -39,6 +39,7 @@ arch = ARGUMENTS.get('arch', platform.machine()) env_vars = {} if 'CXX' in os.environ: env_vars['CXX'] = os.environ['CXX'] if 'CXXFLAGS' in os.environ: env_vars['CXXFLAGS'] = os.environ['CXXFLAGS'].split() +env_vars['ENV'] = os.environ #{'PATH': os.environ['PATH'], 'TMP' : os.environ['TMP']} env = Environment(toolpath=['config/tools'], tools=['default', 'libs', 'tests', 'doc', 'sphinx4scons'], variables=vars, diff --git a/appveyor.yml b/appveyor.yml index 4dbaffd7..bc11c5b8 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -69,13 +69,15 @@ install: # pip will build them from source using the MSVC compiler matching the # target Python version and architecture - easy_install scons + - 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% + - scons arch=%ARCH% --verbose test_script: # Run the project tests diff --git a/src/SConscript b/src/SConscript index 6d81a9dc..49ab73b8 100644 --- a/src/SConscript +++ b/src/SConscript @@ -10,9 +10,11 @@ Import('env') env.AppendUnique(CPPDEFINES = ["${LINK_DYNAMIC and 'BOOST_PYTHON_DYN_LINK=1' or ''}"]) -env.AppendUnique(CPPDEFINES = ['BOOST_PYTHON_SOURCE']) -env.BoostLibrary( +env1 = env.Clone() +env1.AppendUnique(CPPDEFINES = ['BOOST_PYTHON_SOURCE']) + +env1.BoostLibrary( 'python', ['numeric.cpp', 'list.cpp', @@ -44,7 +46,13 @@ env.BoostLibrary( 'object/function_doc_signature.cpp']) if env['NUMPY']: - env.BoostLibrary( + env2 = env.Clone() + env2.Append(CPPPATH=env['NUMPY_CPPPATH']) + build_dir = env.Dir('$BOOST_CURRENT_VARIANT_DIR/src') + env2.AppendUnique(CPPDEFINES = ['BOOST_NUMPY_SOURCE'], + LIBPATH = [build_dir], + LIBS='boost_python' + env["BOOST_SUFFIX"]) + env2.BoostLibrary( 'numpy', ['numpy/dtype.cpp', 'numpy/matrix.cpp', diff --git a/test/SConscript b/test/SConscript index ee41547f..3a0fcf06 100644 --- a/test/SConscript +++ b/test/SConscript @@ -8,9 +8,18 @@ # http://www.boost.org/LICENSE_1_0.txt) import platform +import sys Import('env') +if sys.platform == 'win32': + # HACK: This works around a bug in SCons. + # subprocess.check_output will complain unless all environment + # variables are strings. + system_root = env['ENV']['SystemRoot'] + env['ENV']['SystemRoot'] = str(system_root) + + # libs needed for embedding ELIBS=env['LIBS'] + env['PYTHONLIBS']